summaryrefslogtreecommitdiff
path: root/qdos
diff options
context:
space:
mode:
Diffstat (limited to 'qdos')
-rw-r--r--qdos/IZREADME.SMS600
-rw-r--r--qdos/Makefile.qdos143
-rw-r--r--qdos/Makefile.qlzip139
-rw-r--r--qdos/config.s153
-rw-r--r--qdos/crc68.s99
-rw-r--r--qdos/match.s138
-rw-r--r--qdos/osdep.h33
-rw-r--r--qdos/qdos.c877
-rw-r--r--qdos/qfileio.c235
-rw-r--r--qdos/zipup.h19
10 files changed, 2436 insertions, 0 deletions
diff --git a/qdos/IZREADME.SMS b/qdos/IZREADME.SMS
new file mode 100644
index 0000000..9ad1503
--- /dev/null
+++ b/qdos/IZREADME.SMS
@@ -0,0 +1,600 @@
+IZREADME_SMS (IZREADME.SMS): Info-ZIP for SMS/QDOS, last revised: 15-Jun-1998
+===============================================================================
+[was "InfoZIP_SMSQDOS_ReadMe" in J. Hudson's original ports, ca. 08/1995]
+
+Info-ZIP Programs
+=================
+
+Zip
+UnZip
+UnZipSFX
+fUnZip
+
+Introduction
+------------
+
+This archive is a result of frustrations with contemporary (August 95)
+versions of Zip and UnZip. While they use the same compression
+algorithms as the Info-ZIP programs, there the compatibility ends. If
+you just use Zip/UnZip only on SMS/QDOS, then perhaps this is not a
+problem (but I know for some users it still is); if you use Zip/UnZip
+to transport source code and data between diverse systems, then the
+disregard for Info-ZIP standards is inconvenient, particularly the
+fact that directories are not supported and files are always stored
+underscored.
+
+This release of Zip/UnZip offers:
+
+ o zipfile/directory compatibility with all other supported
+ platforms
+
+ o SMS/QDOS compatibility and back-compatible with earlier
+ versions.
+
+ o Improved performance (Zip is typically 50% faster)
+
+ o Command-line compatibility with Info-ZIP
+
+ o Self-extracting archives (but not very elegantly)
+
+ o Archives are marked as 'created by SMS/QDOS'.
+
+ o Optional recursion into directories
+
+ o Directory structure restored on unzip of Info-ZIP/PKZIP-
+ compatible archives.
+
+ o Config'urable for listing and unpack formats (Info-ZIP (.) or
+ SMS/QDOS (_) and 'Press any key' timeouts. Override options
+ from command line.
+
+Info-ZIP Standards
+------------------
+
+This (rather long-winded and waffling) section discusses the
+conventions and standards used by Info-ZIP-compatible archivers and how
+"Info-ZIP for SMS/QDOS" achieves compatibility.
+
+Info-ZIP Zip/UnZip on all supported platforms (Unix, DOS, OS/2, NT,
+VAX/VMS, Amiga etc etc), works in a specific way. (Until now SMS/QDOS
+was neither 'supported' nor Info-ZIP-compliant.)
+
+ a. The zipfile directory is in (/.) (Unix) format.
+
+ b. When zips are listed, it is in 'zipfile' (Unix) format.
+
+ c. When files are added, they are defined in native format.
+
+ d. When files are added, this is shown in 'zipfile' format.
+
+ e. When files are unpacked, this is done to native format, but
+ selection is done in 'zipfile' format.
+
+Basically, the listing and stored format of a file is that of the
+destination.
+
+So, given a file structure at some arbitrary 'root' level.
+
+ Makefile
+ src (Dir)
+ afile.c
+ bfile.c
+ docs (Dir)
+ prog.txt
+ hdr (Dir)
+ cfile.h
+ dfile.h
+
+Then these would be in Unix (and Amiga) as
+
+ Makefile
+ src/afile.c
+ src/bfile.c
+ src/docs/prog.txt
+ hdr/cfile.h
+ hdr/dfile.h
+
+This is also how the zipfile directory appears.
+
+And in DOS/OS2/NT
+
+ Makefile
+ src\afile.c
+ src\docs\prog.txt
+ hdr\cfile.h .. etc
+
+And in VMS (we SHOUT in VMS and have a silly file system)
+
+ MAKEFILE
+ [SRC]AFILE.C
+ [SRC.DOC]PROG.TXT
+ [HDR]CFILE.H .. etc
+ (OK VMS purist, [.SRC] etc. Only an example)
+
+And in SMS/QDOS (quiet again, but slightly ludicrous !)
+
+ Makefile
+ src_afile_c
+ src_doc_prog_txt
+ hdr_cfile_h .. etc
+
+The main problem regarding SMS/QDOS is not that of extensions - (after
+all, only VMS and DOS _really_ have extensions; Unix, AmigaDOS, NT and
+OS/2 (and Win95) allow multiple '.' in.long.file.names.
+
+The SMS/QDOS problem is that '_' is both a legal file name character
+and a directory separator. This creates the difficulties, as
+directories and files are somewhat different objects.
+
+It is the intention that these versions of SMS/QDOS Zip/UnZip will
+follow the Info-ZIP rules, thus providing compatibility with the other
+platforms. It is possible to zip the file structure described above on
+SMS/QDOS and unpack it on VMS and get the VMS structure as shown in the
+example (and vice-versa). [We only choose the most obtuse file
+systems for the examples].
+
+In order to achieve this, SMS/QDOS names are mapped into Unix-style
+ones when the zipfile is created and un-mapped when it is unpacked.
+There is an option to unpack in 'zipfile' format (i.e. with '.' rather
+than '_'), but there will be no option to pack to all '_'. That would
+contravene the standard. However, a file
+
+ src_split_name_c (which is src->split_name_c !)
+ src/split_name.c)
+
+where src is a hard directory, would be stored in the zip directory as
+
+ src/split_name.c
+
+It does handle '_' with a little intelligence.
+
+The default UnZip option will be to translate '.' to '_'; this is
+because there are still many QDOS/Minerva users that cannot handle '.'
+without quotes, which is immensely inconvenient. For many SMS users
+'_' is also the most natural and convenient option. It also means that
+SMS/QDOS <-> SMS/QDOS Zip - UnZip sequences are transparent.
+
+There will, however, be two ways around this in UnZip.
+
+ 1. It is possible to Config the UnZip default to be '.'
+ translations (or not).
+
+ 2. The UnZip -Q1 option will toggle the default (Config'ed)
+ state.
+
+Examples:
+
+Given that we want/have
+
+ Makefile (Makefile)
+ src/afile.c (src_afile_c)
+ src/bfile.c (src_bfile_c)
+ src/docs/prog.txt (src_docs_prog_txt)
+ hdr/cfile.h (hdr_cfile_h)
+ hdr/dfile.h (hdr_dfile_h)
+
+Then on SMS/QDOS we might have added the *.c files as
+
+ ex zip;'-r test *_c'
+
+(or VMS, just to do something different)
+
+ zip -r test [.src]*.c
+
+In both cases the file lists as above (left).
+
+To unpack on SMS/QDOS (just the _c/.c files)
+
+ ex unzip;'test src/*.c'
+
+ (and VMS, unzip test src/*.c)
+
+i.e. in both cases using the 'zipfile' format. As a concession to
+SMS/QDOS, you could also have:
+
+ ex unzip;'test src_*_c'
+
+ but not unzip test [.src]*.c on VMS !!!!! Sorry, dinosaurs.
+
+Both SMS/QDOS commands unpack to
+
+ src_afile_c etc, where src_ is a hard sub-directory.
+
+(and the VMS example would unpack to [.src]afile.c, (or to src\afile.c on
+DOS/NT/OS2 etc).
+
+Options & SMS/QDOS Features
+---------------------------
+
+The options supported by Zip/UnZip are basically those documented in
+the Info-ZIP documents and shown in on-line 'usage'. In particular, -r
+and -j work as intended.
+
+PLEASE NOTE: Previous SMS/QDOS zip/unzips have NOT followed these
+conventions, for example -r was not implemented and -j was reversed.
+
+A number of -Q (SMS/QDOS-specific) options (not yet in the current
+documents or usage screens) are implemented.
+
+The Zip 2.0.1 (and later) default is to add SMS/QDOS headers where
+file type = 1 (exe) or 2 (rel) or (type > 0 && != 255 and (filesize %
+64) != 0). Directories are included anyway, unless you zip -D.
+
+Where a header is added for an 'exe' file a '*' is displayed after the
+name in the zip display (and '#' for 'rel' files).
+
+The -Q options for Zip are:
+
+ -Q1 Don't add headers for ANY files
+ -Q2 Add headers for all files
+ -Q4 Don't wait for interactive key press
+
+ (additive, so -Q5 => no headers, no wait, -Q6 all headers,
+ no wait etc)
+
+ (the default is exec/rel headers, 5 sec wait)
+
+Zip has rationalised the file header storage in zipfiles. The
+previous Zip used to store a QDOS header for each file. This was very
+wasteful, for example compressing a SMS/QDOS release of PGP in this
+way came to 730Kb, too large for a DD disk. Changing the Zip program
+just to add a header record for the single PGP exe and the zipfile
+size went down to around 690Kb.
+
+And for UnZip
+
+ -Q1 Toggle unpack format status ('.' <-> '_')
+ -Q2 Toggle listing format
+ -Q4 Don't wait for key press
+
+Files Types
+-----------
+
+The history of QDOS suffers from incompatible feature
+implementations. For example, Thor directories have file type 3, CST
+have type 4 and Level 2 have type 255. Some software writers (both
+amateur and otherwise) have used type 3 or 4 for other purposes
+(backward compatibility ?? who cares ??).
+
+In order to bypass problems cause by incompatible (inconsiderate ?)
+usage of file types, the file type denoting a directory is a
+Config'urable item. The default is set to -1 (65535 in Config terms),
+which means "determine directory type from the file header of the root
+directory". If this is appears unsuccessful on your system, the value
+can be Config'ed in the range 3-255.
+
+Zip assumes a file is a directory if:
+
+ ((type == CONFIGed_type) && (file_size % 64) == 0)
+
+If you are unfortunate enough have files of that pass this test but
+are not directories, then Zip will loop endless, as SMS/QDOS opens the
+root directory again !!! (recursion: see recursion etc).
+
+I suggest you refrain from zipping such files and contact the software
+supplier and point out the error of their ways.
+
+File Naming Issues
+------------------
+
+Zip will append a '_zip' suffix to the archive filename when the
+supplied name (i.e. excluding device/directory parts) does not
+contain a '_' or a '.'. This is broadly compatible with Info-ZIP,
+taking into account the '_' aberation.
+
+So
+ ex zip;'ram2_test ...' >> ram2_test_zip
+
+ ex zip;'ram2_test.zip ...' >> ram2_test.zip
+
+ ex zip;'ram2_test_rep ... ' >> ram2_test_rep
+
+ ex zip;'ram2_fdbbs.rep ... ' >> ram2_fdbbs.rep
+
+ ex zip;'ram2_test_rep.zip ...' >> ram2_test_rep.zip
+
+This implies that if a file ram2_test.zip exists, and you do:
+
+ ex zip;'ram2_test ...'
+
+Then a new file (test_zip) is created, rather than 'test.zip' being
+updated.
+
+Zip supports extensive recursive wild-carding, again the fact that '_'
+can be a directory separator as well as part of a file name makes this
+a bit tricky, but given the example:
+
+ test1_bas
+ test2_bas
+ dir1->demo1_bas where -> indicates a sub dir
+ dir2->demo2_bas
+
+ ex zip;'ram2_test *_bas'
+ just finds test1_bas, test2_bas
+
+ ex zip;'-r ram2_test *_bas'
+ recurses and finds all the files
+
+You might think that
+
+ ex zip;'-r ram2_test *_*_bas'
+
+would just find the files in the subdirectories--well yes, but it will
+also find very other sub-dir'ed _bas file on the disk too. This is
+a feature.
+
+The pattern matching supports Unix-style 'regex' so you could:
+
+ ex zip;'ram2_test dir?_*_bas'
+ or
+ ex zip;'ram2_test dir[12]_*_bas
+
+
+UnZip has now got a fixed -d option. This is used to specify the
+directory to unpack the zipfile into, it must follow immediately
+after the zip name.
+
+ ex unzip;'ram2_test_zip -d ram3_ *_txt'
+
+would unpack all *_txt files to ram3_ .
+
+It is not necessary to set the default directory to pack files, Zip
+will remove any device names (and store any hard directory names,
+unless you zip -j).
+
+ ex zip;'ram1_test flp1_*'
+
+ ----->
+ adding: file.dat (deflated 50%)
+ adding: menu.rext # (deflated xx%)
+ adding: zip * (deflated yy%)
+ adding: hard_one (stored 0%)
+ adding: hard_one/stuff.bas (deflated ...)
+
+Due to the way the file-mapping is implemented, it is not supported
+over the nX_ type network device.
+
+Config Options
+--------------
+
+A limited number of SMS/QDOS specific functions can be set using the
+QJump Config program.
+
+ For Zip:
+
+ Timeout for interactive 'Press any key' prompt
+
+ 65535 Wait forever (aka -1)
+ 0 No wait
+ n (1-32767) Wait for 'n' clocks (1/50 sec)
+
+ Other values are unsupported. Note Config works on 'unsigned'
+ integer values (at least according to my manual).
+
+ Directory file type key.
+
+ Config will accept any value in the range 3-255, known useful
+ values are 3 (Thor), 4 (CST) and 255 (Level 2 devices). A value
+ of 65535 (aka -1) means "determine from device info".
+
+ For UnZip:
+
+ Timeout as above
+
+ Unpack mode (SMS/QOS ('_') or Info-ZIP ('.')
+
+ List format (Info-ZIP ('.') or SMS/QDOS ('_')
+
+
+When the 'Press a key' text is displayed, if you press ESC, then it
+waits until you press any other key, infinite timeout. This may be
+useful if you want (much) more time to study a listing etc.
+
+Defaults for timeout and directory type are 250 and -1 respectively.
+
+More Goodies
+------------
+
+Part of the Zip compression code is now in assembler; it runs
+noticably faster than the previous version. Compressing some arbitrary
+files with the previous Zip it took 251 seconds, with Zip 2.0.1 it
+took (a mere) 170 seconds (68008 QL).
+
+More good news is that SMS/QDOS is just another system option on top
+of standard Info-ZIP, unlike the previous ports that were much more
+SMS/QDOS specific. For example, compiling the standard source with c68
+(i.e. #define QDOS), then you get an SMS/QDOS version.
+
+Compile with Linux/gcc and get the standard Linux version. Now, here's
+the cool bit; compile with Linux/gcc and "-DQLZIP", and get a standard
+Linux Zip/UnZip with SMS/QDOS (header) extensions.
+
+so, on Linux:
+
+ zip -Q stuff.zip qtpi zip unzip
+
+the -Q tells Zip to look for XTc68/Lux68 cross-compiler data size
+blocks and produce a zipfile with SMS/QDOS headers in it (for exec
+type programs). This works for exec files produced by the XTc68/Lux68
+cross compilers and ANY SMS/QDOS files copied to a Unix or MS-DOS disk
+from an SMS/QDOS floppy using 'qltools v2.2' (or later).
+
+Self Extracting Archives
+------------------------
+
+Info-ZIP self-extracting archives (_sfx) are created in a rather
+'brute-force' way. The UnZipSFX program is prepended to a zipfile.
+
+i.e. file_sfx = unzipsfx + file_zip
+ ex file_sfx
+
+Although the UnZipSFX program is a cut-down UnZip, it is still around
+30Kb - 50Kb, depending on platform.
+
+The success of this approach depends on how the operating system
+loader loads executable files. On most systems where the loader only
+loads the actual program part (Unix, VMS, DOS et al), the this is
+quite efficient; if you make, say, a 4Mb zipfile and prepend a 30Kb
+UnZipSFX image, then the system only loads the 30Kb program and the
+process is efficient as the zipped data part is still unpacked from
+disk. These systems also supply the running UnZipSFX program stub with
+the path name of the file it was loaded from, so the program knows
+what it has to unpack (so on Linux, for example):
+
+ cat /usr/bin/unzipsfx test.zip > test.sfx # concatenate the files
+ chmod 755 test.sfx # make executable
+ test.sfx # to extract, it
+ # 'knows' it is "test.sfx"
+
+Unfortunately, the more simplistic nature of SMS/QDOS makes this much
+more difficult and rather less efficient as: (see note 1)
+
+ a. The SMS/QDOS 'loader' loads the whole file into memory.
+
+ b. The SMS/DOS 'loader'/c68 run-time system does not return the
+ name of the file from which it was loaded.
+
+ c. You cannot so easily create a image file by concatenating two
+ files, it is also necessary to ensure the executable file
+ header is set correctly.
+
+ d. The show stopper. The data space required for the
+ self-extracting archive is required, as not easily maintained
+ during electronic transfer.
+
+
+If anyone is still interested, then the following support for UnZipSFX
+is provided.
+
+ o A program 'makesfx' will combine a stub (callstub), UnZipSFX image
+ and a zipfile to produce a sfx (self-extracting zip) file.
+
+ o A callable interface is supplied. The user calls the SFX file,
+ which creates the files necessary to do the extraction.
+
+The makesfx program concatenates the supplied files to standard
+output.
+
+So, to create a sfx of all the _c files in the default directory.
+
+ # 1st create a zipfile of the required files
+
+ ex zip;'ram1_test_zip *_c'
+
+ # Now create the sfx file (ram2_test_sfx)
+ # our UnZipSFX image is in 'win1_bin'
+ # as is the call stub.
+
+ex makesfx;'-o test_sfx -x win1_bin_unzipsfx -s win1_bin_callstub -z ram1_test_zip'
+
+The arguments to makesfx are:
+
+ -s stubfile
+ -x UnZipSFX_program
+ -z Zip_file
+ -o Output_file
+
+You can now unpack the _sfx file on any SMS/QDOS-compatible
+system.
+
+ f$ = "win2_tmp_test_sfx"
+ a = alchp(flen(\f$))
+ lbytes f$,a
+ call a
+ rechp(a)
+
+ZipInfo
+-------
+
+Given the above note concerning SMS/QDOS programs not knowing the name
+by which the program was invoked, then the usual symbolic-link-of-unzip-
+to-zipinfo trick is unavailable (presupposing there is some some SMS/QDOS
+trick to emulate symbolic links).
+
+ZipInfo functionality is only available via 'unzip -Z'. There is no
+separate ZipInfo program.
+
+Caveat ATP Users
+----------------
+
+ATP for SMS/QDOS users should pay particular attention to the
+Zip/UnZip options in their atprc and compare with Info-ZIP Zip/UnZip
+usage. Older versions of Zip/UnZip screwed up -j.
+
+
+ zip -jk
+ unzip -jo
+
+Distribution & Copyright
+------------------------
+
+This software is written by and largely copyrighted by the 'Info-ZIP'
+group whose members are noted in the accompanying documentation. This
+particular SMS/QDOS port plus 'makesfx' was written by, but is not
+copyrighted by, Jonathan R Hudson. The SMS/QDOS code in this release
+is written from scratch and is not dependent on previous SMS/QDOS
+releases, but is (largely) compatible.
+
+As a courtesy to the authors of this package, please ensure that the
+documentation is supplied when it is re-distributed.
+
+In particular, if this archive is split into Zip and UnZip components,
+ensure that this document ("IZREADME_SMS") is supplied in
+each component.
+
+SMS/QDOS version by:
+Jonathan R Hudson (jrhudson@bigfoot.com)
+
+I am grateful to Graham Goodwin for finding some most imaginative
+means of breaking the beta code.
+
+I'd also like to thank Thierry Godefroy for providing the 2.1/5.2
+source code and making the initial contact with the Info-ZIP group.
+
+And of course, many, many thanks to the Info-ZIP workers for making
+this code freely available.
+
+Note 1
+------
+
+The 'C' language FAQ ('frequently asked questions' [comp.lang.c])
+notes on the matter of obtaining the load file name of a 'C' program:
+
+16.5: How can my program discover the complete pathname to the
+ executable file from which it was invoked?
+
+A: argv[0] may contain all or part of the pathname, or it may
+ contain nothing. You may be able to duplicate the command
+ language interpreter's search path logic to locate the
+ executable if the name in argv[0] is present but incomplete.
+ However, there is no guaranteed or portable solution.
+ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+Note 2
+------
+
+NUL files for SMS2. There appears to be a conflict between SMS2/LBASIC
+compiled programs and c68 programs using nul as stdin.
+
+ EW zip,nul;'ram1_test *_bas' # will not work
+
+ # This does work !
+ EW zip,#FOP_IN('nul');'ram2_test *_bas' : CLOSE
+
+Note 3
+------
+
+version number incremented to 2.0.1a and 5.12a to accomodate Erling
+Jacobsen's exit message requirements
+
+version number incremented to Zip 2.0.1b to fix bug on zipping files
+starting with leading underscore.
+
+version number incremented to UnZip 5.12b to fix UnZip problem on
+files zipped with leading './', and linked with revised (fixed) c68
+'utime' function (could corrupt level 1 files). (source code _only_ as
+IZQ004.zip).
+
+Ported Zip 2.1 and UnZip 5.2 (July 1996). Released as INZIP005.zip
+
+All later versions --- see Info-ZIP release notes and documentation.
diff --git a/qdos/Makefile.qdos b/qdos/Makefile.qdos
new file mode 100644
index 0000000..1028273
--- /dev/null
+++ b/qdos/Makefile.qdos
@@ -0,0 +1,143 @@
+include /etc/ql.mak
+
+# Makefile for Zip, ZipNote, ZipCloak and ZipSplit
+
+MAKE = make
+SHELL = /bin/sh
+
+#
+BIND = $(CC)
+
+# probably can change this to 'install' if you have it
+INSTALL = cp
+
+# target directories - where to install executables and man pages to
+BINDIR =
+manext=1
+MANDIR =
+ZIPMANUAL = MANUAL
+
+# flags
+# CFLAGS flags for C compile
+# LFLAGS1 flags after output file spec, before obj file list
+# LFLAGS2 flags after obj file list (libraries, etc)
+CFLAGS = -O -DASMV -DASM_CRC
+LFLAGS1 = -v
+#LFLAGS2 = -lutime
+
+all: zip
+
+# object file lists
+OBJZ = zip.o zipfile.o zipup.o fileio.o util.o globals.o crypt.o qdos.o ttyio.o
+OBJI = deflate.o trees.o qfileio.o crctab.o
+OBJA = config.o crc68.o match.o
+# crc32.o
+OBJQ = qdos_.o config.o qfileio_.o
+OBJU = zipfile_.o zipup_.o fileio_.o util_.o globals.o $(OBJQ)
+OBJN = zipnote.o $(OBJU)
+OBJC = zipcloak.o $(OBJU) crctab.o crypt_.o
+OBJS = zipsplit.o $(OBJU)
+
+
+# suffix rules
+.SUFFIXES:
+.SUFFIXES: _.o .o .c .doc .1
+.c_.o:
+ rm -f $*_.c; ln $< $*_.c
+ $(CC) $(CFLAGS) -DUTIL -c $*_.c
+ rm -f $*_.c
+.c.o:
+ $(CC) $(CFLAGS) -c $<
+
+.1.doc:
+ nroff -man $< | col -b | uniq > $@
+
+# rules for zip, zipnote, zipcloak, zipsplit, and zip.doc.
+$(OBJZ): zip.h ziperr.h tailor.h
+$(OBJI): zip.h ziperr.h tailor.h
+$(OBJN): zip.h ziperr.h tailor.h
+$(OBJS): zip.h ziperr.h tailor.h
+$(OBJC): zip.h ziperr.h tailor.h
+zip.o zipup.o crypt.o zipup_.o zipcloak.o crypt_.o: crypt.h
+
+qfileio.o: qdos/qfileio.c
+ cp qdos/qfileio.c qfileio.c
+ $(CC) $(CFLAGS) -c qfileio.c
+ rm -f qfileio.c
+
+qfileio_.o: qdos/qfileio.c
+ cp qdos/qfileio.c qfileio_.c
+ $(CC) $(CFLAGS) -DUTIL -c qfileio_.c
+ rm -f qfileio_.c
+
+match.o: qdos/match.s
+ cp qdos/match.s ./_match.s
+ $(AS) _match.s -o match.o
+ rm -f _match.s
+
+crc68.o: qdos/crc68.s
+ cp qdos/crc68.s ./crc68.s
+ $(AS) crc68.s -o crc68.o
+ rm -f crc68.s
+
+config.o: qdos/config.s
+ cp qdos/config.s ./config.x
+ $(CC) -c -DZIP config.x -o config.o
+ rm -f config.x
+
+ZIPS = zip$E zipnote$E zipsplit$E zipcloak$E
+
+zip.o zipup.o zipnote.o zipcloak.o zipsplit.o: revision.h
+zips: $(ZIPS)
+zipsman: $(ZIPS) $(ZIPMANUAL)
+
+qdos.o: qdos/qdos.c
+ cp qdos/qdos.c .
+ $(CC) -c -oqdos.o qdos.c
+ rm -f qdos.c
+
+qdos_.o: qdos/qdos.c
+ cp qdos/qdos.c ./qdos_.c
+ $(CC) -DUTIL -c -oqdos_.o qdos_.c
+ rm -f qdos_.c
+
+zip$E: $(OBJZ) $(OBJI) $(OBJA)
+ $(BIND) -o zip$E $(LFLAGS1) $(OBJZ) $(OBJI) $(OBJA) $(LFLAGS2)
+zipnote$E: $(OBJN)
+ $(BIND) -o zipnote$E $(LFLAGS1) $(OBJN) $(LFLAGS2)
+zipcloak$E: $(OBJC)
+ $(BIND) -o zipcloak$E $(LFLAGS1) $(OBJC) $(LFLAGS2)
+zipsplit$E: $(OBJS)
+ $(BIND) -o zipsplit$E $(LFLAGS1) $(OBJS) $(LFLAGS2)
+
+$(ZIPMANUAL): man/zip.1
+ nroff -man man/zip.1 | col -b | uniq > $(ZIPMANUAL)
+
+# install
+install: $(ZIPS)
+ $(INSTALL) $(ZIPS) $(BINDIR)
+ $(INSTALL) man/zip.1 $(MANDIR)/zip.$(manext)
+
+uninstall:
+ -cd $(BINDIR); rm -f $(ZIPS)
+ -cd $(MANDIR); rm -f zip.$(manext)
+
+flags: configure
+ sh configure flags
+
+# These symbols, when #defined using -D have these effects on compilation:
+# ZMEM - includes C language versions of memset(), memcpy(), and
+# memcmp() (util.c).
+# SYSV - use <sys/dirent.h> and the library opendir()
+# DIRENT - use <sys/dirent.h> and getdents() instead of <sys/dir.h>
+# and opendir(), etc. (fileio.c).
+# NODIR - used for 3B1, which has neither getdents() nor opendir().
+# NDIR - use "ndir.h" instead of <sys/dir.h> (fileio.c).
+# UTIL - select routines for utilities (note, cloak, and split).
+# PROTO - enable function prototypes.
+# RMDIR - remove directories using a system("rmdir ...") call.
+# CONVEX - for Convex make target.
+# AIX - for AIX make target.
+# LINUX - for linux make target.
+
+# end of Makefile
diff --git a/qdos/Makefile.qlzip b/qdos/Makefile.qlzip
new file mode 100644
index 0000000..e12f004
--- /dev/null
+++ b/qdos/Makefile.qlzip
@@ -0,0 +1,139 @@
+# Makefile for Zip, ZipNote, ZipCloak and ZipSplit
+
+# what you can make ...
+all: zip
+
+#MAKE = make -f unix/Makefile
+SHELL = /bin/sh
+
+# (to use the Gnu compiler, change cc to gcc in CC and BIND)
+CC = cc
+BIND = $(CC)
+AS = $(CC) -c
+E =
+CPP = /lib/cpp
+
+# probably can change this to 'install' if you have it
+INSTALL = cp
+
+# target directories - where to install executables and man pages to
+prefix = /usr/local
+BINDIR = $(prefix)/bin
+manext=1
+MANDIR = $(prefix)/man/man$(manext)
+ZIPMANUAL = MANUAL
+
+# flags
+# CFLAGS flags for C compile
+# LFLAGS1 flags after output file spec, before obj file list
+# LFLAGS2 flags after obj file list (libraries, etc)
+CFLAGS = -O2 -fno-strength-reduce -I. -DUNIX -DQLZIP -DASM_CRC
+LFLAGS1 =
+LFLAGS2 = -s
+
+# object file lists
+OBJZ = zip.o zipfile.o zipup.o fileio.o util.o globals.o crypt.o ttyio.o \
+ unix.o crc_gcc.o crctab.o qdos.o
+OBJI = deflate.o trees.o
+OBJA =
+OBJU = zipfile_.o fileio_.o util_.o globals.o unix_.o
+OBJN = zipnote.o $(OBJU)
+OBJC = zipcloak.o $(OBJU) crctab.o crypt_.o ttyio.o
+OBJS = zipsplit.o $(OBJU)
+
+ZIP_H = zip.h ziperr.h tailor.h unix/osdep.h
+
+# suffix rules
+.SUFFIXES:
+.SUFFIXES: _.o .o .c .doc .1
+.c_.o:
+ rm -f $*_.c; ln $< $*_.c
+ $(CC) -c $(CFLAGS) -DUTIL $*_.c
+ rm -f $*_.c
+.c.o:
+ $(CC) -c $(CFLAGS) $<
+
+.1.doc:
+ nroff -man $< | col -b | uniq > $@
+
+# rules for zip, zipnote, zipcloak, zipsplit, and the Zip MANUAL.
+$(OBJZ): $(ZIP_H)
+$(OBJI): $(ZIP_H)
+$(OBJN): $(ZIP_H)
+$(OBJS): $(ZIP_H)
+$(OBJC): $(ZIP_H)
+zip.o zipup.o crypt.o ttyio.o zipcloak.o crypt_.o: crypt.h
+zip.o zipup.o zipnote.o zipcloak.o zipsplit.o: revision.h
+zip.o crypt.o ttyio.o zipcloak.o crypt_.o: ttyio.h
+zipup.o: unix/zipup.h
+
+match.o: match.S
+ $(CPP) match.S > _match.s
+ $(AS) _match.s
+ mv _match.o match.o
+ rm -f _match.s
+
+unix.o: unix/unix.c
+ $(CC) -c $(CFLAGS) unix/unix.c
+
+unix_.o: unix/unix.c
+ rm -f $*_.c; ln unix/unix.c $*_.c
+ $(CC) -c $(CFLAGS) -DUTIL $*_.c
+ rm -f $*_.c
+
+qdos.o: qdos/qdos.c
+ $(CC) -c $(CFLAGS) qdos/qdos.c
+
+crc_gcc.o: crc_i386.S # 32bit, GNU AS
+ gcc -O3 -I. -DASM_CRC -Di386 -x assembler-with-cpp -c -o $@ crc_i386.S
+
+ZIPS = zip$E zipnote$E zipsplit$E zipcloak$E
+
+zips: $(ZIPS)
+zipsman: $(ZIPS) $(ZIPMANUAL)
+
+zip$E: $(OBJZ) $(OBJI) $(OBJA)
+ $(BIND) -o qlzip$E $(LFLAGS1) $(OBJZ) $(OBJI) $(OBJA) $(LFLAGS2)
+zipnote$E: $(OBJN)
+ $(BIND) -o zipnote$E $(LFLAGS1) $(OBJN) $(LFLAGS2)
+zipcloak$E: $(OBJC)
+ $(BIND) -o zipcloak$E $(LFLAGS1) $(OBJC) $(LFLAGS2)
+zipsplit$E: $(OBJS)
+ $(BIND) -o zipsplit$E $(LFLAGS1) $(OBJS) $(LFLAGS2)
+
+$(ZIPMANUAL): man/zip.1
+ nroff -man man/zip.1 | col -b | uniq > $(ZIPMANUAL)
+
+# install
+install: $(ZIPS)
+ $(INSTALL) $(ZIPS) $(BINDIR)
+ $(INSTALL) man/zip.1 $(MANDIR)/zip.$(manext)
+
+uninstall:
+ -cd $(BINDIR); rm -f $(ZIPS)
+ -cd $(MANDIR); rm -f zip.$(manext)
+
+dist:
+ zip -u9T zip`sed -e '/VERSION/!d' -e 's/.*"\(.*\)".*/\1/' \
+ -e s/[.]//g -e q revision.h` \
+ `awk '/^Makefile/,/vms_zip.rnh/ {print $$1}' < contents`
+
+flags: unix/configure
+ sh unix/configure "${CC}" "${CFLAGS}"
+
+# These symbols, when #defined using -D have these effects on compilation:
+# ZMEM - includes C language versions of memset(), memcpy(),
+# and memcmp() (util.c).
+# HAVE_DIRENT_H - use <dirent.h> instead of <sys/dir.h>
+# NODIR - for 3B1, which has neither getdents() nor opendir().
+# HAVE_NDIR_H - use <ndir.h> (unix/unix.c).
+# HAVE_SYS_DIR_H - use <sys/dir.h>
+# HAVE_SYS_NDIR_H - use <sys/ndir.h>
+# UTIL - select routines for utilities (note, cloak, split)
+# NO_RMDIR - remove directories using a system("rmdir ...") call.
+# NO_PROTO - cannot handle ANSI prototypes
+# NO_CONST - cannot handle ANSI const
+
+# Generic targets:
+
+# end of Makefile
diff --git a/qdos/config.s b/qdos/config.s
new file mode 100644
index 0000000..56a2a85
--- /dev/null
+++ b/qdos/config.s
@@ -0,0 +1,153 @@
+;===========================================================================
+; Copyright (c) 1990-1999 Info-ZIP. All rights reserved.
+;
+; See the accompanying file LICENSE, version 1999-Oct-05 or later
+; (the contents of which are also included in zip.h) for terms of use.
+; If, for some reason, both of these files are missing, the Info-ZIP license
+; also may be found at: ftp://ftp.cdrom.com/pub/infozip/license.html
+;===========================================================================
+#
+.globl _qlflag
+.globl _qlwait
+#ifdef ZIP
+.globl _dtype
+#endif
+
+.data
+ ds.w 0
+ dc.b '<<QCFX>>01'
+#ifdef ZIP
+ dc.w 8
+ dc.b 'Info-ZIP'
+* 12345678901234567890
+ ds.w 0
+ dc.w 4
+ dc.b 'qdos'
+ ds.w 0
+#else
+ dc.w 10
+ dc.b 'Info-UNZIP'
+* 12345678901234567890
+ ds.w 0
+ dc.w 4
+ dc.b 'qdos'
+ ds.w 0
+#endif
+ dc.b 10
+ dc.b 0
+l_4: dc.w _qlwait-l_4
+ dc.w 0
+ dc.w 0
+l_5: dc.w hpt-l_5
+l_6: dc.w hxx-l_6
+
+#ifdef ZIP
+ dc.b 10
+ dc.b 0
+d_4: dc.w _dtype-d_4
+ dc.w 0
+ dc.w 0
+d_5: dc.w dpt-d_5
+d_6: dc.w dxx-d_6
+
+#else
+ dc.b 4
+ dc.b 0
+l5:
+ dc.w list1-l5
+ dc.w 0
+l5a:
+ dc.w Postit-l5a ; post proc
+l6:
+ dc.w apt-l6
+l7:
+ dc.w axx-l7
+* -------------------------------------
+ dc.b 4
+ dc.b 0
+l8:
+ dc.w list2-l8
+ dc.w 0
+l8a:
+ dc.w Postit-l8a ; post proc
+l9:
+ dc.w bpt-l9
+la:
+ dc.w bxx-la
+* -------------------------------------
+#endif
+ dc.w -1 ; end
+
+_qlflag:
+ dc.w 0
+_qlwait:
+ dc.w 250
+_dtype:
+ dc.w 255
+
+hpt: dc.w 10
+ dc.b 'Exit Delay'
+* 12345678901234567890
+ ds.w 0
+hxx: dc.w 0
+ dc.w $ffff
+ dc.w -1
+#ifdef ZIP
+dpt: dc.w 14
+ dc.b 'Directory Type'
+* 12345678901234567890
+ ds.w 0
+dxx: dc.w 3
+ dc.w $ff
+ dc.w -1
+#else
+
+list1:
+ dc.b 0
+list2:
+ dc.b 0
+
+apt:
+ dc.w 11
+ dc.b 'Unpack Mode'
+* 12345678901234567890
+.even
+axx: dc.b 0
+ dc.b 0
+ dc.w 8
+ dc.b 'SMS/QDOS'
+.even
+ dc.b 1
+ dc.b 0
+ dc.w 7
+ dc.b 'Default'
+.even
+ dc.w -1
+.even
+bpt:
+ dc.w 12
+ dc.b 'Listing Mode'
+* 12345678901234567890
+.even
+bxx:
+ dc.w 0
+ dc.w 7
+ dc.b 'Default'
+.even
+ dc.b 2
+ dc.b 0
+ dc.w 8
+ dc.b 'SMS/QDOS'
+* 12345678901234567890
+.even
+ dc.w -1
+Postit:
+ lea.l _qlflag,a0
+ move.b list1,d0
+ move.b d0,(a0)
+ move.b list2,d0
+ or.b d0,(a0)
+ moveq #0,d0
+ rts
+#endif
+ end
diff --git a/qdos/crc68.s b/qdos/crc68.s
new file mode 100644
index 0000000..cf74e47
--- /dev/null
+++ b/qdos/crc68.s
@@ -0,0 +1,99 @@
+;===========================================================================
+; Copyright (c) 1990-1999 Info-ZIP. All rights reserved.
+;
+; See the accompanying file LICENSE, version 1999-Oct-05 or later
+; (the contents of which are also included in zip.h) for terms of use.
+; If, for some reason, both of these files are missing, the Info-ZIP license
+; also may be found at: ftp://ftp.cdrom.com/pub/infozip/license.html
+;===========================================================================
+.text
+
+.globl _crc32 ; (ulg val, uch *buf, extent bufsize)
+.globl _get_crc_table ; ulg *get_crc_table(void)
+
+_crc32:
+ move.l 8(sp),d0
+ bne valid
+ moveq #0,d0
+ rts
+valid: movem.l d2/d3,-(sp)
+ jsr _get_crc_table
+ move.l d0,a0
+ move.l 12(sp),d0
+ move.l 16(sp),a1
+ move.l 20(sp),d1
+ not.l d0
+
+ move.l d1,d2
+ lsr.l #3,d1
+ bra decr8
+loop8: moveq #0,d3
+ move.b (a1)+,d3
+ eor.b d0,d3
+ lsl.w #2,d3
+ move.l 0(a0,d3.w),d3
+ lsr.l #8,d0
+ eor.l d3,d0
+ moveq #0,d3
+ move.b (a1)+,d3
+ eor.b d0,d3
+ lsl.w #2,d3
+ move.l 0(a0,d3.w),d3
+ lsr.l #8,d0
+ eor.l d3,d0
+ moveq #0,d3
+ move.b (a1)+,d3
+ eor.b d0,d3
+ lsl.w #2,d3
+ move.l 0(a0,d3.w),d3
+ lsr.l #8,d0
+ eor.l d3,d0
+ moveq #0,d3
+ move.b (a1)+,d3
+ eor.b d0,d3
+ lsl.w #2,d3
+ move.l 0(a0,d3.w),d3
+ lsr.l #8,d0
+ eor.l d3,d0
+ moveq #0,d3
+ move.b (a1)+,d3
+ eor.b d0,d3
+ lsl.w #2,d3
+ move.l 0(a0,d3.w),d3
+ lsr.l #8,d0
+ eor.l d3,d0
+ moveq #0,d3
+ move.b (a1)+,d3
+ eor.b d0,d3
+ lsl.w #2,d3
+ move.l 0(a0,d3.w),d3
+ lsr.l #8,d0
+ eor.l d3,d0
+ moveq #0,d3
+ move.b (a1)+,d3
+ eor.b d0,d3
+ lsl.w #2,d3
+ move.l 0(a0,d3.w),d3
+ lsr.l #8,d0
+ eor.l d3,d0
+ moveq #0,d3
+ move.b (a1)+,d3
+ eor.b d0,d3
+ lsl.w #2,d3
+ move.l 0(a0,d3.w),d3
+ lsr.l #8,d0
+ eor.l d3,d0
+decr8: dbra d1,loop8
+ and.w #7,d2
+ bra decr1
+loop1: moveq #0,d3
+ move.b (a1)+,d3
+ eor.b d0,d3
+ lsl.w #2,d3
+ move.l 0(a0,d3.w),d3
+ lsr.l #8,d0
+ eor.l d3,d0
+decr1: dbra d2,loop1
+done: movem.l (sp)+,d2/d3
+ not.l d0
+ rts
diff --git a/qdos/match.s b/qdos/match.s
new file mode 100644
index 0000000..53b3013
--- /dev/null
+++ b/qdos/match.s
@@ -0,0 +1,138 @@
+;===========================================================================
+; Copyright (c) 1990-1999 Info-ZIP. All rights reserved.
+;
+; See the accompanying file LICENSE, version 1999-Oct-05 or later
+; (the contents of which are also included in zip.h) for terms of use.
+; If, for some reason, both of these files are missing, the Info-ZIP license
+; also may be found at: ftp://ftp.cdrom.com/pub/infozip/license.html
+;===========================================================================
+; match.a -- optional optimized asm version of longest match in deflate.c
+; Written by Jean-loup Gailly
+;
+; Adapted for the Amiga by Carsten Steger <stegerc@informatik.tu-muenchen.de>
+; using the code in match.S.
+; The major change in this code consists of removing all unaligned
+; word accesses, because they cause 68000-based Amigas to crash.
+; For maximum speed, UNALIGNED_OK can be defined in Makefile.sasc.
+; The program will then only run on 68020-based Amigas, though.
+;
+; This code will run with registerized parameters too, unless SAS
+; changes parameter passing conventions between new releases of SAS/C.
+
+
+;;Cur_Match equr d0 ; Must be in d0!
+;;Best_Len equr d1
+;;Loop_Counter equr d2
+;;Scan_Start equr d3
+;;Scan_End equr d4
+;;Limit equr d5
+;;Chain_Length equr d6
+;;Scan_Test equr d7
+;;Scan equr a0
+;;Match equr a1
+;;Prev_Address equr a2
+;;Scan_Ini equr a3
+;;Match_Ini equr a4
+
+MAX_MATCH equ 258
+MIN_MATCH equ 3
+WSIZE equ 32768
+MAX_DIST equ WSIZE-MAX_MATCH-MIN_MATCH-1
+
+
+ .globl _max_chain_length
+ .globl _prev_length
+ .globl _prev
+ .globl _window
+ .globl _strstart
+ .globl _good_match
+ .globl _match_start
+ .globl _nice_match
+
+ .text
+ .globl _match_init
+ .globl _longest_match
+
+_match_init:
+ rts
+
+
+_longest_match:
+ move.l 4(sp),d0
+ movem.l d2-d7/a2-a4,-(sp)
+ move.l _max_chain_length,d6
+ move.l _prev_length,d1
+ lea _prev,a2
+ lea _window+MIN_MATCH,a4
+ move.l _strstart,d5
+ move.l a4,a3
+ add.l d5,a3
+ subi.w #MAX_DIST,d5
+ bhi limit_ok
+ moveq #0,d5
+limit_ok:
+ cmp.l _good_match,d1
+ bcs length_ok
+ lsr.l #2,d6
+length_ok:
+ subq.l #1,d6
+
+ move.b -MIN_MATCH(a3),d3
+ lsl.w #8,d3
+ move.b -MIN_MATCH+1(a3),d3
+ move.b -MIN_MATCH-1(a3,d1),d4
+ lsl.w #8,d4
+ move.b -MIN_MATCH(a3,d1),d4
+
+ bra do_scan
+
+long_loop:
+
+ move.b -MIN_MATCH-1(a3,d1),d4
+ lsl.w #8,d4
+ move.b -MIN_MATCH(a3,d1),d4
+
+short_loop:
+ lsl.w #1,d0
+ move.w 0(a2,d0.l),d0
+ cmp.w d5,d0
+ dbls d6,do_scan
+ bra return
+
+do_scan:
+ move.l a4,a1
+ add.l d0,a1
+
+ move.b -MIN_MATCH-1(a1,d1),d7
+ lsl.w #8,d7
+ move.b -MIN_MATCH(a1,d1),d7
+ cmp.w d7,d4
+ bne short_loop
+ move.b -MIN_MATCH(a1),d7
+ lsl.w #8,d7
+ move.b -MIN_MATCH+1(a1),d7
+ cmp.w d7,d3
+ bne short_loop
+
+ move.w #(MAX_MATCH-MIN_MATCH),d2
+ move.l a3,a0
+
+scan_loop:
+ cmpm.b (a1)+,(a0)+
+ dbne d2,scan_loop
+
+ sub.l a3,a0
+ addq.l #(MIN_MATCH-1),a0
+ cmp.l d1,a0
+ bls short_loop
+ move.l a0,d1
+ move.l d0,_match_start
+ cmp.l _nice_match,d1
+ bcs long_loop
+return:
+ move.l d1,d0
+ movem.l (sp)+,d2-d7/a2-a4
+ rts
+ end
+
+
diff --git a/qdos/osdep.h b/qdos/osdep.h
new file mode 100644
index 0000000..72169c1
--- /dev/null
+++ b/qdos/osdep.h
@@ -0,0 +1,33 @@
+/*
+ Copyright (c) 1990-1999 Info-ZIP. All rights reserved.
+
+ See the accompanying file LICENSE, version 1999-Oct-05 or later
+ (the contents of which are also included in zip.h) for terms of use.
+ If, for some reason, both of these files are missing, the Info-ZIP license
+ also may be found at: ftp://ftp.cdrom.com/pub/infozip/license.html
+*/
+#ifndef _QDOS_OPDEP
+#define _QDOS_OPDEP
+
+#include <stdlib.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <string.h>
+#include <ctype.h>
+
+char * ql2Unix(char *);
+char * Unix2ql(char *, char **);
+int wild (char *);
+char *LastDir(char *);
+void QDOSexit(void);
+short devlen(char *);
+
+/*
+ * XXX NO_RENAME instead of the following define ?
+ */
+#define link rename
+#define USE_CASE_MAP
+#define USE_EF_UT_TIME
+#define PROCNAME(n) (action == ADD || action == UPDATE ? wild(n) : \
+ procname(n, 1))
+#endif
diff --git a/qdos/qdos.c b/qdos/qdos.c
new file mode 100644
index 0000000..f07f56e
--- /dev/null
+++ b/qdos/qdos.c
@@ -0,0 +1,877 @@
+/*
+ Copyright (c) 1990-2005 Info-ZIP. All rights reserved.
+
+ See the accompanying file LICENSE, version 2004-May-22 or later
+ (the contents of which are also included in zip.h) for terms of use.
+ If, for some reason, both of these files are missing, the Info-ZIP license
+ also may be found at: ftp://ftp.info-zip.org/pub/infozip/license.html
+*/
+/*
+ * Yes this file is necessary; the QDOS file system is the most
+ * ludicrous known to man (even more so than VMS!).
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <dirent.h>
+#include <unistd.h>
+
+#include "zip.h"
+#include "crypt.h"
+#include "ttyio.h"
+
+#ifdef QDOS
+
+# include <qdos.h>
+
+#if CRYPT
+
+char *getp(m, p, n)
+ ZCONST char *m; /* prompt for password */
+ char *p; /* return value: line input */
+ int n; /* bytes available in p[] */
+{
+ int c; /* one-byte buffer for read() to use */
+ int i; /* number of characters input */
+ char *w; /* warning on retry */
+
+ /* get password */
+ w = "";
+ sd_cure(getchid(0), -1); /* enable cursor */
+ do {
+ fputs(w, stderr); /* warning if back again */
+ fputs(m, stderr); /* display prompt and flush */
+ fflush(stderr);
+ i = 0;
+ do {
+ c = getch();
+ if (c == 0xc2) {
+ if (i > 0) {
+ i--; /* the `del' keys works */
+ fputs("\b \b", stderr);
+ }
+ }
+ else if (i < n) {
+ p[i++] = c; /* truncate past n */
+ if(c != '\n') putc('*', stderr);
+ }
+ } while (c != '\n');
+
+ putc('\n', stderr); fflush(stderr);
+ w = "(line too long--try again)\n";
+ } while (p[i-1] != '\n');
+
+ p[i-1] = 0; /* terminate at newline */
+ sd_curs(getchid(0), -1); /* suppress cursor */
+ return p; /* return pointer to password */
+
+} /* end function getp() */
+
+#endif /* CRYPT */
+
+
+#define __attribute__(p)
+
+int newname(char *, int, int);
+
+#else /* !QDOS */
+#define QDOS_FLMAX 36
+
+short qlflag = 0;
+
+struct qdirect {
+ long d_length __attribute__ ((packed)); /* file length */
+ unsigned char d_access __attribute__ ((packed)); /* file access type */
+ unsigned char d_type __attribute__ ((packed)); /* file type */
+ long d_datalen __attribute__ ((packed)); /* data length */
+ long d_reserved __attribute__ ((packed));/* Unused */
+ short d_szname __attribute__ ((packed)); /* size of name */
+ char d_name[QDOS_FLMAX] __attribute__ ((packed));/* name area */
+ long d_update __attribute__ ((packed)); /* last update */
+ long d_refdate __attribute__ ((packed));
+ long d_backup __attribute__ ((packed)); /* EOD */
+ } ;
+#endif /* ?QDOS */
+
+#define SHORTID 0x4afb /* in big-endian order !! */
+#define LONGID "QDOS02"
+#define EXTRALEN (sizeof(struct qdirect) + 8)
+
+typedef struct
+{
+ unsigned short shortid __attribute__ ((packed));
+ struct
+ {
+ unsigned char lo __attribute__ ((packed));
+ unsigned char hi __attribute__ ((packed));
+ } len __attribute__ ((packed));
+ char longid[8] __attribute__ ((packed));
+ struct qdirect header __attribute__ ((packed));
+} qdosextra;
+
+#ifdef USE_EF_UT_TIME
+local int GetExtraTime(struct zlist far *z, iztimes *z_utim, unsigned ut_flg);
+#endif
+
+#ifdef QDOS
+
+#define rev_short(x) (x)
+#define rev_long(x) (x)
+
+char _prog_name[] = "zip";
+char _copyright[] = "(c) Info-ZIP Group";
+long _stack = 16*1024;
+char * _endmsg = NULL;
+
+extern void consetup_title(chanid_t,struct WINDOWDEF *);
+void (*_consetup)(chanid_t,struct WINDOWDEF *) = consetup_title;
+
+struct WINDOWDEF _condetails =
+{
+ 2,
+ 1,
+ 0,
+ 7,
+ 500,
+ 220,
+ 2,
+ 30
+};
+
+extern short qlwait;
+extern short dtype;
+
+#define CHECKDIR(p1) (((p1).d_type == dtype) && (((p1).d_length % 64) == 0))
+
+char * stpcpy (char *d, ZCONST char *s)
+{
+ while(*d++ = *s++)
+ ; /* Null loop */
+ return d-1;
+}
+
+static jobid_t chowner(chanid_t chan)
+{
+ extern char *_sys_var;
+ char *scht;
+ long *cdb;
+ long jid;
+
+ scht = *((char **)(_sys_var + 0x78));
+ cdb = *(long **)((long *)scht + (chan & 0xffff));
+ jid = *(cdb + 2);
+ return jid;
+}
+
+void QDOSexit(void)
+{
+ jobid_t me,you;
+
+ me = getpid();
+ you = chowner(getchid(0));
+
+ if((me == you) && ((qlflag & 4) == 0))
+ {
+ if(isatty(0) && isatty(2) && qlwait)
+ {
+ char c = 0;
+ fputs("Press a key to exit", stderr);
+ if((io_fbyte(getchid(0), qlwait, &c) == 0) && c == 27)
+ {
+ io_fbyte(getchid(0), -1, &c);
+ }
+ }
+ }
+ exit(0);
+}
+
+/* Access seems to be *always* broken in c68 */
+/* Not accurate, just works */
+
+int access (char *f, int mode)
+{
+ struct stat st;
+ int fd;
+
+ if((fd = stat(f, &st)) == 0)
+ {
+ switch(fd)
+ {
+ case F_OK:
+ break;
+ case R_OK:
+ fd = (st.st_mode & 0444) == 0;
+ break;
+ case W_OK:
+ fd = (st.st_mode & 0222) == 0;
+ break;
+ case X_OK:
+ fd = (st.st_mode & 0111) == 0;
+ break;
+ default:
+ fd = -1;
+ break;
+ }
+ }
+ return fd;
+}
+
+/* Fixup a Mickey Mouse file naming system */
+
+char * Unix2ql (char *qlname, char **dot)
+{
+ static char path[64];
+ char name[64];
+ char *q, *r, *s;
+
+ strcpy(name, qlname);
+ if(*name == '~')
+ {
+ r = name+1;
+ getcwd(path, sizeof(path));
+ q = path + strlen(path);
+ if(*(q-1) != '_')
+ {
+ *q++ = '_';
+ }
+ }
+ else
+ {
+ q = path;
+ r = name;
+ }
+
+ if(*r == '/')
+ {
+ r++;
+ }
+
+ strcpy(q, r);
+
+ while (*q)
+ {
+ if(*q == '/' || *q == '.')
+ {
+ if(*q == '.' && dot)
+ {
+ *dot = name + (q - path);
+ }
+ *q = '_';
+ }
+
+ q++;
+ }
+ return path;
+}
+
+#if 0 /* Not used in ZIP */
+
+GuessAltName(char *name, char *dot)
+{
+ if(dot)
+ {
+ *dot = '.';
+ }
+ else
+ {
+ if((dot = strrchr(name, '_')))
+ {
+ *dot = '.';
+ }
+ }
+}
+
+#endif /* 0 */
+
+short devlen(char *p)
+{
+ char defpath[40];
+ short deflen = 0, ok = 0;
+
+ getcwd(defpath, sizeof(defpath));
+ deflen = strlen(defpath);
+ if(deflen)
+ {
+ if(strnicmp(p, defpath, deflen) == 0)
+ {
+ ok = 1;
+ }
+ }
+
+ if(!ok)
+ {
+ if(isdirdev(p))
+ {
+ deflen = 5;
+ }
+ else
+ {
+ deflen = 0;
+ }
+ }
+ return deflen;
+}
+
+char * ql2Unix (char *qlname)
+{
+ struct stat st;
+ int sts;
+ char *p, *r, *s, *ldp;
+ char *pnam = NULL;
+ static char path[64];
+ short deflen;
+ char name[64];
+
+ strcpy(name, qlname);
+ strcpy(path, name);
+
+ deflen = devlen(qlname);
+
+ p = name + deflen;
+ pnam = path + deflen;
+
+ if(s = strrchr(p, '_'))
+ {
+ *s = 0;
+ sts = stat(name, &st);
+ if(deflen && sts ==0 && (st.st_mode & S_IFDIR))
+ {
+ *(path+(s-name)) = '/';
+ }
+ else
+ {
+ *(path+(s-name)) = '.';
+ }
+ }
+
+ ldp = p;
+ for(r = p; *r; r++)
+ {
+ if(r != ldp && *r == '_')
+ {
+ *r = 0;
+ if(deflen)
+ {
+ sts = stat(name, &st);
+ }
+ else
+ sts = -1;
+
+ if(sts ==0 && (st.st_mode & S_IFDIR))
+ {
+ *(path+(r-name)) = '/';
+ ldp = r + 1;
+ }
+ else
+ {
+ *(path+(r-name)) = '_';
+ }
+ *r = '_';
+ }
+ }
+ return pnam;
+}
+
+char *LastDir(char *ws)
+{
+ char *p;
+ char *q = ws;
+ struct stat s;
+
+ for(p = ws; *p; p++)
+ {
+ if(p != ws && *p == '_')
+ {
+ char c;
+
+ p++;
+ c = *p;
+ *p = 0;
+ if(stat(ws, &s) == 0 && S_ISDIR(s.st_mode))
+ {
+ q = p;
+ }
+ *p = c;
+ }
+ }
+ return q;
+}
+
+# ifndef UTIL
+
+static int add_dir(char * dnam)
+{
+ int e = ZE_OK;
+ char *p;
+ short nlen;
+
+ nlen = strlen(dnam);
+ if(p = malloc(nlen + 2))
+ {
+ strncpy (p, dnam, nlen);
+ if(*(p+nlen) != '_')
+ {
+ *(p+nlen) = '_';
+ *(p+nlen+1) = '\0';
+ }
+ if ((e = newname(p, 1, 0)) != ZE_OK)
+ {
+ free(p);
+ }
+ }
+ else
+ {
+ e = ZE_MEM;
+ }
+ return e;
+}
+
+int qlwild (char *dnam, short dorecurse, short l)
+{
+ static char match[40] = {0};
+ static char ddev[8] = {0};
+ static short nc;
+ static short llen;
+ static char base[40];
+
+ int chid;
+ struct qdirect qd;
+ char *dp;
+ int e = ZE_MISS;
+
+ if (l == 0)
+ {
+ nc = 0;
+ *base = '\0';
+ if (isdirdev (dnam))
+ {
+ dp = dnam;
+ strncpy (ddev, dnam, 5);
+ }
+ else
+ {
+
+ char *p;
+ char temp[40];
+
+ getcwd (temp, 40);
+
+ llen = strlen(temp);
+ p = (temp + llen - 1);
+ if (*p != '_')
+ {
+ *p++ = '_';
+ *p = 0;
+ }
+
+ strncpy (ddev, temp, 5);
+ dp = base;
+ p = stpcpy (dp, temp);
+ strcpy (p, dnam);
+ }
+
+ {
+ char *q = isshexp (dp);
+ if(q)
+ {
+ strcpy (match, dp + 5);
+ if (q)
+ {
+ while (q != dp && *q != '_')
+ {
+ q--;
+ }
+ *(++q) = '\0';
+ }
+ }
+ else
+ {
+ struct stat s;
+ if (stat(dp, &s) == 0)
+ {
+ if (!(s.st_mode & S_IFDIR))
+ {
+ return procname(dp, 0);
+ }
+ }
+ else
+ {
+ return ZE_MISS; /* woops, no wildcards! */
+ }
+ }
+
+ }
+ }
+ else
+ {
+ dp = dnam;
+ }
+
+ if ((chid = io_open (dp, 4L)) > 0)
+ {
+ int id = 0;
+ while (io_fstrg (chid, -1, &qd, 64) > 0)
+ {
+ short j;
+
+ if (qd.d_szname)
+ {
+ if (CHECKDIR(qd))
+ {
+ if(dorecurse)
+ {
+ char fnam[256], *p;
+
+ p = stpcpy (fnam, ddev);
+ strncpy (p, qd.d_name, qd.d_szname);
+ *(p + qd.d_szname) = 0;
+ e = qlwild (fnam, dorecurse, l+1);
+ }
+ else
+ {
+ continue;
+ }
+ }
+ else
+ {
+ char nam[48];
+ strcpy(nam, ddev);
+
+ strncpy (nam + 5, qd.d_name, qd.d_szname);
+ *(nam + 5 + qd.d_szname) = 0;
+
+ if (MATCH (match, nam + 5, 0) == 1)
+ {
+ if(dirnames && l && id == 0)
+ {
+ id = 1;
+ if((e = add_dir(dp)) != ZE_OK)
+ {
+ return e;
+ }
+ }
+
+ if((e = procname(nam, 0)) == ZE_OK)
+ {
+ nc++;
+ }
+ }
+ }
+ }
+ }
+ io_close (chid);
+ }
+
+ if (l == 0)
+ {
+ *ddev = 0;
+ *match = 0;
+ e = (nc) ? ZE_OK : ZE_MISS;
+ }
+ return e;
+
+}
+
+int wild(char *p)
+{
+ return qlwild(p, recurse, 0);
+}
+# endif /* !UTIL */
+
+/*
+ * Return QDOS error, 0 if exec 1 if found but not exe or rel
+ */
+int qlstat(char *name, struct qdirect *qs, char *flag)
+{
+ int r;
+ r = qstat(name, qs);
+ if(r == 0)
+ {
+ if(qs->d_type == 0)
+ {
+ r = 1;
+ }
+ else if(CHECKDIR(*qs))
+ {
+ r = 255;
+ }
+ }
+ return r;
+}
+
+#else /* !QDOS */
+
+long rev_long (ulg l)
+{
+ uch cc[4];
+ cc[0] = (uch)(l >> 24);
+ cc[1] = (uch)((l >> 16) & 0xff);
+ cc[2] = (uch)((l >> 8) & 0xff);
+ cc[3] = (uch)(l & 0xff);
+ return *(ulg *)cc;
+}
+
+short rev_short (ush s)
+{
+ uch cc[2];
+ cc[0] = (uch)((s >> 8) & 0xff);
+ cc[1] = (uch)(s & 0xff);
+ return *(ush *)cc;
+}
+
+#define O_BINARY 0
+
+int qlstat(char *name, struct qdirect *qs, char *flag)
+{
+ int r = -1;
+ int n, fd;
+ struct stat s;
+ struct _ntc_
+ {
+ long id;
+ long dlen;
+ } ntc;
+
+ *flag = 0;
+ if((fd = open(name, O_RDONLY | O_BINARY)) > 0)
+ {
+ short nl;
+
+ fstat(fd, &s);
+ lseek(fd, -8, SEEK_END);
+ read(fd, &ntc, 8);
+ qs->d_length = rev_long(s.st_size);
+ qs->d_update = rev_long(s.st_ctime + 283996800);
+
+ nl = strlen(name);
+ if(nl > QDOS_FLMAX)
+ {
+ nl = QDOS_FLMAX;
+ *flag = 1;
+ }
+ qs->d_szname = rev_short(nl);
+ memcpy(qs->d_name, name, nl);
+
+ if(ntc.id == *(long *)"XTcc")
+ {
+ qs->d_datalen = ntc.dlen; /* This is big endian */
+ qs->d_type = 1;
+ r = 0;
+ }
+ else
+ {
+ qs->d_type = 0;
+ qs->d_datalen = 0;
+ r = 1;
+ }
+ close(fd);
+ return r;
+ }
+ else
+ {
+ fprintf(stderr, "Fails %d\n", fd);
+ return r;
+ }
+}
+
+#endif /* ?QDOS */
+
+#ifdef USE_EF_UT_TIME
+
+#define EB_L_UT_SIZE (EB_HEADSIZE + eb_l_ut_len)
+#define EB_C_UT_SIZE (EB_HEADSIZE + eb_c_ut_len)
+
+#ifdef UNIX
+#define EB_L_UX2_SIZE (EB_HEADSIZE + EB_UX2_MINLEN)
+#define EB_C_UX2_SIZE EB_HEADSIZE
+#define EF_L_UT_UX2_SIZE (EB_L_UT_SIZE + EB_L_UX2_SIZE)
+#define EF_C_UT_UX2_SIZE (EB_C_UT_SIZE + EB_C_UX2_SIZE)
+#else
+#define EF_L_UT_UX2_SIZE EB_L_UT_SIZE
+#define EF_C_UT_UX2_SIZE EB_C_UT_SIZE
+#endif
+
+local int GetExtraTime(struct zlist far *z, iztimes *z_utim, unsigned ut_flg)
+{
+ char *eb_l_ptr;
+ char *eb_c_ptr;
+ char *eb_pt;
+ extent eb_l_ut_len = 0;
+ extent eb_c_ut_len = 0;
+
+#ifdef UNIX
+ struct stat s;
+
+ /* For the full sized UT local field including the UID/GID fields, we
+ * have to stat the file, again. */
+ if (stat(z->name, &s))
+ return ZE_OPEN;
+ /* update times in z_utim, stat() call might have changed atime... */
+ z_utim->mtime = s.st_mtime;
+ z_utim->atime = s.st_atime;
+ z_utim->ctime = s.st_mtime; /* best guess (st_ctime != creation time) */
+#endif /* UNIX */
+
+#ifdef IZ_CHECK_TZ
+ if (!zp_tz_is_valid)
+ ut_flg = 0; /* disable UT e.f creation if no valid TZ info */
+#endif
+ if (ut_flg != 0) {
+ if (ut_flg & EB_UT_FL_MTIME)
+ eb_l_ut_len = eb_c_ut_len = 1;
+ if (ut_flg & EB_UT_FL_ATIME)
+ eb_l_ut_len++;
+ if (ut_flg & EB_UT_FL_CTIME)
+ eb_l_ut_len++;
+
+ eb_l_ut_len = EB_UT_LEN(eb_l_ut_len);
+ eb_c_ut_len = EB_UT_LEN(eb_c_ut_len);
+ }
+
+ if (EF_L_UT_UX2_SIZE > EB_HEADSIZE) {
+ if(z->ext)
+ eb_l_ptr = realloc(z->extra, (z->ext + EF_L_UT_UX2_SIZE));
+ else
+ eb_l_ptr = malloc(EF_L_UT_UX2_SIZE);
+
+ if (eb_l_ptr == NULL)
+ return ZE_MEM;
+
+ if(z->cext)
+ eb_c_ptr = realloc(z->cextra, (z->cext + EF_C_UT_UX2_SIZE));
+ else
+ eb_c_ptr = malloc(EF_C_UT_UX2_SIZE);
+
+ if (eb_c_ptr == NULL)
+ return ZE_MEM;
+
+ z->extra = eb_l_ptr;
+ eb_l_ptr += z->ext;
+ z->ext += EF_L_UT_UX2_SIZE;
+
+ if (ut_flg != 0) {
+ eb_l_ptr[0] = 'U';
+ eb_l_ptr[1] = 'T';
+ eb_l_ptr[2] = eb_l_ut_len; /* length of data part of e.f. */
+ eb_l_ptr[3] = 0;
+ eb_l_ptr[4] = ut_flg;
+ eb_pt = eb_l_ptr + 5;
+ if (ut_flg & EB_UT_FL_MTIME) {
+ *eb_pt++ = (char)(z_utim->mtime);
+ *eb_pt++ = (char)(z_utim->mtime >> 8);
+ *eb_pt++ = (char)(z_utim->mtime >> 16);
+ *eb_pt++ = (char)(z_utim->mtime >> 24);
+ }
+ if (ut_flg & EB_UT_FL_ATIME) {
+ *eb_pt++ = (char)(z_utim->atime);
+ *eb_pt++ = (char)(z_utim->atime >> 8);
+ *eb_pt++ = (char)(z_utim->atime >> 16);
+ *eb_pt++ = (char)(z_utim->atime >> 24);
+ }
+ if (ut_flg & EB_UT_FL_CTIME) {
+ *eb_pt++ = (char)(z_utim->ctime);
+ *eb_pt++ = (char)(z_utim->ctime >> 8);
+ *eb_pt++ = (char)(z_utim->ctime >> 16);
+ *eb_pt++ = (char)(z_utim->ctime >> 24);
+ }
+ }
+#ifdef UNIX
+ else {
+ eb_pt = eb_l_ptr;
+ }
+ *eb_pt++ = 'U';
+ *eb_pt++ = 'x';
+ *eb_pt++ = EB_UX2_MINLEN; /* length of data part of local e.f. */
+ *eb_pt++ = 0;
+ *eb_pt++ = (char)(s.st_uid);
+ *eb_pt++ = (char)(s.st_uid >> 8);
+ *eb_pt++ = (char)(s.st_gid);
+ *eb_pt++ = (char)(s.st_gid >> 8);
+#endif /* UNIX */
+
+ z->cextra = eb_c_ptr;
+ eb_c_ptr += z->cext;
+ z->cext += EF_C_UT_UX2_SIZE;
+
+ if (ut_flg != 0) {
+ memcpy(eb_c_ptr, eb_l_ptr, EB_C_UT_SIZE);
+ eb_c_ptr[EB_LEN] = eb_c_ut_len;
+ }
+#ifdef UNIX
+ memcpy(eb_c_ptr+EB_C_UT_SIZE, eb_l_ptr+EB_L_UT_SIZE, EB_C_UX2_SIZE);
+ eb_c_ptr[EB_LEN+EB_C_UT_SIZE] = 0;
+#endif /* UNIX */
+ }
+
+ return ZE_OK;
+}
+
+#endif /* USE_EF_UT_TIME */
+
+
+int set_extra_field (struct zlist *z, iztimes *z_utim )
+{
+ int rv = 0;
+ int last_rv = 0;
+ char flag = 0;
+
+ if ((qlflag & 3) != 1)
+ {
+ qdosextra *lq, *cq;
+ if ((lq = (qdosextra *) calloc(sizeof(qdosextra), 1)) == NULL)
+ return ZE_MEM;
+ if ((cq = (qdosextra *) calloc(sizeof(qdosextra), 1)) == NULL)
+ return ZE_MEM;
+
+ rv = qlstat(z->name, &(lq->header), &flag);
+
+ if (rv == 0 || (rv == 1 && (qlflag & 2)))
+ {
+ lq->shortid = rev_short((short) SHORTID);
+ lq->len.lo = (unsigned char)(EXTRALEN & 0xff);
+ lq->len.hi = (unsigned char)(EXTRALEN >> 8);
+ strcpy(lq->longid, LONGID);
+
+ memcpy(cq, lq, sizeof(qdosextra));
+
+ z->ext = sizeof(qdosextra);
+ z->cext = sizeof(qdosextra);
+ z->extra = (void *) lq;
+ z->cextra = (void *) cq;
+ fprintf (stderr, " %c",
+ lq->header.d_datalen ? '*' : '#');
+ }
+ else if (rv == -1)
+ {
+ fprintf(stderr,
+ "%s: warning: cannot stat %s, no file header added\n",
+ "zip", z->name);
+ }
+ if(flag)
+ {
+ fputs (" !", stderr);
+ }
+ }
+ last_rv = (rv == -1 ? ZE_OPEN : ZE_OK);
+
+#ifdef USE_EF_UT_TIME
+# ifdef QDOS
+# define IZ_UT_FLAGS EB_UT_FL_MTIME
+# endif
+# ifdef UNIX
+# define IZ_UT_FLAGS (EB_UT_FL_MTIME | EB_UT_FL_ATIME)
+# endif
+# ifndef IZ_UT_FLAGS
+# define IZ_UT_FLAGS EB_UT_FL_MTIME
+# endif
+
+ rv = GetExtraTime(z, z_utim, IZ_UT_FLAGS);
+ if (rv != ZE_OK)
+ last_rv = rv;
+#endif /* USE_EF_UT_TIME */
+
+ return last_rv;
+}
diff --git a/qdos/qfileio.c b/qdos/qfileio.c
new file mode 100644
index 0000000..07a6bd8
--- /dev/null
+++ b/qdos/qfileio.c
@@ -0,0 +1,235 @@
+/*
+ Copyright (c) 1990-2005 Info-ZIP. All rights reserved.
+
+ See the accompanying file LICENSE, version 2004-May-22 or later
+ (the contents of which are also included in zip.h) for terms of use.
+ If, for some reason, both of these files are missing, the Info-ZIP license
+ also may be found at: ftp://ftp.info-zip.org/pub/infozip/license.html
+*/
+#include "zip.h"
+
+#ifndef UTIL /* the companion #endif is a bit of ways down ... */
+
+#include <time.h>
+#include <utime.h>
+
+#include <errno.h>
+
+#ifdef S_IWRITE
+# undef S_IWRITE
+#endif /* S_IWRITE */
+#define S_IWRITE S_IWUSR
+
+
+extern char *label;
+local ulg label_time = 0;
+local ulg label_mode = 0;
+local time_t label_utim = 0;
+
+
+typedef time_t statime;
+#define PAD 0
+#define PATH_END '/'
+
+/* Local functions */
+
+int procname(n, caseflag)
+char *n; /* name to process */
+int caseflag; /* true to force case-sensitive match */
+/* Process a name or sh expression to operate on (or exclude). Return
+ an error code in the ZE_ class. */
+{
+ char *a; /* path and name for recursion */
+ int m; /* matched flag */
+ char *p; /* path for recursion */
+ struct stat s; /* result of stat() */
+ struct zlist far *z; /* steps through zfiles list */
+
+ if (strcmp(n, "-") == 0) /* if compressing stdin */
+ return newname(n, 0, caseflag);
+ else if (SSTAT(n, &s) )
+ {
+ /* Not a file or directory--search for shell expression in zip file */
+ p = ex2in(n, 0, (int *)NULL); /* shouldn't affect matching chars */
+
+ m = 1;
+ for (z = zfiles; z != NULL; z = z->nxt) {
+ if (MATCH(p, z->iname, caseflag))
+ {
+ z->mark = pcount ? filter(z->zname, caseflag) : 1;
+ if (verbose)
+ fprintf(mesg, "zip diagnostic: %scluding %s\n",
+ z->mark ? "in" : "ex", z->name);
+ m = 0;
+ }
+ }
+ free(p);
+ return m ? ZE_MISS : ZE_OK;
+ }
+
+ /* Live name--use if file, recurse if directory */
+
+ if ((s.st_mode & S_IFDIR) == 0)
+ {
+ /* add or remove name of file */
+ if ((m = newname(n, 0, caseflag)) != ZE_OK)
+ return m;
+ }
+ return ZE_OK;
+}
+
+
+
+char *ex2in(x, isdir, pdosflag)
+char *x; /* external file name */
+int isdir; /* input: x is a directory */
+int *pdosflag; /* output: force MSDOS file attributes? */
+/* Convert the external file name to a zip file name, returning the malloc'ed
+ string or NULL if not enough memory. */
+{
+ char *n; /* internal file name (malloc'ed) */
+ char *t; /* shortened name */
+ int dosflag;
+
+ t = ql2Unix(x);
+
+ dosflag = dosify; /* default for non-DOS and non-OS/2 */
+
+ /* Make changes, if any, to the copied name (leave original intact) */
+
+ if (!pathput)
+ t = last(t, PATH_END);
+
+ /* Discard directory names with zip -rj */
+ if (*t == '\0')
+ return t;
+
+ /* Malloc space for internal name and copy it */
+ if ((n = malloc(strlen(t) + 1)) == NULL)
+ return NULL;
+ strcpy(n, t);
+
+ if (dosify)
+ msname(n);
+ /* Returned malloc'ed name */
+ if (pdosflag)
+ *pdosflag = dosflag;
+ return n;
+}
+
+
+char *in2ex(n)
+char *n; /* internal file name */
+/* Convert the zip file name to an external file name, returning the malloc'ed
+ string or NULL if not enough memory. */
+{
+ char *x; /* external file name */
+
+ if ((x = malloc(strlen(n) + 1 + PAD)) == NULL)
+ return NULL;
+ strcpy(x, Unix2ql(n, NULL));
+ return x;
+}
+
+
+void stamp(f, d)
+char *f; /* name of file to change */
+ulg d; /* dos-style time to change it to */
+/* Set last updated and accessed time of file f to the DOS time d. */
+{
+ struct utimbuf u; /* argument for utime() const ?? */
+
+ /* Convert DOS time to time_t format in u */
+ u.actime = u.modtime = dos2unixtime(d);
+ utime(f, &u);
+}
+
+ulg filetime(f, a, n, t)
+char *f; /* name of file to get info on */
+ulg *a; /* return value: file attributes */
+long *n; /* return value: file size */
+iztimes *t; /* return value: access, modific. and creation times */
+/* If file *f does not exist, return 0. Else, return the file's last
+ modified date and time as an MSDOS date and time. The date and
+ time is returned in a long with the date most significant to allow
+ unsigned integer comparison of absolute times. Also, if a is not
+ a NULL pointer, store the file attributes there, with the high two
+ bytes being the Unix attributes, and the low byte being a mapping
+ of that to DOS attributes. If n is not NULL, store the file size
+ there. If t is not NULL, the file's access, modification and creation
+ times are stored there as UNIX time_t values.
+ If f is "-", use standard input as the file. If f is a device, return
+ a file size of -1 */
+{
+ struct stat s; /* results of stat() */
+ char *name;
+ unsigned int len = strlen(f);
+
+ if (f == label) {
+ if (a != NULL)
+ *a = label_mode;
+ if (n != NULL)
+ *n = -2L; /* convention for a label name */
+ if (t != NULL)
+ t->atime = t->mtime = t->ctime = label_utim;
+ return label_time;
+ }
+
+ name = malloc(len+1);
+ if (!name)
+ return 0; /* ideally, would like to report alloc-failure warning/error */
+
+ strcpy(name, f);
+ if (name[len - 1] == '/')
+ name[len - 1] = '\0';
+ /* not all systems allow stat'ing a file with / appended */
+ if (strcmp(f, "-") == 0) {
+ if (fstat(fileno(stdin), &s) != 0) {
+ free(name);
+ error("fstat(stdin)");
+ }
+ } else if (LSSTAT(name, &s) != 0) {
+ /* Accept about any file kind including directories
+ * (stored with trailing / with -r option)
+ */
+ free(name);
+ return 0;
+ }
+
+ if (a != NULL) {
+ *a = ((ulg)s.st_mode << 16) | !(s.st_mode & S_IWRITE);
+ if ((s.st_mode & S_IFMT) == S_IFDIR) {
+ *a |= MSDOS_DIR_ATTR;
+ }
+ }
+ if (n != NULL)
+ *n = (s.st_mode & S_IFMT) == S_IFREG ? s.st_size : -1L;
+ if (t != NULL) {
+ t->atime = s.st_atime;
+ t->mtime = s.st_mtime;
+ t->ctime = s.st_ctime;
+ }
+
+ free(name);
+
+ return unix2dostime(&s.st_mtime);
+}
+
+
+int deletedir(d)
+char *d; /* directory to delete */
+/* Delete the directory *d if it is empty, do nothing otherwise.
+ Return the result of rmdir(), delete(), or system().
+ For VMS, d must be in format [x.y]z.dir;1 (not [x.y.z]).
+ */
+{
+ return rmdir(d);
+}
+
+#endif /* !UTIL */
+
+
+void version_local()
+{
+ puts ("Compiled with c68 v4.2x on " __DATE__);
+}
diff --git a/qdos/zipup.h b/qdos/zipup.h
new file mode 100644
index 0000000..1de3f61
--- /dev/null
+++ b/qdos/zipup.h
@@ -0,0 +1,19 @@
+/*
+ Copyright (c) 1990-1999 Info-ZIP. All rights reserved.
+
+ See the accompanying file LICENSE, version 1999-Oct-05 or later
+ (the contents of which are also included in zip.h) for terms of use.
+ If, for some reason, both of these files are missing, the Info-ZIP license
+ also may be found at: ftp://ftp.cdrom.com/pub/infozip/license.html
+*/
+#ifndef O_RDONLY
+# define O_RDONLY 0
+#endif
+#define fhow O_RDONLY
+#define fbad (-1)
+typedef int ftype;
+#define zopen(n,p) open(n,p)
+#define zread(f,b,n) read(f,b,n)
+#define zclose(f) close(f)
+#define zerr(f) (k == (extent)(-1L))
+#define zstdin 0