mirror of
https://github.com/mofeng-git/One-KVM.git
synced 2026-01-29 00:51:53 +08:00
common fstab and libc funcs
This commit is contained in:
50
kvmd/fstab.py
Normal file
50
kvmd/fstab.py
Normal file
@@ -0,0 +1,50 @@
|
|||||||
|
# ========================================================================== #
|
||||||
|
# #
|
||||||
|
# KVMD - The main PiKVM daemon. #
|
||||||
|
# #
|
||||||
|
# Copyright (C) 2018-2022 Maxim Devaev <mdevaev@gmail.com> #
|
||||||
|
# #
|
||||||
|
# This program is free software: you can redistribute it and/or modify #
|
||||||
|
# it under the terms of the GNU General Public License as published by #
|
||||||
|
# the Free Software Foundation, either version 3 of the License, or #
|
||||||
|
# (at your option) any later version. #
|
||||||
|
# #
|
||||||
|
# This program is distributed in the hope that it will be useful, #
|
||||||
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of #
|
||||||
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the #
|
||||||
|
# GNU General Public License for more details. #
|
||||||
|
# #
|
||||||
|
# You should have received a copy of the GNU General Public License #
|
||||||
|
# along with this program. If not, see <https://www.gnu.org/licenses/>. #
|
||||||
|
# #
|
||||||
|
# ========================================================================== #
|
||||||
|
|
||||||
|
|
||||||
|
import re
|
||||||
|
import dataclasses
|
||||||
|
|
||||||
|
|
||||||
|
# =====
|
||||||
|
@dataclasses.dataclass(frozen=True)
|
||||||
|
class FstabStorage:
|
||||||
|
mount_path: str
|
||||||
|
root_path: str
|
||||||
|
user: str
|
||||||
|
|
||||||
|
|
||||||
|
def find_storage(target: str) -> FstabStorage:
|
||||||
|
fstab_path = "/etc/fstab"
|
||||||
|
with open(fstab_path) as file:
|
||||||
|
for line in file.read().split("\n"):
|
||||||
|
line = line.strip()
|
||||||
|
if line and not line.startswith("#"):
|
||||||
|
parts = line.split()
|
||||||
|
if len(parts) == 6:
|
||||||
|
options = dict(re.findall(r"X-kvmd\.%s-(root|user)(?:=([^,]+))?" % (target), parts[3]))
|
||||||
|
if options:
|
||||||
|
return FstabStorage(
|
||||||
|
mount_path=parts[1],
|
||||||
|
root_path=(options.get("root", "") or parts[1]),
|
||||||
|
user=options.get("user", ""),
|
||||||
|
)
|
||||||
|
raise RuntimeError(f"Can't find {target!r} mountpoint in {fstab_path}")
|
||||||
@@ -22,23 +22,10 @@
|
|||||||
|
|
||||||
import sys
|
import sys
|
||||||
import os
|
import os
|
||||||
import re
|
|
||||||
import shutil
|
import shutil
|
||||||
import dataclasses
|
|
||||||
import subprocess
|
import subprocess
|
||||||
|
|
||||||
|
from ... import fstab
|
||||||
# ====
|
|
||||||
_MOUNT_PATH = "/bin/mount"
|
|
||||||
_FSTAB_PATH = "/etc/fstab"
|
|
||||||
|
|
||||||
|
|
||||||
# =====
|
|
||||||
@dataclasses.dataclass(frozen=True)
|
|
||||||
class _Storage:
|
|
||||||
mount_path: str
|
|
||||||
root_path: str
|
|
||||||
user: str
|
|
||||||
|
|
||||||
|
|
||||||
# =====
|
# =====
|
||||||
@@ -46,29 +33,11 @@ def _log(msg: str) -> None:
|
|||||||
print(msg, file=sys.stderr)
|
print(msg, file=sys.stderr)
|
||||||
|
|
||||||
|
|
||||||
def _find_storage(target: str) -> _Storage:
|
|
||||||
assert target
|
|
||||||
with open(_FSTAB_PATH) as fstab_file:
|
|
||||||
for line in fstab_file.read().split("\n"):
|
|
||||||
line = line.strip()
|
|
||||||
if line and not line.startswith("#"):
|
|
||||||
parts = line.split()
|
|
||||||
if len(parts) == 6:
|
|
||||||
options = dict(re.findall(r"X-kvmd\.%s-(root|user)(?:=([^,]+))?" % (target), parts[3]))
|
|
||||||
if options:
|
|
||||||
return _Storage(
|
|
||||||
mount_path=parts[1],
|
|
||||||
root_path=(options.get("root", "") or parts[1]),
|
|
||||||
user=options.get("user", ""),
|
|
||||||
)
|
|
||||||
raise SystemExit(f"Can't find {target!r} mountpoint in {_FSTAB_PATH}")
|
|
||||||
|
|
||||||
|
|
||||||
def _remount(path: str, rw: bool) -> None:
|
def _remount(path: str, rw: bool) -> None:
|
||||||
mode = ("rw" if rw else "ro")
|
mode = ("rw" if rw else "ro")
|
||||||
_log(f"Remounting {path} to {mode.upper()}-mode ...")
|
_log(f"Remounting {path} to {mode.upper()}-mode ...")
|
||||||
try:
|
try:
|
||||||
subprocess.check_call([_MOUNT_PATH, "--options", f"remount,{mode}", path])
|
subprocess.check_call(["/bin/mount", "--options", f"remount,{mode}", path])
|
||||||
except subprocess.CalledProcessError as err:
|
except subprocess.CalledProcessError as err:
|
||||||
raise SystemExit(f"Can't remount: {err}")
|
raise SystemExit(f"Can't remount: {err}")
|
||||||
|
|
||||||
@@ -109,7 +78,8 @@ def main() -> None:
|
|||||||
|
|
||||||
rw = (sys.argv[1] == "rw")
|
rw = (sys.argv[1] == "rw")
|
||||||
|
|
||||||
storage = _find_storage(target)
|
assert target
|
||||||
|
storage = fstab.find_storage(target)
|
||||||
_remount(storage.mount_path, rw)
|
_remount(storage.mount_path, rw)
|
||||||
if rw and storage.root_path:
|
if rw and storage.root_path:
|
||||||
for name in dirs:
|
for name in dirs:
|
||||||
|
|||||||
@@ -22,12 +22,8 @@
|
|||||||
|
|
||||||
import sys
|
import sys
|
||||||
import os
|
import os
|
||||||
import ctypes
|
|
||||||
import ctypes.util
|
|
||||||
|
|
||||||
from ctypes import c_int
|
from ... import libc
|
||||||
from ctypes import c_uint
|
|
||||||
from ctypes import c_char_p
|
|
||||||
|
|
||||||
|
|
||||||
# =====
|
# =====
|
||||||
@@ -35,14 +31,6 @@ def main() -> None:
|
|||||||
if len(sys.argv) != 3:
|
if len(sys.argv) != 3:
|
||||||
raise SystemExit(f"Usage: {sys.argv[0]} <file1> <file2>")
|
raise SystemExit(f"Usage: {sys.argv[0]} <file1> <file2>")
|
||||||
|
|
||||||
path = ctypes.util.find_library("c")
|
|
||||||
if not path:
|
|
||||||
raise SystemExit("Where is libc?")
|
|
||||||
assert path
|
|
||||||
libc = ctypes.CDLL(path)
|
|
||||||
libc.renameat2.restype = c_int
|
|
||||||
libc.renameat2.argtypes = [c_int, c_char_p, c_int, c_char_p, c_uint]
|
|
||||||
|
|
||||||
result = libc.renameat2(
|
result = libc.renameat2(
|
||||||
-100, # AT_FDCWD
|
-100, # AT_FDCWD
|
||||||
os.fsencode(sys.argv[1]),
|
os.fsencode(sys.argv[1]),
|
||||||
@@ -52,4 +40,4 @@ def main() -> None:
|
|||||||
)
|
)
|
||||||
|
|
||||||
if result != 0:
|
if result != 0:
|
||||||
raise SystemExit(f"{sys.argv[0]}: {os.strerror(ctypes.get_errno())}")
|
raise SystemExit(f"{sys.argv[0]}: {os.strerror(libc.get_errno())}")
|
||||||
|
|||||||
@@ -25,7 +25,6 @@
|
|||||||
import sys
|
import sys
|
||||||
import os
|
import os
|
||||||
import asyncio
|
import asyncio
|
||||||
import ctypes
|
|
||||||
import struct
|
import struct
|
||||||
import dataclasses
|
import dataclasses
|
||||||
import types
|
import types
|
||||||
@@ -64,7 +63,7 @@ def _inotify_parsed_buffer(data: bytes) -> Generator[tuple[int, int, int, bytes]
|
|||||||
|
|
||||||
def _inotify_check(retval: int) -> int:
|
def _inotify_check(retval: int) -> int:
|
||||||
if retval < 0:
|
if retval < 0:
|
||||||
c_errno = ctypes.get_errno()
|
c_errno = libc.get_errno()
|
||||||
if c_errno == errno.ENOSPC: # pylint: disable=no-else-raise
|
if c_errno == errno.ENOSPC: # pylint: disable=no-else-raise
|
||||||
raise OSError(c_errno, "Inotify watch limit reached")
|
raise OSError(c_errno, "Inotify watch limit reached")
|
||||||
elif c_errno == errno.EMFILE:
|
elif c_errno == errno.EMFILE:
|
||||||
|
|||||||
@@ -26,6 +26,7 @@ import ctypes
|
|||||||
import ctypes.util
|
import ctypes.util
|
||||||
|
|
||||||
from ctypes import c_int
|
from ctypes import c_int
|
||||||
|
from ctypes import c_uint
|
||||||
from ctypes import c_uint32
|
from ctypes import c_uint32
|
||||||
from ctypes import c_char_p
|
from ctypes import c_char_p
|
||||||
from ctypes import c_void_p
|
from ctypes import c_void_p
|
||||||
@@ -42,6 +43,7 @@ def _load_libc() -> ctypes.CDLL:
|
|||||||
("inotify_init", c_int, []),
|
("inotify_init", c_int, []),
|
||||||
("inotify_add_watch", c_int, [c_int, c_char_p, c_uint32]),
|
("inotify_add_watch", c_int, [c_int, c_char_p, c_uint32]),
|
||||||
("inotify_rm_watch", c_int, [c_int, c_uint32]),
|
("inotify_rm_watch", c_int, [c_int, c_uint32]),
|
||||||
|
("renameat2", c_int, [c_int, c_char_p, c_int, c_char_p, c_uint]),
|
||||||
("free", c_int, [c_void_p]),
|
("free", c_int, [c_void_p]),
|
||||||
]:
|
]:
|
||||||
func = getattr(lib, name)
|
func = getattr(lib, name)
|
||||||
@@ -56,7 +58,10 @@ _libc = _load_libc()
|
|||||||
|
|
||||||
|
|
||||||
# =====
|
# =====
|
||||||
|
get_errno = ctypes.get_errno
|
||||||
|
|
||||||
inotify_init = _libc.inotify_init
|
inotify_init = _libc.inotify_init
|
||||||
inotify_add_watch = _libc.inotify_add_watch
|
inotify_add_watch = _libc.inotify_add_watch
|
||||||
inotify_rm_watch = _libc.inotify_rm_watch
|
inotify_rm_watch = _libc.inotify_rm_watch
|
||||||
|
renameat2 = _libc.renameat2
|
||||||
free = _libc.free
|
free = _libc.free
|
||||||
|
|||||||
@@ -38,12 +38,12 @@ from ....yamlconf import Option
|
|||||||
|
|
||||||
from ....validators.basic import valid_bool
|
from ....validators.basic import valid_bool
|
||||||
from ....validators.basic import valid_number
|
from ....validators.basic import valid_number
|
||||||
from ....validators.os import valid_abs_dir
|
|
||||||
from ....validators.os import valid_printable_filename
|
from ....validators.os import valid_printable_filename
|
||||||
from ....validators.os import valid_command
|
from ....validators.os import valid_command
|
||||||
|
|
||||||
from .... import aiotools
|
from .... import aiotools
|
||||||
from .... import aiohelpers
|
from .... import aiohelpers
|
||||||
|
from .... import fstab
|
||||||
|
|
||||||
from .. import MsdError
|
from .. import MsdError
|
||||||
from .. import MsdIsBusyError
|
from .. import MsdIsBusyError
|
||||||
@@ -143,8 +143,6 @@ class Plugin(BaseMsd): # pylint: disable=too-many-instance-attributes
|
|||||||
write_chunk_size: int,
|
write_chunk_size: int,
|
||||||
sync_chunk_size: int,
|
sync_chunk_size: int,
|
||||||
|
|
||||||
storage_path: str,
|
|
||||||
|
|
||||||
remount_cmd: list[str],
|
remount_cmd: list[str],
|
||||||
|
|
||||||
initial: dict,
|
initial: dict,
|
||||||
@@ -162,7 +160,7 @@ class Plugin(BaseMsd): # pylint: disable=too-many-instance-attributes
|
|||||||
self.__initial_cdrom: bool = initial["cdrom"]
|
self.__initial_cdrom: bool = initial["cdrom"]
|
||||||
|
|
||||||
self.__drive = Drive(gadget, instance=0, lun=0)
|
self.__drive = Drive(gadget, instance=0, lun=0)
|
||||||
self.__storage = Storage(storage_path)
|
self.__storage = Storage(fstab.find_storage("otgmsd").root_path)
|
||||||
|
|
||||||
self.__reader: (MsdFileReader | None) = None
|
self.__reader: (MsdFileReader | None) = None
|
||||||
self.__writer: (MsdFileWriter | None) = None
|
self.__writer: (MsdFileWriter | None) = None
|
||||||
@@ -181,8 +179,6 @@ class Plugin(BaseMsd): # pylint: disable=too-many-instance-attributes
|
|||||||
"write_chunk_size": Option(65536, type=functools.partial(valid_number, min=1024)),
|
"write_chunk_size": Option(65536, type=functools.partial(valid_number, min=1024)),
|
||||||
"sync_chunk_size": Option(4194304, type=functools.partial(valid_number, min=1024)),
|
"sync_chunk_size": Option(4194304, type=functools.partial(valid_number, min=1024)),
|
||||||
|
|
||||||
"storage": Option("/var/lib/kvmd/msd", type=valid_abs_dir, unpack_as="storage_path"),
|
|
||||||
|
|
||||||
"remount_cmd": Option([
|
"remount_cmd": Option([
|
||||||
"/usr/bin/sudo", "--non-interactive",
|
"/usr/bin/sudo", "--non-interactive",
|
||||||
"/usr/bin/kvmd-helper-otgmsd-remount", "{mode}",
|
"/usr/bin/kvmd-helper-otgmsd-remount", "{mode}",
|
||||||
|
|||||||
Reference in New Issue
Block a user