Steamのゲームを外部ディスクにインストールできない
Flatpakは /run/media/ 以下にマウントされた外部ディスクを暗黙的に認識する。このディスクはFlatpakコンテナ内で /run/user/xxx/doc に出現する。
問題は、このディスクにあるファイルを flock しているところで errno = 38 が出ている。このエラーコードは ENOSYS で、定義によると Function not implemented だった。以下はログの一部。
flock /run/user/60331/doc/f9ec6bc3/Steam/libraryfolder.vdf LOCK_SH failed. errno = 38flock /run/user/60331/doc/f9ec6bc3/Steam/steamapps/appmanifest_1384160.acf LOCK_SH failed. errno = 38flock /run/user/60331/doc/f9ec6bc3/Steam/steamapps/appmanifest_1892700.acf LOCK_SH failed. errno = 38flock /run/user/60331/doc/f9ec6bc3/Steam/steamapps/appmanifest_239120.acf LOCK_SH failed. errno = 38flock /run/user/60331/doc/f9ec6bc3/Steam/libraryfolder.vdf LOCK_SH failed. errno = 38Flatpakのパーミッションはおそらく read, write, grant-permissions, delete くらいしかないので、少なくとも読み書きするために必要なものは設定されている。
$ flatpak permissionsTable Object App Permissions Datagnome shortcuts-inhibitor qemu.desktop DENIED []background background com.valvesoftware.Steam yes 0x00documents f9ec6bc3 com.valvesoftware.Steam read,write,grant-permissions (b'/run/media/lufia/games/Steam', 76, 257, 4)類似の事例も報告されていた。
xdg-document-portal がFUSEとして本物のデバイスへのアクセスを中継しているが、これが flock を実装していないことが原因。
Steamを起動してマウント状態をみたところ、/run/user/60331 には tmpfs がマウントされている。
$ grep /run/user /proc/$(pidof -s steam)/mountstmpfs /run/user/60331 tmpfs rw,nosuid,nodev,relatime,size=3255252k,nr_inodes=813813,mode=700,uid=60331,gid=60331,inode64 0 0上のログでは flock でエラーが発生していたので、Flatpakコンテナ内で確認したところ同様のエラーになった。
$ flatpak run --command=bash com.valvesoftware.Steam
[📦 com.valvesoftware.Steam ~]$ cd /run/user/60331/doc/f9ec6bc3/Steam/
[📦 com.valvesoftware.Steam Steam]$ lslibraryfolder.vdf steamapps
[📦 com.valvesoftware.Steam Steam]$ flock -s libraryfolder.vdf lsflock: libraryfolder.vdf: Function not implemented当然だがホスト側から /run/media/ を触った場合は flock も動作する。
パーミッションを疑う
Section titled “パーミッションを疑う”Sandbox Permissionsによると、以下の場所にはアクセスが許されている。
- the runtime
- the app
- ~/.var/app/$FLATPAK_ID
- $XDG_RUNTIME_DIR/app/$FLATPAK_ID
Steamの場合、最後の場所は /run/user/(user)/app/com.valvesoftware.Steam/ のこと。なので /run/user/60331/doc/f9ec6bc3/Steam は許可されていない可能性はある。Sandbox Permissions で xdg-run/path に権限を与えれば /app 以外でも参照できるらしい。
ホストとコンテナで挙動が異なる理由
Section titled “ホストとコンテナで挙動が異なる理由”同じファイルシステムにアクセスしているのに、ホスト上で実行した時は問題なく、Flatpakコンテナ内だとエラーになる挙動の違いはどこに原因があるのか。直接マウントしているなら同じように動くはずなので、 /proc/mounts に出現しているこれが怪しい。
portal /run/flatpak/doc fuse.portal rw,nosuid,nodev,relatime,user_id=60331,group_id=60331 0 0portal デバイスの fuse.portal タイプとは何かというと、FlatpakがXDG Desktop Portal由来のディレクトリをマウントするためのものらしい。これはSandbox Permissions/Portalsによれば、サンドボックスを実現するための一部として実装されている。そうしてPortalはフロントエンドとバックエンドに分かれていて、バックエンドはそれぞれのデスクトップ環境ごとに存在する。
最初のログでエラーが発生していた /run/user/60331/doc はシンボリックリンクになっていて、参照先は /run/flatpak/doc を指していた。そういうことなら、 flock でロックが取れないのはXDG Desktop Portalのフロントエンドが実装していないからだろう。ここまで分かったので ValveSoftware/steam-for-linux リポジトリにイシューを作った。
修正を試みる
Section titled “修正を試みる”現状のソースコードでFUSEのオペレーションを定義しているのは document-portal-fuse.c の xdp_fuse_oper 変数。libfuse には高レベルAPIと低レベルAPIの2種類があるけれど、2024年頃の xdg-document-portal は低レベルAPIの fuse_lowlevel_ops 構造体で実装していた。
static struct fuse_lowlevel_ops xdp_fuse_oper = { .init = xdp_fuse_init_cb, .destroy = xdp_fuse_destroy_cb, .lookup = xdp_fuse_lookup, ... .setlk = xdp_fuse_setlk, .flock = xdp_fuse_flock, .fallocate = xdp_fuse_fallocate,};ここで flock メンバーにxdp_fuse_flock が設定されているけど、実装をみるとエラーを返しているだけだった。
static voidxdp_fuse_flock (fuse_req_t req, fuse_ino_t ino, struct fuse_file_info *fi, int lock_op){ const char *op = "FLOCK";
g_debug ("FLOCK %lx", ino);
xdp_reply_err (op, req, ENOSYS);}meson を使う。 doc/contributing.rst に書かれているように実行する。
sudo pacman -S meson pkgconf
meson setup . _buildmeson compile -C _buildmeson install # 必要なら
# cleanが必要ならninja -C _build cleanどうやってテストするか
Section titled “どうやってテストするか”systemdのユニットが /usr/lib/systemd/user/xdg-document-portal.service にあって、それは単に /usr/lib/xdg-document-portal を実行しているだけだった。
[Unit]Description=flatpak document portal servicePartOf=graphical-session.target
[Service]Type=dbusBusName=org.freedesktop.portal.DocumentsExecStart=/usr/lib/xdg-document-portalSlice=session.sliceということは一時的にこれを、手元でビルドしたコマンドに置き換えて試せばいい。
umount /run/user/60331/doc./xdg-document-portal &原因は分かったが、flock をポータルに実装するにあたっては困難な課題があるので諦めた。詳細は以下のリンク先に書いてある。