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 * routines common to VM/CMS and MVS
11 */
12
13#include "zip.h"
14
15#include <stdio.h>
16#include <time.h>
17#include <errno.h>
18
19#ifndef MVS  /* MVS has perfectly good definitions of the following */
20int stat(const char *path, struct stat *buf)
21{
22   if ((buf->fp = fopen(path, "r")) != NULL) {
23      fldata_t fdata;
24      if (fldata( buf->fp, buf->fname, &fdata ) == 0) {
25         buf->st_dev  = fdata.__device;
26         buf->st_mode = *(short *)(&fdata);
27      }
28      strcpy( buf->fname, path );
29      fclose(buf->fp);
30   }
31   return (buf->fp != NULL ? 0 : 1);
32}
33#endif /* MVS */
34
35
36#ifndef UTIL    /* the companion #endif is a bit of ways down ... */
37
38#define PAD 0
39#define PATH_END '/'
40
41/* Library functions not in (most) header files */
42
43#ifdef USE_ZIPMAIN
44int main OF((void));
45#endif
46
47int utime OF((char *, ztimbuf *));
48
49extern char *label;
50local ulg label_time = 0;
51local ulg label_mode = 0;
52local time_t label_utim = 0;
53
54#ifndef MVS  /* MVS has perfectly good definitions of the following */
55int fstat(int fd, struct stat *buf)
56{
57   fldata_t fdata;
58
59   if ((fd != -1) && (fldata( (FILE *)fd, buf->fname, &fdata ) == 0)) {
60      buf->st_dev  = fdata.__device;
61      buf->st_mode = *(short *)(&fdata);
62      buf->fp      = (FILE *)fd;
63      return 0;
64   }
65   return -1;
66}
67#endif /* MVS */
68
69
70char *ex2in(x, isdir, pdosflag)
71char *x;                /* external file name */
72int isdir;              /* input: x is a directory */
73int *pdosflag;          /* output: force MSDOS file attributes? */
74/* Convert the external file name to a zip file name, returning the malloc'ed
75   string or NULL if not enough memory. */
76{
77  char *n;              /* internal file name (malloc'ed) */
78  char *t;              /* shortened name */
79  int dosflag;
80  char mem[10] = "";    /* member name */
81  char ext[10] = "";     /* extension name */
82
83  dosflag = dosify;  /* default for non-DOS non-OS/2 */
84
85  /* Find starting point in name before doing malloc */
86  for (t = x; *t == '/'; t++)
87    ;
88
89  /* Make changes, if any, to the copied name (leave original intact) */
90  if (!pathput)
91    t = last(t, PATH_END);
92
93  /* Malloc space for internal name and copy it */
94  if ((n = malloc(strlen(t) + 1)) == NULL)
95    return NULL;
96  strcpy(n, t);
97
98#ifdef MVS
99  /* strip quotes from name, non-OE format */
100  if (*n == '\'' && (t = strrchr(n, '\'')) != n) {
101    if (!*(t+1)) {
102      /* yes, it is a quoted name */
103      int l = strlen(n) - 2;
104      memmove(n, n+1, l);
105      *(n+l) = '\0';
106    }
107  }
108  /* Change member names to fn.ext */
109  if (t = strrchr(n, '(')) {
110     *t = '\0';
111     strcpy(mem,t+1);        /* Save member name */
112     if (t = strchr(mem, ')')) *t = '\0';         /* Set end of mbr */
113     /* Save extension */
114     if (t = strrchr(n, '.')) t++;
115     else t = n;
116     strcpy(ext,t);
117     /* Build name as "member.ext" */
118     strcpy(t,mem);
119     strcat(t,".");
120     strcat(t,ext);
121  }
122
123  /* Change all but the last '.' to '/' */
124  if (t = strrchr(n, '.')) {
125     while (--t > n)
126        if (*t == '.')
127          *t = '/';
128  }
129#else
130  /* On CMS, remove the filemode (all past 2nd '.') */
131  if (t = strchr(n, '.'))
132     if (t = strchr(t+1, '.'))
133        *t = '\0';
134  t = n;
135#endif
136
137  strcpy(n, t);
138
139  if (isdir == 42) return n;    /* avoid warning on unused variable */
140
141  if (dosify)
142    msname(n);                  /* msname() needs string in native charset */
143
144  strtoasc(n, n);
145
146  /* Returned malloc'ed name */
147  if (pdosflag)
148    *pdosflag = dosflag;
149  return n;
150}
151
152
153char *in2ex(n)
154char *n;                /* internal file name */
155/* Convert the zip file name to an external file name, returning the malloc'ed
156   string or NULL if not enough memory. */
157{
158  char *x;              /* external file name */
159
160  if ((x = malloc(strlen(n) + 1 + PAD)) == NULL)
161    return NULL;
162  strtoebc(x, n);
163  return x;
164}
165
166
167void stamp(f, d)
168char *f;                /* name of file to change */
169ulg d;                  /* dos-style time to change it to */
170/* Set last updated and accessed time of file f to the DOS time d. */
171{
172  ztimbuf u;            /* argument for utime() */
173
174  /* Convert DOS time to time_t format in u.actime and u.modtime */
175  u.actime = u.modtime = dos2unixtime(d);
176
177  utime(f, &u);
178}
179
180
181ulg filetime(f, a, n, t)
182char *f;                /* name of file to get info on */
183ulg *a;                 /* return value: file attributes */
184long *n;                /* return value: file size */
185iztimes *t;             /* return value: access, modific. and creation times */
186{
187  FILE *stream;
188  time_t ltime;
189
190  if (strcmp(f, "-") != 0) {    /* if not compressing stdin */
191     Trace((mesg, "opening file '%s' with '%s'\n", f, FOPR));
192     if ((stream = fopen(f, FOPR)) == (FILE *)NULL) {
193        return 0;
194     } else {
195        if (n != NULL) {
196           /* With byteseek, this will work */
197           fseek(stream, 0L, SEEK_END);
198           *n = ftell(stream);
199           Trace((mesg, "file size = %lu\n", *((ulg *)n)));
200        }
201        fclose(stream);
202     }
203  }
204  else {
205     /* Reading from stdin */
206     if (n != NULL) {
207        *n = -1L;
208     }
209  }
210
211  /* Return current time for all the times -- for now */
212  time(&ltime);
213  if (t != NULL)
214     t->atime = t->mtime = t->ctime = ltime;
215
216  /* Set attributes (always a file) */
217  if (a != NULL)
218     *a = 0;
219
220  return unix2dostime(&ltime);
221}
222
223
224
225int set_extra_field(z, z_utim)
226struct zlist far *z;
227iztimes *z_utim;
228/* create extra field and change z->att if desired */
229{
230   fldata_t fdata;
231   FILE *stream;
232   char *eb_ptr;
233#ifdef USE_EF_UT_TIME
234   extent ef_l_len = (EB_HEADSIZE+EB_UT_LEN(1));
235#else /* !USE_EF_UT_TIME */
236   extent ef_l_len = 0;
237#endif /* ?USE_EF_UT_TIME */
238   int set_cmsmvs_eb = 0;
239
240/*translate_eol = 0;*/
241  if (aflag == ASCII) {
242     z->att = ASCII;
243  } else {
244    if (bflag)
245      z->att = BINARY;
246    else
247      z->att = __EBCDIC;
248    ef_l_len += sizeof(fdata)+EB_HEADSIZE;
249    set_cmsmvs_eb = 1;
250  }
251
252  if (ef_l_len > 0) {
253    z->extra = (char *)malloc(ef_l_len);
254    if (z->extra == NULL) {
255       printf("\nFLDATA : Unable to allocate memory !\n");
256       return ZE_MEM;
257    }
258    z->cext = z->ext = ef_l_len;
259    eb_ptr = z->cextra = z->extra;
260
261    if (set_cmsmvs_eb) {
262      if (bflag)
263/***    stream = fopen(z->zname,"rb,type=record");   $RGH$ ***/
264        stream = fopen(z->name,"rb");
265      else
266        stream = fopen(z->name,"r");
267      if (stream == NULL) {
268        printf("\nFLDATA : Could not open file : %s !\n",z->name);
269        printf("Error %d: '%s'\n", errno, strerror(errno));
270        return ZE_NONE;
271      }
272
273      fldata(stream,z->name,&fdata);
274      /*put the system ID */
275#ifdef VM_CMS
276      *(eb_ptr) = EF_VMCMS & 0xFF;
277      *(eb_ptr+1) = EF_VMCMS >> 8;
278#else
279      *(eb_ptr) = EF_MVS & 0xFF;
280      *(eb_ptr+1) = EF_MVS >> 8;
281#endif
282      *(eb_ptr+2) = sizeof(fdata) & 0xFF;
283      *(eb_ptr+3) = sizeof(fdata) >> 8;
284
285      memcpy(eb_ptr+EB_HEADSIZE,&fdata,sizeof(fdata));
286      fclose(stream);
287#ifdef USE_EF_UT_TIME
288      eb_ptr += (sizeof(fdata)+EB_HEADSIZE);
289#endif /* USE_EF_UT_TIME */
290    }
291#ifdef USE_EF_UT_TIME
292    eb_ptr[0]  = 0x55;                  /* ascii[(unsigned)('U')] */
293    eb_ptr[1]  = 0x54;                  /* ascii[(unsigned)('T')] */
294    eb_ptr[2]  = EB_UT_LEN(1);          /* length of data part of e.f. */
295    eb_ptr[3]  = 0;
296    eb_ptr[4]  = EB_UT_FL_MTIME;
297    eb_ptr[5]  = (char)(z_utim->mtime);
298    eb_ptr[6]  = (char)(z_utim->mtime >> 8);
299    eb_ptr[7]  = (char)(z_utim->mtime >> 16);
300    eb_ptr[8]  = (char)(z_utim->mtime >> 24);
301#endif /* USE_EF_UT_TIME */
302  }
303
304  return ZE_OK;
305}
306
307int deletedir(d)
308char *d;                /* directory to delete */
309/* Delete the directory *d if it is empty, do nothing otherwise.
310   Return the result of rmdir(), delete(), or system().
311   For VMS, d must be in format [x.y]z.dir;1  (not [x.y.z]).
312 */
313{
314    return 0;
315}
316
317#ifdef USE_ZIPMAIN
318/* This function is called as main() to parse arguments                */
319/* into argc and argv.  This is required for stand-alone               */
320/* execution.  This calls the "real" main() when done.                 */
321
322int main(void)
323   {
324    int  argc=0;
325    char *argv[50];
326
327    int  iArgLen;
328    char argstr[256];
329    char **pEPLIST, *pCmdStart, *pArgStart, *pArgEnd;
330
331   /* Get address of extended parameter list from S/370 Register 0 */
332   pEPLIST = (char **)__xregs(0);
333
334   /* Null-terminate the argument string */
335   pCmdStart = *(pEPLIST+0);
336   pArgStart = *(pEPLIST+1);
337   pArgEnd   = *(pEPLIST+2);
338   iArgLen   = pArgEnd - pCmdStart + 1;
339
340   /* Make a copy of the command string */
341   memcpy(argstr, pCmdStart, iArgLen);
342   argstr[iArgLen] = '\0';  /* Null-terminate */
343
344   /* Store first token (cmd) */
345   argv[argc++] = strtok(argstr, " ");
346
347   /* Store the rest (args) */
348   while (argv[argc-1])
349      argv[argc++] = strtok(NULL, " ");
350   argc--;  /* Back off last NULL entry */
351
352   /* Call "real" main() function */
353   return zipmain(argc, argv);
354
355}
356#endif /* USE_ZIPMAIN */
357
358#endif /* !UTIL */
359
360
361/******************************/
362/*  Function version_local()  */
363/******************************/
364
365void version_local()
366{
367    char liblvlmsg [50+1];
368    char *compiler = "?";
369    char *platform = "?";
370    char complevel[64];
371
372    /* Map the runtime library level information */
373    union {
374       unsigned int iVRM;
375       struct {
376          unsigned int pd:4;    /* Product designation */
377          unsigned int vv:4;    /* Version             */
378          unsigned int rr:8;    /* Release             */
379          unsigned int mm:16;   /* Modification level  */
380       } xVRM;
381    } VRM;
382
383
384    /* Break down the runtime library level */
385    VRM.iVRM = __librel();
386    sprintf(liblvlmsg, "Using runtime library level %s V%dR%dM%d",
387            (VRM.xVRM.pd==1 ? "LE" : "CE"),
388            VRM.xVRM.vv, VRM.xVRM.rr, VRM.xVRM.mm);
389    /* Note:  LE = Language Environment, CE = Common Env. (C/370). */
390    /* This refers ONLY to the current runtimes, not the compiler. */
391
392
393#ifdef VM_CMS
394    platform = "VM/CMS";
395    #ifdef __IBMC__
396       compiler = "IBM C";
397    #else
398       compiler  = "C/370";
399    #endif
400#endif
401
402#ifdef MVS
403    platform = "MVS";
404    #ifdef __IBMC__
405       compiler = "IBM C/C++";
406    #else
407       compiler = "C/370";
408    #endif
409#endif
410
411#ifdef __COMPILER_VER__
412    VRM.iVRM = __COMPILER_VER__;
413    sprintf(complevel," V%dR%dM%d",
414            VRM.xVRM.vv, VRM.xVRM.rr, VRM.xVRM.mm);
415#else
416#ifdef __IBMC__
417    sprintf(complevel," V%dR%d", __IBMC__ / 100, (__IBMC__ % 100)/10);
418#else
419    complevel[0] = '\0';
420#endif
421#endif
422
423
424    printf("Compiled with %s%s for %s%s%s.\n\n",
425
426    /* Add compiler name and level */
427    compiler, complevel,
428
429    /* Add platform */
430    platform,
431
432    /* Add timestamp */
433#ifdef __DATE__
434      " on " __DATE__
435#ifdef __TIME__
436      " at " __TIME__
437#endif
438#endif
439      ".\n",
440      liblvlmsg
441    );
442} /* end function version_local() */
443