flatpak-exports.c (flatpak-1.15.1.tar.xz) | : | flatpak-exports.c (flatpak-1.15.2.tar.xz) | ||
---|---|---|---|---|
skipping to change at line 55 | skipping to change at line 55 | |||
#include "flatpak-utils-base-private.h" | #include "flatpak-utils-base-private.h" | |||
#include "flatpak-dir-private.h" | #include "flatpak-dir-private.h" | |||
#include "flatpak-systemd-dbus-generated.h" | #include "flatpak-systemd-dbus-generated.h" | |||
#include "flatpak-error.h" | #include "flatpak-error.h" | |||
/* We don't want to export paths pointing into these, because they are readonly | /* We don't want to export paths pointing into these, because they are readonly | |||
(so we can't create mountpoints there) and don't match what's on the host any way. | (so we can't create mountpoints there) and don't match what's on the host any way. | |||
flatpak_abs_usrmerged_dirs get the same treatment without having to be listed | flatpak_abs_usrmerged_dirs get the same treatment without having to be listed | |||
here. */ | here. */ | |||
const char *dont_export_in[] = { | const char *dont_export_in[] = { | |||
"/usr", "/etc", "/app", "/dev", "/proc", NULL | "/.flatpak-info", | |||
"/app", | ||||
"/dev", | ||||
"/etc", | ||||
"/proc", | ||||
"/run/flatpak", | ||||
"/run/host", | ||||
"/usr", | ||||
NULL | ||||
}; | }; | |||
static char * | static char * | |||
make_relative (const char *base, const char *path) | make_relative (const char *base, const char *path) | |||
{ | { | |||
GString *s = g_string_new (""); | GString *s = g_string_new (""); | |||
while (*base != 0) | while (*base != 0) | |||
{ | { | |||
while (*base == '/') | while (*base == '/') | |||
skipping to change at line 431 | skipping to change at line 439 | |||
g_autofree const char **keys = (const char **) g_hash_table_get_keys_as_array (exports->hash, &n_keys); | g_autofree const char **keys = (const char **) g_hash_table_get_keys_as_array (exports->hash, &n_keys); | |||
g_autoptr(GList) eps = NULL; | g_autoptr(GList) eps = NULL; | |||
GList *l; | GList *l; | |||
struct stat buf; | struct stat buf; | |||
eps = g_hash_table_get_values (exports->hash); | eps = g_hash_table_get_values (exports->hash); | |||
eps = g_list_sort (eps, (GCompareFunc) compare_eps); | eps = g_list_sort (eps, (GCompareFunc) compare_eps); | |||
g_qsort_with_data (keys, n_keys, sizeof (char *), (GCompareDataFunc) flatpak_s trcmp0_ptr, NULL); | g_qsort_with_data (keys, n_keys, sizeof (char *), (GCompareDataFunc) flatpak_s trcmp0_ptr, NULL); | |||
flatpak_debug2 ("Converting FlatpakExports to bwrap arguments..."); | g_debug ("Converting FlatpakExports to bwrap arguments..."); | |||
for (l = eps; l != NULL; l = l->next) | for (l = eps; l != NULL; l = l->next) | |||
{ | { | |||
ExportedPath *ep = l->data; | ExportedPath *ep = l->data; | |||
const char *path = ep->path; | const char *path = ep->path; | |||
g_assert (is_export_mode (ep->mode)); | g_assert (is_export_mode (ep->mode)); | |||
if (ep->mode == FAKE_MODE_SYMLINK) | if (ep->mode == FAKE_MODE_SYMLINK) | |||
{ | { | |||
flatpak_debug2 ("\"%s\" is meant to be a symlink", path); | g_debug ("\"%s\" is meant to be a symlink", path); | |||
if (path_parent_is_mapped (keys, n_keys, exports->hash, path)) | if (path_parent_is_mapped (keys, n_keys, exports->hash, path)) | |||
{ | { | |||
flatpak_debug2 ("Not creating \"%s\" as symlink because its parent | g_debug ("Not creating \"%s\" as symlink because its parent is " | |||
is " | "already mapped", path); | |||
"already mapped", path); | ||||
} | } | |||
else | else | |||
{ | { | |||
g_autofree char *resolved = flatpak_exports_resolve_link_in_host ( exports, | g_autofree char *resolved = flatpak_exports_resolve_link_in_host ( exports, | |||
path, | path, | |||
NULL); | NULL); | |||
if (resolved) | if (resolved) | |||
{ | { | |||
g_autofree char *parent = g_path_get_dirname (path); | g_autofree char *parent = g_path_get_dirname (path); | |||
g_autofree char *relative = make_relative (parent, resolved); | g_autofree char *relative = make_relative (parent, resolved); | |||
flatpak_debug2 ("Resolved \"%s\" to \"%s\" in host", path, res | g_debug ("Resolved \"%s\" to \"%s\" in host", path, resolved); | |||
olved); | g_debug ("Creating \"%s\" -> \"%s\" in sandbox", path, relativ | |||
flatpak_debug2 ("Creating \"%s\" -> \"%s\" in sandbox", path, | e); | |||
relative); | ||||
flatpak_bwrap_add_args (bwrap, "--symlink", relative, path, N ULL); | flatpak_bwrap_add_args (bwrap, "--symlink", relative, path, N ULL); | |||
} | } | |||
else | else | |||
{ | { | |||
flatpak_debug2 ("Unable to resolve \"%s\" in host, skipping", path); | g_debug ("Unable to resolve \"%s\" in host, skipping", path); | |||
} | } | |||
} | } | |||
} | } | |||
else if (ep->mode == FAKE_MODE_TMPFS) | else if (ep->mode == FAKE_MODE_TMPFS) | |||
{ | { | |||
flatpak_debug2 ("\"%s\" is meant to be a tmpfs or empty directory", pa th); | g_debug ("\"%s\" is meant to be a tmpfs or empty directory", path); | |||
/* Mount a tmpfs to hide the subdirectory, but only if there | /* Mount a tmpfs to hide the subdirectory, but only if there | |||
is a pre-existing dir we can mount the path on. */ | is a pre-existing dir we can mount the path on. */ | |||
if (path_is_dir (exports, path)) | if (path_is_dir (exports, path)) | |||
{ | { | |||
if (!path_parent_is_mapped (keys, n_keys, exports->hash, path)) | if (!path_parent_is_mapped (keys, n_keys, exports->hash, path)) | |||
/* If the parent is not mapped, it will be a tmpfs, no need to m ount another one */ | /* If the parent is not mapped, it will be a tmpfs, no need to m ount another one */ | |||
{ | { | |||
flatpak_debug2 ("Parent of \"%s\" is not mapped, creating empt y directory", path); | g_debug ("Parent of \"%s\" is not mapped, creating empty direc tory", path); | |||
flatpak_bwrap_add_args (bwrap, "--dir", path, NULL); | flatpak_bwrap_add_args (bwrap, "--dir", path, NULL); | |||
} | } | |||
else | else | |||
{ | { | |||
flatpak_debug2 ("Parent of \"%s\" is mapped, creating tmpfs to shadow it", path); | g_debug ("Parent of \"%s\" is mapped, creating tmpfs to shadow it", path); | |||
flatpak_bwrap_add_args (bwrap, "--tmpfs", path, NULL); | flatpak_bwrap_add_args (bwrap, "--tmpfs", path, NULL); | |||
} | } | |||
} | } | |||
else | else | |||
{ | { | |||
flatpak_debug2 ("Not a directory, skipping: \"%s\"", path); | g_debug ("Not a directory, skipping: \"%s\"", path); | |||
} | } | |||
} | } | |||
else if (ep->mode == FAKE_MODE_DIR) | else if (ep->mode == FAKE_MODE_DIR) | |||
{ | { | |||
flatpak_debug2 ("\"%s\" is meant to be a directory", path); | g_debug ("\"%s\" is meant to be a directory", path); | |||
if (path_is_dir (exports, path)) | if (path_is_dir (exports, path)) | |||
{ | { | |||
flatpak_debug2 ("Ensuring \"%s\" is created as a directory", path) ; | g_debug ("Ensuring \"%s\" is created as a directory", path); | |||
flatpak_bwrap_add_args (bwrap, "--dir", path, NULL); | flatpak_bwrap_add_args (bwrap, "--dir", path, NULL); | |||
} | } | |||
else | else | |||
{ | { | |||
flatpak_debug2 ("Not a directory, skipping: \"%s\"", path); | g_debug ("Not a directory, skipping: \"%s\"", path); | |||
} | } | |||
} | } | |||
else | else | |||
{ | { | |||
flatpak_debug2 ("\"%s\" is meant to be shared (ro or rw) with the cont | g_debug ("\"%s\" is meant to be shared (ro or rw) with the container", | |||
ainer", | path); | |||
path); | ||||
flatpak_bwrap_add_args (bwrap, | flatpak_bwrap_add_args (bwrap, | |||
(ep->mode == FLATPAK_FILESYSTEM_MODE_READ_ONLY ) ? "--ro-bind" : "--bind", | (ep->mode == FLATPAK_FILESYSTEM_MODE_READ_ONLY ) ? "--ro-bind" : "--bind", | |||
path, path, NULL); | path, path, NULL); | |||
} | } | |||
} | } | |||
g_assert (exports->host_os >= FLATPAK_FILESYSTEM_MODE_NONE); | g_assert (exports->host_os >= FLATPAK_FILESYSTEM_MODE_NONE); | |||
g_assert (exports->host_os <= FLATPAK_FILESYSTEM_MODE_LAST); | g_assert (exports->host_os <= FLATPAK_FILESYSTEM_MODE_LAST); | |||
if (exports->host_os != FLATPAK_FILESYSTEM_MODE_NONE) | if (exports->host_os != FLATPAK_FILESYSTEM_MODE_NONE) | |||
skipping to change at line 758 | skipping to change at line 766 | |||
g_return_if_fail (is_export_mode (mode)); | g_return_if_fail (is_export_mode (mode)); | |||
ep = g_new0 (ExportedPath, 1); | ep = g_new0 (ExportedPath, 1); | |||
ep->path = g_strdup (path); | ep->path = g_strdup (path); | |||
if (old_ep != NULL) | if (old_ep != NULL) | |||
{ | { | |||
if (old_ep->mode < mode) | if (old_ep->mode < mode) | |||
{ | { | |||
flatpak_debug2 ("Increasing export mode from \"%s\" to \"%s\": %s", | g_debug ("Increasing export mode from \"%s\" to \"%s\": %s", | |||
export_mode_to_verb (old_ep->mode), | export_mode_to_verb (old_ep->mode), | |||
export_mode_to_verb (mode), | export_mode_to_verb (mode), | |||
path); | path); | |||
ep->mode = mode; | ep->mode = mode; | |||
} | } | |||
else | else | |||
{ | { | |||
flatpak_debug2 ("Not changing export mode from \"%s\" to \"%s\": %s", | g_debug ("Not changing export mode from \"%s\" to \"%s\": %s", | |||
export_mode_to_verb (old_ep->mode), | export_mode_to_verb (old_ep->mode), | |||
export_mode_to_verb (mode), | export_mode_to_verb (mode), | |||
path); | path); | |||
ep->mode = old_ep->mode; | ep->mode = old_ep->mode; | |||
} | } | |||
} | } | |||
else | else | |||
{ | { | |||
flatpak_debug2 ("Will %s: %s", export_mode_to_verb (mode), path); | g_debug ("Will %s: %s", export_mode_to_verb (mode), path); | |||
ep->mode = mode; | ep->mode = mode; | |||
} | } | |||
g_hash_table_replace (exports->hash, ep->path, ep); | g_hash_table_replace (exports->hash, ep->path, ep); | |||
} | } | |||
/* AUTOFS mounts are tricky, as using them as a source in a bind mount | /* AUTOFS mounts are tricky, as using them as a source in a bind mount | |||
* causes the mount to trigger, which can take a long time (or forever) | * causes the mount to trigger, which can take a long time (or forever) | |||
* waiting for a device or network mount. We try to open the directory | * waiting for a device or network mount. We try to open the directory | |||
* but time out after a while, ignoring the mount. Unfortunately we | * but time out after a while, ignoring the mount. Unfortunately we | |||
skipping to change at line 864 | skipping to change at line 872 | |||
if (G_UNLIKELY (exports->test_flags & FLATPAK_EXPORTS_TEST_FLAGS_AUTOFS)) | if (G_UNLIKELY (exports->test_flags & FLATPAK_EXPORTS_TEST_FLAGS_AUTOFS)) | |||
{ | { | |||
if (strcmp (path, "/broken-autofs") == 0) | if (strcmp (path, "/broken-autofs") == 0) | |||
return FALSE; | return FALSE; | |||
} | } | |||
return TRUE; | return TRUE; | |||
} | } | |||
/* We use level to avoid infinite recursion */ | /* We use level to avoid infinite recursion. | |||
* | ||||
* Note that some of the errors produced by this function are "real errors" | ||||
* and should show up as a user-visible warning, but others are relatively | ||||
* uninteresting, and in general none are actually fatal: we prefer to | ||||
* continue with fewer paths exposed rather than failing to run. */ | ||||
static gboolean | static gboolean | |||
_exports_path_expose (FlatpakExports *exports, | _exports_path_expose (FlatpakExports *exports, | |||
int mode, | int mode, | |||
const char *path, | const char *path, | |||
int level) | int level, | |||
GError **error) | ||||
{ | { | |||
g_autofree char *canonical = NULL; | g_autofree char *canonical = NULL; | |||
struct stat st; | struct stat st; | |||
struct statfs stfs; | struct statfs stfs; | |||
char *slash; | char *slash; | |||
int i; | int i; | |||
glnx_autofd int o_path_fd = -1; | glnx_autofd int o_path_fd = -1; | |||
g_return_val_if_fail (is_export_mode (mode), FALSE); | g_return_val_if_fail (is_export_mode (mode), FALSE); | |||
flatpak_debug2 ("Trying to %s: %s", export_mode_to_verb (mode), path); | g_debug ("Trying to %s: %s", export_mode_to_verb (mode), path); | |||
if (level > 40) /* 40 is the current kernel ELOOP check */ | if (level > 40) /* 40 is the current kernel ELOOP check */ | |||
{ | { | |||
g_debug ("Expose too deep, bail"); | g_set_error (error, G_IO_ERROR, G_IO_ERROR_TOO_MANY_LINKS, | |||
"%s", g_strerror (ELOOP)); | ||||
return FALSE; | return FALSE; | |||
} | } | |||
if (!g_path_is_absolute (path)) | if (!g_path_is_absolute (path)) | |||
{ | { | |||
g_debug ("Not exposing relative path %s", path); | g_set_error (error, G_IO_ERROR, G_IO_ERROR_INVALID_FILENAME, | |||
_("An absolute path is required")); | ||||
return FALSE; | return FALSE; | |||
} | } | |||
/* Check if it exists at all */ | /* Check if it exists at all */ | |||
o_path_fd = flatpak_exports_open_in_host (exports, path, O_PATH | O_NOFOLLOW); | o_path_fd = flatpak_exports_open_in_host (exports, path, O_PATH | O_NOFOLLOW); | |||
if (o_path_fd == -1) | if (o_path_fd == -1) | |||
{ | { | |||
g_debug ("Unable to open path %s to %s: %s", | int saved_errno = errno; | |||
path, export_mode_to_verb (mode), g_strerror (errno)); | ||||
/* Intentionally using G_IO_ERROR_NOT_FOUND even if errno is | ||||
* something different, so callers can suppress the warning in this | ||||
* relatively likely and uninteresting case: we don't particularly | ||||
* care whether this is happening as a result of ENOENT or EACCES | ||||
* or any other reason. */ | ||||
g_set_error (error, G_IO_ERROR, G_IO_ERROR_NOT_FOUND, | ||||
_("Unable to open path \"%s\": %s"), | ||||
path, g_strerror (saved_errno)); | ||||
return FALSE; | return FALSE; | |||
} | } | |||
if (fstat (o_path_fd, &st) != 0) | if (fstat (o_path_fd, &st) != 0) | |||
{ | return glnx_throw (error, | |||
g_debug ("Unable to get file type of %s: %s", path, g_strerror (errno)); | _("Unable to get file type of \"%s\": %s"), | |||
return FALSE; | path, g_strerror (errno)); | |||
} | ||||
/* Don't expose weird things */ | /* Don't expose weird things */ | |||
if (!(S_ISDIR (st.st_mode) || | if (!(S_ISDIR (st.st_mode) || | |||
S_ISREG (st.st_mode) || | S_ISREG (st.st_mode) || | |||
S_ISLNK (st.st_mode) || | S_ISLNK (st.st_mode) || | |||
S_ISSOCK (st.st_mode))) | S_ISSOCK (st.st_mode))) | |||
{ | return glnx_throw (error, | |||
g_debug ("%s has unsupported file type 0o%o", path, st.st_mode & S_IFMT); | _("File \"%s\" has unsupported type 0o%o"), | |||
return FALSE; | path, st.st_mode & S_IFMT); | |||
} | ||||
/* O_PATH + fstatfs is the magic that we need to statfs without automounting t he target */ | /* O_PATH + fstatfs is the magic that we need to statfs without automounting t he target */ | |||
if (fstatfs (o_path_fd, &stfs) != 0) | if (fstatfs (o_path_fd, &stfs) != 0) | |||
{ | return glnx_throw (error, | |||
g_debug ("Unable to get filesystem information for %s: %s", | _("Unable to get filesystem information for \"%s\": %s"), | |||
path, g_strerror (errno)); | path, g_strerror (errno)); | |||
return FALSE; | ||||
} | ||||
if (stfs.f_type == AUTOFS_SUPER_MAGIC || | if (stfs.f_type == AUTOFS_SUPER_MAGIC || | |||
(G_UNLIKELY (exports->test_flags & FLATPAK_EXPORTS_TEST_FLAGS_AUTOFS) && | (G_UNLIKELY (exports->test_flags & FLATPAK_EXPORTS_TEST_FLAGS_AUTOFS) && | |||
S_ISDIR (st.st_mode))) | S_ISDIR (st.st_mode))) | |||
{ | { | |||
if (!check_if_autofs_works (exports, path)) | if (!check_if_autofs_works (exports, path)) | |||
{ | { | |||
g_debug ("ignoring blocking autofs path %s", path); | g_set_error (error, G_IO_ERROR, G_IO_ERROR_WOULD_BLOCK, | |||
_("Ignoring blocking autofs path \"%s\""), path); | ||||
return FALSE; | return FALSE; | |||
} | } | |||
} | } | |||
/* Syntactic canonicalization only, no need to use host_fd */ | /* Syntactic canonicalization only, no need to use host_fd */ | |||
path = canonical = flatpak_canonicalize_filename (path); | path = canonical = flatpak_canonicalize_filename (path); | |||
for (i = 0; dont_export_in[i] != NULL; i++) | for (i = 0; dont_export_in[i] != NULL; i++) | |||
{ | { | |||
/* Don't expose files in non-mounted dirs like /app or /usr, as | /* Don't expose files in non-mounted dirs like /app or /usr, as | |||
they are not the same as on the host, and we generally can't | they are not the same as on the host, and we generally can't | |||
create the parents for them anyway */ | create the parents for them anyway */ | |||
if (flatpak_has_path_prefix (path, dont_export_in[i])) | if (flatpak_has_path_prefix (path, dont_export_in[i])) | |||
{ | { | |||
g_debug ("skipping export for path %s in unsupported prefix", path); | g_set_error (error, G_IO_ERROR, G_IO_ERROR_NOT_MOUNTABLE_FILE, | |||
_("Path \"%s\" is reserved by Flatpak"), | ||||
dont_export_in[i]); | ||||
return FALSE; | ||||
} | ||||
/* Also don't expose directories that are a parent of a directory | ||||
* that is "owned" by the sandboxing framework. For example, because | ||||
* Flatpak controls /run/host and /run/flatpak, we cannot allow | ||||
* --filesystem=/run, which would prevent us from creating the | ||||
* contents of /run/host and /run/flatpak. */ | ||||
if (flatpak_has_path_prefix (dont_export_in[i], path)) | ||||
{ | ||||
g_set_error (error, G_IO_ERROR, G_IO_ERROR_NOT_MOUNTABLE_FILE, | ||||
_("Path \"%s\" is reserved by Flatpak"), | ||||
dont_export_in[i]); | ||||
return FALSE; | return FALSE; | |||
} | } | |||
} | } | |||
for (i = 0; flatpak_abs_usrmerged_dirs[i] != NULL; i++) | for (i = 0; flatpak_abs_usrmerged_dirs[i] != NULL; i++) | |||
{ | { | |||
/* Same as /usr, but for the directories that get merged into /usr */ | /* Same as /usr, but for the directories that get merged into /usr. | |||
* Keep the translatable string here the same as the one above */ | ||||
if (flatpak_has_path_prefix (path, flatpak_abs_usrmerged_dirs[i])) | if (flatpak_has_path_prefix (path, flatpak_abs_usrmerged_dirs[i])) | |||
{ | { | |||
g_debug ("skipping export for path %s in a /usr-merged directory", pat | g_set_error (error, G_IO_ERROR, G_IO_ERROR_NOT_MOUNTABLE_FILE, | |||
h); | _("Path \"%s\" is reserved by Flatpak"), | |||
flatpak_abs_usrmerged_dirs[i]); | ||||
return FALSE; | return FALSE; | |||
} | } | |||
} | } | |||
/* Handle any symlinks prior to the target itself. This includes path itself, | /* Handle any symlinks prior to the target itself. This includes path itself, | |||
because we expose the target of the symlink. */ | because we expose the target of the symlink. */ | |||
slash = canonical; | slash = canonical; | |||
do | do | |||
{ | { | |||
slash = strchr (slash + 1, '/'); | slash = strchr (slash + 1, '/'); | |||
if (slash) | if (slash) | |||
*slash = 0; | *slash = 0; | |||
if (!path_is_symlink (exports, path)) | if (!path_is_symlink (exports, path)) | |||
{ | { | |||
flatpak_debug2 ("%s is not a symlink", path); | g_debug ("%s is not a symlink", path); | |||
} | } | |||
else if (never_export_as_symlink (path)) | else if (never_export_as_symlink (path)) | |||
{ | { | |||
flatpak_debug2 ("%s is a symlink, but we avoid exporting it as such", path); | g_debug ("%s is a symlink, but we avoid exporting it as such", path); | |||
} | } | |||
else | else | |||
{ | { | |||
g_autoptr(GError) error = NULL; | g_autoptr(GError) local_error = NULL; | |||
g_autofree char *resolved = flatpak_exports_resolve_link_in_host (expo | g_autofree char *resolved = flatpak_exports_resolve_link_in_host (expo | |||
rts, path, &error); | rts, path, &local_error); | |||
g_autofree char *new_target = NULL; | g_autofree char *new_target = NULL; | |||
if (resolved) | if (resolved) | |||
{ | { | |||
flatpak_debug2 ("%s is a symlink, resolved to %s", path, resolved) ; | g_debug ("%s is a symlink, resolved to %s", path, resolved); | |||
if (slash) | if (slash) | |||
new_target = g_build_filename (resolved, slash + 1, NULL); | new_target = g_build_filename (resolved, slash + 1, NULL); | |||
else | else | |||
new_target = g_strdup (resolved); | new_target = g_strdup (resolved); | |||
flatpak_debug2 ("Trying to export the target instead: %s", new_tar get); | g_debug ("Trying to export the target instead: %s", new_target); | |||
if (_exports_path_expose (exports, mode, new_target, level + 1)) | if (_exports_path_expose (exports, mode, new_target, level + 1, &l ocal_error)) | |||
{ | { | |||
do_export_path (exports, path, FAKE_MODE_SYMLINK); | do_export_path (exports, path, FAKE_MODE_SYMLINK); | |||
return TRUE; | return TRUE; | |||
} | } | |||
flatpak_debug2 ("Could not export target %s, so ignoring %s", | g_debug ("Could not export target %s, so ignoring %s", | |||
new_target, path); | new_target, path); | |||
g_propagate_error (error, g_steal_pointer (&local_error)); | ||||
return FALSE; | return FALSE; | |||
} | } | |||
else | else | |||
{ | { | |||
flatpak_debug2 ("%s is a symlink but we were unable to resolve it: | g_set_error (error, G_IO_ERROR, G_IO_ERROR_NOT_FOUND, | |||
%s", | _("Unable to resolve symbolic link \"%s\": %s"), | |||
path, error->message); | path, local_error->message); | |||
return FALSE; | return FALSE; | |||
} | } | |||
} | } | |||
if (slash) | if (slash) | |||
*slash = '/'; | *slash = '/'; | |||
} | } | |||
while (slash != NULL); | while (slash != NULL); | |||
do_export_path (exports, path, mode); | do_export_path (exports, path, mode); | |||
return TRUE; | return TRUE; | |||
} | } | |||
void | gboolean | |||
flatpak_exports_add_path_expose (FlatpakExports *exports, | flatpak_exports_add_path_expose (FlatpakExports *exports, | |||
FlatpakFilesystemMode mode, | FlatpakFilesystemMode mode, | |||
const char *path) | const char *path, | |||
{ | GError **error) | |||
g_return_if_fail (mode > FLATPAK_FILESYSTEM_MODE_NONE); | { | |||
g_return_if_fail (mode <= FLATPAK_FILESYSTEM_MODE_LAST); | g_return_val_if_fail (mode > FLATPAK_FILESYSTEM_MODE_NONE, FALSE); | |||
_exports_path_expose (exports, mode, path, 0); | g_return_val_if_fail (mode <= FLATPAK_FILESYSTEM_MODE_LAST, FALSE); | |||
return _exports_path_expose (exports, mode, path, 0, error); | ||||
} | } | |||
void | gboolean | |||
flatpak_exports_add_path_tmpfs (FlatpakExports *exports, | flatpak_exports_add_path_tmpfs (FlatpakExports *exports, | |||
const char *path) | const char *path, | |||
GError **error) | ||||
{ | { | |||
_exports_path_expose (exports, FAKE_MODE_TMPFS, path, 0); | return _exports_path_expose (exports, FAKE_MODE_TMPFS, path, 0, error); | |||
} | } | |||
void | gboolean | |||
flatpak_exports_add_path_expose_or_hide (FlatpakExports *exports, | flatpak_exports_add_path_expose_or_hide (FlatpakExports *exports, | |||
FlatpakFilesystemMode mode, | FlatpakFilesystemMode mode, | |||
const char *path) | const char *path, | |||
GError **error) | ||||
{ | { | |||
g_return_if_fail (mode >= FLATPAK_FILESYSTEM_MODE_NONE); | g_return_val_if_fail (mode >= FLATPAK_FILESYSTEM_MODE_NONE, FALSE); | |||
g_return_if_fail (mode <= FLATPAK_FILESYSTEM_MODE_LAST); | g_return_val_if_fail (mode <= FLATPAK_FILESYSTEM_MODE_LAST, FALSE); | |||
if (mode == FLATPAK_FILESYSTEM_MODE_NONE) | if (mode == FLATPAK_FILESYSTEM_MODE_NONE) | |||
flatpak_exports_add_path_tmpfs (exports, path); | return flatpak_exports_add_path_tmpfs (exports, path, error); | |||
else | else | |||
flatpak_exports_add_path_expose (exports, mode, path); | return flatpak_exports_add_path_expose (exports, mode, path, error); | |||
} | } | |||
void | gboolean | |||
flatpak_exports_add_path_dir (FlatpakExports *exports, | flatpak_exports_add_path_dir (FlatpakExports *exports, | |||
const char *path) | const char *path, | |||
GError **error) | ||||
{ | { | |||
_exports_path_expose (exports, FAKE_MODE_DIR, path, 0); | return _exports_path_expose (exports, FAKE_MODE_DIR, path, 0, error); | |||
} | } | |||
void | void | |||
flatpak_exports_add_host_etc_expose (FlatpakExports *exports, | flatpak_exports_add_host_etc_expose (FlatpakExports *exports, | |||
FlatpakFilesystemMode mode) | FlatpakFilesystemMode mode) | |||
{ | { | |||
g_return_if_fail (mode > FLATPAK_FILESYSTEM_MODE_NONE); | g_return_if_fail (mode > FLATPAK_FILESYSTEM_MODE_NONE); | |||
g_return_if_fail (mode <= FLATPAK_FILESYSTEM_MODE_LAST); | g_return_if_fail (mode <= FLATPAK_FILESYSTEM_MODE_LAST); | |||
exports->host_etc = mode; | exports->host_etc = mode; | |||
End of changes. 47 change blocks. | ||||
92 lines changed or deleted | 132 lines changed or added |