Subversion Repositories Kolibri OS

Rev

Blame | Last modification | View Log | Download | RSS feed

  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.  
  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.  
  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.  
  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.  
  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.  
  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.  
  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.  
  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.  
  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 */
  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.  
  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.  
  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 */
  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.  
  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.  
  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.  
  871. void rewinddir(DIR *dirp)
  872. {
  873.    dirp->D_curpos = dirp->D_list;
  874. }
  875.  
  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.