Message-Id: <5.0.1.4.0.20001127000014.00a46b50@pop5.banet.net> X-Sender: usbanet DOT farley3 AT pop5 DOT banet DOT net (Unverified) X-Mailer: QUALCOMM Windows Eudora Version 5.0.1 Date: Mon, 27 Nov 2000 00:11:43 -0500 To: djgpp-workers AT delorie DOT com From: "Peter J. Farley III" Subject: Locking fcntl() and flock() patches Mime-Version: 1.0 Content-Type: multipart/mixed; boundary="=====================_24418177==_" Reply-To: djgpp-workers AT delorie DOT com --=====================_24418177==_ Content-Type: text/plain; charset="us-ascii"; format=flowed Attached are three diff files which I *think* should come through as text and not mime-encoded, but *please* let me know how they reach you. src.dif contains all the patches for the /src tree, include.dif contains all the patches for the include tree (including the file I missed the last time, /include/libc/getdinfo.h) and tests.dif contains all the patches for the /tests tree. I think I have all of the bugs worked out, but I'll be happy to fix any you find :) I deliberately did not include a lockf() patch. On further research into the definition of the lockf() function, I think it would trip up someone used to using it on a unixy system, since there seem to be a lot of references in the docs I found to lockf() maintaining its own set of lock tables, which I was not prepared to implement (though it is certainly possible). If anyone here thinks we should just implement it anyway, I'm prepared to hear arguments in favor, but I won't be able to do a table-based implementation myself, as my copious spare time :) is severely depleted. Comments, errata, etc. requested and welcome. --=====================_24418177==_ Content-Type: text/plain; charset="us-ascii" --- src/debug/common/dbgcom.c.0 Mon Oct 11 07:34:18 1999 +++ src/debug/common/dbgcom.c Sat Nov 18 19:39:20 2000 @@ -458,9 +458,16 @@ _get_exception_handler: \n\ pushl %eax \n\ pushf \n\ - .byte 0x2e \n\ - lcall _old_i31 \n\ - popl %eax \n\ + .byte 0x2e \n" +#if (GAS_MAJOR == 2) \ + && ((GAS_MINOR < 9) || ((GAS_MINOR == 9) && (GAS_MINORMINOR < 5))) +" lcall _old_i31 \n\ +" +#else +" lcall *_old_i31 \n\ +" +#endif +" popl %eax \n\ jc Lc31_set_flags_and_iret \n\ pushl %eax \n\ push %es \n\ @@ -487,9 +494,16 @@ pop %ds \n\ pop %es \n\ popl %eax \n\ - .byte 0x2e \n\ - ljmp _old_i31 \n\ - ret \n" + .byte 0x2e \n" +#if (GAS_MAJOR == 2) \ + && ((GAS_MINOR < 9) || ((GAS_MINOR == 9) && (GAS_MINORMINOR < 5))) +" ljmp _old_i31 \n\ +" +#else +" ljmp *_old_i31 \n\ +" +#endif +" ret \n" ); /* Change a handle in the list: EAX is the old handle, EDX is the new */ @@ -562,9 +576,16 @@ pushl %eax \n\ movw $0x0003,%ax \n\ pushf \n\ - .byte 0x2e \n\ - lcall _old_i31 \n\ - movw %ax,%bx \n\ + .byte 0x2e \n" +#if (GAS_MAJOR == 2) \ + && ((GAS_MINOR < 9) || ((GAS_MINOR == 9) && (GAS_MINORMINOR < 5))) +" lcall _old_i31 \n\ +" +#else +" lcall *_old_i31 \n\ +" +#endif +" movw %ax,%bx \n\ popl %eax \n\ pushl %eax \n\ movw %ax,%dx \n\ @@ -691,9 +712,16 @@ cmpw $0x0503,%ax \n\ je Lc31_resize_mem \n\ L_jmp_to_old_i31: \n\ - .byte 0x2e \n\ - ljmp _old_i31 \n\ -Lc31_set_flags_and_iret: \n\ + .byte 0x2e \n" +#if (GAS_MAJOR == 2) \ + && ((GAS_MINOR < 9) || ((GAS_MINOR == 9) && (GAS_MINORMINOR < 5))) +" ljmp _old_i31 \n\ +" +#else +" ljmp *_old_i31 \n\ +" +#endif +"Lc31_set_flags_and_iret: \n\ pushl %eax \n\ pushf \n\ popl %eax /* store the right flags for iret */ \n\ @@ -732,9 +760,16 @@ cmpw _app_ds,%bx \n\ jne L_jmp_to_old_i31 \n\ pushf \n\ - .byte 0x2e \n\ - lcall _old_i31 \n\ - call ___djgpp_save_interrupt_regs \n\ + .byte 0x2e \n" +#if (GAS_MAJOR == 2) \ + && ((GAS_MINOR < 9) || ((GAS_MINOR == 9) && (GAS_MINORMINOR < 5))) +" lcall _old_i31 \n\ +" +#else +" lcall *_old_i31 \n\ +" +#endif +" call ___djgpp_save_interrupt_regs \n\ call __clear_break_DPMI \n\ call __set_break_DPMI \n\ movl ___djgpp_exception_state_ptr,%eax \n\ @@ -753,9 +788,16 @@ jmp L_jmp_to_old_i31 \n\ Lc31_alloc_mem: \n\ pushf \n\ - .byte 0x2e \n\ - lcall _old_i31 \n\ - jc Lc31_set_flags_and_iret \n\ + .byte 0x2e \n" +#if (GAS_MAJOR == 2) \ + && ((GAS_MINOR < 9) || ((GAS_MINOR == 9) && (GAS_MINORMINOR < 5))) +" lcall _old_i31 \n\ +" +#else +" lcall *_old_i31 \n\ +" +#endif +" jc Lc31_set_flags_and_iret \n\ pushf \n\ pushl %edx \n\ pushw %si \n\ @@ -771,9 +813,16 @@ pushw %si \n\ pushw %di \n\ pushf \n\ - .byte 0x2e \n\ - lcall _old_i31 \n\ - jc Lc31_resize_mem_error \n\ + .byte 0x2e \n" +#if (GAS_MAJOR == 2) \ + && ((GAS_MINOR < 9) || ((GAS_MINOR == 9) && (GAS_MINORMINOR < 5))) +" lcall _old_i31 \n\ +" +#else +" lcall *_old_i31 \n\ +" +#endif +" jc Lc31_resize_mem_error \n\ popl %eax \n\ push %edx \n\ xorl %edx,%edx \n\ @@ -785,9 +834,16 @@ pushw %si \n\ pushw %di \n\ pushf \n\ - .byte 0x2e \n\ - lcall _old_i31 \n\ - jnc Lc31_resize_mem_ok \n\ + .byte 0x2e \n" +#if (GAS_MAJOR == 2) \ + && ((GAS_MINOR < 9) || ((GAS_MINOR == 9) && (GAS_MINORMINOR < 5))) +" lcall _old_i31 \n\ +" +#else +" lcall *_old_i31 \n\ +" +#endif +" jnc Lc31_resize_mem_ok \n\ Lc31_resize_mem_error: \n\ addl $4,%esp \n\ stc \n\ @@ -803,9 +859,16 @@ Lc31_alloc_descriptors: \n\ pushl %ecx \n\ pushf \n\ - .byte 0x2e \n\ - lcall _old_i31 \n\ - popl %ecx \n\ + .byte 0x2e \n" +#if (GAS_MAJOR == 2) \ + && ((GAS_MINOR < 9) || ((GAS_MINOR == 9) && (GAS_MINORMINOR < 5))) +" lcall _old_i31 \n\ +" +#else +" lcall *_old_i31 \n\ +" +#endif +" popl %ecx \n\ jc Lc31_set_flags_and_iret \n\ call _add_descriptors \n\ clc \n\ @@ -813,9 +876,16 @@ Lc31_free_descriptor: \n\ pushl %ebx \n\ pushf \n\ - .byte 0x2e \n\ - lcall _old_i31 \n\ - popl %eax \n\ + .byte 0x2e \n" +#if (GAS_MAJOR == 2) \ + && ((GAS_MINOR < 9) || ((GAS_MINOR == 9) && (GAS_MINORMINOR < 5))) +" lcall _old_i31 \n\ +" +#else +" lcall *_old_i31 \n\ +" +#endif +" popl %eax \n\ jc Lc31_set_flags_and_iret \n\ push %edx \n\ xorw %dx,%dx \n\ @@ -825,9 +895,16 @@ jmp Lc31_set_flags_and_iret \n\ Lc31_create_alias_descriptor: \n\ pushf \n\ - .byte 0x2e \n\ - lcall _old_i31 \n\ - jc Lc31_set_flags_and_iret \n\ + .byte 0x2e \n" +#if (GAS_MAJOR == 2) \ + && ((GAS_MINOR < 9) || ((GAS_MINOR == 9) && (GAS_MINORMINOR < 5))) +" lcall _old_i31 \n\ +" +#else +" lcall *_old_i31 \n\ +" +#endif +" jc Lc31_set_flags_and_iret \n\ pushl %eax \n\ push %edx \n\ movw %ax,%dx \n\ @@ -839,9 +916,16 @@ jmp Lc31_set_flags_and_iret \n\ Lc31_allocate_dos_memory: \n\ pushf \n\ - .byte 0x2e \n\ - lcall _old_i31 \n\ - jc Lc31_set_flags_and_iret \n\ + .byte 0x2e \n" +#if (GAS_MAJOR == 2) \ + && ((GAS_MINOR < 9) || ((GAS_MINOR == 9) && (GAS_MINORMINOR < 5))) +" lcall _old_i31 \n\ +" +#else +" lcall *_old_i31 \n\ +" +#endif +" jc Lc31_set_flags_and_iret \n\ pushl %eax \n\ xorl %eax,%eax \n\ call _change_dos_descriptor \n\ @@ -851,9 +935,16 @@ Lc31_free_dos_memory: \n\ pushl %edx \n\ pushf \n\ - .byte 0x2e \n\ - lcall _old_i31 \n\ - popl %eax \n\ + .byte 0x2e \n" +#if (GAS_MAJOR == 2) \ + && ((GAS_MINOR < 9) || ((GAS_MINOR == 9) && (GAS_MINORMINOR < 5))) +" lcall _old_i31 \n\ +" +#else +" lcall *_old_i31 \n\ +" +#endif +" popl %eax \n\ jc Lc31_set_flags_and_iret \n\ xorw %dx,%dx \n\ call _change_dos_descriptor \n\ @@ -865,18 +956,32 @@ pushl %ecx \n\ pushl %edx \n\ pushf \n\ - .byte 0x2e \n\ - lcall _old_i31 \n\ - popl %edx \n\ + .byte 0x2e \n" +#if (GAS_MAJOR == 2) \ + && ((GAS_MINOR < 9) || ((GAS_MINOR == 9) && (GAS_MINORMINOR < 5))) +" lcall _old_i31 \n\ +" +#else +" lcall *_old_i31 \n\ +" +#endif +" popl %edx \n\ popl %ecx \n\ popl %ebx \n\ popl %eax \n\ jc Lc31_set_flags_and_iret \n\ call _change_exception_handler \n\ pushf \n\ - .byte 0x2e \n\ - lcall _old_i31 \n\ - jmp Lc31_set_flags_and_iret \n\ + .byte 0x2e \n" +#if (GAS_MAJOR == 2) \ + && ((GAS_MINOR < 9) || ((GAS_MINOR == 9) && (GAS_MINORMINOR < 5))) +" lcall _old_i31 \n\ +" +#else +" lcall *_old_i31 \n\ +" +#endif +" jmp Lc31_set_flags_and_iret \n\ .balign 16,,7 \n\ .globl _dbgcom_hook_i21 \n\ _dbgcom_hook_i21: \n\ @@ -884,9 +989,16 @@ cmpb $0x4c,%ah \n\ je Lc21 \n\ Lc21_jmp_to_old: \n\ - .byte 0x2e \n\ - ljmp _old_i21 \n\ -Lc21: push %eax \n\ + .byte 0x2e \n" +#if (GAS_MAJOR == 2) \ + && ((GAS_MINOR < 9) || ((GAS_MINOR == 9) && (GAS_MINORMINOR < 5))) +" ljmp _old_i21 \n\ +" +#else +" ljmp *_old_i21 \n\ +" +#endif +"Lc21: push %eax \n\ movl 8(%esp),%eax \n\ cs \n\ cmpw _app_exit_cs,%ax \n\ @@ -1002,9 +1114,14 @@ /* do not set limit of ds selector two times */ asm (".text .global ___dbgcom_kbd_hdlr -___dbgcom_kbd_hdlr: - ljmp %cs:___djgpp_old_kbd"); - +___dbgcom_kbd_hdlr:" +#if (GAS_MAJOR == 2) \ + && ((GAS_MINOR < 9) || ((GAS_MINOR == 9) && (GAS_MINORMINOR < 5))) +" ljmp %cs:___djgpp_old_kbd"); +#else +" ljmp *%cs:___djgpp_old_kbd"); +#endif + static void unhook_dpmi(void) --- /dev/null Thu Jan 1 00:00:00 1970 +++ src/docs/kb/wcfcntl.txi Sat Nov 25 18:52:26 2000 @@ -0,0 +1,63 @@ + +@findex fcntl +The @code{fcntl} function has been significantly enhanced. In +particular: + +@itemize @minus{} +@item +@cindex file locking functions +file locking functions (which were missing in every version up to +v2.03) now work, with two exceptions: (1) command F_GETLK will not +return values in the 'struct flock' parameter identifying what lock +parameters prevent getting the requested lock; and (2) the F_RDLCK +value for requesting a read lock will not work unless all of the +following conditions are true in the passed 'struct flock lock_req': + +@itemize @plus{} +@item +lock_req->l_whence = SEEK_SET +@item +lock_req->l_start == 0 +@item +lock_req->l_len == 0 +@end itemize + +This is because DOS/Windows only supports read locks on a per-file +basis, so any attempted use of a read lock is an error, UNLESS all of +these conditions are true, which makes the request into a per-file lock +equivalent to an F_WRLCK request; + +@item +@cindex fcntl commands F_GETFD and F_SETFD +these functions now interrogate and use the value of the DOS flag +_DEV_NO_INHERIT to implement the FD_CLOEXEC flag; + +@item +@findex fcntl commands F_GETFL and F_SETFL +these functions are still effective no-ops, since DOS/Windows does not +allow flags to be modified on an open file, except for F_SETFL to remove +the O_NONBLOCK flag, which is not supported by DJGPP anyway. + +@item +Documentation has been updated to reflect the new functionality and a +test program has been provided. +@end itemize + +@findex flock +@findex lockf +@code{flock} and @code{lockf} have been implemented using the new +@code{fcntl} locking functions to implement file-level locking and +unlocking. Documentation and test programs have been provided. + +@findex dostrerr +@findex dostrcls +@findex dostract +@findex dostrloc +@findex dosexterr +New internal functions @code{dostrerr}, @code{dostrcls}, +@code{dostrerr} and @code{dostrerr} have been coded to provide string +values for the error codes returned from function @code{dosexterr}. +Documentation and test programs have been provided. These functions are +analogues of the @code{strerror} function for errno values, and are +intended to be used when coding functions or programs that call DOS and +want to print messages when errors occur. --- /dev/null Thu Jan 1 00:00:00 1970 +++ src/libc/compat/sys/file Sun Sep 8 18:07:22 1996 @@ -0,0 +1,9 @@ +# Copyright (C) 1996 DJ Delorie, see COPYING.DJ for details +# Copyright (C) 1995 DJ Delorie, see COPYING.DJ for details +TOP=../../.. + +SRC += resource.c +SRC += gtrlimit.c +SRC += strlimit.c + +include $(TOP)/../makefile.inc --- src/libc/dos/compat/d_exterr.txh.0 Sun Sep 27 11:21:20 1998 +++ src/libc/dos/compat/d_exterr.txh Sat Nov 25 13:29:22 2000 @@ -4,7 +4,7 @@ @example #include -int dosexterr(struct DOSERROR *p_error); +int dosexterr(struct _DOSERROR *p_error); @end example @subheading Description @@ -165,7 +165,7 @@ #include #include -void main(void) +int main(void) @{ FILE *fp; struct _DOSERROR de; @@ -181,5 +181,230 @@ printf("Action: %x\n",de.action); printf("Error Locus: %x\n",de.locus); @} + return 0; +@} +@end example + +@node dostrerr, dos +@subheading Syntax + +@example +#include + +char * +dostrerr(doserrno); +@end example + +@subheading Description + +This function accepts the extended error number from DOS (e.g., from +the return value from function @ref{dosexterr} or from the value of +@ref{_doserrno} after a failed DOS call) and returns the string which +describes that error number. This function is a DOS analogue of the +ANSI function @ref{strerror}, and can be used to print a descriptive +message corresponding to the error. + +For a list of the strings returned for each error number, see the +list at @ref{dosexterr}. + +@subheading Return Value + +Returns with the string describing extended error code. + +@subheading Portability + +@portability !ansi, !posix + +@subheading Example + +@example +#include +#include + +int main(void) +@{ + FILE *fp; + struct _DOSERROR de; + + fp = fopen("EXAMPLE.DAT","r"); + if ( fp == NULL ) + @{ + puts("Unable to open file for reading."); + _dosexterr(&de); + printf("Extended DOS error information:\n"); + printf("Extended error: %i : %s\n",de.exterror,dostrerr(de.exterror)); + printf("Class: %x : %s\n",de.class,dostrcls(de.class)); + printf("Action: %x : %s\n",de.action,dostract(de.action)); + printf("Error Locus: %x : %s\n",de.locus,dostrloc(de.locus)); + @} + return 0; +@} +@end example + +@node dostrcls, dos +@subheading Syntax + +@example +#include + +char * +dostrcls(doserrclass); +@end example + +@subheading Description + +This function accepts the extended error class number from DOS (i.e., +from the returned error class value from function @ref{dosexterr} after +a failed DOS call) and returns the string which describes that error +class number. This function is a DOS analogue of the ANSI function +@ref{strerror}, and can be used to print a descriptive message +corresponding to the error class. + +For a list of the strings returned for each error class number, see the +list at @ref{dosexterr}. + +@subheading Return Value + +Returns with the string describing extended error class code. + +@subheading Portability + +@portability !ansi, !posix + +@subheading Example + +@example +#include +#include + +int main(void) +@{ + FILE *fp; + struct _DOSERROR de; + + fp = fopen("EXAMPLE.DAT","r"); + if ( fp == NULL ) + @{ + puts("Unable to open file for reading."); + _dosexterr(&de); + printf("Extended DOS error information:\n"); + printf("Extended error: %i : %s\n",de.exterror,dostrerr(de.exterror)); + printf("Class: %x : %s\n",de.class,dostrcls(de.class)); + printf("Action: %x : %s\n",de.action,dostract(de.action)); + printf("Error Locus: %x : %s\n",de.locus,dostrloc(de.locus)); + @} + return 0; +@} +@end example + +@node dostract, dos +@subheading Syntax + +@example +#include + +char * +dostract(doserraction); +@end example + +@subheading Description + +This function accepts the extended error action number from DOS (i.e., +from the returned error action value from function @ref{dosexterr} after +a failed DOS call) and returns the string which describes that error +action number. This function is a DOS analogue of the ANSI function +@ref{strerror}, and can be used to print a descriptive message +corresponding to the error action. + +For a list of the strings returned for each error action number, see the +list at @ref{dosexterr}. + +@subheading Return Value + +Returns with the string describing extended error action code. + +@subheading Portability + +@portability !ansi, !posix + +@subheading Example + +@example +#include +#include + +int main(void) +@{ + FILE *fp; + struct _DOSERROR de; + + fp = fopen("EXAMPLE.DAT","r"); + if ( fp == NULL ) + @{ + puts("Unable to open file for reading."); + _dosexterr(&de); + printf("Extended DOS error information:\n"); + printf("Extended error: %i : %s\n",de.exterror,dostrerr(de.exterror)); + printf("Class: %x : %s\n",de.class,dostrcls(de.class)); + printf("Action: %x : %s\n",de.action,dostract(de.action)); + printf("Error Locus: %x : %s\n",de.locus,dostrloc(de.locus)); + @} + return 0; +@} +@end example + +@node dostrloc, dos +@subheading Syntax + +@example +#include + +char * +dostrloc(doserrlocus); +@end example + +@subheading Description + +This function accepts the extended error locus number from DOS (i.e., +from the returned error locus value from function @ref{dosexterr} after +a failed DOS call) and returns the string which describes that error +locus number. This function is a DOS analogue of the ANSI function +@ref{strerror}, and can be used to print a descriptive message +corresponding to the error locus. + +For a list of the strings returned for each error locus number, see the +list at @ref{dosexterr}. + +@subheading Return Value + +Returns with the string describing extended error locus code. + +@subheading Portability + +@portability !ansi, !posix + +@subheading Example + +@example +#include +#include + +int main(void) +@{ + FILE *fp; + struct _DOSERROR de; + + fp = fopen("EXAMPLE.DAT","r"); + if ( fp == NULL ) + @{ + puts("Unable to open file for reading."); + _dosexterr(&de); + printf("Extended DOS error information:\n"); + printf("Extended error: %i : %s\n",de.exterror,dostrerr(de.exterror)); + printf("Class: %x : %s\n",de.class,dostrcls(de.class)); + printf("Action: %x : %s\n",de.action,dostract(de.action)); + printf("Error Locus: %x : %s\n",de.locus,dostrloc(de.locus)); + @} + return 0; @} @end example --- /dev/null Thu Jan 1 00:00:00 1970 +++ src/libc/dos/compat/d_strerr.c Sat Nov 25 12:56:56 2000 @@ -0,0 +1,237 @@ +/* Copyright (C) 2000 DJ Delorie, see COPYING.DJ for details */ +/* + * D_STRERR.C. + * + * Written by Peter J. Farley III 2000 . + * + * This file is distributed WITHOUT ANY WARRANTY; without even the implied + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * + */ + +#include +#include +#include +#include +#include + +/* Values for extended error code (EXTERROR field): */ +const char *__dos_errlist [] = { +/* 00h (0) */ "No error", +/* 01h (1) */ "Function number invalid", +/* 02h (2) */ "File not found", +/* 03h (3) */ "Path not found", +/* 04h (4) */ "Too many open files (no handles available)", +/* 05h (5) */ "Access denied", +/* 06h (6) */ "Invalid handle", +/* 07h (7) */ "Memory control block destroyed", +/* 08h (8) */ "Insufficient memory", +/* 09h (9) */ "Memory block address invalid", +/* 0Ah (10) */ "Environment invalid (usually >32K in length)", +/* 0Bh (11) */ "Format invalid", +/* 0Ch (12) */ "Access code invalid", +/* 0Dh (13) */ "Data invalid", +/* 0Eh (14) */ "Reserved", +/* 0Fh (15) */ "Invalid drive", +/* 10h (16) */ "Attempted to remove current directory", +/* 11h (17) */ "Not same device", +/* 12h (18) */ "No more files", +/* 13h (19) */ "Disk write-protected", +/* 14h (20) */ "Unknown unit", +/* 15h (21) */ "Drive not ready", +/* 16h (22) */ "Unknown command", +/* 17h (23) */ "Data error (CRC)", +/* 18h (24) */ "Bad request structure length", +/* 19h (25) */ "Seek error", +/* 1Ah (26) */ "Unknown media type (non-DOS disk)", +/* 1Bh (27) */ "Sector not found", +/* 1Ch (28) */ "Printer out of paper", +/* 1Dh (29) */ "Write fault", +/* 1Eh (30) */ "Read fault", +/* 1Fh (31) */ "General failure", +/* 20h (32) */ "Sharing violation", +/* 21h (33) */ "Lock violation", +/* 22h (34) */ "Disk change invalid (ES:DI -> media ID structure)(see below)", +/* 23h (35) */ "FCB unavailable", +/* 24h (36) */ "Sharing buffer overflow", +/* 25h (37) */ "(DOS 4+) Code page mismatch", +/* 26h (38) */ "(DOS 4+) Cannot complete file operation (out of input)", +/* 27h (39) */ "(DOS 4+) Insufficient disk space", +/* 28h (40) */ "Reserved", +/* 29h (41) */ "Reserved", +/* 2Ah (42) */ "Reserved", +/* 2Bh (43) */ "Reserved", +/* 2Ch (44) */ "Reserved", +/* 2Dh (45) */ "Reserved", +/* 2Eh (46) */ "Reserved", +/* 2Fh (47) */ "Reserved", +/* 30h (48) */ "Reserved", +/* 31h (49) */ "Reserved", +/* 32h (50) */ "Network request not supported", +/* 33h (51) */ "Remote computer not listening", +/* 34h (52) */ "Duplicate name on network", +/* 35h (53) */ "Network name not found", +/* 36h (54) */ "Network busy", +/* 37h (55) */ "Network device no longer exists", +/* 38h (56) */ "Network BIOS command limit exceeded", +/* 39h (57) */ "Network adapter hardware error", +/* 3Ah (58) */ "Incorrect response from network", +/* 3Bh (59) */ "Unexpected network error", +/* 3Ch (60) */ "Incompatible remote adapter", +/* 3Dh (61) */ "Print queue full", +/* 3Eh (62) */ "Queue not full", +/* 3Fh (63) */ "Not enough space to print file", +/* 40h (64) */ "Network name was deleted", +/* 41h (65) */ "Network: Access denied", +/* 42h (66) */ "Network device type incorrect", +/* 43h (67) */ "Network name not found", +/* 44h (68) */ "Network name limit exceeded", +/* 45h (69) */ "Network BIOS session limit exceeded", +/* 46h (70) */ "Temporarily paused", +/* 47h (71) */ "Network request not accepted", +/* 48h (72) */ "Network print/disk redirection paused", +/* 49h (73) */ "Network software not installed", +/* "(LANtastic) Invalid network version", */ +/* 4Ah (74) */ "Unexpected adapter close", +/* "(LANtastic) Account expired", */ +/* 4Bh (75) */ "(LANtastic) Password expired", +/* 4Ch (76) */ "(LANtastic) Login attempt invalid at this time", +/* 4Dh (77) */ "(LANtastic v3+) Disk limit exceeded on network node", +/* 4Eh (78) */ "(LANtastic v3+) Not logged in to network node", +/* 4Fh (79) */ "Reserved", +/* 50h (80) */ "File exists", +/* 51h (81) */ "Reserved", +/* 52h (82) */ "Cannot make directory", +/* 53h (83) */ "Fail on INT 24h", +/* 54h (84) */ "(DOS 3.3+) Too many redirections", +/* 55h (85) */ "(DOS 3.3+) Duplicate redirection", +/* 56h (86) */ "(DOS 3.3+) Invalid password", +/* 57h (87) */ "(DOS 3.3+) Invalid parameter", +/* 58h (88) */ "(DOS 3.3+) Network write fault", +/* 59h (89) */ "(DOS 4+) Function not supported on network", +/* 5Ah (90) */ "(DOS 4+) Required system component not installed", +/* 5Bh (91) */ "Reserved", +/* 5Ch (92) */ "Reserved", +/* 5Dh (93) */ "Reserved", +/* 5Eh (94) */ "Reserved", +/* 5Fh (95) */ "Reserved", +/* 60h (96) */ "Reserved", +/* 61h (97) */ "Reserved", +/* 62h (98) */ "Reserved", +/* 63h (99) */ "Reserved", +/* 64h (100)*/ "(MSCDEX) Unknown error", +/* 65h (101)*/ "(MSCDEX) Not ready", +/* 66h (102)*/ "(MSCDEX) EMS memory no longer valid", +/* 67h (103)*/ "(MSCDEX) Not High Sierra or ISO-9660 format", +/* 68h (104)*/ "(MSCDEX) Door open" +/* (End of list) */ }; + +int __dos_nerr = sizeof(__dos_errlist) / sizeof(__dos_errlist[0]); + +/* Values for error class (CLASS field): */ +const char *__dos_errclass [] = { +/* 01h (01) */ "Out of resource (storage space or I/O channels)", +/* 02h (02) */ "Temporary situation (file or record lock)", +/* 03h (03) */ "Authorization (denied access)", +/* 04h (04) */ "Internal (system software bug)", +/* 05h (05) */ "Hardware failure", +/* 06h (06) */ "System failure (configuration file missing or incorrect)", +/* 07h (07) */ "Application program error", +/* 08h (08) */ "Not found", +/* 09h (09) */ "Bad format", +/* 0Ah (10) */ "Locked", +/* 0Bh (11) */ "Media error", +/* 0Ch (12) */ "Already exists", +/* 0Dh (13) */ "Unknown" +/* (End of list) */ }; + +int __dos_ncls = sizeof(__dos_errclass) / sizeof(__dos_errclass[0]); + +/* Values for suggested action (ACTION field): */ +const char *__dos_erraction [] = { +/* 01h (01) */ "Retry", +/* 02h (02) */ "Delayed retry", +/* 03h (03) */ "Prompt user to reenter input", +/* 04h (04) */ "Abort after cleanup", +/* 05h (05) */ "Immediate abort", +/* 06h (06) */ "Ignore", +/* 07h (07) */ "Retry after user intervention" +/* (End of list) */ }; + +int __dos_nact = sizeof(__dos_erraction) / sizeof(__dos_erraction[0]); + +/* Values for error locus (LOCUS field): */ +const char *__dos_errlocus [] = { +/* 01h (01) */ "Unknown or not appropriate", +/* 02h (02) */ "Block device (disk error)", +/* 03h (03) */ "Network related", +/* 04h (04) */ "Serial device (timeout)", +/* 05h (05) */ "Memory related" +/* (End of list) */ }; + +int __dos_nloc = sizeof(__dos_errlocus) / sizeof(__dos_errlocus[0]); + +static char * +_err_unknown(int errnum) +{ + static char ebuf[40]; /* 64-bit number + slop */ + char *cp; + int v=1000000, lz=0; + + strcpy(ebuf, "Unknown error: "); + cp = ebuf + 15; + if (errnum < 0) + { + *cp++ = '-'; + errnum = -errnum; + } + while (v) + { + int d = errnum / v; + if (d || lz || (v == 1)) + { + *cp++ = d+'0'; + lz = 1; + } + errnum %= v; + v /= 10; + } + + return ebuf; +} + +char * +dostrerr(int errnum) +{ + if (errnum >= 0 && errnum < __dos_nerr) + return(unconst(__dos_errlist[errnum], char *)); + else + return(_err_unknown(errnum)); +} + +char * +dostrcls(int errnum) +{ + if (errnum >= 0 && errnum < __dos_ncls) + return(unconst(__dos_errclass[errnum], char *)); + else + return(_err_unknown(errnum)); +} + +char * +dostract(int errnum) +{ + if (errnum >= 0 && errnum < __dos_nact) + return(unconst(__dos_erraction[errnum], char *)); + else + return(_err_unknown(errnum)); +} + +char * +dostrloc(int errnum) +{ + if (errnum >= 0 && errnum < __dos_nloc) + return(unconst(__dos_errlocus[errnum], char *)); + else + return(_err_unknown(errnum)); +} --- src/libc/dos/compat/makefile.0 Sun Aug 27 02:38:32 1995 +++ src/libc/dos/compat/makefile Sat Nov 25 13:02:16 2000 @@ -21,6 +21,7 @@ SRC += d_setfa.c SRC += d_setftm.c SRC += d_settim.c +SRC += d_strerr.c SRC += d_write.c include $(TOP)/../makefile.inc --- src/libc/dos/errno/doserr2e.c.0 Tue Sep 8 07:49:26 1998 +++ src/libc/dos/errno/doserr2e.c Sat Nov 25 12:05:32 2000 @@ -1,5 +1,11 @@ +/* Copyright (C) 2000 DJ Delorie, see COPYING.DJ for details */ /* Copyright (C) 1998 DJ Delorie, see COPYING.DJ for details */ /* Copyright (C) 1995 DJ Delorie, see COPYING.DJ for details */ + +/* Changed 11/25/2000, 21h (33) EPERM -> EACCES */ +/* 21h (33) lock violation needs EACCES errno in fcntl */ +/* Peter J. Farley III #include @@ -8,7 +14,7 @@ /* 08-0f */ ENOMEM, EFAULT, EFAULT, EINVAL, EINVAL, EINVAL, EINVAL, ENODEV, /* 10-17 */ EBUSY, EXDEV, ENMFILE, EROFS, ENXIO, ENXIO, EINVAL, EIO, /* 18-1f */ EINVAL, EIO, EIO, EIO, EIO, EIO, EIO, EIO, - /* 20-27 */ EPERM, EPERM, ENXIO, EBADF, ENOLCK, EINVAL, EIO, ENOSPC, + /* 20-27 */ EPERM, EACCES, ENXIO, EBADF, ENOLCK, EINVAL, EIO, ENOSPC, /* 28-2f */ EINVAL, EINVAL, EINVAL, EINVAL, EINVAL, EINVAL, EINVAL, EINVAL, /* 30-37 */ EINVAL, EINVAL, ENOSYS, EIO, EINVAL, EINVAL, EBUSY, ENXIO, /* 38-3f */ EINVAL, EIO, EIO, EIO, EIO, EAGAIN, EINVAL, ENOSPC, --- src/libc/go32/exceptn.S.0 Sun Jul 11 05:09:06 1999 +++ src/libc/go32/exceptn.S Sat Nov 18 19:01:16 2000 @@ -348,7 +348,12 @@ popl %ds popl %ebx popl %eax +#if (GAS_MAJOR == 2) \ + && ((GAS_MINOR < 9) || ((GAS_MINOR == 9) && (GAS_MINORMINOR < 5))) ljmp %cs:___djgpp_old_kbd +#else + ljmp *%cs:___djgpp_old_kbd +#endif .balign 16,,7 .global ___djgpp_kbd_hdlr_pc98 @@ -400,7 +405,12 @@ .byte 0x2e /* CS: */ testb $4, ___djgpp_hwint_flags /* IRET or chain? */ jne 2f +#if (GAS_MAJOR == 2) \ + && ((GAS_MINOR < 9) || ((GAS_MINOR == 9) && (GAS_MINORMINOR < 5))) ljmp %cs:___djgpp_old_timer +#else + ljmp *%cs:___djgpp_old_timer +#endif 2: pushl %eax movb $0x20,%al /* EOI the interrupt */ --- src/libc/posix/fcntl/fcntl.c.0 Thu Jun 3 13:27:38 1999 +++ src/libc/posix/fcntl/fcntl.c Sat Nov 25 13:12:48 2000 @@ -1,3 +1,4 @@ +/* Copyright (C) 2000 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 */ /* Copyright (C) 1995 DJ Delorie, see COPYING.DJ for details */ @@ -7,28 +8,101 @@ #include #include #include +#include #include +#include +#include +#include +#include -static int -is_used_fd(int fd) + +#include + + +static unsigned long _get_sft_entry_ptr(int fd) { __dpmi_regs regs; + unsigned char index; + unsigned long es, di; + - regs.x.ax = 0x4400; + /* Get the JFT entry address for this handle. */ + regs.x.ax = 0x1220; regs.x.bx = fd; - __dpmi_int(0x21, ®s); + __dpmi_int(0x2f, ®s); + + if (regs.x.flags & 1) + { + errno = ENOSYS; return 0; + } + + + /* Get the SFT entry number for this handle. */ + es = regs.x.es; + di = regs.x.di; + index = _farpeekb(_dos_ds, es * 16 + di); - return 1; + + /* Now get the address of the entry. */ + regs.x.ax = 0x1216; + regs.x.bx = index; + __dpmi_int (0x2f, ®s); + if (regs.x.flags & 1) + { + errno = ENOSYS; + return 0; + } + + + es = regs.x.es; + di = regs.x.di; + + + return es * 16 + di; } + +static int +inherit_bit_test (int fd, short dev_info) +{ + __dpmi_regs regs; + short new_dev_info; + + + dev_info |= _DEV_NO_INHERIT; + regs.x.ax = 0x4401; + regs.x.bx = fd; + regs.x.dx = dev_info; + __dpmi_int(0x21, ®s); + + new_dev_info = _get_dev_info(fd); + + /* If the dev info words are equal, then the documented + interface can't be used to set the inheritance bit. */ + return (new_dev_info == dev_info) ? 1 : 0; +} + + int fcntl(int fd, int cmd, ...) { int tofd, open_max; va_list ap; - __FSEXT_Function *func = __FSEXT_get_function(fd); + __FSEXT_Function *func; + short dev_info = _get_dev_info(fd); + static int inherit_bit_visible = -1; + int errno_save; + + /* Verify the descriptor is valid by retrieving + the handle's device info word. */ + if (dev_info == -1) + return dev_info; + + + /* Allow a fd to override with a FSEXT. */ + func = __FSEXT_get_function(fd); if (func) { int rv; @@ -36,62 +110,286 @@ return rv; } + + errno_save = errno; + switch (cmd) { - case F_DUPFD: - va_start(ap, cmd); - tofd = va_arg(ap, int); - va_end(ap); - - open_max = getdtablesize(); - if (tofd < 0 || tofd >= open_max) + case F_DUPFD: { - errno = EINVAL; - return -1; + va_start(ap, cmd); + tofd = va_arg(ap, int); + va_end(ap); + + + open_max = getdtablesize(); + while (tofd < open_max) + { + /* If unable to get the device info for the handle, + then the handle is not active and it can be used. */ + if (_get_dev_info(tofd) == -1) + break; + tofd++; + } + + + if (tofd >= open_max) + { + errno = EMFILE; + return -1; + } + + + errno = errno_save; + return dup2(fd, tofd); } - while (tofd < open_max) + + + case F_GETFD: { - if (! is_used_fd(tofd)) - break; - tofd++; + unsigned long entry_ptr; + + + /* DOS only passes the first 20 handles to child programs. In + addition, handles 19 and 18 will be closed by the stub of the + child program (if it is a DJGPP program). */ + + + if (fd >= 18) + return FD_CLOEXEC; + + + /* Determine if the documented interface will allow twiddling with + the inherit bit. If not, fallback to the undocumented one. */ + if (inherit_bit_visible == -1) + inherit_bit_visible = inherit_bit_test (fd, dev_info); + + if (!inherit_bit_visible) + { + entry_ptr = _get_sft_entry_ptr(fd); + if (entry_ptr == 0) + { + /* The fd has already been validated, so reaching here means + something is wrong with _get_sft_entry_ptr. */ + return -1; + } + /* Offset 5 in the SFT contains the device info word. */ + dev_info = _farpeekw(_dos_ds, entry_ptr + 5); + } + return (dev_info & _DEV_NO_INHERIT) ? FD_CLOEXEC : 0; } - if (tofd >= open_max) + + case F_SETFD: { - errno = EMFILE; - return -1; + unsigned int flag; + unsigned long entry_ptr = 0; /* shut up -Wall */ + __dpmi_regs regs; + + + va_start (ap, cmd); + flag = va_arg(ap, int); + va_end(ap); + + + /* DOS only passes the first 20 handles to child programs. In + addition, handles 19 and 18 will be closed by the stub of the + child program (if it is a DJGPP program). */ + if (fd >= 18) + { + if (flag & FD_CLOEXEC) + return 0; + else + { + errno = ENOSYS; + return -1; + } + } + + + /* Determine if the documented interface will allow twiddling with + the inherit bit. If not, fallback to the undocumented one. */ + if (inherit_bit_visible == -1) + inherit_bit_visible = inherit_bit_test(fd, dev_info); + + if (!inherit_bit_visible) + { + entry_ptr = _get_sft_entry_ptr(fd); + if (entry_ptr == 0) + { + /* The fd has already been validated, so reaching here means + something is wrong with _get_sft_entry_ptr. */ + return -1; + } + + + dev_info = _farpeekw(_dos_ds, entry_ptr + 5); + } + + + if (flag & FD_CLOEXEC) + dev_info |= _DEV_NO_INHERIT; + else + dev_info &= ~(_DEV_NO_INHERIT); + + + if (inherit_bit_visible) + { + regs.x.ax = 0x4401; + regs.x.bx = fd; + regs.x.dx = dev_info; + __dpmi_int(0x21, ®s); + } + else + _farpokew(_dos_ds, entry_ptr + 5, dev_info); + + + return 0; } - return dup2(fd, tofd); - - case F_GETFD: - /* DOS only passes the first 20 handles to child programs. In - addition, handles 19 and 18 will be closed by the stub of the - child program (if it is a DJGPP program). - FIXME: we should look at the no-inherit bit stashed in the SFT - entry pointed to by the handle, since some of the first 18 - handles could have been opened with a no-inherit bit. */ - return fd >= 18 ? FD_CLOEXEC : 0; - case F_SETFD: - if ((fd < 18) ^ ((cmd & FD_CLOEXEC) != 0)) + case F_GETFL: + { return 0; - else + } + + + case F_SETFL: + { + unsigned char new_mode_bits; + + + va_start (ap, cmd); + new_mode_bits = va_arg(ap,int); + va_end(ap); + + + /* Allow removal of O_NONBLOCK, since DJGPP doesn't support it + anyway. */ + return (new_mode_bits == 0) ? 0 : -1; + } + + + case F_GETLK: + case F_SETLK: + case F_SETLKW: + { + struct flock *lock_req = NULL; /* shut up -Wall */ + int ret = -1; + off_t pos, cur_pos, lock_pos; + off_t len; + + + cur_pos = lseek(fd, 0, SEEK_CUR); + va_start (ap, cmd); + lock_req = va_arg(ap, struct flock *); + va_end (ap); + lock_pos = lseek (fd, lock_req->l_start, lock_req->l_whence); + len = lock_req->l_len; + + + /* If l_len is zero, then the lock is to be set from l_start + until the end-of-file. */ + if (len == 0) { - errno = ENOSYS; - return -1; + len = filelength(fd) - cur_pos; + /* This should probably be an error. */ + if (len <= 0) + len = 1; } - case F_GETFL: - return 0; /* FIXME: should use the data in the SFT */ - case F_SETFL: - errno = ENOSYS; - return -1; - case F_GETLK: - case F_SETLK: - case F_SETLKW: - errno = ENOSYS; - return -1; + + + lseek (fd, cur_pos, SEEK_SET); + + + /* If l_len is positive, the area to lock is from l_start + to l_start + l_len - 1. If l_len is negative, the area to lock is + from l_start + len to l_start - 1. */ + if (len > 0) + { + pos = lock_pos; + } + else + { + pos = lock_pos + len; + len = -lock_req->l_len; + } + + + /* DOS/Windows only support read locks on a per-file basis, + so any attempted use of a read lock is an error, + UNLESS all of these conditions are true, which makes the + request into a per-file lock equivalent to F_WRLCK: + + lock_req->l_whence = SEEK_SET + lock_req->l_start == 0 + lock_req->l_len == 0 + */ + if ((lock_req->l_type == F_RDLCK) && + (lock_req->l_whence != SEEK_SET || + lock_req->l_start != 0 || + lock_req->l_len != 0)) + { + errno = ENOSYS; + return -1; + } + + if (lock_req->l_type == F_UNLCK) + { + ret = _dos_unlock(fd, pos, len); + if (ret != 0) + { + _doserrno = ret; + errno = __doserr_to_errno(ret); + return -1; + } + } + else if ((lock_req->l_type == F_WRLCK) || (lock_req->l_type == F_RDLCK)) + { + ret = _dos_lock(fd, pos, len); + if (cmd == F_GETLK) + { + if (ret == 0) + { + _dos_unlock(fd, pos, len); + /* If no lock is found that would prevent a lock from + being created, the lock type is set to F_UNLCK. */ + lock_req->l_type = F_UNLCK; + } + else + { + /* If a lock is found then l_whence, l_start, and l_len + should point to the area covered by the lock. But the + file locking interface doesn't report where the + existing lock is, so nothing more can be done. */ + _doserrno = ret; + errno = __doserr_to_errno(ret); + return -1; + } + } + else if (ret != 0) + { + _doserrno = ret; + errno = __doserr_to_errno(ret); + return -1; + } + + + /* If F_SETLKW is set, wait for the lock to be released. */ + if (cmd == F_SETLKW && ret < 0) + while ((ret = _dos_lock(fd, pos, len)) != 0) + __dpmi_yield(); + } + if (ret != 0) + errno = ENOSYS; + + + return ret; + } } + + + /* In case fcntl is called with an unrecognized command. */ errno = ENOSYS; return -1; } --- src/libc/posix/fcntl/fcntl.txh.0 Thu Jun 3 02:35:56 1999 +++ src/libc/posix/fcntl/fcntl.txh Sun Nov 26 19:24:36 2000 @@ -31,19 +31,33 @@ stub loader of the child DJGPP program will forcibly close handles 19 and 18 (since otherwise it will be unable to read the COFF executable information and enter protected mode). Therefore, the current -implementation always returns 0 for handles below 18, meaning that all -those handles are inherited, and @code{FD_CLOEXEC} for handles 18 and +implementation always returns @code{FD_CLOEXEC} for handles 18 and above. +For handles less than 18, the call will try to determine the status of +the @code{O_NOINHERIT} flag for that file and will return either +@code{FD_CLOEXEC} if the flag is set, or 0 if the flag is not set. If +the status of the @code{O_NOINHERIT} flag cannot be determined, the call +will return -1, setting @code{errno} to @code{ENOSYS}. + The no-inherit bit can be set when the file is open, by using the @code{O_NOINHERIT} in the open flags; see @ref{open}. @item F_SETFD -Set the close-on-exec flag for the handle @var{fd} using the LSB of the -integer value supplied as the third argument. Currently, @code{fcntl} -always fails this call and sets @code{errno} to @code{ENOSYS}, since -DOS/Windows don't support changing the no-inherit status of an open -file. +Set or unset the close-on-exec flag for the handle @var{fd} using the +LSB of the integer value supplied as the third argument. Since only the +first 20 handles are passed to child programs, and since the stub loader +of the child DJGPP program will forcibly close handles 19 and 18 (since +otherwise it will be unable to read the COFF executable information and +enter protected mode), the flag can only be set or unset on the first 18 +handles. Attempts to set the flag for handles 18 or above will always +return 0, and attempts to unset the flag for handles 18 or above will +always return -1, setting @code{errno} to @code{ENOSYS}. + +For handles less than 18, the call will try to set or unset the +@code{O_NOINHERIT} flag for that file and will return 0 if the flag is +changed. If the @code{O_NOINHERIT} flag cannot be changed, the call +will return -1, setting @code{errno} to @code{ENOSYS}. @item F_GETFL Get the open mode and status flags associated with the handle @var{fd}. @@ -53,23 +67,33 @@ @item F_SETFL Set the open mode and status flags associated with the handle @var{fd}. -This always fails and sets @code{errno} to @code{ENOSYS}, since DOS and -Windows don't allow to change the descriptor flags after the file is -open. +This fails in all but one case, and sets @code{errno} to @code{ENOSYS}, +since DOS and Windows don't allow changing the descriptor flags after +the file is open. The one allowed case is for @code{O_NONBLOCK}, since +DJGPP doesn't support it anyway. @item F_GETLK -Get a description of a file segment lock as specified in the structure -pointed to by the third argument. This is unsupported and will always -fail. +Return the lock structure that prevents obtaining the lock pointed to by +the third argument, or set the @code{l_type} field of the lock structure +to @code{F_UNLCK} if there is no obstruction. Currently, only the +setting of the @code{l_type} field is provided. If the lock cannot be +obtained, -1 is returned and @code{errno} is set to the reason (which +will be one of @code{EINVAL}, @code{EBADF}, @code{EACCES} or +@code{ENOLCK}). @item F_SETLK Set or clear a file segment lock according to the structure pointed to -by the third argument. This is unsupported and will always fail. +by the third argument. The lock is set when @code{l_type} is +@code{F_RDLCK} (shared lock request) or @code{F_WRLCK} (exclusive lock +request), and the lock is cleared when @code{l_type} is @code{F_UNLCK}. +If the lock is already held, then this call returns -1 and sets +@code{errno} to @code{EACCES}. @item F_SETLKW Same as @code{F_SETLK}, but if the lock is blocked, the call will wait -until it is unblocked and the lock can be applied. This is unsupported -and will always fail. +(using @code{__dpmi_yield()}) until it is unblocked and the lock can be +applied. This call will never exit if the program making the call is +program which already owns the lock. @end table This function can be hooked by the @dfn{Filesystem extensions}, see @@ -99,4 +123,46 @@ /* Save the handle in a way that it won't be passed to child processes. */ int saved_fd = fcntl (fd, F_DUPFD, 20); + + /* Set an advisory lock for the whole file */ + struct flock flock; + int retval, fd; + + flock.l_type = F_RDLCK; + flock.l_whence = SEEK_SET; + flock.l_start = flock.l_len = 0; + errno = 0; + retval = fcntl(fd, F_SETLK, &flock); + + /* Get the status of the lock we just obtained + (should return -1 with errno == EACCES) */ + errno = 0; + retval = fcntl(fd, F_GETLK, &flock); + + /* Release the lock */ + errno = 0; + flock.l_type = F_UNLCK; + retval = fcntl(fd, F_SETLK, &flock); + + /* Get the status of the lock we just released + (should return 0) */ + errno = 0; + flock.l_type = F_RDLCK; + retval = fcntl(fd, F_GETLK, &flock); + + /* Try to set the O_BINARY flag on the open file + (should return -1 with errno == ENOSYS) */ + errno = 0; + retval = fcntl(fd, F_SETFL, O_BINARY); + + /* Set the O_NONBLOCK flag on the open file + (should return 0) */ + errno = 0; + retval = fcntl(fd, F_SETFL, O_NONBLOCK); + + /* Get the flags on the open file + (always returns 0) */ + errno = 0; + retval = fcntl(fd, F_GETFL); + @end example --- /dev/null Thu Jan 1 00:00:00 1970 +++ src/libc/posix/sys/file/flock.c Sat Nov 25 23:57:40 2000 @@ -0,0 +1,38 @@ +/* Copyright (C) 2000 DJ Delorie, see COPYING.DJ for details */ + +/* This file implements the `flock' function in terms of the POSIX.1 `fcntl' + locking mechanism. */ + +#include +#include +#include +#include + +/* Apply or remove an advisory lock, according to OPERATION, + on the file FD refers to. */ +int +flock (int _fildes, int _op) +{ + struct flock lock_req; + + switch (_op & ~LOCK_NB) + { + case LOCK_SH: + lock_req.l_type = F_RDLCK; + break; + case LOCK_EX: + lock_req.l_type = F_WRLCK; + break; + case LOCK_UN: + lock_req.l_type = F_UNLCK; + break; + default: + errno = EINVAL; + return -1; + } + + lock_req.l_whence = SEEK_SET; + lock_req.l_start = lock_req.l_len = 0L; /* Lock the whole file. */ + + return fcntl (_fildes, (_op & LOCK_NB) ? F_SETLK : F_SETLKW, &lock_req); +} --- /dev/null Thu Jan 1 00:00:00 1970 +++ src/libc/posix/sys/file/flock.txh Sun Nov 26 21:50:10 2000 @@ -0,0 +1,62 @@ +@node flock, sys +@subheading Syntax + +@example +#include + +int flock (int _fildes, int _op); +@end example + +@subheading Description + +Apply or remove an advisory lock on an open file. The file is specified +by file handle @var{_fildes}. Valid operations are given below: + +@table @code +@item LOCK_SH +Shared lock. More than one process may hold a shared lock for a given +file at a given time. + +@item LOCK_EX +Exclusive lock. Only one process may hold an exclusive lock for a given +file at a given time. + +@item LOCK_UN +Unlock the file. + +@item LOCK_NB +Don't block when locking. May be specified (by or'ing) along with one of +the other operations. +@end table + +A single file may not simultaneously have both shared and exclusive +locks. + +A file is locked, not the file descriptor. So, dup (2) does not create +multiple instances of a lock. + +@subheading Return Value + +On success, zero is returned. On error, -1 is returned, and +@code{errno} is set appropriately. + +@subheading Portability + +@port-note posix 4.4BSD (the flock (2) call first appeared in 4.2BSD). +@portability !ansi, posix + +@subheading Example + +@example + /* Request a shared lock on file handle fd */ + errno = 0; + retval = flock(fd, LOCK_SH); + + /* Request an exclusive lock on file handle fd */ + errno = 0; + retval = flock(fd, LOCK_EX); + + /* Release a lock on file handle fd */ + errno = 0; + retval = flock(fd, LOCK_UN); +@end example --- /dev/null Thu Jan 1 00:00:00 1970 +++ src/libc/posix/sys/file/makefile Sun Nov 26 00:28:40 2000 @@ -0,0 +1,6 @@ +# Copyright (C) 2000 DJ Delorie, see COPYING.DJ for details +TOP=../../.. + +SRC += flock.c + +include $(TOP)/../makefile.inc --- src/makefile.inc.0 Mon Sep 7 14:12:10 1998 +++ src/makefile.inc Sat Nov 25 18:09:08 2000 @@ -1,3 +1,4 @@ +# Copyright (C) 2000 DJ Delorie, see COPYING.DJ for details # Copyright (C) 1998 DJ Delorie, see COPYING.DJ for details # -*- makefile -*- @@ -7,12 +8,58 @@ .SUFFIXES: .o .i .c .cc .s +# Set $(GCC{L}_OPT) here so they are defined before first use +# +ifeq ($(CROSS_BUILD),1) +GCC_OPT := $(shell cat $(TOP)/../gcc.opt) +GCCL_OPT := $(shell cat $(TOP)/../gcc-l.opt) +endif + +# Set $(AS) before first use +# +AS := $(shell $(CROSS_GCC) $(GCC_OPT) -print-prog-name=as) +AS := $(subst \,/,$(AS)) + +# These were suggested by Tim Van Holder +# but since $(CROSS_LD) is set in makefile.def and $(LD) is not used +# anywhere, they seem not very useful at this time. +# +#LD := $(shell $(CROSS_GCC) $(GCC_OPT) -print-prog-name=ld) +#LD := $(subst \,/,$(LD)) + +# Figure out GAS version for use in *.S and inline asm compile flags +# +GAS_VERSION := $(subst ., ,$(shell $(AS) --version)) +GAS_MAJOR := $(word 3,$(GAS_VERSION)) +GAS_MINOR := $(word 4,$(GAS_VERSION)) +GAS_MINORMINOR := $(word 5,$(GAS_VERSION)) + +# Defaults for GAS version numbers +ifeq ($(GAS_MAJOR),) +GAS_MAJOR := 0 +endif +ifeq ($(GAS_MINOR),) +GAS_MINOR := 0 +endif +ifeq ($(GAS_MINORMINOR),) +GAS_MINORMINOR := 0 +endif + +# Pass defines as compiler/assembler switches +CFLAGS += -DGAS_MAJOR=$(GAS_MAJOR) +CFLAGS += -DGAS_MINOR=$(GAS_MINOR) +CFLAGS += -DGAS_MINORMINOR=$(GAS_MINORMINOR) + +ASFLAGS += -DGAS_MAJOR=$(GAS_MAJOR) +ASFLAGS += -DGAS_MINOR=$(GAS_MINOR) +ASFLAGS += -DGAS_MINORMINOR=$(GAS_MINORMINOR) + +# Moved setting of $(GCC{L}_OPT) to top of file +# ifneq ($(CROSS_BUILD),1) XGCC = $(CROSS_GCC) @$(TOP)/../gcc.opt -I. -I- -I$(TOP)/../../include $(CFLAGS) XLGCC = $(CROSS_GCC) -s @$(TOP)/../gcc-l.opt -I. -I- -I$(TOP)/../../include $(CFLAGS) else -GCC_OPT := $(shell cat $(TOP)/../gcc.opt) -GCCL_OPT := $(shell cat $(TOP)/../gcc-l.opt) XGCC = $(CROSS_GCC) $(GCC_OPT) -I. -I- -I$(TOP)/../../include $(CFLAGS) XLGCC = $(CROSS_GCC) $(GCCL_OPT) -I. -I- -I$(TOP)/../../include $(CFLAGS) endif @@ -59,13 +106,13 @@ L = $(LIB)/libc.a ifeq ($(LIBGCCA),) -LIBGCCA := $(shell $(CROSS_GCC) -print-file-name=libgcc.a) +LIBGCCA := $(shell $(CROSS_GCC) $(GCC_OPT) -print-file-name=libgcc.a) LIBGCCA := $(subst \,/,$(LIBGCCA)) export LIBGCCA endif ifeq ($(DJGPP_DJL),) -DJGPP_DJL := $(shell $(CROSS_GCC) -print-file-name=djgpp.djl) +DJGPP_DJL := $(shell $(CROSS_GCC) $(GCC_OPT) -print-file-name=djgpp.djl) DJGPP_DJL := $(subst \,/,$(DJGPP_DJL)) export DJGPP_DJL endif --=====================_24418177==_ Content-Type: text/plain; charset="us-ascii" --- include/dos.h.0 Thu Jun 3 13:22:28 1999 +++ include/dos.h Sat Nov 25 12:59:58 2000 @@ -1,3 +1,4 @@ +/* Copyright (C) 2000 DJ Delorie, see COPYING.DJ for details */ /* Copyright (C) 1999 DJ Delorie, see COPYING.DJ for details */ /* Copyright (C) 1998 DJ Delorie, see COPYING.DJ for details */ /* Copyright (C) 1995 DJ Delorie, see COPYING.DJ for details */ @@ -256,6 +257,10 @@ int _dosexterr(struct _DOSERROR *_p_error); #define dosexterr(_ep) _dosexterr(_ep) +char * dostrerr(int); +char * dostrcls(int); +char * dostract(int); +char * dostrloc(int); #define int386(_i, _ir, _or) int86(_i, _ir, _or) #define int386x(_i, _ir, _or, _sr) int86x(_i, _ir, _or, _sr) --- /dev/null Thu Jan 1 00:00:00 1970 +++ include/libc/getdinfo.h Sun Nov 5 12:11:22 2000 @@ -0,0 +1,25 @@ +/* Copyright (C) 2000 DJ Delorie, see COPYING.DJ for details */ +#ifndef __dj_include_libc_getdinfo_h__ +#define __dj_include_libc_getdinfo_h__ + +#ifndef __dj_ENFORCE_ANSI_FREESTANDING + +#ifndef __STRICT_ANSI__ + +#ifndef _POSIX_SOURCE + +/* For parsing the bits returned by _get_dev_info. */ +#define _DEV_STDIN 0x0001 +#define _DEV_STDOUT 0x0002 +#define _DEV_NUL 0x0004 +#define _DEV_CLOCK 0x0008 +#define _DEV_RAW 0x0020 +#define _DEV_CDEV 0x0080 +#define _DEV_NO_INHERIT 0x1000 /* Undocumented. */ +#define _DEV_IOCTRL 0x4000 + +#endif /* !_POSIX_SOURCE */ +#endif /* !__STRICT_ANSI__ */ +#endif /* !__dj_ENFORCE_ANSI_FREESTANDING */ + +#endif --- include/sys/file.h.0 Thu Apr 20 01:35:34 1995 +++ include/sys/file.h Sat Nov 25 23:51:28 2000 @@ -22,7 +22,20 @@ #define L_CURR 1 #define L_INCR 1 #define L_XTND 2 - + +/* Operations for the `flock' call. */ +#define LOCK_SH 1 /* Shared lock. */ +#define LOCK_EX 2 /* Exclusive lock. */ +#define LOCK_UN 8 /* Unlock. */ + +/* Can be OR'd in to one of the above. */ +#define LOCK_NB 4 /* Don't block when locking. */ + + +/* Apply or remove an advisory lock, according to OPERATION, + on the file FD refers to. */ +int flock (int _fildes, int _op); + #ifndef __dj_ENFORCE_FUNCTION_CALLS #endif /* !__dj_ENFORCE_FUNCTION_CALLS */ --=====================_24418177==_ Content-Type: text/plain; charset="us-ascii" --- /dev/null Thu Jan 1 00:00:00 1970 +++ tests/libc/dos/compat/d_exterr.c Sat Nov 25 13:27:38 2000 @@ -0,0 +1,21 @@ +#include +#include + +int main(void) +{ + FILE *fp; + struct _DOSERROR de; + + fp = fopen("EXAMPLE.DAT","r"); + if ( fp == NULL ) + { + puts("Unable to open file for reading."); + _dosexterr(&de); + printf("Extended DOS error information:\n"); + printf("Extended error: %i\n",de.exterror); + printf("Class: %x\n",de.class); + printf("Action: %x\n",de.action); + printf("Error Locus: %x\n",de.locus); + } + return 0; +} --- /dev/null Thu Jan 1 00:00:00 1970 +++ tests/libc/dos/compat/d_strerr.c Sat Nov 25 13:27:38 2000 @@ -0,0 +1,21 @@ +#include +#include + +int main(void) +{ + FILE *fp; + struct _DOSERROR de; + + fp = fopen("EXAMPLE.DAT","r"); + if ( fp == NULL ) + { + puts("Unable to open file for reading."); + _dosexterr(&de); + printf("Extended DOS error information:\n"); + printf("Extended error: %i : %s\n",de.exterror,dostrerr(de.exterror)); + printf("Class: %x : %s\n",de.class,dostrcls(de.class)); + printf("Action: %x : %s\n",de.action,dostract(de.action)); + printf("Error Locus: %x : %s\n",de.locus,dostrloc(de.locus)); + } + return 0; +} --- /dev/null Thu Jan 1 00:00:00 1970 +++ tests/libc/dos/compat/makefile Sat Nov 25 13:26:54 2000 @@ -0,0 +1,6 @@ +TOP=../.. + +SRC += d_exterr.c +SRC += d_strerr.c + +include $(TOP)/../makefile.inc --- tests/libc/posix/fcntl/makefile.0 Sun Aug 27 03:25:44 1995 +++ tests/libc/posix/fcntl/makefile Sat Nov 25 13:17:34 2000 @@ -3,5 +3,6 @@ SRC += binpr.c SRC += bt.c SRC += trunc.c +SRC += tfcntl.c include $(TOP)/../makefile.inc --- /dev/null Thu Jan 1 00:00:00 1970 +++ tests/libc/posix/fcntl/tfcntl.c Sat Nov 25 13:18:52 2000 @@ -0,0 +1,88 @@ +#include +#include +#include +#include +#include +#include +#include +#include + +void prdoserr(void) { + struct _DOSERROR de; + _dosexterr(&de); + printf("errno: %i : %s\n", errno, strerror(errno)); + printf("DOS errno: %i : %s\n", _doserrno, dostrerr(_doserrno)); + printf("DOS extended error to errno: %i : %s\n", + __doserr_to_errno(de.exterror),strerror(__doserr_to_errno(de.exterror))); + printf("Extended DOS error information:\n"); + printf("Extended error: %i : %s\n",de.exterror,dostrerr(de.exterror)); + printf("Class: %02X : %s\n",de.class,dostrcls(de.class)); + printf("Action: %02X : %s\n",de.action,dostract(de.action)); + printf("Error Locus: %02X : %s\n",de.locus,dostrloc(de.locus)); +} + + +int main(void) { +#if defined(F_SETLK) && defined(F_SETLKW) + struct flock flock; + int retval, fd; + + fd = open("tfcntl.c", O_RDONLY); + flock.l_type = F_RDLCK; + flock.l_whence = SEEK_SET; + flock.l_start = flock.l_len = 0; + + errno = 0; + retval = fcntl(fd, F_SETLK, &flock); + printf("F_SETLK/F_RDLCK:retval=%d\n", retval); + if ((retval < 0) && (errno != 0)) prdoserr(); + + errno = 0; + retval = fcntl(fd, F_SETLK, &flock); + printf("F_SETLK/F_RDLCK:retval=%d\n", retval); + if ((retval < 0) && (errno != 0)) prdoserr(); + + errno = 0; + retval = fcntl(fd, F_GETLK, &flock); + printf("F_GETLK/F_RDLCK:retval=%d\n", retval); + if ((retval < 0) && (errno != 0)) prdoserr(); + + errno = 0; + flock.l_type = F_UNLCK; + retval = fcntl(fd, F_SETLK, &flock); + printf("F_SETLK/F_UNLCK:retval=%d\n", retval); + if ((retval < 0) && (errno != 0)) prdoserr(); + + errno = 0; + flock.l_type = F_UNLCK; + retval = fcntl(fd, F_SETLK, &flock); + printf("F_SETLK/F_UNLCK:retval=%d\n", retval); + if ((retval < 0) && (errno != 0)) prdoserr(); + + errno = 0; + flock.l_type = F_RDLCK; + retval = fcntl(fd, F_GETLK, &flock); + printf("F_GETLK/F_RDLCK:retval=%d\n", retval); + if ((retval < 0) && (errno != 0)) prdoserr(); + + errno = 0; + retval = fcntl(fd, F_GETFD); + printf("F_GETFD:retval=%04x\n", retval); + if ((retval < 0) && (errno != 0)) prdoserr(); + + errno = 0; + retval = fcntl(fd, F_SETFL, O_BINARY); + printf("F_SETFL:retval=%04x\n", retval); + if ((retval < 0) && (errno != 0)) prdoserr(); + + errno = 0; + retval = fcntl(fd, F_GETFL); + printf("F_GETFL:retval=%04x\n", retval); + if ((retval < 0) && (errno != 0)) prdoserr(); + + close(fd); + exit(0); +#else + exit(99); +#endif +} --- /dev/null Thu Jan 1 00:00:00 1970 +++ tests/libc/posix/sys/file/makefile Sun Nov 26 01:00:14 2000 @@ -0,0 +1,5 @@ +TOP=../../.. + +SRC += tflock.c + +include $(TOP)/../makefile.inc --- /dev/null Thu Jan 1 00:00:00 1970 +++ tests/libc/posix/sys/file/tflock.c Sun Nov 26 01:01:16 2000 @@ -0,0 +1,68 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include + +void prdoserr(void) { + struct _DOSERROR de; + _dosexterr(&de); + printf("errno: %i : %s\n", errno, strerror(errno)); + printf("DOS errno: %i : %s\n", _doserrno, dostrerr(_doserrno)); + printf("DOS extended error to errno: %i : %s\n", + __doserr_to_errno(de.exterror),strerror(__doserr_to_errno(de.exterror))); + printf("Extended DOS error information:\n"); + printf("Extended error: %i : %s\n",de.exterror,dostrerr(de.exterror)); + printf("Class: %02X : %s\n",de.class,dostrcls(de.class)); + printf("Action: %02X : %s\n",de.action,dostract(de.action)); + printf("Error Locus: %02X : %s\n",de.locus,dostrloc(de.locus)); +} + + +int main(void) { + int retval, fd; + + fd = open("tflock.c", O_RDONLY); + + errno = 0; + retval = flock(fd, LOCK_SH); + printf("LOCK_SH:retval=%d\n", retval); + if ((retval < 0) && (errno != 0)) prdoserr(); + + errno = 0; + retval = flock(fd, LOCK_SH); + printf("LOCK_SH:retval=%d\n", retval); + if ((retval < 0) && (errno != 0)) prdoserr(); + + errno = 0; + retval = flock(fd, LOCK_UN); + printf("LOCK_UN:retval=%d\n", retval); + if ((retval < 0) && (errno != 0)) prdoserr(); + + errno = 0; + retval = fcntl(fd, LOCK_UN); + printf("LOCK_UN:retval=%d\n", retval); + if ((retval < 0) && (errno != 0)) prdoserr(); + + errno = 0; + retval = flock(fd, LOCK_EX); + printf("LOCK_EX:retval=%d\n", retval); + if ((retval < 0) && (errno != 0)) prdoserr(); + + errno = 0; + retval = flock(fd, LOCK_EX); + printf("LOCK_EX:retval=%d\n", retval); + if ((retval < 0) && (errno != 0)) prdoserr(); + + errno = 0; + retval = flock(fd, LOCK_UN); + printf("LOCK_UN:retval=%d\n", retval); + if ((retval < 0) && (errno != 0)) prdoserr(); + + close(fd); + exit(0); +} --- tests/makefile.inc.0 Sun Sep 1 15:39:18 1996 +++ tests/makefile.inc Sun Nov 26 23:13:42 2000 @@ -31,7 +31,19 @@ EXES := $(addsuffix .exe, $(basename $(SRC))) ERRS := $(addsuffix .err, $(basename $(SRC))) -LINK = ld $(LDFLAGS) $^ -o $@ ${LIB}/libgcc.a -T ${TOP}/../../lib/djgpp.djl +ifeq ($(LIBGCCA),) +LIBGCCA := $(shell $(CROSS_GCC) $(GCC_OPT) -print-file-name=libgcc.a) +LIBGCCA := $(subst \,/,$(LIBGCCA)) +export LIBGCCA +endif + +ifeq ($(DJGPP_DJL),) +DJGPP_DJL := $(shell $(CROSS_GCC) $(GCC_OPT) -print-file-name=djgpp.djl) +DJGPP_DJL := $(subst \,/,$(DJGPP_DJL)) +export DJGPP_DJL +endif + +LINK = ld $(LDFLAGS) $^ -o $@ $(LIBGCCA) -T $(DJGPP_DJL) EXE = @${TOP}/../../bin/stubify.exe $@ .PRECIOUS: %.exe %.out %.err --=====================_24418177==_ Content-Type: text/plain; charset="us-ascii"; format=flowed --------------------------------------------------------- Peter J. Farley III (pjfarley AT dorsai DOT org OR pjfarley AT banet DOT net) --=====================_24418177==_--