summaryrefslogtreecommitdiffstats
path: root/cpukit/libcsupport/src/privateenv.c
diff options
context:
space:
mode:
authorJennifer Averett <Jennifer.Averett@OARcorp.com>2003-01-03 18:14:09 +0000
committerJennifer Averett <Jennifer.Averett@OARcorp.com>2003-01-03 18:14:09 +0000
commitf6161c72d1810db34f83d4570906859fc432e506 (patch)
treee68c31f866ef1a48cce276c2aacae038639c43d1 /cpukit/libcsupport/src/privateenv.c
parent2002-11-26 Chris Johns <cjohns@cybertec.com.au> (diff)
downloadrtems-f6161c72d1810db34f83d4570906859fc432e506.tar.bz2
2003-01-03 Till Straumann <strauman@slac.stanford.edu>
* ChangeLog, base_fs.c, getpwent.c, privateenv.c Per PR303, Fix violation of node_access copy syemantics
Diffstat (limited to 'cpukit/libcsupport/src/privateenv.c')
-rw-r--r--cpukit/libcsupport/src/privateenv.c106
1 files changed, 93 insertions, 13 deletions
diff --git a/cpukit/libcsupport/src/privateenv.c b/cpukit/libcsupport/src/privateenv.c
index 93dff453c5..d4e5608be1 100644
--- a/cpukit/libcsupport/src/privateenv.c
+++ b/cpukit/libcsupport/src/privateenv.c
@@ -23,25 +23,75 @@
#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
+#ifdef HAVE_USERENV_REFCNT
+ && --env->refcnt <= 0
+#endif
+ ) {
+ 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_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) {
- 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)
+ 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;
+
+#ifdef HAVE_USERENV_REFCNT
+ tmp->refcnt = 1;
+#endif
+
+ 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;
};
- /* 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*/
+
+ /* 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,6 +101,21 @@ rtems_status_code rtems_libio_set_private_env(void) {
* 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()).
+ */
+
+#ifndef HAVE_USERENV_REFCNT
rtems_status_code rtems_libio_share_private_env(rtems_id task_id) {
rtems_status_code sc;
rtems_user_env_t * shared_user_env;
@@ -61,21 +126,36 @@ rtems_status_code rtems_libio_share_private_env(rtems_id task_id) {
if (rtems_current_user_env->task_id==current_task_id) {
/* kill the current user env & task_var*/
- free(rtems_current_user_env);
+ 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) return sc;
+ if (sc != RTEMS_SUCCESSFUL)
+ goto bailout;
- /* 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;
+ 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 */
+#ifdef HAVE_USERENV_REFCNT
+ rtems_current_user_env->refcnt++;
+#endif
+
return RTEMS_SUCCESSFUL;
+
+bailout:
+ /* fallback to the global env */
+ rtems_current_user_env = &rtems_global_user_env;
+ return sc;
}
+#endif