2
Copyright (c) 1990-2002 Info-ZIP. All rights reserved.
4
See the accompanying file LICENSE, version 2000-Apr-09 or later
5
(the contents of which are also included in zip.h) for terms of use.
6
If, for some reason, all these files are missing, the Info-ZIP license
7
also may be found at: ftp://ftp.info-zip.org/pub/infozip/license.html
10
* routines common to TANDEM (ZIP and UNZIP)
13
#include "zip.h" /* This sets up ZIP / UNZIP define */
16
#include "$system.zsysdefs.zsysc" nolist
17
#include <cextdecs> nolist
20
static time_t gmt_to_time_t (long long *);
28
/********************/
29
/* Function in2ex() */
30
/********************/
38
char *n; /* internal file name */
39
/* Convert the zip file name to an external file name, returning the malloc'ed
40
string or NULL if not enough memory. */
42
char *x; /* external file name buffer */
43
char *y; /* pointer to external buffer */
44
char *max; /* pointer to max end of next file part */
45
char *t; /* pointer to internal - start of substring */
46
char *p; /* pointer to internal - TANDEM delimiter */
47
char *e; /* pointer to internal - DOS extension delimiter */
48
char *z; /* pointer to internal - end of substring */
49
int len; /* length of substring to copy to external name */
50
int allow_dollar; /* $ symbol allowed as next character */
52
if ((x = malloc(strlen(n) + 4)) == NULL) /* + 4 for safety */
57
/* Junk pathname as requested */
59
if (uO.jflag && (t = strrchr(n, INTERNAL_DELIMITER)) != NULL)
66
t = last(n, INTERNAL_DELIMITER);
73
while (*t != '\0') { /* File part could be sys, vol, subvol or file */
74
if (*t == INTERNAL_DELIMITER) { /* System, Volume or Subvol Name */
76
if (*t == INTERNAL_DELIMITER) { /* System */
77
strcat(x, TANDEM_NODE_STR);
81
strcat(x, TANDEM_DELIMITER_STR);
85
/* Work out where end of current external string is */
88
/* Work out substring to copy and externalise */
89
p = strchr(t, INTERNAL_DELIMITER);
90
e = strchr(t, DOS_EXTENSION);
102
/* can't have Tandem name longer than 8 characters */
103
max = y + MAXFILEPARTLEN;
105
/* Allow $ symbol as first character in some cases */
113
/* Make sure first real character is alpha */
117
/* Characters left to process */
122
*y++ = toupper(*t++);
134
/* Last part of filename, store pseudo extension if available */
136
strcat(x, TANDEM_EXTENSION_STR);
139
/* no restriction on extension length as its virtual */
141
while ( *z != '\0' ) {
142
*y++ = toupper(*z++);
156
/* Exit(>0) creates saveabend files */
157
terminate_program (0,0,(short)status,,,);
160
/************************/
161
/* Function zputc() */
162
/************************/
180
_tal _priv short FILE_CHANGELABEL_ (
183
const short _far * /* IN */
186
_c _callable int changelabel OF((short, const short *, const short *));
188
_c _callable int changelabel(fnum, modtime, actime)
190
const short *modtime;
195
err = FILE_CHANGELABEL_(fnum, 16, modtime);
197
err = FILE_CHANGELABEL_(fnum, 17, actime);
203
#define plist_items 1
204
#define plist_size 10
206
short myphandle[ZSYS_VAL_PHANDLE_WLEN];
207
short licensetag[plist_items] = {37};
208
short licensed[plist_size];
209
short maxlen = plist_size;
210
short items = plist_items;
211
short resultlen[1], err;
213
err = PROCESSHANDLE_NULLIT_(myphandle);
216
err = PROCESS_GETINFO_(myphandle);
219
err = PROCESS_GETINFOLIST_(/*cpu*/,
236
#endif /* LICENSED */
238
int utime(file, time)
248
union timestamp_ov lasttime, opentime;
249
struct tm *modt, *opent;
250
short datetime[8], errormask[1];
251
short len, fnum, access, exclus, options;
252
char fname[FILENAME_MAX + 1];
254
char ext[EXTENSION_MAX + 1];
257
/* Attempt to update file label */
258
modt = gmtime( &time->modtime );
260
datetime[0] = modt->tm_year + 1900;
261
datetime[1] = modt->tm_mon + 1;
262
datetime[2] = modt->tm_mday;
263
datetime[3] = modt->tm_hour;
264
datetime[4] = modt->tm_min;
265
datetime[5] = modt->tm_sec;
266
datetime[6] = datetime[7] = 0;
268
lasttime.fulltime = COMPUTETIMESTAMP (datetime, errormask);
270
opent = gmtime( &time->actime );
272
datetime[0] = opent->tm_year + 1900;
273
datetime[1] = opent->tm_mon + 1;
274
datetime[2] = opent->tm_mday;
275
datetime[3] = opent->tm_hour;
276
datetime[4] = opent->tm_min;
277
datetime[5] = opent->tm_sec;
278
datetime[6] = datetime[7] = 0;
280
opentime.fulltime = COMPUTETIMESTAMP (datetime, errormask);
282
/* Remove any (pseudo) file extension */
283
extension = parsename (file,fname,ext);
288
options = NSK_NOUPDATEOPENTIME;
290
extension = parsename (file,fname,ext);
293
err = FILE_OPEN_((char *)fname, len, &fnum, access, exclus,,,options,,,);
294
result = changelabel(fnum,lasttime.wordtime,opentime.wordtime);
295
err = FILE_CLOSE_(fnum);
299
#else /* !LICENSED */
300
return 0; /* "no error", to suppress annoying failure messages */
301
#endif /* ?LICENSED */
304
/* TANDEM version of chmod() function */
306
int chmod(file, unix_sec)
311
struct nsk_sec_type {
321
struct nsk_sec_type bit_ov;
324
union nsk_sec_ov nsk_sec;
325
short fnum, err, nsk_sec_int;
326
short len, access, exclus, extension, options;
327
char fname[FILENAME_MAX + 1];
328
char ext[EXTENSION_MAX + 1];
330
nsk_sec.bit_ov.progid = 0;
331
nsk_sec.bit_ov.clear = 0;
332
nsk_sec.bit_ov.null = 0;
334
/* 4="N", 5="C", 6="U", 7="-" */
336
if (unix_sec & S_IROTH) nsk_sec.bit_ov.read = 4;
337
else if (unix_sec & S_IRGRP) nsk_sec.bit_ov.read = 5;
338
else if (unix_sec & S_IRUSR) nsk_sec.bit_ov.read = 6;
339
else nsk_sec.bit_ov.read = 7;
341
if (unix_sec & S_IWOTH) nsk_sec.bit_ov.write = 4;
342
else if (unix_sec & S_IWGRP) nsk_sec.bit_ov.write = 5;
343
else if (unix_sec & S_IWUSR) nsk_sec.bit_ov.write = 6;
344
else nsk_sec.bit_ov.write = 7;
346
if (unix_sec & S_IXOTH) nsk_sec.bit_ov.execute = 4;
347
else if (unix_sec & S_IXGRP) nsk_sec.bit_ov.execute = 5;
348
else if (unix_sec & S_IXUSR) nsk_sec.bit_ov.execute = 6;
349
else nsk_sec.bit_ov.execute = 7;
351
nsk_sec.bit_ov.purge = nsk_sec.bit_ov.write;
353
nsk_sec_int = nsk_sec.int_ov;
357
options = NSK_NOUPDATEOPENTIME;
359
extension = parsename (file,fname,ext);
362
err = FILE_OPEN_((char *)fname, len, &fnum, access, exclus,,,options,,,);
363
err = (SETMODE(fnum, SET_FILE_SECURITY, nsk_sec_int) != CCE);
364
err = FILE_CLOSE_(fnum);
366
return (err != 0 ? -1 : 0);
369
/* TANDEM version of chown() function */
371
int chown(file, uid, gid)
377
struct nsk_own_type {
382
struct nsk_own_type bit_ov;
385
union nsk_own_ov nsk_own;
386
short fnum, err, nsk_own_int;
387
short len, access, exclus, extension, options;
388
char fname[FILENAME_MAX + 1];
389
char ext[EXTENSION_MAX + 1];
391
nsk_own.bit_ov.group = gid;
392
nsk_own.bit_ov.user = uid;
394
nsk_own_int = nsk_own.int_ov;
398
options = NSK_NOUPDATEOPENTIME;
400
extension = parsename (file,fname,ext);
403
err = FILE_OPEN_((char *)fname, len, &fnum, access, exclus,,,options,,,);
404
err = (SETMODE(fnum, SET_FILE_OWNER, nsk_own_int) != CCE);
405
err = FILE_CLOSE_(fnum);
406
return (err != 0 ? -1 : 0);
409
/* TANDEM version of getch() - non-echo character reading */
413
short f, err, count, fnum, rlen;
416
f = (short)fileno(stdin);
419
err = (SETMODE(fnum, ECHO_MODE, 0) != CCE);
420
err = (READX(fnum, &ch, rlen, (short *) &count) != CCE);
421
err = (SETMODE(fnum, ECHO_MODE, 1) != CCE);
435
short parsename(srce, fname, ext)
440
/* As a way of supporting DOS extensions from Tandem we look for a space
441
separated extension string after the Guardian filename
442
e.g. ZIP ZIPFILE "$DATA4.TESTING.INVOICE TXT"
449
*fname = *ext = '\0'; /* set to null string */
451
fstart = (char *) srce;
453
if ((fptr = strrchr(fstart, TANDEM_EXTENSION)) != NULL) {
457
strncat(ext, fptr, _min(EXTENSION_MAX, strlen(fptr)));
459
fptr = strchr(fstart, TANDEM_EXTENSION); /* End of filename */
460
strncat(fname, fstart, _min(FILENAME_MAX, (fptr - fstart)));
463
/* just copy string */
464
strncat(fname, srce, _min(FILENAME_MAX, strlen(srce)));
470
static time_t gmt_to_time_t (gmt)
479
long long lct, lst, itime;
483
lct = CONVERTTIMESTAMP(*gmt, type,, err);
487
lst = CONVERTTIMESTAMP(*gmt, type,, err);
490
itime = (err[0] ? *gmt : lct);
491
/* If we have no DST in force then make sure we give it a value,
492
else mktime screws up if we set the isdst flag to -1 */
493
temp_tm.tm_isdst = (err[0] ? 0 : ((lct == lst) ? 0 : 1));
495
julian_dayno = INTERPRETTIMESTAMP(itime, date_time);
497
temp_tm.tm_sec = date_time[5];
498
temp_tm.tm_min = date_time[4];
499
temp_tm.tm_hour = date_time[3];
500
temp_tm.tm_mday = date_time[2];
501
temp_tm.tm_mon = date_time[1] - 1; /* C's so sad */
502
temp_tm.tm_year = date_time[0] - 1900; /* it's almost funny */
504
return (mktime(&temp_tm));
507
/* TANDEM version of stat() function */
512
#define ilist_items 26
513
#define klist_items 4
514
#define slist_items 3
515
#define ulist_items 1
516
#define flist_size 100
518
short err, i, extension;
519
char fname[FILENAME_MAX + 1];
521
char ext[EXTENSION_MAX + 1];
523
/* #0 #1 #2 #3 #4 #5 #6 #7 #8 #9 */
524
short ilist[ilist_items]={56,144, 54,142, 58, 62, 60, 41, 42, 44,
525
50, 51, 52, 61, 63, 66, 67, 70, 72, 73,
526
74, 75, 76, 77, 78, 79 };
527
short ilen[ilist_items] ={ 4, 4, 4, 2, 1, 2, 1, 1, 1, 1,
528
1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
530
short ioff[ilist_items];
532
/* #0 #1 #2 #3 #4 #5 #6 #7 #8 #9 */
533
short klist[klist_items]={45, 46, 68, 69 };
534
short klen[klist_items] ={ 1, 1, 1, 1 };
535
short koff[klist_items];
537
/* #0 #1 #2 #3 #4 #5 #6 #7 #8 #9 */
538
short slist[slist_items]={43, 80, 90 };
539
short slen[slist_items] ={ 1, 1, 1 };
540
short soff[slist_items];
542
/* #0 #1 #2 #3 #4 #5 #6 #7 #8 #9 */
543
short ulist[ulist_items]={65 };
544
short ulen[ulist_items] ={ 1 };
545
short uoff[ulist_items];
547
short flist[flist_size];
549
short *rlen=&extra[0];
550
short *err_item=&extra[1];
551
unsigned short *fowner;
552
unsigned short *fprogid;
556
nsk_file_attrs *nsk_attr;
558
short end, count, kind, level, options, searchid;
561
/* Initialise stat structure */
562
s->st_dev = _S_GUARDIANOBJECT;
566
s->st_uid = s->st_gid = 0;
568
s->st_atime = s->st_ctime = s->st_mtime = 0;
569
s->st_reserved[0] = 0;
570
s->st_reserved[1] = 0;
571
s->st_reserved[2] = 0;
572
nsk_ov = (nsk_stat_ov *)&s->st_reserved[0];
573
nsk_attr = (nsk_file_attrs *)&nsk_ov->ov.nsk_ef_region;
575
/* Check to see if name contains a (pseudo) file extension */
576
extension = parsename (n,fname,ext);
578
fnamelen = strlen(fname);
580
options = 3; /* Allow Subvols and Templates */
581
err = FILENAME_SCAN_( fname,
589
/* allow kind == 2 (DEFINE names) */
590
if (err != 0) return -1;
592
if (kind == 1 || (kind == 0 && level < 2)) {
593
/* Pattern, Subvol Name or One part Filename - lets see if it exists */
594
err = FILENAME_FINDSTART_ ( &searchid,
602
end = FILENAME_FINDFINISH_ ( searchid );
606
err = FILENAME_FINDNEXT_ ( searchid,
612
end = FILENAME_FINDFINISH_ ( searchid );
615
return -1; /* Non existing template, subvol or file */
617
if (kind == 1 || info[2] == -1) {
618
s->st_mode = S_IFDIR; /* Its an existing template or directory */
622
/* Must be a real file so drop to code below to get info on it */
625
err = FILE_GETINFOLISTBYNAME_( fname,
634
if (err != 0) return -1;
638
/* Build up table of offets into result list */
639
for (i=1; i < ilist_items; i++)
640
ioff[i] = ioff[i-1] + ilen[i-1];
642
/* Set up main stat fields */
644
/* Setup timestamps */
645
s->st_atime = gmt_to_time_t ((long long *)&flist[ioff[0]]);
646
s->st_mtime = s->st_ctime = gmt_to_time_t ((long long *)&flist[ioff[1]]);
647
nsk_ov->ov.creation_time = gmt_to_time_t ((long long *)&flist[ioff[2]]);
649
s->st_size = *(off_t *)&flist[ioff[3]];
651
fowner = (unsigned short *)&flist[ioff[4]];
652
s->st_uid = *fowner & 0x00ff;
653
s->st_gid = *fowner >> 8;
655
/* Note that Purge security (fsec[3]) in NSK has no relevance to stat() */
656
fsec = (char *)&flist[ioff[5]];
657
fprogid = (unsigned short *)&flist[ioff[6]];
659
s->st_mode = S_IFREG | /* Regular File */
660
/* Parse Read Flag */
661
((fsec[0] & 0x03) == 0x00 ? S_IROTH : 0) |
662
((fsec[0] & 0x02) == 0x00 ? S_IRGRP : 0) |
663
((fsec[0] & 0x03) != 0x03 ? S_IRUSR : 0) |
664
/* Parse Write Flag */
665
((fsec[1] & 0x03) == 0x00 ? S_IWOTH : 0) |
666
((fsec[1] & 0x02) == 0x00 ? S_IWGRP : 0) |
667
((fsec[1] & 0x03) != 0x03 ? S_IWUSR : 0) |
668
/* Parse Execute Flag */
669
((fsec[2] & 0x03) == 0x00 ? S_IXOTH : 0) |
670
((fsec[2] & 0x02) == 0x00 ? S_IXGRP : 0) |
671
((fsec[2] & 0x03) != 0x03 ? S_IXUSR : 0) |
673
(*fprogid == 1 ? (S_ISUID | S_ISGID) : 0) ;
675
/* Set up NSK additional stat fields */
676
nsk_attr->progid = (unsigned) flist[ioff[6]];
677
nsk_attr->filetype = (unsigned) flist[ioff[7]];
678
nsk_attr->filecode = (unsigned) flist[ioff[8]];
679
nsk_attr->block = (unsigned short) flist[ioff[9]];
680
nsk_attr->priext = (unsigned short) flist[ioff[10]];
681
nsk_attr->secext = (unsigned short) flist[ioff[11]];
682
nsk_attr->maxext = (unsigned short) flist[ioff[12]];
683
nsk_attr->flags.clearonpurge = (unsigned) flist[ioff[13]];
684
nsk_attr->licensed = (unsigned) flist[ioff[14]];
685
nsk_attr->flags.audited = (unsigned) flist[ioff[15]];
686
nsk_attr->flags.acompress = (unsigned) flist[ioff[16]];
687
nsk_attr->flags.refresheof = (unsigned) flist[ioff[17]];
688
nsk_attr->flags.buffered = (unsigned) (flist[ioff[18]] == 0 ? 1 : 0);
689
nsk_attr->flags.verified = (unsigned) flist[ioff[19]];
690
nsk_attr->flags.serial = (unsigned) flist[ioff[20]];
691
nsk_attr->flags.crashopen = (unsigned) flist[ioff[22]];
692
nsk_attr->flags.rollforward = (unsigned) flist[ioff[23]];
693
nsk_attr->flags.broken = (unsigned) flist[ioff[24]];
694
nsk_attr->flags.corrupt = (unsigned) flist[ioff[25]];
695
nsk_attr->fileopen = (unsigned) flist[ioff[21]];
698
if (nsk_attr->filetype == NSK_UNSTRUCTURED) {
699
/* extra info for Unstructured files */
700
err = FILE_GETINFOLISTBYNAME_( fname,
709
if (err != 0) return -1;
713
/* Build up table of offets into result list */
714
for (i=1; i < ulist_items; i++)
715
uoff[i] = uoff[i-1] + ulen[i-1];
718
/* extra info for Structured files */
719
err = FILE_GETINFOLISTBYNAME_( fname,
728
if (err != 0) return -1;
732
/* Build up table of offets into result list */
733
for (i=1; i < slist_items; i++)
734
soff[i] = soff[i-1] + slen[i-1];
736
nsk_attr->reclen = (unsigned) flist[soff[0]];
737
nsk_attr->flags.secpart = (unsigned) flist[soff[1]];
738
nsk_attr->flags.primpart = (unsigned)
739
( (flist[soff[2]] > 0 && nsk_attr->flags.secpart == 0) ? 1 : 0 );
741
if (nsk_attr->filetype == NSK_KEYSEQUENCED) {
742
/* extra info for Key Sequenced files */
743
err = FILE_GETINFOLISTBYNAME_( fname,
752
if (err != 0) return -1;
756
/* Build up table of offets into result list */
757
for (i=1; i < klist_items; i++)
758
koff[i] = koff[i-1] + klen[i-1];
760
nsk_attr->keyoff = (unsigned) flist[koff[0]];
761
nsk_attr->keylen = (unsigned) flist[koff[1]];
762
nsk_attr->flags.dcompress = (unsigned) flist[koff[2]];
763
nsk_attr->flags.icompress = (unsigned) flist[koff[3]];
771
/* TANDEM Directory processing */
773
DIR *opendir(const char *dirname)
776
char sname[FILENAME_MAX + 1];
778
char fname[FILENAME_MAX + 1];
781
short searchid, err, end;
782
struct dirent *entry;
784
char ext[EXTENSION_MAX + 1];
787
extension = parsename(dirname, sname, ext);
788
snamelen = strlen(sname);
790
/* First we work out how detailed the template is...
791
* e.g. If the template is DAVES*.* we want the search result
797
while ((p = strchr(p, TANDEM_DELIMITER)) != NULL){
803
/* Attempt to start a filename template */
804
err = FILENAME_FINDSTART_ ( &searchid,
811
end = FILENAME_FINDFINISH_(searchid);
815
/* Create DIR structure */
816
if ((dirp = malloc(sizeof(DIR))) == NULL ) {
817
end = FILENAME_FINDFINISH_(searchid);
820
dirp->D_list = dirp->D_curpos = NULL;
821
strcpy(dirp->D_path, dirname);
823
while ((err = FILENAME_FINDNEXT_(searchid,
829
/* Create space for entry */
830
if ((entry = malloc (sizeof(struct dirent))) == NULL) {
831
end = FILENAME_FINDFINISH_(searchid);
835
/* Link to last entry */
836
if (dirp->D_curpos == NULL)
837
dirp->D_list = dirp->D_curpos = entry; /* First name */
839
dirp->D_curpos->d_next = entry; /* Link */
840
dirp->D_curpos = entry;
842
/* Add directory entry */
843
*dirp->D_curpos->d_name = '\0';
844
strncat(dirp->D_curpos->d_name,fname,fnamelen);
846
strcat(dirp->D_curpos->d_name,TANDEM_EXTENSION_STR);
847
strcat(dirp->D_curpos->d_name,ext);
849
dirp->D_curpos->d_next = NULL;
852
end = FILENAME_FINDFINISH_(searchid);
854
if (err == 1) { /* Should return EOF at end of search */
855
dirp->D_curpos = dirp->D_list; /* Set current pos to start */
862
struct dirent *readdir(DIR *dirp)
866
cur = dirp->D_curpos;
867
dirp->D_curpos = dirp->D_curpos->d_next;
871
void rewinddir(DIR *dirp)
873
dirp->D_curpos = dirp->D_list;
876
int closedir(DIR *dirp)
880
while (dirp->D_list != NULL) {
882
dirp->D_list = dirp->D_list->d_next;