mirror of
https://github.com/jart/cosmopolitan.git
synced 2025-05-24 14:22:28 +00:00
221 lines
6.2 KiB
C
221 lines
6.2 KiB
C
/*
|
|
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
|
|
*/
|
|
/*
|
|
* 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;
|
|
}
|