www.delorie.com/archives/browse.cgi   search  
Mail Archives: djgpp-workers/1997/09/18/17:10:04

Message-Id: <3.0.1.32.19970918160708.006ce794@yacker.xiotech.com>
Date: Thu, 18 Sep 1997 16:07:08 -0500
To: djgpp-workers AT delorie DOT com
From: Randy Maas <randym AT xiotech DOT com>
Subject: Some possible fs changes p2
Mime-Version: 1.0

--=====================_874634828==_
Content-Type: text/plain; charset="us-ascii"

This is the second part of my proposed changes to the fsext system the
standard c library.

Randy Maas
randym AT acm DOT org
--=====================_874634828==_
Content-Type: text/plain; charset="us-ascii"
Content-Disposition: attachment; filename="_copy.c"

/*
   1997, Randall Maas.  Created this, but based it the _open example, so
   portions are:
   Copyright (C) 1995 DJ Delorie, see COPYING.DJ for details */
#include <errno.h>
# if defined(__DJGPP__)
#  include <sys/fsext.h>
# else
#  include "fsext.h"
# endif

/*
   @txh
    @node _copy, file system
     @subheading Syntax
      @example
*/
int _copy(const char* src, const char* dest)
/*@end example*/
{
   /*
      @subheading Description
       This has the File System Extension copy a file.

      @subheading Return Value
       -1 on error.

      @end txh
    */

  int rv;

  if (__FSEXT_call_open_handlers(__FSEXT_copy, &rv, &src))
    return rv;

  errno = EINVAL; /* The file was not copied */
  return -1;
}


--=====================_874634828==_
Content-Type: text/plain; charset="us-ascii"
Content-Disposition: attachment; filename="_def_fs.c"

/*
   Default FS extension
   1997, Randall Maas
 */

#include <sys/fsext.h>

/*
   @txh
    @node _def_fsext, file system
     @syntax
      @example
*/
int _def_fsext(__FSEXT_Fnumber Op, int* rv, va_list Args, void* State)
/* @end example */
{
   /*
      @subheading Description
       This is the lowest level file system extension.  By default,
       @code{_def_fsext} calls MSDOS (@pxref{_DOS_FS_Entry}).  By providing
       your own @code{_def_fsext} subroutine, the basic file system services
       can be changed.  For instance, if you were trying to implement a win32
       based system (and didn't want MSDOS in the way), you would want to
       provide a dummy @code{_def_fsext} routine that calls your win32
       interface.
      @end txh
    */

   return _DOS_FS_Entry(Op, rv, Args, State);
}

--=====================_874634828==_
Content-Type: text/plain; charset="us-ascii"
Content-Disposition: attachment; filename="_DOS_fd.c"

/*
    1997, Randall Maas -- maked _DOS_alloc_fd separate from __FSEXT_alloc_fd
        so that it can be overridden.
    Copyright (C) 1995 DJ Delorie, see COPYING.DJ for details
*/
#include <dpmi.h>
#include <go32.h>
#include <libc/dosio.h>
#include <errno.h>

/*
   @txh
    @node _DOS_alloc_fd, dos
    @subheading Syntax
     @example
*/
int _DOS_alloc_fd()
/*@end example*/
{
   /*
      @subheading Description
       This function opens DOS's @samp{NUL} device, so as to allocate a
       handle that DOS won't then reuse.  It also assigns the handler
       function for that descriptor.

      @subheading Return Value
       Returns the handle, or -1 on error

      @end txh
    */

  __dpmi_regs r;

  _put_path("nul");
  r.x.ax = 0x3d82;	/* open, no inherit, read/write */
  r.x.dx = __tb_offset;
  r.x.ds = __tb_segment;
  __dpmi_int(0x21, &r);

  if (r.x.flags & 1)
  {
    errno = __doserr_to_errno(r.x.ax);
    return -1;
  }

  return r.x.ax;
}


--=====================_874634828==_
Content-Type: text/plain; charset="us-ascii"
Content-Disposition: attachment; filename="_DOS_fsext.c"

/*
   DOS File System Extension for DJGPP.
   Copyright 1997 Randall Maas.
   1997, Randall Maas remove DOS specific code and inlined documentation.
   Brought in DOS specific calls -- the code for these were written by
   DJ Delorie and by Morten Welinder, these 
   Copyright (C) 1996 DJ Delorie, see COPYING.DJ for details
   Copyright (C) 1995 DJ Delorie, see COPYING.DJ for details

   Copyright 1995 by Morten Welinder
   This file maybe freely distributed and modified as long as the
   copyright notice remains.

   1997, Randall Maas: Split _close into _close and _DOS_close;
        Renamed to _DOS_remove.
        inlined the documentation.
*/

#include <stdio.h>
#include <libc/stubs.h>
#include <string.h>
#include <fcntl.h>
#include <errno.h>
#include <go32.h>
#include <dpmi.h>
#include <libc/dosio.h>
#include <fsext.h>
#include <unistd.h>
#include <io.h>

static int _DOS_open   (va_list);
static int _DOS_create (va_list);
static int _DOS_close  (va_list);
static int _DOS_read   (va_list);
static int _DOS_write  (va_list);
static int _DOS_ready  (va_list);
static int _DOS_seek   (va_list);
static int _DOS_remove (va_list);

/*
   @txh
    @node _DOS_FS_Entry, dos
    @subheading Syntax
     @example
 */
int _DOS_FS_Entry(Op, RV, Args, State)
        __FSEXT_Fnumber Op;    /*// Operation to perform. */
        int*             RV;   /*// Return value of the operation. */
        va_list          Args; /*// Arguments to the operation. */
        void*            State; /*// Ignored */
/* @end example */
{
   /*
      @subheading Description
       This provides a common entry point for DOS file system functions.
       (see @ref{File System Extensions}).
      @end txh
    */

   if (Op ==  __FSEXT_nop)
     {
        /* No operation. */
        *RV = 0;
        return 1;
     }

   switch(Op)
    {
       /* Check the status DOS based file. */
       case __FSEXT_ready: *RV = _DOS_ready(Args); break;

       /* Read from the DOS based file. */
       case __FSEXT_read: *RV = _DOS_read(Args); break;

       /* Write to the DOS based file. */
       case __FSEXT_write: *RV = _DOS_write(Args); break;

       /* Do a seek with the DOS file */
       case __FSEXT_seek: *RV = _DOS_seek(Args); break;

       /* Open a DOS based file */
       case __FSEXT_open: *RV = _DOS_open(Args); break;

       /* Create a DOS based file */
       case __FSEXT_creat: *RV = _DOS_create(Args); break;

       /* Close the DOS file. */
       case __FSEXT_close: *RV = _DOS_close(Args); break;

       /* Remove the DOS file. */
       case __FSEXT_unlink: *RV =_DOS_remove(Args); break;

       default: return 0; /* Emulation was not done. */
    }
   return 1;
}

/*
   @txh
    The FS_Ext functions are implemented as follows:
    @table @code
   @end txh
*/

static int _DOS_open(va_list Args)
{
   /*
      @txh
      @item __FSEXT_open
       This is a direct connection to the MS-DOS open function call, int
       0x21, %ah = 0x3d.  The file is set to binary mode.
      @end txh
    */

  __dpmi_regs r;
  int use_lfn = _USE_LFN;
  const char* filename;
  int oflag;

  filename = va_arg(Args, const char*);
  if (filename == 0)
  {
    errno = EINVAL;
    return -1;
    /* Bug: should simply indicate not handled. */
  }

  oflag = va_arg(Args, int);

  _put_path(filename);
  if(use_lfn) {
    r.x.ax = 0x716c;
    r.x.bx = oflag & 0xff;
    r.x.dx = 1;			/* Open existing file */
    r.x.si = __tb_offset;
  } else {
    r.h.ah = 0x3d;
    r.h.al = oflag;
    r.x.dx = __tb_offset;
  }
  r.x.cx = 0;
  r.x.ds = __tb_segment;
  __dpmi_int(0x21, &r);
  if(r.x.flags & 1)
  {
    errno = __doserr_to_errno(r.x.ax);
    return -1;
  }
  __file_handle_set(r.x.ax, O_BINARY);
  return r.x.ax;
}

static int _DOS_create (va_list Args)
{
   /*
     @txh
      @item __FSEXT_creat
       This is a direct connection to the MS-DOS creat function call, int
       0x21, %ah = 0x3c.  The file is set to binary mode.
     @end txh
    */

  __dpmi_regs r;
  unsigned use_lfn = _USE_LFN;
  const char* filename;
  int attrib;

  filename = va_arg(Args, const char*);
  if (filename == 0)
  {
    errno = EINVAL;
    return -1;
    /* BUG: We don't handle this... */
  }

  attrib = va_arg(Args, int);

  _put_path(filename);
  if(use_lfn) {
    r.x.ax = 0x716c;
    r.x.bx = 0x0002;		/* open r/w */
    r.x.dx = 0x0012;		/* Create, truncate if exists */
    r.x.si = __tb_offset;
  } else {
    r.h.ah = 0x3c;
    r.x.dx = __tb_offset;
  }
  r.x.cx = attrib;
  r.x.ds = __tb_segment;
  __dpmi_int(0x21, &r);
  if(r.x.flags & 1)
  {
    errno = __doserr_to_errno(r.x.ax);
    return -1;
  }
  __file_handle_set(r.x.ax, O_BINARY);
  return r.x.ax;
}

static int _DOS_close(va_list Args)
{
   /*
     @txh
      @item __FSEXT_close
       This is a direct connection to the MS-DOS close function call, int
       0x21, %ah = 0x3e.  Returns zero if the file was closed, else nonzero.
      @end txh
    */

  __dpmi_regs r;
  int handle; /* The file descriptor. */

  handle = va_arg(Args, int);

  r.h.ah = 0x3e;
  r.x.bx = handle;
  __dpmi_int(0x21, &r);
  if (r.x.flags & 1)
  {
    errno = EBADF;
    return -1;
  }
  return 0;
}

static int _DOS_seek(va_list Args)
{
   /*
     @txh
      @item __FSEXT_seek
       This is a direct connection to the MS-DOS lseek function call, int
       0x21, %ah = 0x42.  Returns -1 on error, the position within the file
       otherwise.
      @end txh
    */


  __dpmi_regs r;
  int handle, whence;
  off_t offset;

  handle = va_arg(Args, int);
  offset = va_arg(Args, off_t);
  whence = va_arg(Args, int);

  r.h.ah = 0x42;
  r.h.al = whence;
  r.x.bx = handle;
  r.x.cx = offset >> 16;
  r.x.dx = offset & 0xffff;
  __dpmi_int(0x21, &r);
  if (r.x.flags & 1)
  {
    errno = __doserr_to_errno(r.x.ax);
    return -1;
  }
  return (r.x.dx << 16) + r.x.ax;
}

static int _DOS_write(va_list Args)
{
   /*
     @txh 
      @item __FSEXT_write
       This is a direct connection to the MS-DOS write function call, int
       0x21, %ah = 0x40.  No conversion is done on the data; it is written as
       raw binary data.
     @end txh
    */

  size_t j, i;
  int nput;
  unsigned long tbsize;
  __dpmi_regs r;
   int handle;
   const void* buffer;
   size_t count;

   handle = va_arg(Args, int);
   buffer = va_arg(Args, void*);
   count  = va_arg(Args, size_t);

  tbsize = _go32_info_block.size_of_transfer_buffer;
  nput = 0;
  do {
    j = (count <= tbsize) ? count : tbsize;
    if (j)
      dosmemput(buffer, j, __tb);
    r.x.ax = 0x4000;
    r.x.bx = handle;
    r.x.cx = j;
    r.x.dx = __tb & 15;
    r.x.ds = __tb / 16;
    __dpmi_int(0x21, &r);
    if (r.x.flags & 1)
    {
      errno = __doserr_to_errno(r.x.ax);
      return -1;
    }
    i = r.x.ax;
    count -= i;
    buffer = (void *)((int)buffer + i);
    nput += i;
  } while(count && (i == j));

  if (count && nput == 0)
  {
    errno = ENOSPC;
    return -1;
  }

  return nput;
}

static int _DOS_read(va_list Args)
{
   /*
      @txh
      @item __FSEXT_read
       This is a direct connection to the MS-DOS read function call, int
       0x21, %ah = 0x3f.  No conversion is done on the data; it is read as
       raw binary data.
      @end txh
    */

  size_t j, k;
  int ngot;
  unsigned long tbsize;
  __dpmi_regs r;
   int handle;
   void* buffer;
   size_t count;

   handle = va_arg(Args, int);
   buffer = va_arg(Args, void*);
   count  = va_arg(Args, size_t);

  tbsize = _go32_info_block.size_of_transfer_buffer;
  ngot = 0;
  do {
    j = (count <= tbsize) ? count : tbsize;
    r.x.ax = 0x3f00;
    r.x.bx = handle;
    r.x.cx = j;
    r.x.dx = __tb & 15;
    r.x.ds = __tb / 16;
    __dpmi_int(0x21, &r);
    if(r.x.flags & 1)
    {
      errno = __doserr_to_errno(r.x.ax);
      return -1;
    }
    count -= j;
    k = r.x.ax;
    ngot += k;
    if (k)
      dosmemget(__tb, k, buffer);
    buffer = (void *)((int)buffer + k);
  } while(count && j == k);	/* if not == on DOS then no more */
  return ngot;
}

/*
   Most of this is credited to Morten Welinder

   This is as close as we get, I think.  For a file connected to a printer
   we could of course go ask the BIOS, but this should be enough.  */


/* The Dos call 4407 always returns TRUE for disk files.  So the
   following really is meaningful for character devices only...  */

inline static int _DOS_output_ready(int fd)
{

  __dpmi_regs regs;

  regs.x.ax = 0x4407;
  regs.x.bx = fd;
  __dpmi_int (0x21, &regs);
  if (regs.x.flags & 1)
  {
    errno = __doserr_to_errno (regs.x.ax);
    return -1;
  }
  else
    return regs.h.al == 0xff;
}

inline static int _DOS_input_ready(int fd)
{

  __dpmi_regs regs;

  regs.x.ax = 0x4406;
  regs.x.bx = fd;
  __dpmi_int (0x21, &regs);
  if (regs.x.flags & 1)
  {
    errno = __doserr_to_errno (regs.x.ax);
    return -1;
  }
  else
    return regs.h.al == 0xff;
}

static int _DOS_ready(va_list Args)
{
   int Ret = 0, X, fd;

   fd = va_arg(Args, int);

   X = _DOS_input_ready(fd);
   Ret |= (X < 0) ?  __FSEXT_ready_error : (X) ? __FSEXT_ready_read: 0;

   X = _DOS_output_ready(fd);
   Ret |= (X < 0) ?  __FSEXT_ready_error : (X) ? __FSEXT_ready_write: 0;

   return Ret;
}

static int _DOS_remove(va_list Args)
{
  __dpmi_regs r;
  unsigned attr;
  int directory_p;
  int use_lfn = _USE_LFN;
  const char *fn = va_arg(Args, const char*);
 
  /* Get the file attribute byte.  */
  attr = _chmod(fn, 0);
  directory_p = attr & 0x10;
 
  /* Now, make the file writable.  We must reset Vol, Dir, Sys and Hidden bits 
     in addition to the Read-Only bit, or else 214301 will fail.  */
  _chmod(fn, 1, attr & 0xffe0);

  /* Now delete it.  Note, _chmod leaves dir name in tranfer buffer. */
  if (directory_p)
    r.h.ah = 0x3a;		/* DOS Remove Directory function */
  else
    r.h.ah = 0x41;		/* DOS Remove File function */
  if(use_lfn) {
    r.h.al = r.h.ah;
    r.h.ah = 0x71;
    r.x.si = 0;			/* No Wildcards */
  }
  r.x.dx = __tb_offset;
  r.x.ds = __tb_segment;
  __dpmi_int(0x21, &r);
  if(r.x.flags & 1)
  {
    /* We failed.  Leave the things as we've found them.  */
    int e = __doserr_to_errno(r.x.ax);
 
    _chmod(fn, 1, attr & 0xffe7);
    errno = e;
    return -1;
  }
  return 0;
}

/*
   @txh
    @end table
   @end txh
 */

--=====================_874634828==_
Content-Type: text/plain; charset="us-ascii"
Content-Disposition: attachment; filename="_fs_call.c"

/*
   File System Call.
   1997 Randall Maas.
   Portions Copyright (C) 1995 DJ Delorie, see COPYING.DJ for details
*/
#include <stdio.h>
/* The test is her for using this code on a couple of non DJGPP platforms as well */
#if defined(__djgpp__)
#  include <sys/fsext.h>
# else
#  include "fsext.h"
#endif
#include <errno.h>

/*
   @txh
    @node __FSEXT_Call, file system
    @subheading Syntax
     @example
 */
int __FSEXT_Call(__FSEXT_Fnumber Op, int Handle, va_list Args)
        /*//Op     identifies which function is to be emulated.*/
        /*//Handle is the handle to entity to worked on.*/
        /*//Args   represents the arguments passed to the original function */
/*@end example */
{
   /*
      @subheading Description
       This procedure is meant to be called by functions require some form of
       emulation.  It calls the File System Extension associated with the
       Handle.  If the function is not emulated by this extension, it tries
       a generic function emulator to carry out the operation.

      @subheading Return Value
       If it is unable to find a handler that corresponds to the handle, or
       the handler did not carry out the operation, @code{_FS_Call} sets
       @var{errno} to EINVAL and returns -1.  Otherwise it returns the
       value from the handler.
      @end txh
    */

  __FSEXT_Function *func;
  void* state;
  int rv;

  if (__FSEXT_get_handler(Handle, &func, &state) && func)
    {
      /* Try to call the function. */
      if (func(Op, &rv, Args, state))
        return rv; /* The operation was carried out. */
       else
        {
           /* The operation was not carried out.  Let's see if we can emulate
              the operation in some other way.  We only do this if the
              original File Handler does not implement operation.
            */
           if (__FSEXT_Emu(Op, &rv, Args, NULL))
            return rv;
        }
    }
   else
    {
       /* The handle is not one defined in our FS extensions -- it may be
          one not open internally (stdin, stdout, stderr, or one passed via
          argument).  We punt by letting the default extensions do it  */
       if (_def_fsext(Op, &rv, Args, NULL)) return rv;
    }

  errno = EINVAL;
  return -1;
}

--=====================_874634828==_
Content-Type: text/plain; charset="us-ascii"
Content-Disposition: attachment; filename="_io_api.c"

/*
  Forms the C Library basic IO procedures API.

  1997, Randa # else
! #  include "fsext.h"
! # endif
  
  typedef struct FuncList

--- 1,5 -----
  /* Copyright (C) 1995 DJ Delorie, see COPYING.DJ for details */
  #include <stdlib.h>
! #include <sys/fsext.h>
  
  typedef struct FuncList {
***************
*** 7,12
  # endif
  
! typedef struct FuncList
! {
    struct FuncList *next;
    __FSEXT_Function *function;

--- 3,7 -----
  #include <sys/fsext.h>
  
! typedef struct FuncList {
    struct FuncList *next;
    __FSEXT_Function *function;
***************
*** 15,27
  static FuncList *func_list = 0;
  
! /*
!    @txh
!     @node __FSEXT_add_open_handler, file system
!     @subheading Syntax
!      @example
!       #include <sys/fsext.h>
! */
! int __FSEXT_add_open_handler(__FSEXT_Function *_function)
! /*@end example*/
  {
     /*

--- 10,15 -----
  static FuncList *func_list = 0;
  
! int
! __FSEXT_add_open_handler(__FSEXT_Function *_function)
  {
    FuncList *new_func_list = (FuncList *)malloc(sizeof(FuncList));
***************
*** 25,53
  /*@end example*/
  {
-    /*
-       @subheading Example
-        @example
-         static int _my_handler(__FSEXT_Fnumber n, int *rv, va_list args)
-         @{
-              . . .
-         @}
- 
-         int main()
-         @{
-            __FSEXT_add_open_handler(_my_handler);
-         @}
- 
-        @end example
- 
-      @subheading Description
-       This function is part of the @ref{File System Extensions}.  It is used
-       to add a handler for functions that do not get passed descriptors,
-       such as @code{_open} and @code{_creat}.
- 
-      @subheading Return Value
-       Returns 0 if the extension was added, 1 otherwise.
-      @end txh
-     */
- 
    FuncList *new_func_list = (FuncList *)malloc(sizeof(FuncList));
    if (new_func_list == 0)

--- 13,16 -----
  __FSEXT_add_open_handler(__FSEXT_Function *_function)
  {
    FuncList *new_func_list = (FuncList *)malloc(sizeof(FuncList));
    if (new_func_list == 0)
***************
*** 59,70
  }
  
! /*
!    @txh
!     @node __FSEXT_call_open_handlers, file system
!      @subheading Syntax
!       @example
!        #include <sys/fsext.h>
! */
! int __FSEXT_call_open_handlers(__FSEXT_Fnumber _function_number,
  			   int *rv, va_list _args)
  /*@end example*/

--- 22,27 -----
  }
  
! int
! __FSEXT_call_open_handlers(__FSEXT_Fnumber _function_number,
  			   int *rv, va_list _args)
  {
***************
*** 68,72
  int __FSEXT_call_open_handlers(__FSEXT_Fnumber _function_number,
  			   int *rv, va_list _args)
- /*@end example*/
  {
     /*

--- 25,28 -----
  __FSEXT_call_open_handlers(__FSEXT_Fnumber _function_number,
  			   int *rv, va_list _args)
  {
    FuncList *f;
***************
*** 70,85
  /*@end example*/
  {
-    /*
-      @subheading Description
-       This function is part of the @ref{File System Extensions}.  It is used
-       internally to libc.a to allow extensions to get an opportunity to
-       override the @code{_open}, @code{_creat}, @code{_copy} functions.
- 
-      @subheading Return Value
-       Returns true (1) if an extension handled the request, false (0)
-       otherwise.
-      @end txh
-     */
- 
    FuncList *f;
    for (f=func_list; f; f=f->next)

--- 26,29 -----
  			   int *rv, va_list _args)
  {
    FuncList *f;
    for (f=func_list; f; f=f->next)
***************
*** 84,88
    FuncList *f;
    for (f=func_list; f; f=f->next)
!     if (f->function(_function_number, rv, _args, NULL))
        return 1;
    return 0;

--- 28,32 -----
    FuncList *f;
    for (f=func_list; f; f=f->next)
!     if (f->function(_function_number, rv, _args))
        return 1;
    return 0;

--=====================_874634699==_
Content-Type: text/plain; charset="us-ascii"
Content-Disposition: attachment; filename="fsext.dif"

diff -c2 fsext.c src\libc\fsext\fsext.c
*** fsext.c	Thu Sep 18 15:14:18 1997
--- \local\src\libc\fsext\fsext.c	Sat Nov 25 17:48:12 1995
***************
*** 1,114
! /*
!     1997, Randall Maas.  Inlined documentation. 
!     Copyright (C) 1995 DJ Delorie, see COPYING.DJ for details
!     
!    @txh
!     @node File System Extensions, file system
!      @subheading Description
!       The File System Extensions are a part of the lowest level of I/O
!       operations in the C runtime library of DJGPP.  These extensions are
!       provided to allow for cases where Unix uses a file descriptor to
!       access such items as serial ports, memory, and the network, but DOS
!       does not.  It allows a set of functions (called an @i{extension}) to
!       gain control when one of these low-level functions is called on a file
!       descriptor set up by the extension.
! 
!       Each extension must provide one or two handler functions.  All handler
!       functions take the same arguments:
! 
!       @example
!        int function(__FSEXT_Fnumber func_number, int *rv, va_list args);
!       @end example
! 
!       The @var{func_number} identifies which function is to be emulated.
!       The file @code{<sys/fsext.h>} defines the function numbers as follows:
! 
!       @table @code
!        @item __FSEXT_nop
! 
!         A no-op.  This is currently unused by the library functions.
! 
!        @item __FSEXT_open
! 
!         An open handler.  This is called just before the library is about to
!         issue the DOS OpenFile call on behalf of your program.
! 
!        @item __FSEXT_creat
! 
!         A create handler.  Called when a file needs to be created.  Note that
!         the handler should both create the ``file'' and open it.
! 
!        @item __FSEXT_read
! 
!         A read handler.  Called when data should be read from a ``file''.
! 
!        @item __FSEXT_write
! 
!         A write handler.  Called to write data to a ``file''.
! 
!        @item __FSEXT_ready
! 
!         A ready handler.  It is called by @code{select} library function
!         (@pxref{select}) when it needs to know whether a handle used to
!         reference the ``file'' is ready for reading or writing, or has an
!         error condition set.  The handler should return an OR'ed bit mask of
!         the following bits (defined on @code{<sys/fsext.h>}):
!         @table @code
!          @item __FSEXT_ready_read
! 
!           The ``file'' is ready for reading.
! 
!          @item __FSEXT_ready_write
! 
!           The ``file'' is ready for writing.
! 
!          @item __FSEXT_ready_error
! 
!           The ``file'' has an error condition set.
!         
!         @end table
! 
!        @item __FSEXT_close
! 
!         A close handler.  Called when the ``file'' should be closed.
! 
!       @end table
! 
!      @var{rv} points to a temporary return value pointer.  If the function is
!      emulated by the handler, the return value should be stored here, and the
!      handler should return a nonzero value.  If the handler returns zero, it
!      is assumed to have not emulated the call, and the regular DOS I/O
!      function will happen.  The @var{args} represent the arguments passed to
!      the original function; these point to the actual arguments on the stack,
!      so the emulation may choose to modify them and return zero to the
!      regular function, which will then act on the modified arguments.
! 
!      A normal extension would provide these parts:
!      @itemize @bullet
!       @item
! 
!        Some function to create a connection to the extension.  This may be a
!        custom function (such as @code{socket} for networking) or an extension
!        to open (such as for @code{/dev/null} emulation).
! 
!       @item
! 
!        Initialization code that adds the open handler, if any.
! 
!       @item
! 
!         Overrides for the basic I/O functions, such as @code{read} and
!         @code{write}.  This is a single function in the extension that uses
!         the function number parameter to select an extension function.
! 
!       @item
! 
!         The core functionality of the extension, if any.
! 
!      @end itemize
! 
!    @end txh
! */
! 
  #include <stdio.h>
  #include <stdlib.h>

--- 1,3 -----
! /* Copyright (C) 1995 DJ Delorie, see COPYING.DJ for details */
  #include <stdio.h>
  #include <stdlib.h>
***************
*** 113,126
  #include <stdio.h>
  #include <stdlib.h>
! # if defined(__DJGPP__)
! #  include <go32.h>
! #  include <dpmi.h>
! #  include <sys/fsext.h>
! #  include <libc/bss.h>
! #  include <libc/dosio.h>
! # else
! #  include "fsext.h"
! # endif
! # include <fcntl.h>
  #include <errno.h>
  # include <io.h>

--- 2,7 -----
  #include <stdio.h>
  #include <stdlib.h>
! #include <go32.h>
! #include <dpmi.h>
  #include <errno.h>
  #include <sys/fsext.h>
***************
*** 124,129
  # include <fcntl.h>
  #include <errno.h>
! # include <io.h>
! # include <string.h>
  
  #if defined(__DJGPP__)

--- 5,11 -----
  #include <dpmi.h>
  #include <errno.h>
! #include <sys/fsext.h>
! #include <libc/bss.h>
! #include <libc/dosio.h>
  
  static int num_fds;
***************
*** 127,142
  # include <string.h>
  
- #if defined(__DJGPP__)
- extern int _DOS_alloc_fd(void);
- # else
-  /* This is for non-DJGPP environments */
- int __bss_count = 0;
- int _DOS_alloc_fd() {return open("/dev/null", O_RDWR|O_CREAT);}
- 
- # if defined(WIN32)
- #  define bzero(a,b) memset(a, 0, b)
- # endif
- #endif
- 
  static int num_fds;
  

--- 9,12 -----
  #include <libc/dosio.h>
  
  static int num_fds;
  static __FSEXT_Function **func_list;
***************
*** 140,143
  
  static int num_fds;
  
  typedef struct

--- 10,14 -----
  
  static int num_fds;
+ static __FSEXT_Function **func_list;
  
  static void
***************
*** 141,145
  static int num_fds;
  
! typedef struct
  {
     __FSEXT_Function* func; /* The handler for the descriptor */

--- 12,17 -----
  static __FSEXT_Function **func_list;
  
! static void
! init(void)
  {
    static int init_count = -1;
***************
*** 143,154
  typedef struct
  {
-    __FSEXT_Function* func; /* The handler for the descriptor */
-    void* state_ptr; /* The handlers instance data */
- } __FSEXT_func_rec;
- 
- static __FSEXT_func_rec *func_list;
- 
- static void init(void)
- {
    static int init_count = -1;
    if (init_count == __bss_count)

--- 15,18 -----
  init(void)
  {
    static int init_count = -1;
    if (init_count == __bss_count)
***************
*** 159,171
  }
  
! /*
!    @txh
!     @node __FSEXT_alloc_fd, file system
!     @subheading Syntax
!      @example
!       #include <sys/fsext.h>
! */
! int __FSEXT_alloc_fd(__FSEXT_Function *_function, void* state)
! /*@end example*/
  {
     /*

--- 23,28 -----
  }
  
! int
! __FSEXT_alloc_fd(__FSEXT_Function *_function)
  {
    int fd;
***************
*** 169,196
  /*@end example*/
  {
-    /*
-       @subheading Example
-        @example
-         int socket()
-         @{
-           int fd = __FSEXT_alloc_fd(socket_handler, NULL);
-           init_socket(fd);
-           return fd;
-         @}
-        @end example
- 
-      @subheading Description
-       This function is part of the @ref{File System Extensions}.  It is used
-       by extensions that fully emulate the I/O functions, and thus don't
-       have a corresponding DOS file handle.  It calls _DOS_alloc_fd
-       (@ref{_DOS_alloc_fd}) to allocate a handle that DOS won't reuse.
- 
-       The module is responsible for calling @code{_close} on the descriptor
-       after setting the handler function to zero in the extended close
-       handler.
- 
-       @end txh
-   */
- 
    int fd;
  

--- 26,29 -----
  __FSEXT_alloc_fd(__FSEXT_Function *_function)
  {
    int fd;
    __dpmi_regs r;
***************
*** 194,197
  
    int fd;
  
    init();

--- 27,31 -----
  {
    int fd;
+   __dpmi_regs r;
  
    init();
***************
*** 196,200
  
    init();
-   fd = _DOS_alloc_fd();
  
    __FSEXT_set_function(fd, _function, state);

--- 30,33 -----
  
    init();
  
    _put_path("nul");
***************
*** 198,202
    fd = _DOS_alloc_fd();
  
!   __FSEXT_set_function(fd, _function, state);
    return fd;
  }

--- 31,48 -----
    init();
  
!   _put_path("nul");
!   r.x.ax = 0x3d82;	/* open, no inherit, read/write */
!   r.x.dx = __tb_offset;
!   r.x.ds = __tb_segment;
!   __dpmi_int(0x21, &r);
! 
!   if (r.x.flags & 1)
!   {
!     errno = __doserr_to_errno(r.x.ax);
!     return -1;
!   }
! 
!   fd = r.x.ax;
!   __FSEXT_set_function(fd, _function);
    return fd;
  }
***************
*** 202,214
  }
  
! /*
!    @txh
!     @node __FSEXT_set_function, file system
!      @subheading Syntax
!       @example
!        #include <sys/fsext.h>
! */
! int __FSEXT_set_function(int _fd, __FSEXT_Function *_function, void* state)
! /*@end example*/
  {
     /*

--- 48,53 -----
  }
  
! int
! __FSEXT_set_function(int _fd, __FSEXT_Function *_function)
  {
    init();
***************
*** 212,270
  /*@end example*/
  {
-    /*
-       @subheading Example
-        @example
-         #include <sys/fsext.h>
-         #include <conio.h>
- 
-         /* A simple example of a write handler which converts DOS I/O to the
-            screen into direct writes to video RAM.  **//*/
-        static int
-        my_screen_write (__FSEXT_Fnumber func, int *retval, va_list rest_args)
-        @{
-           char *buf, *mybuf;
-           size_t buflen;
-           int fd = va_arg (rest_args, int);
- 
-           if (func != __FSEXT_write || !isatty (fd))
-             return 0;  /* and the usual DOS call will be issued **//*/
- 
-           buf = va_arg (rest_args, char *);
-           buflen = va_arg (rest_args, size_t);
-           mybuf = alloca (buflen + 1);
-           memcpy (mybuf, buf, buflen);
-           mybuf[buflen] = '\0';
-           cputs (mybuf);
-           *retval = buflen;
-           return 1;  /* meaning that we handled the call **//*/
-         @}
- 
-         /* Install our handler.  The `attribute constructor' causes this
-            function to be called by the startup code.  **//*/
-         static void __attribute__((constructor))
-         install_screen_write_handler (void)
-         @{
-           __FSEXT_set_function (fileno (stdout), my_screen_write, NULL);
-         @}
- 
-       @end example
- 
-      @subheading Description
-       This function is part of the @ref{File System Extensions}.  It is used
-       to set the handler function for those extensions that use DOS files
-       for I/O.  One situation where you might need this is when you must catch
-       output to the terminal and play some tricks with it, like colorize it or
-       redirect it to another device.  The @var{state} is an optional pointer
-       to the handlers specific data for the file descriptor.
- 
-      @subheading Return Value
-        Zero in case of success, non-zero in case of failure (like if @var{_fd}
-        is negative).
- 
-      @subheading See Also
-       @xref{__FSEXT_get_function}
- 
-      @end txh
-     */
    init();
  

--- 51,54 -----
  __FSEXT_set_function(int _fd, __FSEXT_Function *_function)
  {
    init();
  
***************
*** 276,281
      int old_fds = num_fds, i;
      num_fds = (_fd+256) & ~255;
!     func_list = (__FSEXT_func_rec*)realloc(func_list,
!                                           num_fds * sizeof(__FSEXT_func_rec));
      if (func_list == 0)
        return 1;

--- 60,64 -----
      int old_fds = num_fds, i;
      num_fds = (_fd+256) & ~255;
!     func_list = (__FSEXT_Function **)realloc(func_list, num_fds * sizeof(__FSEXT_Function *));
      if (func_list == 0)
        return 1;
***************
*** 281,285
        return 1;
      for (i=old_fds; i<num_fds; i++)
!       bzero(&func_list[i], sizeof(func_list[i]));
    }
    func_list[_fd].func = _function;

--- 64,68 -----
        return 1;
      for (i=old_fds; i<num_fds; i++)
!       func_list[i] = 0;
    }
    func_list[_fd] = _function;
***************
*** 283,288
        bzero(&func_list[i], sizeof(func_list[i]));
    }
!   func_list[_fd].func = _function;
!   func_list[_fd].state_ptr = state;
    return 0;
  }

--- 66,70 -----
        func_list[i] = 0;
    }
!   func_list[_fd] = _function;
    return 0;
  }
***************
*** 288,303
  }
  
! /* Note: __FSEXT_get_function has same parameters and semantics as version
!           2.01.  __FSEXT_get_handler will provide both the function pointer
!           and the state pointer.
!  */
! /*
!    @node __FSEXT_get_function, file system
!    @subheading Syntax
!     @example
!     #include <sys/fsext.h>
! */
! __FSEXT_Function * __FSEXT_get_function(int _fd)
! /*@end example*/
  {
     /*

--- 70,75 -----
  }
  
! __FSEXT_Function *
! __FSEXT_get_function(int _fd)
  {
    init();
***************
*** 301,327
  /*@end example*/
  {
-    /*
-       @subheading Example
-        @example
-         _read(int fd, void *buf, int len)
-         @{
-             __FSEXT_Function *func = __FSEXT_get_function(fd);
-             if (func)
-              @{
-                 int rv;
-                 if (func(__FSEXT_read, &rv, &fd, NULL)) return rv;
-              @}
-             /* rest of read() **//*/
-         @}
-        @end example
- 
-       @subheading Description
-        This function is part of the @ref{File System Extensions}.  It is used
-        internal to libc.a to redirect I/O requests to the appropriate
-        extensions.
- 
-      @end txh
-    */
- 
    init();
    if (_fd < 0 || _fd >= num_fds) return 0;

--- 73,76 -----
  __FSEXT_get_function(int _fd)
  {
    init();
    if (_fd < 0 || _fd >= num_fds)
***************
*** 325,369
  
    init();
-   if (_fd < 0 || _fd >= num_fds) return 0;
-   return func_list[_fd].func;
- }
- 
- /*
-    @node __FSEXT_get_handler, file system
-    @subheading Syntax
-     @example
-     #include <sys/fsext.h>
- */
- int __FSEXT_get_handler(int _fd, __FSEXT_Function** func, void** state)
- /*@end example*/
- {
-    /*
-       @subheading Example
-        @example
-         _read(int fd, void *buf, int len)
-         @{
-             void* state;
-             __FSEXT_Function *func;
-             if (__FSEXT_get_handler(fd, &func, &state) && func)
-              @{
-                 int rv;
-                 if (func(__FSEXT_read, &rv, &fd, state)) return rv;
-              @}
-             /* rest of read() **//*/
-         @}
-        @end example
- 
-       @subheading Description
-        This function is part of the @ref{File System Extensions}.  It is used
-        internal to libc.a to redirect I/O requests to the appropriate
-        extensions.
- 
-       @subheading Return Value
-        1 if the file descriptor has a handler associated with it, 0 otherwise.
- 
-      @end txh
-    */
- 
-   init();
    if (_fd < 0 || _fd >= num_fds)
      {

--- 74,77 -----
  {
    init();
    if (_fd < 0 || _fd >= num_fds)
      return 0;
***************
*** 367,380
    init();
    if (_fd < 0 || _fd >= num_fds)
!     {
!        /* Clear out func just in case */
!        if (func) *func = NULL;
!        return 0;
!     }
! 
!   /* Return the parameters */
!   if (func) *func = func_list[_fd].func;
!   if (state) *state = func_list[_fd].state_ptr;
!   return 1;
  }
  

--- 75,79 -----
    init();
    if (_fd < 0 || _fd >= num_fds)
!     return 0;
!   return func_list[_fd];
  }
***************
*** 378,409
    return 1;
  }
- 
- 
- /*
-   @txh
-    @node __FSEXT_close_all, file system
-    @subheading Syntax
-     @example
- */
- void __FSEXT_close_all (void)
- /* @end example */
- {
-    /*
-       @subheading Description
-        @code{__FSEXT_close_all} closes all of the currently open handles.
-        This should be called during a programs exit phase, after libc has
-        @code{fclose}'d all of the files it has opened.  The reason for this
-        is that not every operating system will close a handle (e.g. file
-        descriptor or socket handle) after a program has exit.  This can
-        eventually cause the system to run out of handles until it reboots.
-       @end txh
-      */
- 
-    int I;
- 
-    if (!func_list) return;
-    for (I = 0; I < num_fds; I++)
-     if (func_list[I].func)
-       _close(I);
- }
- 

--- 78,79 -----
    return func_list[_fd];
  }

--=====================_874634699==_
Content-Type: text/plain; charset="us-ascii"
Content-Disposition: attachment; filename="fsext-h.dif"

diff -c2 fsext.h include\sys\fsext.h
*** fsext.h	Wed Sep 17 16:45:44 1997
--- include\sys\fsext.h
***************
*** 23,28
    __FSEXT_ready,
    __FSEXT_close,
-   __FSEXT_pread,
-   __FSEXT_pwrite,
    __FSEXT_fcntl,
    __FSEXT_ioctl,

--- 23,26 -----
    __FSEXT_ready,
    __FSEXT_close,
    __FSEXT_fcntl,
    __FSEXT_ioctl,
***************
*** 27,34
    __FSEXT_fcntl,
    __FSEXT_ioctl,
-   __FSEXT_lseek,
-   __FSEXT_link,
-   __FSEXT_unlink,
-   __FSEXT_copy
  } __FSEXT_Fnumber;
  

--- 25,28 -----
    __FSEXT_fcntl,
    __FSEXT_ioctl,
  } __FSEXT_Fnumber;
  
***************
*** 42,46
     caller's functionality. */
  typedef int (__FSEXT_Function)(__FSEXT_Fnumber _function_number,
!                                int *_rv, va_list _args, void* state);
  
  int               __FSEXT_alloc_fd(__FSEXT_Function *_function, void* state);

--- 36,40 -----
     caller's functionality. */
  typedef int (__FSEXT_Function)(__FSEXT_Fnumber _function_number,
! 			       int *_rv, va_list _args);
  
  int               __FSEXT_alloc_fd(__FSEXT_Function *_function);
***************
*** 44,50
                                 int *_rv, va_list _args, void* state);
  
! int               __FSEXT_alloc_fd(__FSEXT_Function *_function, void* state);
! int               __FSEXT_set_function(int _fd, __FSEXT_Function *_function,
!                                        void* state);
  __FSEXT_Function *__FSEXT_get_function(int _fd);
  int               __FSEXT_get_handler(int _fd, __FSEXT_Function** func,

--- 38,43 -----
  			       int *_rv, va_list _args);
  
! int               __FSEXT_alloc_fd(__FSEXT_Function *_function);
! int               __FSEXT_set_function(int _fd, __FSEXT_Function *_function);
  __FSEXT_Function *__FSEXT_get_function(int _fd);
  
***************
*** 48,55
                                         void* state);
  __FSEXT_Function *__FSEXT_get_function(int _fd);
! int               __FSEXT_get_handler(int _fd, __FSEXT_Function** func,
!                                          void** state);
! int               __FSEXT_Call(__FSEXT_Fnumber, int, va_list);
! int               __FSEXT_Emu (__FSEXT_Fnumber, int*, va_list, void*);
  int               __FSEXT_add_open_handler(__FSEXT_Function *_function);
  int               __FSEXT_call_open_handlers(__FSEXT_Fnumber _function_number,

--- 41,45 -----
  int               __FSEXT_set_function(int _fd, __FSEXT_Function *_function);
  __FSEXT_Function *__FSEXT_get_function(int _fd);
! 
  int               __FSEXT_add_open_handler(__FSEXT_Function *_function);
  int               __FSEXT_call_open_handlers(__FSEXT_Fnumber _function_number,

--=====================_874634699==_
Content-Type: text/plain; charset="us-ascii"
Content-Disposition: attachment; filename="link.dif"

diff -c2 link.c src\libc\posix\unistd\link.c
*** link.c	Wed Sep 17 13:46:32 1997
--- \local\src\libc\posix\unistd\link.c	Wed May 10 02:13:46 1995
***************
*** 1,6
! /*
!     1997, Modified by Randall Maas to be a wrapper to _link.  Inlined the
!           documentation
!     Copyright (C) 1995 DJ Delorie, see COPYING.DJ for details */
  #include <libc/stubs.h>
  #include <sys/stat.h>		/* For stat() */

--- 1,3 -----
! /* Copyright (C) 1995 DJ Delorie, see COPYING.DJ for details */
  #include <libc/stubs.h>
  #include <sys/stat.h>		/* For stat() */
***************
*** 6,9
  #include <sys/stat.h>		/* For stat() */
  #include <fcntl.h>		/* For O_RDONLY, etc. */
  #include <limits.h>		/* For PATH_MAX */
  #include <utime.h>		/* For utime() */

--- 3,7 -----
  #include <sys/stat.h>		/* For stat() */
  #include <fcntl.h>		/* For O_RDONLY, etc. */
+ #include <unistd.h>		/* For read(), write(), etc. */
  #include <limits.h>		/* For PATH_MAX */
  #include <utime.h>		/* For utime() */
***************
*** 10,23
  #include <errno.h>		/* For errno */
  
! /*
!    @txh
!     @node link, io
!     @subheading Syntax
!      @example
! */
! 
! #include <unistd.h>             /*// For read(), write(), etc. */
! int link(const char *exists, const char *new)
! /*@end example*/
  {
     /*

--- 8,16 -----
  #include <errno.h>		/* For errno */
  
! /* Of course, DOS can't really do a link.  We just do a copy instead,
!    which is as close as DOS gets.  Alternatively, we could always fail
!    and return -1.  I think this is slightly better. */
! int
! link(const char *path1, const char *path2)
  {
    struct stat statbuf1, statbuf2;
***************
*** 21,29
  /*@end example*/
  {
!    /*
!       @subheading Example
!        @example
!         link("foo.c", "foo.bak");
!        @end example
  
        @subheading Description

--- 14,21 -----
  link(const char *path1, const char *path2)
  {
!   struct stat statbuf1, statbuf2;
!   struct utimbuf times;
!   char buf[16384];
!   int fd1, fd2, nbyte, status1, status2;
  
    /* Fail if either path is null */
***************
*** 27,34
         @end example
  
!       @subheading Description
!        Because of limitations of MS-DOS, this function doesn't really link two
!        MSDOS files together.  However, it simulates a real @code{link} by
!        copying these files at @var{exists} to @var{new}. 
  
        @subheading Return Value

--- 19,33 -----
    int fd1, fd2, nbyte, status1, status2;
  
!   /* Fail if either path is null */
!   if (path1 == NULL || path2 == NULL)
!   {
!     errno = EFAULT;
!     return -1;
!   }
!   if (*path1 == '\0' || *path2 == '\0')
!   {
!     errno = ENOENT;
!     return -1;
!   }
  
    /* Fail if path1 does not exist - stat() will set errno */
***************
*** 32,37
         copying these files at @var{exists} to @var{new}. 
  
!       @subheading Return Value
!        Zero on success, nonzero on failure.
  
        @end txh

--- 31,36 -----
    }
  
!   /* Fail if path1 does not exist - stat() will set errno */
!   if (stat(path1, &statbuf1) < 0) return -1;
  
    /* Fail if path1 is not a regular file */
***************
*** 35,40
         Zero on success, nonzero on failure.
  
!       @end txh
!     */
  
      /* _link is defined as a File System Extension call */

--- 34,43 -----
    if (stat(path1, &statbuf1) < 0) return -1;
  
!   /* Fail if path1 is not a regular file */
!   if (!S_ISREG(statbuf1.st_mode))
!   {
!     errno = EPERM;
!     return -1;
!   }
  
    /* Fail if unable to open path1 - open() will set errno */
***************
*** 38,43
      */
  
!     /* _link is defined as a File System Extension call */
!    return _link(exists, new);
! }
  

--- 41,47 -----
    }
  
!   /* Fail if unable to open path1 - open() will set errno */
!   fd1 = open(path1, O_RDONLY | O_BINARY);
!   if (fd1 < 0) return -1;
  
    /* Fail if unable to create path2 - open() will set errno */
***************
*** 42,43
  }
  

--- 45,95 -----
    if (fd1 < 0) return -1;
  
+   /* Fail if unable to create path2 - open() will set errno */
+   fd2 = open(path2, O_WRONLY | O_BINARY | O_CREAT | O_EXCL, 0600);
+   if (fd2 < 0)
+   {
+     (void) close(fd1);
+     return -1;
+   }
+ 
+   /* Fail if path1 and path2 are on different devices */
+   if (fstat(fd2, &statbuf2) < 0) return -1;
+   if (statbuf1.st_dev != statbuf2.st_dev)
+   {
+     (void)close(fd1);
+     (void)close(fd2);
+     (void)unlink(path2);
+     errno = EXDEV;
+     return -1;
+   }
+ 
+   /* Copy path1 to path2 */
+   do
+   {
+     nbyte = read(fd1, buf, sizeof buf);
+     if (nbyte <= 0) break;
+     if (write(fd2, buf, nbyte) != nbyte) nbyte = -1;
+   }
+   while (nbyte > 0);
+ 
+   /* Fail if the copy failed or we can't clean up */
+   status1 = close(fd1);
+   status2 = close(fd2);
+   if (nbyte < 0 || status1 < 0 || status2 < 0)
+   {
+     (void) unlink(path2);
+     return -1;
+   }
+ 
+   /* Success! */
+ 
+   /* Set the mode to match the original, ignoring errors */
+   (void) chmod(path2, statbuf1.st_mode);
+ 
+   /* Set the file time to match the original, ignoring errors */
+   times.actime = statbuf1.st_atime;
+   times.modtime = statbuf1.st_mtime;
+   (void) utime(path2, &times);
+ 
+   return 0;
+ }

--=====================_874634699==_
Content-Type: text/plain; charset="us-ascii"
Content-Disposition: attachment; filename="lseek.dif"

diff -c2 lseek.c src\libc\posix\unistd\lseek.c
*** lseek.c	Wed Sep 17 13:46:04 1997
--- \local\src\libc\posix\unistd\lseek.c	Sun Feb 26 19:43:10 1995
***************
*** 1,5
! /*
!    1997, Randall Maas. Converted to a wrapper to _lseek and inlined the documentation
!    Copyright (C) 1995 DJ Delorie, see COPYING.DJ for details */
  #include <libc/stubs.h>
  #include <errno.h>

--- 1,3 -----
! /* Copyright (C) 1995 DJ Delorie, see COPYING.DJ for details */
  #include <libc/stubs.h>
  #include <unistd.h>
***************
*** 3,6
     Copyright (C) 1995 DJ Delorie, see COPYING.DJ for details */
  #include <libc/stubs.h>
  #include <errno.h>
  #include <go32.h>

--- 1,5 -----
  /* Copyright (C) 1995 DJ Delorie, see COPYING.DJ for details */
  #include <libc/stubs.h>
+ #include <unistd.h>
  #include <errno.h>
  #include <go32.h>
***************
*** 8,17
  
  #include <libc/dosio.h>
- /*
-    @txh
-     @node lseek, io
-     @subheading Syntax
-      @example
-  */
  
  #include <unistd.h>

--- 7,10 -----
  
  #include <libc/dosio.h>
  
  off_t
***************
*** 15,21
   */
  
! #include <unistd.h>
! off_t lseek(int fd, off_t offset, int whence)
! /* @end example*/
  {
     /*

--- 8,13 -----
  #include <libc/dosio.h>
  
! off_t
! lseek(int handle, off_t offset, int whence)
  {
    __dpmi_regs r;
***************
*** 19,52
  /* @end example*/
  {
!    /*
!       @subheading Example
!        @example
!         lseek(fd, 12, SEEK_CUR); /* skip 12 bytes **//*/
!        @end example
! 
!       @subheading Description
!        This function moves the file pointer for @var{fd} according to
!        @var{mode}:
! 
!        @table @code
!         @item SEEK_SET
!          The file pointer is moved to the offset specified.
! 
!         @item SEEK_CUR
!          The file pointer is moved relative to its current position.
! 
!         @item SEEK_END
!          The file pointer is moved to a position @var{offset} bytes from the
!          end of the file.  The offset is usually nonpositive in this case.
! 
!        @end table
! 
!       @subheading Return Value
!        The new offset is returned.
! 
!       @end txh
!    */
! 
!    return _lseek(fd, offset, whence);
  }
  

--- 11,26 -----
  lseek(int handle, off_t offset, int whence)
  {
!   __dpmi_regs r;
!   r.h.ah = 0x42;
!   r.h.al = whence;
!   r.x.bx = handle;
!   r.x.cx = offset >> 16;
!   r.x.dx = offset & 0xffff;
!   __dpmi_int(0x21, &r);
!   if (r.x.flags & 1)
!   {
!     errno = __doserr_to_errno(r.x.ax);
!     return -1;
!   }
!   return (r.x.dx << 16) + r.x.ax;
  }
***************
*** 50,52
     return _lseek(fd, offset, whence);
  }
- 

--- 25,26 -----
    return (r.x.dx << 16) + r.x.ax;
  }

--=====================_874634699==_
Content-Type: text/plain; charset="us-ascii"
Content-Disposition: attachment; filename="remove.dif"

diff -c2 remove.c src\libc\ansi\stdio\remove.c
*** remove.c	Thu Jun  5 09:33:06 1997
--- \local\src\libc\ansi\stdio\remove.c	Sat Aug 31 21:09:32 1996
***************
*** 1,5
! /*
!    1997, Randall Maas: Made into a wrapper for _remove, and inlined documentation
!    Copyright (C) 1995 DJ Delorie, see COPYING.DJ for details */
  #include <stdio.h>
  

--- 1,5 -----
! /* Copyright (C) 1995 DJ Delorie, see COPYING.DJ for details */
! #include <libc/stubs.h>
! #include <io.h>
  #include <stdio.h>
  #include <fcntl.h>
***************
*** 3,17
     Copyright (C) 1995 DJ Delorie, see COPYING.DJ for details */
  #include <stdio.h>
! 
! /*
!    @txh
!     @node remove, file system
!     @subheading Syntax
! 
!     @example
!      #include <stdio.h>
! */
! int remove(const char *file_name)
! /* @end example */
  {
     /*

--- 3,14 -----
  #include <io.h>
  #include <stdio.h>
! #include <fcntl.h>
! #include <errno.h>
! #include <dpmi.h>
! #include <go32.h>
! #include <libc/dosio.h>
!  
! int
! remove(const char *fn)
  {
    __dpmi_regs r;
***************
*** 15,23
  /* @end example */
  {
!    /*
!       @subheading Example
!        @example
!         remove("/tmp/data.tmp");
!        @end example
  
        @subheading Description

--- 12,27 -----
  remove(const char *fn)
  {
!   __dpmi_regs r;
!   unsigned attr;
!   int directory_p;
!   int use_lfn = _USE_LFN;
!  
!   /* Get the file attribute byte.  */
!   attr = _chmod(fn, 0);
!   directory_p = attr & 0x10;
!  
!   /* Now, make the file writable.  We must reset Vol, Dir, Sys and Hidden bits 
!      in addition to the Read-Only bit, or else 214301 will fail.  */
!   _chmod(fn, 1, attr & 0xffe0);
  
    /* Now delete it.  Note, _chmod leaves dir name in tranfer buffer. */
***************
*** 21,35
         @end example
  
!       @subheading Description
!        This function removes the named @var{file} from the file system.
!        Unless you have an un-erase program, the file and its contents are
!        gone for good. 
! 
!       @subheading Return Value
!        Zero on success, nonzero on failure.
! 
!       @end txh
!     */
! 
!    return _remove(file_name);
  }

--- 25,50 -----
    _chmod(fn, 1, attr & 0xffe0);
  
!   /* Now delete it.  Note, _chmod leaves dir name in tranfer buffer. */
!   if (directory_p)
!     r.h.ah = 0x3a;		/* DOS Remove Directory function */
!   else
!     r.h.ah = 0x41;		/* DOS Remove File function */
!   if(use_lfn) {
!     r.h.al = r.h.ah;
!     r.h.ah = 0x71;
!     r.x.si = 0;			/* No Wildcards */
!   }
!   r.x.dx = __tb_offset;
!   r.x.ds = __tb_segment;
!   __dpmi_int(0x21, &r);
!   if(r.x.flags & 1)
!   {
!     /* We failed.  Leave the things as we've found them.  */
!     int e = __doserr_to_errno(r.x.ax);
!  
!     _chmod(fn, 1, attr & 0xffe7);
!     errno = e;
!     return -1;
!   }
!   return 0;
  }

--=====================_874634699==_
Content-Type: text/plain; charset="us-ascii"
Content-Disposition: attachment; filename="select.dif"

diff -c2 select.c src\libc\compat\time\select.c
*** select.c	Tue Jun 17 12:05:40 1997
--- \local\src\libc\compat\time\select.c	Tue Jul 23 22:41:26 1996
***************
*** 1,3
- /* 1997, Randall Maas: inlined documentation and removed MSDOS specific code */
  /* Copyright (C) 1996 DJ Delorie, see COPYING.DJ for details */
  /* Copyright (C) 1995 DJ Delorie, see COPYING.DJ for details */

--- 1,2 -----
  /* Copyright (C) 1996 DJ Delorie, see COPYING.DJ for details */
  /* Copyright (C) 1995 DJ Delorie, see COPYING.DJ for details */
***************
*** 25,29
  #include <sys/fsext.h>
  
! inline static int fp_input_ready (FILE *fp)
  {
    /* I think if there is something in the buffer, we should return

--- 24,29 -----
  #include <sys/fsext.h>
  
! inline static int
! fp_output_ready(FILE *fp)
  {
    return !ferror(fp);
***************
*** 27,30
  inline static int fp_input_ready (FILE *fp)
  {
    /* I think if there is something in the buffer, we should return
       ``ready'', even if some error was encountered.  Let him consume

--- 27,45 -----
  fp_output_ready(FILE *fp)
  {
+   return !ferror(fp);
+ }
+ 
+ /* This is as close as we get, I think.  For a file connected to a printer
+    we could of course go ask the BIOS, but this should be enough.  */
+ 
+ inline static int
+ fp_except_ready(FILE *fp)
+ {
+   return ferror (fp);
+ }
+ 
+ inline static int
+ fp_input_ready (FILE *fp)
+ {
    /* I think if there is something in the buffer, we should return
       ``ready'', even if some error was encountered.  Let him consume
***************
*** 30,34
       ``ready'', even if some error was encountered.  Let him consume
       the buffered characters, *then* return ``not ready''.  */
!   if (fp->_cnt) return 1;
  
    /* The `feof' part is only correct in a single-tasked environment.  */

--- 45,50 -----
       ``ready'', even if some error was encountered.  Let him consume
       the buffered characters, *then* return ``not ready''.  */
!   if (fp->_cnt)
!     return 1;
  
    /* The `feof' part is only correct in a single-tasked environment.  */
***************
*** 42,46
  }
  
! inline static int fp_output_ready(FILE *fp)
  {
    return !ferror(fp);

--- 58,66 -----
  }
  
! /* The Dos call 4407 always returns TRUE for disk files.  So the
!    following really is meaningful for character devices only...  */
! 
! inline static int
! fd_output_ready(int fd)
  {
  
***************
*** 44,48
  inline static int fp_output_ready(FILE *fp)
  {
!   return !ferror(fp);
  }
  

--- 64,80 -----
  fd_output_ready(int fd)
  {
! 
!   __dpmi_regs regs;
! 
!   regs.x.ax = 0x4407;
!   regs.x.bx = fd;
!   __dpmi_int (0x21, &regs);
!   if (regs.x.flags & 1)
!   {
!     errno = __doserr_to_errno (regs.x.ax);
!     return -1;
!   }
!   else
!     return regs.h.al == 0xff;
  }
  
***************
*** 48,52
  
  inline static int
! fp_except_ready(FILE *fp)
  {
    return ferror (fp);

--- 80,84 -----
  
  inline static int
! fd_input_ready(int fd)
  {
  
***************
*** 50,54
  fp_except_ready(FILE *fp)
  {
!   return ferror (fp);
  }
  

--- 82,98 -----
  fd_input_ready(int fd)
  {
! 
!   __dpmi_regs regs;
! 
!   regs.x.ax = 0x4406;
!   regs.x.bx = fd;
!   __dpmi_int (0x21, &regs);
!   if (regs.x.flags & 1)
!   {
!     errno = __doserr_to_errno (regs.x.ax);
!     return -1;
!   }
!   else
!     return regs.h.al == 0xff;
  }
  
***************
*** 53,64
  }
  
! /*
!    @txh
!     @node select, unix
!      @subheading Syntax
!       @example
!        #include <time.h>
! */
! int select(int nfds,
  	fd_set *readfds,
  	fd_set *writefds,

--- 97,102 -----
  }
  
! int
! select(int nfds,
  	fd_set *readfds,
  	fd_set *writefds,
***************
*** 65,69
  	fd_set *exceptfds,
  	struct timeval *timeout)
- /*@end example*/
  {
    /*

--- 103,106 -----
  	fd_set *exceptfds,
  	struct timeval *timeout)
  {
    int ready;
***************
*** 67,99
  /*@end example*/
  {
-   /*
-      @subheading Description
-       This function waits for files to be ready for input or output, or for
-       a timeout.  Each fd_set represents a set of bits representing file
-       descriptors.  The following macros shall be used to deal with these
-       sets:
- 
-       @table @code
-        @item FD_ZERO(p)
-         Initialize the set to all zeros.
-        @item FD_SET(n, p)
-         Set member @var{n} in set @var{p}.
-        @item FD_CLR(n, p)
-         Clear member @var{n} in set @var{p}.
-        @item FD_ISSET(n, p)
-         Return the value of member @var{n} in set @var{p}.
-       @end table
- 
-       The @var{timeout} value may be a NULL pointer (no timeout), a pointer
-       to a zero-value structure (poll mode), or a pointer to an
-       interval-filled structure (timeout).
- 
-      @subheading Return Value
-       The number of files ready.  The input sets are replaced with sets that
-       describe which files are ready for which operations.
- 
-      @end txh
-    */
- 
    int ready;
    fd_set oread, owrite, oexcept;

--- 104,107 -----
  	struct timeval *timeout)
  {
    int ready;
    fd_set oread, owrite, oexcept;
***************
*** 147,152
  	    ready++, FD_SET(i, &oread);
  	}
! /*        else if ((ioctl_result = fd_input_ready (i)) == -1)
!           return -1; */
          else if (ioctl_result)
            ready++, FD_SET (i, &oread);

--- 155,160 -----
  	    ready++, FD_SET(i, &oread);
  	}
!         else if ((ioctl_result = fd_input_ready (i)) == -1)
!           return -1;
          else if (ioctl_result)
            ready++, FD_SET (i, &oread);
***************
*** 159,164
  	    ready++, FD_SET(i, &owrite);
  	}
! /*        else if ((ioctl_result = fd_output_ready (i)) == -1)
!           return -1;*/
          else if (ioctl_result)
            ready++, FD_SET (i, &owrite);

--- 167,172 -----
  	    ready++, FD_SET(i, &owrite);
  	}
!         else if ((ioctl_result = fd_output_ready (i)) == -1)
!           return -1;
          else if (ioctl_result)
            ready++, FD_SET (i, &owrite);

--=====================_874634699==_
Content-Type: text/plain; charset="us-ascii"



--=====================_874634699==_--

- Raw text -


  webmaster     delorie software   privacy  
  Copyright © 2019   by DJ Delorie     Updated Jul 2019