delorie.com/archives/browse.cgi   search  
Mail Archives: djgpp-workers/2002/04/05/07:45:21

X-Authentication-Warning: delorie.com: mailnull set sender to djgpp-workers-bounces using -f
Date: Fri, 05 Apr 2002 13:49:14 +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.2.50 (via feedmail 8.3.emacs20_6 I) and Blat ver 1.8.6
Subject: PATCH: fcntl and F_GETFL, mark 2
Message-Id: <E16tT5c-0000m9-00@phekda.freeserve.co.uk>
Reply-To: djgpp-workers AT delorie DOT com

Hello.

Below is the revised patch to add F_GETFL support to fcntl. Changes are:

* return O_RDWR if we can't find an SFT entry for the FD;
* update the fcntl documentation;
* add a "What's Changed" entry describing the changes.

If there are no further comments, I'll commit this patch next Saturday.

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/04/05 12:42:42
@@ -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,45 @@ 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. */
+      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, we're probably running
+	 * on Windows NT/2000/XP. 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/04/05 12:42:42
@@ -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/04/05 12:42:48
@@ -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/2000/XP this cannot report the open mode correctly -
+@code{O_RDWR} 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.110
diff -p -u -3 -r1.110 wc204.txi
--- src/docs/kb/wc204.txi	2002/02/17 18:54:33	1.110
+++ src/docs/kb/wc204.txi	2002/04/05 12:42:52
@@ -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 and status flags.
+However, the open flags are only computed correctly on DOS -
+@code{O_RDWR} is always returned on Windows NT/2000/XP.
 
 @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