mirror of
https://github.com/flatpak/flatpak.git
synced 2026-04-24 00:54:27 -04:00
common: Move flatpak_run_allocate_id() to flatpak-instance
This localizes knowledge of the internal structure of $XDG_RUNTIME_DIR/.flatpak into the flatpak-instance module. Signed-off-by: Simon McVittie <smcv@collabora.com>
This commit is contained in:
committed by
Alexander Larsson
parent
495449daf6
commit
3393366877
@@ -25,6 +25,8 @@
|
||||
|
||||
FlatpakInstance *flatpak_instance_new (const char *dir);
|
||||
FlatpakInstance *flatpak_instance_new_for_id (const char *id);
|
||||
char *flatpak_instance_allocate_id (char **host_dir_out,
|
||||
int *lock_fd_out);
|
||||
|
||||
void flatpak_instance_iterate_all_and_gc (GPtrArray *out_instances);
|
||||
|
||||
|
||||
@@ -420,6 +420,71 @@ flatpak_instance_new (const char *dir)
|
||||
return self;
|
||||
}
|
||||
|
||||
/*
|
||||
* @host_dir_out: (not optional): used to return the directory on the host
|
||||
* system representing this instance
|
||||
* @lock_fd_out: (not optional): used to return a non-exclusive (read) lock
|
||||
* on the lockdirectory on the host-file
|
||||
*/
|
||||
char *
|
||||
flatpak_instance_allocate_id (char **host_dir_out,
|
||||
int *lock_fd_out)
|
||||
{
|
||||
g_autofree char *user_runtime_dir = flatpak_get_real_xdg_runtime_dir ();
|
||||
g_autofree char *base_dir = g_build_filename (user_runtime_dir, ".flatpak", NULL);
|
||||
int count;
|
||||
|
||||
g_return_val_if_fail (host_dir_out != NULL, NULL);
|
||||
g_return_val_if_fail (*host_dir_out == NULL, NULL);
|
||||
g_return_val_if_fail (lock_fd_out != NULL, NULL);
|
||||
g_return_val_if_fail (*lock_fd_out == -1, NULL);
|
||||
|
||||
g_mkdir_with_parents (base_dir, 0755);
|
||||
|
||||
flatpak_instance_iterate_all_and_gc (NULL);
|
||||
|
||||
for (count = 0; count < 1000; count++)
|
||||
{
|
||||
g_autofree char *instance_id = NULL;
|
||||
g_autofree char *instance_dir = NULL;
|
||||
|
||||
instance_id = g_strdup_printf ("%u", g_random_int ());
|
||||
|
||||
instance_dir = g_build_filename (base_dir, instance_id, NULL);
|
||||
|
||||
/* We use an atomic mkdir to ensure the instance id is unique */
|
||||
if (mkdir (instance_dir, 0755) == 0)
|
||||
{
|
||||
g_autofree char *lock_file = g_build_filename (instance_dir, ".ref", NULL);
|
||||
glnx_autofd int lock_fd = -1;
|
||||
struct flock l = {
|
||||
.l_type = F_RDLCK,
|
||||
.l_whence = SEEK_SET,
|
||||
.l_start = 0,
|
||||
.l_len = 0
|
||||
};
|
||||
|
||||
/* Then we take a file lock inside the dir, hold that during
|
||||
* setup and in bwrap. Anyone trying to clean up unused
|
||||
* directories need to first verify that there is a .ref
|
||||
* file and take a write lock on .ref to ensure its not in
|
||||
* use. */
|
||||
lock_fd = open (lock_file, O_RDWR | O_CREAT | O_CLOEXEC, 0644);
|
||||
/* There is a tiny race here between the open creating the file and the lock succeeding.
|
||||
We work around that by only gc:ing "old" .ref files */
|
||||
if (lock_fd != -1 && fcntl (lock_fd, F_SETLK, &l) == 0)
|
||||
{
|
||||
*lock_fd_out = glnx_steal_fd (&lock_fd);
|
||||
g_debug ("Allocated instance id %s", instance_id);
|
||||
*host_dir_out = g_steal_pointer (&instance_dir);
|
||||
return g_steal_pointer (&instance_id);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
FlatpakInstance *
|
||||
flatpak_instance_new_for_id (const char *id)
|
||||
{
|
||||
@@ -462,7 +527,8 @@ flatpak_instance_iterate_all_and_gc (GPtrArray *out_instances)
|
||||
glnx_autofd int lock_fd = openat (iter.fd, ref_file, O_RDWR | O_CLOEXEC);
|
||||
if (lock_fd != -1 &&
|
||||
fstat (lock_fd, &statbuf) == 0 &&
|
||||
/* Only gc if created at least 3 secs ago, to work around race mentioned in flatpak_run_allocate_id() */
|
||||
/* Only gc if created at least 3 secs ago, to work around race mentioned in
|
||||
* flatpak_instance_allocate_id() */
|
||||
statbuf.st_mtime + 3 < time (NULL) &&
|
||||
fcntl (lock_fd, F_GETLK, &l) == 0 &&
|
||||
l.l_type == F_UNLCK)
|
||||
|
||||
@@ -2034,64 +2034,6 @@ flatpak_app_compute_permissions (GKeyFile *app_metadata,
|
||||
return g_steal_pointer (&app_context);
|
||||
}
|
||||
|
||||
static void
|
||||
flatpak_run_gc_ids (void)
|
||||
{
|
||||
flatpak_instance_iterate_all_and_gc (NULL);
|
||||
}
|
||||
|
||||
static char *
|
||||
flatpak_run_allocate_id (int *lock_fd_out)
|
||||
{
|
||||
g_autofree char *user_runtime_dir = flatpak_get_real_xdg_runtime_dir ();
|
||||
g_autofree char *base_dir = g_build_filename (user_runtime_dir, ".flatpak", NULL);
|
||||
int count;
|
||||
|
||||
g_mkdir_with_parents (base_dir, 0755);
|
||||
|
||||
flatpak_run_gc_ids ();
|
||||
|
||||
for (count = 0; count < 1000; count++)
|
||||
{
|
||||
g_autofree char *instance_id = NULL;
|
||||
g_autofree char *instance_dir = NULL;
|
||||
|
||||
instance_id = g_strdup_printf ("%u", g_random_int ());
|
||||
|
||||
instance_dir = g_build_filename (base_dir, instance_id, NULL);
|
||||
|
||||
/* We use an atomic mkdir to ensure the instance id is unique */
|
||||
if (mkdir (instance_dir, 0755) == 0)
|
||||
{
|
||||
g_autofree char *lock_file = g_build_filename (instance_dir, ".ref", NULL);
|
||||
glnx_autofd int lock_fd = -1;
|
||||
struct flock l = {
|
||||
.l_type = F_RDLCK,
|
||||
.l_whence = SEEK_SET,
|
||||
.l_start = 0,
|
||||
.l_len = 0
|
||||
};
|
||||
|
||||
/* Then we take a file lock inside the dir, hold that during
|
||||
* setup and in bwrap. Anyone trying to clean up unused
|
||||
* directories need to first verify that there is a .ref
|
||||
* file and take a write lock on .ref to ensure its not in
|
||||
* use. */
|
||||
lock_fd = open (lock_file, O_RDWR | O_CREAT | O_CLOEXEC, 0644);
|
||||
/* There is a tiny race here between the open creating the file and the lock succeeding.
|
||||
We work around that by only gc:ing "old" .ref files */
|
||||
if (lock_fd != -1 && fcntl (lock_fd, F_SETLK, &l) == 0)
|
||||
{
|
||||
*lock_fd_out = glnx_steal_fd (&lock_fd);
|
||||
g_debug ("Allocated instance id %s", instance_id);
|
||||
return g_steal_pointer (&instance_id);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
#ifdef HAVE_DCONF
|
||||
|
||||
static void
|
||||
@@ -2350,14 +2292,12 @@ flatpak_run_add_app_info_args (FlatpakBwrap *bwrap,
|
||||
g_autofree char *instance_id_host_dir = NULL;
|
||||
g_autofree char *instance_id_sandbox_dir = NULL;
|
||||
g_autofree char *instance_id_lock_file = NULL;
|
||||
g_autofree char *user_runtime_dir = flatpak_get_real_xdg_runtime_dir ();
|
||||
g_autofree char *arch = flatpak_decomposed_dup_arch (runtime_ref);
|
||||
|
||||
instance_id = flatpak_run_allocate_id (&lock_fd);
|
||||
instance_id = flatpak_instance_allocate_id (&instance_id_host_dir, &lock_fd);
|
||||
if (instance_id == NULL)
|
||||
return flatpak_fail_error (error, FLATPAK_ERROR_SETUP_FAILED, _("Unable to allocate instance id"));
|
||||
|
||||
instance_id_host_dir = g_build_filename (user_runtime_dir, ".flatpak", instance_id, NULL);
|
||||
instance_id_sandbox_dir = g_strdup_printf ("/run/user/%d/.flatpak/%s", getuid (), instance_id);
|
||||
instance_id_lock_file = g_build_filename (instance_id_sandbox_dir, ".ref", NULL);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user