# Diffed against OAR_orig (ss-20020301) on Sun Nov  3 00:24:13 PST 2002
# T.S.

For more information about this patch consult README (CAVEATS section).

To apply this patch,

chdir to c/src/lib/libc

and issue 

	patch -p0 < this_file

It is always a good idea to try a "dry-run" before applying a patch:

    patch --dry-run -p0 < this_file

Index: Makefile.am
===================================================================
RCS file: /afs/slac/g/spear/cvsrep/rtems/src/c/src/lib/libc/Makefile.am,v
retrieving revision 1.1.1.2
retrieving revision 1.2
diff -c -r1.1.1.2 -r1.2
*** Makefile.am	7 Mar 2002 01:53:46 -0000	1.1.1.2
--- Makefile.am	28 Mar 2002 20:59:16 -0000	1.2
***************
*** 1,5 ****
  ##
! ##  $Id: rtems-filesystem-patch,v 1.1 2002/11/26 20:50:14 till Exp $
  ##
  
  AUTOMAKE_OPTIONS = foreign 1.4
--- 1,5 ----
  ##
! ##  $Id: rtems-filesystem-patch,v 1.1 2002/11/26 20:50:14 till Exp $
  ##
  
  AUTOMAKE_OPTIONS = foreign 1.4
***************
*** 32,37 ****
--- 32,39 ----
  
  MALLOC_C_FILES = malloc.c mallocfreespace.c __brk.c __sbrk.c
  
+ ENVIRON_C_FILES = envlock.c
+ 
  PASSWORD_GROUP_C_FILES = getpwent.c getgrent.c
  
  TERMINAL_IDENTIFICATION_C_FILES = ctermid.c isatty.c ttyname.c ttyname_r.c
***************
*** 42,48 ****
  UNIX_LIBC_C_FILES = unixlibc.c hosterr.c
  
  COMMON_C_FILES = gxx_wrappers.c printk.c $(BASE_FS_C_FILES) \
!     $(MALLOC_C_FILES) $(TERMIOS_C_FILES) $(ERROR_C_FILES) \
      $(ASSOCIATION_C_FILES)
  
  UNIX_C_FILES = $(UNIX_LIBC_C_FILES)
--- 44,50 ----
  UNIX_LIBC_C_FILES = unixlibc.c hosterr.c
  
  COMMON_C_FILES = gxx_wrappers.c printk.c $(BASE_FS_C_FILES) \
!     $(MALLOC_C_FILES) $(ENVIRON_C_FILES) $(TERMIOS_C_FILES) $(ERROR_C_FILES) \
      $(ASSOCIATION_C_FILES)
  
  UNIX_C_FILES = $(UNIX_LIBC_C_FILES)
Index: base_fs.c
===================================================================
RCS file: /afs/slac/g/spear/cvsrep/rtems/src/c/src/lib/libc/base_fs.c,v
retrieving revision 1.1.1.1
diff -c -r1.1.1.1 base_fs.c
*** base_fs.c	14 Dec 2001 22:52:31 -0000	1.1.1.1
--- base_fs.c	26 Oct 2002 02:45:15 -0000
***************
*** 49,54 ****
--- 49,55 ----
    int                                   status;
    rtems_filesystem_mount_table_entry_t *entry;
    rtems_filesystem_mount_table_t       *mt;
+   rtems_filesystem_location_info_t		loc;
    
    /*
     *  Set the default umask to "022".
***************
*** 75,82 ****
      rtems_fatal_error_occurred( 0xABCD0002 );
  
    rtems_filesystem_link_counts = 0;
    rtems_filesystem_root        = entry->mt_fs_root;
!   rtems_filesystem_current     = rtems_filesystem_root;
  
  
    /*
--- 76,113 ----
      rtems_fatal_error_occurred( 0xABCD0002 );
  
    rtems_filesystem_link_counts = 0;
+ 
+   /* setup the 'current' and 'root' directories
+    *
+    * NOTE: cloning the pathlocs is not strictly
+    *       necessary. Since we implicitely let
+    *       all threads that don't call
+    *       libio_set_private_env() share the same
+    *       (initial) 'root' and 'current' locs,
+    *       we (also implicitely) assume that the
+    *       root filesystem doesn't care about
+    *       reference counts.
+    *       I just inserted the code snippet below
+    *       to remind everybody of the fact by
+    *       making it more explicit...
+    *       Ideally, every thread would have to
+    *       call either share_private_env() or
+    *       set_private_env() - but then: that's
+    *       gonna hit performance.
+    *
+    *       Till Straumann, 10/25/2002
+    */
    rtems_filesystem_root        = entry->mt_fs_root;
!   /* Clone the root pathloc */
!   rtems_filesystem_evaluate_path("/", 0, &loc, 0);
!   rtems_filesystem_root        = loc;
!   /* One more clone for the current node */
!   rtems_filesystem_evaluate_path("/", 0, &loc, 0);
!   rtems_filesystem_current     = loc;
! 
!   /* Note: the global_env's refcnt doesn't matter
!    * as the global env is never released
!    */
  
  
    /*
Index: chroot.c
===================================================================
RCS file: /afs/slac/g/spear/cvsrep/rtems/src/c/src/lib/libc/chroot.c,v
retrieving revision 1.1.1.2
diff -c -r1.1.1.2 chroot.c
*** chroot.c	7 Mar 2002 01:53:47 -0000	1.1.1.2
--- chroot.c	29 Oct 2002 03:01:47 -0000
***************
*** 38,51 ****
      rtems_set_errno_and_return_minus_one( ENOTSUP );
    }; 
  
-   loc = rtems_filesystem_root;     /* save the value */
- 
    result = chdir(pathname);
    if (result) {
-     rtems_filesystem_root = loc; /* restore the value */
      rtems_set_errno_and_return_minus_one( errno );
    };
!   rtems_filesystem_root = rtems_filesystem_current;
  
    return 0;
  }
--- 38,53 ----
      rtems_set_errno_and_return_minus_one( ENOTSUP );
    }; 
  
    result = chdir(pathname);
    if (result) {
      rtems_set_errno_and_return_minus_one( errno );
    };
!   /* clone the new root location */
!   if (rtems_filesystem_evaluate_path(".", 0, &loc, 0)) {
!     rtems_set_errno_and_return_minus_one( errno );
!   }
!   rtems_filesystem_freenode(&rtems_filesystem_root);
!   rtems_filesystem_root = loc;
  
    return 0;
  }
Index: eval.c
===================================================================
RCS file: /afs/slac/g/spear/cvsrep/rtems/src/c/src/lib/libc/eval.c,v
retrieving revision 1.1.1.2
retrieving revision 1.2
diff -c -r1.1.1.2 -r1.2
*** eval.c	7 Mar 2002 01:53:48 -0000	1.1.1.2
--- eval.c	29 Oct 2002 21:03:50 -0000	1.2
***************
*** 10,16 ****
   *  found in the file LICENSE in this distribution or at
   *  http://www.OARcorp.com/rtems/license.html.
   *
!  *  $Id: rtems-filesystem-patch,v 1.1 2002/11/26 20:50:14 till Exp $
   */
  
  #if HAVE_CONFIG_H
--- 10,16 ----
   *  found in the file LICENSE in this distribution or at
   *  http://www.OARcorp.com/rtems/license.html.
   *
!  *  $Id: rtems-filesystem-patch,v 1.1 2002/11/26 20:50:14 till Exp $
   */
  
  #if HAVE_CONFIG_H
***************
*** 60,76 ****
  
    if ( (result == 0) && follow_link ) {
  
!     if ( !pathloc->ops->node_type_h )
        rtems_set_errno_and_return_minus_one( ENOTSUP );
  
      type = (*pathloc->ops->node_type_h)( pathloc );
  
      if ( ( type == RTEMS_FILESYSTEM_HARD_LINK ) ||
           ( type == RTEMS_FILESYSTEM_SYM_LINK ) ) {
  
!         if ( !pathloc->ops->eval_link_h )
            rtems_set_errno_and_return_minus_one( ENOTSUP );
  
           result =  (*pathloc->ops->eval_link_h)( pathloc, flags );
   
      }
--- 60,93 ----
  
    if ( (result == 0) && follow_link ) {
  
!     if ( !pathloc->ops->node_type_h ) {
! 	  rtems_filesystem_freenode(pathloc);
        rtems_set_errno_and_return_minus_one( ENOTSUP );
+ 	}
  
      type = (*pathloc->ops->node_type_h)( pathloc );
  
      if ( ( type == RTEMS_FILESYSTEM_HARD_LINK ) ||
           ( type == RTEMS_FILESYSTEM_SYM_LINK ) ) {
  
!         if ( !pathloc->ops->eval_link_h ) {
! 	      rtems_filesystem_freenode(pathloc);
            rtems_set_errno_and_return_minus_one( ENOTSUP );
+ 		}
  
+ 		/* what to do with the valid node pathloc points to
+ 		 * if eval_link_h() fails?
+ 		 * Let the FS implementation deal with this case. It
+ 		 * should probably free pathloc in either case:
+ 		 *   - if the link evaluation fails, it must free the
+ 		 *     original (valid) pathloc because we are going
+ 		 *     to return -1 and hence the FS generics won't
+ 		 *     cleanup pathloc
+ 		 *   - if the link evaluation is successful, the updated
+ 		 *     pathloc will be passed up (and eventually released).
+ 		 *     Hence, the (valid) original node that we submit to 
+ 		 *     eval_link_h() should be released by the handler.
+ 		 */
           result =  (*pathloc->ops->eval_link_h)( pathloc, flags );
   
      }
Index: fchdir.c
===================================================================
RCS file: /afs/slac/g/spear/cvsrep/rtems/src/c/src/lib/libc/fchdir.c,v
retrieving revision 1.1.1.2
diff -c -r1.1.1.2 fchdir.c
*** fchdir.c	7 Mar 2002 01:53:48 -0000	1.1.1.2
--- fchdir.c	25 Oct 2002 23:59:03 -0000
***************
*** 29,34 ****
--- 29,35 ----
  )
  {
    rtems_libio_t *iop;
+   rtems_filesystem_location_info_t loc;
    
    rtems_libio_check_fd( fd );
    iop = rtems_libio_iop( fd );
***************
*** 65,74 ****
     *         this node which we are making here. I can
     *         see the freenode interface but do not see
     *         allocnode node interface. It maybe node_type.
     */
    
    rtems_filesystem_current = iop->pathinfo;
    
    return 0;
  }
- 
--- 66,80 ----
     *         this node which we are making here. I can
     *         see the freenode interface but do not see
     *         allocnode node interface. It maybe node_type.
+    *
+    * FIXEC:  T.Straumann: it is evaluate_path()
     */
    
    rtems_filesystem_current = iop->pathinfo;
    
+   /* clone the current node */
+   rtems_filesystem_evaluate_path(".", 0, &loc, 0);
+   rtems_filesystem_current = loc;
+   
    return 0;
  }
Index: getgrent.c
===================================================================
RCS file: /afs/slac/g/spear/cvsrep/rtems/src/c/src/lib/libc/getgrent.c,v
retrieving revision 1.1.1.1
diff -c -r1.1.1.1 getgrent.c
*** getgrent.c	14 Dec 2001 22:52:31 -0000	1.1.1.1
--- getgrent.c	27 Oct 2002 18:24:20 -0000
***************
*** 50,63 ****
--- 50,69 ----
  )
  {
    FILE *fp;
+ #if 0
    rtems_user_env_t * aux=rtems_current_user_env; /* save */
+ #endif
  
    init_etc_passwd_group();
+ #if 0
    rtems_current_user_env=&rtems_global_user_env; /* set root */
+ #endif
  
    if ((fp = fopen ("/etc/group", "r")) == NULL) {
      errno = EINVAL;
+ #if 0
      rtems_current_user_env=aux; /* restore */
+ #endif
      return -1;
    }
  
***************
*** 72,84 ****
--- 78,94 ----
      if (!strcmp (groupname, name)) {
        fclose (fp);
        *result = grp;
+ #if 0
        rtems_current_user_env=aux; /* restore */
+ #endif
        return 0;
      }
    }
    fclose (fp);
    errno = EINVAL;
+ #if 0
    rtems_current_user_env=aux; /* restore */
+ #endif
    return -1;
  }
  
***************
*** 104,118 ****
--- 114,134 ----
  )
  {
    FILE *fp;
+ #if 0
    rtems_user_env_t * aux=rtems_current_user_env; /* save */
+ #endif
  
  
    init_etc_passwd_group();
+ #if 0
    rtems_current_user_env=&rtems_global_user_env; /* set root */
+ #endif
  
    if ((fp = fopen ("/etc/group", "r")) == NULL) {
      errno = EINVAL;
+ #if 0
      rtems_current_user_env=aux; /* restore */
+ #endif
      return -1;
    }
  
***************
*** 128,140 ****
--- 144,160 ----
      if (gid == gr_group.gr_gid) {
        fclose (fp);
        *result = grp;
+ #if 0
        rtems_current_user_env=aux; /* restore */
+ #endif
        return 0;
      }
    }
    fclose (fp);
    errno = EINVAL;
+ #if 0
    rtems_current_user_env=aux; /* restore */
+ #endif
    return -1;
  }
  
***************
*** 174,188 ****
--- 194,214 ----
  void
  setgrent ()
  {
+ #if 0
    rtems_user_env_t * aux=rtems_current_user_env; /* save */
+ #endif
    init_etc_passwd_group();
+ #if 0
    rtems_current_user_env=&rtems_global_user_env; /* set root */
+ #endif
  
    if (group_fp != NULL)
      fclose (group_fp);
  
    group_fp = fopen ("/etc/group", "r");
+ #if 0
    rtems_current_user_env=aux; /* restore */
+ #endif
  }
  
  void
Index: getpwent.c
===================================================================
RCS file: /afs/slac/g/spear/cvsrep/rtems/src/c/src/lib/libc/getpwent.c,v
retrieving revision 1.1.1.1
diff -c -r1.1.1.1 getpwent.c
*** getpwent.c	14 Dec 2001 22:52:31 -0000	1.1.1.1
--- getpwent.c	27 Oct 2002 18:18:52 -0000
***************
*** 97,110 ****
--- 97,116 ----
  )
  {
    FILE *fp;
+ #if 0
    rtems_user_env_t * aux=rtems_current_user_env; /* save */
+ #endif
  
    init_etc_passwd_group();
+ #if 0
    rtems_current_user_env=&rtems_global_user_env; /* set root */
+ #endif
  
    if ((fp = fopen ("/etc/passwd", "r")) == NULL) {
      errno = EINVAL;
+ #if 0
      rtems_current_user_env=aux; /* restore */
+ #endif
      return -1;
    }
  
***************
*** 123,135 ****
--- 129,145 ----
      if (!strcmp (logname, name)) {
        fclose (fp);
        *result = pwd;
+ #if 0
        rtems_current_user_env=aux; /* restore */
+ #endif
        return 0;
      }
    }
    fclose (fp);
    errno = EINVAL;
+ #if 0
      rtems_current_user_env=aux; /* restore */
+ #endif
    return -1;
  }
  
***************
*** 155,168 ****
--- 165,184 ----
  )
  {
    FILE *fp;
+ #if 0
    rtems_user_env_t * aux=rtems_current_user_env; /* save */
+ #endif
  
    init_etc_passwd_group();
+ #if 0
    rtems_current_user_env=&rtems_global_user_env; /* set root */
+ #endif
  
    if ((fp = fopen ("/etc/passwd", "r")) == NULL) {
      errno = EINVAL;
+ #if 0
      rtems_current_user_env=aux; /* restore */
+ #endif
      return -1;
    }
  
***************
*** 181,193 ****
--- 197,213 ----
      if (uid == pwd->pw_uid) {
        fclose (fp);
        *result = pwd;
+ #if 0
        rtems_current_user_env=aux; /* restore */
+ #endif
        return 0;
      }
    }
    fclose (fp);
    errno = EINVAL;
+ #if 0
    rtems_current_user_env=aux; /* restore */
+ #endif
    return -1;
  }
  
***************
*** 230,244 ****
--- 250,270 ----
  
  void setpwent( void )
  {
+ #if 0
    rtems_user_env_t * aux=rtems_current_user_env; /* save */
+ #endif
    init_etc_passwd_group();
+ #if 0
    rtems_current_user_env=&rtems_global_user_env; /* set root */
+ #endif
  
    if (passwd_fp != NULL)
      fclose (passwd_fp);
  
    passwd_fp = fopen ("/etc/passwd", "r");
+ #if 0
    rtems_current_user_env=aux; /* restore */
+ #endif
  }
  
  void endpwent( void )
Index: mknod.c
===================================================================
RCS file: /afs/slac/g/spear/cvsrep/rtems/src/c/src/lib/libc/mknod.c,v
retrieving revision 1.1.1.2
retrieving revision 1.2
diff -c -r1.1.1.2 -r1.2
*** mknod.c	7 Mar 2002 01:53:51 -0000	1.1.1.2
--- mknod.c	29 Oct 2002 21:03:50 -0000	1.2
***************
*** 12,18 ****
   *  found in the file LICENSE in this distribution or at
   *  http://www.OARcorp.com/rtems/license.html.
   *
!  *  $Id: rtems-filesystem-patch,v 1.1 2002/11/26 20:50:14 till Exp $
   */
  
  #if HAVE_CONFIG_H
--- 12,18 ----
   *  found in the file LICENSE in this distribution or at
   *  http://www.OARcorp.com/rtems/license.html.
   *
!  *  $Id: rtems-filesystem-patch,v 1.1 2002/11/26 20:50:14 till Exp $
   */
  
  #if HAVE_CONFIG_H
***************
*** 49,55 ****
    rtems_filesystem_get_start_loc( pathname, &i, &temp_loc );
  
    if ( !temp_loc.ops->evalformake_h ) {
-     rtems_filesystem_freenode( &temp_loc );
      rtems_set_errno_and_return_minus_one( ENOTSUP );
    }
  
--- 49,54 ----
Index: mount.c
===================================================================
RCS file: /afs/slac/g/spear/cvsrep/rtems/src/c/src/lib/libc/mount.c,v
retrieving revision 1.1.1.1
diff -c -r1.1.1.1 mount.c
*** mount.c	14 Dec 2001 22:52:33 -0000	1.1.1.1
--- mount.c	30 Oct 2002 06:39:09 -0000
***************
*** 14,20 ****
   *  found in the file LICENSE in this distribution or at
   *  http://www.OARcorp.com/rtems/license.html.
   *
!  *  $Id: rtems-filesystem-patch,v 1.1 2002/11/26 20:50:14 till Exp $
   */
  
  #if HAVE_CONFIG_H
--- 14,20 ----
   *  found in the file LICENSE in this distribution or at
   *  http://www.OARcorp.com/rtems/license.html.
   *
!  *  $Id: rtems-filesystem-patch,v 1.1 2002/11/26 20:50:14 till Exp $
   */
  
  #if HAVE_CONFIG_H
***************
*** 101,106 ****
--- 101,113 ----
      return -1;
    }
  
+   /* Do they support being mounted at all ? */
+   if ( !fs_ops->fsmount_me_h ) {
+     errno = ENOTSUP;
+     goto cleanup_and_bail;
+   }
+ 
+ 
    /*
     * Allocate a mount table entry 
     */
***************
*** 140,145 ****
--- 147,158 ----
       */
  
      loc_to_free = &loc;
+ 
+ 	if ( !loc.ops->node_type_h ) {
+ 	  errno = ENOTSUP;
+       goto cleanup_and_bail;
+ 	}
+ 
      if ( loc.ops->node_type_h( &loc ) != RTEMS_FILESYSTEM_DIRECTORY ) {
        errno = ENOTDIR;
        goto cleanup_and_bail;
***************
*** 198,210 ****
      temp_mt_entry->mt_point_node.mt_entry = NULL;
    }
  
!   if ( !fs_ops->fsmount_me_h ) {
!     errno = ENOTSUP;
      goto cleanup_and_bail;
    }
- 
-   if ( fs_ops->fsmount_me_h( temp_mt_entry ) )
-     goto cleanup_and_bail;
  
    /*
     *  Add the mount table entry to the mount table chain 
--- 211,223 ----
      temp_mt_entry->mt_point_node.mt_entry = NULL;
    }
  
!   if ( fs_ops->fsmount_me_h( temp_mt_entry ) ) {
! 	/* try to undo the mount operation */
! 	if ( loc.ops->unmount_h ) {
! 		loc.ops->unmount_h( temp_mt_entry );
!     }
      goto cleanup_and_bail;
    }
  
    /*
     *  Add the mount table entry to the mount table chain 
Index: newlibc.c
===================================================================
RCS file: /afs/slac/g/spear/cvsrep/rtems/src/c/src/lib/libc/newlibc.c,v
retrieving revision 1.1.1.1
retrieving revision 1.3
diff -c -r1.1.1.1 -r1.3
*** newlibc.c	14 Dec 2001 22:52:33 -0000	1.1.1.1
--- newlibc.c	16 Apr 2002 19:41:03 -0000	1.3
***************
*** 9,15 ****
   *  found in the file LICENSE in this distribution or at
   *  http://www.OARcorp.com/rtems/license.html.
   *
!  *  $Id: rtems-filesystem-patch,v 1.1 2002/11/26 20:50:14 till Exp $
   *
   */
  
--- 9,15 ----
   *  found in the file LICENSE in this distribution or at
   *  http://www.OARcorp.com/rtems/license.html.
   *
!  *  $Id: rtems-filesystem-patch,v 1.1 2002/11/26 20:50:14 till Exp $
   *
   */
  
Index: privateenv.c
===================================================================
RCS file: /afs/slac/g/spear/cvsrep/rtems/src/c/src/lib/libc/privateenv.c,v
retrieving revision 1.1.1.2
diff -c -r1.1.1.2 privateenv.c
*** privateenv.c	7 Mar 2002 01:53:51 -0000	1.1.1.2
--- privateenv.c	27 Oct 2002 18:35:34 -0000
***************
*** 23,47 ****
  #include <rtems/libio.h>
  #include <rtems/libio_.h>
  
  rtems_status_code rtems_libio_set_private_env(void) {
!   rtems_status_code sc;
!   rtems_id          task_id;
  
    sc=rtems_task_ident(RTEMS_SELF,0,&task_id);
    if (sc != RTEMS_SUCCESSFUL) return sc;
  
    /* Only for the first time a malloc is necesary */
!   if (rtems_current_user_env==&rtems_global_user_env) { 
!    sc = rtems_task_variable_add(RTEMS_SELF,(void*)&rtems_current_user_env,free);
!    if (sc != RTEMS_SUCCESSFUL) return sc;
!    rtems_current_user_env = malloc(sizeof(rtems_user_env_t));
!    if (!rtems_current_user_env)
       return RTEMS_NO_MEMORY;
    }; 
  
-   /* the side effect desired . chroot("/") */
    *rtems_current_user_env = rtems_global_user_env; /* get the global values*/
    rtems_current_user_env->task_id=task_id;         /* mark the local values*/
  
    return RTEMS_SUCCESSFUL;
  }
--- 23,92 ----
  #include <rtems/libio.h>
  #include <rtems/libio_.h>
  
+ extern Chain_Control rtems_filesystem_mount_table_control;
+ 
+ #define THE_ROOT_FS_LOC \
+ 	(((rtems_filesystem_mount_table_entry_t*)\
+ 	   rtems_filesystem_mount_table_control.first)->mt_fs_root)
+ 
+ /* cleanup a user environment
+  * NOTE: this must be called with
+  *       thread dispatching disabled!
+  */
+ static void
+ free_user_env(rtems_user_env_t *env)
+ {
+ 	if (env != &rtems_global_user_env 
+ 		&& --env->refcnt <= 0) {
+ 		rtems_filesystem_freenode( &env->current_directory);
+ 		rtems_filesystem_freenode( &env->root_directory);
+ 		free(env);
+ 	}
+ }
+ 
  rtems_status_code rtems_libio_set_private_env(void) {
!   rtems_status_code 					sc;
!   rtems_id          					task_id;
!   rtems_filesystem_location_info_t		loc;
  
    sc=rtems_task_ident(RTEMS_SELF,0,&task_id);
    if (sc != RTEMS_SUCCESSFUL) return sc;
  
    /* Only for the first time a malloc is necesary */
!   if (rtems_current_user_env==&rtems_global_user_env) {
!    rtems_user_env_t	*tmp = malloc(sizeof(rtems_user_env_t));
!    if (!tmp)
       return RTEMS_NO_MEMORY;
+ 
+    tmp->refcnt = 1;
+ 
+    sc = rtems_task_variable_add(RTEMS_SELF,(void*)&rtems_current_user_env,free_user_env);
+    if (sc != RTEMS_SUCCESSFUL) {
+ 	 /* don't use free_user_env because the pathlocs are
+ 	  * not initialized yet
+ 	  */
+      free(tmp);
+      return sc;
+    }
+    rtems_current_user_env = tmp;
    }; 
  
    *rtems_current_user_env = rtems_global_user_env; /* get the global values*/
    rtems_current_user_env->task_id=task_id;         /* mark the local values*/
+   
+   /* get a clean root */
+   rtems_filesystem_root    = THE_ROOT_FS_LOC;
+ 
+   /* Clone the pathlocs. In contrast to most other
+    * code we must _not_ free the original locs because
+    * what we are trying to do here is forking off
+    * clones.
+    */
+ 
+   rtems_filesystem_evaluate_path("/", 0, &loc, 0);
+   rtems_filesystem_root    = loc;
+   rtems_filesystem_evaluate_path("/", 0, &loc, 0);
+   rtems_filesystem_current = loc;
  
    return RTEMS_SUCCESSFUL;
  }
***************
*** 51,56 ****
--- 96,115 ----
   *   Task_id (remote) and RTEMS_SELF(current).
   */
  
+ /* NOTE:
+  *
+  * THIS CODE HAS NO PROTECTION IMPLEMENTED
+  *
+  * Tasks who wish to share their environments must
+  *
+  *  a) assert that no participants are concurrently
+  *     executing
+  *     libio_share_private_env() and/or libio_set_private_env()
+  *
+  *  b) mutex access to rtems_filesystem_current, rtems_filesytem_root
+  *     while changing any of those (chdir(), chroot()).
+  */
+ 
  rtems_status_code rtems_libio_share_private_env(rtems_id task_id) {
    rtems_status_code  sc;
    rtems_user_env_t * shared_user_env;
***************
*** 61,81 ****
  
    if (rtems_current_user_env->task_id==current_task_id) {
     /* kill the current user env & task_var*/	  
!    free(rtems_current_user_env);	  
     sc = rtems_task_variable_delete(RTEMS_SELF,(void*)&rtems_current_user_env);
     if (sc != RTEMS_SUCCESSFUL) return sc;
    };
  
    sc = rtems_task_variable_get(task_id,(void*)&rtems_current_user_env,
  		                       (void*)&shared_user_env       );
!   if (sc != RTEMS_SUCCESSFUL) return sc;
  
!   /* don't free(NULL'ed) at the task_delete. It is a shared var... */	   
!   sc = rtems_task_variable_add(RTEMS_SELF,(void*)&rtems_current_user_env,NULL);
!   if (sc != RTEMS_SUCCESSFUL) return sc;
    
    /* the current_user_env is the same pointer that remote env */
    rtems_current_user_env = shared_user_env;
  
    return RTEMS_SUCCESSFUL;
  }
--- 120,152 ----
  
    if (rtems_current_user_env->task_id==current_task_id) {
     /* kill the current user env & task_var*/	  
! 	rtems_user_env_t 	*tmp = rtems_current_user_env;
     sc = rtems_task_variable_delete(RTEMS_SELF,(void*)&rtems_current_user_env);
     if (sc != RTEMS_SUCCESSFUL) return sc;
+    free_user_env(tmp);	  
    };
  
+   /* AT THIS POINT, rtems_current_user_env is DANGLING */
+ 
    sc = rtems_task_variable_get(task_id,(void*)&rtems_current_user_env,
  		                       (void*)&shared_user_env       );
!   if (sc != RTEMS_SUCCESSFUL)
!     goto bailout;
  
!   sc = rtems_task_variable_add(RTEMS_SELF,(void*)&rtems_current_user_env,free_user_env);
!   if (sc != RTEMS_SUCCESSFUL)
!     goto bailout;
    
    /* the current_user_env is the same pointer that remote env */
    rtems_current_user_env = shared_user_env;
  
+   /* increase the reference count */
+   rtems_current_user_env->refcnt++;
+ 
    return RTEMS_SUCCESSFUL;
+ 
+ bailout:
+   /* fallback to the global env */
+   rtems_current_user_env = &rtems_global_user_env;
+   return sc;
  }
