delorie.com/archives/browse.cgi   search  
Mail Archives: djgpp-workers/2002/04/03/10:29:55

X-Authentication-Warning: delorie.com: mailnull set sender to djgpp-workers-bounces using -f
Sender: rich AT phekda DOT freeserve DOT co DOT uk
Message-ID: <3CAB1FDB.68F9CF2F@phekda.freeserve.co.uk>
Date: Wed, 03 Apr 2002 16:29:31 +0100
From: Richard Dawe <rich AT phekda DOT freeserve DOT co DOT uk>
X-Mailer: Mozilla 4.77 [en] (X11; U; Linux 2.2.19 i586)
X-Accept-Language: de,fr
MIME-Version: 1.0
To: djgpp-workers AT delorie DOT com
Subject: Re: redirection problem with perl
References: <Pine DOT SUN DOT 3 DOT 91 DOT 1020128134413 DOT 26430D-100000 AT is>
Reply-To: djgpp-workers AT delorie DOT com

Hello.

Eli Zaretskii wrote:
> 
> On Mon, 28 Jan 2002, Laszlo Molnar wrote:
> 
> > old_h = fileno(old_stream)
> > old_mode = fcntl(old_h, F_GETFL)
> > new_stream =  fdopen(dup(old_h), mode_to_string(old_mode))
> >
> > This fails because this fcntl call always returns 0, which means fdopen
> > is always called with "r" as the mode.
> >
> > Any idea to work around this?
[snip]
> Or fix the FIXME in fcntl.c that would make F_GETFL something other than
> a no-op, and then use the fixed version to build Perl ;-)

How about the diff below? This updates the test program to parse F_GETFL's
return code. OK to commit? I'll add a "What's Changed" entry too for the
commit.

BTW _creatnew seems to ignore the flags that are passed to it. For instance,
if you try to create a new file in write-only mode, then _creatnew ignores the
write-only flag and opens it read-write. Hence the test below will show that
the file opened with O_WRONLY was actually opened read-write.

Bye, Rich =]

-- 
Richard Dawe [ http://www.phekda.freeserve.co.uk/richdawe/ ]

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/03 15:25:22
@@ -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,41 @@ 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;
+
+      /* FIXME: Use the data in the SFT. */
+      sft_entry_ptr = _get_sft_entry_ptr(fd);
+      if (!sft_entry_ptr)
+      {
+       /* Pass through `errno'. */
+       return -1;
+      }
+
+      /* 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;
+      }
+
+      /* 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/03 15:25:22
@@ -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);
 }

- Raw text -


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