ftp.delorie.com/archives/browse.cgi   search  
Mail Archives: djgpp/2011/09/17/08:01:59

X-Authentication-Warning: delorie.com: mail set sender to djgpp-bounces using -f
X-Recipient: djgpp AT delorie DOT com
X-Authenticated: #27081556
X-Provags-ID: V01U2FsdGVkX1/7q44/q8f7H4tGjlO7L0ua/3rmQhBv6O7VmgautD
6N55gi0ii7D0OG
From: Juan Manuel Guerrero <juan DOT guerrero AT gmx DOT de>
To: djgpp AT delorie DOT com
Subject: Re: Isues concerning the INT 21 Windows95 - LONG FILENAME FUNCTIONS (0x71XX) implementation.
Date: Sat, 17 Sep 2011 13:56:52 +0200
User-Agent: KMail/1.9.10
MIME-Version: 1.0
Message-Id: <201109171356.53360.juan.guerrero@gmx.de>
X-Y-GMX-Trusted: 0

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






2011-09-16  Juan Manuel Guerrero  <juan DOT guerrero AT gmx DOT de>

	* 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  <juan DOT guerrero AT gmx DOT de>

	* 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  <juan DOT guerrero AT gmx DOT de>

	* 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  <juan DOT guerrero AT gmx DOT de>

	* 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  <juan DOT guerrero AT gmx DOT de>

	* 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 <libc/stubs.h>
 #include <stdlib.h>
@@ -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 <libc/stubs.h>
 #include <stdlib.h>
 #include <string.h>
@@ -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, &regs);
 
   /* 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 <libc/stubs.h>
 #include <io.h>
 #include <errno.h>
@@ -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 <libc/stubs.h>
@@ -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 <libc/stubs.h>
 #include <stdarg.h>
@@ -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 <libc/stubs.h>
@@ -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 <libc/stubs.h>
 #include <fcntl.h>	/* for _USE_LFN */
 #include <io.h>		/* for the prototype of `_flush_disk_cache' */
 #include <dir.h>	/* for `getdisk' */
 #include <dpmi.h>	/* 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 <libc/stubs.h>
 #include <ctype.h>
@@ -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 <libc/stubs.h>
 #include <string.h>
 #include <unistd.h>
 #include <sys/stat.h>
@@ -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, &regs);
 
     /*  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, &regs);
   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, &regs);
   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, &regs);
   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, &regs);
 
     /*  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 <libc/stubs.h>
@@ -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 <libc/stubs.h>
@@ -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;
 }

- Raw text -


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