summaryrefslogtreecommitdiff
path: root/cmsmvs/mvs.c
diff options
context:
space:
mode:
Diffstat (limited to 'cmsmvs/mvs.c')
-rw-r--r--cmsmvs/mvs.c221
1 files changed, 221 insertions, 0 deletions
diff --git a/cmsmvs/mvs.c b/cmsmvs/mvs.c
new file mode 100644
index 0000000..fabc4f0
--- /dev/null
+++ b/cmsmvs/mvs.c
@@ -0,0 +1,221 @@
+/*
+ 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
+*/
+/*
+ * MVS specific things
+ */
+#include "zip.h"
+#include "mvs.h"
+#include <errno.h>
+
+static int gen_node( DIR *dirp, RECORD *recptr )
+{
+ char *ptr, *name, ttr[TTRLEN];
+ int skip, count = 2;
+ unsigned int info_byte, alias, ttrn;
+ struct dirent *new;
+
+ ptr = recptr->rest;
+ while (count < recptr->count) {
+ if (!memcmp( ptr, endmark, NAMELEN ))
+ return 1;
+ name = ptr; /* member name */
+ ptr += NAMELEN;
+ memcpy( ttr, ptr, TTRLEN ); /* ttr name */
+ ptr += TTRLEN;
+ info_byte = (unsigned int) (*ptr); /* info byte */
+ if ( !(info_byte & ALIAS_MASK) ) { /* no alias */
+ new = malloc( sizeof(struct dirent) );
+ if (dirp->D_list == NULL)
+ dirp->D_list = dirp->D_curpos = new;
+ else
+ dirp->D_curpos = (dirp->D_curpos->d_next = new);
+ new->d_next = NULL;
+ memcpy( new->d_name, name, NAMELEN );
+ new->d_name[NAMELEN] = '\0';
+ if ((name = strchr( new->d_name, ' ' )) != NULL)
+ *name = '\0'; /* skip trailing blanks */
+ }
+ skip = (info_byte & SKIP_MASK) * 2 + 1;
+ ptr += skip;
+ count += (TTRLEN + NAMELEN + skip);
+ }
+ return 0;
+}
+
+DIR *opendir(const char *dirname)
+{
+ int bytes, list_end = 0;
+ DIR *dirp;
+ FILE *fp;
+ RECORD rec;
+
+ fp = fopen( dirname, "rb" );
+ if (fp != NULL) {
+ dirp = malloc( sizeof(DIR) );
+ if (dirp != NULL) {
+ dirp->D_list = dirp->D_curpos = NULL;
+ strcpy( dirp->D_path, dirname );
+ do {
+ bytes = fread( &rec, 1, sizeof(rec), fp );
+ if (bytes == sizeof(rec))
+ list_end = gen_node( dirp, &rec );
+ } while (!feof(fp) && !list_end);
+ fclose( fp );
+ dirp->D_curpos = dirp->D_list;
+ return dirp;
+ }
+ fclose( fp );
+ }
+ return NULL;
+}
+
+struct dirent *readdir(DIR *dirp)
+{
+ struct dirent *cur;
+
+ cur = dirp->D_curpos;
+ dirp->D_curpos = dirp->D_curpos->d_next;
+ return cur;
+}
+
+void rewinddir(DIR *dirp)
+{
+ dirp->D_curpos = dirp->D_list;
+}
+
+int closedir(DIR *dirp)
+{
+ struct dirent *node;
+
+ while (dirp->D_list != NULL) {
+ node = dirp->D_list;
+ dirp->D_list = dirp->D_list->d_next;
+ free( node );
+ }
+ free( dirp );
+ return 0;
+}
+
+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;
+}
+
+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 far *z; /* steps through zfiles list */
+ int exists; /* 1 if file exists */
+
+ if (strcmp(n, "-") == 0) /* if compressing stdin */
+ return newname(n, 0, caseflag);
+ else if (!(exists = (LSSTAT(n, &s) == 0)))
+ {
+#ifdef MVS
+ /* special case for MVS. stat does not work on non-HFS files so if
+ * stat fails with ENOENT, try to open the file for reading anyway.
+ * If the user has no OMVS segment, stat gets an initialization error,
+ * even on external files.
+ */
+ if (errno == ENOENT || errno == EMVSINITIAL) {
+ FILE *f = fopen(n, "r");
+ if (f) {
+ /* stat got ENOENT but fopen worked, external file */
+ fclose(f);
+ exists = 1;
+ memset(&s, '\0', sizeof(s)); /* stat data is unreliable for externals */
+ s.st_mode = S_IFREG; /* fudge it */
+ }
+ }
+#endif /* MVS */
+ }
+ if (! exists) {
+ /* 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((zvoid *)p);
+ return m ? ZE_MISS : ZE_OK;
+ }
+
+ /* Live name--use if file, recurse if directory */
+ if (!S_ISDIR(s.st_mode))
+ {
+ /* add or remove name of file */
+ if ((m = newname(n, 0, caseflag)) != ZE_OK)
+ return m;
+ } 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);
+ } /* (s.st_mode & S_IFDIR) == 0) */
+ return ZE_OK;
+}