FILE_DOS.C

16.1 KB 51a21a821cf7e2eb…
/*--------------------------------------------------------------------------*/
/*                                                                          */
/*                                                                          */
/*      ------------         Bit-Bucket Software, Co.                       */
/*      \ 10001101 /         Writers and Distributors of                    */
/*       \ 011110 /          Freely Available<tm> Software.                 */
/*        \ 1011 /                                                          */
/*         ------                                                           */
/*                                                                          */
/*  (C) Copyright 1987-91, Bit Bucket Software Co., a Delaware Corporation. */
/*                                                                          */
/*                                                                          */
/*                This module was written by Vince Perriello                */
/*                   OS/2 code contributed by Bill Andrus                   */
/*                                                                          */
/*            DOS and OS/2 File I/O routines used by BinkleyTerm            */
/*                                                                          */
/*                                                                          */
/*    For complete  details  of the licensing restrictions, please refer    */
/*    to the License  agreement,  which  is published in its entirety in    */
/*    the MAKEFILE and BT.C, and also contained in the file LICENSE.250.    */
/*                                                                          */
/*    USE  OF THIS FILE IS SUBJECT TO THE  RESTRICTIONS CONTAINED IN THE    */
/*    BINKLEYTERM  LICENSING  AGREEMENT.  IF YOU DO NOT FIND THE TEXT OF    */
/*    THIS  AGREEMENT IN ANY OF THE  AFOREMENTIONED FILES,  OR IF YOU DO    */
/*    NOT HAVE THESE FILES,  YOU  SHOULD  IMMEDIATELY CONTACT BIT BUCKET    */
/*    SOFTWARE CO.  AT ONE OF THE  ADDRESSES  LISTED BELOW.  IN NO EVENT    */
/*    SHOULD YOU  PROCEED TO USE THIS FILE  WITHOUT HAVING  ACCEPTED THE    */
/*    TERMS  OF  THE  BINKLEYTERM  LICENSING  AGREEMENT,  OR  SUCH OTHER    */
/*    AGREEMENT AS YOU ARE ABLE TO REACH WITH BIT BUCKET SOFTWARE, CO.      */
/*                                                                          */
/*                                                                          */
/* You can contact Bit Bucket Software Co. at any one of the following      */
/* addresses:                                                               */
/*                                                                          */
/* Bit Bucket Software Co.        FidoNet  1:104/501, 1:343/491             */
/* P.O. Box 460398                AlterNet 7:491/0                          */
/* Aurora, CO 80046               BBS-Net  86:2030/1                        */
/*                                Internet f491.n343.z1.fidonet.org         */
/*                                                                          */
/* Please feel free to contact us at any time to share your comments about  */
/* our software and/or licensing policies.                                  */
/*                                                                          */
/*--------------------------------------------------------------------------*/

/* Include this file before any other includes or defines! */

#include "includes.h"

#ifdef NEED_MKTEMP
char *mktemp (char *template)
{
   static char save[8] = "Z";
   char *p;
   int i;

   p = save;

   if (*p == 'Z')
      sprintf (p, "%06d", TaskNumber);
   while (*p)
      {
      if (isdigit (*p))
         {
         *p = 'a';
         break;
         }
      if (*p++ < 'z')
         {
         break;
         }
      }
   if ((*p == '\0') || ((i = strlen (template)) < 6))
      return (NULL);
   strcpy (&template[i-6], save);
   return (template);
}
#endif

#ifdef NEED_DOSREAD
int _dos_read (int fd, void far *buf, unsigned nbytes, unsigned int *bytes_read)
{
    union REGS regs;
    struct SREGS sregs;

    regs.h.ah = 0x3f;    /* read file */
    regs.x.bx = fd;
    regs.x.cx = nbytes;
    regs.x.dx = FP_OFF (buf);
    sregs.ds = FP_SEG (buf);
    *bytes_read = intdosx (&regs, &regs, &sregs);
    return regs.x.cflag ? -1 : 0;
}

int _dos_write (int fd, void far *buf, unsigned nbytes, unsigned int *bytes_read)
{
    union REGS regs;
    struct SREGS sregs;

    regs.h.ah = 0x40;    /* write file */
    regs.x.bx = fd;
    regs.x.cx = nbytes;
    regs.x.dx = FP_OFF (buf);
    sregs.ds = FP_SEG (buf);
    *bytes_read = intdosx (&regs, &regs, &sregs);
    return regs.x.cflag ? -1 : 0;
}
#endif

#ifdef __TURBOC__ 
/* 
 * utime function for Turbo / Borland C.
 *
 * We should make this more generic in case some other DOS
 * compiler comes up lacking, but for now the only one we
 * have that needs it happens to be Borland.
 *
 */

int cdecl utime (char *name, struct utimbuf *times)
{
    int handle;
    struct date d;
    struct time t;
    struct ftime ft;

    unixtodos (times->modtime, &d, &t);
    ft.ft_tsec = t.ti_sec / 2;
    ft.ft_min = t.ti_min;
    ft.ft_hour = t.ti_hour;
    ft.ft_day = d.da_day;
    ft.ft_month = d.da_mon;
    ft.ft_year = d.da_year - 1980;
    if ((handle = open(name, O_RDONLY)) == -1)
        return -1;

    setftime (handle, &ft);
    close (handle);
    return 0;
}
#endif
 

int dexists (char *filename)
{
   struct stat stbuf;

   return (stat (filename, &stbuf) != -1) ? 1 : 0;
}

int dfind (struct FILEINFO *dta, char *name, int times)
{
#ifndef OS_2
   union REGS r;
   struct SREGS s;
   char far *dtaptr = (char *)dta;
   char far *nameptr = (char *)name;

   s.ds = FP_SEG (dtaptr);
   r.x.dx = FP_OFF (dtaptr);
   r.h.ah = 0x1a;
   (void) intdosx (&r, &r, &s);
   r.x.bx = 0;
   r.x.cx = ~0x08;
   s.ds = FP_SEG (nameptr);
   r.x.dx = FP_OFF (nameptr);
   r.x.si = 0;
   r.x.di = 0;
   if (times == 0)
      {
      r.h.ah = 0x4e;
      (void) intdosx (&r, &r, &s);
      dta->nill = '\0';
      /* If not found or a character device (e.g. "COM1") */
      if ((r.x.cflag != 0) || ((dta->attr & 0x40) != 0))
         {
         dta->name[0] = '\0';
         return (1);
         }
      return (0);
      }
   else
      {
      r.h.ah = 0x4f;
      (void) intdosx (&r, &r, &s);
      dta->nill = '\0';
      /* If not found or a character device (e.g. "COM1") */
      if ((r.x.cflag != 0) || ((dta->attr & 0x40) != 0))
         {
         dta->name[0] = '\0';
         return (1);
         }
      return (0);
      }
#else
   if (times == 0)
      {
      return (dir_findfirst (name, 0x37, dta));
      }
   else
      {
      return (dir_findnext (dta));
      }
#endif
}


int got_error (char *string1, char *string2)
{
   if (errno == 0x18)
      errno = 0;
   if (errno != 0)
      {
      status_line ("%s %d, %s %s %s", MSG_TXT(M_ERROR), errno, MSG_TXT(M_CANT), string1, string2);
      errno = 0;
      return (1);
      }
   return (0);
}


/* Z F R E E -- Return total number of free bytes on drive specified */
#ifdef OS_2
long zfree (char *path)
{
   int drive;
   FSALLOCATE dt;

   if (*path != '\0' && path[1] == ':')
      drive = tolower (*path) - 'a' + 1;
   else
      drive = 0;
   DosQFSInfo (drive, 1, (char far *) &dt, sizeof (FSALLOCATE));
   return ( dt.cSectorUnit * dt.cUnitAvail * dt.cbSector);
}

#else /* OS_2 */

long zfree (char *drive)
{
   union REGS r;

   unsigned char driveno;
   long stat;

   if (drive[0] != '\0' && drive[1] == ':')
      {
      driveno = (unsigned char) (islower (*drive) ? toupper (*drive) : *drive);
      driveno = (unsigned char) (driveno - 'A' + 1);
      }
   else driveno = 0;                             /* Default drive    */

   r.x.ax = 0x3600;                              /* get free space   */
   r.h.dl = driveno;                             /* on this drive    */
   (void) int86 (0x21, &r, &r);                  /* go do it         */

   if (r.x.ax == 0xffff)                         /* error return??   */
      return (0);

   stat = (long) r.x.bx                          /* bx = clusters avail  */
      * (long) r.x.ax                            /* ax = sectors/clust   */
      * (long) r.x.cx;                           /* cx = bytes/sector    */

   return (stat);

}

#endif /* OS_2 */


static int share_flags[] = {
                             SH_COMPAT,
                             SH_DENYNO,
                             SH_DENYRD,
                             SH_DENYRW,
                             SH_DENYWR
                           };


int share_open (char *filename, int oflag, int shflag)
{
    if ((no_sharing == 0) && (_osmajor >= 3))
        return (sopen (filename, oflag, share_flags[shflag]));
    else
        return (open (filename, oflag));

}

FILE *share_fopen (char *filename, char *mode, int shflag)
{
#ifdef MUST_FDOPEN
    int fd;
    int open_mode;
    char c, *p;
    int sflag = S_IREAD | S_IWRITE;
    FILE *stream;
/*
 *  Microsoft made this easy for us. They gave us a stream-open
 *  function that supports file sharing. Borland was not so kind.
 *  So -- what we do here is open the file using the only sharing
 *  API they provide -- that gives us a file handle -- then we
 *  use fdopen to get a file stream out of it. Sheesh!
 *
 *  Of course, Microsoft 5.1 provides about the same level of
 *  support as Borland -- almost. They explicitly warn you not
 *  to do this neat thing I did for Borland. So I get no sharing
 *  support for fopen() under 5.1. Double sheesh!
 */
    if ((no_sharing == 0) && (_osmajor >= 3))
        {

        /* Figure out the translation from fopen-mode to
           open-mode... */

        p = mode;
        c = *p++;
        if (c == 'w')
            open_mode = O_CREAT | O_RDWR;
        else if (c == 'r')
            open_mode = O_RDONLY;
        else if (c == 'a')
            open_mode = O_CREAT | O_RDWR | O_APPEND;
        else return (FILE *) NULL;
        while (*p)
            {
            c = *p++;
            if (c == 't')
                open_mode |= O_TEXT;
            if (c == 'b')
                open_mode |= O_BINARY;
            if (c == '+')
                {
                if (open_mode & O_RDONLY)
                    {
                    open_mode = (open_mode & ~O_RDONLY) | O_RDWR;
                    }
                else if (!(open_mode & O_APPEND))
                    open_mode |= O_TRUNC;
                }
            }

        /* Open the file handle */

        fd = open (filename, open_mode | share_flags[shflag], sflag);

        if (fd == -1)
            return (FILE *) NULL;

        /* Got the handle, make the stream */

        if ((stream = fdopen (fd, mode)) == (FILE *) NULL)
            (void) close (fd);
        return (stream);
        }
    else
#else
#ifndef CANT_FSOPEN
    if ((no_sharing == 0) && (_osmajor >= 3))
        return (_fsopen (filename, mode, share_flags[shflag]));
    else
#else
    happy_compiler = shflag;    /* Makes the compiler happy */
#endif
#endif
        return (fopen (filename, mode));
}

#ifdef OS_2

/*--------------------------------------------------------------------------*/
/* Static variable definitions                                              */
/*--------------------------------------------------------------------------*/

struct FileTimeBuf {
   unsigned c_date;       /* date of file creation */
   unsigned c_time;       /* time of file creation */
   unsigned a_date;       /* date of last access   */
   unsigned a_time;       /* time of last access   */
   unsigned w_date;       /* date of last write    */
   unsigned w_time;       /* time of last write    */
   };

static struct FileTimeBuf TimeBuf;

struct FileInfo {
   USHORT hDir;
   char rsvd[19];
   char attrib;
   unsigned wr_date;
   unsigned wr_time;
   long size;
   char name[13];
   char nill;
   };

struct FileFindBuf {
        unsigned create_date;           /* date of file creation */
        unsigned create_time;           /* time of file creation */
        unsigned access_date;           /* date of last access */
        unsigned access_time;           /* time of last access */
        unsigned wr_date;               /* date of last write */
        unsigned wr_time;               /* time of last write */
        unsigned long size;             /* file size (end of data) */
        unsigned long falloc_size;      /* file allocated size */
        unsigned attrib;                /* attributes of the file */
        unsigned char string_len;       /* returned length of ascii name str. */
                                        /* length does not include null byte */
        char name[255];                 /* name string */
        };

static struct FileFindBuf InfoBuf;

/*--------------------------------------------------------------------------*/
/* Locally defined globals                                                  */
/*--------------------------------------------------------------------------*/

struct FileInfo *dtap;
HDIR             hDirA;
USHORT           cSearch;
USHORT           usAttrib;

/*--------------------------------------------------------------------------*/
/* Local constants                                                          */
/*--------------------------------------------------------------------------*/

#define FILENAMELEN 13

int dir_findfirst(char far * filename, int attribute, struct FILEINFO * dta)
{

    cSearch  = 1;
    dtap     = (struct FileInfo *)dta;
    hDirA    =  dtap->hDir;
    usAttrib = attribute;

    if ((hDirA != 0xffff) && (hDirA != 0x0000))
        (void) DosFindClose( hDirA);

    hDirA = 0xffff;

    if ((DosFindFirst( filename
                 , &hDirA
                 , usAttrib
                 , (PFILEFINDBUF) &InfoBuf
                 , (USHORT) (sizeof(InfoBuf) * cSearch)
                 , &cSearch
                 , (ULONG) NULL) != 0) || (cSearch != 1))
    {
        (void) DosFindClose( hDirA);
        dtap->hDir = 0xffff;
        errno = ENOENT;
        return (1);
    } else {
        dtap->wr_date   = InfoBuf.wr_date;
        dtap->wr_time   = InfoBuf.wr_time;
        dtap->attrib    = (char) InfoBuf.attrib;
        dtap->size      = InfoBuf.size / ((_osmajor == 10) ? 2 : 1);
        strcpy( dtap->name, InfoBuf.name);
        dtap->hDir      = hDirA;
        errno = 0;
        return (0);
    }
}


int dir_findnext(struct FILEINFO * dta)
{

    cSearch        = 1;
    dtap           = (struct FileInfo *)dta;
    hDirA          = dtap->hDir;

    if ((DosFindNext( hDirA
                , (PFILEFINDBUF) &InfoBuf
                , (USHORT) (sizeof(InfoBuf) * cSearch)
                , &cSearch) != 0) || (cSearch != 1))
    {
        (void) DosFindClose( hDirA);
        dtap->hDir = 0xffff;
        errno      = ENOENT;
        return (1);
    } else {
        dtap->wr_date   = InfoBuf.wr_date;
        dtap->wr_time   = InfoBuf.wr_time;
        dtap->attrib    = (char) InfoBuf.attrib;
        dtap->size      = InfoBuf.size / ((_osmajor == 10) ? 2 : 1);
        strcpy( dtap->name, InfoBuf.name);
        dtap->hDir      = hDirA;
        errno = 0;
        return (0);
    }
}

void set_fileinfo(int fh, unsigned date, unsigned time)
{

    if ((time/2048) < (unsigned)(timezone/3600L)) {
        TimeBuf.a_date = TimeBuf.w_date = TimeBuf.c_date = date-1;
        TimeBuf.c_time = time+((unsigned)(86400-((unsigned)(timezone/3600L)*2048)));
        TimeBuf.a_time = TimeBuf.w_time = TimeBuf.c_time;
    } else {
        TimeBuf.a_date = TimeBuf.w_date = TimeBuf.c_date = date;
        TimeBuf.c_time = time-((unsigned)(timezone/3600L)*2048);
        TimeBuf.a_time = TimeBuf.w_time = TimeBuf.c_time;
    }
    (void) DosSetFileInfo((HFILE) fh,
                        (USHORT) 1,
                        (PBYTE) &TimeBuf,
                        (USHORT) 12);
}

#endif /* ifdef OS_2 */