From 966851e8bd2d95168727fd39af699572fc42cdeb Mon Sep 17 00:00:00 2001 From: Olaf Barthel Date: Mon, 14 Mar 2005 10:03:06 +0000 Subject: [PATCH] - ftruncate() ended up changing the current file position, contrary to what it is supposed to do. Fixed. git-svn-id: file:///Users/olsen/Code/migration-svn-zu-git/logical-line-staging/clib2/trunk@14888 87f5fb63-7c3d-0410-a384-fd976d0f7a62 --- library/changes | 3 + library/stdio_fdhookentry.c | 33 ++++++---- library/stdio_grow_file.c | 7 ++- library/unistd_ftruncate.c | 116 +++++++++++++++++++++++++----------- 4 files changed, 109 insertions(+), 50 deletions(-) diff --git a/library/changes b/library/changes index f7b07ce..13017e6 100644 --- a/library/changes +++ b/library/changes @@ -91,6 +91,9 @@ entire library constructor/destructor functionality to use the same approach as libnix. +- ftruncate() ended up changing the current file position, contrary + to what it is supposed to do. Fixed. + c.lib 1.189 (5.3.2005) diff --git a/library/stdio_fdhookentry.c b/library/stdio_fdhookentry.c index 34be47c..8de90ef 100644 --- a/library/stdio_fdhookentry.c +++ b/library/stdio_fdhookentry.c @@ -1,5 +1,5 @@ /* - * $Id: stdio_fdhookentry.c,v 1.21 2005-03-12 09:49:47 obarthel Exp $ + * $Id: stdio_fdhookentry.c,v 1.22 2005-03-14 10:03:06 obarthel Exp $ * * :ts=4 * @@ -151,17 +151,28 @@ __fd_hook_entry( if(FLAG_IS_SET(fd->fd_Flags,FDF_APPEND)) { + LONG position; + SHOWMSG("appending data"); PROFILE_OFF(); - if(Seek(file,0,OFFSET_END) >= 0) + position = Seek(file,0,OFFSET_END); + if(position >= 0) { if(FLAG_IS_SET(fd->fd_Flags,FDF_CACHE_POSITION)) fd->fd_Position = Seek(file,0,OFFSET_CURRENT); } PROFILE_ON(); + + if(position < 0) + { + D(("seek to end of file failed; ioerr=%ld",IoErr())); + + fam->fam_Error = __translate_io_error_to_errno(IoErr()); + goto out; + } } D(("write %ld bytes to position %ld from 0x%08lx",fam->fam_Size,Seek(file,0,OFFSET_CURRENT),fam->fam_Data)); @@ -349,6 +360,8 @@ __fd_hook_entry( old_dir = CurrentDir(parent_dir); + /* ZZZ we probably ought to observe the current umask settings. */ + flags = fib->fib_Protection ^ (FIBF_READ|FIBF_WRITE|FIBF_EXECUTE|FIBF_DELETE); CLEAR_FLAG(flags,FIBF_EXECUTE); @@ -454,18 +467,14 @@ __fd_hook_entry( #if defined(UNIX_PATH_SEMANTICS) { - if(NOT fib_is_valid && CANNOT __safe_examine_file_handle(file,fib)) - { - fam->fam_Error = __translate_io_error_to_errno(IoErr()); + /* Check if this operation failed because the file is shorter than + the new file position. First, we need to find out if the file + is really shorter than required. If not, then it must have + been a different error. */ + if((NOT fib_is_valid && CANNOT __safe_examine_file_handle(file,fib)) || (new_position <= fib->fib_Size)) goto out; - } - - if(new_position <= fib->fib_Size) - { - fam->fam_Error = __translate_io_error_to_errno(IoErr()); - goto out; - } + /* Now try to make that file larger. */ if(__grow_file_size(fd,new_position - fib->fib_Size) < 0) { fam->fam_Error = __translate_io_error_to_errno(IoErr()); diff --git a/library/stdio_grow_file.c b/library/stdio_grow_file.c index bf221cc..954475b 100644 --- a/library/stdio_grow_file.c +++ b/library/stdio_grow_file.c @@ -1,5 +1,5 @@ /* - * $Id: stdio_grow_file.c,v 1.1 2005-02-18 18:53:16 obarthel Exp $ + * $Id: stdio_grow_file.c,v 1.2 2005-03-14 10:03:06 obarthel Exp $ * * :ts=4 * @@ -41,7 +41,8 @@ /****************************************************************************/ -/* Seek to the end of a file, then add a certain number of 0 bytes. */ +/* Seek to the end of a file, then add a certain number of 0 bytes. Note that + this function will change the current file position! */ int __grow_file_size(struct fd * fd,int num_bytes) { @@ -104,7 +105,7 @@ __grow_file_size(struct fd * fd,int num_bytes) position = Seek(fd->fd_DefaultFile,0,OFFSET_END); PROFILE_ON(); - if(position == -1) + if(position < 0) { SHOWMSG("could not move to the end of the file"); goto out; diff --git a/library/unistd_ftruncate.c b/library/unistd_ftruncate.c index 53423f6..dbf06de 100644 --- a/library/unistd_ftruncate.c +++ b/library/unistd_ftruncate.c @@ -1,5 +1,5 @@ /* - * $Id: unistd_ftruncate.c,v 1.7 2005-03-07 11:16:43 obarthel Exp $ + * $Id: unistd_ftruncate.c,v 1.8 2005-03-14 10:03:06 obarthel Exp $ * * :ts=4 * @@ -47,7 +47,9 @@ ftruncate(int file_descriptor, off_t length) D_S(struct FileInfoBlock,fib); int result = -1; struct fd * fd = NULL; - long int position; + BOOL restore_initial_position = FALSE; + off_t current_file_size; + off_t initial_position = -1; BOOL success; ENTER(); @@ -62,6 +64,8 @@ ftruncate(int file_descriptor, off_t length) if(__check_abort_enabled) __check_abort(); + PROFILE_OFF(); + fd = __get_file_descriptor(file_descriptor); if(fd == NULL) { @@ -101,11 +105,7 @@ ftruncate(int file_descriptor, off_t length) goto out; } - /* Remember where we started. */ - position = lseek(file_descriptor,0,SEEK_CUR); - if(position < 0) - goto out; - + /* Figure out how large the file is right now. */ if(CANNOT __safe_examine_file_handle(fd->fd_DefaultFile,fib)) { SHOWMSG("couldn't examine file"); @@ -114,47 +114,93 @@ ftruncate(int file_descriptor, off_t length) goto out; } - PROFILE_OFF(); + current_file_size = fib->fib_Size; - if(length < fib->fib_Size) + /* Is the file to be made shorter than it is right now? */ + if(length < current_file_size) { + /* Remember where we started. */ + if(initial_position < 0) + { + initial_position = Seek(fd->fd_DefaultFile,0,OFFSET_CURRENT); + if(initial_position < 0) + goto out; + } + /* Careful: seek to a position where the file can be safely truncated. */ - success = (Seek(fd->fd_DefaultFile,length,OFFSET_BEGINNING) != -1 && SetFileSize(fd->fd_DefaultFile,length,OFFSET_BEGINNING) != -1); + if(Seek(fd->fd_DefaultFile,length,OFFSET_BEGINNING) < 0) + { + D(("could not move to file offset %ld",length)); + + __set_errno(__translate_io_error_to_errno(IoErr())); + goto out; + } + + if(SetFileSize(fd->fd_DefaultFile,length,OFFSET_BEGINNING) < 0) + { + D(("could not reduce file to size %ld",length)); + + __set_errno(__translate_io_error_to_errno(IoErr())); + goto out; + } + + /* If the file is now shorter than the file position, which must + not be changed by a call to ftruncate(), extend the file again, + filling the extension with 0 bytes. */ + if(initial_position > length) + { + current_file_size = length; + + length = initial_position; + } + + restore_initial_position = TRUE; } - else if (length > fib->fib_Size) + + /* Is the size of the file to grow? */ + if(length > current_file_size) { - success = (Seek(fd->fd_DefaultFile,fib->fib_Size,OFFSET_BEGINNING) != -1 && __grow_file_size(fd,length - fib->fib_Size) == OK); + /* Remember where we started. */ + if(initial_position < 0) + { + initial_position = Seek(fd->fd_DefaultFile,0,OFFSET_CURRENT); + if(initial_position < 0) + goto out; + } + + /* Move to what should be the end of the file. */ + if(Seek(fd->fd_DefaultFile,current_file_size,OFFSET_BEGINNING) < 0) + { + D(("could not move to file offset %ld",current_file_size)); + + __set_errno(__translate_io_error_to_errno(IoErr())); + goto out; + } + + /* Add as many bytes to the end of the file as are required + to make it as large as requested. */ + if(__grow_file_size(fd,length - current_file_size) != OK) + { + D(("could not extend file to size %ld",length)); + + __set_errno(__translate_io_error_to_errno(IoErr())); + goto out; + } + + restore_initial_position = TRUE; } - else - { - success = TRUE; - } - - PROFILE_ON(); - - if(NO success) - { - int error; - - error = __translate_io_error_to_errno(IoErr()); - - /* Return to the original file position. */ - lseek(file_descriptor,position,SEEK_SET); - - __set_errno(error); - goto out; - } - - /* Return to the original file position. */ - if(lseek(file_descriptor,position,SEEK_SET) < 0) - goto out; result = 0; out: + if(restore_initial_position) + Seek(fd->fd_DefaultFile,initial_position,OFFSET_CURRENT); + __fd_unlock(fd); + PROFILE_ON(); + RETURN(result); return(result); }