summaryrefslogtreecommitdiffstats
path: root/cpukit/libcsupport
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
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')
-rw-r--r--cpukit/libcsupport/src/base_fs.c33
-rw-r--r--cpukit/libcsupport/src/getpwent.c18
-rw-r--r--cpukit/libcsupport/src/privateenv.c106
3 files changed, 125 insertions, 32 deletions
diff --git a/cpukit/libcsupport/src/base_fs.c b/cpukit/libcsupport/src/base_fs.c
index 119f38d794..61151eef07 100644
--- a/cpukit/libcsupport/src/base_fs.c
+++ b/cpukit/libcsupport/src/base_fs.c
@@ -49,6 +49,7 @@ void rtems_filesystem_initialize( void )
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,8 +76,38 @@ void rtems_filesystem_initialize( void )
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;
- rtems_filesystem_current = rtems_filesystem_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
+ */
/*
diff --git a/cpukit/libcsupport/src/getpwent.c b/cpukit/libcsupport/src/getpwent.c
index 00ae4a47f6..b2b4531b0d 100644
--- a/cpukit/libcsupport/src/getpwent.c
+++ b/cpukit/libcsupport/src/getpwent.c
@@ -185,21 +185,17 @@ static int getpw_r(
{
FILE *fp;
int match;
- rtems_user_env_t * aux=rtems_current_user_env; /* save */
init_etc_passwd_group();
- rtems_current_user_env=&rtems_global_user_env; /* set root */
if ((fp = fopen("/etc/passwd", "r")) == NULL) {
errno = EINVAL;
- rtems_current_user_env=aux; /* restore */
return -1;
}
for(;;) {
if (!scanpw(fp, pwd, buffer, bufsize)) {
errno = EINVAL;
fclose(fp);
- rtems_current_user_env=aux; /* restore */
return -1;
}
if (name) {
@@ -211,13 +207,11 @@ static int getpw_r(
if (match) {
fclose(fp);
*result = pwd;
- rtems_current_user_env=aux; /* restore */
return 0;
}
}
fclose(fp);
errno = EINVAL;
- rtems_current_user_env=aux; /* restore */
return -1;
}
@@ -276,14 +270,11 @@ struct passwd *getpwent()
void setpwent(void)
{
- rtems_user_env_t * aux=rtems_current_user_env; /* save */
init_etc_passwd_group();
- rtems_current_user_env=&rtems_global_user_env; /* set root */
if (passwd_fp != NULL)
fclose(passwd_fp);
passwd_fp = fopen("/etc/passwd", "r");
- rtems_current_user_env=aux; /* restore */
}
void endpwent(void)
@@ -353,21 +344,17 @@ static int getgr_r(
{
FILE *fp;
int match;
- rtems_user_env_t * aux=rtems_current_user_env; /* save */
init_etc_passwd_group();
- rtems_current_user_env=&rtems_global_user_env; /* set root */
if ((fp = fopen("/etc/group", "r")) == NULL) {
errno = EINVAL;
- rtems_current_user_env=aux; /* restore */
return -1;
}
for(;;) {
if (!scangr(fp, grp, buffer, bufsize)) {
errno = EINVAL;
fclose(fp);
- rtems_current_user_env=aux; /* restore */
return -1;
}
if (name) {
@@ -379,13 +366,11 @@ static int getgr_r(
if (match) {
fclose(fp);
*result = grp;
- rtems_current_user_env=aux; /* restore */
return 0;
}
}
fclose(fp);
errno = EINVAL;
- rtems_current_user_env=aux; /* restore */
return -1;
}
@@ -444,14 +429,11 @@ struct group *getgrent()
void setgrent(void)
{
- rtems_user_env_t * aux=rtems_current_user_env; /* save */
init_etc_passwd_group();
- rtems_current_user_env=&rtems_global_user_env; /* set root */
if (group_fp != NULL)
fclose(group_fp);
group_fp = fopen("/etc/group", "r");
- rtems_current_user_env=aux; /* restore */
}
void endgrent(void)
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