Alexandre Julliard : server: Keep a file descriptor open to the config directory to make sure we don' t write the registry in the wrong place.
Alexandre Julliard
julliard at winehq.org
Thu Apr 17 07:38:44 CDT 2008
Module: wine
Branch: master
Commit: 161160f05ae2340ab5bb35307ca02056cbca68e9
URL: http://source.winehq.org/git/wine.git/?a=commit;h=161160f05ae2340ab5bb35307ca02056cbca68e9
Author: Alexandre Julliard <julliard at winehq.org>
Date: Thu Apr 17 12:41:34 2008 +0200
server: Keep a file descriptor open to the config directory to make sure we don't write the registry in the wrong place.
---
server/registry.c | 57 +++++++++++++++++++---------------------------------
server/request.c | 11 ++++++++-
server/request.h | 1 +
3 files changed, 31 insertions(+), 38 deletions(-)
diff --git a/server/registry.c b/server/registry.c
index 5084892..d2c0b23 100644
--- a/server/registry.c
+++ b/server/registry.c
@@ -112,7 +112,7 @@ static void set_periodic_save_timer(void);
struct save_branch_info
{
struct key *key;
- char *path;
+ const char *path;
};
#define MAX_SAVE_BRANCH_INFO 3
@@ -1396,11 +1396,9 @@ static void load_init_registry_from_file( const char *filename, struct key *key
assert( save_branch_count < MAX_SAVE_BRANCH_INFO );
- if ((save_branch_info[save_branch_count].path = strdup( filename )))
- {
- save_branch_info[save_branch_count++].key = (struct key *)grab_object( key );
- make_object_static( &key->obj );
- }
+ save_branch_info[save_branch_count].path = filename;
+ save_branch_info[save_branch_count++].key = (struct key *)grab_object( key );
+ make_object_static( &key->obj );
}
static WCHAR *format_user_registry_path( const SID *sid, struct unicode_str *path )
@@ -1438,27 +1436,24 @@ void init_registry(void)
WCHAR *current_user_path;
struct unicode_str current_user_str;
- const char *config = wine_get_config_dir();
- char *p, *filename;
struct key *key;
int dummy;
+ /* switch to the config dir */
+
+ if (fchdir( config_dir_fd ) == -1) fatal_perror( "chdir to config dir" );
+
/* create the root key */
root_key = alloc_key( &root_name, time(NULL) );
assert( root_key );
make_object_static( &root_key->obj );
- if (!(filename = malloc( strlen(config) + 16 ))) fatal_error( "out of memory\n" );
- strcpy( filename, config );
- p = filename + strlen(filename);
-
/* load system.reg into Registry\Machine */
if (!(key = create_key( root_key, &HKLM_name, NULL, 0, time(NULL), &dummy )))
fatal_error( "could not create Machine registry key\n" );
- strcpy( p, "/system.reg" );
- load_init_registry_from_file( filename, key );
+ load_init_registry_from_file( "system.reg", key );
release_object( key );
/* load userdef.reg into Registry\User\.Default */
@@ -1466,8 +1461,7 @@ void init_registry(void)
if (!(key = create_key( root_key, &HKU_name, NULL, 0, time(NULL), &dummy )))
fatal_error( "could not create User\\.Default registry key\n" );
- strcpy( p, "/userdef.reg" );
- load_init_registry_from_file( filename, key );
+ load_init_registry_from_file( "userdef.reg", key );
release_object( key );
/* load user.reg into HKEY_CURRENT_USER */
@@ -1478,14 +1472,14 @@ void init_registry(void)
!(key = create_key( root_key, ¤t_user_str, NULL, 0, time(NULL), &dummy )))
fatal_error( "could not create HKEY_CURRENT_USER registry key\n" );
free( current_user_path );
- strcpy( p, "/user.reg" );
- load_init_registry_from_file( filename, key );
+ load_init_registry_from_file( "user.reg", key );
release_object( key );
- free( filename );
-
/* start the periodic save timer */
set_periodic_save_timer();
+
+ /* go back to the server dir */
+ if (fchdir( server_dir_fd ) == -1) fatal_perror( "chdir to server dir" );
}
/* save a registry branch to a file */
@@ -1532,8 +1526,8 @@ static void save_registry( struct key *key, obj_handle_t handle )
static int save_branch( struct key *key, const char *path )
{
struct stat st;
- char *p, *real, *tmp = NULL;
- int fd, count = 0, ret = 0, by_symlink;
+ char *p, *tmp = NULL;
+ int fd, count = 0, ret = 0;
FILE *f;
if (!(key->flags & KEY_DIRTY))
@@ -1542,25 +1536,13 @@ static int save_branch( struct key *key, const char *path )
return 1;
}
- /* get the real path */
-
- by_symlink = (!lstat(path, &st) && S_ISLNK (st.st_mode));
- if (!(real = malloc( PATH_MAX ))) return 0;
- if (!realpath( path, real ))
- {
- free( real );
- real = NULL;
- }
- else path = real;
-
/* test the file type */
if ((fd = open( path, O_WRONLY )) != -1)
{
/* if file is not a regular file or has multiple links or is accessed
* via symbolic links, write directly into it; otherwise use a temp file */
- if (by_symlink ||
- (!fstat( fd, &st ) && (!S_ISREG(st.st_mode) || st.st_nlink > 1)))
+ if (!lstat( path, &st ) && (!S_ISREG(st.st_mode) || st.st_nlink > 1))
{
ftruncate( fd, 0 );
goto save;
@@ -1610,7 +1592,6 @@ static int save_branch( struct key *key, const char *path )
done:
free( tmp );
- free( real );
if (ret) make_clean( key );
return ret;
}
@@ -1620,9 +1601,11 @@ static void periodic_save( void *arg )
{
int i;
+ if (fchdir( config_dir_fd ) == -1) return;
save_timeout_user = NULL;
for (i = 0; i < save_branch_count; i++)
save_branch( save_branch_info[i].key, save_branch_info[i].path );
+ if (fchdir( server_dir_fd ) == -1) fatal_perror( "chdir to server dir" );
set_periodic_save_timer();
}
@@ -1638,6 +1621,7 @@ void flush_registry(void)
{
int i;
+ if (fchdir( config_dir_fd ) == -1) return;
for (i = 0; i < save_branch_count; i++)
{
if (!save_branch( save_branch_info[i].key, save_branch_info[i].path ))
@@ -1647,6 +1631,7 @@ void flush_registry(void)
perror( " " );
}
}
+ if (fchdir( server_dir_fd ) == -1) fatal_perror( "chdir to server dir" );
}
diff --git a/server/request.c b/server/request.c
index 9a2c7b1..8726e1c 100644
--- a/server/request.c
+++ b/server/request.c
@@ -120,6 +120,8 @@ static const struct fd_ops master_socket_fd_ops =
struct thread *current = NULL; /* thread handling the current request */
unsigned int global_error = 0; /* global error code for when no thread is current */
timeout_t server_start_time = 0; /* server startup time */
+int server_dir_fd = -1; /* file descriptor for the server dir */
+int config_dir_fd = -1; /* file descriptor for the config dir */
static struct master_socket *master_socket; /* the master socket object */
static struct timeout_user *master_timeout;
@@ -553,7 +555,8 @@ static void create_server_dir( const char *dir )
create_dir( server_dir, &st );
if (chdir( server_dir ) == -1) fatal_perror( "chdir %s", server_dir );
- if (stat( ".", &st2 ) == -1) fatal_perror( "stat %s", server_dir );
+ if ((server_dir_fd = open( ".", O_RDONLY )) == -1) fatal_perror( "open %s", server_dir );
+ if (fstat( server_dir_fd, &st2 ) == -1) fatal_perror( "stat %s", server_dir );
if (st.st_dev != st2.st_dev || st.st_ino != st2.st_ino)
fatal_error( "chdir did not end up in %s\n", server_dir );
@@ -733,6 +736,7 @@ static void acquire_lock(void)
void open_master_socket(void)
{
const char *server_dir = wine_get_server_dir();
+ const char *config_dir = wine_get_config_dir();
int fd, pid, status, sync_pipe[2];
char dummy;
@@ -740,7 +744,10 @@ void open_master_socket(void)
assert( sizeof(union generic_request) == sizeof(struct request_max_size) );
assert( sizeof(union generic_reply) == sizeof(struct request_max_size) );
- if (!server_dir) fatal_error( "directory %s cannot be accessed\n", wine_get_config_dir() );
+ if (!server_dir) fatal_error( "directory %s cannot be accessed\n", config_dir );
+ if (chdir( config_dir ) == -1) fatal_perror( "chdir to %s", config_dir );
+ if ((config_dir_fd = open( ".", O_RDONLY )) == -1) fatal_perror( "open %s", config_dir );
+
create_server_dir( server_dir );
if (!foreground)
diff --git a/server/request.h b/server/request.h
index 283ad97..496c5ff 100644
--- a/server/request.h
+++ b/server/request.h
@@ -61,6 +61,7 @@ extern void close_master_socket( timeout_t timeout );
extern void shutdown_master_socket(void);
extern int wait_for_lock(void);
extern int kill_lock_owner( int sig );
+extern int server_dir_fd, config_dir_fd;
extern void trace_request(void);
extern void trace_reply( enum request req, const union generic_reply *reply );
More information about the wine-cvs
mailing list