Message-Id: <5.0.2.1.0.20001229070006.00a50b60@pop5.banet.net> X-Sender: usbanet DOT farley3 AT pop5 DOT banet DOT net X-Mailer: QUALCOMM Windows Eudora Version 5.0.2 Date: Fri, 29 Dec 2000 07:01:19 -0500 To: djgpp-workers AT delorie DOT com From: "Peter J. Farley III" Subject: fcntl locking changes #3: main fcntl changes Mime-Version: 1.0 Content-Type: multipart/mixed; boundary="=====================_12624979==_" Reply-To: djgpp-workers AT delorie DOT com --=====================_12624979==_ Content-Type: text/plain; charset="us-ascii"; format=flowed Here are the main fcntl changes. The new function dostrerr patch is required to run any of the test programs. --=====================_12624979==_ Content-Type: text/plain; charset="us-ascii" diff -ruN djgpp-cvs/include/fcntl.h djgpp/include/fcntl.h --- djgpp-cvs/include/fcntl.h Thu Aug 17 04:46:00 2000 +++ djgpp/include/fcntl.h Mon Dec 11 21:56:46 2000 @@ -21,6 +21,9 @@ #define F_SETFL 6 #define F_SETLK 7 #define F_SETLKW 8 +#define F_GETLK64 9 +#define F_SETLK64 10 +#define F_SETLKW64 11 #define F_UNLCK 0 #define F_RDLCK 1 @@ -51,6 +54,14 @@ short l_type; short l_whence; }; + +struct flock64 { + offset_t l_len; + pid_t l_pid; + offset_t l_start; + short l_type; + short l_whence; +}; extern int _fmode; /* O_TEXT or O_BINARY */ diff -ruN djgpp-cvs/include/io.h djgpp/include/io.h --- djgpp-cvs/include/io.h Sun Jun 28 18:42:16 1998 +++ djgpp/include/io.h Fri Dec 15 21:19:54 2000 @@ -21,15 +21,20 @@ int _creatnew(const char *_path, int _attrib, int _mode); ssize_t crlf2nl(char *_buffer, ssize_t _length); int _dos_lock(int _fd, long _offset, long _length); +int _dos_lk64(int _fd, long long _offset, long long _length); long filelength(int _handle); +long long lfilelength(int _handle); short _get_dev_info(int _arg); int lock(int _fd, long _offset, long _length); +int lock64(int _fd, long long _offset, long long _length); int _open(const char *_path, int _oflag); ssize_t _read(int _fd, void *_buf, size_t _nbyte); int setmode(int _fd, int _newmode); off_t tell(int _fd); int _dos_unlock(int _fd, long _offset, long _length); +int _dos_unlk64(int _fd, long long _offset, long long _length); int unlock(int _fd, long _offset, long _length); +int unlock64(int _fd, long long _offset, long long _length); ssize_t _write(int _fd, const void *_buf, size_t _nbyte); int _chmod(const char *_path, int _func, ...); void _flush_disk_cache(void); diff -ruN djgpp-cvs/include/libc/getdinfo.h djgpp/include/libc/getdinfo.h --- djgpp-cvs/include/libc/getdinfo.h Thu Jan 1 00:00:00 1970 +++ djgpp/include/libc/getdinfo.h Mon Dec 11 21:56:46 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 diff -ruN djgpp-cvs/include/libc/stubs.h djgpp/include/libc/stubs.h --- djgpp-cvs/include/libc/stubs.h Fri Dec 29 04:48:06 2000 +++ djgpp/include/libc/stubs.h Fri Dec 29 04:35:02 2000 @@ -1,3 +1,4 @@ +/* Copyright (C) 2000 DJ Delorie, see COPYING.DJ for details */ /* Copyright (C) 1997 DJ Delorie, see COPYING.DJ for details */ /* Copyright (C) 1995 DJ Delorie, see COPYING.DJ for details */ #ifndef __dj_include_libc_stubs_h__ @@ -45,6 +46,7 @@ #define getdtablesize __getdtablesize #define getitimer __getitimer #define gettimeofday __gettimeofday +#define lfilelength __lfilelength #define llseek __llseek #define modfl __modfl #define movedata __movedata diff -ruN djgpp-cvs/tests/libc/posix/fcntl/fcntl3gb.c djgpp/tests/libc/posix/fcntl/fcntl3gb.c --- djgpp-cvs/tests/libc/posix/fcntl/fcntl3gb.c Thu Jan 1 00:00:00 1970 +++ djgpp/tests/libc/posix/fcntl/fcntl3gb.c Wed Dec 27 04:49:02 2000 @@ -0,0 +1,223 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include + +void prdoserr(int fd) { + struct DOSERROR de; + struct DOSERROR_STR se; + int errsave; + + printf("fd: %i\n", fd); + printf("errno: %i : %s\n", errno, strerror(errno)); + dosexterr(&de); + errsave = de.exterror; + de.exterror = _doserrno; + dostrerr(&de, &se); + printf("DOS errno: %i : %s\n", _doserrno, se.exterror_str); + de.exterror = errsave; + dostrerr(&de, &se); + 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,se.exterror_str); + printf("Class: %02X : %s\n",de.class,se.class_str); + printf("Action: %02X : %s\n",de.action,se.action_str); + printf("Error Locus: %02X : %s\n",de.locus,se.locus_str); +} + + +int main(void) { +#if defined(F_SETLK) && defined(F_SETLKW) + struct flock fl; + struct flock64 fl64; + int retval, fd; + + fd = open("fcntl3gb.dat", O_RDONLY); + fl.l_type = F_RDLCK; + fl.l_whence = SEEK_SET; + fl.l_start = 32767LL; + fl.l_len = 0; + + fl64.l_type = F_RDLCK; + fl64.l_whence = SEEK_SET; + fl64.l_start = 32767LL + INT_MAX; + fl64.l_len = 0L; + + errno = 0; + retval = fcntl(fd, F_SETLK, &fl); + printf("F_SETLK/F_RDLCK:retval=%d,fl.l_start=%d\n", retval, fl.l_start); + if ((retval < 0) && (errno != 0)) prdoserr(fd); + + errno = 0; + retval = fcntl(fd, F_SETLK, &fl); + printf("F_SETLK/F_RDLCK:retval=%d,fl.l_start=%d\n", retval, fl.l_start); + if ((retval < 0) && (errno != 0)) prdoserr(fd); + + errno = 0; + retval = fcntl(fd, F_GETLK, &fl); + printf("F_GETLK/F_RDLCK:retval=%d,fl.l_start=%d\n", retval, fl.l_start); + if ((retval < 0) && (errno != 0)) prdoserr(fd); + + errno = 0; + fl.l_type = F_UNLCK; + retval = fcntl(fd, F_SETLK, &fl); + printf("F_SETLK/F_UNLCK:retval=%d,fl.l_start=%d\n", retval, fl.l_start); + if ((retval < 0) && (errno != 0)) prdoserr(fd); + + errno = 0; + fl.l_type = F_UNLCK; + retval = fcntl(fd, F_SETLK, &fl); + printf("F_SETLK/F_UNLCK:retval=%d,fl.l_start=%d\n", retval, fl.l_start); + if ((retval < 0) && (errno != 0)) prdoserr(fd); + + errno = 0; + fl.l_type = F_RDLCK; + retval = fcntl(fd, F_GETLK, &fl); + printf("F_GETLK/F_RDLCK:retval=%d,fl.l_start=%d\n", retval, fl.l_start); + if ((retval < 0) && (errno != 0)) prdoserr(fd); + + /* F_SETLKW tests */ + + errno = 0; + fl.l_type = F_RDLCK; + retval = fcntl(fd, F_SETLKW, &fl); + printf("F_SETLKW/F_RDLCK:retval=%d,fl.l_start=%d\n", retval, fl.l_start); + if ((retval < 0) && (errno != 0)) prdoserr(fd); + + /* This call will lock the program in an endless loop, + since it already has the lock. + + FIXME -- Need to add SIGINT interrupt handler and + console output (syserr?) telling user to + press CNTL-Break to continue the test. + + Commented out for now, replaced with message about bypass. + + errno = 0; + retval = fcntl(fd, F_SETLKW, &fl); + printf("F_SETLKW/F_RDLCK:retval=%d,fl.l_start=%d\n", retval, fl.l_start); + if ((retval < 0) && (errno != 0)) prdoserr(fd); + + */ + + printf("F_SETLKW/F_RDLCK:Bypassed to avoid lockup in endless loop.\n"); + + errno = 0; + retval = fcntl(fd, F_GETLK, &fl); + printf("F_GETLK/F_RDLCK:retval=%d,fl.l_start=%d\n", retval, fl.l_start); + if ((retval < 0) && (errno != 0)) prdoserr(fd); + + errno = 0; + fl.l_type = F_UNLCK; + retval = fcntl(fd, F_SETLK, &fl); + printf("F_SETLK/F_UNLCK:retval=%d,fl.l_start=%d\n", retval, fl.l_start); + if ((retval < 0) && (errno != 0)) prdoserr(fd); + + errno = 0; + fl.l_type = F_RDLCK; + retval = fcntl(fd, F_GETLK, &fl); + printf("F_GETLK/F_RDLCK:retval=%d,fl.l_start=%d\n", retval, fl.l_start); + if ((retval < 0) && (errno != 0)) prdoserr(fd); + + /* FAT32 tests */ + + errno = 0; + fl64.l_type = F_RDLCK; + retval = fcntl(fd, F_SETLK64, &fl64); + printf("F_SETLK64/F_RDLCK:retval=%d,fl64.l_start=%lld\n", retval, fl64.l_start); + if ((retval < 0) && (errno != 0)) prdoserr(fd); + + errno = 0; + retval = fcntl(fd, F_SETLK64, &fl64); + printf("F_SETLK64/F_RDLCK:retval=%d,fl64.l_start=%lld\n", retval, fl64.l_start); + if ((retval < 0) && (errno != 0)) prdoserr(fd); + + errno = 0; + retval = fcntl(fd, F_GETLK64, &fl64); + printf("F_GETLK64/F_RDLCK:retval=%d,fl64.l_start=%lld\n", retval, fl64.l_start); + if ((retval < 0) && (errno != 0)) prdoserr(fd); + + errno = 0; + fl64.l_type = F_UNLCK; + retval = fcntl(fd, F_SETLK64, &fl64); + printf("F_SETLK64/F_UNLCK:retval=%d,fl64.l_start=%lld\n", retval, fl64.l_start); + if ((retval < 0) && (errno != 0)) prdoserr(fd); + + errno = 0; + fl64.l_type = F_RDLCK; + retval = fcntl(fd, F_GETLK64, &fl64); + printf("F_GETLK64/F_RDLCK:retval=%d,fl64.l_start=%lld\n", retval, fl64.l_start); + if ((retval < 0) && (errno != 0)) prdoserr(fd); + + /* F_SETLKW64 tests */ + + errno = 0; + fl64.l_type = F_RDLCK; + retval = fcntl(fd, F_SETLKW64, &fl64); + printf("F_SETLKW64/F_RDLCK:retval=%d,fl64.l_start=%lld\n", retval, fl64.l_start); + if ((retval < 0) && (errno != 0)) prdoserr(fd); + + /* This call will lock the program in an endless loop, + since it already has the lock. + + FIXME -- Need to add SIGINT interrupt handler and + console output (syserr?) telling user to + press CNTL-Break to continue the test. + + Commented out for now, replaced with message about bypass. + + errno = 0; + retval = fcntl(fd, F_SETLKW64, &fl64); + printf("F_SETLKW64/F_RDLCK:retval=%d,fl64.l_start=%lld\n", retval, fl64.l_start); + if ((retval < 0) && (errno != 0)) prdoserr(fd); + + */ + + printf("F_SETLKW64/F_RDLCK:Bypassed to avoid lockup in endless loop.\n"); + + errno = 0; + retval = fcntl(fd, F_GETLK64, &fl64); + printf("F_GETLK64/F_RDLCK:retval=%d,fl64.l_start=%lld\n", retval, fl64.l_start); + if ((retval < 0) && (errno != 0)) prdoserr(fd); + + errno = 0; + fl64.l_type = F_UNLCK; + retval = fcntl(fd, F_SETLK64, &fl64); + printf("F_SETLK64/F_UNLCK:retval=%d,fl64.l_start=%lld\n", retval, fl64.l_start); + if ((retval < 0) && (errno != 0)) prdoserr(fd); + + errno = 0; + fl64.l_type = F_RDLCK; + retval = fcntl(fd, F_GETLK64, &fl64); + printf("F_GETLK64/F_RDLCK:retval=%d,fl64.l_start=%lld\n", retval, fl64.l_start); + if ((retval < 0) && (errno != 0)) prdoserr(fd); + + /* Other function tests (non-lock-related) */ + + errno = 0; + retval = fcntl(fd, F_GETFD); + printf("F_GETFD:retval=%04x\n", retval); + if ((retval < 0) && (errno != 0)) prdoserr(fd); + + errno = 0; + retval = fcntl(fd, F_SETFL, O_BINARY); + printf("F_SETFL:retval=%04x\n", retval); + if ((retval < 0) && (errno != 0)) prdoserr(fd); + + errno = 0; + retval = fcntl(fd, F_GETFL); + printf("F_GETFL:retval=%04x\n", retval); + if ((retval < 0) && (errno != 0)) prdoserr(fd); + + close(fd); + exit(0); +#else + exit(99); +#endif +} diff -ruN djgpp-cvs/tests/libc/posix/fcntl/fcntl3gb.ok djgpp/tests/libc/posix/fcntl/fcntl3gb.ok --- djgpp-cvs/tests/libc/posix/fcntl/fcntl3gb.ok Thu Jan 1 00:00:00 1970 +++ djgpp/tests/libc/posix/fcntl/fcntl3gb.ok Fri Dec 29 03:47:50 2000 @@ -0,0 +1,87 @@ +F_SETLK/F_RDLCK:retval=0,fl.l_start=32767 +F_SETLK/F_RDLCK:retval=-1,fl.l_start=32767 +fd: 5 +errno: 4 : Permission denied (EACCES) +DOS errno: 33 : Lock violation +DOS extended error to errno: 4 : Permission denied (EACCES) +Extended DOS error information: +Extended error: 33 : Lock violation +Class: 0A : Media error +Action: 02 : Prompt user to reenter input +Error Locus: 02 : Network related +F_GETLK/F_RDLCK:retval=-1,fl.l_start=32767 +fd: 5 +errno: 4 : Permission denied (EACCES) +DOS errno: 33 : Lock violation +DOS extended error to errno: 4 : Permission denied (EACCES) +Extended DOS error information: +Extended error: 33 : Lock violation +Class: 0A : Media error +Action: 02 : Prompt user to reenter input +Error Locus: 02 : Network related +F_SETLK/F_UNLCK:retval=0,fl.l_start=32767 +F_SETLK/F_UNLCK:retval=-1,fl.l_start=32767 +fd: 5 +errno: 4 : Permission denied (EACCES) +DOS errno: 33 : Lock violation +DOS extended error to errno: 4 : Permission denied (EACCES) +Extended DOS error information: +Extended error: 33 : Lock violation +Class: 0A : Media error +Action: 02 : Prompt user to reenter input +Error Locus: 02 : Network related +F_GETLK/F_RDLCK:retval=0,fl.l_start=32767 +F_SETLKW/F_RDLCK:retval=0,fl.l_start=32767 +F_SETLKW/F_RDLCK:Bypassed to avoid lockup in endless loop. +F_GETLK/F_RDLCK:retval=-1,fl.l_start=32767 +fd: 5 +errno: 4 : Permission denied (EACCES) +DOS errno: 33 : Lock violation +DOS extended error to errno: 4 : Permission denied (EACCES) +Extended DOS error information: +Extended error: 33 : Lock violation +Class: 0A : Media error +Action: 02 : Prompt user to reenter input +Error Locus: 02 : Network related +F_SETLK/F_UNLCK:retval=0,fl.l_start=32767 +F_GETLK/F_RDLCK:retval=0,fl.l_start=32767 +F_SETLK64/F_RDLCK:retval=0,fl64.l_start=2147516414 +F_SETLK64/F_RDLCK:retval=-1,fl64.l_start=2147516414 +fd: 5 +errno: 4 : Permission denied (EACCES) +DOS errno: 33 : Lock violation +DOS extended error to errno: 4 : Permission denied (EACCES) +Extended DOS error information: +Extended error: 33 : Lock violation +Class: 0A : Media error +Action: 02 : Prompt user to reenter input +Error Locus: 02 : Network related +F_GETLK64/F_RDLCK:retval=-1,fl64.l_start=2147516414 +fd: 5 +errno: 4 : Permission denied (EACCES) +DOS errno: 33 : Lock violation +DOS extended error to errno: 4 : Permission denied (EACCES) +Extended DOS error information: +Extended error: 33 : Lock violation +Class: 0A : Media error +Action: 02 : Prompt user to reenter input +Error Locus: 02 : Network related +F_SETLK64/F_UNLCK:retval=0,fl64.l_start=2147516414 +F_GETLK64/F_RDLCK:retval=0,fl64.l_start=2147516414 +F_SETLKW64/F_RDLCK:retval=0,fl64.l_start=2147516414 +F_SETLKW64/F_RDLCK:Bypassed to avoid lockup in endless loop. +F_GETLK64/F_RDLCK:retval=-1,fl64.l_start=2147516414 +fd: 5 +errno: 4 : Permission denied (EACCES) +DOS errno: 33 : Lock violation +DOS extended error to errno: 4 : Permission denied (EACCES) +Extended DOS error information: +Extended error: 33 : Lock violation +Class: 0A : Media error +Action: 02 : Prompt user to reenter input +Error Locus: 02 : Network related +F_SETLK64/F_UNLCK:retval=0,fl64.l_start=2147516414 +F_GETLK64/F_RDLCK:retval=0,fl64.l_start=2147516414 +F_GETFD:retval=0000 +F_SETFL:retval=ffffffff +F_GETFL:retval=0000 diff -ruN djgpp-cvs/tests/libc/posix/fcntl/makef3gb.c djgpp/tests/libc/posix/fcntl/makef3gb.c --- djgpp-cvs/tests/libc/posix/fcntl/makef3gb.c Thu Jan 1 00:00:00 1970 +++ djgpp/tests/libc/posix/fcntl/makef3gb.c Fri Dec 29 03:42:32 2000 @@ -0,0 +1,62 @@ +#include +#include +#include +#include +#include +#include +#include +#include + +#define BIGBUFSIZE 500*1024 + +void prdoserr(int fd) { + struct DOSERROR de; + struct DOSERROR_STR se; + int errsave; + + printf("fd: %i\n", fd); + printf("errno: %i : %s\n", errno, strerror(errno)); + dosexterr(&de); + errsave = de.exterror; + de.exterror = _doserrno; + dostrerr(&de, &se); + printf("DOS errno: %i : %s\n", _doserrno, se.exterror_str); + de.exterror = errsave; + dostrerr(&de, &se); + 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,se.exterror_str); + printf("Class: %02X : %s\n",de.class,se.class_str); + printf("Action: %02X : %s\n",de.action,se.action_str); + printf("Error Locus: %02X : %s\n",de.locus,se.locus_str); +} + + +int main(void) { + int retval, i; + long long int flen; + FILE *f3GB; + char bigbuf[BIGBUFSIZE]; + + f3GB = fopen("fcntl3GB.dat", "w"); + + for (i = 0; i <= BIGBUFSIZE; i++) bigbuf[i] = (char) i; + + for (flen = 0; flen < (long long)(3LL * (INT_MAX/2LL)); flen += BIGBUFSIZE) + { + retval = fwrite(bigbuf, sizeof(char), BIGBUFSIZE, f3GB); + if (retval != BIGBUFSIZE) { + printf("\nError writing 3GB file, fwrite returned %d!\n", retval); + prdoserr(fileno(f3GB)); + fclose(f3GB); + exit(1); + } + printf("Writing 3GB file, so far wrote %lld\r", flen); + } + + printf("\nWrote 3GB file OK!\n"); + fclose(f3GB); + + return 0; +} diff -ruN djgpp-cvs/tests/libc/posix/fcntl/makefile djgpp/tests/libc/posix/fcntl/makefile --- djgpp-cvs/tests/libc/posix/fcntl/makefile Thu Aug 17 04:46:22 2000 +++ djgpp/tests/libc/posix/fcntl/makefile Wed Dec 27 04:29:38 2000 @@ -4,5 +4,9 @@ SRC += bt.c SRC += open.c SRC += trunc.c +SRC += tfcntl.c +SRC += tfcntl2.c +SRC += fcntl3gb.c +SRC += makef3gb.c include $(TOP)/../makefile.inc diff -ruN djgpp-cvs/tests/libc/posix/fcntl/tfcntl.c djgpp/tests/libc/posix/fcntl/tfcntl.c --- djgpp-cvs/tests/libc/posix/fcntl/tfcntl.c Thu Jan 1 00:00:00 1970 +++ djgpp/tests/libc/posix/fcntl/tfcntl.c Wed Dec 27 04:42:48 2000 @@ -0,0 +1,220 @@ +#include +#include +#include +#include +#include +#include +#include +#include + +void prdoserr(int fd) { + struct DOSERROR de; + struct DOSERROR_STR se; + int errsave; + + printf("fd: %i\n", fd); + printf("errno: %i : %s\n", errno, strerror(errno)); + dosexterr(&de); + errsave = de.exterror; + de.exterror = _doserrno; + dostrerr(&de, &se); + printf("DOS errno: %i : %s\n", _doserrno, se.exterror_str); + de.exterror = errsave; + dostrerr(&de, &se); + 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,se.exterror_str); + printf("Class: %02X : %s\n",de.class,se.class_str); + printf("Action: %02X : %s\n",de.action,se.action_str); + printf("Error Locus: %02X : %s\n",de.locus,se.locus_str); +} + + +int main(void) { +#if defined(F_SETLK) && defined(F_SETLKW) + struct flock fl; + struct flock64 fl64; + int retval, fd; + + fd = open("tfcntl.c", O_RDONLY); + fl.l_type = F_RDLCK; + fl.l_whence = SEEK_SET; + fl.l_start = fl.l_len = 0; + + fl64.l_type = F_RDLCK; + fl64.l_whence = SEEK_SET; + fl64.l_start = fl64.l_len = 0L; + + errno = 0; + retval = fcntl(fd, F_SETLK, &fl); + printf("F_SETLK/F_RDLCK:retval=%d\n", retval); + if ((retval < 0) && (errno != 0)) prdoserr(fd); + + errno = 0; + retval = fcntl(fd, F_SETLK, &fl); + printf("F_SETLK/F_RDLCK:retval=%d\n", retval); + if ((retval < 0) && (errno != 0)) prdoserr(fd); + + errno = 0; + retval = fcntl(fd, F_GETLK, &fl); + printf("F_GETLK/F_RDLCK:retval=%d\n", retval); + if ((retval < 0) && (errno != 0)) prdoserr(fd); + + errno = 0; + fl.l_type = F_UNLCK; + retval = fcntl(fd, F_SETLK, &fl); + printf("F_SETLK/F_UNLCK:retval=%d\n", retval); + if ((retval < 0) && (errno != 0)) prdoserr(fd); + + errno = 0; + fl.l_type = F_UNLCK; + retval = fcntl(fd, F_SETLK, &fl); + printf("F_SETLK/F_UNLCK:retval=%d\n", retval); + if ((retval < 0) && (errno != 0)) prdoserr(fd); + + errno = 0; + fl.l_type = F_RDLCK; + retval = fcntl(fd, F_GETLK, &fl); + printf("F_GETLK/F_RDLCK:retval=%d\n", retval); + if ((retval < 0) && (errno != 0)) prdoserr(fd); + + /* F_SETLKW tests */ + + errno = 0; + fl.l_type = F_RDLCK; + retval = fcntl(fd, F_SETLKW, &fl); + printf("F_SETLKW/F_RDLCK:retval=%d\n", retval); + if ((retval < 0) && (errno != 0)) prdoserr(fd); + + /* This call will lock the program in an endless loop, + since it already has the lock. + + FIXME -- Need to add SIGINT interrupt handler and + console output (syserr?) telling user to + press CNTL-Break to continue the test. + + Commented out for now, replaced with message about bypass. + + errno = 0; + retval = fcntl(fd, F_SETLKW, &fl); + printf("F_SETLKW/F_RDLCK:retval=%d\n", retval); + if ((retval < 0) && (errno != 0)) prdoserr(fd); + + */ + + printf("F_SETLKW/F_RDLCK:Bypassed to avoid lockup in endless loop.\n"); + + errno = 0; + retval = fcntl(fd, F_GETLK, &fl); + printf("F_GETLK/F_RDLCK:retval=%d\n", retval); + if ((retval < 0) && (errno != 0)) prdoserr(fd); + + errno = 0; + fl.l_type = F_UNLCK; + retval = fcntl(fd, F_SETLK, &fl); + printf("F_SETLK/F_UNLCK:retval=%d\n", retval); + if ((retval < 0) && (errno != 0)) prdoserr(fd); + + errno = 0; + fl.l_type = F_RDLCK; + retval = fcntl(fd, F_GETLK, &fl); + printf("F_GETLK/F_RDLCK:retval=%d\n", retval); + if ((retval < 0) && (errno != 0)) prdoserr(fd); + + /* FAT32 tests */ + + errno = 0; + fl64.l_type = F_RDLCK; + retval = fcntl(fd, F_SETLK64, &fl64); + printf("F_SETLK64/F_RDLCK:retval=%d\n", retval); + if ((retval < 0) && (errno != 0)) prdoserr(fd); + + errno = 0; + retval = fcntl(fd, F_SETLK64, &fl64); + printf("F_SETLK64/F_RDLCK:retval=%d\n", retval); + if ((retval < 0) && (errno != 0)) prdoserr(fd); + + errno = 0; + retval = fcntl(fd, F_GETLK64, &fl64); + printf("F_GETLK64/F_RDLCK:retval=%d\n", retval); + if ((retval < 0) && (errno != 0)) prdoserr(fd); + + errno = 0; + fl64.l_type = F_UNLCK; + retval = fcntl(fd, F_SETLK64, &fl64); + printf("F_SETLK64/F_UNLCK:retval=%d\n", retval); + if ((retval < 0) && (errno != 0)) prdoserr(fd); + + errno = 0; + fl64.l_type = F_RDLCK; + retval = fcntl(fd, F_GETLK64, &fl64); + printf("F_GETLK64/F_RDLCK:retval=%d\n", retval); + if ((retval < 0) && (errno != 0)) prdoserr(fd); + + /* F_SETLKW64 tests */ + + errno = 0; + fl64.l_type = F_RDLCK; + retval = fcntl(fd, F_SETLKW64, &fl64); + printf("F_SETLKW64/F_RDLCK:retval=%d\n", retval); + if ((retval < 0) && (errno != 0)) prdoserr(fd); + + /* This call will lock the program in an endless loop, + since it already has the lock. + + FIXME -- Need to add SIGINT interrupt handler and + console output (syserr?) telling user to + press CNTL-Break to continue the test. + + Commented out for now, replaced with message about bypass. + + errno = 0; + retval = fcntl(fd, F_SETLKW64, &fl64); + printf("F_SETLKW64/F_RDLCK:retval=%d\n", retval); + if ((retval < 0) && (errno != 0)) prdoserr(fd); + + */ + + printf("F_SETLKW64/F_RDLCK:Bypassed to avoid lockup in endless loop.\n"); + + errno = 0; + retval = fcntl(fd, F_GETLK64, &fl64); + printf("F_GETLK64/F_RDLCK:retval=%d\n", retval); + if ((retval < 0) && (errno != 0)) prdoserr(fd); + + errno = 0; + fl64.l_type = F_UNLCK; + retval = fcntl(fd, F_SETLK64, &fl64); + printf("F_SETLK64/F_UNLCK:retval=%d\n", retval); + if ((retval < 0) && (errno != 0)) prdoserr(fd); + + errno = 0; + fl64.l_type = F_RDLCK; + retval = fcntl(fd, F_GETLK64, &fl64); + printf("F_GETLK64/F_RDLCK:retval=%d\n", retval); + if ((retval < 0) && (errno != 0)) prdoserr(fd); + + /* Other function tests (non-lock-related) */ + + errno = 0; + retval = fcntl(fd, F_GETFD); + printf("F_GETFD:retval=%04x\n", retval); + if ((retval < 0) && (errno != 0)) prdoserr(fd); + + errno = 0; + retval = fcntl(fd, F_SETFL, O_BINARY); + printf("F_SETFL:retval=%04x\n", retval); + if ((retval < 0) && (errno != 0)) prdoserr(fd); + + errno = 0; + retval = fcntl(fd, F_GETFL); + printf("F_GETFL:retval=%04x\n", retval); + if ((retval < 0) && (errno != 0)) prdoserr(fd); + + close(fd); + exit(0); +#else + exit(99); +#endif +} diff -ruN djgpp-cvs/tests/libc/posix/fcntl/tfcntl.ok djgpp/tests/libc/posix/fcntl/tfcntl.ok --- djgpp-cvs/tests/libc/posix/fcntl/tfcntl.ok Thu Jan 1 00:00:00 1970 +++ djgpp/tests/libc/posix/fcntl/tfcntl.ok Fri Dec 29 03:37:32 2000 @@ -0,0 +1,87 @@ +F_SETLK/F_RDLCK:retval=0 +F_SETLK/F_RDLCK:retval=-1 +fd: 5 +errno: 4 : Permission denied (EACCES) +DOS errno: 33 : Lock violation +DOS extended error to errno: 4 : Permission denied (EACCES) +Extended DOS error information: +Extended error: 33 : Lock violation +Class: 0A : Media error +Action: 02 : Prompt user to reenter input +Error Locus: 02 : Network related +F_GETLK/F_RDLCK:retval=-1 +fd: 5 +errno: 4 : Permission denied (EACCES) +DOS errno: 33 : Lock violation +DOS extended error to errno: 4 : Permission denied (EACCES) +Extended DOS error information: +Extended error: 33 : Lock violation +Class: 0A : Media error +Action: 02 : Prompt user to reenter input +Error Locus: 02 : Network related +F_SETLK/F_UNLCK:retval=0 +F_SETLK/F_UNLCK:retval=-1 +fd: 5 +errno: 4 : Permission denied (EACCES) +DOS errno: 33 : Lock violation +DOS extended error to errno: 4 : Permission denied (EACCES) +Extended DOS error information: +Extended error: 33 : Lock violation +Class: 0A : Media error +Action: 02 : Prompt user to reenter input +Error Locus: 02 : Network related +F_GETLK/F_RDLCK:retval=0 +F_SETLKW/F_RDLCK:retval=0 +F_SETLKW/F_RDLCK:Bypassed to avoid lockup in endless loop. +F_GETLK/F_RDLCK:retval=-1 +fd: 5 +errno: 4 : Permission denied (EACCES) +DOS errno: 33 : Lock violation +DOS extended error to errno: 4 : Permission denied (EACCES) +Extended DOS error information: +Extended error: 33 : Lock violation +Class: 0A : Media error +Action: 02 : Prompt user to reenter input +Error Locus: 02 : Network related +F_SETLK/F_UNLCK:retval=0 +F_GETLK/F_RDLCK:retval=0 +F_SETLK64/F_RDLCK:retval=0 +F_SETLK64/F_RDLCK:retval=-1 +fd: 5 +errno: 4 : Permission denied (EACCES) +DOS errno: 33 : Lock violation +DOS extended error to errno: 4 : Permission denied (EACCES) +Extended DOS error information: +Extended error: 33 : Lock violation +Class: 0A : Media error +Action: 02 : Prompt user to reenter input +Error Locus: 02 : Network related +F_GETLK64/F_RDLCK:retval=-1 +fd: 5 +errno: 4 : Permission denied (EACCES) +DOS errno: 33 : Lock violation +DOS extended error to errno: 4 : Permission denied (EACCES) +Extended DOS error information: +Extended error: 33 : Lock violation +Class: 0A : Media error +Action: 02 : Prompt user to reenter input +Error Locus: 02 : Network related +F_SETLK64/F_UNLCK:retval=0 +F_GETLK64/F_RDLCK:retval=0 +F_SETLKW64/F_RDLCK:retval=0 +F_SETLKW64/F_RDLCK:Bypassed to avoid lockup in endless loop. +F_GETLK64/F_RDLCK:retval=-1 +fd: 5 +errno: 4 : Permission denied (EACCES) +DOS errno: 33 : Lock violation +DOS extended error to errno: 4 : Permission denied (EACCES) +Extended DOS error information: +Extended error: 33 : Lock violation +Class: 0A : Media error +Action: 02 : Prompt user to reenter input +Error Locus: 02 : Network related +F_SETLK64/F_UNLCK:retval=0 +F_GETLK64/F_RDLCK:retval=0 +F_GETFD:retval=0000 +F_SETFL:retval=ffffffff +F_GETFL:retval=0000 diff -ruN djgpp-cvs/tests/libc/posix/fcntl/tfcntl2.c djgpp/tests/libc/posix/fcntl/tfcntl2.c --- djgpp-cvs/tests/libc/posix/fcntl/tfcntl2.c Thu Jan 1 00:00:00 1970 +++ djgpp/tests/libc/posix/fcntl/tfcntl2.c Wed Dec 27 04:42:52 2000 @@ -0,0 +1,173 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include + +void prdoserr(int fd) { + struct DOSERROR de; + struct DOSERROR_STR se; + int errsave; + + printf("fd: %i\n", fd); + printf("errno: %i : %s\n", errno, strerror(errno)); + dosexterr(&de); + errsave = de.exterror; + de.exterror = _doserrno; + dostrerr(&de, &se); + printf("DOS errno: %i : %s\n", _doserrno, se.exterror_str); + de.exterror = errsave; + dostrerr(&de, &se); + 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,se.exterror_str); + printf("Class: %02X : %s\n",de.class,se.class_str); + printf("Action: %02X : %s\n",de.action,se.action_str); + printf("Error Locus: %02X : %s\n",de.locus,se.locus_str); +} + + +void do_fcntl(long long int this_pos) { + struct flock fl; + struct flock64 fl64; + int retval, fd; + long int flen; + long long int flen64; + off_t fpos; + offset_t fpos64; + + fd = open("tfcntl2.c", O_RDONLY); + + flen = filelength(fd); + flen64 = lfilelength(fd); + + fpos = (off_t) this_pos; + fpos64 = (offset_t) this_pos; + + fl.l_start = fpos; + fl.l_len = 0; + fl.l_whence = SEEK_SET; + + fl64.l_start = fpos64; + fl64.l_len = 0L; + fl64.l_whence = SEEK_SET; + + /* FAT16 tests */ + + fpos64 = llseek(fd, 0L, SEEK_SET); + + errno = 0; + fl.l_type = F_RDLCK; + retval = fcntl(fd, F_SETLK, &fl); + printf("F_SETLK/F_RDLCK/BOF:retval=%d,fl.l_start=%d\n", retval, fl.l_start); + if ((retval < 0) && (errno != 0)) prdoserr(fd); + + errno = 0; + fl.l_type = F_UNLCK; + retval = fcntl(fd, F_SETLK, &fl); + printf("F_SETLK/F_UNLCK/BOF:retval=%d,fl.l_start=%d\n", retval, fl.l_start); + if ((retval < 0) && (errno != 0)) prdoserr(fd); + + fpos64 = llseek(fd, 0L, SEEK_END); + + errno = 0; + fl.l_type = F_RDLCK; + retval = fcntl(fd, F_SETLK, &fl); + printf("F_SETLK/F_RDLCK/EOF:retval=%d,fl.l_start=%d\n", retval, fl.l_start); + if ((retval < 0) && (errno != 0)) prdoserr(fd); + + errno = 0; + fl.l_type = F_UNLCK; + retval = fcntl(fd, F_SETLK, &fl); + printf("F_SETLK/F_UNLCK/EOF:retval=%d,fl.l_start=%d\n", retval, fl.l_start); + if ((retval < 0) && (errno != 0)) prdoserr(fd); + + fpos64 = llseek(fd, flen * 2L, SEEK_SET); + + errno = 0; + fl.l_type = F_RDLCK; + retval = fcntl(fd, F_SETLK, &fl); + printf("F_SETLK/F_RDLCK/2*EOF:retval=%d,fl.l_start=%d\n", retval, fl.l_start); + if ((retval < 0) && (errno != 0)) prdoserr(fd); + + errno = 0; + fl.l_type = F_UNLCK; + retval = fcntl(fd, F_SETLK, &fl); + printf("F_SETLK/F_UNLCK/2*EOF:retval=%d,fl.l_start=%d\n", retval, fl.l_start); + if ((retval < 0) && (errno != 0)) prdoserr(fd); + + /* FAT32 tests */ + + fpos64 = llseek(fd, 0L, SEEK_SET); + + errno = 0; + fl64.l_type = F_RDLCK; + retval = fcntl(fd, F_SETLK64, &fl64); + printf("F_SETLK64/F_RDLCK/BOF:retval=%d,fl64.l_start=%ld\n", retval, (long)fl64.l_start); + if ((retval < 0) && (errno != 0)) prdoserr(fd); + + errno = 0; + fl64.l_type = F_UNLCK; + retval = fcntl(fd, F_SETLK64, &fl64); + printf("F_SETLK64/F_UNLCK/BOF:retval=%d,fl64.l_start=%ld\n", retval, (long)fl64.l_start); + if ((retval < 0) && (errno != 0)) prdoserr(fd); + + fpos64 = llseek(fd, 0L, SEEK_END); + + errno = 0; + fl64.l_type = F_RDLCK; + retval = fcntl(fd, F_SETLK64, &fl64); + printf("F_SETLK64/F_RDLCK/EOF:retval=%d,fl64.l_start=%ld\n", retval, (long)fl64.l_start); + if ((retval < 0) && (errno != 0)) prdoserr(fd); + + errno = 0; + fl64.l_type = F_UNLCK; + retval = fcntl(fd, F_SETLK64, &fl64); + printf("F_SETLK64/F_UNLCK/EOF:retval=%d,fl64.l_start=%ld\n", retval, (long)fl64.l_start); + if ((retval < 0) && (errno != 0)) prdoserr(fd); + + fpos64 = llseek(fd, flen64 * 2L, SEEK_SET); + + errno = 0; + fl64.l_type = F_RDLCK; + retval = fcntl(fd, F_SETLK64, &fl64); + printf("F_SETLK64/F_RDLCK/2*EOF:retval=%d,fl64.l_start=%ld\n", retval, (long)fl64.l_start); + if ((retval < 0) && (errno != 0)) prdoserr(fd); + + errno = 0; + fl64.l_type = F_UNLCK; + retval = fcntl(fd, F_SETLK64, &fl64); + printf("F_SETLK64/F_UNLCK/2*EOF:retval=%d,fl64.l_start=%ld\n", retval, (long)fl64.l_start); + if ((retval < 0) && (errno != 0)) prdoserr(fd); + + close(fd); +} + + +int main(void) { +#if defined(F_SETLK) && defined(F_SETLKW) + int fd; + long long int flen64; + + fd = open("tfcntl2.c", O_RDONLY); + + flen64 = lfilelength(fd); + + close(fd); + + do_fcntl(0LL); + do_fcntl(flen64 / 2LL); + do_fcntl(flen64); + do_fcntl(flen64 * 2LL); + + return 0; + +#else + exit(99); +#endif +} diff -ruN djgpp-cvs/tests/libc/posix/fcntl/tfcntl2.ok djgpp/tests/libc/posix/fcntl/tfcntl2.ok --- djgpp-cvs/tests/libc/posix/fcntl/tfcntl2.ok Thu Jan 1 00:00:00 1970 +++ djgpp/tests/libc/posix/fcntl/tfcntl2.ok Fri Dec 29 03:37:40 2000 @@ -0,0 +1,156 @@ +F_SETLK/F_RDLCK/BOF:retval=0,fl.l_start=0 +F_SETLK/F_UNLCK/BOF:retval=0,fl.l_start=0 +F_SETLK/F_RDLCK/EOF:retval=0,fl.l_start=0 +F_SETLK/F_UNLCK/EOF:retval=0,fl.l_start=0 +F_SETLK/F_RDLCK/2*EOF:retval=0,fl.l_start=0 +F_SETLK/F_UNLCK/2*EOF:retval=0,fl.l_start=0 +F_SETLK64/F_RDLCK/BOF:retval=0,fl64.l_start=0 +F_SETLK64/F_UNLCK/BOF:retval=0,fl64.l_start=0 +F_SETLK64/F_RDLCK/EOF:retval=0,fl64.l_start=0 +F_SETLK64/F_UNLCK/EOF:retval=0,fl64.l_start=0 +F_SETLK64/F_RDLCK/2*EOF:retval=0,fl64.l_start=0 +F_SETLK64/F_UNLCK/2*EOF:retval=0,fl64.l_start=0 +F_SETLK/F_RDLCK/BOF:retval=0,fl.l_start=2386 +F_SETLK/F_UNLCK/BOF:retval=0,fl.l_start=2386 +F_SETLK/F_RDLCK/EOF:retval=0,fl.l_start=2386 +F_SETLK/F_UNLCK/EOF:retval=0,fl.l_start=2386 +F_SETLK/F_RDLCK/2*EOF:retval=0,fl.l_start=2386 +F_SETLK/F_UNLCK/2*EOF:retval=0,fl.l_start=2386 +F_SETLK64/F_RDLCK/BOF:retval=0,fl64.l_start=2386 +F_SETLK64/F_UNLCK/BOF:retval=0,fl64.l_start=2386 +F_SETLK64/F_RDLCK/EOF:retval=0,fl64.l_start=2386 +F_SETLK64/F_UNLCK/EOF:retval=0,fl64.l_start=2386 +F_SETLK64/F_RDLCK/2*EOF:retval=0,fl64.l_start=2386 +F_SETLK64/F_UNLCK/2*EOF:retval=0,fl64.l_start=2386 +F_SETLK/F_RDLCK/BOF:retval=-1,fl.l_start=4772 +fd: 5 +errno: 4 : Permission denied (EACCES) +DOS errno: 33 : Lock violation +DOS extended error to errno: 4 : Permission denied (EACCES) +Extended DOS error information: +Extended error: 33 : Lock violation +Class: 0A : Media error +Action: 02 : Prompt user to reenter input +Error Locus: 02 : Network related +F_SETLK/F_UNLCK/BOF:retval=-1,fl.l_start=4772 +fd: 5 +errno: 4 : Permission denied (EACCES) +DOS errno: 33 : Lock violation +DOS extended error to errno: 4 : Permission denied (EACCES) +Extended DOS error information: +Extended error: 33 : Lock violation +Class: 0A : Media error +Action: 02 : Prompt user to reenter input +Error Locus: 02 : Network related +F_SETLK/F_RDLCK/EOF:retval=-1,fl.l_start=4772 +fd: 5 +errno: 4 : Permission denied (EACCES) +DOS errno: 33 : Lock violation +DOS extended error to errno: 4 : Permission denied (EACCES) +Extended DOS error information: +Extended error: 33 : Lock violation +Class: 0A : Media error +Action: 02 : Prompt user to reenter input +Error Locus: 02 : Network related +F_SETLK/F_UNLCK/EOF:retval=-1,fl.l_start=4772 +fd: 5 +errno: 4 : Permission denied (EACCES) +DOS errno: 33 : Lock violation +DOS extended error to errno: 4 : Permission denied (EACCES) +Extended DOS error information: +Extended error: 33 : Lock violation +Class: 0A : Media error +Action: 02 : Prompt user to reenter input +Error Locus: 02 : Network related +F_SETLK/F_RDLCK/2*EOF:retval=-1,fl.l_start=4772 +fd: 5 +errno: 4 : Permission denied (EACCES) +DOS errno: 33 : Lock violation +DOS extended error to errno: 4 : Permission denied (EACCES) +Extended DOS error information: +Extended error: 33 : Lock violation +Class: 0A : Media error +Action: 02 : Prompt user to reenter input +Error Locus: 02 : Network related +F_SETLK/F_UNLCK/2*EOF:retval=-1,fl.l_start=4772 +fd: 5 +errno: 4 : Permission denied (EACCES) +DOS errno: 33 : Lock violation +DOS extended error to errno: 4 : Permission denied (EACCES) +Extended DOS error information: +Extended error: 33 : Lock violation +Class: 0A : Media error +Action: 02 : Prompt user to reenter input +Error Locus: 02 : Network related +F_SETLK64/F_RDLCK/BOF:retval=-1,fl64.l_start=4772 +fd: 5 +errno: 4 : Permission denied (EACCES) +DOS errno: 33 : Lock violation +DOS extended error to errno: 4 : Permission denied (EACCES) +Extended DOS error information: +Extended error: 33 : Lock violation +Class: 0A : Media error +Action: 02 : Prompt user to reenter input +Error Locus: 02 : Network related +F_SETLK64/F_UNLCK/BOF:retval=-1,fl64.l_start=4772 +fd: 5 +errno: 4 : Permission denied (EACCES) +DOS errno: 33 : Lock violation +DOS extended error to errno: 4 : Permission denied (EACCES) +Extended DOS error information: +Extended error: 33 : Lock violation +Class: 0A : Media error +Action: 02 : Prompt user to reenter input +Error Locus: 02 : Network related +F_SETLK64/F_RDLCK/EOF:retval=-1,fl64.l_start=4772 +fd: 5 +errno: 4 : Permission denied (EACCES) +DOS errno: 33 : Lock violation +DOS extended error to errno: 4 : Permission denied (EACCES) +Extended DOS error information: +Extended error: 33 : Lock violation +Class: 0A : Media error +Action: 02 : Prompt user to reenter input +Error Locus: 02 : Network related +F_SETLK64/F_UNLCK/EOF:retval=-1,fl64.l_start=4772 +fd: 5 +errno: 4 : Permission denied (EACCES) +DOS errno: 33 : Lock violation +DOS extended error to errno: 4 : Permission denied (EACCES) +Extended DOS error information: +Extended error: 33 : Lock violation +Class: 0A : Media error +Action: 02 : Prompt user to reenter input +Error Locus: 02 : Network related +F_SETLK64/F_RDLCK/2*EOF:retval=-1,fl64.l_start=4772 +fd: 5 +errno: 4 : Permission denied (EACCES) +DOS errno: 33 : Lock violation +DOS extended error to errno: 4 : Permission denied (EACCES) +Extended DOS error information: +Extended error: 33 : Lock violation +Class: 0A : Media error +Action: 02 : Prompt user to reenter input +Error Locus: 02 : Network related +F_SETLK64/F_UNLCK/2*EOF:retval=-1,fl64.l_start=4772 +fd: 5 +errno: 4 : Permission denied (EACCES) +DOS errno: 33 : Lock violation +DOS extended error to errno: 4 : Permission denied (EACCES) +Extended DOS error information: +Extended error: 33 : Lock violation +Class: 0A : Media error +Action: 02 : Prompt user to reenter input +Error Locus: 02 : Network related +F_SETLK/F_RDLCK/BOF:retval=0,fl.l_start=9544 +F_SETLK/F_UNLCK/BOF:retval=0,fl.l_start=9544 +F_SETLK/F_RDLCK/EOF:retval=0,fl.l_start=9544 +F_SETLK/F_UNLCK/EOF:retval=0,fl.l_start=9544 +F_SETLK/F_RDLCK/2*EOF:retval=0,fl.l_start=9544 +F_SETLK/F_UNLCK/2*EOF:retval=0,fl.l_start=9544 +F_SETLK64/F_RDLCK/BOF:retval=0,fl64.l_start=9544 +F_SETLK64/F_UNLCK/BOF:retval=0,fl64.l_start=9544 +F_SETLK64/F_RDLCK/EOF:retval=0,fl64.l_start=9544 +F_SETLK64/F_UNLCK/EOF:retval=0,fl64.l_start=9544 +F_SETLK64/F_RDLCK/2*EOF:retval=0,fl64.l_start=9544 +F_SETLK64/F_UNLCK/2*EOF:retval=0,fl64.l_start=9544 diff -ruN djgpp-cvs/tests/makefile.def djgpp/tests/makefile.def --- djgpp-cvs/tests/makefile.def Thu Jan 1 00:00:00 1970 +++ djgpp/tests/makefile.def Mon Dec 11 21:56:52 2000 @@ -0,0 +1,65 @@ +# Copyright (C) 1998 DJ Delorie, see COPYING.DJ for details +# -*- makefile -*- + +# These define the cross-to-djgpp and native programs. + +ifneq ($(COMSPEC),) +CROSS_BUILD = 0 +else +CROSS_BUILD = 1 +endif + +# OK, pay attention: The CROSS_* programs are used to build objects +# and executables that become part of djgpp itself (like libc.a and +# stubedit.exe) and the not-CROSS_* programs are used to build +# programs that are used as part of the build. When you're building +# *with* djgpp, they should be the same program, but when you're +# building under unix (IRIX, Linux, etc), it makes a difference +# because we often have to build programs twice - once for our use +# (runs under unix) and once for the distribution (runs under dos). + +ifeq ($(CROSS_BUILD),0) + +# These programs shouldn't need to be changed; they're used +# when building djgpp *with* djgpp. + +# For building distributed (djgpp) libraries and programs +CROSS_GCC = gcc +CROSS_AR = ar +CROSS_LD = ld +CROSS_STRIP = strip +CROSS_BISON = bison + +# For building native programs (hostbin/*); assumes GNU versions +GCC = gcc -g +AR = ar +LD = ld +STRIP = strip +BISON = bison + +else + +# These may need to be changed based on where/how you installed +# your native gcc and your cross compiler. + +# For building distributed (djgpp) libraries and programs + +CROSS_GCC = i586-pc-msdosdjgpp-gcc -pipe +CROSS_AR = i586-pc-msdosdjgpp-ar +CROSS_LD = i586-pc-msdosdjgpp-ld +CROSS_STRIP = i586-pc-msdosdjgpp-strip +CROSS_BISON = bison + +# For building programs that *run* during the build (hostbin/*); +# assumes GNU versions + +GCC = gcc -g -O2 -pipe +AR = ar +LD = ld +STRIP = strip +BISON = bison + +# You may need to replace coff-go32 with coff-i386 in lib/djgpp.djl or +# edit your cross_ld to replace coff-i386 with coff-go32 (as I did) + +endif diff -ruN djgpp-cvs/tests/makefile.inc djgpp/tests/makefile.inc --- djgpp-cvs/tests/makefile.inc Sun Sep 1 15:39:18 1996 +++ djgpp/tests/makefile.inc Mon Dec 11 21:56:52 2000 @@ -1,3 +1,6 @@ +# Copyright (C) 2000 DJ Delorie, see COPYING.DJ for details + +include $(TOP)/../makefile.def .SUFFIXES: .o .i .c .cc .s @@ -31,7 +34,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 diff -ruN djgpp-cvs/src/docs/kb/wcfcntl.txi djgpp/src/docs/kb/wcfcntl.txi --- djgpp-cvs/src/docs/kb/wcfcntl.txi Thu Jan 1 00:00:00 1970 +++ djgpp/src/docs/kb/wcfcntl.txi Fri Dec 29 04:42:00 2000 @@ -0,0 +1,56 @@ + +@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 some exceptions relating to the absence of any +read locking in DOS/Win9x environments. + +@item +@findex fcntl AT r{ commands }F_GETFD AT r{ and }F_SETFD +These functions now interrogate and use the value of the DOS flag +@code{_DEV_NO_INHERIT} to implement the @code{FD_CLOEXEC} flag; + +@item +@findex fcntl AT r{ commands }F_GETFL AT r{ and }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. + +@item +Documentation has been updated to reflect the new functionality and +test programs have been provided for most new or changed functions. + +@findex flock +@findex lockf +@findex llockf +@code{flock} has been implemented using the new @code{fcntl} locking +functions to implement file-level locking and unlocking. @code{lockf} +(31-bit support) and @code{llockf} (FAT32 support, 32-bit only) have +been added as compatible interfaces to the new @code{fcntl} locking +functions. + +@findex dosexterr +@findex dostrerr +New function @code{dostrerr} has been coded to provide string +values for the error codes returned from function @code{dosexterr}. +Documentation and a test program have been provided. This function is +an analogue of the @code{strerror} function for errno values, and is +intended to be used when coding functions or programs that call DOS and +want to print messages when errors occur. + +@findex _dos_lk64 +@findex _dos_unlk64 +@findex lock64 +@findex unlock64 +New functions @code{_dos_lk64} and @code{_dos_unlk64} have been added to +provide a FAT32-compatible interface to the DOS locking code. +Compatible functions @code{lock64} and @code{unlock64} are direct +interfaces to these two new "_dos" functions. +@end itemize diff -ruN djgpp-cvs/src/libc/dos/errno/doserr2e.c djgpp/src/libc/dos/errno/doserr2e.c --- djgpp-cvs/src/libc/dos/errno/doserr2e.c Tue Sep 8 07:49:26 1998 +++ djgpp/src/libc/dos/errno/doserr2e.c Mon Dec 11 21:56:58 2000 @@ -1,5 +1,10 @@ +/* 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 */ + +/* 21h (33) EPERM -> EACCES */ +/* lock violation needs EACCES errno in fcntl */ + #include #include @@ -8,7 +13,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, diff -ruN djgpp-cvs/src/libc/dos/io/doslk64.c djgpp/src/libc/dos/io/doslk64.c --- djgpp-cvs/src/libc/dos/io/doslk64.c Thu Jan 1 00:00:00 1970 +++ djgpp/src/libc/dos/io/doslk64.c Mon Dec 11 21:56:58 2000 @@ -0,0 +1,19 @@ +/* Copyright (C) 1995 DJ Delorie, see COPYING.DJ for details */ +#include +#include + +int +_dos_lk64(int _fd, long long _offset, long long _length) +{ + __dpmi_regs r; + r.x.ax = 0x5c00; + r.x.bx = _fd; + r.x.cx = _offset >> 16; + r.x.dx = _offset & 0xffff; + r.x.si = _length >> 16; + r.x.di = _length & 0xffff; + __dpmi_int(0x21, &r); + if (r.x.flags & 1) + return r.x.ax; + return 0; +} diff -ruN djgpp-cvs/src/libc/dos/io/dosunl64.c djgpp/src/libc/dos/io/dosunl64.c --- djgpp-cvs/src/libc/dos/io/dosunl64.c Thu Jan 1 00:00:00 1970 +++ djgpp/src/libc/dos/io/dosunl64.c Mon Dec 11 21:56:58 2000 @@ -0,0 +1,19 @@ +/* Copyright (C) 1995 DJ Delorie, see COPYING.DJ for details */ +#include +#include + +int +_dos_unlk64(int _fd, long long _offset, long long _length) +{ + __dpmi_regs r; + r.x.ax = 0x5c01; + r.x.bx = _fd; + r.x.cx = _offset >> 16; + r.x.dx = _offset & 0xffff; + r.x.si = _length >> 16; + r.x.di = _length & 0xffff; + __dpmi_int(0x21, &r); + if (r.x.flags & 1) + return r.x.ax; + return 0; +} diff -ruN djgpp-cvs/src/libc/dos/io/lock64.c djgpp/src/libc/dos/io/lock64.c --- djgpp-cvs/src/libc/dos/io/lock64.c Thu Jan 1 00:00:00 1970 +++ djgpp/src/libc/dos/io/lock64.c Mon Dec 11 21:56:58 2000 @@ -0,0 +1,24 @@ +/* Copyright (C) 2000 DJ Delorie, see COPYING.DJ for details */ +/* Copyright (C) 1997 DJ Delorie, see COPYING.DJ for details */ +/* Copyright (C) 1995 DJ Delorie, see COPYING.DJ for details */ +#include +#include +#include + +int +lock64(int fd, long long offset, long long length) +{ + int ret = _dos_lk64(fd, offset, length); +#if 0 /* __doserr_to_errno does the same */ + /* change return code because Borland does it this way */ + if (ret == 0x21) + ret = EACCES; +#endif + if (ret != 0) + { + errno = __doserr_to_errno(ret); + return -1; + } + else + return 0; +} diff -ruN djgpp-cvs/src/libc/dos/io/makefile djgpp/src/libc/dos/io/makefile --- djgpp-cvs/src/libc/dos/io/makefile Sun Jun 28 18:42:16 1998 +++ djgpp/src/libc/dos/io/makefile Mon Dec 11 21:56:58 2000 @@ -12,14 +12,18 @@ SRC += _write.c SRC += crlf2nl.c SRC += dosio.c +SRC += doslk64.c SRC += doslock.c +SRC += dosunl64.c SRC += dosunloc.c SRC += fmode.c SRC += lock.c +SRC += lock64.c SRC += putpath.c SRC += setmode.c SRC += tell.c SRC += unlock.c +SRC += unlock64.c SRC += flushdc.c include $(TOP)/../makefile.inc diff -ruN djgpp-cvs/src/libc/dos/io/unlock64.c djgpp/src/libc/dos/io/unlock64.c --- djgpp-cvs/src/libc/dos/io/unlock64.c Thu Jan 1 00:00:00 1970 +++ djgpp/src/libc/dos/io/unlock64.c Mon Dec 11 21:56:58 2000 @@ -0,0 +1,25 @@ +/* Copyright (C) 2000 DJ Delorie, see COPYING.DJ for details */ +/* Copyright (C) 1997 DJ Delorie, see COPYING.DJ for details */ +/* Copyright (C) 1995 DJ Delorie, see COPYING.DJ for details */ +#include +#include +#include + +int +unlock64(int fd, long long offset, long long length) +{ + int ret = _dos_unlk64(fd, offset, length); +#if 0 /* __doserr_to_errno does the same */ + /* change return code because Borland does it this way */ + if (ret == 0x21) + ret = EACCES; +#endif + if (ret != 0) + { + errno = __doserr_to_errno(ret); + return -1; + } + else + return 0; +} + diff -ruN djgpp-cvs/src/libc/posix/fcntl/fcntl.c djgpp/src/libc/posix/fcntl/fcntl.c --- djgpp-cvs/src/libc/posix/fcntl/fcntl.c Thu Jun 3 13:27:38 1999 +++ djgpp/src/libc/posix/fcntl/fcntl.c Sat Dec 16 01:11:12 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,261 @@ #include #include #include +#include #include +#include +#include +#include +#include + + +#include + + +static unsigned long _get_sft_entry_ptr(int fd) +{ + __dpmi_regs regs; + unsigned char index; + unsigned long es, di; + + + /* Get the JFT entry address for this handle. */ + regs.x.ax = 0x1220; + regs.x.bx = fd; + __dpmi_int(0x2f, ®s); + + + if (regs.x.flags & 1) /* int2F/1220 returns CF set if bad input */ + { + errno = __doserr_to_errno(regs.h.al); /* And AL has the error number */ + 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); + + + if (index < 0xff) + { + /* Now get the address of the entry. */ + regs.x.ax = 0x1216; + regs.x.bx = index; + __dpmi_int (0x2f, ®s); + } + else + regs.x.flags |= 1; /* Set carry flag to simulate error */ + + if (regs.x.flags & 1) /* int2F/1216 returns CF set if bad input */ + { + errno = EBADF; /* But no other information is returned */ + return 0; + } + + + es = regs.x.es; + di = regs.x.di; + + + return es * 16 + di; +} + static int -is_used_fd(int fd) +inherit_bit_test (int fd, short dev_info) { __dpmi_regs regs; + short new_dev_info; + - regs.x.ax = 0x4400; + dev_info |= _DEV_NO_INHERIT; + regs.x.ax = 0x4401; regs.x.bx = fd; + regs.x.dx = dev_info; __dpmi_int(0x21, ®s); - if (regs.x.flags & 1) - return 0; - return 1; + new_dev_info = _get_dev_info(fd); + + /* If the dev info words are equal, then the documented + interface can be used to set the inheritance bit. */ + return (new_dev_info == dev_info) ? 1 : 0; +} + +static int +_get_SHARE_status (void) +{ + __dpmi_regs regs; + + regs.x.ax = 0x1000; + __dpmi_int(0x2f, ®s); + + /* If al == 0xff then SHARE is installed, otherwise not */ + return (regs.h.al == 0xff) ? 1 : 0; } +static int +_fcntl_lk64(int fd, int cmd, struct flock64 *lock_r64) +{ + int ret = -1; + long long int ret64 = -1L; + offset_t pos, cur_pos, lock_pos, len; + long long int flen; + + /* First check if SHARE is loaded */ + ret = _get_SHARE_status(); + + if (!ret) /* Then SHARE is NOT loaded, just return success */ + { + if (cmd == F_GETLK64) /* Then make believe the lock is available */ + lock_r64->l_type = F_UNLCK; + + return ret; + } + else ret = -1; /* Restore default value */ + + cur_pos = llseek(fd, 0L, SEEK_CUR); + if (cur_pos < 0) + return -1; /* Assumes llseek has set errno */ + + lock_pos = llseek (fd, lock_r64->l_start, lock_r64->l_whence); + if (lock_pos < 0) + return -1; /* Assumes llseek has set errno */ + + len = lock_r64->l_len; + + + /* If l_len is zero, then the lock is to be set from the position + represented by l_start/l_whence to the current end-of-file. + */ + if (len == 0L) + { + flen = lfilelength(fd); /* Hold lfilelength in case len < 0 */ + len = flen - lock_pos; /* len > 0 lock_pos before EOF + len == 0 lock_pos at EOF + len < 0 lock_pos after EOF + */ + + /* If now len < 0, then lock_pos is beyond EOF, and + the code below will calculate the correct region. + */ + if (len < 0L) + { + pos = flen; /* Start at EOF == lfilelength(fd) */ + lock_pos = flen; /* Also set lock_pos for later */ + len = -len; /* Make the length positive */ + } + } + + + /* Return to saved position */ + ret64 = llseek (fd, cur_pos, SEEK_SET); + if (ret64 < 0L) + return -1; /* Assumes llseek has set errno */ + else + ret64 = -1; /* Restore default value */ + + + /* 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. + + Note that if l_len == 0, then pos and len may have already + been set above, and lock_pos may have been reset to flen. + */ + if (len > 0L) + { + pos = lock_pos; + } + else + { + pos = lock_pos + len; + len = -len; + } + + + /* DOS/Win9x only support write locks via int 21/5C, so + all read lock requests are treated like write locks + */ + + if (lock_r64->l_type == F_UNLCK) + { + ret = _dos_unlk64(fd, pos, len); + if (ret != 0) + { + _doserrno = ret; + errno = __doserr_to_errno(ret); + return -1; + } + } + else if ((lock_r64->l_type == F_WRLCK) || + (lock_r64->l_type == F_RDLCK)) + { + ret = _dos_lk64(fd, pos, len); + if (cmd == F_GETLK64) + { + if (!ret) + { + _dos_unlk64(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_r64->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 F_SETLKW64 is set, wait for the lock to be released. */ + if (cmd == F_SETLKW64 && ret) + { + while ((ret = _dos_lk64(fd, pos, len))) + __dpmi_yield(); + } + else if (ret) + { + _doserrno = ret; + errno = __doserr_to_errno(ret); + return -1; + } + } + } + if (ret) + errno = ENOSYS; + + return ret; +} + + 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 +270,220 @@ 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 */ + struct flock64 lock_r64; + int ret = -1, lcmd = -1; + + va_start (ap, cmd); + lock_req = va_arg(ap, struct flock *); + va_end (ap); + + switch (cmd) { - errno = ENOSYS; - return -1; + case F_GETLK: lcmd = F_GETLK64; break; + case F_SETLK: lcmd = F_SETLK64; break; + case F_SETLKW: lcmd = F_SETLKW64; break; } - 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; + + lock_r64.l_type = lock_req->l_type; + lock_r64.l_start = lock_req->l_start; + lock_r64.l_whence = lock_req->l_whence; + lock_r64.l_len = lock_req->l_len; + + ret = _fcntl_lk64(fd, lcmd, &lock_r64); + + lock_req->l_type = lock_r64.l_type; + lock_req->l_start = (off_t) lock_r64.l_start; + lock_req->l_whence = lock_r64.l_whence; + lock_req->l_len = (off_t) lock_r64.l_len; + + return ret; + } + + + case F_GETLK64: + case F_SETLK64: + case F_SETLKW64: + { + struct flock64 *lock_r64; /* shut up -Wall */ + int ret; + + va_start (ap, cmd); + lock_r64 = va_arg(ap, struct flock64 *); + va_end (ap); + + ret = _fcntl_lk64(fd, cmd, lock_r64); + + return ret; + } } + + + /* In case fcntl is called with an unrecognized command. */ errno = ENOSYS; return -1; } diff -ruN djgpp-cvs/src/libc/posix/fcntl/fcntl.txh djgpp/src/libc/posix/fcntl/fcntl.txh --- djgpp-cvs/src/libc/posix/fcntl/fcntl.txh Thu Jun 3 02:35:56 1999 +++ djgpp/src/libc/posix/fcntl/fcntl.txh Mon Dec 11 21:56:58 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. -The no-inherit bit can be set when the file is open, by using the +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 opened 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,55 @@ @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. That is, calls using @code{F_SETFL} will fail for +all flag values @strong{except} @code{O_NONBLOCK}. + +@example +#include + +ret = fcntl (fd, F_SETFL, O_BINARY); /* This will fail, returning -1 */ + /* and setting errno to ENOSYS */ + +ret = fcntl (fd, F_SETFL, O_NONBLOCK); /* This will succeed */ + /* returning 0 */ +@end example @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. This call will not +return values in the @code{struct flock} parameter identifying what lock +parameters prevent getting the requested lock, since there is no way to +obtain this information from DOS/Windows. 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}. + +The @code{F_RDLCK} value for requesting a read lock is always treated as +if it were @code{F_WRLCK} for a write lock. + +This is because DOS/Win9x only supports one kind of lock, and it is the +exclusive kind. @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}, see @pxref{__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 +145,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 diff -ruN djgpp-cvs/src/libc/posix/sys/stat/lfilelen.c djgpp/src/libc/posix/sys/stat/lfilelen.c --- djgpp-cvs/src/libc/posix/sys/stat/lfilelen.c Thu Jan 1 00:00:00 1970 +++ djgpp/src/libc/posix/sys/stat/lfilelen.c Fri Dec 15 21:13:44 2000 @@ -0,0 +1,62 @@ +/* Copyright (C) 2000 DJ Delorie, see COPYING.DJ for details */ +/* This is file LFILELEN.C */ +/* + * Copyright (c) 1994 Eli Zaretskii + * + * This software may be used freely so long as this copyright notice is + * left intact. There is no warranty on this software. + * + */ + +#include +#include +#include + +long long __lfilelength(int); + +long long +__lfilelength(int fhandle) +{ + __dpmi_regs regs; + unsigned short fpos_high, fpos_low; + long long retval; + + /* Remember the current file position, so we can return there + later. */ + regs.x.ax = 0x4201; /* set pointer from current position */ + regs.x.bx = fhandle; + regs.x.cx = regs.x.dx = 0; /* move 0 bytes (i.e., stay put) */ + __dpmi_int(0x21, ®s); + if (regs.x.flags & 1) + { + errno = __doserr_to_errno(regs.x.ax); + return -1L; + } + fpos_high = regs.x.dx; /* save current position */ + fpos_low = regs.x.ax; + + regs.x.cx = regs.x.dx = 0; + regs.x.ax = 0x4202; /* set pointer 0 bytes from the end of file */ + __dpmi_int(0x21, ®s); + if (regs.x.flags & 1) + { + errno = __doserr_to_errno(regs.x.ax); + return -1L; + } + + /* The absolute byte offset returned in DX:AX is the file size. */ + retval = ( (long long)regs.x.dx << 16 ) + regs.x.ax; + + /* Leave things as we have found them. */ + regs.x.ax = 0x4200; /* set pointer from the beginning of file */ + regs.x.cx = fpos_high; + regs.x.dx = fpos_low; + __dpmi_int(0x21, ®s); + if (regs.x.flags & 1) + { + errno = __doserr_to_errno(regs.x.ax); + return -1L; + } + + return retval; +} diff -ruN djgpp-cvs/src/libc/posix/sys/stat/makefile djgpp/src/libc/posix/sys/stat/makefile --- djgpp-cvs/src/libc/posix/sys/stat/makefile Sat Aug 5 12:53:46 2000 +++ djgpp/src/libc/posix/sys/stat/makefile Sat Dec 16 01:08:58 2000 @@ -6,6 +6,7 @@ SRC += fixpath.c SRC += fstat.c SRC += is_exec.c +SRC += lfilelen.c SRC += lstat.c SRC += mkdir.c SRC += mkfifo.c --=====================_12624979==_ Content-Type: text/plain; charset="us-ascii"; format=flowed --------------------------------------------------------- Peter J. Farley III (pjfarley AT dorsai DOT org OR pjfarley AT banet DOT net) --=====================_12624979==_--