delorie.com/archives/browse.cgi   search  
Mail Archives: djgpp-workers/2005/05/15/04:42:42

X-Authentication-Warning: delorie.com: mail set sender to djgpp-workers-bounces using -f
From: <ams AT ludd DOT ltu DOT se>
Message-Id: <200505140100.j4E10PQY004042@speedy.ludd.ltu.se>
Subject: Re: DJGPP v2.04 Bugs - suggested patch
To: DJGPP-WORKERS <djgpp-workers AT delorie DOT com>
Date: Sat, 14 May 2005 03:00:25 +0200 (CEST)
X-Mailer: ELM [version 2.4ME+ PL78 (25)]
MIME-Version: 1.0
X-ltu-MailScanner-Information: Please contact the ISP for more information
X-ltu-MailScanner: Found to be clean
X-MailScanner-From: ams AT ludd DOT ltu DOT se
Reply-To: djgpp-workers AT delorie DOT com

According to Charles Sandmann:
> > I've de-spaghetti-fied it and if you tell me exactly under which
> > conditions it should retry, I'll add that and post a patch.
> > 
> > Most optimal would be the if statement, something like:
> > /* Carry from INT 0x21,AX=0x716c set. */
> > if( r.x.ax == X && some other condition )
> 
> I got a chance today to code for the first time in a long time.  Attached
> is a fix that seems to work.

I prefer this. Much more clear. Here I understand what's
happening. But generates bigger code, ~150 bytes. As the patch seems
to bigger and much less readable I've included the source with the
headers removed.


Right,

						MartinS
_open.c:
...
int
_open(const char* filename, int oflag)
{
  __dpmi_regs r;
  int rv;
  int use_lfn = _USE_LFN;

  if (filename == 0)
  {
    errno = EINVAL;
    return -1;
  }

  if (__FSEXT_call_open_handlers_wrapper(__FSEXT_open, &rv, filename, oflag))
    return rv;

  if(use_lfn) {
    if( _os_trueversion == 0x532) {
      /* Windows 2000 or XP; or NT with LFN TSR.  Windows 2000 behaves
         badly when using IOCTL and write-truncate calls on LFN handles.
         We convert the long name to a short name and open existing files
         via short name.  New files use LFN, but we know they aren't
         character devices. */
      r.x.ax = 0x7160;
      r.x.cx = 1;                               /* Get short name equivalent */
      r.x.ds = __tb_segment;
      r.x.si = __tb_offset;             /* Long name to convert - putpath */
      r.x.es = __tb_segment;
      r.x.di = __tb_offset + _put_path(filename);       /* Short name destinati\
on */
      __dpmi_int(0x21, &r);
      if(!(r.x.flags & 1)) {            /* Get short name success */
        r.x.ax = 0x6c00;
        r.x.bx = (oflag & 0xff);
        r.x.dx = 1;                     /* Open existing file */
        r.x.si = r.x.di;
        r.x.cx = 0;
        __dpmi_int(0x21, &r);
        if(r.x.flags & 1) {
          errno = __doserr_to_errno(r.x.ax);
          return -1;
        }
      } else {
        /* Short name get failed, file doesn't exist or is device (same error) \
*/
        r.x.ax = 0x7143;                        /* Get attributes */
        r.h.bl = 0;
        r.x.dx = __tb_offset;           /* Original long name */
        __dpmi_int(0x21, &r);           /* This is same as lfn _chmod */
        if(!(r.x.flags & 1)) {          /* Name exists, probably device */
          r.x.ax = 0x6c00;
          r.x.bx = (oflag & 0xff);
          r.x.dx = 1;                     /* Open existing file */
          r.x.si = __tb_offset;         /* Treat original name as short */
          r.x.cx = 0;
          __dpmi_int(0x21, &r);
          if(!(r.x.flags & 1)) {                /* Success! */
            __file_handle_set(r.x.ax, O_BINARY);
            return r.x.ax;
          }
          /* Fail on short name open after _chmod said OK.
             Device with directory?  We should re-try with LFN.
             Permission?  Readonly file?  We should quit.
             Let it fall through to the LFN open which should succeed.  */
        }
      }
    }

    r.x.ax = 0x716c;
    r.x.bx = (oflag & 0xff);
    /* The FAT32 bit should _not_ be set on Windows 2000, because
       that bit fails function 716Ch on W2K.  The test below is
       based on the assumption that W2K returns DOS version 5.  */
    if (7 <= _osmajor && _osmajor < 10) {
      r.x.bx |= 0x1000; /* 0x1000 is FAT32 extended size. */
    }
    r.x.dx = 1;                 /* Open existing file */
    r.x.si = __tb_offset;
    r.x.ds = __tb_segment;
    _put_path(filename);
    r.x.cx = 0;
    __dpmi_int(0x21, &r);
    if (r.x.flags & 1) {
      if (r.x.ax == 80) {
        /* Need to retry because XP file servers fails with error 80. */
        r.h.ah = 0x3d;
        r.h.al = oflag;
        r.x.dx = __tb_offset;
        r.x.ds = __tb_segment;
        _put_path(filename);
        r.x.cx = 0;
        __dpmi_int(0x21, &r);
        if (!(r.x.flags & 1)) {
          __file_handle_set(r.x.ax, O_BINARY);
          return r.x.ax;
        }
        /* Fall through. */
      }
      errno = __doserr_to_errno(r.x.ax);
      return -1;
    }
    __file_handle_set(r.x.ax, O_BINARY);
    return r.x.ax;
  } else {
    if (7 <= _osmajor && _osmajor < 10) {
      r.x.ax = 0x6c00;
      r.x.bx = (oflag & 0xff) | 0x1000; /* 0x1000 is FAT32 extended size. */
      /* FAT32 extended size flag doesn't help on WINDOZE 4.1 (98). It
         seems it has a bug which only lets you create these big files
         if LFN is enabled. */
      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.ds = __tb_segment;
    _put_path(filename);
    r.x.cx = 0;
    __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;
  }
}

- Raw text -


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