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 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: Content-Type: text/plain; charset=us-ascii Content-Transfer-Encoding: 7bit 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 #include #include +#include #include @@ -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 #include +#include #include #include +#include #include -#include #include #include -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); }