From 6f010ddf87ce99aeef6aec1a1f79603773c43090 Mon Sep 17 00:00:00 2001 From: Olaf Barthel Date: Fri, 1 Apr 2005 18:46:37 +0000 Subject: [PATCH] - File descriptors produced by dup() or dup2() now work exactly like the original file descriptors they are duplicates of. I modified the function which maps file descriptor numbers to file descriptor table entries to return the table entries of the original files. - In the thread-safe library, duplicated stdin/stdout/stderr descriptors now work like the "real" ones. This is true even if the "real" ones were closed and only their former aliases remain. git-svn-id: file:///Users/olsen/Code/migration-svn-zu-git/logical-line-staging/clib2/trunk@14909 87f5fb63-7c3d-0410-a384-fd976d0f7a62 --- library/changes | 9 +++ library/fcntl_close.c | 6 +- library/fcntl_lock.c | 12 +--- library/mount_fstatfs.c | 4 +- library/signal_raise.c | 6 +- library/socket_select.c | 10 ++-- library/stat_fchmod.c | 4 +- library/stdio_fdhookentry.c | 90 ++++++++++++++++------------- library/stdio_file_init.c | 12 ++-- library/stdio_get_file_descriptor.c | 42 +++++++++++++- library/stdio_grow_file.c | 4 +- library/stdio_iobhookentry.c | 10 +++- library/stdio_protos.h | 3 +- library/stdio_record_locking.c | 3 +- library/stdio_remove_fd_alias.c | 12 +++- library/stdlib_main.c | 11 ++-- library/unistd_fchown.c | 4 +- library/unistd_ftruncate.c | 4 +- library/unistd_sync_fd.c | 4 +- 19 files changed, 155 insertions(+), 95 deletions(-) diff --git a/library/changes b/library/changes index b2f3c4b..935e76d 100644 --- a/library/changes +++ b/library/changes @@ -20,6 +20,15 @@ - Simplified the library/open close code in "stdlib_main.c". +- File descriptors produced by dup() or dup2() now work exactly like + the original file descriptors they are duplicates of. I modified the + function which maps file descriptor numbers to file descriptor + table entries to return the table entries of the original files. + +- In the thread-safe library, duplicated stdin/stdout/stderr + descriptors now work like the "real" ones. This is true even if + the "real" ones were closed and only their former aliases remain. + c.lib 1.190 (25.3.2005) diff --git a/library/fcntl_close.c b/library/fcntl_close.c index be51c9f..4abe3df 100644 --- a/library/fcntl_close.c +++ b/library/fcntl_close.c @@ -1,5 +1,5 @@ /* - * $Id: fcntl_close.c,v 1.10 2005-02-20 15:46:52 obarthel Exp $ + * $Id: fcntl_close.c,v 1.11 2005-04-01 18:46:37 obarthel Exp $ * * :ts=4 * @@ -59,7 +59,9 @@ close(int file_descriptor) if(__check_abort_enabled) __check_abort(); - fd = __get_file_descriptor(file_descriptor); + /* We want to affect this very file descriptor and not the + original one associated with an alias of it. */ + fd = __get_file_descriptor_dont_resolve(file_descriptor); if(fd == NULL) { __set_errno(EBADF); diff --git a/library/fcntl_lock.c b/library/fcntl_lock.c index 0d25f32..1584e91 100644 --- a/library/fcntl_lock.c +++ b/library/fcntl_lock.c @@ -1,5 +1,5 @@ /* - * $Id: fcntl_lock.c,v 1.2 2005-03-12 09:43:47 obarthel Exp $ + * $Id: fcntl_lock.c,v 1.3 2005-04-01 18:46:37 obarthel Exp $ * * :ts=4 * @@ -44,11 +44,6 @@ void __fd_lock(struct fd * fd) { - /* If this descriptor is really an alias, use the semaphore - associated with the original instead. */ - if(fd != NULL && fd->fd_Original != NULL) - fd = fd->fd_Original; - if(fd != NULL && fd->fd_Lock != NULL) ObtainSemaphore(fd->fd_Lock); } @@ -58,11 +53,6 @@ __fd_lock(struct fd * fd) void __fd_unlock(struct fd * fd) { - /* If this descriptor is really an alias, use the semaphore - associated with the original instead. */ - if(fd != NULL && fd->fd_Original != NULL) - fd = fd->fd_Original; - if(fd != NULL && fd->fd_Lock != NULL) ReleaseSemaphore(fd->fd_Lock); } diff --git a/library/mount_fstatfs.c b/library/mount_fstatfs.c index d3f3e28..04ec23f 100644 --- a/library/mount_fstatfs.c +++ b/library/mount_fstatfs.c @@ -1,5 +1,5 @@ /* - * $Id: mount_fstatfs.c,v 1.9 2005-03-07 11:16:43 obarthel Exp $ + * $Id: mount_fstatfs.c,v 1.10 2005-04-01 18:46:37 obarthel Exp $ * * :ts=4 * @@ -97,7 +97,7 @@ fstatfs(int file_descriptor, struct statfs *buf) goto out; } - if(fd->fd_DefaultFile == ZERO) + if(FLAG_IS_SET(fd->fd_Flags,FDF_STDIO)) { __set_errno(EBADF); goto out; diff --git a/library/signal_raise.c b/library/signal_raise.c index 28c594b..94befc0 100644 --- a/library/signal_raise.c +++ b/library/signal_raise.c @@ -1,5 +1,5 @@ /* - * $Id: signal_raise.c,v 1.6 2005-03-27 10:02:50 obarthel Exp $ + * $Id: signal_raise.c,v 1.7 2005-04-01 18:46:37 obarthel Exp $ * * :ts=4 * @@ -112,10 +112,6 @@ raise(int sig) __print_termination_message(break_string); SHOWMSG("bye, bye..."); - - /* Note that we drop into the exit() function which - does not trigger the exit trap. */ - _exit(EXIT_FAILURE); } /* Drop straight into abort(), which might call signal() diff --git a/library/socket_select.c b/library/socket_select.c index f560f57..28b8faf 100644 --- a/library/socket_select.c +++ b/library/socket_select.c @@ -1,5 +1,5 @@ /* - * $Id: socket_select.c,v 1.9 2005-03-25 08:50:59 obarthel Exp $ + * $Id: socket_select.c,v 1.10 2005-04-01 18:46:37 obarthel Exp $ * * :ts=4 * @@ -309,9 +309,9 @@ map_descriptor_sets( else { /* We only watch files bound to console streams. */ - if(FLAG_IS_CLEAR(fd->fd_Flags,FDF_IS_INTERACTIVE) || fd->fd_DefaultFile == ZERO) + if(FLAG_IS_CLEAR(fd->fd_Flags,FDF_IS_INTERACTIVE) || FLAG_IS_SET(fd->fd_Flags,FDF_STDIO)) { - SHOWMSG("this is a file"); + SHOWMSG("this is a file, or otherwise unsuitable"); continue; } @@ -761,7 +761,7 @@ select(int num_fds,fd_set *read_fds,fd_set *write_fds,fd_set *except_fds,struct { if(FLAG_IS_SET(fd->fd_Flags,FDF_READ)) { - assert( FLAG_IS_CLEAR(fd->fd_Flags,FDF_IS_SOCKET) && fd->fd_DefaultFile != ZERO ); + assert( FLAG_IS_CLEAR(fd->fd_Flags,FDF_IS_SOCKET) && FLAG_IS_CLEAR(fd->fd_Flags,FDF_STDIO) ); /* Does this one have input? */ PROFILE_OFF(); @@ -921,7 +921,7 @@ select(int num_fds,fd_set *read_fds,fd_set *write_fds,fd_set *except_fds,struct { if(FLAG_IS_SET(fd->fd_Flags,FDF_READ)) { - assert( FLAG_IS_CLEAR(fd->fd_Flags,FDF_IS_SOCKET) && fd->fd_DefaultFile != ZERO ); + assert( FLAG_IS_CLEAR(fd->fd_Flags,FDF_IS_SOCKET) && FLAG_IS_CLEAR(fd->fd_Flags,FDF_STDIO) ); PROFILE_OFF(); diff --git a/library/stat_fchmod.c b/library/stat_fchmod.c index 91117ec..37ea156 100644 --- a/library/stat_fchmod.c +++ b/library/stat_fchmod.c @@ -1,5 +1,5 @@ /* - * $Id: stat_fchmod.c,v 1.8 2005-03-07 11:16:43 obarthel Exp $ + * $Id: stat_fchmod.c,v 1.9 2005-04-01 18:46:37 obarthel Exp $ * * :ts=4 * @@ -80,7 +80,7 @@ fchmod(int file_descriptor, mode_t mode) goto out; } - if(fd->fd_DefaultFile == ZERO) + if(FLAG_IS_SET(fd->fd_Flags,FDF_STDIO)) { __set_errno(EBADF); goto out; diff --git a/library/stdio_fdhookentry.c b/library/stdio_fdhookentry.c index cf08846..607e43f 100644 --- a/library/stdio_fdhookentry.c +++ b/library/stdio_fdhookentry.c @@ -1,5 +1,5 @@ /* - * $Id: stdio_fdhookentry.c,v 1.24 2005-03-24 16:40:16 obarthel Exp $ + * $Id: stdio_fdhookentry.c,v 1.25 2005-04-01 18:46:37 obarthel Exp $ * * :ts=4 * @@ -65,6 +65,7 @@ __fd_hook_entry( int new_mode; char * buffer = NULL; int result = -1; + BOOL is_aliased; BPTR file; ENTER(); @@ -74,52 +75,61 @@ __fd_hook_entry( __fd_lock(fd); - file = fd->fd_DefaultFile; - #if defined(__THREAD_SAFE) { /* Check if this file should be dynamically bound to one of the three standard I/O streams. */ - if(file == ZERO && FLAG_IS_SET(fd->fd_Flags,FDF_STDIO)) + if(FLAG_IS_SET(fd->fd_Flags,FDF_STDIO)) { - /* We assume that the file descriptors are organized in the - default layout, i.e. 0 = stdin, 1 = stdout, 2 = stderr. - It might be that the table does not hold more than one - entry, though, hence the __num_fd checks prior to - accessing the table entries. The first test is really - redundant since there has to be at least one file - descriptor table entry around or this function would - not have been invoked in the first place. */ - if (/*__num_fd > STDIN_FILENO &&*/ fd == __fd[STDIN_FILENO]) + switch(fd->fd_DefaultFile) { - file = Input(); - } - else if (__num_fd > STDOUT_FILENO && fd == __fd[STDOUT_FILENO]) - { - file = Output(); - } - else if (__num_fd > STDERR_FILENO && fd == __fd[STDERR_FILENO]) - { - #if defined(__amigaos4__) - { - file = ErrorOutput(); - } - #else - { - struct Process * this_process = (struct Process *)FindTask(NULL); + case STDIN_FILENO: - file = this_process->pr_CES; - } - #endif /* __amigaos4__ */ + file = Input(); + break; + + case STDOUT_FILENO: - /* The following is rather controversial; if the standard error stream - is unavailable, we default to reuse the standard output stream. This - is problematic if the standard output stream was redirected and should - not be the same as the standard error output stream. */ - if(file == ZERO) file = Output(); + break; + + case STDERR_FILENO: + + #if defined(__amigaos4__) + { + file = ErrorOutput(); + } + #else + { + struct Process * this_process = (struct Process *)FindTask(NULL); + + file = this_process->pr_CES; + } + #endif /* __amigaos4__ */ + + /* The following is rather controversial; if the standard error stream + is unavailable, we default to reuse the standard output stream. This + is problematic if the standard output stream was redirected and should + not be the same as the standard error output stream. */ + if(file == ZERO) + file = Output(); + + break; + + default: + + file = ZERO; + break; } } + else + { + file = fd->fd_DefaultFile; + } + } + #else + { + file = fd->fd_DefaultFile; } #endif /* __THREAD_SAFE */ @@ -223,11 +233,12 @@ __fd_hook_entry( result = 0; /* If this is an alias, just remove it. */ - if(__fd_is_aliased(fd)) + is_aliased = __fd_is_aliased(fd); + if(is_aliased) { __remove_fd_alias(fd); } - else if (fd->fd_DefaultFile != ZERO) + else if (FLAG_IS_CLEAR(fd->fd_Flags,FDF_STDIO)) { /* Are we disallowed to close this file? */ if(FLAG_IS_SET(fd->fd_Flags,FDF_NO_CLOSE)) @@ -405,7 +416,8 @@ __fd_hook_entry( #if defined(__THREAD_SAFE) { /* Free the lock semaphore now. */ - __delete_semaphore(fd->fd_Lock); + if(NOT is_aliased) + __delete_semaphore(fd->fd_Lock); } #endif /* __THREAD_SAFE */ diff --git a/library/stdio_file_init.c b/library/stdio_file_init.c index 1372afa..7a76c2f 100644 --- a/library/stdio_file_init.c +++ b/library/stdio_file_init.c @@ -1,5 +1,5 @@ /* - * $Id: stdio_file_init.c,v 1.7 2005-03-24 16:40:16 obarthel Exp $ + * $Id: stdio_file_init.c,v 1.8 2005-04-01 18:46:37 obarthel Exp $ * * :ts=4 * @@ -274,10 +274,10 @@ FILE_CONSTRUCTOR(stdio_file_init) goto out; } - /* We ignore the file handle and let the file I/O code - in the fd hook pick up the appropriate Input/Output/ErrorOutput - handle. */ - default_file = ZERO; + /* We ignore the file handle and let the file I/O + code in the fd hook pick up the appropriate + Input/Output/ErrorOutput handle. */ + default_file = i; fd_flags |= FDF_NO_CLOSE | FDF_STDIO; } @@ -364,7 +364,7 @@ FILE_CONSTRUCTOR(stdio_file_init) PROFILE_OFF(); /* Figure out if the standard error stream is bound to a console. */ - if(__fd[STDERR_FILENO]->fd_DefaultFile != ZERO) + if(FLAG_IS_CLEAR(__fd[STDERR_FILENO]->fd_Flags,FDF_STDIO)) { if(IsInteractive(__fd[STDERR_FILENO]->fd_DefaultFile)) SET_FLAG(__fd[STDERR_FILENO]->fd_Flags,FDF_IS_INTERACTIVE); diff --git a/library/stdio_get_file_descriptor.c b/library/stdio_get_file_descriptor.c index 9915ab0..cd7c74f 100644 --- a/library/stdio_get_file_descriptor.c +++ b/library/stdio_get_file_descriptor.c @@ -1,5 +1,5 @@ /* - * $Id: stdio_get_file_descriptor.c,v 1.3 2005-02-27 21:58:21 obarthel Exp $ + * $Id: stdio_get_file_descriptor.c,v 1.4 2005-04-01 18:46:37 obarthel Exp $ * * :ts=4 * @@ -37,8 +37,16 @@ /****************************************************************************/ -struct fd * -__get_file_descriptor(int file_descriptor) +enum resolution_mode_t +{ + resolution_mode_exact, /* Return the descriptor exactly as it is. */ + resolution_mode_alias /* Resolve the descriptor's alias, if necessary. */ +}; + +/****************************************************************************/ + +STATIC struct fd * +get_file_descriptor(int file_descriptor,enum resolution_mode_t resolution_mode) { struct fd * result = NULL; struct fd * fd; @@ -64,6 +72,10 @@ __get_file_descriptor(int file_descriptor) goto out; } + /* Move up to the original file, if this is an alias. */ + if(resolution_mode == resolution_mode_alias && fd->fd_Original != NULL) + fd = fd->fd_Original; + result = fd; out: @@ -72,3 +84,27 @@ __get_file_descriptor(int file_descriptor) return(result); } + +/****************************************************************************/ + +struct fd * +__get_file_descriptor(int file_descriptor) +{ + struct fd * result; + + result = get_file_descriptor(file_descriptor,resolution_mode_alias); + + return(result); +} + +/****************************************************************************/ + +struct fd * +__get_file_descriptor_dont_resolve(int file_descriptor) +{ + struct fd * result; + + result = get_file_descriptor(file_descriptor,resolution_mode_exact); + + return(result); +} diff --git a/library/stdio_grow_file.c b/library/stdio_grow_file.c index 954475b..0c231d7 100644 --- a/library/stdio_grow_file.c +++ b/library/stdio_grow_file.c @@ -1,5 +1,5 @@ /* - * $Id: stdio_grow_file.c,v 1.2 2005-03-14 10:03:06 obarthel Exp $ + * $Id: stdio_grow_file.c,v 1.3 2005-04-01 18:46:37 obarthel Exp $ * * :ts=4 * @@ -67,6 +67,8 @@ __grow_file_size(struct fd * fd,int num_bytes) PROFILE_OFF(); + assert( FLAG_IS_CLEAR(fd->fd_Flags,FDF_STDIO) ); + fh = BADDR(fd->fd_DefaultFile); if(fh != NULL && fh->fh_Type != NULL && DoPkt(fh->fh_Type,ACTION_DISK_INFO,MKBADDR(id),0,0,0,0)) block_size = id->id_BytesPerBlock; diff --git a/library/stdio_iobhookentry.c b/library/stdio_iobhookentry.c index c442f3c..f7238ea 100644 --- a/library/stdio_iobhookentry.c +++ b/library/stdio_iobhookentry.c @@ -1,5 +1,5 @@ /* - * $Id: stdio_iobhookentry.c,v 1.4 2005-02-21 16:09:41 obarthel Exp $ + * $Id: stdio_iobhookentry.c,v 1.5 2005-04-01 18:46:37 obarthel Exp $ * * :ts=4 * @@ -58,7 +58,13 @@ __iob_hook_entry( assert( __fd[file_iob->iob_Descriptor] != NULL ); assert( FLAG_IS_SET(__fd[file_iob->iob_Descriptor]->fd_Flags,FDF_IN_USE) ); - fd = __get_file_descriptor(file_iob->iob_Descriptor); + /* When closing, we want to affect this very file descriptor + and not the original one associated with an alias of it. */ + if(fam->fam_Action == file_action_close) + fd = __get_file_descriptor_dont_resolve(file_iob->iob_Descriptor); + else + fd = __get_file_descriptor(file_iob->iob_Descriptor); + if(fd == NULL) { fam->fam_Error = EBADF; diff --git a/library/stdio_protos.h b/library/stdio_protos.h index e727df4..0637393 100644 --- a/library/stdio_protos.h +++ b/library/stdio_protos.h @@ -1,5 +1,5 @@ /* - * $Id: stdio_protos.h,v 1.16 2005-03-20 11:18:06 obarthel Exp $ + * $Id: stdio_protos.h,v 1.17 2005-04-01 18:46:37 obarthel Exp $ * * :ts=4 * @@ -84,6 +84,7 @@ extern int __translate_access_io_error_to_errno(LONG io_error); /* stdio_get_file_descriptor.c */ extern struct fd * __get_file_descriptor(int file_descriptor); +extern struct fd * __get_file_descriptor_dont_resolve(int file_descriptor); /****************************************************************************/ diff --git a/library/stdio_record_locking.c b/library/stdio_record_locking.c index 6156990..1d3248f 100644 --- a/library/stdio_record_locking.c +++ b/library/stdio_record_locking.c @@ -1,5 +1,5 @@ /* - * $Id: stdio_record_locking.c,v 1.8 2005-03-26 10:53:35 obarthel Exp $ + * $Id: stdio_record_locking.c,v 1.9 2005-04-01 18:46:37 obarthel Exp $ * * :ts=4 * @@ -772,6 +772,7 @@ __handle_record_locking(int cmd,struct flock * l,struct fd * fd,int * error_ptr) assert( F_RDLCK <= l->l_type && l->l_type <= F_WRLCK ); assert( SEEK_SET <= l->l_whence && l->l_whence <= SEEK_END ); assert( error_ptr != NULL ); + assert( FLAG_IS_CLEAR(fd->fd_Flags,FDF_STDIO) ); /* Remember to unlock any records before closing the file. */ fd->fd_Cleanup = cleanup_locked_records; diff --git a/library/stdio_remove_fd_alias.c b/library/stdio_remove_fd_alias.c index 757b644..e13deb0 100644 --- a/library/stdio_remove_fd_alias.c +++ b/library/stdio_remove_fd_alias.c @@ -1,5 +1,5 @@ /* - * $Id: stdio_remove_fd_alias.c,v 1.2 2005-02-28 13:22:53 obarthel Exp $ + * $Id: stdio_remove_fd_alias.c,v 1.3 2005-04-01 18:46:37 obarthel Exp $ * * :ts=4 * @@ -66,14 +66,22 @@ __remove_fd_alias(struct fd * fd) else if (fd->fd_NextLink != NULL) /* this one has aliases attached; it is the 'original' resource */ { struct fd * first_alias; + struct fd * next_alias; struct fd * list_fd; /* The first link now becomes the original resource */ first_alias = fd->fd_NextLink; + next_alias = first_alias->fd_NextLink; + + /* Structure copy... */ + (*first_alias) = (*fd); + + /* Fix up the linkage. */ + first_alias->fd_NextLink = next_alias; first_alias->fd_Original = NULL; /* The resources are migrated to the first link. */ - for(list_fd = first_alias->fd_NextLink ; + for(list_fd = next_alias ; list_fd != NULL ; list_fd = list_fd->fd_NextLink) { diff --git a/library/stdlib_main.c b/library/stdlib_main.c index 1d9e3af..448a219 100644 --- a/library/stdlib_main.c +++ b/library/stdlib_main.c @@ -1,5 +1,5 @@ /* - * $Id: stdlib_main.c,v 1.21 2005-03-30 19:37:43 obarthel Exp $ + * $Id: stdlib_main.c,v 1.22 2005-04-01 18:46:37 obarthel Exp $ * * :ts=4 * @@ -98,6 +98,9 @@ call_main(void) /* Switch off function name printing, if it was enabled. */ __hide_profile_names(); + /* From this point on, don't worry about ^C checking any more. */ + __check_abort_enabled = FALSE; + /* If we end up here with the __stack_overflow variable set then the stack overflow handler dropped into longjmp() and _exit() did not get called. This @@ -107,12 +110,6 @@ call_main(void) { SHOWMSG("we have a stack overflow"); - /* Dump whatever is waiting to be written to the - standard I/O streams, and make sure that no - break signal is about to make things any more - complicated than they already are. */ - __check_abort_enabled = FALSE; - /* Dump all currently unwritten data, especially to the console. */ __flush_all_files(-1); diff --git a/library/unistd_fchown.c b/library/unistd_fchown.c index f5d3572..051ce97 100644 --- a/library/unistd_fchown.c +++ b/library/unistd_fchown.c @@ -1,5 +1,5 @@ /* - * $Id: unistd_fchown.c,v 1.8 2005-03-07 11:16:43 obarthel Exp $ + * $Id: unistd_fchown.c,v 1.9 2005-04-01 18:46:37 obarthel Exp $ * * :ts=4 * @@ -80,7 +80,7 @@ fchown(int file_descriptor, uid_t owner, gid_t group) goto out; } - if(fd->fd_DefaultFile == ZERO) + if(FLAG_IS_SET(fd->fd_Flags,FDF_STDIO)) { __set_errno(EBADF); goto out; diff --git a/library/unistd_ftruncate.c b/library/unistd_ftruncate.c index 7e368bd..6ab0962 100644 --- a/library/unistd_ftruncate.c +++ b/library/unistd_ftruncate.c @@ -1,5 +1,5 @@ /* - * $Id: unistd_ftruncate.c,v 1.9 2005-03-16 09:28:37 obarthel Exp $ + * $Id: unistd_ftruncate.c,v 1.10 2005-04-01 18:46:37 obarthel Exp $ * * :ts=4 * @@ -80,7 +80,7 @@ ftruncate(int file_descriptor, off_t length) goto out; } - if(fd->fd_DefaultFile == ZERO) + if(FLAG_IS_SET(fd->fd_Flags,FDF_STDIO)) { __set_errno(EBADF); goto out; diff --git a/library/unistd_sync_fd.c b/library/unistd_sync_fd.c index a68d5f6..64df52b 100644 --- a/library/unistd_sync_fd.c +++ b/library/unistd_sync_fd.c @@ -1,5 +1,5 @@ /* - * $Id: unistd_sync_fd.c,v 1.4 2005-03-07 11:58:50 obarthel Exp $ + * $Id: unistd_sync_fd.c,v 1.5 2005-04-01 18:46:37 obarthel Exp $ * * :ts=4 * @@ -62,7 +62,7 @@ __sync_fd(struct fd * fd,int mode) goto out; } - if(fd->fd_DefaultFile == ZERO) + if(FLAG_IS_SET(fd->fd_Flags,FDF_STDIO)) { __set_errno(EBADF); goto out;