Make --symlink idempotent, or introduce a new --symlink-idempotent #549
Description
We've had several Flatpak issues of this general form:
- Flatpak bind-mounts some directory
/dir
into the sandbox (read-only or read/write) - Flatpak also wants to set up some symlink
/dir/symlink -> target
below that directory - The symlink already exists in the bind-mounted directory
- ... so
bwrap --symlink target /dir/symlink
fails withEEXIST
or this:
- Flatpak explicitly creates a symlink
/var/run -> /run
- The host system also has a symlink
/var/run -> /run
- Flatpak has been asked to share some filesystem with the container which happens to be below
/var/run
, like/var/run/media
, which it does by creating the symlink/var/run -> /run
and mounting/run/media
onto the sandbox's/run/media
- ... so it ends up with
bwrap --symlink /run /var/run ... --symlink /run /var/run
which fails withEEXIST
I see two ways this could be addressed.
The most general solution would be for Flatpak (and other projects that use bwrap) to be more aware of what it is mounting and how, so that if it wants to create a symlink below a directory it is sharing with the sandbox, it creates it in the source directory on the host instead of asking bwrap to create it below the destination mount point. Flatpak already has FlatpakExports
, which is aware of every --filesystem
that it is going to share with the sandbox, but is currently unaware of things like --persist
, leading to bugs; so this solution would involve extending FlatpakExports
to be aware of more locations. However, this general solution is going to be quite complicated.
A 90% solution would be to make bwrap --symlink
idempotent, or leave bwrap --symlink
as-is for bug-for-bug compatibility but introduce a new --symlink-idempotent
(or an --idempotent
modifier to be used like --size
, or something). How this would work:
- if the symlink doesn't already exist in
/newroot
, still create it, like--symlink
- if the symlink already exists in
/newroot
, and it has the same target we want to create, new behaviour: do nothing - if the symlink already exists in
/newroot
, and it has a different target but works out to be equivalent (like we want/var/run -> /run
when/var/run -> ../run
exists), maybe new behaviour: also do nothing (I am unsure whether this is desirable or not) - if the desired path already exists in
/newroot
but is not a symlink, or is a symlink pointing somewhere different, still fail like--symlink
would
Activity