delorie.com/archives/browse.cgi   search  
Mail Archives: djgpp-workers/2002/06/09/17:19:36

Date: Sun, 09 Jun 2002 21:20:41 +0100
From: "Richard Dawe" <rich AT phekda DOT freeserve DOT co DOT uk>
Sender: rich AT phekda DOT freeserve DOT co DOT uk
To: djgpp-workers AT delorie DOT com
X-Mailer: Emacs 21.3.50 (via feedmail 8.3.emacs20_6 I) and Blat ver 1.8.6
Subject: PATCH: fcntl and F_GETFL, mark 3
Message-Id: <E17H951-0000Xf-00@phekda.freeserve.co.uk>
Reply-To: djgpp-workers AT delorie DOT com

Hello.

Below is version 3 of the patch to add support for F_GETFL to fcntl().
The only change since version 2 is that there are notes saying
that the SFT entry code does not work properly on Windows NT 4 -
the open mode will always be reported as O_RDONLY.

OK to commit?

Thanks, bye, Rich =]

Index: src/libc/posix/fcntl/fcntl.c
===================================================================
RCS file: /cvs/djgpp/djgpp/src/libc/posix/fcntl/fcntl.c,v
retrieving revision 1.7
diff -p -u -3 -r1.7 fcntl.c
--- src/libc/posix/fcntl/fcntl.c	2001/06/12 12:42:42	1.7
+++ src/libc/posix/fcntl/fcntl.c	2002/06/09 20:11:50
@@ -1,3 +1,4 @@
+/* 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) 1996 DJ Delorie, see COPYING.DJ for details */
@@ -14,6 +15,7 @@
 #include <libc/farptrgs.h>
 #include <libc/dosio.h>
 #include <libc/getdinfo.h>
+#include <libc/fd_props.h>
 #include <go32.h>
 
 
@@ -408,8 +410,52 @@ fcntl(int fd, int cmd, ...)
 
     case F_GETFL:
     {
-      return 0; /* FIXME: should use the data in the SFT, and the
-		   FILE_DESC_APPEND flag in __fd_properties */
+      unsigned long sft_entry_ptr;
+      unsigned char sft_open_flags;
+      int flags = 0;
+
+      /*
+       * Use the data in the SFT.
+       *
+       * This seems to work on Windows 2000 and therefore probably works
+       * on Windows XP. It does not work on Windows NT 4, where the file
+       * will always appear to have been opened read-only. It's hard
+       * to distinguish Windows 2000 and Windows NT 4 with an LFN TSR,
+       * so we can't have a special case for Windows NT 4.
+       */
+      sft_entry_ptr = _get_sft_entry_ptr(fd);
+      if (sft_entry_ptr)
+      {
+	/* Offset 2 in the SFT contains the open flags. */
+	sft_open_flags = _farpeekw(_dos_ds, sft_entry_ptr + 2);
+
+	switch(sft_open_flags & 0x7)
+	{
+	case 0: flags |= O_RDONLY; break;
+	case 1: flags |= O_WRONLY; break;
+	case 2: flags |= O_RDWR;   break;
+
+	default:
+	  break;
+	}
+      }
+      else
+      {
+	/* If we've failed to get an SFT pointer, pretend that the file
+	 * is read-write, since that's most likely to be correct. */
+	flags |= O_RDWR;
+      }
+
+      /* Check the FILE_DESC_APPEND flag in __fd_properties. */
+      if (__has_fd_properties(fd))
+      {
+	unsigned long fd_flags = __get_fd_flags(fd);
+
+	if (fd_flags & FILE_DESC_APPEND)
+	  flags |= O_APPEND;
+      }
+
+      return flags;
     }
 
 
Index: tests/libc/posix/fcntl/tfcntl.c
===================================================================
RCS file: /cvs/djgpp/djgpp/tests/libc/posix/fcntl/tfcntl.c,v
retrieving revision 1.1
diff -p -u -3 -r1.1 tfcntl.c
--- tests/libc/posix/fcntl/tfcntl.c	2001/02/01 19:24:45	1.1
+++ tests/libc/posix/fcntl/tfcntl.c	2002/06/09 20:11:50
@@ -1,13 +1,14 @@
 #include <stdio.h>
 #include <stdlib.h>
+#include <string.h>
 #include <unistd.h>
 #include <fcntl.h>
+#include <sys/stat.h>
 #include <errno.h>
-#include <strings.h>
 #include <dos.h>
 #include <libc/dosio.h>
 
-void prdoserr(int fd) {
+static void prdoserr(int fd) {
   struct DOSERROR de;
   struct DOSERROR_STR se;
   int errsave;
@@ -30,14 +31,59 @@ void prdoserr(int fd) {
   printf("Error Locus:    %02X : %s\n",de.locus,se.locus_str);
 }
 
+static const char *flags2str(const int flags) {
+  static char buf[256];
+  int need_comma = 0;
+
+  buf[0] = '\0';
+
+  switch(flags & O_ACCMODE) {
+  case O_RDONLY: strcat(buf, "O_RDONLY"); need_comma++; break;
+  case O_WRONLY: strcat(buf, "O_WRONLY"); need_comma++; break;
+  case O_RDWR:   strcat(buf, "O_RDWR");   need_comma++; break;
+
+  default:
+    break;
+  }
+
+  if (flags & O_APPEND) {
+    if (need_comma) {
+      strcat(buf, ", ");
+      need_comma--;
+    }
+
+    strcat(buf, "O_APPEND");
+    need_comma++;
+  }
+
+  if (flags & O_NONBLOCK) {
+    if (need_comma) {
+      strcat(buf, ", ");
+      need_comma--;
+    }
+
+    strcat(buf, "O_NONBLOCK");
+    need_comma++;
+  }
 
+  return(buf);
+}
+
 int main(void) {
+  int retval, fd;
+
 #if defined(F_SETLK) && defined(F_SETLKW)
   struct flock fl;
   struct flock64 fl64;
-  int retval, fd;
+#endif /* F_SETLK && F_SETLKW */
 
   fd = open("tfcntl.c", O_RDONLY);
+  if (fd < 0) {
+    perror("tfcntl");
+    return(EXIT_FAILURE);
+  }
+
+#if defined(F_SETLK) && defined(F_SETLKW)
   fl.l_type = F_RDLCK;
   fl.l_whence = SEEK_SET;
   fl.l_start = fl.l_len = 0;
@@ -80,6 +126,7 @@ int main(void) {
   if ((retval < 0) && (errno != 0)) prdoserr(fd);
 
   /* F_SETLKW tests */
+  puts("--- F_SETLKW tests ---");
 
   errno = 0;
   fl.l_type = F_RDLCK;
@@ -123,6 +170,7 @@ int main(void) {
   if ((retval < 0) && (errno != 0)) prdoserr(fd);
 
   /* FAT32 tests */
+  puts("--- FAT32 tests ---");
 
   errno = 0;
   fl64.l_type = F_RDLCK;
@@ -153,6 +201,7 @@ int main(void) {
   if ((retval < 0) && (errno != 0)) prdoserr(fd);
 
   /* F_SETLKW64 tests */
+  puts("--- F_SETLKW64 tests ---");
 
   errno = 0;
   fl64.l_type = F_RDLCK;
@@ -194,8 +243,10 @@ int main(void) {
   retval = fcntl(fd, F_GETLK64, &fl64);
   printf("F_GETLK64/F_RDLCK:retval=%d\n", retval);
   if ((retval < 0) && (errno != 0)) prdoserr(fd);
+#endif /* F_SETLK && F_SETLKW */
 
   /* Other function tests (non-lock-related) */
+  puts("--- Other tests ---");
 
   errno = 0;
   retval = fcntl(fd, F_GETFD);
@@ -208,13 +259,73 @@ int main(void) {
   if ((retval < 0) && (errno != 0)) prdoserr(fd);
 
   errno = 0;
+  retval = fcntl(fd, F_GETFL);
+  printf("F_GETFL:retval=%04x = %s\n", retval, flags2str(retval));
+  if ((retval < 0) && (errno != 0)) prdoserr(fd);
+
+  close(fd);
+
+  /* F_GETFL tests */
+  puts("--- F_GETFL tests ---");
+
+  /* Open a file for read-only */
+  fd = open("tfcntl.c", O_RDONLY);
+  if (fd < 0) {
+    perror("tfcntl");
+    return(EXIT_FAILURE);
+  }
+
+  errno = 0;
+  retval = fcntl(fd, F_GETFL);
+  printf("F_GETFL:retval=%04x = %s\n", retval, flags2str(retval));
+  if ((retval < 0) && (errno != 0)) prdoserr(fd);
+
+  close(fd);
+
+  /* Open a file for write-only */
+  remove("tfcntl.wo");
+  fd = open("tfcntl.wo", O_CREAT|O_WRONLY);
+  if (fd < 0) {
+    perror("tfcntl");
+    return(EXIT_FAILURE);
+  }
+
+  errno = 0;
   retval = fcntl(fd, F_GETFL);
-  printf("F_GETFL:retval=%04x\n", retval);
+  printf("F_GETFL:retval=%04x = %s\n", retval, flags2str(retval));
   if ((retval < 0) && (errno != 0)) prdoserr(fd);
 
   close(fd);
-  exit(0);
-#else
-  exit(99);
-#endif
+
+  /* Try opening a file for write-only using creat(). */
+  remove("tfcntl.wo");
+  fd = creat("tfcntl.wo", S_IWUSR);
+  if (fd < 0) {
+    perror("tfcntl");
+    return(EXIT_FAILURE);
+  }
+
+  errno = 0;
+  retval = fcntl(fd, F_GETFL);
+  printf("F_GETFL:retval=%04x = %s\n", retval, flags2str(retval));
+  if ((retval < 0) && (errno != 0)) prdoserr(fd);
+
+  close(fd);
+
+  /* Open a file for read-write, append */
+  remove("tfcntl.rwa");
+  fd = open("tfcntl.rwa", O_CREAT|O_RDWR|O_APPEND);
+  if (fd < 0) {
+    perror("tfcntl");
+    return(EXIT_FAILURE);
+  }
+
+  errno = 0;
+  retval = fcntl(fd, F_GETFL);
+  printf("F_GETFL:retval=%04x = %s\n", retval, flags2str(retval));
+  if ((retval < 0) && (errno != 0)) prdoserr(fd);
+
+  close(fd);
+
+  return(EXIT_SUCCESS);
 }
Index: src/libc/posix/fcntl/fcntl.txh
===================================================================
RCS file: /cvs/djgpp/djgpp/src/libc/posix/fcntl/fcntl.txh,v
retrieving revision 1.8
diff -p -u -3 -r1.8 fcntl.txh
--- src/libc/posix/fcntl/fcntl.txh	2001/02/01 19:19:24	1.8
+++ src/libc/posix/fcntl/fcntl.txh	2002/06/09 20:11:58
@@ -62,8 +62,10 @@ will return -1, setting @code{errno} to 
 @item F_GETFL
 Get the open mode and status flags associated with the handle @var{fd}.
 The flags are those supported by @code{open} and @code{creat} functions,
-like @code{O_RDONLY}, @code{O_APPEND}, etc.  Currently, this command
-always returns zero, with no flags set.
+like @code{O_RDONLY}, @code{O_APPEND}, etc.
+
+On Windows NT this cannot report the open mode correctly ---
+@code{O_RDONLY} is always returned.
 
 @item F_SETFL
 Set the open mode and status flags associated with the handle @var{fd}.
Index: src/docs/kb/wc204.txi
===================================================================
RCS file: /cvs/djgpp/djgpp/src/docs/kb/wc204.txi,v
retrieving revision 1.113
diff -p -u -3 -r1.113 wc204.txi
--- src/docs/kb/wc204.txi	2002/04/14 16:25:43	1.113
+++ src/docs/kb/wc204.txi	2002/06/09 20:12:02
@@ -273,11 +273,15 @@ These functions now interrogate and use 
 
 @item
 @findex fcntl AT r{ commands @code{F_GETFL} and @code{F_SETFL}}
-These functions are still effective no-ops, since DOS/Windows does not
-allow flags to be modified on an open file.  A small exception is made
-for @code{F_SETFL}:  You may use @code{F_SETFL} to remove the
-@code{O_NONBLOCK} flag, because it is not supported by DJGPP anyway, and
-it does no harm to allow this functionality.
+The @code{F_SETFL} function is still an effective no-op, since
+DOS/Windows does not allow flags to be modified on an open file.
+A small exception is made for @code{F_SETFL}:  You may use @code{F_SETFL}
+to remove the AT code{O_NONBLOCK} flag, because it is not supported
+by DJGPP anyway, and it does no harm to allow this functionality.
+
+The @code{F_GETFL} function now computes the open mode and status flags.
+On Windows NT this cannot report the open mode correctly ---
+@code{O_RDONLY} is always returned.
 
 @item
 Documentation has been updated to reflect the new functionality and

- Raw text -


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