Mail Archives: djgpp-workers/2002/04/03/10:29:55
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 -