Date: Tue, 11 Jun 2002 12:13:08 +0100 From: "Richard Dawe" Sender: rich AT phekda DOT freeserve DOT co DOT uk To: djgpp-workers AT delorie DOT com X-Mailer: Emacs 21.3.50 (via feedmail 8.3.emacs20_6 I) and Blat ver 1.8.6 Subject: /dev/zero, /dev/full: Bugfixes, add support for llseek, fchown Message-Id: Reply-To: djgpp-workers AT delorie DOT com Hello. Below is a patch that does the following for /dev/zero and /dev/full: * Some FSEXT functions that take file descriptors did not check that the file descriptor was valid, before using it: ioctl, lseek (IIRC). This has been fixed. * Support for llseek has been added. This works like lseek. * Support for fchown has been added. This works like fchown does on regular files - it always succeeds. OK to commit? Thanks, bye, Rich =] Index: src/libc/fsext/fse_zero.c =================================================================== RCS file: /cvs/djgpp/djgpp/src/libc/fsext/fse_zero.c,v retrieving revision 1.1 diff -p -u -3 -r1.1 fse_zero.c --- src/libc/fsext/fse_zero.c 2002/02/08 21:22:54 1.1 +++ src/libc/fsext/fse_zero.c 2002/06/11 11:03:11 @@ -176,22 +176,26 @@ match_dev_path (const char *filename, co static int dev_fsext (__FSEXT_Fnumber n, int *rv, va_list args) { - int emul = 0; /* Emulated call? 1 => yes, 0 = no. */ - int fd = 0; - DEV_DATA *data = NULL; - char *filename = NULL; - int open_mode = 0; - int perm = 0; - mode_t creat_mode = 0; - void *buf = NULL; - size_t buflen = 0; - off_t offset = 0; - int whence = 0; - struct stat *sbuf = NULL; - int cmd = 0; - int iparam = 0; + int emul = 0; /* Emulated call? 1 => yes, 0 = no. */ + int fd = 0; + DEV_DATA *data = NULL; + char *filename = NULL; + char *new_filename = NULL; + int open_mode = 0; + int perm = 0; + mode_t creat_mode = 0; + void *buf = NULL; + size_t buflen = 0; + off_t offset = 0; + offset_t lloffset = 0; + uid_t owner = 0; + gid_t group = 0; + int whence = 0; + struct stat *sbuf = NULL; + int cmd = 0; + int iparam = 0; #ifdef DJGPP_SUPPORTS_FIONBIO_NOW - int *piparam = NULL; + int *piparam = NULL; #endif /* DJGPP_SUPPORTS_FIONBIO_NOW */ switch(n) { @@ -478,6 +482,14 @@ dev_fsext (__FSEXT_Fnumber n, int *rv, v /* This must be emulated, since the FSEXT has been called. */ emul = 1; + /* Get context */ + data = (DEV_DATA *) __FSEXT_get_data(fd); + if (data == NULL) { + errno = EBADF; + *rv = -1; + break; + } + switch(cmd) { /* */ #ifdef DJGPP_SUPPORTS_FIONBIO_NOW @@ -502,15 +514,68 @@ dev_fsext (__FSEXT_Fnumber n, int *rv, v case __FSEXT_lseek: fd = va_arg(args, int); offset = va_arg(args, off_t); - whence = va_arg(args, int); + whence = va_arg(args, int); + + /* This must be emulated, since the FSEXT has been called. */ + emul = 1; + + /* Get context */ + data = (DEV_DATA *) __FSEXT_get_data(fd); + if (data == NULL) { + errno = EBADF; + *rv = -1; + break; + } + + /* Seek is meaningless */ + *rv = 0; + break; + + case __FSEXT_llseek: + fd = va_arg(args, int); + lloffset = va_arg(args, offset_t); + whence = va_arg(args, int); + + /* This must be emulated, since the FSEXT has been called. */ + emul = 1; + + /* Get context */ + data = (DEV_DATA *) __FSEXT_get_data(fd); + if (data == NULL) { + errno = EBADF; + *rv = -1; + break; + } + + /* Seek is meaningless */ + *rv = 0; + break; + case __FSEXT_fchown: + fd = va_arg(args, int); + owner = va_arg(args, uid_t); + group = va_arg(args, gid_t); + /* This must be emulated, since the FSEXT has been called. */ emul = 1; + /* Get context */ + data = (DEV_DATA *) __FSEXT_get_data(fd); + if (data == NULL) { + errno = EBADF; + *rv = -1; + break; + } + + /* Behave like fchown() does on a regular file - succeed whatever + * the uid, gid are. */ *rv = 0; break; case __FSEXT_link: + filename = va_arg(args, char *); + new_filename = va_arg(args, char *); + /* This must be emulated, since the FSEXT has been called. */ emul = 1; @@ -518,8 +583,10 @@ dev_fsext (__FSEXT_Fnumber n, int *rv, v errno = EPERM; *rv = -1; break; + + case __FSEXT_unlink: + filename = va_arg(args, char *); - case __FSEXT_unlink: /* This must be emulated, since the FSEXT has been called. */ emul = 1; @@ -534,6 +601,14 @@ dev_fsext (__FSEXT_Fnumber n, int *rv, v /* This must be emulated, since the FSEXT has been called. */ emul = 1; + + /* Get context */ + data = (DEV_DATA *) __FSEXT_get_data(fd); + if (data == NULL) { + errno = EBADF; + *rv = -1; + break; + } /* Done */ *rv = internal_dup(fd); Index: tests/libc/fsext/tzero.c =================================================================== RCS file: /cvs/djgpp/djgpp/tests/libc/fsext/tzero.c,v retrieving revision 1.1 diff -p -u -3 -r1.1 tzero.c --- tests/libc/fsext/tzero.c 2002/02/08 21:22:54 1.1 +++ tests/libc/fsext/tzero.c 2002/06/11 11:03:11 @@ -108,15 +108,20 @@ main (int argc, char *argv[]) { char buf[32768]; char filename[PATH_MAX]; - int fd = 0; - int new_fd = 0; + int fd = 0; + int new_fd = 0; fd_set readfds, writefds; struct timeval tv; struct stat sbuf; - off_t offset = 0; - off_t ret_offset = 0; - int n = 0; - size_t i = 0; + off_t offset = 0; + offset_t lloffset = 0; + off_t ret_offset = 0; + offset_t ret_lloffset = 0; + uid_t owner = 0; + gid_t group = 0; + int ret = 0; + int n = 0; + size_t i = 0; if (!__install_dev_zero()) { fprintf(stderr, "__install_dev_zero() failed\n"); @@ -386,6 +391,62 @@ main (int argc, char *argv[]) close(fd); + /* - Check llseek() - */ + fd = open(DEV_ZERO_PATH, O_RDWR); + if (fd == -1) { + fprintf(stderr, + "Unable to open %s: %s\n", DEV_ZERO_PATH, strerror(errno)); + return(EXIT_FAILURE); + } + + for (i = 0; i < 1000; i++) { + lloffset = (offset_t) random(); + ret_lloffset = llseek(fd, offset, SEEK_SET); + + if (ret_lloffset < 0) + fprintf(stderr, "llseek() to position %Lu failed\n", lloffset); + } + + close(fd); + + /* - Check fchown() - */ + + /* fchown() should behave the same way for /dev/zero as it does for + * regular files - it should always succeed. */ + fd = open(DEV_ZERO_PATH, O_RDWR); + if (fd == -1) { + fprintf(stderr, + "Unable to open %s: %s\n", DEV_ZERO_PATH, strerror(errno)); + return(EXIT_FAILURE); + } + + /* Try the current uid, gid. */ + owner = getuid(); + group = getgid(); + + ret = fchown(fd, owner, group); + if (ret < 0) { + fprintf(stderr, + "fchown() on %s failed unexpectedly, when changing ownership " + "to current owner: %s\n", DEV_ZERO_PATH, strerror(errno)); + close(fd); + return(EXIT_FAILURE); + } + + /* Try a non-existent uid, gid. */ + owner *= 2, group *= 2; + + ret = fchown(fd, owner, group); + if (ret < 0) { + fprintf(stderr, + "fchown() on %s failed unexpectedly, when changing ownership: " + "%s\n", DEV_ZERO_PATH, strerror(errno)); + close(fd); + return(EXIT_FAILURE); + } + + close(fd); + /* - Check dup works - */ #ifdef DJGPP_SUPPORTS_FSEXT_DUP_NOW fd = open(DEV_ZERO_PATH, O_RDWR); @@ -532,6 +593,9 @@ main (int argc, char *argv[]) /* - Check fstat() works - */ test_fstat(DEV_ZERO_PATH); test_fstat(DEV_FULL_PATH); + + /* Success!*/ + printf("SUCCESS\n"); return(EXIT_SUCCESS); }