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