fuse-overlayfs/contrib/fix-mode.py
Akihiko Odaki 90bea22c73 Prefer user.containers.override_stat over user.fuseoverlayfs.
Previously, fuse-overlayfs always used user.fuseoverlayfs.override_stat
for the upper layer while honoring user.containers.override_stat for
lower layers so that it can consume a layer created by
containers/storage.

It turned out that containers/storage also needs to get the overriding
extended attribute set by fuse-overlayfs and to set one for the upper
layer to make the root directory of the upper layer inherit the mode
of a lower layer. Adding code to get and to set
user.fuseoverlayfs.override_stat to containers/storage is a bit ugly.

The underlying problem is that fuse-overlayfs changes what name to use
ad hoc. Fix it by always preferring user.containers.override_stat, which
containers/storage honors, over user.fuseoverlayfs.overlayfs, which is
specific to fuse-overlayfs.

Signed-off-by: Akihiko Odaki <odaki@rsg.ci.i.u-tokyo.ac.jp>
2024-06-17 22:50:14 +09:00

52 lines
1.3 KiB
Python
Executable File

#!/bin/python
import os
import sys
import stat
import errno
XATTR_OVERRIDE_STAT_PRIVILEGED = "security.fuseoverlayfs.override_stat"
XATTR_OVERRIDE_CONTAINERS_STAT = "user.fuseoverlayfs.override_stat"
if os.geteuid() == 0:
xattr_name = XATTR_OVERRIDE_STAT_PRIVILEGED
else:
xattr_name = XATTR_OVERRIDE_CONTAINERS_STAT
cwd_fd = os.open(".", os.O_PATH)
def fix_path(path):
st = os.lstat(path)
content = "%s:%s:%o" % (st.st_uid, st.st_gid, stat.S_IMODE(st.st_mode))
try:
os.setxattr(path, xattr_name, str.encode(content), flags=os.XATTR_CREATE, follow_symlinks=False)
except Exception as e:
if e.errno == errno.EEXIST:
print("attr %s already present for %s: %s" % (xattr_name, path, e.errno))
return
raise e
fd = os.open(path, os.O_PATH|os.O_NOFOLLOW|os.O_NONBLOCK)
try:
proc_path = "/proc/self/fd/%d" % fd
os.chmod(proc_path, 0o755)
except Exception as e:
if e.errno != errno.ENOTSUP:
raise e
finally:
os.close(fd)
def fix_mode_directory(d):
for root, dirs, files in os.walk(d, topdown=False):
for i in dirs+files:
path = os.path.join(root, i)
fix_path(path)
fix_path(d)
for i in sys.argv[1:]:
fix_mode_directory(i)