home *** CD-ROM | disk | FTP | other *** search
/ ftp.wwiv.com / ftp.wwiv.com.zip / ftp.wwiv.com / pub / DOOR / BD2K260A.ZIP / SRC.ZIP / SRC / FILE_DOS.C < prev    next >
C/C++ Source or Header  |  1998-10-03  |  26KB  |  989 lines

  1. /*--------------------------------------------------------------------------*/
  2. /*                                                                          */
  3. /*                                                                          */
  4. /*      ------------         Bit-Bucket Software, Co.                       */
  5. /*      \ 10001101 /         Writers and Distributors of                    */
  6. /*       \ 011110 /          Freely Available<tm> Software.                 */
  7. /*        \ 1011 /                                                          */
  8. /*         ------                                                           */
  9. /*                                                                          */
  10. /*              (C) Copyright 1987-96, Bit Bucket Software Co.              */
  11. /*                                                                          */
  12. /*                This module was written by Vince Perriello                */
  13. /*                   OS/2 code contributed by Bill Andrus                   */
  14. /*            DOS and OS/2 File I/O routines used by BinkleyTerm            */
  15. /*                                                                          */
  16. /*                                                                          */
  17. /*    For complete  details  of the licensing restrictions, please refer    */
  18. /*    to the License  agreement,  which  is published in its entirety in    */
  19. /*    the MAKEFILE and BT.C, and also contained in the file LICENSE.260.    */
  20. /*                                                                          */
  21. /*    USE  OF THIS FILE IS SUBJECT TO THE  RESTRICTIONS CONTAINED IN THE    */
  22. /*    BINKLEYTERM  LICENSING  AGREEMENT.  IF YOU DO NOT FIND THE TEXT OF    */
  23. /*    THIS  AGREEMENT IN ANY OF THE  AFOREMENTIONED FILES,  OR IF YOU DO    */
  24. /*    NOT HAVE THESE FILES,  YOU  SHOULD  IMMEDIATELY CONTACT BIT BUCKET    */
  25. /*    SOFTWARE CO.  AT ONE OF THE  ADDRESSES  LISTED BELOW.  IN NO EVENT    */
  26. /*    SHOULD YOU  PROCEED TO USE THIS FILE  WITHOUT HAVING  ACCEPTED THE    */
  27. /*    TERMS  OF  THE  BINKLEYTERM  LICENSING  AGREEMENT,  OR  SUCH OTHER    */
  28. /*    AGREEMENT AS YOU ARE ABLE TO REACH WITH BIT BUCKET SOFTWARE, CO.      */
  29. /*                                                                          */
  30. /*                                                                          */
  31. /* You can contact Bit Bucket Software Co. at any one of the following      */
  32. /* addresses:                                                               */
  33. /*                                                                          */
  34. /* Bit Bucket Software Co.        FidoNet  1:104/501, 1:343/491             */
  35. /* P.O. Box 460398                AlterNet 7:42/1491                        */
  36. /* Aurora, CO 80046               BBS-Net  86:2030/1                        */
  37. /*                                Internet f491.n343.z1.fidonet.org         */
  38. /*                                                                          */
  39. /* Please feel free to contact us at any time to share your comments about  */
  40. /* our software and/or licensing policies.                                  */
  41. /*                                                                          */
  42. /*--------------------------------------------------------------------------*/
  43.  
  44. /* Include this file before any other includes or defines! */
  45.  
  46. #include "includes.h"
  47.  
  48. #ifdef NEED_MKTEMP
  49. char *
  50. mktemp (char *template)
  51. {
  52.     static char save[8] = "Z";
  53.     char *p;
  54.     int i;
  55.  
  56.     p = save;
  57.  
  58.     if (*p == 'Z')
  59.         sprintf (p, "%06d", TaskNumber);
  60.     while (*p)
  61.     {
  62.         if (isdigit (*p))
  63.         {
  64.             *p = 'a';
  65.             break;
  66.         }
  67.         if (*p++ < 'z')
  68.         {
  69.             break;
  70.         }
  71.     }
  72.     if ((*p == '\0') || ((i = strlen (template)) < 6))
  73.         return (NULL);
  74.     strcpy (&template[i - 6], save);
  75.     return (template);
  76. }
  77. #endif
  78.  
  79. #ifdef NEED_DOSREAD
  80. #ifdef _WIN32
  81. int 
  82. _dos_read (int fd, void far * buf, unsigned nbytes, unsigned int *bytes_read)
  83. {
  84.     *bytes_read = read (fd, buf, nbytes);
  85.     return (*bytes_read == nbytes) ? 0 : -1;
  86. }
  87.  
  88. int 
  89. _dos_write (int fd, void far * buf, unsigned nbytes, unsigned int *bytes_read)
  90. {
  91.     *bytes_read = write (fd, buf, nbytes);
  92.     return (*bytes_read == nbytes) ? 0 : -1;
  93. }
  94. #endif
  95. #ifdef DOS16
  96. int 
  97. _dos_read (int fd, void far * buf, unsigned nbytes, unsigned int *bytes_read)
  98. {
  99.     union REGS regs;
  100.     struct SREGS sregs;
  101.  
  102.     regs.h.ah = 0x3f;            /* read file */
  103.     regs.x.bx = fd;
  104.     regs.x.cx = nbytes;
  105.     regs.x.dx = FP_OFF (buf);
  106.     sregs.ds = FP_SEG (buf);
  107.     *bytes_read = intdosx (®s, ®s, &sregs);
  108.     return regs.x.cflag ? -1 : 0;
  109. }
  110.  
  111. int 
  112. _dos_write (int fd, void far * buf, unsigned nbytes, unsigned int *bytes_read)
  113. {
  114.     union REGS regs;
  115.     struct SREGS sregs;
  116.  
  117.     regs.h.ah = 0x40;            /* write file */
  118.     regs.x.bx = fd;
  119.     regs.x.cx = nbytes;
  120.     regs.x.dx = FP_OFF (buf);
  121.     sregs.ds = FP_SEG (buf);
  122.     *bytes_read = intdosx (®s, ®s, &sregs);
  123.     return regs.x.cflag ? -1 : 0;
  124. }
  125. #endif
  126. #endif
  127.  
  128. /* For Borland C++ 2.0, change __TURBOC_OLD__ to __TURBOC__ */
  129. #ifdef __TURBOC_OLD__
  130. /*
  131.  * utime function for Turbo / Borland C.
  132.  *
  133.  * We should make this more generic in case some other DOS
  134.  * compiler comes up lacking, but for now the only one we
  135.  * have that needs it happens to be Borland.
  136.  *
  137.  */
  138.  
  139. int cdecl
  140. utime (char *name, struct utimbuf *times)
  141. {
  142.     int handle;
  143.     struct date d;
  144.     struct time t;
  145.     struct ftime ft;
  146.  
  147.     /* [Y2K] Ok as is.  Turbo C, circa 1988, returns the proper
  148.      * values for the year 2000.  Microsoft Windows 98, circa 1998,
  149.      * often does not.
  150.      */
  151.     unixtodos (times->modtime, &d, &t);
  152.     ft.ft_tsec = t.ti_sec / 2;
  153.     ft.ft_min = t.ti_min;
  154.     ft.ft_hour = t.ti_hour;
  155.     ft.ft_day = d.da_day;
  156.     ft.ft_month = d.da_mon;
  157.  
  158.     /* [Y2K] Ok as is.  setftime() is passed year-1980, or 20 for
  159.      * the year 2000.  When passed 20, it writes a file date of
  160.      * 2000 (which looks like 00 in a directory listing).  Verified
  161.      * with a disk hex editor.
  162.      */
  163.     ft.ft_year = d.da_year - 1980;
  164.     if ((handle = open (name, O_RDONLY)) == -1)
  165.         return -1;
  166.  
  167.     setftime (handle, &ft);
  168.     close (handle);
  169.     return 0;
  170. }
  171. #endif
  172.  
  173. int
  174. dexists (char *filename)
  175. {
  176.     struct stat stbuf;
  177.  
  178.     return (stat (filename, &stbuf) != -1) ? 1 : 0;
  179. }
  180.  
  181. int
  182. got_error (char *string1, char *string2)
  183. {
  184.     if (errno == 0x18)
  185.         errno = 0;
  186.     if (errno != 0)
  187.     {
  188.         status_line ("%s %d, %s %s %s", MSG_TXT (M_ERROR), errno, MSG_TXT (M_CANT), string1, string2);
  189.         errno = 0;
  190.         return (1);
  191.     }
  192.     return (0);
  193. }
  194.  
  195. /* Z F R E E -- Return total number of free bytes on drive specified */
  196.  
  197. #ifdef DOS16
  198. long
  199. zfree (char *drive)
  200. {
  201.     union REGS r;
  202.  
  203.     unsigned char driveno;
  204.     long stat;
  205.  
  206.     if (drive[0] != '\0' && drive[1] == ':')
  207.     {
  208.         driveno = (unsigned char) (islower (*drive) ? toupper (*drive) : *drive);
  209.         driveno = (unsigned char) (driveno - 'A' + 1);
  210.     }
  211.     else
  212.         driveno = 0;            /* Default drive    */
  213.  
  214.     r.x.ax = 0x3600;            /* get free space   */
  215.     r.h.dl = driveno;            /* on this drive    */
  216.     (void) int86 (0x21, &r, &r);/* go do it         */
  217.  
  218.     if (r.x.ax == 0xffff)        /* error return??   */
  219.         return (0);
  220.  
  221.     stat = (long) r.x.bx        /* bx = clusters avail  */
  222.         * (long) r.x.ax            /* ax = sectors/clust   */
  223.         * (long) r.x.cx;        /* cx = bytes/sector    */
  224.  
  225.     return (stat);
  226.  
  227. }
  228. #endif                            /* DOS16 */
  229.  
  230. #ifdef OS_2
  231. long
  232. zfree (char *path)
  233. {
  234.     int drive;
  235.     FSALLOCATE dt;
  236.  
  237.     if (*path != '\0' && path[1] == ':')
  238.         drive = tolower (*path) - 'a' + 1;
  239.     else
  240.         drive = 0;
  241.     DosQFSInfo ((USHORT) drive, 1, (unsigned char far *) &dt, sizeof (FSALLOCATE));
  242.     return (dt.cSectorUnit * dt.cUnitAvail * dt.cbSector);
  243. }
  244. #endif
  245.  
  246. #ifdef _WIN32
  247. long
  248. zfree (char *drive)
  249. {
  250.     unsigned driveno;
  251.     struct _diskfree_t diskinfo;
  252.     long stat;
  253.  
  254.     if (drive[0] != '\0' && drive[1] == ':')
  255.     {
  256.         driveno = (unsigned) (islower (*drive) ? toupper (*drive) : *drive);
  257.         driveno = (unsigned) (driveno - 'A' + 1);
  258.     }
  259.     else
  260.         driveno = 0;            /* Default drive    */
  261.  
  262.     if (_getdiskfree (driveno, &diskinfo) != 0)
  263.         return 0;
  264.  
  265.     stat = diskinfo.avail_clusters
  266.         * diskinfo.sectors_per_cluster
  267.         * diskinfo.bytes_per_sector;
  268.  
  269.     return (stat);
  270. }
  271. #endif                            /* _WIN32 */
  272.  
  273. static int share_flags[] =
  274. {
  275. #ifdef SH_COMPAT
  276.     SH_COMPAT,
  277. #else
  278.     0,
  279. #endif
  280.     SH_DENYNO,
  281.     SH_DENYRD,
  282.     SH_DENYRW,
  283.     SH_DENYWR
  284. };
  285.  
  286. int 
  287. share_open (char *filename, int oflag, int shflag)
  288. {
  289. #ifdef DOS16
  290.     if ((no_sharing == 0) && (_osmajor >= 3))
  291. #else
  292.     if (no_sharing == 0)
  293. #endif /* DOS16 */
  294.         return (sopen (filename, oflag, share_flags[shflag]));
  295.     else
  296.         return (open (filename, oflag));
  297.  
  298. }
  299.  
  300. FILE *
  301. share_fopen (char *filename, char *mode, int shflag)
  302. {
  303. #ifdef MUST_FDOPEN
  304.     int fd;
  305.     int open_mode;
  306.     char c, *p;
  307.     int sflag = S_IREAD | S_IWRITE;
  308.     FILE *stream;
  309.  
  310. /*
  311.  *  Microsoft made this easy for us. They gave us a stream-open
  312.  *  function that supports file sharing. Borland was not so kind.
  313.  *  So -- what we do here is open the file using the only sharing
  314.  *  API they provide -- that gives us a file handle -- then we
  315.  *  use fdopen to get a file stream out of it. Sheesh!
  316.  *
  317.  *  Of course, Microsoft 5.1 provides about the same level of
  318.  *  support as Borland -- almost. They explicitly warn you not
  319.  *  to do this neat thing I did for Borland. So I get no sharing
  320.  *  support for fopen() under 5.1. Double sheesh!
  321.  */
  322.     if ((no_sharing == 0) && (_osmajor >= 3))
  323.     {
  324.  
  325.         /* Figure out the translation from fopen-mode to
  326.            open-mode... */
  327.  
  328.         p = mode;
  329.         c = *p++;
  330.         if (c == 'w')
  331.             open_mode = O_CREAT | O_RDWR;
  332.         else if (c == 'r')
  333.             open_mode = O_RDONLY;
  334.         else if (c == 'a')
  335.             open_mode = O_CREAT | O_RDWR | O_APPEND;
  336.         else
  337.             return (FILE *) NULL;
  338.         while (*p)
  339.         {
  340.             c = *p++;
  341.             if (c == 't')
  342.                 open_mode = (open_mode & ~O_BINARY) | O_TEXT;
  343.             if (c == 'b')
  344.                 open_mode = (open_mode & ~O_TEXT) | O_BINARY;
  345.             if (c == '+')
  346.             {
  347.                 if ((open_mode & (O_RDONLY | O_WRONLY | O_RDWR)) == O_RDONLY)
  348.                 {
  349.                     open_mode = (open_mode & ~O_RDONLY) | O_RDWR;
  350.                 }
  351.                 else if (!(open_mode & O_APPEND))
  352.                     open_mode |= O_TRUNC;
  353.             }
  354.         }
  355.  
  356.         /* Open the file handle */
  357.  
  358. #ifdef    SHARE_SOPEN
  359.         fd = sopen (filename, open_mode, share_flags[shflag], sflag);
  360. #else
  361.         fd = open (filename, open_mode | share_flags[shflag], sflag);
  362. #endif
  363.         if (fd == -1)
  364.             return (FILE *) NULL;
  365.  
  366.         /* Got the handle, make the stream */
  367.  
  368.         if ((stream = fdopen (fd, mode)) == (FILE *) NULL)
  369.             (void) close (fd);
  370.         return (stream);
  371.     }
  372.     else
  373. #else
  374. #ifndef CANT_FSOPEN
  375. #ifdef DOS16
  376.     if ((no_sharing == 0) && (_osmajor >= 3))
  377. #else
  378.     if (no_sharing == 0)
  379. #endif /* DOS16 */
  380.         return (_fsopen (filename, mode, share_flags[shflag]));
  381.     else
  382. #else
  383.     happy_compiler = shflag;    /* Makes the compiler happy */
  384. #endif
  385. #endif
  386.     return (fopen (filename, mode));
  387. }
  388.  
  389. #ifdef DOS16
  390. int
  391. dfind (struct FILEINFO *dta, char *name, int times)
  392. {
  393.     union REGS r;
  394.     struct SREGS s;
  395.     char far *dtaptr = (char *) dta;
  396.     char far *nameptr = (char *) name;
  397.  
  398.     s.ds = FP_SEG (dtaptr);
  399.     r.x.dx = FP_OFF (dtaptr);
  400.     r.h.ah = 0x1a;
  401.     (void) intdosx (&r, &r, &s);
  402.     r.x.bx = 0;
  403.     r.x.cx = (unsigned int) ~0x08;
  404.     s.ds = FP_SEG (nameptr);
  405.     r.x.dx = FP_OFF (nameptr);
  406.     r.x.si = 0;
  407.     r.x.di = 0;
  408.     if (times == 0)
  409.     {
  410.         r.h.ah = 0x4e;
  411.         (void) intdosx (&r, &r, &s);
  412.         dta->nill = '\0';
  413.         /* If not found or a character device (e.g. "COM1") */
  414.         if ((r.x.cflag != 0) || ((dta->attr & 0x40) != 0))
  415.         {
  416.             dta->name[0] = '\0';
  417.             return (1);
  418.         }
  419.         return (0);
  420.     }
  421.     else if (times == 1)
  422.     {
  423.         r.h.ah = 0x4f;
  424.         (void) intdosx (&r, &r, &s);
  425.         dta->nill = '\0';
  426.         /* If not found or a character device (e.g. "COM1") */
  427.         if ((r.x.cflag != 0) || ((dta->attr & 0x40) != 0))
  428.         {
  429.             dta->name[0] = '\0';
  430.             return (1);
  431.         }
  432.         return (0);
  433.     }
  434.     else
  435.         return (0);
  436. }
  437.  
  438. #endif                            /* DOS16 */
  439.  
  440. #ifdef OS_2
  441. #ifndef __32BIT__
  442.  
  443. static int dir_findfirst (char far *, int, struct FILEINFO *);
  444. static int dir_findnext (struct FILEINFO *);
  445. static int dir_findrelease (struct FILEINFO *);
  446.  
  447. int
  448. dfind (struct FILEINFO *dta, char *name, int times)
  449. {
  450.     if (times == 0)
  451.     {
  452.         return (dir_findfirst (name, 0x37, dta));
  453.     }
  454.     else if (times == 1)
  455.     {
  456.         return (dir_findnext (dta));
  457.     }
  458.     else
  459.         return (dir_findrelease (dta));
  460. }
  461.  
  462. /*--------------------------------------------------------------------------*/
  463. /* Static variable definitions                                              */
  464. /*--------------------------------------------------------------------------*/
  465.  
  466. struct FileTimeBuf
  467. {
  468.     unsigned short c_date;        /* date of file creation */
  469.     unsigned short c_time;        /* time of file creation */
  470.     unsigned short a_date;        /* date of last access   */
  471.     unsigned short a_time;        /* time of last access   */
  472.     unsigned short w_date;        /* date of last write    */
  473.     unsigned short w_time;        /* time of last write    */
  474. };
  475.  
  476. static struct FileTimeBuf TimeBuf;
  477.  
  478. struct FileInfo
  479. {
  480.     USHORT hDir;
  481.     char rsvd[19];
  482.     char attrib;
  483.     unsigned short wr_date;
  484.     unsigned short wr_time;
  485.     long size;
  486.     char name[13];
  487.     char nill;
  488. };
  489.  
  490. struct FileFindBuf
  491. {
  492.     unsigned short create_date;    /* date of file creation */
  493.     unsigned short create_time;    /* time of file creation */
  494.     unsigned short access_date;    /* date of last access */
  495.     unsigned short access_time;    /* time of last access */
  496.     unsigned short wr_date;        /* date of last write */
  497.     unsigned short wr_time;        /* time of last write */
  498.     unsigned long size;            /* file size (end of data) */
  499.     unsigned long falloc_size;    /* file allocated size */
  500.     unsigned short attrib;        /* attributes of the file */
  501.     unsigned char string_len;    /* returned length of ascii name str. */
  502.     /* length does not include null byte */
  503.     char name[255];                /* name string */
  504. };
  505.  
  506. static struct FileFindBuf InfoBuf;
  507.  
  508. /*--------------------------------------------------------------------------*/
  509. /* Locally defined globals                                                  */
  510. /*--------------------------------------------------------------------------*/
  511.  
  512. struct FileInfo *dtap;
  513. HDIR hDirA;
  514. USHORT cSearch;
  515. USHORT usAttrib;
  516. USHORT findrc;
  517.  
  518. /*--------------------------------------------------------------------------*/
  519. /* Local constants                                                          */
  520. /*--------------------------------------------------------------------------*/
  521.  
  522. #define FILENAMELEN 13
  523.  
  524. static int 
  525. dir_findfirst (char far * filename, int attribute, struct FILEINFO *dta)
  526. {
  527.  
  528.     cSearch = 1;
  529.     dtap = (struct FileInfo *) dta;
  530.     hDirA = dtap->hDir;
  531.     usAttrib = (USHORT) attribute;
  532.  
  533.     if ((hDirA != 0xffff) && (hDirA != 0x0000))
  534.         (void) DosFindClose (hDirA);
  535.  
  536.     hDirA = 0xffff;
  537.  
  538.     findrc = DosFindFirst ((PSZ) filename
  539.         ,&hDirA
  540.         ,usAttrib
  541.         ,(PFILEFINDBUF) & InfoBuf
  542.         ,(USHORT)(sizeof (InfoBuf)) * cSearch
  543.         ,&cSearch
  544.         ,(ULONG) NULL);
  545.     if ((cSearch != 1) || (findrc && (findrc != ERROR_EAS_DIDNT_FIT)))
  546.     {
  547.         (void) DosFindClose (hDirA);
  548.         dtap->hDir = 0xffff;
  549.         errno = ENOENT;
  550.         return (1);
  551.     }
  552.     else
  553.     {
  554.         dtap->wr_date = InfoBuf.wr_date;
  555.         dtap->wr_time = InfoBuf.wr_time;
  556.         dtap->attrib = (char) InfoBuf.attrib;
  557.         dtap->size = InfoBuf.size / ((_osmajor == 10) ? 2 : 1);
  558.         strcpy (dtap->name, InfoBuf.name);
  559.         (void) strupr (dtap->name);
  560.         dtap->hDir = hDirA;
  561.         errno = 0;
  562.         return (0);
  563.     }
  564. }
  565.  
  566. static int 
  567. dir_findnext (struct FILEINFO *dta)
  568. {
  569.  
  570.     cSearch = 1;
  571.     dtap = (struct FileInfo *) dta;
  572.     hDirA = dtap->hDir;
  573.  
  574.     findrc = DosFindNext (hDirA
  575.         ,(PFILEFINDBUF) & InfoBuf
  576.         ,(USHORT) (sizeof (InfoBuf)) * cSearch
  577.         ,&cSearch);
  578.  
  579.     if ((cSearch != 1) || (findrc && (findrc != ERROR_EAS_DIDNT_FIT)))
  580.     {
  581.         (void) DosFindClose (hDirA);
  582.         dtap->hDir = 0xffff;
  583.         errno = ENOENT;
  584.         return (1);
  585.     }
  586.     else
  587.     {
  588.         dtap->wr_date = InfoBuf.wr_date;
  589.         dtap->wr_time = InfoBuf.wr_time;
  590.         dtap->attrib = (char) InfoBuf.attrib;
  591.         dtap->size = InfoBuf.size / ((_osmajor == 10) ? 2 : 1);
  592.         strcpy (dtap->name, InfoBuf.name);
  593.         (void) strupr (dtap->name);
  594.         dtap->hDir = hDirA;
  595.         errno = 0;
  596.         return (0);
  597.     }
  598. }
  599.  
  600. static int 
  601. dir_findrelease (struct FILEINFO *dta)
  602. {
  603.     dtap = (struct FileInfo *) dta;
  604.     hDirA = dtap->hDir;
  605.  
  606.     if (hDirA != 0xffff)
  607.     {
  608.         (void) DosFindClose (hDirA);
  609.         dtap->hDir = 0xffff;
  610.         errno = ENOENT;
  611.         return (1);
  612.     }
  613.     else
  614.         return (0);
  615. }
  616.  
  617. void 
  618. set_fileinfo (int fh, unsigned date, unsigned time)
  619. {
  620.  
  621.     if ((time / 2048) < (unsigned) (TIMEZONE / 3600L))
  622.     {
  623.         TimeBuf.a_date = TimeBuf.w_date = TimeBuf.c_date = date - 1;
  624.         TimeBuf.c_time = time + ((unsigned) (86400 - ((unsigned) (TIMEZONE / 3600L) * 2048)));
  625.         TimeBuf.a_time = TimeBuf.w_time = TimeBuf.c_time;
  626.     }
  627.     else
  628.     {
  629.         TimeBuf.a_date = TimeBuf.w_date = TimeBuf.c_date = date;
  630.         TimeBuf.c_time = time - ((unsigned) (TIMEZONE / 3600L) * 2048);
  631.         TimeBuf.a_time = TimeBuf.w_time = TimeBuf.c_time;
  632.     }
  633.     (void) DosSetFileInfo ((HFILE) fh,
  634.         (USHORT) 1,
  635.         (PBYTE) & TimeBuf,
  636.         (USHORT) 12);
  637. }
  638.  
  639. #else                            /* ifndef __32BIT__ */
  640.  
  641. static int dir_findfirst (char far *, int, struct FILEINFO *);
  642. static int dir_findnext (struct FILEINFO *);
  643. static int dir_findrelease (struct FILEINFO *);
  644.  
  645. int 
  646. dfind (struct FILEINFO *dta, char *name, int times)
  647. {
  648.     if (times == 0)
  649.     {
  650.         return (dir_findfirst (name, 0x37, dta));
  651.     }
  652.     else if (times == 1)
  653.     {
  654.         return (dir_findnext (dta));
  655.     }
  656.     else
  657.         return (dir_findrelease (dta));
  658. }
  659.  
  660. /*--------------------------------------------------------------------------*/
  661. /* Static variable definitions                                              */
  662. /*--------------------------------------------------------------------------*/
  663.  
  664. struct FileTimeBuf
  665. {
  666.     unsigned short c_date;        /* date of file creation */
  667.     unsigned short c_time;        /* time of file creation */
  668.     unsigned short a_date;        /* date of last access   */
  669.     unsigned short a_time;        /* time of last access   */
  670.     unsigned short w_date;        /* date of last write    */
  671.     unsigned short w_time;        /* time of last write    */
  672. };
  673.  
  674. static struct FileTimeBuf TimeBuf;
  675.  
  676. struct FileInfo
  677. {
  678.     unsigned short hDir;
  679.     char rsvd[19];
  680.     char attrib;
  681.     unsigned short wr_date;
  682.     unsigned short wr_time;
  683.     ULONG size;
  684.     char name[13];
  685.     char nill;
  686. };
  687.  
  688. struct FileFindBuf
  689. {
  690.     ULONG nDir;                    /* pointer to next structure */
  691.     unsigned short create_date;    /* date of file creation */
  692.     unsigned short create_time;    /* time of file creation */
  693.     unsigned short access_date;    /* date of last access */
  694.     unsigned short access_time;    /* time of last access */
  695.     unsigned short wr_date;        /* date of last write */
  696.     unsigned short wr_time;        /* time of last write */
  697.     ULONG size;                    /* file size (end of data) */
  698.     ULONG falloc_size;            /* file allocated size */
  699.     ULONG attrib;                /* attributes of the file */
  700.     UCHAR string_len;            /* returned length of ascii name str. */
  701.     /* length does not include null byte */
  702.     char name[CCHMAXPATHCOMP];    /* name string */
  703. };
  704.  
  705. static struct FileFindBuf InfoBuf;
  706.  
  707. /*--------------------------------------------------------------------------*/
  708. /* Locally defined globals                                                  */
  709. /*--------------------------------------------------------------------------*/
  710.  
  711. struct FileInfo *dtap;
  712. HDIR hDirA;
  713. ULONG cSearch;
  714. ULONG usAttrib;
  715. ULONG infolevel;
  716. APIRET findrc;
  717.  
  718. /*--------------------------------------------------------------------------*/
  719. /* Local constants                                                          */
  720. /*--------------------------------------------------------------------------*/
  721.  
  722. #define FILENAMELEN 13
  723.  
  724. static int 
  725. dir_findfirst (char far * filename, int attribute, struct FILEINFO *dta)
  726. {
  727.  
  728.     cSearch = 1;
  729.     dtap = (struct FileInfo *) dta;
  730.     hDirA = dtap->hDir;
  731.     usAttrib = (USHORT) attribute;
  732.     infolevel = 1;
  733.  
  734.     if ((hDirA != 0xffff) && (hDirA != 0x0000) && (hDirA != 0xffffffff))
  735.         (void) DosFindClose (hDirA);
  736.  
  737.     hDirA = 0xffffffff;
  738.  
  739.     findrc = DosFindFirst ((PSZ) filename
  740.         ,&hDirA
  741.         ,usAttrib
  742.         ,(PVOID) & InfoBuf
  743.         ,(ULONG) (sizeof (InfoBuf) * cSearch)
  744.         ,&cSearch
  745.         ,infolevel);
  746.  
  747.     if ((cSearch != 1) || (findrc && (findrc != ERROR_EAS_DIDNT_FIT)))
  748.     {
  749.         (void) DosFindClose (hDirA);
  750.         dtap->hDir = 0xffff;
  751.         errno = ENOENT;
  752.         return (1);
  753.     }
  754.     else
  755.     {
  756.         dtap->wr_date = InfoBuf.wr_date;
  757.         dtap->wr_time = InfoBuf.wr_time;
  758.         dtap->attrib = (char) InfoBuf.attrib;
  759.         dtap->size = InfoBuf.size / ((_osmajor == 10) ? 2 : 1);
  760.         strcpy (dtap->name, InfoBuf.name);
  761.         (void) strupr (dtap->name);
  762.         dtap->hDir = hDirA;
  763.         errno = 0;
  764.         return (0);
  765.     }
  766. }
  767.  
  768. static int 
  769. dir_findnext (struct FILEINFO *dta)
  770. {
  771.  
  772.     cSearch = 1;
  773.     dtap = (struct FileInfo *) dta;
  774.     hDirA = dtap->hDir;
  775.  
  776.     findrc = DosFindNext (hDirA
  777.         ,(PVOID) & InfoBuf
  778.         ,(ULONG) (sizeof (InfoBuf) * cSearch)
  779.         ,&cSearch);
  780.  
  781.     if ((cSearch != 1) || (findrc && (findrc != ERROR_EAS_DIDNT_FIT)))
  782.     {
  783.         (void) DosFindClose (hDirA);
  784.         dtap->hDir = 0xffff;
  785.         errno = ENOENT;
  786.         return (1);
  787.     }
  788.     else
  789.     {
  790.         dtap->wr_date = InfoBuf.wr_date;
  791.         dtap->wr_time = InfoBuf.wr_time;
  792.         dtap->attrib = (char) InfoBuf.attrib;
  793.         dtap->size = InfoBuf.size / ((_osmajor == 10) ? 2 : 1);
  794.         strcpy (dtap->name, InfoBuf.name);
  795.         (void) strupr (dtap->name);
  796.         dtap->hDir = hDirA;
  797.         errno = 0;
  798.         return (0);
  799.     }
  800. }
  801.  
  802. static int 
  803. dir_findrelease (struct FILEINFO *dta)
  804. {
  805.     dtap = (struct FileInfo *) dta;
  806.     hDirA = dtap->hDir;
  807.  
  808.     if ((hDirA != 0xffff) && (hDirA != 0xffffffff))
  809.     {
  810.         (void) DosFindClose (hDirA);
  811.         dtap->hDir = 0xffff;
  812.         errno = ENOENT;
  813.         return (1);
  814.     }
  815.     else
  816.         return (0);
  817. }
  818.  
  819. void 
  820. set_fileinfo (int fh, unsigned date, unsigned time)
  821. {
  822.  
  823.     if ((time / 2048) < (unsigned) (TIMEZONE / 3600L))
  824.     {
  825.         TimeBuf.a_date = TimeBuf.w_date = TimeBuf.c_date = date - 1;
  826.         TimeBuf.c_time = time + ((unsigned) (86400 - ((unsigned) (TIMEZONE / 3600L) * 2048)));
  827.         TimeBuf.a_time = TimeBuf.w_time = TimeBuf.c_time;
  828.     }
  829.     else
  830.     {
  831.         TimeBuf.a_date = TimeBuf.w_date = TimeBuf.c_date = date;
  832.         TimeBuf.c_time = time - ((unsigned) (TIMEZONE / 3600L) * 2048);
  833.         TimeBuf.a_time = TimeBuf.w_time = TimeBuf.c_time;
  834.     }
  835.     (void) DosSetFileInfo ((HFILE) fh,
  836.         (USHORT) 1,
  837.         (PBYTE) & TimeBuf,
  838.         (USHORT) 12);
  839. }
  840.  
  841. #endif                            /* ifndef __32BIT__ */
  842. #endif                            /* ifdef OS_2 */
  843.  
  844. #ifdef _WIN32
  845. static int dir_findfirst (char far *, struct FILEINFO *);
  846. static int dir_findnext (struct FILEINFO *);
  847. static int dir_findrelease (struct FILEINFO *);
  848.  
  849. int
  850. dfind (struct FILEINFO *dta, char *name, int times)
  851. {
  852.     if (times == 0)
  853.     {
  854.         return (dir_findfirst (name, dta));
  855.     }
  856.     else if (times == 1)
  857.     {
  858.         return (dir_findnext (dta));
  859.     }
  860.     else
  861.         return (dir_findrelease (dta));
  862. }
  863.  
  864. /*--------------------------------------------------------------------------*/
  865. /* Static variable definitions                                              */
  866. /*--------------------------------------------------------------------------*/
  867.  
  868. struct FileInfo
  869. {
  870.     long hDir;
  871.     int fActive;
  872.     char rsvd[13];
  873.     char attrib;
  874.     long time;
  875.     long size;
  876.     char name[13];
  877.     char nill;
  878. };
  879.  
  880. static struct _finddata_t InfoBuf;
  881.  
  882. /*--------------------------------------------------------------------------*/
  883. /* Local functions                                                          */
  884. /*--------------------------------------------------------------------------*/
  885.  
  886. static void dir_move (struct FileInfo *dta);
  887.  
  888. /*--------------------------------------------------------------------------*/
  889. /* Local constants                                                          */
  890. /*--------------------------------------------------------------------------*/
  891.  
  892. #define FILENAMELEN 13
  893.  
  894. static int
  895. dir_findfirst (char far * filename, struct FILEINFO *dta)
  896. {
  897.     struct FileInfo *dtap = (struct FileInfo *) dta;
  898.     long hDirA;
  899.  
  900.     if (dtap->fActive)
  901.     {
  902.         (void) dir_findrelease (dta);
  903.     }
  904.  
  905.     hDirA = _findfirst (filename, &InfoBuf);
  906.  
  907.     if (hDirA == -1)
  908.     {
  909.         errno = ENOENT;
  910.         return (1);
  911.     }
  912.  
  913.     dir_move (dtap);
  914.     dtap->hDir = hDirA;
  915.     dtap->fActive = 1;
  916.     return (0);
  917. }
  918.  
  919. static int
  920. dir_findnext (struct FILEINFO *dta)
  921. {
  922.     struct FileInfo *dtap = (struct FileInfo *) dta;
  923.     long hDirA;
  924.     int fResult;
  925.  
  926.     if (!dtap->fActive)
  927.         return (1);
  928.  
  929.     hDirA = dtap->hDir;
  930.  
  931.     fResult = (_findnext (hDirA, &InfoBuf) != 0);
  932.  
  933.     if (fResult)
  934.     {
  935.         errno = ENOENT;
  936.         (void) dir_findrelease (dta);
  937.         return (1);
  938.     }
  939.  
  940.     dir_move (dtap);
  941.     return (0);
  942. }
  943.  
  944. static void
  945. dir_move (struct FileInfo *dtap)
  946. {
  947.     struct tm *ptm;
  948.     long timelong;
  949.  
  950.     /* [Y2K] Need a Win32 compiler to test this, but
  951.      * the usage is consistent with how values are used
  952.      * from localtime() elsewhere in the code.  Also,
  953.      * there's room for 7 bits of year, which should hold
  954.      * us until 1900+127=2027.
  955.      */
  956.     ptm = localtime (&InfoBuf.time_write);
  957.     timelong =    (long) (ptm->tm_sec / 2)            +
  958.                 (long) ((ptm->tm_min)         << 5)    +
  959.                 (long) ((ptm->tm_hour)         << 11)    +
  960.                 (long) ((ptm->tm_mday)        << 16)    +
  961.                 (long) ((ptm->tm_mon + 1)    << 21)    +
  962.                 (long) ((ptm->tm_year - 80)    << 25);
  963.  
  964.     dtap->time = timelong;
  965.     dtap->size = InfoBuf.size;
  966.     dtap->attrib = (char) InfoBuf.attrib;
  967.     strncpy (dtap->name, InfoBuf.name, FILENAMELEN);
  968.     (void) strupr (dtap->name);
  969.     dtap->nill = 0;
  970.     errno = 0;
  971. }
  972.  
  973. static int
  974. dir_findrelease (struct FILEINFO *dta)
  975. {
  976.     struct FileInfo *dtap = (struct FileInfo *) dta;
  977.     long hDirA;
  978.  
  979.     if (!dtap->fActive)
  980.         return (1);
  981.  
  982.     hDirA = dtap->hDir;
  983.  
  984.     (void) _findclose (hDirA);
  985.     dtap->fActive = 0;
  986.     return (0);
  987. }
  988. #endif                            /* ifdef _WIN32 */
  989.