From 85f818d82e9bc1ce779a6ea1b9bca922d1aa7cd8 Mon Sep 17 00:00:00 2001 From: liujinchang Date: Wed, 14 Aug 2024 17:17:07 +0800 Subject: [PATCH] feat: [ulnfs] add ulnfs [ulnfs] add to ulnfs Log: [ulnfs] add dlnfs to ulnfs Task: https://pms.uniontech.com/task-view-359649.html --- .../configs/org.deepin.dde.file-manager.json | 22 +++ assets/scripts/99dfm-ulnfs-automount | 7 + assets/scripts/dfm-dlnfs-automount | 5 +- assets/scripts/dfm-ulnfs-automount | 63 ++++++++ debian/dde-file-manager.install | 2 + src/dfm-base/CMakeLists.txt | 6 + src/dfm-base/utils/fileutils.cpp | 2 +- .../daemonplugin_mountcontrol_global.h | 5 +- .../mountcontroldbus.cpp | 4 + .../mounthelpers/dlnfsmounthelper.cpp | 4 +- .../mounthelpers/ulnfsmounthelper.cpp | 142 ++++++++++++++++++ .../mounthelpers/ulnfsmounthelper.h | 28 ++++ 12 files changed, 284 insertions(+), 6 deletions(-) create mode 100755 assets/scripts/99dfm-ulnfs-automount create mode 100755 assets/scripts/dfm-ulnfs-automount create mode 100755 src/plugins/daemon/daemonplugin-mountcontrol/mounthelpers/ulnfsmounthelper.cpp create mode 100644 src/plugins/daemon/daemonplugin-mountcontrol/mounthelpers/ulnfsmounthelper.h diff --git a/assets/configs/org.deepin.dde.file-manager.json b/assets/configs/org.deepin.dde.file-manager.json index 174f7ffd5e..1e9ddd97f7 100644 --- a/assets/configs/org.deepin.dde.file-manager.json +++ b/assets/configs/org.deepin.dde.file-manager.json @@ -112,6 +112,28 @@ "permissions":"readwrite", "visibility":"private" }, + "dfm.mount.ulnfs": { + "value":false, + "serial":0, + "flags":[], + "name":"Extend characters of file names by ulnfs", + "name[zh_CN]":"扩展文件名字符数", + "description[zh_CN]":"扩展文件名字符数需重启后才能生效", + "description":"To extend characters of file names, you should restart to make the configuration effective.", + "permissions":"readwrite", + "visibility":"private" + }, + "dfm.mount.ulnfs.defaults": { + "value":["$HOME"], + "serial":0, + "flags":[], + "name":"Dirs that support long file names by ulnfs", + "name[zh_CN]":"启用长文件名扩展的目录", + "description[zh_CN]":"默认启用长文件名扩展的目录", + "description":"Dirs that support long file names by default.", + "permissions":"readwrite", + "visibility":"private" + }, "dfm.mount.dlnfs": { "value":false, "serial":0, diff --git a/assets/scripts/99dfm-ulnfs-automount b/assets/scripts/99dfm-ulnfs-automount new file mode 100755 index 0000000000..50e21ba4be --- /dev/null +++ b/assets/scripts/99dfm-ulnfs-automount @@ -0,0 +1,7 @@ +# SPDX-FileCopyrightText: 2023 UnionTech Software Technology Co., Ltd. +# +# SPDX-License-Identifier: GPL-3.0-or-later + +echo "\ndfm_INFO: start main script to mount ulnfs at" $(date "+%Y-%m-%d %H:%M:%S.%3N") +[ -f /etc/deepin/dde-file-manager/dfm-ulnfs-automount ] && bash /etc/deepin/dde-file-manager/dfm-ulnfs-automount & +echo "dfm_INFO: end main script at" $(date "+%Y-%m-%d %H:%M:%S.%3N") diff --git a/assets/scripts/dfm-dlnfs-automount b/assets/scripts/dfm-dlnfs-automount index ab883cc27b..ff6f7ea290 100755 --- a/assets/scripts/dfm-dlnfs-automount +++ b/assets/scripts/dfm-dlnfs-automount @@ -13,7 +13,10 @@ query_dconfig="dde-dconfig --get -a org.deepin.dde.file-manager -r org.deepin.dd dlnfs_enable=`$query_dconfig dfm.mount.dlnfs` echo "dfm_INFO: dlnfs mount status: $dlnfs_enable" -if [ "$dlnfs_enable" == "true" ]; then +ulnfs_enable=`$query_dconfig dfm.mount.ulnfs` +echo "dfm_INFO: ulnfs mount status: $ulnfs_enable" + +if [ "$dlnfs_enable" == "true" ] && [ "$ulnfs_enable" != "true" ]; then default_paths=`$query_dconfig dfm.mount.dlnfs.defaults` echo "dfm_INFO: default mount paths: $default_paths" diff --git a/assets/scripts/dfm-ulnfs-automount b/assets/scripts/dfm-ulnfs-automount new file mode 100755 index 0000000000..5ce531178e --- /dev/null +++ b/assets/scripts/dfm-ulnfs-automount @@ -0,0 +1,63 @@ +#!/bin/bash + +# SPDX-FileCopyrightText: 2023 UnionTech Software Technology Co., Ltd. +# +# SPDX-License-Identifier: GPL-3.0-or-later + +start_time=$(date "+%Y-%m-%d %H:%M:%S.%3N") +echo -e "\n>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> started mounting ulnfs at [${start_time}]" +echo "dfm_INFO: user: $USER, uid: `id -u`, home: $HOME" + +query_dconfig="dde-dconfig --get -a org.deepin.dde.file-manager -r org.deepin.dde.file-manager -k " +# obtain the config of ulnfs mount enable +ulnfs_enable=`$query_dconfig dfm.mount.ulnfs` +echo "dfm_INFO: ulnfs mount status: $ulnfs_enable" + +if [ "$ulnfs_enable" == "true" ]; then + + default_paths=`$query_dconfig dfm.mount.ulnfs.defaults` + echo "dfm_INFO: default mount paths: $default_paths" + + formats='"[ " ]' + for path in $default_paths + do + contains=$(echo $formats | grep -F "${path}") + if [ "$contains" != "" ]; then + continue + fi + + # remove quotes and commas + path=${path//'"'/} + path=${path//','/} + abs_path=$path + + env_path=`echo $path | grep -o '\$[^/]*'` # env_path = $HOME + + if [ "$env_path" != "" ]; then + env_var=${env_path//'$'/} # env_var = HOME + abs_env_path=`echo ${!env_var}` # abs_env_path = /home/$USER + abs_path=${path/$env_path/$abs_env_path} #path = /home/xxxx/xxxx + fi + + echo "dfm_INFO: ========================= $path [$abs_path]" + if [ ! -d $abs_path ]; then + echo "dfm_WARNING: $abs_path do not exist" + continue + fi + + gdbus call -y \ + -d com.deepin.filemanager.daemon \ + -o /com/deepin/filemanager/daemon/MountControl \ + -m com.deepin.filemanager.daemon.MountControl.Mount \ + "${abs_path}" \ + "{'fsType': <'ulnfs'>}" \ + -t 1 + + step_time=$(date "+%Y-%m-%d %H:%M:%S.%3N") + echo -e "dfm_INFO: finished mount ${abs_path} at [${step_time}]\n" + done + +fi + +end_time=$(date "+%Y-%m-%d %H:%M:%S.%3N") +echo -e "<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< finished mounting ulnfs at [${end_time}]\n" diff --git a/debian/dde-file-manager.install b/debian/dde-file-manager.install index 2ae068cc46..bef96bcb20 100644 --- a/debian/dde-file-manager.install +++ b/debian/dde-file-manager.install @@ -27,3 +27,5 @@ usr/lib/systemd/user/ etc/dbus-1/system.d/com.deepin.filemanager.daemon.conf etc/X11/Xsession.d/99dfm-dlnfs-automount etc/deepin/dde-file-manager/dfm-dlnfs-automount +etc/X11/Xsession.d/99dfm-ulnfs-automount +etc/deepin/dde-file-manager/dfm-ulnfs-automount diff --git a/src/dfm-base/CMakeLists.txt b/src/dfm-base/CMakeLists.txt index 2fb0ebbcb8..dc376dd11c 100644 --- a/src/dfm-base/CMakeLists.txt +++ b/src/dfm-base/CMakeLists.txt @@ -181,6 +181,12 @@ install(FILES ${DLNFS_SCRIPT} DESTINATION ${CMAKE_INSTALL_SYSCONFDIR}/deepin/dde set(DLNFS_SCRIPT_LAUNCHER ${AssetsPath}/scripts/99dfm-dlnfs-automount) install(FILES ${DLNFS_SCRIPT_LAUNCHER} DESTINATION ${CMAKE_INSTALL_SYSCONFDIR}/X11/Xsession.d) +set(ULNFS_SCRIPT ${AssetsPath}/scripts/dfm-ulnfs-automount) +install(FILES ${ULNFS_SCRIPT} DESTINATION ${CMAKE_INSTALL_SYSCONFDIR}/deepin/dde-file-manager) + +set(ULNFS_SCRIPT_LAUNCHER ${AssetsPath}/scripts/99dfm-ulnfs-automount) +install(FILES ${ULNFS_SCRIPT_LAUNCHER} DESTINATION ${CMAKE_INSTALL_SYSCONFDIR}/X11/Xsession.d) + set(Mimetypes "${ShareDir}/mimetypes") FILE(GLOB MIMETYPE_FILES ${AssetsPath}/mimetypes/*) install(FILES ${MIMETYPE_FILES} DESTINATION ${Mimetypes}) diff --git a/src/dfm-base/utils/fileutils.cpp b/src/dfm-base/utils/fileutils.cpp index 038bd43bb8..80740531e1 100644 --- a/src/dfm-base/utils/fileutils.cpp +++ b/src/dfm-base/utils/fileutils.cpp @@ -1341,7 +1341,7 @@ QString FileUtils::normalPathToTrash(const QString &normal) bool FileUtils::supportLongName(const QUrl &url) { const static QList datas { - "vfat", "exfat", "ntfs", "fuseblk", "fuse.dlnfs" + "vfat", "exfat", "ntfs", "fuseblk", "fuse.dlnfs", "ulnfs" }; const QString &fileSystem = dfmio::DFMUtils::fsTypeFromUrl(url); diff --git a/src/plugins/daemon/daemonplugin-mountcontrol/daemonplugin_mountcontrol_global.h b/src/plugins/daemon/daemonplugin-mountcontrol/daemonplugin_mountcontrol_global.h index 88215c244b..2558490034 100644 --- a/src/plugins/daemon/daemonplugin-mountcontrol/daemonplugin_mountcontrol_global.h +++ b/src/plugins/daemon/daemonplugin-mountcontrol/daemonplugin_mountcontrol_global.h @@ -38,6 +38,7 @@ inline constexpr char kErrorMessage[] { "errMsg" }; namespace MountFstypeSupportedField { inline constexpr char kDlnFs[] { "dlnfs" }; +inline constexpr char kUlnFs[] { "ulnfs" }; inline constexpr char kCifs[] { "cifs" }; inline constexpr char kCommon[] { "common" }; } @@ -51,8 +52,8 @@ enum MountErrorCode { // NOTE(xust): use NAGATIVE value when return, avoid con kMountNotExist, kNotOwnerOfMount, - kDlnFsProcessNotExists, - kDlnMountMounted, + kLnFsProcessNotExists, + kLnMountMounted, kFusermountProcessNotExists, kUnhandledError = 1000 diff --git a/src/plugins/daemon/daemonplugin-mountcontrol/mountcontroldbus.cpp b/src/plugins/daemon/daemonplugin-mountcontrol/mountcontroldbus.cpp index f3cfa531b6..cab7eed0d8 100644 --- a/src/plugins/daemon/daemonplugin-mountcontrol/mountcontroldbus.cpp +++ b/src/plugins/daemon/daemonplugin-mountcontrol/mountcontroldbus.cpp @@ -8,6 +8,7 @@ #include "mounthelpers/cifsmounthelper.h" #include "mounthelpers/dlnfsmounthelper.h" #include "mounthelpers/commonmounthelper.h" +#include "mounthelpers/ulnfsmounthelper.h" #include #include @@ -79,9 +80,12 @@ MountControlDBusPrivate::MountControlDBusPrivate(MountControlDBus *qq) { CifsMountHelper *cifsHelper = new CifsMountHelper(qq); DlnfsMountHelper *dlnfsHelper = new DlnfsMountHelper(qq); + UlnfsMountHelper *ulnfsHelper = new UlnfsMountHelper(qq); CommonMountHelper *commonHelper = new CommonMountHelper(qq); cifsHelper->cleanMountPoint(); + mountHelpers.insert(MountFstypeSupportedField::kCifs, cifsHelper); + mountHelpers.insert(MountFstypeSupportedField::kUlnFs, ulnfsHelper); mountHelpers.insert(MountFstypeSupportedField::kDlnFs, dlnfsHelper); supportedFS.append(MountFstypeSupportedField::kDlnFs); mountHelpers.insert(MountFstypeSupportedField::kCommon, commonHelper); diff --git a/src/plugins/daemon/daemonplugin-mountcontrol/mounthelpers/dlnfsmounthelper.cpp b/src/plugins/daemon/daemonplugin-mountcontrol/mounthelpers/dlnfsmounthelper.cpp index 2fd937d7ed..73446e3b27 100644 --- a/src/plugins/daemon/daemonplugin-mountcontrol/mounthelpers/dlnfsmounthelper.cpp +++ b/src/plugins/daemon/daemonplugin-mountcontrol/mounthelpers/dlnfsmounthelper.cpp @@ -22,13 +22,13 @@ QVariantMap DlnfsMountHelper::mount(const QString &path, const QVariantMap &opts // 1. check if dlnfs at `path` is already exist. if (checkDlnfsExist(path)) return { { kResult, true }, - { kErrorCode, -kDlnMountMounted }, + { kErrorCode, -kLnMountMounted }, { kErrorMessage, QString("dlnfs is already mounted at %1").arg(path) } }; // 2. check `dlnfs` process exist. if (QStandardPaths::findExecutable(kDlnfs).isEmpty()) return { { kResult, false }, - { kErrorCode, -kDlnFsProcessNotExists }, + { kErrorCode, -kLnFsProcessNotExists }, { kErrorMessage, "dlnfs do not exist" } }; // 3. mount dlnfs on `path` diff --git a/src/plugins/daemon/daemonplugin-mountcontrol/mounthelpers/ulnfsmounthelper.cpp b/src/plugins/daemon/daemonplugin-mountcontrol/mounthelpers/ulnfsmounthelper.cpp new file mode 100755 index 0000000000..68a1124cba --- /dev/null +++ b/src/plugins/daemon/daemonplugin-mountcontrol/mounthelpers/ulnfsmounthelper.cpp @@ -0,0 +1,142 @@ +// SPDX-FileCopyrightText: 2023 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: GPL-3.0-or-later + +#include "ulnfsmounthelper.h" + +#include +#include +#include +#include +#include + +#include + +DAEMONPMOUNTCONTROL_USE_NAMESPACE + +QVariantMap UlnfsMountHelper::mount(const QString &path, const QVariantMap &opts) +{ + Q_UNUSED(opts) // not used yet and might be used in the future. + using namespace MountReturnField; + + static constexpr char kUlnfs[] { "ulnfs" }; + + // 1. check if ulnfs/dlnfs at `path` is already exist. + if (checkLnfsExist(path)) + return { { kResult, true }, + { kErrorCode, -kLnMountMounted }, + { kErrorMessage, QString("lnfs is already mounted at %1").arg(path) } }; + + // 2. check `ulnfs` is loaded. + if (!isModuleLoaded(kUlnfs) && !loadKernelModule(kUlnfs)) + return { { kResult, false }, + { kErrorCode, -kLnFsProcessNotExists }, + { kErrorMessage, QString("ulnfs is not loaded.") } }; + + // 3. mount ulnfs on `path` + auto aPath = path.toLocal8Bit().constData(); + int ret = ::mount(aPath, aPath, kUlnfs, 0, ""); + + fmInfo() << "ulnfs: mount result: " << ret << aPath; + if (ret == 0) { + return { { kMountPoint, aPath }, { kResult, true }, { kErrorCode, 0 } }; + } else { + int errNum = errno; + QString errMsg = strerror(errNum); + return { { kResult, false }, + { kErrorMessage, errMsg }, + { kErrorCode, parseErrorCodeByMsg(ret) } }; + } +} + +QVariantMap UlnfsMountHelper::unmount(const QString &path, const QVariantMap &opts) +{ + Q_UNUSED(opts) + using namespace MountReturnField; + + // 1. check if ulnfs is already mounted at `path` + if (!checkLnfsExist(path)) { + fmDebug() << "dlnfs: is not mounted at" << path; + return { { kResult, true }, + { kErrorCode, -kMountNotExist }, + { kErrorMessage, QString("dlnfs is not mounted at %1").arg(path) } }; + } + + // 2. do unmount ulnfs + + int ret = ::umount(path.toStdString().c_str()); + int err = errno; + QString errMsg = strerror(errno); + if (ret != 0) + fmWarning() << "unmount failed: " << path << err << errMsg; + + return { { kResult, ret == 0 }, { kErrorCode, err }, { kErrorMessage, errMsg } }; +} + +bool UlnfsMountHelper::isModuleLoaded(const QString &moduleName) +{ + QProcess process; + process.start("lsmod"); + process.waitForFinished(); + + QString output = process.readAllStandardOutput(); + QStringList lines = output.split('\n'); + + foreach (const QString &line, lines) { + if (line.startsWith(moduleName)) { + return true; + } + } + return false; +} + +bool UlnfsMountHelper::loadKernelModule(const QString &moduleName) +{ + QProcess modprobeProcess; + + modprobeProcess.start("modprobe", QStringList() << moduleName); + + if (!modprobeProcess.waitForFinished()) { + qCritical("Failed to load module: %s", qPrintable(modprobeProcess.errorString())); + return false; + } + + QByteArray output = modprobeProcess.readAllStandardOutput(); + qDebug() << moduleName << "Module loaded successfully."; + return true; +} + +bool UlnfsMountHelper::checkLnfsExist(const QString &path) +{ + QFile mountsFile("/proc/mounts"); + if (!mountsFile.open(QIODevice::ReadOnly)) { + qWarning() << "Failed to open /proc/mounts."; + return false; + } + + QByteArray content = mountsFile.readAll(); + QString fileContent(content); + + QStringList lines = fileContent.split('\n'); + for (const QString &line : lines) { + QStringList parts = line.split(' '); + + if (parts.size() >= 3) { + QString mountPoint = parts[1]; + QString fsType = parts[2]; + + if (mountPoint == path && fsType == "ulnfs") { + return true; + } + } + } + + return false; +} + +int UlnfsMountHelper::parseErrorCodeByMsg(int res) +{ + if (res == 0) + return 0; + return -kUnhandledError; +} diff --git a/src/plugins/daemon/daemonplugin-mountcontrol/mounthelpers/ulnfsmounthelper.h b/src/plugins/daemon/daemonplugin-mountcontrol/mounthelpers/ulnfsmounthelper.h new file mode 100644 index 0000000000..122f312fe5 --- /dev/null +++ b/src/plugins/daemon/daemonplugin-mountcontrol/mounthelpers/ulnfsmounthelper.h @@ -0,0 +1,28 @@ +// SPDX-FileCopyrightText: 2023 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: GPL-3.0-or-later + +#ifndef UlnfsMountHelper_H +#define UlnfsMountHelper_H + +#include "abstractmounthelper.h" + +DAEMONPMOUNTCONTROL_BEGIN_NAMESPACE +class UlnfsMountHelper : public AbstractMountHelper +{ +public: + explicit UlnfsMountHelper(QDBusContext *context) + : AbstractMountHelper(context) {} + + virtual QVariantMap mount(const QString &path, const QVariantMap &opts) override; + virtual QVariantMap unmount(const QString &path, const QVariantMap &opts) override; + +private: + bool loadKernelModule(const QString &moduleName); + bool checkLnfsExist(const QString &path); + bool isModuleLoaded(const QString &path); + int parseErrorCodeByMsg(int res); +}; +DAEMONPMOUNTCONTROL_END_NAMESPACE + +#endif // UlnfsMountHelper_H