Message-Id: <3.0.1.32.19970919161604.006d64f0@yacker.xiotech.com> Date: Fri, 19 Sep 1997 16:16:04 -0500 To: djgpp-workers AT delorie DOT com From: Randy Maas Subject: some proposed changes to fsext p3 Mime-Version: 1.0 Content-Type: multipart/mixed; boundary="=====================_874721764==_" Precedence: bulk --=====================_874721764==_ Content-Type: text/plain; charset="us-ascii" Apparently part 1 didn't send properly the first time. I've split it up and am trying again. Randy Maas randym AT acm DOT org --=====================_874721764==_ Content-Type: text/plain; charset="us-ascii" Content-Disposition: attachment; filename="fsext-h.dif" diff -c2 fsext.h include\sys\fsext.h *** fsext.h Wed Sep 17 16:45:44 1997 --- include\sys\fsext.h *************** *** 23,28 __FSEXT_ready, __FSEXT_close, - __FSEXT_pread, - __FSEXT_pwrite, __FSEXT_fcntl, __FSEXT_ioctl, --- 23,26 ----- __FSEXT_ready, __FSEXT_close, __FSEXT_fcntl, __FSEXT_ioctl, *************** *** 27,34 __FSEXT_fcntl, __FSEXT_ioctl, - __FSEXT_lseek, - __FSEXT_link, - __FSEXT_unlink, - __FSEXT_copy } __FSEXT_Fnumber; --- 25,28 ----- __FSEXT_fcntl, __FSEXT_ioctl, } __FSEXT_Fnumber; *************** *** 42,46 caller's functionality. */ typedef int (__FSEXT_Function)(__FSEXT_Fnumber _function_number, ! int *_rv, va_list _args, void* state); int __FSEXT_alloc_fd(__FSEXT_Function *_function, void* state); --- 36,40 ----- caller's functionality. */ typedef int (__FSEXT_Function)(__FSEXT_Fnumber _function_number, ! int *_rv, va_list _args); int __FSEXT_alloc_fd(__FSEXT_Function *_function); *************** *** 44,50 int *_rv, va_list _args, void* state); ! int __FSEXT_alloc_fd(__FSEXT_Function *_function, void* state); ! int __FSEXT_set_function(int _fd, __FSEXT_Function *_function, ! void* state); __FSEXT_Function *__FSEXT_get_function(int _fd); int __FSEXT_get_handler(int _fd, __FSEXT_Function** func, --- 38,43 ----- int *_rv, va_list _args); ! int __FSEXT_alloc_fd(__FSEXT_Function *_function); ! int __FSEXT_set_function(int _fd, __FSEXT_Function *_function); __FSEXT_Function *__FSEXT_get_function(int _fd); *************** *** 48,55 void* state); __FSEXT_Function *__FSEXT_get_function(int _fd); ! int __FSEXT_get_handler(int _fd, __FSEXT_Function** func, ! void** state); ! int __FSEXT_Call(__FSEXT_Fnumber, int, va_list); ! int __FSEXT_Emu (__FSEXT_Fnumber, int*, va_list, void*); int __FSEXT_add_open_handler(__FSEXT_Function *_function); int __FSEXT_call_open_handlers(__FSEXT_Fnumber _function_number, --- 41,45 ----- int __FSEXT_set_function(int _fd, __FSEXT_Function *_function); __FSEXT_Function *__FSEXT_get_function(int _fd); ! int __FSEXT_add_open_handler(__FSEXT_Function *_function); int __FSEXT_call_open_handlers(__FSEXT_Fnumber _function_number, --=====================_874721764==_ Content-Type: text/plain; charset="us-ascii" Content-Disposition: attachment; filename="link.dif" diff -c2 link.c src\libc\posix\unistd\link.c *** link.c Wed Sep 17 13:46:32 1997 --- \local\src\libc\posix\unistd\link.c Wed May 10 02:13:46 1995 *************** *** 1,6 ! /* ! 1997, Modified by Randall Maas to be a wrapper to _link. Inlined the ! documentation ! Copyright (C) 1995 DJ Delorie, see COPYING.DJ for details */ #include #include /* For stat() */ --- 1,3 ----- ! /* Copyright (C) 1995 DJ Delorie, see COPYING.DJ for details */ #include #include /* For stat() */ *************** *** 6,9 #include /* For stat() */ #include /* For O_RDONLY, etc. */ #include /* For PATH_MAX */ #include /* For utime() */ --- 3,7 ----- #include /* For stat() */ #include /* For O_RDONLY, etc. */ + #include /* For read(), write(), etc. */ #include /* For PATH_MAX */ #include /* For utime() */ *************** *** 10,23 #include /* For errno */ ! /* ! @txh ! @node link, io ! @subheading Syntax ! @example ! */ ! ! #include /*// For read(), write(), etc. */ ! int link(const char *exists, const char *new) ! /*@end example*/ { /* --- 8,16 ----- #include /* For errno */ ! /* Of course, DOS can't really do a link. We just do a copy instead, ! which is as close as DOS gets. Alternatively, we could always fail ! and return -1. I think this is slightly better. */ ! int ! link(const char *path1, const char *path2) { struct stat statbuf1, statbuf2; *************** *** 21,29 /*@end example*/ { ! /* ! @subheading Example ! @example ! link("foo.c", "foo.bak"); ! @end example @subheading Description --- 14,21 ----- link(const char *path1, const char *path2) { ! struct stat statbuf1, statbuf2; ! struct utimbuf times; ! char buf[16384]; ! int fd1, fd2, nbyte, status1, status2; /* Fail if either path is null */ *************** *** 27,34 @end example ! @subheading Description ! Because of limitations of MS-DOS, this function doesn't really link two ! MSDOS files together. However, it simulates a real @code{link} by ! copying these files at @var{exists} to @var{new}. @subheading Return Value --- 19,33 ----- int fd1, fd2, nbyte, status1, status2; ! /* Fail if either path is null */ ! if (path1 == NULL || path2 == NULL) ! { ! errno = EFAULT; ! return -1; ! } ! if (*path1 == '\0' || *path2 == '\0') ! { ! errno = ENOENT; ! return -1; ! } /* Fail if path1 does not exist - stat() will set errno */ *************** *** 32,37 copying these files at @var{exists} to @var{new}. ! @subheading Return Value ! Zero on success, nonzero on failure. @end txh --- 31,36 ----- } ! /* Fail if path1 does not exist - stat() will set errno */ ! if (stat(path1, &statbuf1) < 0) return -1; /* Fail if path1 is not a regular file */ *************** *** 35,40 Zero on success, nonzero on failure. ! @end txh ! */ /* _link is defined as a File System Extension call */ --- 34,43 ----- if (stat(path1, &statbuf1) < 0) return -1; ! /* Fail if path1 is not a regular file */ ! if (!S_ISREG(statbuf1.st_mode)) ! { ! errno = EPERM; ! return -1; ! } /* Fail if unable to open path1 - open() will set errno */ *************** *** 38,43 */ ! /* _link is defined as a File System Extension call */ ! return _link(exists, new); ! } --- 41,47 ----- } ! /* Fail if unable to open path1 - open() will set errno */ ! fd1 = open(path1, O_RDONLY | O_BINARY); ! if (fd1 < 0) return -1; /* Fail if unable to create path2 - open() will set errno */ *************** *** 42,43 } --- 45,95 ----- if (fd1 < 0) return -1; + /* Fail if unable to create path2 - open() will set errno */ + fd2 = open(path2, O_WRONLY | O_BINARY | O_CREAT | O_EXCL, 0600); + if (fd2 < 0) + { + (void) close(fd1); + return -1; + } + + /* Fail if path1 and path2 are on different devices */ + if (fstat(fd2, &statbuf2) < 0) return -1; + if (statbuf1.st_dev != statbuf2.st_dev) + { + (void)close(fd1); + (void)close(fd2); + (void)unlink(path2); + errno = EXDEV; + return -1; + } + + /* Copy path1 to path2 */ + do + { + nbyte = read(fd1, buf, sizeof buf); + if (nbyte <= 0) break; + if (write(fd2, buf, nbyte) != nbyte) nbyte = -1; + } + while (nbyte > 0); + + /* Fail if the copy failed or we can't clean up */ + status1 = close(fd1); + status2 = close(fd2); + if (nbyte < 0 || status1 < 0 || status2 < 0) + { + (void) unlink(path2); + return -1; + } + + /* Success! */ + + /* Set the mode to match the original, ignoring errors */ + (void) chmod(path2, statbuf1.st_mode); + + /* Set the file time to match the original, ignoring errors */ + times.actime = statbuf1.st_atime; + times.modtime = statbuf1.st_mtime; + (void) utime(path2, ×); + + return 0; + } --=====================_874721764==_ Content-Type: text/plain; charset="us-ascii" Content-Disposition: attachment; filename="lseek.dif" diff -c2 lseek.c src\libc\posix\unistd\lseek.c *** lseek.c Wed Sep 17 13:46:04 1997 --- \local\src\libc\posix\unistd\lseek.c Sun Feb 26 19:43:10 1995 *************** *** 1,5 ! /* ! 1997, Randall Maas. Converted to a wrapper to _lseek and inlined the documentation ! Copyright (C) 1995 DJ Delorie, see COPYING.DJ for details */ #include #include --- 1,3 ----- ! /* Copyright (C) 1995 DJ Delorie, see COPYING.DJ for details */ #include #include *************** *** 3,6 Copyright (C) 1995 DJ Delorie, see COPYING.DJ for details */ #include #include #include --- 1,5 ----- /* Copyright (C) 1995 DJ Delorie, see COPYING.DJ for details */ #include + #include #include #include *************** *** 8,17 #include - /* - @txh - @node lseek, io - @subheading Syntax - @example - */ #include --- 7,10 ----- #include off_t *************** *** 15,21 */ ! #include ! off_t lseek(int fd, off_t offset, int whence) ! /* @end example*/ { /* --- 8,13 ----- #include ! off_t ! lseek(int handle, off_t offset, int whence) { __dpmi_regs r; *************** *** 19,52 /* @end example*/ { ! /* ! @subheading Example ! @example ! lseek(fd, 12, SEEK_CUR); /* skip 12 bytes **//*/ ! @end example ! ! @subheading Description ! This function moves the file pointer for @var{fd} according to ! @var{mode}: ! ! @table @code ! @item SEEK_SET ! The file pointer is moved to the offset specified. ! ! @item SEEK_CUR ! The file pointer is moved relative to its current position. ! ! @item SEEK_END ! The file pointer is moved to a position @var{offset} bytes from the ! end of the file. The offset is usually nonpositive in this case. ! ! @end table ! ! @subheading Return Value ! The new offset is returned. ! ! @end txh ! */ ! ! return _lseek(fd, offset, whence); } --- 11,26 ----- lseek(int handle, off_t offset, int whence) { ! __dpmi_regs r; ! r.h.ah = 0x42; ! r.h.al = whence; ! r.x.bx = handle; ! r.x.cx = offset >> 16; ! r.x.dx = offset & 0xffff; ! __dpmi_int(0x21, &r); ! if (r.x.flags & 1) ! { ! errno = __doserr_to_errno(r.x.ax); ! return -1; ! } ! return (r.x.dx << 16) + r.x.ax; } *************** *** 50,52 return _lseek(fd, offset, whence); } - --- 25,26 ----- return (r.x.dx << 16) + r.x.ax; } --=====================_874721764==_ Content-Type: text/plain; charset="us-ascii" Content-Disposition: attachment; filename="remove.dif" diff -c2 remove.c src\libc\ansi\stdio\remove.c *** remove.c Thu Jun 5 09:33:06 1997 --- \local\src\libc\ansi\stdio\remove.c Sat Aug 31 21:09:32 1996 *************** *** 1,5 ! /* ! 1997, Randall Maas: Made into a wrapper for _remove, and inlined documentation ! Copyright (C) 1995 DJ Delorie, see COPYING.DJ for details */ #include --- 1,5 ----- ! /* Copyright (C) 1995 DJ Delorie, see COPYING.DJ for details */ ! #include ! #include #include #include *************** *** 3,17 Copyright (C) 1995 DJ Delorie, see COPYING.DJ for details */ #include ! ! /* ! @txh ! @node remove, file system ! @subheading Syntax ! ! @example ! #include ! */ ! int remove(const char *file_name) ! /* @end example */ { /* --- 3,14 ----- #include #include ! #include ! #include ! #include ! #include ! #include ! ! int ! remove(const char *fn) { __dpmi_regs r; *************** *** 15,23 /* @end example */ { ! /* ! @subheading Example ! @example ! remove("/tmp/data.tmp"); ! @end example @subheading Description --- 12,27 ----- remove(const char *fn) { ! __dpmi_regs r; ! unsigned attr; ! int directory_p; ! int use_lfn = _USE_LFN; ! ! /* Get the file attribute byte. */ ! attr = _chmod(fn, 0); ! directory_p = attr & 0x10; ! ! /* Now, make the file writable. We must reset Vol, Dir, Sys and Hidden bits ! in addition to the Read-Only bit, or else 214301 will fail. */ ! _chmod(fn, 1, attr & 0xffe0); /* Now delete it. Note, _chmod leaves dir name in tranfer buffer. */ *************** *** 21,35 @end example ! @subheading Description ! This function removes the named @var{file} from the file system. ! Unless you have an un-erase program, the file and its contents are ! gone for good. ! ! @subheading Return Value ! Zero on success, nonzero on failure. ! ! @end txh ! */ ! ! return _remove(file_name); } --- 25,50 ----- _chmod(fn, 1, attr & 0xffe0); ! /* Now delete it. Note, _chmod leaves dir name in tranfer buffer. */ ! if (directory_p) ! r.h.ah = 0x3a; /* DOS Remove Directory function */ ! else ! r.h.ah = 0x41; /* DOS Remove File function */ ! if(use_lfn) { ! r.h.al = r.h.ah; ! r.h.ah = 0x71; ! r.x.si = 0; /* No Wildcards */ ! } ! r.x.dx = __tb_offset; ! r.x.ds = __tb_segment; ! __dpmi_int(0x21, &r); ! if(r.x.flags & 1) ! { ! /* We failed. Leave the things as we've found them. */ ! int e = __doserr_to_errno(r.x.ax); ! ! _chmod(fn, 1, attr & 0xffe7); ! errno = e; ! return -1; ! } ! return 0; } --=====================_874721764==_ Content-Type: text/plain; charset="us-ascii" Content-Disposition: attachment; filename="select.dif" diff -c2 select.c src\libc\compat\time\select.c *** select.c Tue Jun 17 12:05:40 1997 --- \local\src\libc\compat\time\select.c Tue Jul 23 22:41:26 1996 *************** *** 1,3 - /* 1997, Randall Maas: inlined documentation and removed MSDOS specific code */ /* Copyright (C) 1996 DJ Delorie, see COPYING.DJ for details */ /* Copyright (C) 1995 DJ Delorie, see COPYING.DJ for details */ --- 1,2 ----- /* Copyright (C) 1996 DJ Delorie, see COPYING.DJ for details */ /* Copyright (C) 1995 DJ Delorie, see COPYING.DJ for details */ *************** *** 25,29 #include ! inline static int fp_input_ready (FILE *fp) { /* I think if there is something in the buffer, we should return --- 24,29 ----- #include ! inline static int ! fp_output_ready(FILE *fp) { return !ferror(fp); *************** *** 27,30 inline static int fp_input_ready (FILE *fp) { /* I think if there is something in the buffer, we should return ``ready'', even if some error was encountered. Let him consume --- 27,45 ----- fp_output_ready(FILE *fp) { + return !ferror(fp); + } + + /* This is as close as we get, I think. For a file connected to a printer + we could of course go ask the BIOS, but this should be enough. */ + + inline static int + fp_except_ready(FILE *fp) + { + return ferror (fp); + } + + inline static int + fp_input_ready (FILE *fp) + { /* I think if there is something in the buffer, we should return ``ready'', even if some error was encountered. Let him consume *************** *** 30,34 ``ready'', even if some error was encountered. Let him consume the buffered characters, *then* return ``not ready''. */ ! if (fp->_cnt) return 1; /* The `feof' part is only correct in a single-tasked environment. */ --- 45,50 ----- ``ready'', even if some error was encountered. Let him consume the buffered characters, *then* return ``not ready''. */ ! if (fp->_cnt) ! return 1; /* The `feof' part is only correct in a single-tasked environment. */ *************** *** 42,46 } ! inline static int fp_output_ready(FILE *fp) { return !ferror(fp); --- 58,66 ----- } ! /* The Dos call 4407 always returns TRUE for disk files. So the ! following really is meaningful for character devices only... */ ! ! inline static int ! fd_output_ready(int fd) { *************** *** 44,48 inline static int fp_output_ready(FILE *fp) { ! return !ferror(fp); } --- 64,80 ----- fd_output_ready(int fd) { ! ! __dpmi_regs regs; ! ! regs.x.ax = 0x4407; ! regs.x.bx = fd; ! __dpmi_int (0x21, ®s); ! if (regs.x.flags & 1) ! { ! errno = __doserr_to_errno (regs.x.ax); ! return -1; ! } ! else ! return regs.h.al == 0xff; } *************** *** 48,52 inline static int ! fp_except_ready(FILE *fp) { return ferror (fp); --- 80,84 ----- inline static int ! fd_input_ready(int fd) { *************** *** 50,54 fp_except_ready(FILE *fp) { ! return ferror (fp); } --- 82,98 ----- fd_input_ready(int fd) { ! ! __dpmi_regs regs; ! ! regs.x.ax = 0x4406; ! regs.x.bx = fd; ! __dpmi_int (0x21, ®s); ! if (regs.x.flags & 1) ! { ! errno = __doserr_to_errno (regs.x.ax); ! return -1; ! } ! else ! return regs.h.al == 0xff; } *************** *** 53,64 } ! /* ! @txh ! @node select, unix ! @subheading Syntax ! @example ! #include ! */ ! int select(int nfds, fd_set *readfds, fd_set *writefds, --- 97,102 ----- } ! int ! select(int nfds, fd_set *readfds, fd_set *writefds, *************** *** 65,69 fd_set *exceptfds, struct timeval *timeout) - /*@end example*/ { /* --- 103,106 ----- fd_set *exceptfds, struct timeval *timeout) { int ready; *************** *** 67,99 /*@end example*/ { - /* - @subheading Description - This function waits for files to be ready for input or output, or for - a timeout. Each fd_set represents a set of bits representing file - descriptors. The following macros shall be used to deal with these - sets: - - @table @code - @item FD_ZERO(p) - Initialize the set to all zeros. - @item FD_SET(n, p) - Set member @var{n} in set @var{p}. - @item FD_CLR(n, p) - Clear member @var{n} in set @var{p}. - @item FD_ISSET(n, p) - Return the value of member @var{n} in set @var{p}. - @end table - - The @var{timeout} value may be a NULL pointer (no timeout), a pointer - to a zero-value structure (poll mode), or a pointer to an - interval-filled structure (timeout). - - @subheading Return Value - The number of files ready. The input sets are replaced with sets that - describe which files are ready for which operations. - - @end txh - */ - int ready; fd_set oread, owrite, oexcept; --- 104,107 ----- struct timeval *timeout) { int ready; fd_set oread, owrite, oexcept; *************** *** 147,152 ready++, FD_SET(i, &oread); } ! /* else if ((ioctl_result = fd_input_ready (i)) == -1) ! return -1; */ else if (ioctl_result) ready++, FD_SET (i, &oread); --- 155,160 ----- ready++, FD_SET(i, &oread); } ! else if ((ioctl_result = fd_input_ready (i)) == -1) ! return -1; else if (ioctl_result) ready++, FD_SET (i, &oread); *************** *** 159,164 ready++, FD_SET(i, &owrite); } ! /* else if ((ioctl_result = fd_output_ready (i)) == -1) ! return -1;*/ else if (ioctl_result) ready++, FD_SET (i, &owrite); --- 167,172 ----- ready++, FD_SET(i, &owrite); } ! else if ((ioctl_result = fd_output_ready (i)) == -1) ! return -1; else if (ioctl_result) ready++, FD_SET (i, &owrite); --=====================_874721764==_ Content-Type: text/plain; charset="us-ascii" --=====================_874721764==_--