server: Keep a file descriptor open to the config directory to make sure we don't write the registry in the wrong place.
This commit is contained in:
parent
e52e5e6715
commit
161160f05a
|
@ -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" );
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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 );
|
||||
|
|
Loading…
Reference in New Issue