1/* 2 Copyright (c) 1990-1999 Info-ZIP. All rights reserved. 3 4 See the accompanying file LICENSE, version 1999-Oct-05 or later 5 (the contents of which are also included in zip.h) for terms of use. 6 If, for some reason, both of these files are missing, the Info-ZIP license 7 also may be found at: ftp://ftp.cdrom.com/pub/infozip/license.html 8*/ 9/* 10 * MVS specific things 11 */ 12#include "zip.h" 13#include "mvs.h" 14#include <errno.h> 15 16static int gen_node( DIR *dirp, RECORD *recptr ) 17{ 18 char *ptr, *name, ttr[TTRLEN]; 19 int skip, count = 2; 20 unsigned int info_byte, alias, ttrn; 21 struct dirent *new; 22 23 ptr = recptr->rest; 24 while (count < recptr->count) { 25 if (!memcmp( ptr, endmark, NAMELEN )) 26 return 1; 27 name = ptr; /* member name */ 28 ptr += NAMELEN; 29 memcpy( ttr, ptr, TTRLEN ); /* ttr name */ 30 ptr += TTRLEN; 31 info_byte = (unsigned int) (*ptr); /* info byte */ 32 if ( !(info_byte & ALIAS_MASK) ) { /* no alias */ 33 new = malloc( sizeof(struct dirent) ); 34 if (dirp->D_list == NULL) 35 dirp->D_list = dirp->D_curpos = new; 36 else 37 dirp->D_curpos = (dirp->D_curpos->d_next = new); 38 new->d_next = NULL; 39 memcpy( new->d_name, name, NAMELEN ); 40 new->d_name[NAMELEN] = '\0'; 41 if ((name = strchr( new->d_name, ' ' )) != NULL) 42 *name = '\0'; /* skip trailing blanks */ 43 } 44 skip = (info_byte & SKIP_MASK) * 2 + 1; 45 ptr += skip; 46 count += (TTRLEN + NAMELEN + skip); 47 } 48 return 0; 49} 50 51DIR *opendir(const char *dirname) 52{ 53 int bytes, list_end = 0; 54 DIR *dirp; 55 FILE *fp; 56 RECORD rec; 57 58 fp = fopen( dirname, "rb" ); 59 if (fp != NULL) { 60 dirp = malloc( sizeof(DIR) ); 61 if (dirp != NULL) { 62 dirp->D_list = dirp->D_curpos = NULL; 63 strcpy( dirp->D_path, dirname ); 64 do { 65 bytes = fread( &rec, 1, sizeof(rec), fp ); 66 if (bytes == sizeof(rec)) 67 list_end = gen_node( dirp, &rec ); 68 } while (!feof(fp) && !list_end); 69 fclose( fp ); 70 dirp->D_curpos = dirp->D_list; 71 return dirp; 72 } 73 fclose( fp ); 74 } 75 return NULL; 76} 77 78struct dirent *readdir(DIR *dirp) 79{ 80 struct dirent *cur; 81 82 cur = dirp->D_curpos; 83 dirp->D_curpos = dirp->D_curpos->d_next; 84 return cur; 85} 86 87void rewinddir(DIR *dirp) 88{ 89 dirp->D_curpos = dirp->D_list; 90} 91 92int closedir(DIR *dirp) 93{ 94 struct dirent *node; 95 96 while (dirp->D_list != NULL) { 97 node = dirp->D_list; 98 dirp->D_list = dirp->D_list->d_next; 99 free( node ); 100 } 101 free( dirp ); 102 return 0; 103} 104 105local char *readd(d) 106DIR *d; /* directory stream to read from */ 107/* Return a pointer to the next name in the directory stream d, or NULL if 108 no more entries or an error occurs. */ 109{ 110 struct dirent *e; 111 112 e = readdir(d); 113 return e == NULL ? (char *) NULL : e->d_name; 114} 115 116int procname(n, caseflag) 117char *n; /* name to process */ 118int caseflag; /* true to force case-sensitive match */ 119/* Process a name or sh expression to operate on (or exclude). Return 120 an error code in the ZE_ class. */ 121{ 122 char *a; /* path and name for recursion */ 123 DIR *d; /* directory stream from opendir() */ 124 char *e; /* pointer to name from readd() */ 125 int m; /* matched flag */ 126 char *p; /* path for recursion */ 127 struct stat s; /* result of stat() */ 128 struct zlist far *z; /* steps through zfiles list */ 129 int exists; /* 1 if file exists */ 130 131 if (strcmp(n, "-") == 0) /* if compressing stdin */ 132 return newname(n, 0, caseflag); 133 else if (!(exists = (LSSTAT(n, &s) == 0))) 134 { 135#ifdef MVS 136 /* special case for MVS. stat does not work on non-HFS files so if 137 * stat fails with ENOENT, try to open the file for reading anyway. 138 * If the user has no OMVS segment, stat gets an initialization error, 139 * even on external files. 140 */ 141 if (errno == ENOENT || errno == EMVSINITIAL) { 142 FILE *f = fopen(n, "r"); 143 if (f) { 144 /* stat got ENOENT but fopen worked, external file */ 145 fclose(f); 146 exists = 1; 147 memset(&s, '\0', sizeof(s)); /* stat data is unreliable for externals */ 148 s.st_mode = S_IFREG; /* fudge it */ 149 } 150 } 151#endif /* MVS */ 152 } 153 if (! exists) { 154 /* Not a file or directory--search for shell expression in zip file */ 155 p = ex2in(n, 0, (int *)NULL); /* shouldn't affect matching chars */ 156 m = 1; 157 for (z = zfiles; z != NULL; z = z->nxt) { 158 if (MATCH(p, z->iname, caseflag)) 159 { 160 z->mark = pcount ? filter(z->zname, caseflag) : 1; 161 if (verbose) 162 fprintf(mesg, "zip diagnostic: %scluding %s\n", 163 z->mark ? "in" : "ex", z->name); 164 m = 0; 165 } 166 } 167 free((zvoid *)p); 168 return m ? ZE_MISS : ZE_OK; 169 } 170 171 /* Live name--use if file, recurse if directory */ 172 if (!S_ISDIR(s.st_mode)) 173 { 174 /* add or remove name of file */ 175 if ((m = newname(n, 0, caseflag)) != ZE_OK) 176 return m; 177 } else { 178 /* Add trailing / to the directory name */ 179 if ((p = malloc(strlen(n)+2)) == NULL) 180 return ZE_MEM; 181 if (strcmp(n, ".") == 0) { 182 *p = '\0'; /* avoid "./" prefix and do not create zip entry */ 183 } else { 184 strcpy(p, n); 185 a = p + strlen(p); 186 if (a[-1] != '/') 187 strcpy(a, "/"); 188 if (dirnames && (m = newname(p, 1, caseflag)) != ZE_OK) { 189 free((zvoid *)p); 190 return m; 191 } 192 } 193 /* recurse into directory */ 194 if (recurse && (d = opendir(n)) != NULL) 195 { 196 while ((e = readd(d)) != NULL) { 197 if (strcmp(e, ".") && strcmp(e, "..")) 198 { 199 if ((a = malloc(strlen(p) + strlen(e) + 1)) == NULL) 200 { 201 closedir(d); 202 free((zvoid *)p); 203 return ZE_MEM; 204 } 205 strcat(strcpy(a, p), e); 206 if ((m = procname(a, caseflag)) != ZE_OK) /* recurse on name */ 207 { 208 if (m == ZE_MISS) 209 zipwarn("name not matched: ", a); 210 else 211 ziperr(m, a); 212 } 213 free((zvoid *)a); 214 } 215 } 216 closedir(d); 217 } 218 free((zvoid *)p); 219 } /* (s.st_mode & S_IFDIR) == 0) */ 220 return ZE_OK; 221} 222