mvs.c 6.2 KB

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