X-Authentication-Warning: delorie.com: mail set sender to djgpp-bounces using -f X-Recipient: djgpp AT delorie DOT com DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=gamma; h=mime-version:in-reply-to:references:date:message-id:subject:from:to :cc:content-type:content-transfer-encoding; bh=UT7gQafspANHAEMtRU0UPRKn9BQpnTVNLFhr6YjYZ0Q=; b=P/5xpHHoN0q+CFo3oKwrrBiDkLcspzMfbPJ1/tdtLjGz/NMSl/SCk7+5RLy07szzPG HNuLAjbsmEfyLjRL4f3Cqp+uN749w1L4g+7oeI9EuihQ21IDC6ddTrLcdLfcnO+C/JQY tc5BPB7fYzNj09X7RocpIeAxODoAVdOZuL1W4= MIME-Version: 1.0 In-Reply-To: <201109171356.53360.juan.guerrero@gmx.de> References: <201109171356 DOT 53360 DOT juan DOT guerrero AT gmx DOT de> Date: Sat, 17 Sep 2011 15:56:30 +0300 Message-ID: Subject: Re: Isues concerning the INT 21 Windows95 - LONG FILENAME FUNCTIONS (0x71XX) implementation. From: Ozkan Sezer To: Juan Manuel Guerrero Cc: djgpp AT delorie DOT com Content-Type: text/plain; charset=ISO-8859-1 Content-Transfer-Encoding: 8bit X-MIME-Autoconverted: from quoted-printable to 8bit by delorie.com id p8HCuZUV028554 Reply-To: djgpp AT delorie DOT com Errors-To: nobody AT delorie DOT com X-Mailing-List: djgpp AT delorie DOT com X-Unsubscribes-To: listserv AT delorie DOT com Precedence: bulk On Sat, Sep 17, 2011 at 2:56 PM, Juan Manuel Guerrero wrote: > Here is a patch >  - to set always the CF flag before calling a 0x71XX function >  - to check that AX does not contain 0x7100 after return signaling >    that the driver supports the called function. >  - to react if the driver does not support the function. > In almost all cases I followed Eli Zaretskii's suggestions. > > I have tested it on: >  MSDOS 6.22 with and without DOSLFN 0.40c/e >  FreedOS 1.0 with and without DOSLFN 0.40c >  Win 98SE (dos box/prompt) >  MSDOS 7.0  with and without DOSLFN 0.40c/e >  WinXP Prof SP3 (dos box/prompt) > I have not experienced any difficulties. > Unfortunately I have not the time to check other LFN drivers but I assume > that if the changes work for one driver it work for all drivers. > The procedure is always the same: set CF before calling, check that AX != 0x7100 > and react if the function is not supported. > > As usual suggestions, objections, comments are welcome. > > > Regards, > Juan M. Guerrero > Tested this _very_ briefly on IBM PC-DOS 7 + DOSLFN 0.40e (from http://adoxa.110mb.com/doslfn/) by running hexen2 for dos, no problems so far with or without doslfn loaded in memory. FWIW, though, I have to note that all disk access was in 8.3 style. With doslfn loaded, the hard disk scratching was unbearable to hear. Living with conventional dos is a bliss.. -- O.S. > > 2011-09-16  Juan Manuel Guerrero   > >        * src/libc/dos/io/flushdc.c: Check that 0x710D call is supported >        by checking that AX does not contain 0x7100.  If not supported fall >        back on BIOS DISK RESET.  Set CF before calling 0x710D function. > > > 2011-09-15  Juan Manuel Guerrero   > >        * src/libc/posix/sys/stat/fixpath.c: Check that 0x7147 call is supported >        by checking that AX does not contain 0x7100.  If not supported fall >        back on 0x47NN.  Set CF before calling 0x713B function. > >        * src/libc/posix/unistd/getcwd.c: Check that 0x713B call is supported >        by checking that AX does not contain 0x7100.  If not supported fall >        back on 0x3BNN.  Set CF before calling 0x7147 function. > >        * src/libcdos/process/dosexec.c: Check that 0x7160 call is supported >        by checking that AX does not contain 0x7100.  If not supported ignore. >        Set CF before calling 0x7160 function. > >        * src/libc/posix/dirent/opendir.c: Check that 0x71A1 call is supported >        by checking that AX does not contain 0x7100.  If not supported ignore. >        Set CF before calling 0x71A1 function. > >        * src/libc/posix/sys/stat/mkdir.c: Check that 0x7139 call is supported >        by checking that AX does not contain 0x7100.  If not supported fall >        back on 0x39NN.  Set CF before calling 0x7139 function. > >        * src/libc/posix/unistd/rmdir.c: Check that 0x713A call is supported >        by checking that AX does not contain 0x7100.  If not supported fail. >        Set CF before calling 0x713A function. > >        * src/libc/posix/unistd/chdir.c: Check that 0x713B call is supported >        by checking that AX does not contain 0x7100.  If not supported fall >        back on 0x3BNN.  Set CF before calling 0x713B function. > > > 2011-09-13  Juan Manuel Guerrero   > >        * src/libc/posix/sys/stat/fstat.c:  Check that 0x71A6 call is >        supported by checking that AX does not contain 0x7100.  If not >        supported ignore.  Set CF before calling 0x71A6 function. > >        * src/libc/posix/sys/stat/filelen.c:  Check that 0x71A6 call is >        supported by checking that AX does not contain 0x7100.  If not >        supported fall back on 0x42NN.  Set CF before calling 0x71A6 >        function. > >        * src/libc/posix/sys/stat/lfilelen.c:  Check that 0x71A6 call is >        supported by checking that AX does not contain 0x7100.  If not >        supported fall back on 0x42NN.  Set CF before calling 0x71A6 >        function. > >        * src/libc/posix/sys/stat/fchmod.c: If 0x71A6 function not supported >        fail.  Set CF before calling 0x71A6 function. > >        * src/libc/dos/io/_open.c: If 0x716C function not supported fall >        back on SFN.  Set CF before calling 0x716C function. > > > 2011-09-12  Juan Manuel Guerrero   > >        * src/libc/dos/io/_creat_n.c: If 0x716C function not supported fall >        back on SFN.  Set CF before calling 0x716C function. > >        * src/libc/dos/io/_creat.c: If 0x716C function not supported fall >        back on SFN.  Set CF before calling 0x716C function. > >        * src/libc/dos/io/_chmod.c: If 0x7143 function not supported fail. >        Set CF before calling 0x7143 function. > >        * src/libc/dos/lfn/lfnshort.c: If 0x71a8 function not supported fall >        back on SFN.  Set CF before calling 0x71a8 function. > >        * src/libc/dos/lfn/_use_lfn.c: Set CF before calling 0x71a0 function. > > > 2011-09-09  Juan Manuel Guerrero   > >        * src/libc/ansi/stdio/_rename.c: Check that 0x71A6 call is supported >        by checking that AX does not contain 0x7100.  If not supported fail. >        Set CF before calling 0x71A6 function. > >        * src/libc/ansi/stdio/remove.c: Check that 0x713A and 0x7141 calls are >        supported by checking that AX does not contain 0x7100.  If not supported >        fail.  Set CF before calling 0x71NN function. > >        * src/libc/ansi/stdio/findfirs.c: Check that 0x714E call is supported >        by checking that AX does not contain 0x7100.  If not supported fail. >        Set CF before calling 0x714E function. > >        * src/libc/ansi/stdio/findnext.c: Check that 0x714F call is supported >        by checking that AX does not contain 0x7100.  If not supported fail. >        Set CF before calling 0x714F function. > >        * src/libc/dos/dos/truename.c: Check that 0x7160 call is supported >        by checking that AX does not contain 0x7100.  If not supported fall >        back on 0x6000.  Set CF before calling 0x7160 function. > > > > > > > diff -aprNU5 djgpp.orig/src/libc/ansi/stdio/_rename.c djgpp/src/libc/ansi/stdio/_rename.c > --- djgpp.orig/src/libc/ansi/stdio/_rename.c    2001-03-18 16:52:40 +0000 > +++ djgpp/src/libc/ansi/stdio/_rename.c 2011-09-16 20:06:46 +0000 > @@ -1,5 +1,6 @@ > +/* Copyright (C) 2011 DJ Delorie, see COPYING.DJ for details */ >  /* Copyright (C) 2001 DJ Delorie, see COPYING.DJ for details */ >  /* Copyright (C) 2000 DJ Delorie, see COPYING.DJ for details */ >  /* Copyright (C) 1999 DJ Delorie, see COPYING.DJ for details */ >  /* Copyright (C) 1998 DJ Delorie, see COPYING.DJ for details */ >  /* Copyright (C) 1997 DJ Delorie, see COPYING.DJ for details */ > @@ -67,11 +68,11 @@ int _rename(const char *old, const char >        makes OLD and NEW the same file.  We must rename >        through a temporary file to work around this.  */ > >     char *pbase = 0, *p; >     static char try_char[] = "abcdefghijklmnopqrstuvwxyz012345789"; > -    int idx = sizeof(try_char)-1; > +    int idx = sizeof(try_char) - 1; > >     /* Generate a temporary name.  Can't use `tmpnam', since $TMPDIR >        might point to another drive, which will fail the DOS call.  */ >     strcpy(tempfile, old); >     for (p = tempfile; *p; p++)        /* ensure temporary is on the same drive */ > @@ -88,16 +89,19 @@ int _rename(const char *old, const char >       if (idx <= 0) >        return -1; >       *pbase = try_char[--idx]; >     } while (_chmod(tempfile, 0) != -1); > > +    r.x.flags |= 1;  /* Always set CF before calling a 0x71NN function. */ >     r.x.ax = 0x7156; >     _put_path2(tempfile, olen); >     _put_path(old); >     __dpmi_int(0x21, &r); > -    if (r.x.flags & 1) > +    if (r.x.flags & 1 || r.x.ax == 0x7100) >     { > +      /*  Never assume that the complete LFN API is implemented, > +          so check that AX != 0x7100.  E.G.: MSDOS 6.22 and DOSLFN 0.40.  */ >       errno = __doserr_to_errno(r.x.ax); >       return -1; >     } > >     /* Now create a file with the original name.  This will > @@ -109,14 +113,17 @@ int _rename(const char *old, const char >     olen = strlen(tempfile) + 1; >     old  = tempfile; >     r.x.di = __tb_offset + olen; >   } > > -  for (i=0; i<2; i++) > +  for (i = 0; i < 2; i++) >   { > -    if(use_lfn) > +    if (use_lfn) > +    { > +      r.x.flags |= 1;  /* Always set CF before calling a 0x71NN function. */ >       r.x.ax = 0x7156; > +    } >  #if 0 >     /* It seems that no version of DOS, including DOS 8, which is part >        of Windows/ME, implements this function.  Without LFN, this fails >        _rename on Windows/ME.  Disabled.  */ >     else if ((_osmajor > 7 && _osmajor < 10) /* OS/2 returns v10 and above */ > @@ -133,12 +140,15 @@ int _rename(const char *old, const char >     else >       r.h.ah = 0x56; >     _put_path2(new, olen); >     _put_path(old); >     __dpmi_int(0x21, &r); > -    if(r.x.flags & 1) > +    if (r.x.flags & 1 && r.x.ax != 0x7100) >     { > +      /*  Never assume that the complete LFN API is implemented, > +          so check that AX != 0x7100.  E.G.: MSDOS 6.22 and DOSLFN 0.40.  */ > + >       if (i == 0 >          && !identical_but_for_case /* don't nuke OLD! */ >          && (r.x.ax == 5 || (r.x.ax == 2 && __file_exists(old)) >              /* Windows 2000 returns B7h when the target file exists.  */ >              || r.x.ax == 0xb7)) > diff -aprNU5 djgpp.orig/src/libc/ansi/stdio/remove.c djgpp/src/libc/ansi/stdio/remove.c > --- djgpp.orig/src/libc/ansi/stdio/remove.c     2006-01-18 16:13:10 +0000 > +++ djgpp/src/libc/ansi/stdio/remove.c  2011-09-16 20:06:46 +0000 > @@ -1,5 +1,6 @@ > +/* Copyright (C) 2011 DJ Delorie, see COPYING.DJ for details */ >  /* Copyright (C) 2003 DJ Delorie, see COPYING.DJ for details */ >  /* Copyright (C) 2002 DJ Delorie, see COPYING.DJ for details */ >  /* Copyright (C) 2000 DJ Delorie, see COPYING.DJ for details */ >  /* Copyright (C) 1998 DJ Delorie, see COPYING.DJ for details */ >  /* Copyright (C) 1996 DJ Delorie, see COPYING.DJ for details */ > @@ -57,28 +58,33 @@ remove(const char *fn) >   /* Now delete it.  Note, _chmod leaves dir name in transfer buffer. */ >   if (directory_p) >     r.h.ah = 0x3a;             /* DOS Remove Directory function */ >   else >     r.h.ah = 0x41;             /* DOS Remove File function */ > -  if(use_lfn) { > +  if (use_lfn) > +  { > +    r.x.flags |= 1;            /* Always set CF before calling a 0x71NN function. */ >     r.h.al = r.h.ah; >     r.h.ah = 0x71; >     r.x.si = 0;                        /* No Wildcards */ >   } >   r.x.cx = 0;                  /* Fix for ROM-DOS */ >   r.x.dx = __tb_offset; >   r.x.ds = __tb_segment; >   __dpmi_int(0x21, &r); > -  if(r.x.flags & 1) > +  if (r.x.flags & 1 || r.x.ax == 0x7100) >   { > +    /*  Never assume that the complete LFN API is implemented, > +        so check that AX != 0x7100.  E.G.: MSDOS 6.22 and DOSLFN 0.40.  */ > + >     /* We failed.  Leave the things as we've found them.  */ >     int e = __doserr_to_errno(r.x.ax); > >     /* We know the file exists, so ENOENT at this point means a bug. >        Since write-protected floppies are the most probable cause, >        return EACCES instead.  */ > -    if(e == ENOENT) > +    if (e == ENOENT) >       e = EACCES; > >     _chmod(real_name, 1, attr & 0xffe7); >     errno = e; >     return -1; > diff -aprNU5 djgpp.orig/src/libc/dos/dir/findfirs.c djgpp/src/libc/dos/dir/findfirs.c > --- djgpp.orig/src/libc/dos/dir/findfirs.c      2008-04-09 04:13:38 +0000 > +++ djgpp/src/libc/dos/dir/findfirs.c   2011-09-16 20:06:46 +0000 > @@ -1,5 +1,6 @@ > +/* Copyright (C) 2011 DJ Delorie, see COPYING.DJ for details */ >  /* Copyright (C) 2002 DJ Delorie, see COPYING.DJ for details */ >  /* Copyright (C) 1996 DJ Delorie, see COPYING.DJ for details */ >  /* Copyright (C) 1995 DJ Delorie, see COPYING.DJ for details */ >  #include >  #include > @@ -30,11 +31,12 @@ findfirst(const char *pathname, struct f >   attrib &= 0xff; > >   pathlen = strlen(pathname) + 1; > >   _put_path(pathname); > -  if(use_lfn) { > +  if (use_lfn) > +  { > >     /* si = 1 indicates DOS style dates, 0 means Win32 type dates. >        DOS style dates are broken in some Win95 betas, build for either. >        Release works with DOS date, it's faster, so use it. */ >     #define USEDOSDATE 1 > @@ -42,19 +44,24 @@ findfirst(const char *pathname, struct f >       #define _Win32_to_DOS (long) >     #else >       extern long _Win32_to_DOS(long long WinTime); >     #endif > > +    r.x.flags |= 1;  /* Always set CF before calling a 0x71NN function. */ >     r.x.ax = 0x714e; >     r.x.cx = attrib; >     r.x.dx = __tb_offset; >     r.x.ds = __tb_segment; >     r.x.di = __tb_offset + pathlen; >     r.x.es = r.x.ds; >     r.x.si = USEDOSDATE; >     __dpmi_int(0x21, &r); > -    if(!(r.x.flags & 1)) { > +    if (!(r.x.flags & 1) && r.x.ax != 0x7100) > +    { > +      /*  Never assume that the complete LFN API is implemented, > +          so check that AX != 0x7100.  E.G.: MSDOS 6.22 and DOSLFN 0.40.  */ > + >       struct ffblklfn ffblk32; >       unsigned long t1; >       /* Recover results */ >       dosmemget(__tb+pathlen, sizeof(struct ffblklfn), &ffblk32); > > @@ -67,11 +74,13 @@ findfirst(const char *pathname, struct f >       ffblk->ff_fsize = ffblk32.fd_size; >       strcpy(ffblk->ff_name, ffblk32.fd_longname); >       strcpy(ffblk->lfn_magic, "LFN32"); > >       /* If no wildcards, close the handle */ > -      if(!strchr(pathname,'*') && !strchr(pathname,'?')) { > +      if (!strchr(pathname, '*') && !strchr(pathname, '?')) > +      { > +        r.x.flags |= 1;  /* Always set CF before calling a 0x71NN function. */ >         r.x.bx = r.x.ax; >         r.x.ax = 0x71a1; >         __dpmi_int(0x21, &r); >         r.x.ax = 0; >       } > @@ -85,11 +94,13 @@ findfirst(const char *pathname, struct f >       ffblk->lfn_atime = t1; >       ffblk->lfn_adate = t1 >> 16; > >       return 0; >     } > -  } else { > +  } > +  else > +  { > >     #define _sizeof_dos_ffblk 44 >     /* There will be a _sizeof_dos_ffblk character return value from findfirst >        in the DTA.  Put the file name before this.  First set the DTA to be >        transfer buffer. */ > @@ -102,13 +113,14 @@ findfirst(const char *pathname, struct f >     r.h.ah = 0x4e; >     r.x.dx = __tb_offset; >     r.x.ds = __tb_segment; >     r.x.cx = attrib; >     __dpmi_int(0x21, &r); > -    if(!(r.x.flags & 1)) { > +    if (!(r.x.flags & 1)) > +    { >       /* Recover results */ > -      dosmemget(__tb+pathlen, _sizeof_dos_ffblk, ffblk); > +      dosmemget(__tb + pathlen, _sizeof_dos_ffblk, ffblk); >       return 0; >     } >   } > >   errno = __doserr_to_errno(r.x.ax); > diff -aprNU5 djgpp.orig/src/libc/dos/dir/findnext.c djgpp/src/libc/dos/dir/findnext.c > --- djgpp.orig/src/libc/dos/dir/findnext.c      2008-04-09 04:13:38 +0000 > +++ djgpp/src/libc/dos/dir/findnext.c   2011-09-16 20:06:46 +0000 > @@ -1,5 +1,6 @@ > +/* Copyright (C) 2011 DJ Delorie, see COPYING.DJ for details */ >  /* Copyright (C) 1996 DJ Delorie, see COPYING.DJ for details */ >  /* Copyright (C) 1995 DJ Delorie, see COPYING.DJ for details */ >  #include >  #include >  #include > @@ -19,11 +20,11 @@ findnext(struct ffblk *ffblk) >   { >     errno = EACCES; >     return -1; >   } > > -  if(_USE_LFN) > +  if (_USE_LFN) >   { >     /* si = 1 indicates DOS style dates, 0 means Win32 type dates. >        DOS style dates are broken in some Win95 betas, build for either. >        Release works with DOS date, it's faster, so use it. */ >     #define USEDOSDATE 1 > @@ -31,24 +32,28 @@ findnext(struct ffblk *ffblk) >       #define _Win32_to_DOS (long) >     #else >       extern long _Win32_to_DOS(long long WinTime); >     #endif > > +    r.x.flags |= 1;  /* Always set CF before calling a 0x71NN function. */ >     r.x.ax = 0x714f; >     r.x.bx = ffblk->lfn_handle; > -    if(!r.x.bx) > +    if (!r.x.bx) >     { >       errno = ENMFILE; >       return 1; >     } >     r.x.di = __tb_offset; >     r.x.es = __tb_segment; >     r.x.si = USEDOSDATE; > >     __dpmi_int(0x21, &r); > -    if (!(r.x.flags & 1)) > +    if (!(r.x.flags & 1) && r.x.ax != 0x7100) >     { > +      /*  Never assume that the complete LFN API is implemented, > +          so check that AX != 0x7100.  E.G.: MSDOS 6.22 and DOSLFN 0.40.  */ > + >       unsigned long t1; >       struct ffblklfn ffblk32; >       /* Recover results */ >       dosmemget(__tb, sizeof(struct ffblklfn), &ffblk32); > > @@ -69,13 +74,14 @@ findnext(struct ffblk *ffblk) >     } >     errno = __doserr_to_errno(r.x.ax); >     if (errno == ENMFILE)         /* call FindClose */ >     { >       ffblk->lfn_handle = 0; > +      r.x.flags |= 1;  /* Always set CF before calling a 0x71NN function. */ >       r.x.ax = 0x71a1; >       __dpmi_int(0x21, &r); > -      if(r.x.flags & 1) > +      if (r.x.flags & 1) >       { >         errno = __doserr_to_errno(r.x.ax); >         return -1; >       } >       return 1; > @@ -95,11 +101,11 @@ findnext(struct ffblk *ffblk) > >     dosmemput(ffblk, sizeof(struct ffblk), __tb); > >     r.h.ah = 0x4f; >     __dpmi_int(0x21, &r); > -    if(r.x.flags & 1) > +    if (r.x.flags & 1) >     { >       errno = __doserr_to_errno(r.x.ax); >       return -1; >     } > > diff -aprNU5 djgpp.orig/src/libc/dos/dos/truename.c djgpp/src/libc/dos/dos/truename.c > --- djgpp.orig/src/libc/dos/dos/truename.c      2003-08-09 12:32:10 +0000 > +++ djgpp/src/libc/dos/dos/truename.c   2011-09-16 20:06:46 +0000 > @@ -1,5 +1,6 @@ > +/* Copyright (C) 2011 DJ Delorie, see COPYING.DJ for details */ >  /* Copyright (C) 2003 DJ Delorie, see COPYING.DJ for details */ >  /* Copyright (C) 1997 DJ Delorie, see COPYING.DJ for details */ >  /* Copyright (C) 1995 DJ Delorie, see COPYING.DJ for details */ >  /* >  * This is file TRUENAME.C > @@ -103,57 +104,72 @@ _truename_internal(const char *file, cha >       name_start[4] = '\0'; >     } >   _put_path(name_start); > >   /* Call DOS INT 21H undocumented function 60h. */ > -  if(use_lfn) { > +  if (use_lfn) > +  { > +    regs.x.flags |= 1;  /* Always set CF before calling a 0x71NN function. */ >     regs.x.ax = 0x7160; >     /* Get Long Path Name (if there is one) and we want it. */ >     regs.x.cx = try_lfn ? 2 : 0; > -  } else > +  } > +  else >     regs.x.ax = 0x6000; > >   /* According to Ralph Brown's Interrupt List, can't make the input >      and output buffers be the same, because it doesn't work for early >      versions of DR-DOS.  */ > - lfn_retry: > +lfn_retry: >   regs.x.ds = regs.x.es = __tb_segment; >   regs.x.si = __tb_offset; >   regs.x.di = __tb_offset + MAX_TRUE_NAME; >   __dpmi_int(0x21, ®s); > >   /* Now get the result from lower memory. */ >   movedata(dos_mem_selector, __tb + MAX_TRUE_NAME, >            our_mem_selector, (unsigned int)true_name, MAX_TRUE_NAME); > >   if (regs.x.flags & 1) > +  { > +    if (use_lfn) >     { > -      if (use_lfn && first_time) > -       { > -         /* If the file doesn't exist, 217160/CX=2 fails.  Try again > -            with CX=0, so that this time it won't validate the path.  */ > -         first_time = 0; > -         regs.x.ax = 0x7160; > -         regs.x.cx = 0; > -         goto lfn_retry; > -       } > -      errno = __doserr_to_errno(regs.x.ax); > -      return (char *)0; > +      if (regs.x.ax == 0x7100) > +      { > +        /*  Never assume that the complete LFN API is implemented, > +            so check that AX != 0x7100.  E.G.: MSDOS 6.22 and DOSLFN 0.40. > +            If not supported fall back on 0x6000.  */ > +        use_lfn = 0; > +        regs.x.ax = 0x6000; > +        goto lfn_retry; > +      } > +      else if (first_time) > +      { > +        /* If the file doesn't exist, 217160/CX=2 fails.  Try again > +           with CX=0, so that this time it won't validate the path.  */ > +        first_time = 0; > +        regs.x.ax = 0x7160; > +        regs.x.cx = 0; > +        goto lfn_retry; > +      } >     } > +    errno = __doserr_to_errno(regs.x.ax); > +    return (char *)0; > +  } >   else > +  { > +    if (buf == (char *)0) > +      buf = (char *)malloc(strlen(true_name) + 1); > +    if (buf == (char *)0) > +      errno = ENOMEM; > +    else >     { > -      if (buf == (char *)0) > -        buf = (char *)malloc(strlen(true_name)+1); > -      if (buf == (char *)0) > -        errno = ENOMEM; > -      else > -        { > -          errno = e; > -          strcpy(buf, true_name); > -        } > -      return buf; > +      errno = e; > +      strcpy(buf, true_name); >     } > +    return buf; > +  } >  } > >  char * >  _truename(const char *file, char *buf) >  { > diff -aprNU5 djgpp.orig/src/libc/dos/io/_chmod.c djgpp/src/libc/dos/io/_chmod.c > --- djgpp.orig/src/libc/dos/io/_chmod.c 1996-08-31 22:09:32 +0000 > +++ djgpp/src/libc/dos/io/_chmod.c      2011-09-16 20:06:46 +0000 > @@ -1,5 +1,6 @@ > +/* Copyright (C) 2011 DJ Delorie, see COPYING.DJ for details */ >  /* Copyright (C) 1996 DJ Delorie, see COPYING.DJ for details */ >  /* Copyright (C) 1995 DJ Delorie, see COPYING.DJ for details */ >  #include >  #include >  #include > @@ -11,22 +12,25 @@ >  int >  _chmod(const char *filename, int func, ...) >  { >   __dpmi_regs r; > > -  if(_USE_LFN) { > +  if (_USE_LFN) > +  { > +    r.x.flags |= 1;                    /* Always set CF before calling a 0x71NN function. */ >     r.x.ax = 0x7143; >     r.h.bl = func;                     /* Get or Put */ > -  } else > +  } > +  else >     r.x.ax = 0x4300 + func; >   _put_path(filename); >   if (func == 1) >     r.x.cx = *(&func + 1);             /* Value to set */ >   r.x.dx = __tb_offset; >   r.x.ds = __tb_segment; >   __dpmi_int(0x21, &r); > -  if(r.x.flags & 1) > +  if (r.x.flags & 1) >   { >     errno = __doserr_to_errno(r.x.ax); >     return -1; >   } > > diff -aprNU5 djgpp.orig/src/libc/dos/io/_creat.c djgpp/src/libc/dos/io/_creat.c > --- djgpp.orig/src/libc/dos/io/_creat.c 2002-06-14 14:25:20 +0000 > +++ djgpp/src/libc/dos/io/_creat.c      2011-09-16 20:06:46 +0000 > @@ -1,5 +1,6 @@ > +/* Copyright (C) 2011 DJ Delorie, see COPYING.DJ for details */ >  /* Copyright (C) 2002 DJ Delorie, see COPYING.DJ for details */ >  /* Copyright (C) 2001 DJ Delorie, see COPYING.DJ for details */ >  /* Copyright (C) 1996 DJ Delorie, see COPYING.DJ for details */ >  /* Copyright (C) 1995 DJ Delorie, see COPYING.DJ for details */ >  #include > @@ -29,45 +30,62 @@ _creat(const char* filename, int attrib) >   } > >   if (__FSEXT_call_open_handlers_wrapper(__FSEXT_creat, &rv, filename, attrib)) >     return rv; > > -  if(use_lfn) { > +  if (use_lfn) > +  { > +    r.x.flags |= 1;  /* Always set CF before calling a 0x71NN function. */ >     r.x.ax = 0x716c; >     r.x.bx = 0x0002;           /* Open r/w. */ >     /* 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) { > +    if (7 <= _osmajor && _osmajor < 10) >       r.x.bx |= 0x1000; /* 0x1000 is FAT32 extended size. */ > -    } >     r.x.dx = 0x0012;           /* Create, truncate if exists */ >     r.x.si = __tb_offset; > -  } else { > -    if (7 <= _osmajor && _osmajor < 10) { > +  } > +  else > +  { > +    if (7 <= _osmajor && _osmajor < 10) > +    { >       r.x.ax = 0x6c00; >       r.x.bx = 0x1002;           /* Open r/w with 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 = 0x0012;           /* Create, truncate if exists */ >       r.x.si = __tb_offset; > -    } else { > +    } > +    else > +    { >       r.h.ah = 0x3c; >       r.x.dx = __tb_offset; >     } >   } > +do_create: >   r.x.cx = attrib; >   r.x.ds = __tb_segment; >   _put_path(filename); >   __dpmi_int(0x21, &r); > -  if(r.x.flags & 1) > +  if (r.x.flags & 1) >   { > +    if (r.x.ax == 0x7100) > +    { > +      /*  Never assume that the complete LFN API is implemented, > +          so check that AX != 0x7100.  E.G.: MSDOS 6.22 and DOSLFN 0.40. > +          If not supported fall back on SFN API.  */ > +      use_lfn = 0; > +      r.h.ah = 0x3c; > +      r.x.dx = __tb_offset; > +      goto do_create; > +    } >     errno = __doserr_to_errno(r.x.ax); >     return -1; >   } > -  if(use_lfn && _os_trueversion == 0x532) { > +  if (use_lfn && _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 close the long name file and re-open it with _open.c (short) >        to work around the bugs. */ >     rv = _open(filename, 2);   /* 2 is a read/write flag */ > diff -aprNU5 djgpp.orig/src/libc/dos/io/_creat_n.c djgpp/src/libc/dos/io/_creat_n.c > --- djgpp.orig/src/libc/dos/io/_creat_n.c       2002-06-14 14:25:26 +0000 > +++ djgpp/src/libc/dos/io/_creat_n.c    2011-09-16 20:06:46 +0000 > @@ -1,5 +1,6 @@ > +/* Copyright (C) 2011 DJ Delorie, see COPYING.DJ for details */ >  /* Copyright (C) 2002 DJ Delorie, see COPYING.DJ for details */ >  /* Copyright (C) 2001 DJ Delorie, see COPYING.DJ for details */ >  /* Copyright (C) 1998 DJ Delorie, see COPYING.DJ for details */ >  #include >  #include > @@ -34,16 +35,17 @@ _creatnew(const char* filename, int attr >   _put_path(filename); >   r.x.bx = >     0x2002 | (flags & 0xfff0); /* r/w, no Int 24h, use caller-defined flags */ >   r.x.dx = 0x0010;             /* Create, fail if exists */ >   r.x.si = __tb_offset; > -  if(use_lfn) > +  if (use_lfn) >   { >     if (7 <= _osmajor && _osmajor < 10) >     { >       r.x.bx |= 0x1000;        /* FAT32 extended size. */ >     } > +    r.x.flags |= 1;            /* Always set CF before calling a 0x71NN function. */ >     r.x.ax = 0x716c; >   } >   else >   { >     if (7 <= _osmajor && _osmajor < 10) > @@ -62,25 +64,38 @@ _creatnew(const char* filename, int attr >       r.x.bx = 0;              /* lose support for fancy flags in DOS 3.x */ >       r.x.dx = __tb_offset; >       r.x.si = 0; >     } >   } > +do_create: >   r.x.cx = attrib & 0xffff; >   r.x.ds = __tb_segment; >   __dpmi_int(0x21, &r); > -  if(r.x.flags & 1) > +  if (r.x.flags & 1) >   { > +    if (r.x.ax == 0x7100) > +    { > +      /*  Never assume that the complete LFN API is implemented, > +          so check that AX != 0x7100.  E.G.: MSDOS 6.22 and DOSLFN 0.40. > +          If not supported fall back on SFN API.  */ > +      use_lfn = 0; > +      r.h.ah = 0x5b; > +      r.x.bx = 0;              /* lose support for fancy flags in DOS 3.x */ > +      r.x.dx = __tb_offset; > +      r.x.si = 0; > +      goto do_create; > +    } >     errno = __doserr_to_errno(r.x.ax); >     return -1; >   } > -  if(use_lfn && _os_trueversion == 0x532) { > +  if (use_lfn && _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 close the long name file and re-open it with _open.c (short) >        to work around the bugs. */ >     rv = _open(filename, flags | 2);   /* 2 is a read/write flag */ > -    if(rv != -1) {     /* Re-open failure, continue with LFN handle */ > +    if (rv != -1) {    /* Re-open failure, continue with LFN handle */ >       dup2(rv, r.x.ax);        /* Close ax, put handle in first position (bugs) */ >       _close(rv); >     } >   } >   __file_handle_set(r.x.ax, O_BINARY); > diff -aprNU5 djgpp.orig/src/libc/dos/io/_open.c djgpp/src/libc/dos/io/_open.c > --- djgpp.orig/src/libc/dos/io/_open.c  2002-06-14 14:25:34 +0000 > +++ djgpp/src/libc/dos/io/_open.c       2011-09-16 20:06:46 +0000 > @@ -1,5 +1,6 @@ > +/* Copyright (C) 2011 DJ Delorie, see COPYING.DJ for details */ >  /* Copyright (C) 2002 DJ Delorie, see COPYING.DJ for details */ >  /* Copyright (C) 2001 DJ Delorie, see COPYING.DJ for details */ >  /* Copyright (C) 1996 DJ Delorie, see COPYING.DJ for details */ >  /* Copyright (C) 1995 DJ Delorie, see COPYING.DJ for details */ >  #include > @@ -29,85 +30,108 @@ _open(const char* filename, int oflag) >   } > >   if (__FSEXT_call_open_handlers_wrapper(__FSEXT_open, &rv, filename, oflag)) >     return rv; > > -  if(use_lfn && _os_trueversion == 0x532) { > +  if (use_lfn && _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.flags |= 1;  /* Always set CF before calling a 0x71NN function. */ >     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 destination */ >     __dpmi_int(0x21, &r); > -    if(!(r.x.flags & 1)) {             /* Get short name success */ > +    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; >       goto do_open; > -    } else { > +    } > +    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 */ > +      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! */ > +        if (!(r.x.flags & 1))          /* Success! */ >           goto do_hset; > -        } > + >        /* 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.  */ >       } >     } >   } > -  if(use_lfn) { > +  if (use_lfn) > +  { > +    r.x.flags |= 1;  /* Always set CF before calling a 0x71NN function. */ >     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) { > +    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; > -  } else { > -    if (7 <= _osmajor && _osmajor < 10) { > +  } > +  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 { > +    } > +    else > +    { >       r.h.ah = 0x3d; >       r.h.al = oflag; >       r.x.dx = __tb_offset; >     } >   } >   r.x.ds = __tb_segment; >   _put_path(filename); >  do_open: >   r.x.cx = 0; >   __dpmi_int(0x21, &r); > -  if(r.x.flags & 1) > +  if (r.x.flags & 1) >   { > +    if (r.x.ax == 0x7100) > +    { > +      /*  Never assume that the complete LFN API is implemented, > +          so check that AX != 0x7100.  E.G.: MSDOS 6.22 and DOSLFN 0.40. > +          If not supported fall back on SFN API.  */ > +      use_lfn = 0; > +      r.h.ah = 0x3d; > +      r.h.al = oflag; > +      r.x.dx = __tb_offset; > +      goto do_open; > +    } >     errno = __doserr_to_errno(r.x.ax); >     return -1; >   } >  do_hset: >   __file_handle_set(r.x.ax, O_BINARY); > diff -aprNU5 djgpp.orig/src/libc/dos/io/flushdc.c djgpp/src/libc/dos/io/flushdc.c > --- djgpp.orig/src/libc/dos/io/flushdc.c        1996-09-19 23:38:56 +0000 > +++ djgpp/src/libc/dos/io/flushdc.c     2011-09-16 23:12:04 +0000 > @@ -1,37 +1,44 @@ > +/* Copyright (C) 2011 DJ Delorie, see COPYING.DJ for details */ >  /* Copyright (C) 1996 DJ Delorie, see COPYING.DJ for details */ >  #include >  #include     /* for _USE_LFN */ >  #include                /* for the prototype of `_flush_disk_cache' */ >  #include       /* for `getdisk' */ >  #include      /* for `__dpmi_int' and friends */ > >  /* Try to cause the disk cache to write the cached data to disk(s).  */ >  void > -_flush_disk_cache (void) > +_flush_disk_cache(void) >  { >   __dpmi_regs r; > -  int drv = getdisk (); > +  int drv = getdisk(); > >   if (_USE_LFN) > +  { > +    /* Windows 95 have special function to do what we want.  */ > +    /* FIXME: What if LFN is supported by a platform other than W95?  */ > +    r.x.flags |= 1;  /* Always set CF before calling a 0x71XX function. */ > +    r.x.ax = 0x710d; > +    r.x.cx = 1;      /* flush buffers and cache, reset drive */ > +    r.x.dx = drv + 1; > +    __dpmi_int (0x21, &r); > +    if (r.x.flags & 1 || r.x.ax == 0x7100) >     { > -      /* Windows 95 have special function to do what we want.  */ > -      /* FIXME: What if LFN is supported by a platform other than W95?  */ > -      r.x.ax = 0x710d; > -      r.x.cx = 1;      /* flush buffers and cache, reset drive */ > -      r.x.dx = drv + 1; > -      __dpmi_int (0x21, &r); > -      /* According to docs (Interrupt list), this doesn't return > -        any error codes (??).  */ > -    } > -  else > -    { > -      /* The BIOS Disk Reset function causes most DOS caches to flush.  */ > -      r.x.ax = 0; > -      /* Hard disks should have 7th bit set.  */ > -      /* FIXME: The mapping between DOS drive numbers and BIOS > -        drives is ignored.  The assumption is that Reset function > -        on ANY hard disk causes the cache to flush its buffers.  */ > -      r.x.dx = drv > 2 ? ((drv - 2) | 0x80) : drv; > -      __dpmi_int (0x13, &r); > +      /*  Never assume that the complete LFN API is implemented, > +          so check that AX != 0x7100.  E.G.: MSDOS 6.22 and DOSLFN 0.40. > +          If not supported fall back on SFN API.  */ > +      goto do_BIOS_DISK_RESET; >     } > +    return; > +  } > + > +do_BIOS_DISK_RESET: > +  /* The BIOS Disk Reset function causes most DOS caches to flush.  */ > +  r.x.ax = 0; > +  /* Hard disks should have 7th bit set.  */ > +  /* FIXME: The mapping between DOS drive numbers and BIOS > +     drives is ignored.  The assumption is that Reset function > +     on ANY hard disk causes the cache to flush its buffers.  */ > +  r.x.dx = drv > 2 ? ((drv - 2) | 0x80) : drv; > +  __dpmi_int(0x13, &r); >  } > diff -aprNU5 djgpp.orig/src/libc/dos/lfn/_use_lfn.c djgpp/src/libc/dos/lfn/_use_lfn.c > --- djgpp.orig/src/libc/dos/lfn/_use_lfn.c      2007-12-11 07:27:38 +0000 > +++ djgpp/src/libc/dos/lfn/_use_lfn.c   2011-09-16 20:06:46 +0000 > @@ -1,5 +1,6 @@ > +/* Copyright (C) 2011 DJ Delorie, see COPYING.DJ for details */ >  /* Copyright (C) 2001 DJ Delorie, see COPYING.DJ for details */ >  /* Copyright (C) 1999 DJ Delorie, see COPYING.DJ for details */ >  /* Copyright (C) 1998 DJ Delorie, see COPYING.DJ for details */ >  /* Copyright (C) 1997 DJ Delorie, see COPYING.DJ for details */ >  /* Copyright (C) 1996 DJ Delorie, see COPYING.DJ for details */ > @@ -70,10 +71,11 @@ _get_volume_info (const char *path, int >     _farpokeb(_dos_ds, tbuf_la++, ':'); >     _farpokeb(_dos_ds, tbuf_la++, '\\'); >     _farpokeb(_dos_ds, tbuf_la++, '\0'); >   } > > +  r.x.flags |= 1;      /* Always set CF before calling a 0x71NN function. */ >   r.x.ax = 0x71a0;     /* Get Volume Information function */ >   r.x.ds = tbuf_seg;   /* DS:DX points to root directory name */ >   r.x.dx = 0; >   r.x.es = tbuf_seg;   /* ES:DI points to a buffer for filesys name */ >   r.x.di = (tbuf_la - __tb) & 0xffff; > diff -aprNU5 djgpp.orig/src/libc/dos/lfn/lfnshort.c djgpp/src/libc/dos/lfn/lfnshort.c > --- djgpp.orig/src/libc/dos/lfn/lfnshort.c      1999-06-03 17:27:34 +0000 > +++ djgpp/src/libc/dos/lfn/lfnshort.c   2011-09-16 20:06:46 +0000 > @@ -1,5 +1,6 @@ > +/* Copyright (C) 2011 DJ Delorie, see COPYING.DJ for details */ >  /* Copyright (C) 1999 DJ Delorie, see COPYING.DJ for details */ >  /* Copyright (C) 1998 DJ Delorie, see COPYING.DJ for details */ >  /* Copyright (C) 1997 DJ Delorie, see COPYING.DJ for details */ >  #include >  #include > @@ -19,10 +20,11 @@ char * >  _lfn_gen_short_fname (const char *long_fname, char *short_fname) >  { >   __dpmi_regs r; >   unsigned long tbuf = __tb; > > +  r.x.flags |= 1;  /* Always set CF before calling a 0x71NN function. */ >   r.x.ax = 0x7100; >   if (_USE_LFN) >     { >       dosmemput (long_fname, strlen (long_fname) + 1, tbuf); >       r.x.ax = 0x71a8; > diff -aprNU5 djgpp.orig/src/libc/dos/process/dosexec.c djgpp/src/libc/dos/process/dosexec.c > --- djgpp.orig/src/libc/dos/process/dosexec.c   2005-01-31 08:14:46 +0000 > +++ djgpp/src/libc/dos/process/dosexec.c        2011-09-16 20:06:46 +0000 > @@ -1,5 +1,6 @@ > +/* Copyright (C) 2011 DJ Delorie, see COPYING.DJ for details */ >  /* Copyright (C) 2003 DJ Delorie, see COPYING.DJ for details */ >  /* Copyright (C) 2001 DJ Delorie, see COPYING.DJ for details */ >  /* Copyright (C) 2000 DJ Delorie, see COPYING.DJ for details */ >  /* Copyright (C) 1999 DJ Delorie, see COPYING.DJ for details */ >  /* Copyright (C) 1998 DJ Delorie, see COPYING.DJ for details */ > @@ -208,19 +209,23 @@ direct_exec_tail_1 (const char *program, >   if (!check_talloc(proglen)) >     return -1; >   /* Make sure any magic names, like /dev/c/foo, are converted to the >      usual DOS form, and, under LFN, to the short 8+3 alias.  */ >   _put_path2(program, tbuf_beg == __tb ? tbuf_ptr - tbuf_beg : 0); > -  if(lfn) { > +  if (lfn) > +  { >     unsigned pgm_name_loc = tbuf_beg == __tb ? tbuf_ptr : __tb; > +    r.x.flags |= 1;                    /* Always set CF before calling a 0x71NN function. */ >     r.x.ax = 0x7160;                   /* Truename */ >     r.x.cx = 1;                                /* Get short name */ >     r.x.ds = r.x.es = pgm_name_loc / 16; >     r.x.si = r.x.di = pgm_name_loc & 15; >     __dpmi_int(0x21, &r); > -    if (r.x.flags & 1) > +    if (r.x.flags & 1 || r.x.ax == 0x7100) >     { > +      /*  Never assume that the complete LFN API is implemented, > +          so check that AX != 0x7100.  E.G.: MSDOS 6.22 and DOSLFN 0.40.  */ >       errno = __doserr_to_errno(r.x.ax); >       return -1; >     } >   } >   dosmemget(tbuf_beg == __tb ? tbuf_ptr : __tb, FILENAME_MAX, short_name); > diff -aprNU5 djgpp.orig/src/libc/posix/dirent/opendir.c djgpp/src/libc/posix/dirent/opendir.c > --- djgpp.orig/src/libc/posix/dirent/opendir.c  2008-12-08 17:48:50 +0000 > +++ djgpp/src/libc/posix/dirent/opendir.c       2011-09-16 20:06:46 +0000 > @@ -1,5 +1,6 @@ > +/* Copyright (C) 2011 DJ Delorie, see COPYING.DJ for details */ >  /* Copyright (C) 2008 DJ Delorie, see COPYING.DJ for details */ >  /* Copyright (C) 2001 DJ Delorie, see COPYING.DJ for details */ >  /* Copyright (C) 2000 DJ Delorie, see COPYING.DJ for details */ >  /* Copyright (C) 1998 DJ Delorie, see COPYING.DJ for details */ >  /* Copyright (C) 1997 DJ Delorie, see COPYING.DJ for details */ > @@ -40,15 +41,18 @@ >  void >  _lfn_find_close(int handle) >  { >   __dpmi_regs r; > > +  r.x.flags |= 1;  /* Always set CF before calling a 0x71NN function. */ >   r.x.bx = handle; >   r.x.ax = 0x71a1; >   __dpmi_int(0x21, &r); > -  if (r.x.flags & 1) > +  if (r.x.flags & 1 || r.x.ax == 0x7100) >   { > +    /*  Never assume that the complete LFN API is implemented, > +        so check that AX != 0x7100.  E.G.: MSDOS 6.22 and DOSLFN 0.40.  */ >     errno = __doserr_to_errno(r.x.ax); >   } >  } > >  void > diff -aprNU5 djgpp.orig/src/libc/posix/sys/stat/fchmod.c djgpp/src/libc/posix/sys/stat/fchmod.c > --- djgpp.orig/src/libc/posix/sys/stat/fchmod.c 2003-03-08 00:41:16 +0000 > +++ djgpp/src/libc/posix/sys/stat/fchmod.c      2011-09-16 22:52:50 +0000 > @@ -1,5 +1,6 @@ > +/* Copyright (C) 2011 DJ Delorie, see COPYING.DJ for details */ >  /* Copyright (C) 2003 DJ Delorie, see COPYING.DJ for details */ >  #include >  #include >  #include >  #include > @@ -18,19 +19,22 @@ static int >  get_current_mode (const int fd) >  { >   __dpmi_regs r; >   int         mode = 0; /* Fail by default */ > > -  if (_USE_LFN) { > +  if (_USE_LFN) > +  { > +    r.x.flags |= 1;  /* Always set CF before calling a 0x71NN function. */ >     r.x.ax = 0x71a6; /* File info by handle */ >     r.x.bx = fd; >     r.x.ds = __tb >> 4; >     r.x.dx = 0; > >     __dpmi_int(0x21, &r); > > -    if ((r.x.flags & 1) == 0) { > +    if (!(r.x.flags & 1) && r.x.ax != 0x7100) > +    { >       int attr = _farpeekl(_dos_ds, __tb); > >       mode = S_IRUSR; /* Files are always readable. */ >       if ((attr & 1) == 0) >        mode |= S_IWUSR; > diff -aprNU5 djgpp.orig/src/libc/posix/sys/stat/filelen.c djgpp/src/libc/posix/sys/stat/filelen.c > --- djgpp.orig/src/libc/posix/sys/stat/filelen.c        2011-09-04 21:16:44 +0000 > +++ djgpp/src/libc/posix/sys/stat/filelen.c     2011-09-16 20:06:46 +0000 > @@ -34,15 +34,15 @@ filelength(int fhandle) >      combos work properly.  This assumes this routine is called from fstat() >      before we get the magic number or other things that do both seeks and >      reads. */ >   if (_USE_LFN && (fhandle != 0 || _os_trueversion != 0x532)) >   { > +    regs.x.flags |= 1;  /* Always set CF before calling a 0x71NN function. */ >     regs.x.ax = 0x71A6; >     regs.x.bx = fhandle; >     regs.x.ds = __tb >> 4; >     regs.x.dx = 0; > -    regs.x.flags |= 1; >     __dpmi_int(0x21, ®s); > >     /*  It is always necessary to test if LFN function >         has been implemented because the assumption has >         been proven false that a driver will set the CF > @@ -50,11 +50,13 @@ filelength(int fhandle) >         E.g.: all DOSLFN drivers do not implement >         0x71A6 and DOSLFN 0.40e does not set CF >         making MSDOS 6.22 fail.  If FreeDOS 1.0 is >         used, the same LFN driver sets the CF. >         If the ax register contains 0x7100 then the > -        corresponding LFN function is not implemented.  */ > +        corresponding LFN function is not implemented. > +        If the 0x71A6 function is not supported fall back > +        on 0x42NN.  */ >     if ((regs.x.flags & 1) == 0 && regs.x.ax != 0x7100) >     { >       /* Offset 0x24 contains the low 32-bits of the file size. >          Offset 0x20 contains the high 32-bits.  */ >       retval = _farpeekl(_dos_ds, __tb + 0x24); > @@ -73,37 +75,37 @@ filelength(int fhandle) >   regs.x.ax = 0x4201;      /* set pointer from current position */ >   regs.x.bx = fhandle; >   regs.x.cx = regs.x.dx = 0; /* move 0 bytes (i.e., stay put) */ >   __dpmi_int(0x21, ®s); >   if (regs.x.flags & 1) > -    { > -      errno = __doserr_to_errno(regs.x.ax); > -      return -1L; > -    } > +  { > +    errno = __doserr_to_errno(regs.x.ax); > +    return -1L; > +  } >   fpos_high = regs.x.dx;   /* save current position */ >   fpos_low  = regs.x.ax; > >   regs.x.cx = regs.x.dx = 0; >   regs.x.ax = 0x4202;      /* set pointer 0 bytes from the end of file */ >   __dpmi_int(0x21, ®s); >   if (regs.x.flags & 1) > -    { > -      errno = __doserr_to_errno(regs.x.ax); > -      return -1L; > -    } > +  { > +    errno = __doserr_to_errno(regs.x.ax); > +    return -1L; > +  } > >   /* The absolute byte offset returned in DX:AX is the file size. */ >   retval = ( (long)regs.x.dx << 16 ) + regs.x.ax; > >   /* Leave things as we have found them. */ >   regs.x.ax = 0x4200;      /* set pointer from the beginning of file */ >   regs.x.cx = fpos_high; >   regs.x.dx = fpos_low; >   __dpmi_int(0x21, ®s); >   if (regs.x.flags & 1) > -    { > -      errno = __doserr_to_errno(regs.x.ax); > -      return -1L; > -    } > +  { > +    errno = __doserr_to_errno(regs.x.ax); > +    return -1L; > +  } > >   return retval; >  } > diff -aprNU5 djgpp.orig/src/libc/posix/sys/stat/fixpath.c djgpp/src/libc/posix/sys/stat/fixpath.c > --- djgpp.orig/src/libc/posix/sys/stat/fixpath.c        2008-12-06 13:53:42 +0000 > +++ djgpp/src/libc/posix/sys/stat/fixpath.c     2011-09-16 22:17:32 +0000 > @@ -1,5 +1,6 @@ > +/* Copyright (C) 2011 DJ Delorie, see COPYING.DJ for details */ >  /* Copyright (C) 2008 DJ Delorie, see COPYING.DJ for details */ >  /* Copyright (C) 2002 DJ Delorie, see COPYING.DJ for details */ >  /* Copyright (C) 2001 DJ Delorie, see COPYING.DJ for details */ >  /* Copyright (C) 1999 DJ Delorie, see COPYING.DJ for details */ >  /* Copyright (C) 1997 DJ Delorie, see COPYING.DJ for details */ > @@ -32,14 +33,15 @@ __get_current_directory(char *out, int d >   __dpmi_regs r; >   char tmpbuf[FILENAME_MAX]; > >   memset(&r, 0, sizeof(r)); >   r.x.flags = 1;               /* Set carry for safety */ > -  if(use_lfn) > +  if (use_lfn) >     r.x.ax = 0x7147; >   else >     r.h.ah = 0x47; > +do_get_current_directory: >   r.h.dl = drive_number + 1; >   r.x.si = __tb_offset; >   r.x.ds = __tb_segment; >   __dpmi_int(0x21, &r); > > @@ -47,10 +49,19 @@ __get_current_directory(char *out, int d >   { >  #ifdef TEST >     errno = __doserr_to_errno(r.x.ax); >     perror("Get dir failed in fixpath"); >  #endif > +    if (r.x.ax == 0x7100) > +    { > +      /*  Never assume that the complete LFN API is implemented, > +          so check that AX != 0x7100.  E.G.: MSDOS 6.22 and DOSLFN 0.40. > +          If not supported fall back on SFN API.  */ > +      use_lfn = 0; > +      r.h.ah = 0x47; > +      goto do_get_current_directory; > +    } >     *out++ = '.';      /* Return relative path (lfn=n on Win9x) */ >     return out; >   } >   else >   { > @@ -347,27 +358,29 @@ int main (int argc, char *argv[]) >   char fixed[FILENAME_MAX]; >   __dpmi_regs r; > >   if (argc > 2) { >     _put_path(argv[1]); > -    if(_USE_LFN) > +    r.x.flags = 1;             /* Set carry for safety */ > +    if (_USE_LFN) >       r.x.ax = 0x713b; >     else >       r.h.ah = 0x3b; >     r.x.dx = __tb_offset; >     r.x.ds = __tb_segment; >     __dpmi_int(0x21, &r); > -    if(r.x.flags & 1) { > +    if (r.x.flags & 1) { >       errno = __doserr_to_errno(r.x.ax); >       sprintf(fixed, "Change dir to %s failed (lfn=%d)", argv[1], _USE_LFN); >       perror(fixed); >     } else >       printf("Set dir: %s\n", argv[1]); >     argc--; >     argv++; >   } > > +  r.x.flags = 1;               /* Set carry for safety */ >   if(_USE_LFN) >     r.x.ax = 0x7147; >   else >     r.h.ah = 0x47; >   r.h.dl = 0; > diff -aprNU5 djgpp.orig/src/libc/posix/sys/stat/fstat.c djgpp/src/libc/posix/sys/stat/fstat.c > --- djgpp.orig/src/libc/posix/sys/stat/fstat.c  2008-03-26 23:37:40 +0000 > +++ djgpp/src/libc/posix/sys/stat/fstat.c       2011-09-16 20:06:46 +0000 > @@ -819,51 +819,56 @@ fstat_assist(int fhandle, struct stat *s >                = _invent_inode(filename, dos_ftime, trusted_fsize); >             } > >           if (trusted_fsize == 510) >           { > -             int old_errno = errno; > -             char buf[2]; > -             int bytes_read = __internal_readlink(NULL, fhandle, buf, 1); > -             if (bytes_read != -1) > -             { > -                stat_buf->st_mode = S_IFLNK; > -                is_link = 1; > -             } > -             else > -                errno = old_errno; > +            int old_errno = errno; > +            char buf[2]; > +            int bytes_read = __internal_readlink(NULL, fhandle, buf, 1); > +            if (bytes_read != -1) > +            { > +              stat_buf->st_mode = S_IFLNK; > +              is_link = 1; > +            } > +            else > +              errno = old_errno; >           } >           if (!is_link) >           { > -              /* Return the minimum access bits every file has under DOS. */ > -              stat_buf->st_mode |= (S_IFREG | READ_ACCESS); > -              if (_djstat_flags & _STAT_ACCESS) > +            /* Return the minimum access bits every file has under DOS. */ > +            stat_buf->st_mode |= (S_IFREG | READ_ACCESS); > +            if (_djstat_flags & _STAT_ACCESS) >                 _djstat_fail_bits |= _STFAIL_WRITEBIT; > - > -             /* If we are runing on Windows 9X, NT 4.0 with LFN or 2000 or XP > -                with LFN is enabled, try harder. Note that we deliberately do > -                NOT use this call when LFN is disabled, even if we are on > -                Windows, because then we open the file with function 3Ch, and > -                such handles aren't supported by 71A6h call we use here.  */ > -             if  (_USE_LFN) > -                { > -                  __dpmi_regs r; > - > -                  r.x.ax = 0x71a6;     /* file info by handle */ > -                  r.x.bx = fhandle; > -                  r.x.ds = __tb >> 4; > -                  r.x.dx = 0; > -                 __dpmi_int(0x21, &r); > -                 if ((r.x.flags & 1) == 0 > -                     && (_farpeekl(_dos_ds, __tb) & 0x07) == 0) > -                   stat_buf->st_mode |= WRITE_ACCESS; /* no R, S or H bits set */ > -               } > - > -              /* Executables are detected if they have magic numbers.  */ > -              if ( (_djstat_flags & _STAT_EXEC_MAGIC) == 0 && > + > +            /* If we are runing on Windows 9X, NT 4.0 with LFN or 2000 or XP > +               with LFN is enabled, try harder. Note that we deliberately do > +               NOT use this call when LFN is disabled, even if we are on > +               Windows, because then we open the file with function 3Ch, and > +               such handles aren't supported by 71A6h call we use here.  */ > +           if (_USE_LFN) > +            { > +              __dpmi_regs r; > + > +              r.x.flags |= 1;    /* Always set CF before calling a 0x71NN function. */ > +              r.x.ax = 0x71a6;   /* file info by handle */ > +              r.x.bx = fhandle; > +              r.x.ds = __tb >> 4; > +              r.x.dx = 0; > +              __dpmi_int(0x21, &r); > +              if ((r.x.flags & 1) == 0 && r.x.ax != 0x7100 > +                  && (_farpeekl(_dos_ds, __tb) & 0x07) == 0) > +              { > +                /*  Never assume that the complete LFN API is implemented, > +                    so check that AX != 0x7100.  E.G.: MSDOS 6.22 and DOSLFN 0.40.  */ > +                stat_buf->st_mode |= WRITE_ACCESS; /* no R, S or H bits set */ > +              } > +            } > + > +            /* Executables are detected if they have magic numbers.  */ > +            if ((_djstat_flags & _STAT_EXEC_MAGIC) == 0 && >                 _is_executable((const char *)0, fhandle, (const char *)0)) > -                stat_buf->st_mode |= EXEC_ACCESS; > +              stat_buf->st_mode |= EXEC_ACCESS; >           } >           /* Lower 6 bits of IOCTL return value give the device number. */ >           stat_buf->st_dev = dev_info & 0x3f; >  #ifdef  HAVE_ST_RDEV >           stat_buf->st_rdev = dev_info & 0x3f; > @@ -877,11 +882,11 @@ fstat_assist(int fhandle, struct stat *s >           stat_buf->st_size  = trusted_fsize; >           stat_buf->st_atime = stat_buf->st_ctime = stat_buf->st_mtime = >             _file_time_stamp(dos_ftime); > >          /* Additional time info for LFN platforms.  */ > -         set_fstat_times (fhandle, stat_buf); > +         set_fstat_times(fhandle, stat_buf); >         } >       return 0; >     } > >   /* Don't have even values from conventional DOS calls. > diff -aprNU5 djgpp.orig/src/libc/posix/sys/stat/lfilelen.c djgpp/src/libc/posix/sys/stat/lfilelen.c > --- djgpp.orig/src/libc/posix/sys/stat/lfilelen.c       2011-09-04 21:16:44 +0000 > +++ djgpp/src/libc/posix/sys/stat/lfilelen.c    2011-09-16 20:06:46 +0000 > @@ -28,15 +28,15 @@ lfilelength(int fhandle) > >   /* DOS 7 provides a way to get the file size directly. >      Prefer it when available.  */ >   if (_USE_LFN) >   { > +    regs.x.flags |= 1;  /* Always set CF before calling a 0x71NN function. */ >     regs.x.ax = 0x71A6; >     regs.x.bx = fhandle; >     regs.x.ds = __tb >> 4; >     regs.x.dx = 0; > -    regs.x.flags |= 1; >     __dpmi_int (0x21, ®s); > >     /*  It is always necessary to test if LFN function >         has been implemented because the assumption has >         been proven false that a driver will set the CF > @@ -44,11 +44,13 @@ lfilelength(int fhandle) >         E.g.: all DOSLFN drivers do not implement >         0x71A6 and DOSLFN 0.40e does not set CF >         making MSDOS 6.22 fail.  If FreeDOS 1.0 is >         used, the same LFN driver sets the CF. >         If the ax register contains 0x7100 then the > -        corresponding LFN function is not implemented.  */ > +        corresponding LFN function is not implemented. > +        If the 0x71A6 function is not supported fall back > +        on 0x42NN.  */ >     if ((regs.x.flags & 1) == 0 && regs.x.ax != 0x7100) >     { >       /* Offset 0x24 contains the low 32-bits of the file size. >          Offset 0x20 contains the high 32-bits.  */ >       long retval_l = _farpeekl (_dos_ds, __tb + 0x24); > diff -aprNU5 djgpp.orig/src/libc/posix/sys/stat/mkdir.c djgpp/src/libc/posix/sys/stat/mkdir.c > --- djgpp.orig/src/libc/posix/sys/stat/mkdir.c  2001-03-18 16:52:40 +0000 > +++ djgpp/src/libc/posix/sys/stat/mkdir.c       2011-09-16 20:06:46 +0000 > @@ -1,5 +1,6 @@ > +/* Copyright (C) 2011 DJ Delorie, see COPYING.DJ for details */ >  /* Copyright (C) 2001 DJ Delorie, see COPYING.DJ for details */ >  /* Copyright (C) 2000 DJ Delorie, see COPYING.DJ for details */ >  /* Copyright (C) 1998 DJ Delorie, see COPYING.DJ for details */ >  /* Copyright (C) 1996 DJ Delorie, see COPYING.DJ for details */ >  /* Copyright (C) 1995 DJ Delorie, see COPYING.DJ for details */ > @@ -27,12 +28,15 @@ mkdir(const char *mydirname, mode_t mode >   if (!__solve_symlinks(mydirname, dir_name)) >      return -1; > >   _put_path(dir_name); > > -  if(use_lfn) > +  if (use_lfn) > +  { > +    r.x.flags |= 1;  /* Always set CF before calling a 0x71NN function. */ >     r.x.ax = 0x7139; > +  } >  #if 0 >   /* It seems that no version of DOS, including DOS 8, which is part >      of Windows/ME, implements this function.  Without LFN, this fails >      mkdir on Windows/ME.  Disabled.  */ >   else if ((_osmajor > 7 && _osmajor < 10) /* OS/2 returns v10 and above */ > @@ -46,26 +50,38 @@ mkdir(const char *mydirname, mode_t mode >     r.h.cl = 0x39; >   } >  #endif >   else >     r.h.ah = 0x39; > +do_mkdir: >   r.x.ds = __tb_segment; >   r.x.dx = __tb_offset; >   __dpmi_int(0x21, &r); > >   if (r.x.flags & 1) >   { > -    int save_errno; > -    save_errno = errno = __doserr_to_errno(r.x.ax); > -    if (errno == EACCES) > +    if (r.x.ax == 0x7100) > +    { > +      /*  Never assume that the complete LFN API is implemented, > +          so check that AX != 0x7100.  E.G.: MSDOS 6.22 and DOSLFN 0.40. > +          If not supported fall back on SFN API.  */ > +      r.h.ah = 0x39; > +      goto do_mkdir; > +    } > +    else >     { > -      /* see if the directory existed, in which case > -        we should return EEXIST - DJ */ > -      if (access(mydirname, D_OK) == 0) > -       errno = EEXIST; > -      else > -       errno = save_errno; > +      int save_errno; > +      save_errno = errno = __doserr_to_errno(r.x.ax); > +      if (errno == EACCES) > +      { > +        /* see if the directory existed, in which case > +           we should return EEXIST - DJ */ > +        if (access(mydirname, D_OK) == 0) > +          errno = EEXIST; > +        else > +          errno = save_errno; > +      } >     } >     return -1; >   } > >   /* mkdir is stub'd, and we don't want to stub chmod also.  */ > diff -aprNU5 djgpp.orig/src/libc/posix/unistd/chdir.c djgpp/src/libc/posix/unistd/chdir.c > --- djgpp.orig/src/libc/posix/unistd/chdir.c    2007-12-10 20:16:00 +0000 > +++ djgpp/src/libc/posix/unistd/chdir.c 2011-09-16 20:06:46 +0000 > @@ -1,5 +1,6 @@ > +/* Copyright (C) 2011 DJ Delorie, see COPYING.DJ for details */ >  /* Copyright (C) 2001 DJ Delorie, see COPYING.DJ for details */ >  /* Copyright (C) 2000 DJ Delorie, see COPYING.DJ for details */ >  /* Copyright (C) 1998 DJ Delorie, see COPYING.DJ for details */ >  /* Copyright (C) 1996 DJ Delorie, see COPYING.DJ for details */ >  /* Copyright (C) 1995 DJ Delorie, see COPYING.DJ for details */ > @@ -50,19 +51,32 @@ __chdir (const char *mydirname) >     __dpmi_int(0x21, &r); >   } > >   if (drv_no == -1 || _farpeekb(_dos_ds, __tb + 2) != 0) >   { > -    if(_USE_LFN) > +    if (_USE_LFN) > +    { > +      r.x.flags |= 1;  /* Always set CF before calling a 0x71NN function. */ >       r.x.ax = 0x713b; > +    } >     else >       r.h.ah = 0x3b; > +do_chdir: >     r.x.dx = __tb_offset; >     r.x.ds = __tb_segment; >     __dpmi_int(0x21, &r); > -    if(r.x.flags & 1) > +    if (r.x.flags & 1) >     { > +      if (r.x.ax == 0x7100) > +      { > +        /*  Never assume that the complete LFN API is implemented, > +            so check that AX != 0x7100.  E.G.: MSDOS 6.22 and DOSLFN 0.40. > +            If not supported fall back on SFN API.  */ > +        r.h.ah = 0x3b; > +        goto do_chdir; > +      } > + >       errno = __doserr_to_errno(r.x.ax); >       return -1; >     } >   } > > diff -aprNU5 djgpp.orig/src/libc/posix/unistd/getcwd.c djgpp/src/libc/posix/unistd/getcwd.c > --- djgpp.orig/src/libc/posix/unistd/getcwd.c   2003-05-10 15:31:12 +0000 > +++ djgpp/src/libc/posix/unistd/getcwd.c        2011-09-16 20:06:46 +0000 > @@ -1,5 +1,6 @@ > +/* Copyright (C) 2011 DJ Delorie, see COPYING.DJ for details */ >  /* Copyright (C) 2003 DJ Delorie, see COPYING.DJ for details */ >  /* Copyright (C) 2001 DJ Delorie, see COPYING.DJ for details */ >  /* Copyright (C) 1996 DJ Delorie, see COPYING.DJ for details */ >  /* Copyright (C) 1995 DJ Delorie, see COPYING.DJ for details */ >  #include > @@ -45,22 +46,35 @@ __getcwd(char *buf, size_t size) >   /* make sure we don't overrun the TB */ >   if (size > __tb_size) >     size = __tb_size; > >   /* get the path into the transfer buffer at least */ > -  if(use_lfn) > +  if (use_lfn) > +  { > +    r.x.flags |= 1;  /* Always set CF before calling a 0x71NN function. */ >     r.x.ax = 0x7147; > +  } >   else >     r.h.ah = 0x47; > +do_getcwd: >   r.h.dl = 0; >   r.x.si = __tb_offset; >   r.x.ds = __tb_segment; >   __dpmi_int(0x21, &r); > >   /* current drive may be invalid (it happens) */ >   if (r.x.flags & 1) >   { > +    if (r.x.ax == 0x7100) > +    { > +      /*  Never assume that the complete LFN API is implemented, > +          so check that AX != 0x7100.  E.G.: MSDOS 6.22 and DOSLFN 0.40. > +          If not supported fall back on SFN API.  */ > +      use_lfn = 0; > +      r.h.ah = 0x47; > +      goto do_getcwd; > +    } >     errno = __doserr_to_errno(r.x.ax); >     return 0; >   } > >   /* path is ASCIIZ.  Scan it, filling in buf, watching for > diff -aprNU5 djgpp.orig/src/libc/posix/unistd/rmdir.c djgpp/src/libc/posix/unistd/rmdir.c > --- djgpp.orig/src/libc/posix/unistd/rmdir.c    2000-08-25 11:40:48 +0000 > +++ djgpp/src/libc/posix/unistd/rmdir.c 2011-09-16 20:06:46 +0000 > @@ -1,5 +1,6 @@ > +/* Copyright (C) 2011 DJ Delorie, see COPYING.DJ for details */ >  /* Copyright (C) 2000 DJ Delorie, see COPYING.DJ for details */ >  /* Copyright (C) 1998 DJ Delorie, see COPYING.DJ for details */ >  /* Copyright (C) 1996 DJ Delorie, see COPYING.DJ for details */ >  /* Copyright (C) 1995 DJ Delorie, see COPYING.DJ for details */ >  #include > @@ -20,20 +21,25 @@ rmdir(const char *mydirname) > >   if (!__solve_dir_symlinks(mydirname, real_dir)) >     return -1; > >   if(_USE_LFN) > +  { > +    r.x.flags |= 1;  /* Always set CF before calling a 0x71NN function. */ >     r.x.ax = 0x713a; > +  } >   else >     r.h.ah = 0x3a; >   r.x.ds = __tb_segment; >   r.x.dx = __tb_offset; >   _put_path(real_dir); >   __dpmi_int(0x21, &r); > > -  if (r.x.flags & 1) > +  if (r.x.flags & 1 || r.x.ax == 0x7100) >   { > +    /*  Never assume that the complete LFN API is implemented, > +        so check that AX != 0x7100.  E.G.: MSDOS 6.22 and DOSLFN 0.40.  */ >     errno = __doserr_to_errno(r.x.ax); >     return -1; >   } >   return 0; >  } >