Mail Archives: djgpp-workers/2002/06/09/17:19:36
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 -