Commit 161160f0 authored by Alexandre Julliard's avatar Alexandre Julliard

server: Keep a file descriptor open to the config directory to make sure we…

server: Keep a file descriptor open to the config directory to make sure we don't write the registry in the wrong place.
parent e52e5e67
...@@ -112,7 +112,7 @@ static void set_periodic_save_timer(void); ...@@ -112,7 +112,7 @@ static void set_periodic_save_timer(void);
struct save_branch_info struct save_branch_info
{ {
struct key *key; struct key *key;
char *path; const char *path;
}; };
#define MAX_SAVE_BRANCH_INFO 3 #define MAX_SAVE_BRANCH_INFO 3
...@@ -1396,11 +1396,9 @@ static void load_init_registry_from_file( const char *filename, struct key *key ...@@ -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 ); assert( save_branch_count < MAX_SAVE_BRANCH_INFO );
if ((save_branch_info[save_branch_count].path = strdup( filename ))) save_branch_info[save_branch_count].path = filename;
{ save_branch_info[save_branch_count++].key = (struct key *)grab_object( key );
save_branch_info[save_branch_count++].key = (struct key *)grab_object( key ); make_object_static( &key->obj );
make_object_static( &key->obj );
}
} }
static WCHAR *format_user_registry_path( const SID *sid, struct unicode_str *path ) static WCHAR *format_user_registry_path( const SID *sid, struct unicode_str *path )
...@@ -1438,27 +1436,24 @@ void init_registry(void) ...@@ -1438,27 +1436,24 @@ void init_registry(void)
WCHAR *current_user_path; WCHAR *current_user_path;
struct unicode_str current_user_str; struct unicode_str current_user_str;
const char *config = wine_get_config_dir();
char *p, *filename;
struct key *key; struct key *key;
int dummy; int dummy;
/* switch to the config dir */
if (fchdir( config_dir_fd ) == -1) fatal_perror( "chdir to config dir" );
/* create the root key */ /* create the root key */
root_key = alloc_key( &root_name, time(NULL) ); root_key = alloc_key( &root_name, time(NULL) );
assert( root_key ); assert( root_key );
make_object_static( &root_key->obj ); 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 */ /* load system.reg into Registry\Machine */
if (!(key = create_key( root_key, &HKLM_name, NULL, 0, time(NULL), &dummy ))) if (!(key = create_key( root_key, &HKLM_name, NULL, 0, time(NULL), &dummy )))
fatal_error( "could not create Machine registry key\n" ); fatal_error( "could not create Machine registry key\n" );
strcpy( p, "/system.reg" ); load_init_registry_from_file( "system.reg", key );
load_init_registry_from_file( filename, key );
release_object( key ); release_object( key );
/* load userdef.reg into Registry\User\.Default */ /* load userdef.reg into Registry\User\.Default */
...@@ -1466,8 +1461,7 @@ void init_registry(void) ...@@ -1466,8 +1461,7 @@ void init_registry(void)
if (!(key = create_key( root_key, &HKU_name, NULL, 0, time(NULL), &dummy ))) if (!(key = create_key( root_key, &HKU_name, NULL, 0, time(NULL), &dummy )))
fatal_error( "could not create User\\.Default registry key\n" ); fatal_error( "could not create User\\.Default registry key\n" );
strcpy( p, "/userdef.reg" ); load_init_registry_from_file( "userdef.reg", key );
load_init_registry_from_file( filename, key );
release_object( key ); release_object( key );
/* load user.reg into HKEY_CURRENT_USER */ /* load user.reg into HKEY_CURRENT_USER */
...@@ -1478,14 +1472,14 @@ void init_registry(void) ...@@ -1478,14 +1472,14 @@ void init_registry(void)
!(key = create_key( root_key, &current_user_str, NULL, 0, time(NULL), &dummy ))) !(key = create_key( root_key, &current_user_str, NULL, 0, time(NULL), &dummy )))
fatal_error( "could not create HKEY_CURRENT_USER registry key\n" ); fatal_error( "could not create HKEY_CURRENT_USER registry key\n" );
free( current_user_path ); free( current_user_path );
strcpy( p, "/user.reg" ); load_init_registry_from_file( "user.reg", key );
load_init_registry_from_file( filename, key );
release_object( key ); release_object( key );
free( filename );
/* start the periodic save timer */ /* start the periodic save timer */
set_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 */ /* save a registry branch to a file */
...@@ -1532,8 +1526,8 @@ static void save_registry( struct key *key, obj_handle_t handle ) ...@@ -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 ) static int save_branch( struct key *key, const char *path )
{ {
struct stat st; struct stat st;
char *p, *real, *tmp = NULL; char *p, *tmp = NULL;
int fd, count = 0, ret = 0, by_symlink; int fd, count = 0, ret = 0;
FILE *f; FILE *f;
if (!(key->flags & KEY_DIRTY)) if (!(key->flags & KEY_DIRTY))
...@@ -1542,25 +1536,13 @@ static int save_branch( struct key *key, const char *path ) ...@@ -1542,25 +1536,13 @@ static int save_branch( struct key *key, const char *path )
return 1; 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 */ /* test the file type */
if ((fd = open( path, O_WRONLY )) != -1) if ((fd = open( path, O_WRONLY )) != -1)
{ {
/* if file is not a regular file or has multiple links or is accessed /* 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 */ * via symbolic links, write directly into it; otherwise use a temp file */
if (by_symlink || if (!lstat( path, &st ) && (!S_ISREG(st.st_mode) || st.st_nlink > 1))
(!fstat( fd, &st ) && (!S_ISREG(st.st_mode) || st.st_nlink > 1)))
{ {
ftruncate( fd, 0 ); ftruncate( fd, 0 );
goto save; goto save;
...@@ -1610,7 +1592,6 @@ static int save_branch( struct key *key, const char *path ) ...@@ -1610,7 +1592,6 @@ static int save_branch( struct key *key, const char *path )
done: done:
free( tmp ); free( tmp );
free( real );
if (ret) make_clean( key ); if (ret) make_clean( key );
return ret; return ret;
} }
...@@ -1620,9 +1601,11 @@ static void periodic_save( void *arg ) ...@@ -1620,9 +1601,11 @@ static void periodic_save( void *arg )
{ {
int i; int i;
if (fchdir( config_dir_fd ) == -1) return;
save_timeout_user = NULL; save_timeout_user = NULL;
for (i = 0; i < save_branch_count; i++) for (i = 0; i < save_branch_count; i++)
save_branch( save_branch_info[i].key, save_branch_info[i].path ); 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(); set_periodic_save_timer();
} }
...@@ -1638,6 +1621,7 @@ void flush_registry(void) ...@@ -1638,6 +1621,7 @@ void flush_registry(void)
{ {
int i; int i;
if (fchdir( config_dir_fd ) == -1) return;
for (i = 0; i < save_branch_count; i++) for (i = 0; i < save_branch_count; i++)
{ {
if (!save_branch( save_branch_info[i].key, save_branch_info[i].path )) if (!save_branch( save_branch_info[i].key, save_branch_info[i].path ))
...@@ -1647,6 +1631,7 @@ void flush_registry(void) ...@@ -1647,6 +1631,7 @@ void flush_registry(void)
perror( " " ); perror( " " );
} }
} }
if (fchdir( server_dir_fd ) == -1) fatal_perror( "chdir to server dir" );
} }
......
...@@ -120,6 +120,8 @@ static const struct fd_ops master_socket_fd_ops = ...@@ -120,6 +120,8 @@ static const struct fd_ops master_socket_fd_ops =
struct thread *current = NULL; /* thread handling the current request */ struct thread *current = NULL; /* thread handling the current request */
unsigned int global_error = 0; /* global error code for when no thread is current */ unsigned int global_error = 0; /* global error code for when no thread is current */
timeout_t server_start_time = 0; /* server startup time */ 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 master_socket *master_socket; /* the master socket object */
static struct timeout_user *master_timeout; static struct timeout_user *master_timeout;
...@@ -553,7 +555,8 @@ static void create_server_dir( const char *dir ) ...@@ -553,7 +555,8 @@ static void create_server_dir( const char *dir )
create_dir( server_dir, &st ); create_dir( server_dir, &st );
if (chdir( server_dir ) == -1) fatal_perror( "chdir %s", server_dir ); 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) 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 ); fatal_error( "chdir did not end up in %s\n", server_dir );
...@@ -733,6 +736,7 @@ static void acquire_lock(void) ...@@ -733,6 +736,7 @@ static void acquire_lock(void)
void open_master_socket(void) void open_master_socket(void)
{ {
const char *server_dir = wine_get_server_dir(); const char *server_dir = wine_get_server_dir();
const char *config_dir = wine_get_config_dir();
int fd, pid, status, sync_pipe[2]; int fd, pid, status, sync_pipe[2];
char dummy; char dummy;
...@@ -740,7 +744,10 @@ void open_master_socket(void) ...@@ -740,7 +744,10 @@ void open_master_socket(void)
assert( sizeof(union generic_request) == sizeof(struct request_max_size) ); assert( sizeof(union generic_request) == sizeof(struct request_max_size) );
assert( sizeof(union generic_reply) == 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 ); create_server_dir( server_dir );
if (!foreground) if (!foreground)
......
...@@ -61,6 +61,7 @@ extern void close_master_socket( timeout_t timeout ); ...@@ -61,6 +61,7 @@ extern void close_master_socket( timeout_t timeout );
extern void shutdown_master_socket(void); extern void shutdown_master_socket(void);
extern int wait_for_lock(void); extern int wait_for_lock(void);
extern int kill_lock_owner( int sig ); extern int kill_lock_owner( int sig );
extern int server_dir_fd, config_dir_fd;
extern void trace_request(void); extern void trace_request(void);
extern void trace_reply( enum request req, const union generic_reply *reply ); extern void trace_reply( enum request req, const union generic_reply *reply );
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment