Working DOS version
authorRobert Pengelly <robertapengelly@hotmail.com>
Sun, 1 Mar 2026 15:39:05 +0000 (15:39 +0000)
committerRobert Pengelly <robertapengelly@hotmail.com>
Sun, 1 Mar 2026 15:39:05 +0000 (15:39 +0000)
makefile.wat [new file with mode: 0644]
report.c
tar.c

diff --git a/makefile.wat b/makefile.wat
new file mode 100644 (file)
index 0000000..f2a1cb6
--- /dev/null
@@ -0,0 +1,19 @@
+#******************************************************************************
+# @file             Makefile.wat
+#******************************************************************************
+SRCDIR              ?=  $(CURDIR)
+VPATH               :=  $(SRCDIR)
+
+CSRC                :=  lib.c tar.c report.c
+INCDIR              :=  $(subst /,\,$(SRCDIR))
+
+all: unzip.exe
+
+unzip.exe: $(CSRC)
+
+       wcl -fe=$@ $^
+
+clean:
+
+       for /r %%f in (*.obj) do ( if exist %%f ( del /q %%f ) )
+       if exist unzip.exe ( del /q unzip.exe )
index 8e128ef31f46400f43a7afab03f4526adf5fcc2c..b30b515c4703e607e0182757afe9ccaf441c510e 100755 (executable)
--- a/report.c
+++ b/report.c
@@ -17,7 +17,11 @@ static int OriginalConsoleColor = -1;
 
 static void reset_console_color (void) {
 
-#if     defined (_WIN32)
+#if     defined (unix) || defined (__unix) || defined (__unix__) || defined (__APPLE__)
+
+    fprintf (stderr, "\033[0m");
+
+#elif   defined (_WIN32)
 
     HANDLE hStdError = GetStdHandle (STD_ERROR_HANDLE);
     
@@ -26,17 +30,17 @@ static void reset_console_color (void) {
     SetConsoleTextAttribute (hStdError, OriginalConsoleColor);
     OriginalConsoleColor = -1;
 
-#else
-
-    fprintf (stderr, "\033[0m");
-
 #endif
 
 }
 
 static void set_console_color (int color) {
 
-#if     defined (_WIN32)
+#if     defined (unix) || defined (__unix) || defined (__unix__) || defined (__APPLE__)
+
+    fprintf (stderr, "\033[%dm", color);
+
+#elif   defined (_WIN32)
 
     HANDLE hStdError = GetStdHandle (STD_ERROR_HANDLE);
     WORD wColor;
@@ -56,10 +60,6 @@ static void set_console_color (int color) {
     wColor = (OriginalConsoleColor & 0xF0) + (color & 0xF);
     SetConsoleTextAttribute (hStdError, wColor);
 
-#else
-
-    fprintf (stderr, "\033[%dm", color);
-
 #endif
 
 }
diff --git a/tar.c b/tar.c
index fd3f88be20fe9d3e443c55fa9a87b2775ebba938..80e51c31818fc508a0cb47889e533c6741c342d7 100755 (executable)
--- a/tar.c
+++ b/tar.c
@@ -867,6 +867,513 @@ static void extract_files (FILE *tarfp, char *root) {
     
     free (p2);
 
+}
+#elif       defined (__WATCOMC__)
+# include       <i86.h>
+
+static int IsDirectory (const char *path) {
+
+    struct SREGS sr = { 0 };
+    union REGS r = { 0 };
+    
+    char *temp = xstrdup (path);
+    unsigned len = strlen (temp);
+    
+    if (len > 3) {
+    
+        while (temp[len - 1] == '\\') {
+            temp[--len] = '\0';
+        }
+    
+    }
+    
+    r.w.ax = 0x4300;
+    r.w.dx = FP_OFF (temp);
+    
+    sr.ds = FP_SEG (temp);
+    int86x (0x21, &r, &r, &sr);
+    
+    free (temp);
+    return (!(r.w.cflag & 1) && (r.w.cx & 0x10));
+
+}
+
+int CreateDirectory (const char *path) {
+
+    struct SREGS sr = { 0 };
+    union REGS r = { 0 };
+    
+    char *p = (char *) path;
+    
+    while (p && *p != '\0') {
+    
+        while (*p && *p == '\\') {
+            p++;
+        }
+        
+        if (*p == '\0') { break; }
+        
+        if ((p = strchr (p, '\\'))) {
+            *p = '\0';
+        }
+        
+        r.w.ax = 0x3900;
+        r.w.dx = FP_OFF (path);
+        
+        sr.ds = FP_SEG (path);
+        int86x (0x21, &r, &r, &sr);
+        
+        if (r.w.cflag & 1) {
+        
+            r.w.ax = 0x4300;
+            r.w.dx = FP_OFF (path);
+            
+            sr.ds = FP_SEG (path);
+            int86x (0x21, &r, &r, &sr);
+            
+            if (r.w.cflag & 1) {
+                return 1;
+            }
+        
+        }
+        
+        if (p) { *p = '\\'; }
+    
+    }
+    
+    return 0;
+
+}
+
+static int FindFirstFile (const char *path) {
+
+    struct SREGS sr = { 0 };
+    union REGS r = { 0 };
+    
+    char *temp = xstrdup (path);
+    unsigned len = strlen (temp);
+    
+    if (len > 3) {
+    
+        while (temp[len - 1] == '\\') {
+            temp[--len] = '\0';
+        }
+    
+    }
+    
+    r.w.ax = 0x4E00;
+    r.w.cx = 0x30;
+    r.w.dx = FP_OFF (temp);
+    
+    sr.ds = FP_SEG (temp);
+    int86x (0x21, &r, &r, &sr);
+    
+    free (temp);
+    return (!(r.w.cflag & 1));
+
+}
+
+static int SetDiskTransfer (void *buf) {
+
+    struct SREGS sr = { 0 };
+    union REGS r = { 0 };
+    
+    r.w.ax = 0x1A00;
+    r.w.dx = FP_OFF (buf);
+    
+    sr.ds = FP_SEG (buf);
+    int86x (0x21, &r, &r, &sr);
+    
+    return (!(r.w.cflag & 1));
+
+}
+
+static int FindNextFile (void) {
+
+    struct SREGS sr = { 0 };
+    union REGS r = { 0 };
+    
+    r.w.ax = 0x4F00;
+    int86x (0x21, &r, &r, &sr);
+    
+    return (!(r.w.cflag & 1));
+
+}
+
+static void add_entry (FILE *tarfp, char *root, const char *path) {
+
+    struct tar_raw_header header;
+    
+    const char *p = path;
+    char *p2;
+    
+    unsigned long len, i;
+    int mode;
+    
+    if (isalpha ((int) p[0]) && p[1] == ':') {
+        p += 2;
+    }
+    
+    while (*p == '/' || *p == '\\') {
+        p++;
+    }
+    
+    if (root) {
+    
+        len = strlen (root);
+        
+        while (root[len - 1] == '/' || root[len - 1] == '\\') {
+        
+            root[len - 1] = '\0';
+            len--;
+        
+        }
+        
+        for (i = 0; i < len; i++) {
+        
+            if (root[i] == '\\') {
+                root[i] = '/';
+            }
+        
+        }
+        
+        p2 = xmalloc (len + 1);
+        sprintf (p2, "%s/", root);
+    
+    } else {
+        p2 = xstrdup (path);
+    }
+    
+    memset (&header, 0, sizeof (header));
+    strcpy (header.name, p);
+    
+    memset (header.mtime, '0', 11);
+    sprintf (header.owner, "%07o", 0);
+    
+    if (state->mode) {
+    
+        int o1, o2, o3;
+        
+        o1 = state->mode[1] - '0';
+        o2 = state->mode[2] - '0';
+        o3 = state->mode[3] - '0';
+        
+        mode = (o1 << 6) | (o2 << 3) | o3;
+    
+    } else {
+        mode = (IsDirectory (p2) ? 0775 : 0644);
+    }
+    
+    sprintf (header.mode, "%07o", mode);
+    
+    if (IsDirectory (p2)) {
+    
+        unsigned char dta[128] = { 0 };
+        char *subpath, *filename;
+        
+        memset (header.size, '0', 11);
+        header.type = '5';              /* MTAR_TDIR */
+        
+        if (header.name[strlen(p) - 1] != '/') {
+            header.name[strlen(p)] = '/';
+        }
+        
+        sprintf (header.checksum, "%06o", checksum (&header));
+        header.checksum[7] = ' ';
+        
+        if (fwrite (&header, 1, sizeof (header), tarfp) != sizeof (header)) {
+            report_at (program_name, 0, REPORT_ERROR, "failed to write header to '%s'", state->target);
+        }
+        
+        len = strlen (p2);
+        
+        if (p2[len - 1] == '/') {
+        
+            subpath = xmalloc (len + 5);
+            sprintf (subpath, "%s*.*", p2);
+        
+        } else {
+        
+            subpath = xmalloc (len + 6);
+            sprintf (subpath, "%s/*.*", p2);
+        
+        }
+        
+        if (!SetDiskTransfer (dta) || !FindFirstFile (subpath)) {
+        
+            free (subpath);
+            return;
+        
+        }
+        
+        free (subpath);
+        
+        do {
+        
+            filename = dta + 0x1E;
+            
+            if (filename[0] == '.' && (filename[1] == '\0' || (filename[1] == '.' && filename[2] == '\0'))) {
+                continue;
+            }
+            
+            len = strlen (path);
+            
+            if (path[len - 1] == '/') {
+            
+                len += (strlen (filename) + 1);
+                
+                if (!(subpath = malloc (len))) {
+                
+                    report_at (program_name, 0, REPORT_ERROR, "failed to allocate memory for '%s'", filename);
+                    continue;
+                
+                }
+                
+                sprintf (subpath, "%s%s", path, filename);
+            
+            } else {
+            
+                len += (1 + strlen (filename) + 1);
+                
+                if (!(subpath = malloc (len))) {
+                
+                    report_at (program_name, 0, REPORT_ERROR, "failed to allocate memory for '%s'", filename);
+                    continue;
+                
+                }
+                
+                sprintf (subpath, "%s/%s", path, filename);
+            
+            }
+            
+            add_entry (tarfp, root, subpath);
+            free (subpath);
+        
+        } while (FindNextFile ());
+        
+        /*FindClose (hFind);*/
+    
+    } else {
+    
+        FILE *fp;
+        
+        unsigned char *data;
+        uint64_t bytes, read;
+        
+        if (!(fp = fopen (p2, "r+b"))) {
+        
+            report_at (program_name, 0, REPORT_WARNING, "failed to open '%s' for reading", path);
+            goto _end;
+        
+        }
+        
+        fseek (fp, 0, SEEK_END);
+        bytes = ftell (fp);
+        
+        fseek (fp, 0, SEEK_SET);
+        
+        sprintf (header.size, "%011"I64_FMT"o", bytes);
+        header.type = '0';              /* MTAR_TREG */
+        
+        sprintf (header.checksum, "%06o", checksum (&header));
+        header.checksum[7] = ' ';
+        
+        if (fwrite (&header, 1, sizeof (header), tarfp) != sizeof (header)) {
+        
+            report_at (program_name, 0, REPORT_ERROR, "failed to write header to '%s'", state->target);
+            fclose (fp);
+            
+            goto _end;
+        
+        }
+        
+        data = xmalloc (512);
+        
+        for (;;) {
+        
+            if (bytes == 0 || feof (fp)) {
+                break;
+            }
+            
+            read = (bytes > 512 ? 512 : bytes);
+            
+            if (fread (data, 1, read, fp) != read) {
+            
+                report_at (program_name, 0, REPORT_ERROR, "failed to read %lu bytes from %s", read, path);
+                break;
+            
+            }
+            
+            if (fwrite (data, 1, read, tarfp) != read) {
+            
+                report_at (program_name, 0, REPORT_ERROR, "failed to write %lu bytes to %s", read, state->target);
+                break;
+            
+            }
+            
+            bytes -= read;
+        
+        }
+        
+        bytes = ftell (fp) % 512;
+        fclose (fp);
+        
+        if (bytes != 0) {
+            write_null_bytes (tarfp, 512 - bytes);
+        }
+    
+    }
+    
+_end:
+    
+    free (p2);
+
+}
+
+static void extract_files (FILE *tarfp, char *root) {
+
+    struct tar_raw_header header;
+    
+    char *path, *p2;
+    FILE *fp;
+    
+    unsigned long len, i;
+    
+    if (root) {
+    
+        len = strlen (root);
+        
+        while (root[len - 1] == '/' || root[len - 1] == '\\') {
+        
+            root[len - 1] = '\0';
+            len--;
+        
+        }
+        
+        for (i = 0; i < len; i++) {
+        
+            if (root[i] == '\\') {
+                root[i] = '/';
+            }
+        
+        }
+        
+        if (!CreateDirectory (root)) {
+        
+            report_at (program_name, 0, REPORT_ERROR, "failed to root directory %s", root);
+            return;
+        
+        }
+        
+        p2 = xmalloc (len + 1);
+        sprintf (p2, "%s/", root);
+    
+    } else {
+        p2 = xstrdup ("");
+    }
+    
+    for (;;) {
+    
+        if (feof (tarfp)) {
+            break;
+        }
+        
+        if (fread (&header, 1, sizeof (header), tarfp) != sizeof (header)) {
+        
+            report_at (program_name, 0, REPORT_ERROR, "failed to read archive header");
+            break;
+        
+        }
+        
+        if (!header.name[0]) {
+            break;
+        }
+        
+        path = xmalloc (strlen (p2) + strlen (header.name) + 1);
+        sprintf (path, "%s%s", p2, header.name);
+        
+        printf ("extracting: %s\n", path);
+        
+        if (path[strlen (path) - 1] == '/') {
+        
+            path[strlen (path) - 1] = '\0';
+            
+            if (!CreateDirectory (path)) {
+            
+                report_at (program_name, 0, REPORT_ERROR, "failed to create directory %s, %lx", path);
+                
+                free (path);
+                free (p2);
+                
+                return;
+            
+            }
+        
+        } else {
+        
+            unsigned long padding = 0, bytes, read;
+            unsigned char *data;
+            
+            if (!(fp = fopen (path, "w+b"))) {
+            
+                report_at (program_name, 0, REPORT_ERROR, "failed to create %s", path);
+                
+                free (path);
+                free (p2);
+                
+                return;
+            
+            }
+            
+            bytes = strtol (header.size, 0, 8);
+            
+            if ((bytes % 512) != 0) {
+                padding = 512 - (bytes % 512);
+            }
+            
+            data = xmalloc (512);
+            
+            for (;;) {
+            
+                memset (data, 0, 512);
+                
+                if (bytes == 0) {
+                    break;
+                }
+                
+                read = (bytes > 512 ? 512 : bytes);
+                
+                if (fread (data, 1, read, tarfp) != read) {
+                
+                    report_at (program_name, 0, REPORT_ERROR, "failed to read %lu bytes from %s", read, path);
+                    break;
+                
+                }
+                
+                if (fwrite (data, 1, read, fp) != read) {
+                
+                    report_at (program_name, 0, REPORT_ERROR, "failed to write %lu bytes to %s", read, state->target);
+                    break;
+                
+                }
+                
+                bytes -= read;
+            
+            }
+            
+            fseek (tarfp, padding, SEEK_CUR);
+            
+            free (data);
+            fclose (fp);
+        
+        }
+        
+        free (path);
+    
+    }
+    
+    free (p2);
+
 }
 #endif