1 /*
2 Copyright (c) 1990-2002 Info-ZIP. All rights reserved.
3
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
8 */
9 /*
10 * routines common to TANDEM (ZIP and UNZIP)
11 */
12
13 #include "zip.h" /* This sets up ZIP / UNZIP define */
14
15 #include <tal.h>
16 #include "$system.zsysdefs.zsysc" nolist
17 #include <cextdecs> nolist
18 #include "tannsk.h"
19
20 static time_t gmt_to_time_t (long long *);
21
isatty(fnum)22 int isatty (fnum)
23 int fnum;
24 {
25 return 1;
26 }
27
28 /********************/
29 /* Function in2ex() */
30 /********************/
31
32 #ifdef UNZIP
33 char *in2ex(__G__ n)
34 __GDEF
35 #else
36 char *in2ex(n)
37 #endif
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. */
41 {
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 */
51
52 if ((x = malloc(strlen(n) + 4)) == NULL) /* + 4 for safety */
53 return NULL;
54
55 *x = '\0';
56
57 /* Junk pathname as requested */
58 #ifdef UNZIP
59 if (uO.jflag && (t = strrchr(n, INTERNAL_DELIMITER)) != NULL)
60 ++t;
61 else
62 t = n;
63 #endif /* UNZIP */
64 #ifdef ZIP
65 if (!pathput)
66 t = last(n, INTERNAL_DELIMITER);
67 else
68 t = n;
69 #endif /* ZIP */
70
71 allow_dollar = TRUE;
72
73 while (*t != '\0') { /* File part could be sys, vol, subvol or file */
74 if (*t == INTERNAL_DELIMITER) { /* System, Volume or Subvol Name */
75 t++;
76 if (*t == INTERNAL_DELIMITER) { /* System */
77 strcat(x, TANDEM_NODE_STR);
78 t++;
79 }
80 else {
81 strcat(x, TANDEM_DELIMITER_STR);
82 allow_dollar = FALSE;
83 }
84 }
85 /* Work out where end of current external string is */
86 y = x + strlen(x);
87
88 /* Work out substring to copy and externalise */
89 p = strchr(t, INTERNAL_DELIMITER);
90 e = strchr(t, DOS_EXTENSION);
91 if (p != NULL) {
92 if (e > p)
93 e = NULL;
94 }
95
96 z = e;
97 if (z == NULL)
98 z = p;
99 if (z == NULL)
100 z = t + strlen(t);
101
102 /* can't have Tandem name longer than 8 characters */
103 max = y + MAXFILEPARTLEN;
104
105 /* Allow $ symbol as first character in some cases */
106 if (*t == '$') {
107 if (allow_dollar)
108 *y++ = *t++;
109 else;
110 *t++;
111 }
112
113 /* Make sure first real character is alpha */
114 if (! isalpha(*t) )
115 *y++ = 'A';
116
117 /* Characters left to process */
118 len = z - t;
119
120 while ( len > 0 ) {
121 if ( isalnum(*t) ) {
122 *y++ = toupper(*t++);
123 if (y >= max)
124 break;
125 }
126 else
127 t++;
128 len--;
129 }
130 *y = '\0';
131 t = p;
132
133 if (p == NULL) {
134 /* Last part of filename, store pseudo extension if available */
135 if (e != NULL) {
136 strcat(x, TANDEM_EXTENSION_STR);
137 y = x + strlen(x);
138
139 /* no restriction on extension length as its virtual */
140 z = e + 1;
141 while ( *z != '\0' ) {
142 *y++ = toupper(*z++);
143 }
144 *y = '\0';
145 }
146 break;
147 }
148 }
149
150 return x;
151 }
152
zexit(status)153 void zexit(status)
154 int status;
155 {
156 /* Exit(>0) creates saveabend files */
157 terminate_program (0,0,(short)status,,,);
158 }
159
160 /************************/
161 /* Function zputc() */
162 /************************/
163
164 #ifdef putc
165 # undef putc
166 #endif
167
zputc(ch,fptr)168 int zputc(ch, fptr)
169 int ch;
170 FILE *fptr;
171 {
172 int err;
173 err = putc(ch,fptr);
174 fflush(fptr);
175 return err;
176 }
177 #define putc zputc
178
179 #ifdef LICENSED
180 _tal _priv short FILE_CHANGELABEL_ (
181 short, /* IN */
182 short, /* IN */
183 const short _far * /* IN */
184 );
185
186 _c _callable int changelabel OF((short, const short *, const short *));
187
changelabel(fnum,modtime,actime)188 _c _callable int changelabel(fnum, modtime, actime)
189 short fnum;
190 const short *modtime;
191 const short *actime;
192 {
193 int err;
194
195 err = FILE_CHANGELABEL_(fnum, 16, modtime);
196 if (!err)
197 err = FILE_CHANGELABEL_(fnum, 17, actime);
198 return err;
199 }
200
islicensed(void)201 int islicensed(void)
202 {
203 #define plist_items 1
204 #define plist_size 10
205
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;
212
213 err = PROCESSHANDLE_NULLIT_(myphandle);
214
215 if (!err)
216 err = PROCESS_GETINFO_(myphandle);
217
218 if (!err)
219 err = PROCESS_GETINFOLIST_(/*cpu*/,
220 /*pin*/,
221 /*nodename*/,
222 /*nodenamelen*/,
223 myphandle,
224 licensetag,
225 items,
226 licensed,
227 maxlen,
228 resultlen
229 );
230
231 if (err != 0)
232 return 0;
233 else
234 return licensed[0];
235 }
236 #endif /* LICENSED */
237
utime(file,time)238 int utime(file, time)
239 const char *file;
240 const ztimbuf *time;
241 {
242 #ifdef LICENSED
243 int result, err;
244 union timestamp_ov {
245 long long fulltime;
246 short wordtime[4];
247 };
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];
253 short extension;
254 char ext[EXTENSION_MAX + 1];
255
256 if (islicensed() ) {
257 /* Attempt to update file label */
258 modt = gmtime( &time->modtime );
259
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;
267 errormask[0] = 0;
268 lasttime.fulltime = COMPUTETIMESTAMP (datetime, errormask);
269
270 opent = gmtime( &time->actime );
271
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;
279 errormask[0] = 0;
280 opentime.fulltime = COMPUTETIMESTAMP (datetime, errormask);
281
282 /* Remove any (pseudo) file extension */
283 extension = parsename (file,fname,ext);
284 len = strlen(fname);
285
286 access = NSK_WRONLY;
287 exclus = NSK_SHARED;
288 options = NSK_NOUPDATEOPENTIME;
289
290 extension = parsename (file,fname,ext);
291 len = strlen(fname);
292
293 err = FILE_OPEN_((char *)fname, len, &fnum, access, exclus,,,options,,,);
294 result = changelabel(fnum,lasttime.wordtime,opentime.wordtime);
295 err = FILE_CLOSE_(fnum);
296 return result;
297 }
298 return -1;
299 #else /* !LICENSED */
300 return 0; /* "no error", to suppress annoying failure messages */
301 #endif /* ?LICENSED */
302 }
303
304 /* TANDEM version of chmod() function */
305
chmod(file,unix_sec)306 int chmod(file, unix_sec)
307 const char *file;
308 mode_t unix_sec;
309 {
310 FILE *stream;
311 struct nsk_sec_type {
312 unsigned progid : 1;
313 unsigned clear : 1;
314 unsigned null : 2;
315 unsigned read : 3;
316 unsigned write : 3;
317 unsigned execute: 3;
318 unsigned purge : 3;
319 };
320 union nsk_sec_ov {
321 struct nsk_sec_type bit_ov;
322 short int_ov;
323 };
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];
329
330 nsk_sec.bit_ov.progid = 0;
331 nsk_sec.bit_ov.clear = 0;
332 nsk_sec.bit_ov.null = 0;
333
334 /* 4="N", 5="C", 6="U", 7="-" */
335
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;
340
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;
345
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;
350
351 nsk_sec.bit_ov.purge = nsk_sec.bit_ov.write;
352
353 nsk_sec_int = nsk_sec.int_ov;
354
355 access = NSK_RDONLY;
356 exclus = NSK_SHARED;
357 options = NSK_NOUPDATEOPENTIME;
358
359 extension = parsename (file,fname,ext);
360 len = strlen(fname);
361
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);
365
366 return (err != 0 ? -1 : 0);
367 }
368
369 /* TANDEM version of chown() function */
370
chown(file,uid,gid)371 int chown(file, uid, gid)
372 const char *file;
373 uid_t uid;
374 gid_t gid;
375 {
376 FILE *stream;
377 struct nsk_own_type {
378 unsigned group : 8;
379 unsigned user : 8;
380 };
381 union nsk_own_ov {
382 struct nsk_own_type bit_ov;
383 short int_ov;
384 };
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];
390
391 nsk_own.bit_ov.group = gid;
392 nsk_own.bit_ov.user = uid;
393
394 nsk_own_int = nsk_own.int_ov;
395
396 access = NSK_RDONLY;
397 exclus = NSK_SHARED;
398 options = NSK_NOUPDATEOPENTIME;
399
400 extension = parsename (file,fname,ext);
401 len = strlen(fname);
402
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);
407 }
408
409 /* TANDEM version of getch() - non-echo character reading */
zgetch(void)410 int zgetch(void)
411 {
412 char ch;
413 short f, err, count, fnum, rlen;
414
415 rlen = 1;
416 f = (short)fileno(stdin);
417 fnum = fdtogfn (f);
418 #define ECHO_MODE 20
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);
422
423 if (err)
424 if (err != 1)
425 return EOF;
426 else
427 ch = 'q';
428 else
429 if (count == 0)
430 ch = '\r';
431
432 return (int)ch;
433 }
434
parsename(srce,fname,ext)435 short parsename(srce, fname, ext)
436 const char *srce;
437 char *fname;
438 char *ext;
439 {
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"
443 */
444
445 char *fstart;
446 char *fptr;
447 short extension = 0;
448
449 *fname = *ext = '\0'; /* set to null string */
450
451 fstart = (char *) srce;
452
453 if ((fptr = strrchr(fstart, TANDEM_EXTENSION)) != NULL) {
454 extension = 1;
455
456 fptr++;
457 strncat(ext, fptr, _min(EXTENSION_MAX, strlen(fptr)));
458
459 fptr = strchr(fstart, TANDEM_EXTENSION); /* End of filename */
460 strncat(fname, fstart, _min(FILENAME_MAX, (fptr - fstart)));
461 }
462 else {
463 /* just copy string */
464 strncat(fname, srce, _min(FILENAME_MAX, strlen(srce)));
465 }
466
467 return extension;
468 }
469
gmt_to_time_t(gmt)470 static time_t gmt_to_time_t (gmt)
471 long long *gmt;
472 {
473 #define GMT_TO_LCT 0
474 #define GMT_TO_LST 1
475
476 struct tm temp_tm;
477 short date_time[8];
478 long julian_dayno;
479 long long lct, lst, itime;
480 short err[1], type;
481
482 type = GMT_TO_LCT;
483 lct = CONVERTTIMESTAMP(*gmt, type,, err);
484
485 if (!err[0]) {
486 type = GMT_TO_LST;
487 lst = CONVERTTIMESTAMP(*gmt, type,, err);
488 }
489
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));
494
495 julian_dayno = INTERPRETTIMESTAMP(itime, date_time);
496
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 */
503
504 return (mktime(&temp_tm));
505 }
506
507 /* TANDEM version of stat() function */
stat(n,s)508 int stat(n, s)
509 const char *n;
510 struct stat *s;
511 {
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
517
518 short err, i, extension;
519 char fname[FILENAME_MAX + 1];
520 short fnamelen;
521 char ext[EXTENSION_MAX + 1];
522
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,
529 1, 1, 1, 1, 1, 1 };
530 short ioff[ilist_items];
531
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];
536
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];
541
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];
546
547 short flist[flist_size];
548 short extra[2];
549 short *rlen=&extra[0];
550 short *err_item=&extra[1];
551 unsigned short *fowner;
552 unsigned short *fprogid;
553 char *fsec;
554
555 nsk_stat_ov *nsk_ov;
556 nsk_file_attrs *nsk_attr;
557
558 short end, count, kind, level, options, searchid;
559 short info[5];
560
561 /* Initialise stat structure */
562 s->st_dev = _S_GUARDIANOBJECT;
563 s->st_ino = 0;
564 s->st_nlink = 0;
565 s->st_rdev = 0;
566 s->st_uid = s->st_gid = 0;
567 s->st_size = 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;
574
575 /* Check to see if name contains a (pseudo) file extension */
576 extension = parsename (n,fname,ext);
577
578 fnamelen = strlen(fname);
579
580 options = 3; /* Allow Subvols and Templates */
581 err = FILENAME_SCAN_( fname,
582 fnamelen,
583 &count,
584 &kind,
585 &level,
586 options
587 );
588
589 /* allow kind == 2 (DEFINE names) */
590 if (err != 0) return -1;
591
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,
595 fname,
596 fnamelen,
597 ,
598 DISK_DEVICE
599 );
600
601 if (err != 0) {
602 end = FILENAME_FINDFINISH_ ( searchid );
603 return -1;
604 }
605
606 err = FILENAME_FINDNEXT_ ( searchid,
607 fname,
608 FILENAME_MAX,
609 &fnamelen,
610 info
611 );
612 end = FILENAME_FINDFINISH_ ( searchid );
613
614 if (err != 0)
615 return -1; /* Non existing template, subvol or file */
616
617 if (kind == 1 || info[2] == -1) {
618 s->st_mode = S_IFDIR; /* Its an existing template or directory */
619 return 0;
620 }
621
622 /* Must be a real file so drop to code below to get info on it */
623 }
624
625 err = FILE_GETINFOLISTBYNAME_( fname,
626 fnamelen,
627 ilist,
628 ilist_items,
629 flist,
630 flist_size,
631 rlen,
632 err_item
633 );
634 if (err != 0) return -1;
635
636 ioff[0] = 0;
637
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];
641
642 /* Set up main stat fields */
643
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]]);
648
649 s->st_size = *(off_t *)&flist[ioff[3]];
650
651 fowner = (unsigned short *)&flist[ioff[4]];
652 s->st_uid = *fowner & 0x00ff;
653 s->st_gid = *fowner >> 8;
654
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]];
658
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) |
672 /* Parse Progid */
673 (*fprogid == 1 ? (S_ISUID | S_ISGID) : 0) ;
674
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]];
696
697
698 if (nsk_attr->filetype == NSK_UNSTRUCTURED) {
699 /* extra info for Unstructured files */
700 err = FILE_GETINFOLISTBYNAME_( fname,
701 fnamelen,
702 ulist,
703 ulist_items,
704 flist,
705 flist_size,
706 rlen,
707 err_item
708 );
709 if (err != 0) return -1;
710
711 uoff[0] = 0;
712
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];
716 }
717 else {
718 /* extra info for Structured files */
719 err = FILE_GETINFOLISTBYNAME_( fname,
720 fnamelen,
721 slist,
722 slist_items,
723 flist,
724 flist_size,
725 rlen,
726 err_item
727 );
728 if (err != 0) return -1;
729
730 soff[0] = 0;
731
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];
735
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 );
740
741 if (nsk_attr->filetype == NSK_KEYSEQUENCED) {
742 /* extra info for Key Sequenced files */
743 err = FILE_GETINFOLISTBYNAME_( fname,
744 fnamelen,
745 klist,
746 klist_items,
747 flist,
748 flist_size,
749 rlen,
750 err_item
751 );
752 if (err != 0) return -1;
753
754 koff[0] = 0;
755
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];
759
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]];
764 }
765 }
766
767 return 0;
768 }
769
770 #ifndef SFX
771 /* TANDEM Directory processing */
772
opendir(const char * dirname)773 DIR *opendir(const char *dirname)
774 {
775 short i, resolve;
776 char sname[FILENAME_MAX + 1];
777 short snamelen;
778 char fname[FILENAME_MAX + 1];
779 short fnamelen;
780 char *p;
781 short searchid, err, end;
782 struct dirent *entry;
783 DIR *dirp;
784 char ext[EXTENSION_MAX + 1];
785 short extension;
786
787 extension = parsename(dirname, sname, ext);
788 snamelen = strlen(sname);
789
790 /* First we work out how detailed the template is...
791 * e.g. If the template is DAVES*.* we want the search result
792 * in the same format
793 */
794
795 p = sname;
796 i = 0;
797 while ((p = strchr(p, TANDEM_DELIMITER)) != NULL){
798 i++;
799 p++;
800 };
801 resolve = 2 - i;
802
803 /* Attempt to start a filename template */
804 err = FILENAME_FINDSTART_ ( &searchid,
805 sname,
806 snamelen,
807 resolve,
808 DISK_DEVICE
809 );
810 if (err != 0) {
811 end = FILENAME_FINDFINISH_(searchid);
812 return NULL;
813 }
814
815 /* Create DIR structure */
816 if ((dirp = malloc(sizeof(DIR))) == NULL ) {
817 end = FILENAME_FINDFINISH_(searchid);
818 return NULL;
819 }
820 dirp->D_list = dirp->D_curpos = NULL;
821 strcpy(dirp->D_path, dirname);
822
823 while ((err = FILENAME_FINDNEXT_(searchid,
824 fname,
825 FILENAME_MAX,
826 &fnamelen
827 )
828 ) == 0 ){
829 /* Create space for entry */
830 if ((entry = malloc (sizeof(struct dirent))) == NULL) {
831 end = FILENAME_FINDFINISH_(searchid);
832 return NULL;
833 }
834
835 /* Link to last entry */
836 if (dirp->D_curpos == NULL)
837 dirp->D_list = dirp->D_curpos = entry; /* First name */
838 else {
839 dirp->D_curpos->d_next = entry; /* Link */
840 dirp->D_curpos = entry;
841 };
842 /* Add directory entry */
843 *dirp->D_curpos->d_name = '\0';
844 strncat(dirp->D_curpos->d_name,fname,fnamelen);
845 if (extension) {
846 strcat(dirp->D_curpos->d_name,TANDEM_EXTENSION_STR);
847 strcat(dirp->D_curpos->d_name,ext);
848 };
849 dirp->D_curpos->d_next = NULL;
850 };
851
852 end = FILENAME_FINDFINISH_(searchid);
853
854 if (err == 1) { /* Should return EOF at end of search */
855 dirp->D_curpos = dirp->D_list; /* Set current pos to start */
856 return dirp;
857 }
858 else
859 return NULL;
860 }
861
readdir(DIR * dirp)862 struct dirent *readdir(DIR *dirp)
863 {
864 struct dirent *cur;
865
866 cur = dirp->D_curpos;
867 dirp->D_curpos = dirp->D_curpos->d_next;
868 return cur;
869 }
870
rewinddir(DIR * dirp)871 void rewinddir(DIR *dirp)
872 {
873 dirp->D_curpos = dirp->D_list;
874 }
875
closedir(DIR * dirp)876 int closedir(DIR *dirp)
877 {
878 struct dirent *node;
879
880 while (dirp->D_list != NULL) {
881 node = dirp->D_list;
882 dirp->D_list = dirp->D_list->d_next;
883 free( node );
884 }
885 free( dirp );
886 return 0;
887 }
888
889 #endif /* !SFX */
890