diff options
author | Joel Sherrill <joel.sherrill@OARcorp.com> | 2001-08-16 22:20:06 +0000 |
---|---|---|
committer | Joel Sherrill <joel.sherrill@OARcorp.com> | 2001-08-16 22:20:06 +0000 |
commit | dfd218d5fe18569de44bbd00f75773c4f2fe8316 (patch) | |
tree | d53da8a83b02066a06ab3169eff2afc80cd938d0 | |
parent | 2001-08-10 Radzislaw Galler <rgaller@et.put.poznan.pl> (diff) | |
download | rtems-dfd218d5fe18569de44bbd00f75773c4f2fe8316.tar.bz2 |
2001-08-16 Joel Sherrill <joel@OARcorp.com>
* libc/lseek.c: Modified after discussion with Eugeny S. Mints
<jack@oktet.ru> to correct the behavior. There were two mistakes.
First, iop->offset was incorrectly set for SEEK_END. Second,
iop->offset should be left unmodified if there are errors.
This modification attempts to fix both situations.
-rw-r--r-- | c/src/exec/libcsupport/src/lseek.c | 32 | ||||
-rw-r--r-- | c/src/lib/ChangeLog | 8 | ||||
-rw-r--r-- | c/src/lib/libc/lseek.c | 32 | ||||
-rw-r--r-- | cpukit/libcsupport/src/lseek.c | 32 |
4 files changed, 86 insertions, 18 deletions
diff --git a/c/src/exec/libcsupport/src/lseek.c b/c/src/exec/libcsupport/src/lseek.c index 069952ff8e..910b81d231 100644 --- a/c/src/exec/libcsupport/src/lseek.c +++ b/c/src/exec/libcsupport/src/lseek.c @@ -26,15 +26,25 @@ off_t lseek( ) { rtems_libio_t *iop; + off_t old_offset; + off_t status; rtems_libio_check_fd( fd ); iop = rtems_libio_iop( fd ); rtems_libio_check_is_open(iop); /* + * Check as many errors as possible before touching iop->offset. + */ + + if ( !iop->handlers->lseek_h ) + set_errno_and_return_minus_one( ENOTSUP ); + + /* * Now process the lseek(). */ + old_offset = iop->offset; switch ( whence ) { case SEEK_SET: iop->offset = offset; @@ -45,18 +55,28 @@ off_t lseek( break; case SEEK_END: - iop->offset = iop->size - offset; + iop->offset = iop->size + offset; break; default: - errno = EINVAL; - return -1; + set_errno_and_return_minus_one( EINVAL ); } - if ( !iop->handlers->lseek_h ) - set_errno_and_return_minus_one( ENOTSUP ); + /* + * At this time, handlers assume iop->offset has the desired + * new offset. + */ + + status = (*iop->handlers->lseek_h)( iop, offset, whence ); + if ( !status ) + return 0; + + /* + * So if the operation failed, we have to restore iop->offset. + */ - return (*iop->handlers->lseek_h)( iop, offset, whence ); + iop->offset = old_offset; + return status; } /* diff --git a/c/src/lib/ChangeLog b/c/src/lib/ChangeLog index 29727ca717..994617a053 100644 --- a/c/src/lib/ChangeLog +++ b/c/src/lib/ChangeLog @@ -1,3 +1,11 @@ +2001-08-16 Joel Sherrill <joel@OARcorp.com> + + * libc/lseek.c: Modified after discussion with Eugeny S. Mints + <jack@oktet.ru> to correct the behavior. There were two mistakes. + First, iop->offset was incorrectly set for SEEK_END. Second, + iop->offset should be left unmodified if there are errors. + This modification attempts to fix both situations. + 2001-08-16 Mike Siers <mikes@poliac.com> * include/rtems/termiostypes.h, include/sys/ioccom.h: diff --git a/c/src/lib/libc/lseek.c b/c/src/lib/libc/lseek.c index 069952ff8e..910b81d231 100644 --- a/c/src/lib/libc/lseek.c +++ b/c/src/lib/libc/lseek.c @@ -26,15 +26,25 @@ off_t lseek( ) { rtems_libio_t *iop; + off_t old_offset; + off_t status; rtems_libio_check_fd( fd ); iop = rtems_libio_iop( fd ); rtems_libio_check_is_open(iop); /* + * Check as many errors as possible before touching iop->offset. + */ + + if ( !iop->handlers->lseek_h ) + set_errno_and_return_minus_one( ENOTSUP ); + + /* * Now process the lseek(). */ + old_offset = iop->offset; switch ( whence ) { case SEEK_SET: iop->offset = offset; @@ -45,18 +55,28 @@ off_t lseek( break; case SEEK_END: - iop->offset = iop->size - offset; + iop->offset = iop->size + offset; break; default: - errno = EINVAL; - return -1; + set_errno_and_return_minus_one( EINVAL ); } - if ( !iop->handlers->lseek_h ) - set_errno_and_return_minus_one( ENOTSUP ); + /* + * At this time, handlers assume iop->offset has the desired + * new offset. + */ + + status = (*iop->handlers->lseek_h)( iop, offset, whence ); + if ( !status ) + return 0; + + /* + * So if the operation failed, we have to restore iop->offset. + */ - return (*iop->handlers->lseek_h)( iop, offset, whence ); + iop->offset = old_offset; + return status; } /* diff --git a/cpukit/libcsupport/src/lseek.c b/cpukit/libcsupport/src/lseek.c index 069952ff8e..910b81d231 100644 --- a/cpukit/libcsupport/src/lseek.c +++ b/cpukit/libcsupport/src/lseek.c @@ -26,15 +26,25 @@ off_t lseek( ) { rtems_libio_t *iop; + off_t old_offset; + off_t status; rtems_libio_check_fd( fd ); iop = rtems_libio_iop( fd ); rtems_libio_check_is_open(iop); /* + * Check as many errors as possible before touching iop->offset. + */ + + if ( !iop->handlers->lseek_h ) + set_errno_and_return_minus_one( ENOTSUP ); + + /* * Now process the lseek(). */ + old_offset = iop->offset; switch ( whence ) { case SEEK_SET: iop->offset = offset; @@ -45,18 +55,28 @@ off_t lseek( break; case SEEK_END: - iop->offset = iop->size - offset; + iop->offset = iop->size + offset; break; default: - errno = EINVAL; - return -1; + set_errno_and_return_minus_one( EINVAL ); } - if ( !iop->handlers->lseek_h ) - set_errno_and_return_minus_one( ENOTSUP ); + /* + * At this time, handlers assume iop->offset has the desired + * new offset. + */ + + status = (*iop->handlers->lseek_h)( iop, offset, whence ); + if ( !status ) + return 0; + + /* + * So if the operation failed, we have to restore iop->offset. + */ - return (*iop->handlers->lseek_h)( iop, offset, whence ); + iop->offset = old_offset; + return status; } /* |