summaryrefslogtreecommitdiff
path: root/theos
diff options
context:
space:
mode:
authorKim Kibum <kb0929.kim@samsung.com>2012-08-24 14:34:26 +0900
committerKim Kibum <kb0929.kim@samsung.com>2012-08-24 14:34:26 +0900
commit4acc22dd2f30f063c7b07fdbc911384feeda58eb (patch)
treea78b9ba604297cddb9a23424ccc8abfc6ae7ba94 /theos
parent3101b2a7be8f0e3cc6ff469ce2597945c862264b (diff)
downloadzip-4acc22dd2f30f063c7b07fdbc911384feeda58eb.tar.gz
zip-4acc22dd2f30f063c7b07fdbc911384feeda58eb.tar.bz2
zip-4acc22dd2f30f063c7b07fdbc911384feeda58eb.zip
upload source
Diffstat (limited to 'theos')
-rw-r--r--theos/Makefile135
-rw-r--r--theos/README34
-rw-r--r--theos/_chmod.c21
-rw-r--r--theos/_fprintf.c26
-rw-r--r--theos/_isatty.c26
-rw-r--r--theos/_rename.c83
-rw-r--r--theos/_setargv.c140
-rw-r--r--theos/_stat.c461
-rw-r--r--theos/charconv.h93
-rw-r--r--theos/osdep.h58
-rw-r--r--theos/stat.h106
-rw-r--r--theos/theos.c558
-rw-r--r--theos/zipup.h19
13 files changed, 1760 insertions, 0 deletions
diff --git a/theos/Makefile b/theos/Makefile
new file mode 100644
index 0000000..cb3d6da
--- /dev/null
+++ b/theos/Makefile
@@ -0,0 +1,135 @@
+# Makefile for Zip, ZipCloak, ZipNote and ZipSplit for
+# THEOS ANSI C
+# To use, do "make -f theos/makefile"
+# This make file uses cl, a C compiler and linker driver written by
+# Jean-Michel Dubois. Send a mail to jmdubois@ibcfrance.fr to get it for free.
+# MAINWA_BUG Workaround argument expansion failure
+# LOCATE_BUG Workaround stat, fopen and open failure on relative paths to
+# root dir.
+
+CC=cl
+CFLAGS=-Zi -W3 -DDYN_ALLOC -DCRYPT -DMAINWA_BUG -DLOCATE_BUG
+LD=cl -o
+LDFLAGS=-m -Zi
+AS=cc
+ASFLAGS=
+
+UTILFLAGS=-DUTIL $(CFLAGS) -Fo
+
+# variables
+
+# object file lists
+OBJZ = zip.o zipfile.o zipup.o fileio.o util.o globals.o crypt.o ttyio.o \
+ theos.o crc32.o crctab.o _fprintf.o _stat.o _chmod.o _isatty.o \
+ _setargv.o _rename.o
+OBJI = deflate.o trees.o
+OBJA =
+OBJU = zipfile_.o fileio_.o util_.o globals.o theos_.o _rename.o _stat.o \
+ _chmod.o _fprintf.o
+OBJN = zipnote.o $(OBJU)
+OBJC = zipcloak.o $(OBJU) crctab.o crypt_.o ttyio.o
+OBJS = zipsplit.o $(OBJU)
+
+ZIPS = zip.command zipnote.command zipsplit.command zipcloak.command
+
+zips: $(ZIPS)
+
+zip.o: zip.h theos/osdep.h ziperr.h tailor.h ttyio.h revision.h zip.c
+ $(CC) -c $(CFLAGS) $*.c
+
+zipfile.o: zip.h theos/osdep.h ziperr.h tailor.h zipfile.c
+ $(CC) -c $(CFLAGS) $*.c
+
+zipup.o: zip.h theos/osdep.h ziperr.h tailor.h revision.h zipup.c
+ $(CC) -c $(CFLAGS) $*.c
+
+fileio.o: zip.h theos/osdep.h ziperr.h tailor.h fileio.c
+ $(CC) -c $(CFLAGS) $*.c
+
+util.o: zip.h theos/osdep.h theos/charconv.h ziperr.h tailor.h util.c
+ $(CC) -c $(CFLAGS) $*.c
+
+globals.o: zip.h theos/osdep.h ziperr.h tailor.h globals.c
+ $(CC) -c $(CFLAGS) $*.c
+
+crc32.o: zip.h theos/osdep.h ziperr.h tailor.h crc32.c
+ $(CC) -c $(CFLAGS) $*.c
+
+crctab.o: zip.h theos/osdep.h ziperr.h tailor.h crctab.c
+ $(CC) -c $(CFLAGS) $*.c
+
+deflate.o: zip.h theos/osdep.h ziperr.h tailor.h deflate.c
+ $(CC) -c $(CFLAGS) $*.c
+
+trees.o: zip.h theos/osdep.h ziperr.h tailor.h trees.c
+ $(CC) -c $(CFLAGS) $*.c
+
+crypt.o: zip.h theos/osdep.h ziperr.h tailor.h crypt.c
+ $(CC) -c $(CFLAGS) $*.c
+
+theos.o: zip.h theos/osdep.h ziperr.h tailor.h theos/theos.c
+ $(CC) -c $(CFLAGS) -Fo$@ theos/theos.c
+
+_fprintf.o: theos/_fprintf.c
+ $(CC) -c $(CFLAGS) -Fo$@ theos/_fprintf.c
+
+_stat.o: theos/_stat.c
+ $(CC) -c $(CFLAGS) -Fo$@ theos/_stat.c
+
+_chmod.o: theos/_chmod.c
+ $(CC) -c $(CFLAGS) -Fo$@ theos/_chmod.c
+
+_isatty.o: theos/_isatty.c
+ $(CC) -c $(CFLAGS) -Fo$@ theos/_isatty.c
+
+_rename.o: theos/_rename.c
+ $(CC) -c $(CFLAGS) -Fo$@ theos/_rename.c
+
+_setargv.o: theos/_setargv.c
+ $(CC) -c $(CFLAGS) -Fo$@ theos/_setargv.c
+
+ttyio.o: zip.h theos/osdep.h ziperr.h tailor.h ttyio.h ttyio.c
+ $(CC) -c $(CFLAGS) $*.c
+
+zipcloak.o: zip.h theos/osdep.h ziperr.h tailor.h ttyio.h revision.h zipcloak.c
+ $(CC) -c $(CFLAGS) $*.c
+
+zipnote.o: zip.h theos/osdep.h ziperr.h tailor.h revision.h zipnote.c
+ $(CC) -c $(CFLAGS) $*.c
+
+zipsplit.o: zipsplit.c zip.h theos/osdep.h ziperr.h tailor.h revision.h
+ $(CC) -c $(CFLAGS) $*.c
+
+zipfile_.o: zipfile.c zip.h theos/osdep.h ziperr.h tailor.h
+ $(CC) -c $(UTILFLAGS)$@ zipfile.c
+
+fileio_.o: fileio.c zip.h theos/osdep.h ziperr.h tailor.h
+ $(CC) -c $(UTILFLAGS)$@ fileio.c
+
+theos_.o: zip.h theos/osdep.h ziperr.h tailor.h theos/theos.c
+ $(CC) -c $(UTILFLAGS)$@ theos/theos.c
+
+util_.o: util.c zip.h theos/osdep.h ziperr.h tailor.h
+ $(CC) -c $(UTILFLAGS)$@ util.c
+
+crypt_.o: zip.h theos/osdep.h ziperr.h tailor.h crypt.c
+ $(CC) -c $(UTILFLAGS)$@ crypt.c
+
+zip.command: $(OBJZ) $(OBJI)
+ $(LD) $@ $(OBJZ) $(OBJI) $(LDFLAGS)
+
+zipcloak.command: $(OBJC)
+ $(LD) $@ $(OBJC) $(LDFLAGS)
+
+zipnote.command: $(OBJN)
+ $(LD) $@ $(OBJN) $(LDFLAGS)
+
+zipsplit.command: $(OBJS)
+ $(LD) $@ $(OBJS) $(LDFLAGS)
+
+install: $(ZIPS)
+ copy *.command /system.cmd32.=(rep noq not
+
+clean:
+ erase *.o(noq not
+ erase *.command(noq not
diff --git a/theos/README b/theos/README
new file mode 100644
index 0000000..1ec99d3
--- /dev/null
+++ b/theos/README
@@ -0,0 +1,34 @@
+This Theos port supports all the unusual features of Theos filesystem.
+
+Under Theos filesystem files are typed. Types include :
+- stream
+- relative
+- keyed
+- indexed (ISAM)
+- program (86 real mode, 16 bits protected mode, 32 bits protected mode)
+- directory
+- library (contains files of any other types librry and directory excepted).
+
+Most of the information on the type and on the structure of a file are not
+contained in the file itself but its in directory entry. For all types of
+files, directory and stream files excepted, this information is vital. If it
+is lost, the file can no longer be usable.
+
+In zip files the information is stored in an extra block with type "Th".
+
+A few years ago I ported ZIP for internal use and spreaded it a little around
+me. It was using a non portable extra block structure. Its type was "TH".
+For backward compatibility it is supported by UNZIP 5.4.0 port to Theos.
+ZIP archives created with ZIP 2.3 port MUST be unzipped with 5.4.0 or a later
+version.
+
+Also disk search sequence is supported. The disk name is not stored into
+the zip archive.
+
+Thanks to Bob Baker from Stockboy Services who spent his time to check this
+port under other conditions than mines.
+
+Jean-Michel Dubois
+IBC France / THEOS France
+jmdubois@ibcfrance.fr
+jean-michel-dubois@wanadoo.fr
diff --git a/theos/_chmod.c b/theos/_chmod.c
new file mode 100644
index 0000000..0937b45
--- /dev/null
+++ b/theos/_chmod.c
@@ -0,0 +1,21 @@
+/*
+ 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
+*/
+/* Change UNIX modes */
+
+#pragma library
+
+#include <sc.h>
+
+int _chmod(const char *fname, short mask)
+{
+ extern char _um2tm_(short);
+
+ return _filechange(fname,'p',(size_t) _um2tm_(mask)|0x80);
+}
+
diff --git a/theos/_fprintf.c b/theos/_fprintf.c
new file mode 100644
index 0000000..5c8c927
--- /dev/null
+++ b/theos/_fprintf.c
@@ -0,0 +1,26 @@
+/*
+ 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
+*/
+#include <stdio.h>
+#include <stdarg.h>
+
+/* for Info and similar macroes. fprintf is already a macro and fprintf x
+ * fools the preprocessor
+ */
+
+int _fprintf(FILE* fp, const char* fmt, ...)
+{
+ va_list ap;
+ long n;
+
+ va_start(ap, fmt);
+ n = vfprintf(fp, fmt, (long*) ap);
+ va_end(ap);
+ return n;
+}
+
diff --git a/theos/_isatty.c b/theos/_isatty.c
new file mode 100644
index 0000000..26f177b
--- /dev/null
+++ b/theos/_isatty.c
@@ -0,0 +1,26 @@
+/*
+ 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
+*/
+/* replace standard library function who needs a FILE* */
+
+#pragma library
+
+#include <stdio.h>
+#include <fcntl.h>
+#include <sc.h>
+#include <lub.h>
+
+short _isatty(int fd)
+{
+ register short lub;
+
+ lub = (int) _fcntl(&stdin[fd], 5, (size_t) 0);
+ return (lub >= CONIN && lub <= CONOUT)
+ || (lub >= COM1 && lub <= COM4)
+ || (lub >= COM5 && lub <= COM16);
+}
diff --git a/theos/_rename.c b/theos/_rename.c
new file mode 100644
index 0000000..04eb204
--- /dev/null
+++ b/theos/_rename.c
@@ -0,0 +1,83 @@
+/*
+ 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
+*/
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+
+#define EXDEV 590
+
+#define _sys_rename() _sc_140()
+extern unsigned short _sys_rename(const char _far *oldfn, char *newfn);
+
+/* rename a file. Report an error on cross disk renames */
+
+static void _n_(const char* fn, char* bfn)
+{
+ if (*fn != '.' && *fn != '/')
+ strcpy(bfn, "./");
+ else
+ *bfn = '\0';
+ strcat(bfn, fn);
+}
+
+int _rename(const char* old, const char* new)
+{
+ char* p;
+ char* q;
+ char* r;
+ char olddrv, newdrv;
+ char dir[FILENAME_MAX];
+ short status;
+ char bold[FILENAME_MAX], bnew[FILENAME_MAX];
+
+ p = strrchr(old, ':');
+ q = strrchr(new, ':');
+
+ /* if at least one path includes a disk name, check for equality */
+ if (p != NULL || q != NULL) {
+ /* getcwd return a NULL pointer for /:S */
+ getcwd(dir, FILENAME_MAX);
+ r = strrchr(dir, ':');
+
+ if (p == NULL)
+ p = r;
+ olddrv = p ? p[1] : 'S';
+
+ if (q == NULL)
+ q = r;
+ newdrv = q ? q[1] : 'S';
+
+ /* return an error if uppercased disk names are not the same */
+ if ((old & ~0x20) != (new & ~0x20)) {
+ _errarg = NULL;
+ return errno = _errnum = EXDEV;
+ }
+ }
+ /* prepend ./ if there is no path to force rename to work on files
+ * in the current directory instead of default library
+ */
+ _n_(old, bold);
+ _n_(new, bnew);
+
+ status = _sys_rename(bold, bnew);
+ /* can be :
+ * 0 no error
+ * 19 "old" file not found
+ * 44 "new" file already exist
+ * 45 "new" filename missing
+ * 46 "old" file name missing
+ */
+ if (status) {
+ errno = _errnum = status;
+ _errarg = (status == 44 || status == 45) ? new : old;
+ }
+
+ return status;
+}
diff --git a/theos/_setargv.c b/theos/_setargv.c
new file mode 100644
index 0000000..d76f955
--- /dev/null
+++ b/theos/_setargv.c
@@ -0,0 +1,140 @@
+/*
+ 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
+*/
+/*
+ * __setargv.c - command argument expander
+ *
+ * Author : Jean-Michel Dubois
+ * Date : 09/26/92
+ *
+ * Function: Expands the command line arguments by replacing any filename
+ * including wilcards by the sorted list of matching files name.
+ * Strings beginning by a dash are considered as options and left
+ * unchanged.
+ *
+ * Syntax : void _setargv(int *argc, char ***argv);
+ *
+ * Returns : new argc. Caller's argc and argv are updated.
+ * If a insufficient memory condition occurs, return 0 and errno
+ * is set to ENOMEM.
+ *
+ * Example :
+ * main(int argc, char **argv)
+ * {
+ * if (_setargv(&argc, &argv)) {
+ * ...
+ */
+#pragma library
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <malloc.h>
+#include <errno.h>
+#include <scr.h>
+#include <peek.h>
+
+/* Allocate argv array in 16 entries chunks */
+
+static int allocarg(int n, int l, char ***nargv, char *s)
+{
+ if ((n+1) > l) { /* If array full */
+ l += 16; /* increase size and reallocate */
+ if (!(*nargv = (char **) realloc(*nargv,l * sizeof (void *)))) {
+ errno = _errnum = ENOMEM; /* Not enough memory */
+ return 0;
+ }
+ }
+ (*nargv)[n] = strdup(s); /* Save argument */
+ return l; /* Return new maxsize */
+}
+
+/* Comparison function for qsort */
+
+static int sortcmp(char **p, char **q)
+{
+ return stricmp(*p,*q);
+}
+
+/* Main body of the function */
+
+int _setargv(int *argc, char ***argv)
+{
+ register int nargc; /* New arguments counter */
+ char **nargv; /* New arguments pointers */
+ register int i, l, base;
+ char *p, *q, *r;
+ char path[FILENAME_MAX];
+
+ _errnum = 0;
+ nargc = 0; /* Initialise counter, size counter */
+ l = *argc; /* and new argument vector to the */
+ /* current argv array size */
+
+ if ((nargv = (char **) calloc((size_t) *argc, sizeof (void *))) != NULL) {
+ /* For each initial argument */
+ for (i = 0; i < *argc; i++) {
+ q = (*argv)[i];
+ if (q[0] == '-' || ! testwild(q)) {
+ /* if it begins with a dash or doesnt include
+ * wildcard simply add it to the new array
+ */
+ if (! (l = allocarg(nargc, l, &nargv, q)))
+ return 0; /* Not enough memory */
+ nargc++;
+ } else {
+ /* else keep current counter for qsort */
+ base = nargc;
+ /* open directory with argument */
+ diropen(q);
+ while ((r = dirread()) != NULL) {
+ /* reduce path to given one */
+ if ((p = strrchr(q, '/')) != NULL) {
+ strncpy(path, q, p-q+1);
+ path[p-q+1] = '\0';
+ } else
+ path[0] = '\0';
+
+ if ((p = strrchr(r, '/')) != NULL)
+ strcat(path, p+1);
+ else
+ strcat(path, r);
+
+ if (peekscr(&SCR->searchseq[1]) == 255
+ && strchr(q, ':') == NULL) {
+ *strchr(path, ':') = '\0';
+ }
+ /* and add each matching filename. */
+ if (! (l = allocarg(nargc,l,&nargv,path)))
+ return 0;/* Not enough memory */
+ nargc++;
+ }
+ if (nargc == base) {
+ /* if no match found include wild card name */
+ if (! (l = allocarg(nargc, l, &nargv, q)))
+ return 0; /* Not enough memory */
+ nargc++;
+ } else if ((nargc - base) > 1)
+ /* If more than one file name matchs */
+ /* sort arguments. */
+ qsort(&(nargv[base]),(size_t)nargc-base,
+ sizeof(void *),sortcmp);
+ dirclose();
+ }
+ }
+ /* Update caller's parameters */
+ *argc = nargc;
+ *argv = nargv;
+ /* and sign on success */
+ return nargc;
+ }
+
+ /* If it is not possible to allocate initial array, sign on error */
+ _errnum = ENOMEM;
+ return 0;
+}
diff --git a/theos/_stat.c b/theos/_stat.c
new file mode 100644
index 0000000..6855d28
--- /dev/null
+++ b/theos/_stat.c
@@ -0,0 +1,461 @@
+/*
+ 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
+*/
+#pragma library
+#include <stdio.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <string.h>
+#include <sc.h>
+#include <peek.h>
+#include <lub.h>
+#include <fdb.h>
+#include <fsa.h>
+#include "theos/stat.h"
+
+/* replacement for standard library functions stat and fstat */
+
+int _stat_(struct stat* st, struct fdb* fdb);
+int _dstat_(struct stat* st);
+
+#define peekucb() peeknuc()
+
+/* map THEOS protection code to Unix modes */
+
+unsigned short _tm2um_(char protect)
+{
+ unsigned short umask = 0;
+
+ if (!(protect & _FDB_READ_PROTECT))
+ umask = S_IRUSR|S_IRGRP;
+
+ if (!(protect & _FDB_WRITE_PROTECT))
+ umask |= S_IWUSR|S_IWGRP;
+
+ if (!(protect & _FDB_EXECUTE_PROTECT))
+ umask |= S_IXUSR|S_IXGRP;
+
+ if (!(protect & _FDB_ERASE_PROTECT))
+ umask |= S_IEUSR|S_IEGRP;
+
+ if (!(protect & _FDB_SHARED_READ_PROTECT)) {
+ if (_osmajor > 3)
+ umask |= S_IROTH|S_IXOTH;
+ else
+ umask |= S_IROTH;
+ }
+
+ if (!(protect & _FDB_SHARED_WRITE_PROTECT))
+ umask |= S_IWOTH;
+
+ if (!(protect & _FDB_MODIFIED)) {
+ if (_osmajor > 3)
+ umask |= S_IMODF;
+ else
+ umask |= S_IXOTH;
+ }
+
+ if (protect & _FDB_NOT_HIDDEN)
+ umask |= S_INHID;
+
+ return umask;
+}
+
+/* map Unix modes to THEOS protections */
+
+char _um2tm_(unsigned short mask)
+{
+ char protect = 0;
+
+ if (!(mask & (S_IRUSR|S_IRGRP)))
+ protect |= _FDB_READ_PROTECT;
+
+ if (!(mask & (S_IWUSR|S_IWGRP)))
+ protect |= _FDB_WRITE_PROTECT;
+
+ if (!(mask & (S_IXUSR|S_IXGRP)))
+ protect |= _FDB_EXECUTE_PROTECT;
+
+ if (!(mask & (S_IEUSR|S_IEGRP)))
+ protect |= _FDB_ERASE_PROTECT;
+
+ if (_osmajor < 4) {
+ if (!(mask & S_IROTH))
+ protect |= _FDB_SHARED_READ_PROTECT;
+ } else {
+ if (!(mask & (S_IROTH|S_IXOTH)))
+ protect |= _FDB_SHARED_READ_PROTECT;
+ }
+
+ if (!(mask & S_IWOTH))
+ protect |= _FDB_SHARED_WRITE_PROTECT;
+
+ if (mask & S_IMODF && _osmajor > 3)
+ protect |= _FDB_MODIFIED;
+
+ if (mask & S_INHID && _osmajor > 3)
+ protect |= _FDB_NOT_HIDDEN;
+
+ return protect;
+}
+
+/* root directory stat */
+
+static int rdirstat(const char* fn, struct stat *st)
+{
+ register char* p = strchr(fn, ':');
+ char drive;
+
+ drive = p ? p[1] : 'S';
+
+ if (drive >= 'a' && drive <= 'Z')
+ drive -= 0x40;
+
+ memset(st, 0, sizeof(struct stat));
+
+ if (getlub(drive - 'A') != 255) {
+ st->st_org = _FDB_STAT_DIRECTORY;
+ st->st_mode = S_IFDIR|S_IRUSR|S_IWUSR|S_IROTH|S_IWOTH;
+ st->st_nlink = 1;
+ st->st_dev = st->st_rdev = drive - 'A';
+ st->st_uid = st->st_gid = getuid();
+ st->st_protect = _FDB_ERASE_PROTECT;
+ return 0;
+ }
+ errno = _errnum = ENOENT;
+ _errarg = fn;
+ return -1;
+}
+
+#ifdef LOCATE_BUG
+
+/* locate fails when stating a file in root dir from a directory with a
+ * relative path. Workaround by setting directory to root dir
+ * getting the file directory block, then restoring the current directory.
+ */
+
+struct fdb* __locate(const char* fn, char* buf, short* drv)
+{
+ struct fdb* fdb;
+ char buf2[FILENAME_MAX];
+ char cwd[FILENAME_MAX];
+ char drive[3];
+ char* p;
+ char* q;
+
+ /* return if file found */
+ if (fdb = _locate(fn, buf, drv))
+ return fdb;
+
+ /* if file name does not contain a path delimiter it really does not exist.
+ */
+ strcpy(buf2, fn);
+
+ if ((p = strrchr(buf2, '/')) == NULL)
+ return NULL;
+
+ /* get drive name from file path */
+ q = strrchr(buf2, ':');
+
+ /* cat drive name if any to directory path */
+ if (q) {
+ strncpy(drive, q, 2);
+ drive[2] = '\0';
+ strcpy(p, q);
+ } else
+ *p = '\0';
+ /* save current directory */
+ getcwd(cwd, FILENAME_MAX);
+ /* chdir to directory path */
+ chdir(buf2);
+ /* get File Directory Block */
+ p = strrchr(fn, '/');
+ fdb = _locate(p + 1, buf, drv);
+ /* restore current directory */
+ chdir(cwd);
+ return fdb;
+}
+
+#undef _locate
+#define _locate() __locate()
+
+/* same cause, same consequence for fopen and open.
+*/
+
+FILE* _fopen(const char* fn, const char* mode)
+{
+ FILE* fp;
+ char buf[FILENAME_MAX];
+ short drv;
+
+ /* prepend a path to current dir to avoid use of default library */
+ if (*fn != '.' && *fn != '/') {
+ strcpy(buf, "./");
+ strcat(buf, fn);
+ return fopen(buf, mode);
+ }
+
+ if (fp = fopen(fn, mode))
+ return fp;
+
+ /* see comment for _locate */
+ if (_locate(fn, buf, &drv)) {
+ fn = strrchr(fn, '/');
+ return fopen(fn, mode);
+ }
+ return NULL;
+}
+
+#undef open
+int open(const char*, int, ...);
+
+int __open(const char* fn, int mode)
+{
+ int fd;
+ char buf[FILENAME_MAX];
+ short drv;
+
+ /* prepend a path to current dir to avoid use of default library */
+ if (*fn != '.' && *fn != '/') {
+ strcpy(buf, "./");
+ strcat(buf, fn);
+ return open(buf, mode);
+ }
+
+ if ((fd = open(fn, mode)) != EOF)
+ return fd;
+
+ /* see comment for _locate */
+ if (_locate(fn, buf, &drv)) {
+ fn = strrchr(fn, '/');
+ if (fn)
+ return open(fn, mode);
+ }
+ return EOF;
+}
+#endif
+
+/* replacement for standard file stat */
+
+int _stat(const char *_fn, struct stat *st)
+{
+ char buf[FILENAME_MAX], buf2[FILENAME_MAX], buf3[FILENAME_MAX];
+ register struct fdb* fdb;
+ register char* p;
+ register char* fn;
+
+ fn = strcpy(buf3, _fn);
+
+ if (p = strrchr(fn, ':'))
+ *p = 0;
+
+ /* on current drive ./:d and .:m point to current dir
+ * on another drive to root directory, workaround to avoid it */
+
+ if (! strcmp(fn, "/") || ! strcmp(fn, ".") || ! strcmp(fn, "./")) {
+ if (p == NULL) {
+ /* current dir on current drive */
+ fn = getcwd(buf2, FILENAME_MAX);
+ /* getcwd returns NULL on root dir on drive S */
+ if (fn == NULL)
+ fn = strcpy(buf2, "/:S");
+ /* getcwd returns /:d on root dir on any other drive */
+ if (fn[1] == ':')
+ return rdirstat(fn, st);
+ } else {
+ *p = ':';
+ return rdirstat(fn, st);
+ }
+ if (p)
+ *p = ':';
+ } else {
+ if (p)
+ *p = ':';
+ if (*fn != '.' && *fn != '/') {
+ strcpy(buf2, "./");
+ fn = strcat(buf2, fn);
+ }
+ }
+
+ if (buf2 != fn)
+ strcpy(buf2, fn);
+ /* remove trailing slash before optional disk name */
+ if (p = strrchr(buf2, '/')) {
+ if (p[1] == ':') {
+ *p = p[1];
+ p[1] = p[2];
+ p[2] = p[3];
+ } else if (p[1] == '\0')
+ *p = '\0';
+ }
+ /* if fn is a file get file directory block structure and device */
+ if (fdb = _locate(buf2, buf, &st->st_dev)) {
+ /* is it a file from another user... */
+ if (strchr(buf2, '\\')
+ /* a public system file... */
+ || fdb->fileowner == 0
+ /* or a file from the current user account ? */
+ || fdb->fileowner == getuid())
+ /* yes, return stat */
+ return _stat_(st, fdb);
+ else {
+ /* no, say file doesn't exist */
+ errno = _errnum = ENOENT;
+ _errarg = fn;
+ return -1;
+ }
+ }
+ /* else should be a device, get device number from device name */
+ st->st_rdev = st->st_dev = _lub_name(*fn == ':' ? fn+1 : fn);
+ /* if it is really a device return device status */
+ if (st->st_dev != -1 && getlub(st->st_dev) != 255)
+ return _dstat_(st);
+ /* neither an existing file or a device name, return EOF */
+ st->st_rdev = st->st_dev = 0;
+ errno = _errnum = ENOENT;
+ _errarg = fn;
+ return -1;
+}
+
+/* replacement for fstat */
+
+int _fstat(int fd, struct stat *st)
+{
+ unsigned short fsanum;
+ struct fsa fsa;
+ register FILE *fp;
+ int status;
+ register int i;
+ register char *p;
+
+ if (fd < FOPEN_MAX) {
+ fp = &stdin[fd];
+ /* get File Save Area number */
+ if (_fcntl(fp,1,0) & 0x80) {
+ fsanum = (unsigned short) _fcntl(fp,83,0);
+ st->st_dev = (unsigned short) _fcntl(fp,5,0);
+
+ if (st->st_dev >= A_DISK && st->st_dev <= Z_DISK) {
+ /* if opened file is a disk file */
+ /* copy far fsa in protected segment to local fsa */
+ for (i = 0, fsanum *= sizeof(fsa), p = (char *) &fsa;
+ i < (sizeof(fsa));
+ i++, fsanum++, p++)
+ *p = _peekfsa((char *) fsanum);
+ /* build stat structure from fsa */
+ status = _stat_(st, (struct fdb*) &fsa);
+ /* get blocksize */
+ if ((st->st_blksize = _fcntl(fp,817,0)) == 0)
+ st->st_blksize = BUFSIZ;
+ return status;
+ }
+ /* return device status */
+ return _dstat_(st);
+ }
+ }
+ errno = _errnum = EBADF;
+ return -1;
+}
+
+static int _isprt(int dev)
+{
+ return IS_PRT_LUB(dev);
+}
+
+/* device stat */
+
+int _dstat_(st)
+register struct stat* st;
+{
+ register struct ucb* ucb;
+
+ ucb = getucb(st->st_dev);
+ st->st_ino = 0;
+ if (st->st_dev <= Z_DISK
+ || (st->st_dev >= TAPE1 && st->st_dev <= TAPE4)) {
+ st->st_mode = S_IFBLK | S_IWUSR | S_IRUSR;
+ if (peekucb(&ucb->devowner) == 255)
+ st->st_mode |= S_IWGRP | S_IWOTH | S_IRGRP | S_IROTH;
+ } else {
+ st->st_mode = S_IFCHR | S_IWUSR;
+ if (_isprt(st->st_dev))
+ st->st_mode |= S_IRUSR;
+ if (peekucb(&ucb->devowner) == 255) {
+ st->st_mode |= S_IWGRP | S_IWOTH;
+ if (_isprt(st->st_dev))
+ st->st_mode |= S_IRGRP | S_IROTH;
+ }
+ }
+ st->st_nlink = 1;
+ st->st_uid = st->st_gid = getuid();
+ st->st_size = 0;
+ st->st_atime = st->st_mtime = st->st_ctime = 0;
+ st->st_rlen = 0;
+ st->st_klen = 0;
+ st->st_grow = 0;
+ st->st_blksize = 0;
+ return 0;
+}
+
+/* regular file stat */
+
+int _stat_(st, fdb)
+register struct stat* st;
+register struct fdb* fdb;
+{
+ st->st_rdev = st->st_dev;
+ st->st_ino = 0;
+ st->st_org = fdb->filestat;
+
+ /* map fdb file status to stat mode */
+ switch (fdb->filestat) {
+ case _FDB_STAT_LIBRARY: st->st_mode = S_IFLIB; break;
+ case _FDB_STAT_DIRECTORY: st->st_mode = S_IFDIR; break;
+ case _FDB_STAT_STREAM: st->st_mode = S_IFREG; break;
+ case _FDB_STAT_RELATIVE: st->st_mode = S_IFREL; break;
+ case _FDB_STAT_KEYED: st->st_mode = S_IFKEY; break;
+ case _FDB_STAT_INDEXED: st->st_mode = S_IFIND; break;
+ case _FDB_STAT_RANDOM: st->st_mode = S_IFRND; break;
+ case _FDB_STAT_PROGRAM: st->st_mode = S_IFR16; break;
+ case _FDB_STAT_16_BIT_PROGRAM: st->st_mode = S_IFP16; break;
+ case _FDB_STAT_32_BIT_PROGRAM: st->st_mode = S_IFP32; break;
+ }
+
+ /* map theos file protection codes to stat mode */
+ st->st_mode |= _tm2um_(st->st_protect = fdb->protect);
+ st->st_nlink = 1;
+ st->st_uid = st->st_gid = fdb->fileowner;
+ st->st_size = fdb->filesize;
+ st->st_atime = st->st_mtime = st->st_ctime = getfiledate(fdb);
+ st->st_blksize = 0;
+ /* specific theos information */
+ st->st_rlen = fdb->reclen;
+ st->st_klen = fdb->keylen;
+ st->st_grow = fdb->filegrow;
+ return 0;
+}
+
+#include <direct.h>
+
+/* standard diropen fails on path endung with a '/', workaround */
+
+struct dirent* _opendir(const char* dirpath)
+{
+ int l;
+ char dirp[FILENAME_MAX];
+ struct dirent* dir;
+
+ if (dirpath && (l = strlen(dirpath))) {
+ if (dirpath[l - 1] == '/') {
+ strcpy(dirp, dirpath);
+ dirp[l - 1] = '\0';
+ return opendir(dirp);
+ }
+ }
+ return opendir(dirpath);
+}
diff --git a/theos/charconv.h b/theos/charconv.h
new file mode 100644
index 0000000..a2d8dfa
--- /dev/null
+++ b/theos/charconv.h
@@ -0,0 +1,93 @@
+/*
+ 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
+*/
+
+#ifdef IZ_THS2ISO_ARRAY
+ZCONST uch Far ths2iso[] = {
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, /* 80 - 87 */
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, /* 88 - 8F */
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, /* 90 - 97 */
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, /* 98 - 9F */
+ 0x2B, 0x2B, 0x2B, 0x2B, 0x2B, 0x2B, 0x2B, 0x2B, /* A0 - A7 */
+ 0x2B, 0x2D, 0x7C, 0x2B, 0x2B, 0x2B, 0x2B, 0x23, /* A8 - AF */
+ 0x23, 0x23, 0x23, 0x23, 0x23, 0x23, 0x23, 0x23, /* B0 - B7 */
+ 0x3D, 0x23, 0xBA, 0xBB, 0xBC, 0xBD, 0xBE, 0xBF, /* B8 - BF */
+ 0xC4, 0xE4, 0xE2, 0xE0, 0xE1, 0xC9, 0xEB, 0xEA, /* C0 - C7 */
+ 0xE8, 0xE9, 0xEF, 0xEE, 0xEC, 0xED, 0xD6, 0xF6, /* C8 - CF */
+ 0xF4, 0xF2, 0xF3, 0xDC, 0xFC, 0xFB, 0xF9, 0xFA, /* D0 - D7 */
+ 0xC7, 0xE7, 0xD1, 0xF1, 0xC6, 0xE6, 0xC5, 0xE5, /* D8 - DF */
+ 0xDF, 0xBF, 0xA1, 0xA2, 0xA3, 0xA5, 0xB5, 0xA4, /* E0 - E7 */
+ 0xBC, 0xBD, 0xFF, 0xA7, 0xB0, 0xB2, 0x20, 0x20, /* E8 - EF */
+ 0x20, 0xB1, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, /* F0 - F7 */
+ 0x20, 0x20, 0xB7, 0x20, 0x20, 0x20, 0x20, 0x20 /* F8 - FF */
+};
+#endif /* IZ_THS2ISO_ARRAY */
+
+#ifdef IZ_THS2OEM_ARRAY
+ZCONST uch Far ths2oem[] = {
+ 254,254,254,254, 254,254,134,135, /* 80 - 87 */
+ 136,137,138,139, 140,141,142,143, /* 88 - 8F */
+ 144,145,146,147, 148,149,150,151, /* 90 - 97 */
+ 152,153,154,155, 156,157,158,159, /* 98 - 9F */
+ 218,191,217,192, 197,195,180,194, /* A0 - A7 */
+ 193,196,179,218, 191,217,192,201, /* A8 - AF */
+ 183,188,200,206, 199,182,203,202, /* B0 - B7 */
+ 205,186,186,187, 188,189,190,191, /* B8 - BF */
+ 142,132,131,133, 160,144,137,136, /* C0 - C7 */
+ 138,130,139,140, 141,161,153,148, /* C8 - CF */
+ 147,149,162,154, 129,150,151,163, /* D0 - D7 */
+ 128,135,165,164, 146,145,143,134, /* D8 - DF */
+ 225,168,173,155, 156,157,158, 31, /* E0 - E7 */
+ 172,171,152, 21, 248,253,238,239, /* E8 - EF */
+ 240,241,242,243, 244,245,246,247, /* F0 - F7 */
+ 248,249,250,251, 252,253,254,255 /* F8 - FF */
+};
+#endif /* IZ_THS2OEM_ARRAY */
+
+#ifdef IZ_ISO2THS_ARRAY
+ZCONST uch Far iso2ths[] = {
+ 0x3F, 0x3F, 0x27, 0x3F, 0x22, 0x2E, 0xA4, 0xB3, /* 80 - 87 */
+ 0x5E, 0x25, 0x53, 0x3C, 0x4F, 0x3F, 0x3F, 0x3F, /* 88 - 8F */
+ 0x3F, 0x27, 0x27, 0x22, 0x22, 0x07, 0x2D, 0x2D, /* 90 - 97 */
+ 0x7E, 0x54, 0x73, 0x3E, 0x6F, 0x3F, 0x3F, 0x59, /* 98 - 9F */
+ 0x20, 0xE2, 0xE3, 0xE4, 0xE7, 0xE5, 0x7C, 0xEB, /* A0 - A7 */
+ 0x20, 0x20, 0x20, 0x22, 0x20, 0x2D, 0x20, 0x2D, /* A8 - AF */
+ 0xEC, 0xF1, 0xED, 0x20, 0x20, 0xE6, 0x20, 0xFA, /* B0 - B7 */
+ 0x20, 0x20, 0x20, 0x22, 0xE8, 0xE9, 0x20, 0xE1, /* B8 - BF */
+ 0xC3, 0xC4, 0xC2, 0x41, 0xC0, 0xDE, 0xDC, 0xD8, /* C0 - C7 */
+ 0xC8, 0xC5, 0xC7, 0xC6, 0xCC, 0xCD, 0xCB, 0xCA, /* C8 - CF */
+ 0x44, 0xDA, 0xD1, 0xD2, 0xD0, 0x4F, 0xCE, 0x78, /* D0 - D7 */
+ 0x4F, 0xD6, 0xD7, 0xD5, 0xD3, 0x59, 0x20, 0xE0, /* D8 - DF */
+ 0xC3, 0xC4, 0xC2, 0x61, 0xC1, 0xDF, 0xDD, 0xD9, /* E0 - E7 */
+ 0xC8, 0xC9, 0xC7, 0xC6, 0xCC, 0xCD, 0xCB, 0xCA, /* E8 - EF */
+ 0x64, 0xDB, 0xD1, 0xD2, 0xD0, 0x4F, 0xCF, 0xF1, /* F0 - F7 */
+ 0x6F, 0xD6, 0xD7, 0xD5, 0xD4, 0x79, 0x20, 0xEA /* F8 - FF */
+};
+#endif /* IZ_ISO2THS_ARRAY */
+
+#ifdef IZ_OEM2THS_ARRAY
+ZCONST uch Far oem2ths[] = {
+ 216,212,201,194, 193,195,223,217, /* 80 - 87 */
+ 199,198,200,202, 203,204,192,222, /* 88 - 8F */
+ 197,221,220,208, 207,209,213,214, /* 90 - 97 */
+ 234,206,211,227, 228,229,230,159, /* 98 - 9F */
+ 196,205,210,215, 219,218,254,254, /* A0 - A7 */
+ 225,254,254,233, 232,226, 34, 34, /* A8 - AF */
+ 254,254,254,170, 166,166,181,176, /* B0 - B7 */
+ 161,181,185,176, 177,177,162,161, /* B8 - BF */
+ 163,168,167,165, 169,164,165,180, /* C0 - C7 */
+ 178,175,183,182, 180,184,179,168, /* C8 - CF */
+ 183,167,182,178, 163,160,175,179, /* D0 - D7 */
+ 164,162,160,254, 254,254,254,254, /* D8 - DF */
+ 254,224,254,254, 254,254,254, 31, /* E0 - E7 */
+ 254,254,254, 21, 254,254,238,239, /* E8 - EF */
+ 240,241,242,243, 244,245,246,247, /* F0 - F7 */
+ 236,249,250,251, 252,237,254,255 /* F8 - FF */
+};
+#endif /* IZ_OEM2THS_ARRAY */
+
diff --git a/theos/osdep.h b/theos/osdep.h
new file mode 100644
index 0000000..4f4857e
--- /dev/null
+++ b/theos/osdep.h
@@ -0,0 +1,58 @@
+/*
+ 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
+*/
+/*
+ * XXX this should somehow depend on the stuff in revision.h
+ */
+#pragma prog 2.3,0,0,0
+
+/* use argument expansion */
+#if !defined(UTIL) && !defined(MAINWA_BUG)
+# pragma wild argv
+#endif
+
+#include <stdio.h>
+#include <malloc.h>
+#include <handle.h>
+#include <conio.h>>
+#include <locale.h>
+#include <sys/types.h>
+#include "theos/stat.h" /* use JMD's extended stat function */
+
+#define isatty() _isatty() /* THEOS isatty uses a FILE* instead of a fd */
+int _isatty(int fd);
+
+#define deletedir(d) rmdir(d)
+
+/* will come later */
+#if 0
+#define USE_EF_UT_TIME /* Enable use of "UT" extra field time info */
+#endif
+
+#if DEBUG
+int _fprintf(FILE* fp, const char* fmt, ...);
+#endif
+
+/* for rename() replacement. Standard function is bugged */
+
+int _rename(const char* old, const char* new);
+#define rename(a,b) _rename(a,b)
+
+#ifdef LOCATE_BUG
+/* for fopen replacement. Standard function fails on relative path pointing
+ * to root directory.
+ */
+#undef _fopen
+#undef open
+#define fopen() _fopen()
+FILE* _fopen(const char*, const char*);
+#define open() __open()
+FILE* __open(const char*, int);
+#endif
+
+#define EXDEV 10000
diff --git a/theos/stat.h b/theos/stat.h
new file mode 100644
index 0000000..3a716f8
--- /dev/null
+++ b/theos/stat.h
@@ -0,0 +1,106 @@
+#ifndef __theos_stat_h
+#define __theos_stat_h
+/*
+ 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
+*/
+
+/* extended stat structure for stat, fstat, chmod */
+/* Written by Jean-Michel Dubois */
+
+#pragma field word
+struct stat {
+ unsigned short st_mode; /* file attributes */
+ #define S_IFMT 0xf000 /* file type mask */
+ #define S_IFIFO 0x1000 /* pipe */
+ #define S_IFCHR 0x2000 /* char device */
+ #define S_IFSOCK 0x3000 /* socket */
+ #define S_IFDIR 0x4000 /* directory */
+ #define S_IFLIB 0x5000 /* library */
+ #define S_IFBLK 0x6000 /* block device */
+ #define S_IFREG 0x8000 /* regular file */
+ #define S_IFREL 0x9000 /* relative (direct) */
+ #define S_IFKEY 0xA000 /* keyed */
+ #define S_IFIND 0xB000 /* indexed */
+ #define S_IFRND 0xC000 /* ???? */
+ #define S_IFR16 0xD000 /* 16 bit real mode program */
+ #define S_IFP16 0xE000 /* 16 bit protected mode prog */
+ #define S_IFP32 0xF000 /* 32 bit protected mode prog */
+
+ #define S_ISUID 0x0800 /* meaningless */
+ #define S_ISGID 0x0400 /* meaningless */
+ #define S_ISVTX 0x0200 /* meaningless */
+
+ #define S_IMODF 0x0800 /* modified */
+ #define S_INHID 0x0400 /* not hidden */
+
+ #define S_IRWXU 0x03c0 /* read,write,execute: owner */
+ #define S_IEUSR 0x0200 /* erase permission: owner */
+ #define S_IRUSR 0x0100 /* read permission: owner */
+ #define S_IWUSR 0x0080 /* write permission: owner */
+ #define S_IXUSR 0x0040 /* execute permission: owner */
+ /* group permissions */
+ #define S_IRWXG 0x0238
+ #define S_IEGRP 0x0200
+ #define S_IRGRP 0x0020
+ #define S_IWGRP 0x0010
+ #define S_IXGRP 0x0008
+ /* other never has erase permission */
+ #define S_IRWXO 0x0207 /* read,write,execute: other */
+ #define S_IROTH 0x0004 /* read permission: other */
+ #define S_IWOTH 0x0002 /* write permission: other */
+ #define S_IXOTH 0x0001 /* execute permission: other */
+
+ #define S_IREAD 0x0100 /* read permission, owner */
+ #define S_IEXEC 0x0040 /* execute permission, owner */
+ #define S_IWRITE 0x0080 /* write permission, owner */
+ short st_ino; /* not used */
+ short st_dev; /* not used */
+ short st_rdev; /* not used */
+ short st_nlink; /* not used */
+ short st_uid; /* owner id */
+ short st_gid; /* not used */
+ unsigned long st_size; /* size of file */
+ unsigned long st_atime; /* not used */
+ unsigned long st_mtime; /* date & time last modified */
+ unsigned long st_ctime; /* not used */
+ unsigned long st_blksize; /* buffer size */
+ unsigned short st_org; /* organization */
+ unsigned short st_rlen; /* record size */
+ unsigned short st_klen; /* key size */
+ char st_grow; /* growing factor */
+ char st_protect; /* native protections */
+};
+#pragma field
+
+#define S_ISREG(m) (((m) & S_IFMT) >= S_IFREG)
+#define S_ISLIB(m) (((m) & S_IFMT) == S_IFLIB)
+#define S_ISDIR(m) (((m) & S_IFMT) == S_IFDIR)
+#define S_ISCHR(m) (((m) & S_IFMT) == S_IFCHR)
+#define S_ISBLK(m) (((m) & S_IFMT) == S_IFBLK)
+
+#define S_ISSEQ(m) (((m) & S_IFMT) == S_IFREG)
+#define S_ISREL(m) (((m) & S_IFMT) == S_IFREL)
+#define S_ISKEY(m) (((m) & S_IFMT) == S_IFKEY)
+#define S_ISIND(m) (((m) & S_IFMT) == S_IFIND)
+#define S_ISPRG(m) (((m) & S_IFMT) >= S_IFP16)
+#define S_ISLNK(m) 0
+
+/* avoid conflict with original THEOS functions */
+
+#define stat(a,b) _stat(a,b)
+#define fstat(a,b) _fstat(a,b)
+#define chmod(a,b) _chmod(a,b)
+
+extern int _stat(const char *file, struct stat *statptr);
+extern int _fstat(int fd, struct stat *statptr);
+extern int _chmod(const char *file, short mask);
+
+#define _chstat(a,b) ((int) _sc_168(a,'p',(size_t)(b)))
+extern unsigned short _sc_168(const char _far *fn, int cmd, size_t value);
+
+#endif /* !__theos_stat_h */
diff --git a/theos/theos.c b/theos/theos.c
new file mode 100644
index 0000000..17db108
--- /dev/null
+++ b/theos/theos.c
@@ -0,0 +1,558 @@
+/*
+ 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
+*/
+/*---------------------------------------------------------------------------
+
+ theos.c (zip)
+
+ Contribution by Jean-Michel Dubois. 20-Jun-1995, 20-Dec-98
+
+ THEOS specific extra informations
+
+ ---------------------------------------------------------------------------*/
+
+
+#include <stdio.h>
+
+#ifndef UTIL
+
+#include "zip.h"
+
+#include <stdlib.h>
+#include <ctype.h>
+#include <time.h>
+#include <sc.h>
+#include <direct.h>
+#include <sys/utime.h>
+
+#define opendir(a) _opendir(a)
+extern struct dirent* _opendir(char* fname);
+
+#define PAD 0
+
+#define RET_ERROR 1
+#define RET_SUCCESS 0
+#define RET_EOF 0
+
+extern char *label;
+local ulg label_time = 0;
+local ulg label_mode = 0;
+local time_t label_utim = 0;
+
+/* match from Phase One Systems */
+
+int match(char *s, char *p) /*S Returns non-zero if string matches
+ the literal mask */
+{
+ int matched, k;
+
+ if (!(*p))
+ return 1;
+ for(;;) {
+ if ( (!(*s)) && (!(*p)) )
+ return(1);
+ else if ( !(*p) )
+ return(0);
+ else if (*p == '*') {
+ if (!*(p+1))
+ return(1);
+ k=0;
+ do {
+ matched = match(s+k,p+1);
+ k++;
+ } while ( (!matched) && *(s+k));
+ return(matched);
+ } else if (*p == '@') {
+ if (!((*s >= 'a' && *s <= 'z')
+ ||(*s >= 'A' && *s <= 'Z')))
+ return(0);
+ } else if (*p == '#') {
+ if (*s < '0' || *s > '9')
+ return(0);
+ } else if (*p != '?') {
+ if (tolower(*s) != tolower(*p))
+ return(0);
+ }
+ s++; p++;
+ }
+}
+
+local char *readd(d)
+DIR *d; /* directory stream to read from */
+/* Return a pointer to the next name in the directory stream d, or NULL if
+ no more entries or an error occurs. */
+{
+ struct dirent *e;
+
+ e = readdir(d);
+ return e == NULL ? (char *) NULL : e->d_name;
+}
+
+/* check if file is a member of a library */
+
+int ismember(char* path)
+{
+ char* p;
+
+ if ((p = strrchr(path, '/')) == NULL)
+ p = path;
+ return ((p = strchr(p, '.')) && (p = strchr(p + 1, '.')));
+}
+
+/* extract library name from a file name */
+
+char* libname(char* path)
+{
+ char* p;
+ static char lib[FILENAME_MAX];
+ char drive[3];
+
+ strcpy(lib, path);
+ if (p = strrchr(lib, ':')) {
+ strncpy(drive, p, 2);
+ drive[2] = '\0';
+ *p = '\0' ;
+ } else
+ drive[0] = '\0';
+
+ if ((p = strrchr(lib, '/')) == NULL)
+ p = lib;
+
+ p = strchr(p, '.');
+ p = strchr(p + 1, '.');
+ *p = 0;
+ strcat(lib, drive);
+ return lib;
+}
+
+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 */
+ DIR *d; /* directory stream from opendir() */
+ char *e; /* pointer to name from readd() */
+ int m; /* matched flag */
+ char *p; /* path for recursion */
+ struct stat s; /* result of stat() */
+ struct zlist *z; /* steps through zfiles list */
+ struct flist *f; /* steps through files list */
+ char* path; /* full name */
+ char drive[3]; /* drive name */
+ int recursion; /* save recurse flag */
+
+ if (strcmp(n, "-") == 0) /* if compressing stdin */
+ return newname(n, 0, caseflag);
+ else if (LSSTAT(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(z->iname, p))
+ {
+ 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((zvoid *)p);
+ return m ? ZE_MISS : ZE_OK;
+ }
+
+ /* Live name--use if file, recurse if directory or library */
+ if (S_ISREG(s.st_mode)) {
+ if ((path = malloc(strlen(n) + 2)) == NULL)
+ return ZE_MEM;
+
+ strcpy(path, n);
+
+ /* if member name, include library name before any member name */
+ if (ismember(path)) {
+ strcpy(path, libname(path));
+ /* mask recursion flag to avoid endless loop recursion
+ * if -r is used with member names
+ */
+ recursion = recurse;
+ recurse = FALSE;
+ if ((m = procname(path, caseflag)) != ZE_OK) /* recurse on name */
+ {
+ if (m == ZE_MISS)
+ zipwarn("name not matched: ", path);
+ else
+ ziperr(m, a);
+ }
+ /* restore recursion flag */
+ recurse = recursion;
+ }
+
+ strcpy(path, n);
+
+ if ((p = strchr(path, ':')) != NULL) {
+ p[2] = '\0';
+ strcpy(drive, p);
+ } else
+ drive[0] = '\0';
+
+ /* remove trailing dot in flat file name */
+ p = strend(path) - 1;
+ if (*p == '.')
+ *p = '\0';
+
+ strcat(path, drive);
+ /* add or remove name of file */
+ if ((m = newname(path, 0, caseflag)) != ZE_OK) {
+ free(path);
+ return m;
+ }
+ free(path);
+ } else if (S_ISLIB(s.st_mode)) {
+ if ((path = malloc(strlen(n) + 2)) == NULL)
+ return ZE_MEM;
+
+ strcpy(path, n);
+
+ if ((p = strchr(path, ':')) != NULL) {
+ p[2] = '\0';
+ strcpy(drive, p);
+ } else
+ drive[0] = '\0';
+
+ /* add a trailing dot in flat file name... */
+ p = strend(path) - 1;
+ if (*p != '/')
+ strcat(path, "/");
+ p = strend(path);
+ /* ... then add drive name */
+ strcpy(p, drive);
+
+ /* don't include the library name twice... or more */
+ for (f = found; f != NULL; f = f->nxt) {
+ if (! stricmp(path, f->name)) {
+ free(path);
+ return ZE_OK;
+ }
+ }
+ /* add or remove name of library */
+ if ((m = newname(path, 0, caseflag)) != ZE_OK) {
+ free(path);
+ return m;
+ }
+ /* recurse into library if required */
+ strcpy(p - 1, ".*");
+ strcat(p, drive);
+ if (recurse && diropen(path) == 0)
+ {
+ while ((e = dirread()) != NULL) {
+ if (strcmp(e, ".") && strcmp(e, ".."))
+ {
+ if (*drive == '\0')
+ *strchr(e, ':') = '\0';
+ if ((a = malloc(strlen(e) + 1)) == NULL)
+ {
+ dirclose();
+ free((zvoid *)p);
+ return ZE_MEM;
+ }
+ strcpy(a, e);
+ if ((m = procname(a, caseflag)) != ZE_OK) /* recurse on name */
+ {
+ if (m == ZE_MISS)
+ zipwarn("name not matched: ", a);
+ else
+ ziperr(m, a);
+ }
+ free((zvoid *)a);
+ }
+ }
+ dirclose();
+ }
+ free(path);
+ } else {
+ /* Add trailing / to the directory name */
+ if ((p = malloc(strlen(n)+2)) == NULL)
+ return ZE_MEM;
+ if (strcmp(n, ".") == 0) {
+ *p = '\0'; /* avoid "./" prefix and do not create zip entry */
+ } else {
+ strcpy(p, n);
+ a = p + strlen(p);
+ if (a[-1] != '/')
+ strcpy(a, "/");
+ if (dirnames && (m = newname(p, 1, caseflag)) != ZE_OK) {
+ free((zvoid *)p);
+ return m;
+ }
+ }
+ /* recurse into directory */
+ if (recurse && (d = opendir(n)) != NULL)
+ {
+ while ((e = readd(d)) != NULL) {
+ if (strcmp(e, ".") && strcmp(e, ".."))
+ {
+ if ((a = malloc(strlen(p) + strlen(e) + 1)) == NULL)
+ {
+ closedir(d);
+ free((zvoid *)p);
+ return ZE_MEM;
+ }
+ strcat(strcpy(a, p), e);
+ if ((m = procname(a, caseflag)) != ZE_OK) /* recurse on name */
+ {
+ if (m == ZE_MISS)
+ zipwarn("name not matched: ", a);
+ else
+ ziperr(m, a);
+ }
+ free((zvoid *)a);
+ }
+ }
+ closedir(d);
+ }
+ free((zvoid *)p);
+ }
+ 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 */
+ char *p;
+ int dosflag;
+
+ dosflag = dosify; /* default for non-DOS and non-OS/2 */
+
+ /* Find starting point in name before doing malloc */
+ for (t = x; *t == '/'; t++)
+ ;
+
+ /* Make changes, if any, to the copied name (leave original intact) */
+ if (!pathput)
+ t = last(t, '/');
+
+ /* Malloc space for internal name and copy it */
+ if ((n = malloc(strlen(t) + 1)) == NULL)
+ return NULL;
+
+ strcpy(n, t);
+ if (p = strchr(n, ':'))
+ *p = '\0';
+ for (p = n; *p = tolower(*p); p++);
+
+ if (isdir == 42) return n; /* avoid warning on unused variable */
+
+ 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, n);
+ return x;
+}
+
+/*
+ * XXX use ztimbuf in both POSIX and non POSIX cases ?
+ */
+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. Bits 8 to 15 contains native THEOS protection
+ code. 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;
+ }
+
+ if ((name = malloc(len + 1)) == NULL) {
+ ZIPERR(ZE_MEM, "filetime");
+ }
+ strcpy(name, f);
+
+ if (name[len - 1] == '/' || 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
+ || (s.st_mode & S_IFMT) == S_IFLIB) {
+ *a |= MSDOS_DIR_ATTR;
+ }
+ /* Map Theos' hidden attribute to DOS's hidden attribute */
+ if (!(st.st_protect & 0x80))
+ *a |= MSDOS_HIDDEN_ATTR;
+ *a |= ((ulg) s.st_protect) << 8;
+ }
+ 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 = t->mtime; /* best guess, (s.st_ctime: last status change!!) */
+ }
+
+ free(name);
+
+ return unix2dostime(&s.st_mtime);
+}
+/*
+ * Get file THEOS attributes and store them into extent fields.
+ * On error leave z intact.
+ */
+
+/*
+* Extra record format
+* ===================
+* signature (2 bytes) = 'T','h'
+* size (2 bytes)
+* flags (1 byte)
+* filesize (4 bytes)
+* keylen (2 bytes)
+* reclen (2 bytes)
+* filegrow (1 byte)
+* reserved (4 bytes)
+*/
+
+#define EB_L_THSIZE 4
+#define EB_L_TH_SIZE 14
+
+int set_extra_field(z, z_utim)
+ struct zlist *z;
+ iztimes *z_utim;
+ /* store full data in local header but just modification time stamp info
+ in central header */
+{
+ char *extra = NULL;
+ char *p;
+ char c;
+ struct stat st;
+ int status;
+
+ if (status = stat(z->name, &st)) {
+ p = &z->name[strlen(z->name) - 1];
+ if (*p == '/' || *p == '.') {
+ c = *p;
+ *p = '\0';
+ status = stat(z->name, &st);
+ *p = c;
+ }
+#ifdef DEBUG
+ fprintf(stderr, "set_extra_field: stat for file %s:\n status = %d\n",
+ z->name, status);
+#endif
+ if (status)
+ return RET_ERROR;
+ }
+
+ if ((extra = malloc(EB_L_TH_SIZE)) == NULL ) {
+ fprintf(stderr, "set_extra_field: Insufficient memory.\n" );
+ return RET_ERROR;
+ }
+
+
+ extra[0] = 'T';
+ extra[1] = 'h';
+ extra[2] = EB_L_TH_SIZE;
+ extra[3] = EB_L_TH_SIZE >> 8;
+ extra[4] = 0;
+ extra[5] = st.st_size;
+ extra[6] = st.st_size >> 8;
+ extra[7] = st.st_size >> 16;
+ extra[8] = st.st_size >> 24;
+ extra[9] = st.st_org;
+ extra[10] = st.st_rlen;
+ extra[11] = st.st_rlen >> 8;
+ extra[12] = st.st_klen;
+ extra[13] = st.st_klen >> 8;
+ extra[14] = st.st_grow;
+ extra[15] = st.st_protect;
+ extra[16] = 0;
+ extra[17] = 0;
+ z->ext = z->cext = EB_L_TH_SIZE + EB_HEADSIZE;
+ z->extra = z->cextra = extra;
+ return RET_SUCCESS;
+}
+#endif
+
+/******************************/
+/* Function version_local() */
+/******************************/
+
+void version_local()
+{
+ printf("Compiled with THEOS C 5.28 for THEOS 4.x on %s %s.\n\n",
+ __DATE__, __TIME__);
+}
+
diff --git a/theos/zipup.h b/theos/zipup.h
new file mode 100644
index 0000000..1de3f61
--- /dev/null
+++ b/theos/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