diff --git a/.gear/gpui.spec b/.gear/gpui.spec index 3d6fabb..e8cbcac 100644 --- a/.gear/gpui.spec +++ b/.gear/gpui.spec @@ -17,7 +17,6 @@ BuildRequires: qt5-base-devel BuildRequires: qt5-declarative-devel BuildRequires: qt5-tools-devel BuildRequires: libsmbclient-devel libsmbclient -BuildRequires: libnemofolderlistmodel-devel BuildRequires: qt5-base-common BuildRequires: doxygen @@ -62,6 +61,8 @@ Group policy editor %_libdir/gpui/plugins/libshortcuts-plugin.so %_libdir/gpui/plugins/libvariables-plugin.so +%_libdir/gpui/plugins/libsmb-storage-plugin.so + %changelog * Tue Jun 08 2021 Vladimir Rubanov 0.1.0-alt1 - Initial build diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 617e9f5..87b34d4 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -15,16 +15,6 @@ jobs: - name: Checkout uses: actions/checkout@v2 - - name: Download artifact - uses: august-alt/action-download-artifact@v2 - with: - github_token: ${{secrets.GITHUB_TOKEN}} - workflow: main.yml - branch: alt-linux - name: libfolderlistmodel-${{ matrix.alt-version.artifact }}-${{ matrix.architecture }} - path: RPMS - repo: august-alt/filemanager-app - - run: docker build . --file Dockerfile --tag build-environment --build-arg USER_ID=$(id -u) --build-arg GROUP_ID=$(id -g) --build-arg DISTR=${{ matrix.alt-version.dist }} --build-arg ARCH=${{ matrix.architecture }} - if: ${{ matrix.architecture == 'i386' }} diff --git a/script/build.sh b/script/build.sh index 74756bf..f0e48f7 100755 --- a/script/build.sh +++ b/script/build.sh @@ -9,8 +9,5 @@ mkdir /home/builder2/.hasher cp /app/hasher/config /home/builder2/.hasher/config hsh --initroot-only --no-wait-lock -vv /home/builder2/hasher -hsh-install /home/builder2/hasher /app/RPMS/libnemofolderlistmodel-0.1.0-alt1.x86_64.rpm -hsh-install /home/builder2/hasher /app/RPMS/libnemofolderlistmodel-devel-0.1.0-alt1.x86_64.rpm - cd /app/ && gear --hasher -- hsh-rebuild /home/builder2/hasher cp /home/builder2/hasher/repo/x86_64/RPMS.hasher/*.rpm /app/RPMS/ diff --git a/src/gui/CMakeLists.txt b/src/gui/CMakeLists.txt index d20b072..741ea2e 100644 --- a/src/gui/CMakeLists.txt +++ b/src/gui/CMakeLists.txt @@ -2,14 +2,6 @@ find_package(Qt5 COMPONENTS Widgets Qml LinguistTools REQUIRED) set(CMAKE_INCLUDE_CURRENT_DIR ON) -include_directories( - /usr/include/libnemofolderlistmodel/ - /usr/include/libnemofolderlistmodel/net - /usr/include/libnemofolderlistmodel/smb - /usr/include/libnemofolderlistmodel/disk - /usr/include/libnemofolderlistmodel/trash - ) - set(HEADERS contentwidget.h commandlineoptions.h @@ -19,7 +11,6 @@ set(HEADERS mainwindow.h mainwindowsettings.h presentationbuilder.h - smbfilebrowser.h ) set(SOURCES @@ -30,15 +21,12 @@ set(SOURCES mainwindow.cpp mainwindowsettings.cpp presentationbuilder.cpp - smbfilebrowser.cpp - smbfilebrowserslots.cpp ) set(UI_FORMS contentwidget.ui listboxdialog.ui mainwindow.ui - smbfilebrowser.ui ) set(MOC_HEADERS @@ -46,7 +34,6 @@ set(MOC_HEADERS listboxdialog.h mainwindow.h mainwindowsettings.h - smbfilebrowser.h ) set(TS_FILES @@ -72,27 +59,4 @@ qt5_add_resources(LIB_RESOURCES ${RESOURCES_SRC}) add_gpui_library(gpui-gui ${UI_SOURCES} ${MOC_SOURCES} ${SOURCES} ${LIB_RESOURCES}) target_link_libraries(gpui-gui Qt5::Widgets Qt5::Qml) target_link_libraries(gpui-gui gpui-model gpui-io) - -find_package(PkgConfig REQUIRED) - -pkg_check_modules(Nemo REQUIRED IMPORTED_TARGET libnemofolderlistmodel) -target_link_libraries(gpui-gui PkgConfig::Nemo) - -## samba requires libsmbclient -find_path(SAMBA_INCLUDE_DIR - NAMES libsmbclient.h - HINTS /usr/include/smbclient /usr/include/samba /usr/include/samba-3.0 /usr/include/samba-4.0 - ) -find_library(SAMBA_LIBRARIES NAMES smbclient ) -message(STATUS "samba include=${SAMBA_INCLUDE_DIR}") -message(STATUS "samba lib=${SAMBA_LIBRARIES}=${SAMBA_LIBRARIES}") - -if(SAMBA_INCLUDE_DIR AND SAMBA_LIBRARIES) - message(STATUS "Found samba: include=${SAMBA_INCLUDE_DIR} library=${SAMBA_LIBRARIES}") - INCLUDE_DIRECTORIES(${SAMBA_INCLUDE_DIR}) - TARGET_LINK_LIBRARIES(gpui-gui ${SAMBA_LIBRARIES}) -else(SAMBA_INCLUDE_DIR AND SAMBA_LIBRARIES) - message(FATAL_ERROR "Could not find Samba libsmbclient") -endif(SAMBA_INCLUDE_DIR AND SAMBA_LIBRARIES) -mark_as_advanced(SAMBA_INCLUDE_DIR SAMBA_LIBRARIES) -## end samba confiuration +target_link_libraries(gpui-gui smb-storage-static) diff --git a/src/gui/mainwindow.cpp b/src/gui/mainwindow.cpp index 0248015..d4db4f0 100644 --- a/src/gui/mainwindow.cpp +++ b/src/gui/mainwindow.cpp @@ -37,9 +37,7 @@ #include "../io/registryfile.h" #include "../io/registryfileformat.h" -#include "smbfilebrowser.h" - -#include +#include "../plugins/storage/smb/smbfile.h" void registerResources() { @@ -108,13 +106,13 @@ void save(const std::string &fileName, std::shared_ptrstr().size() > 0) + if (isOpen && oss->str().size() > 0) { smbLocationItemFile.write(&oss->str().at(0), oss->str().size()); } @@ -123,7 +121,11 @@ void save(const std::string &fileName, std::shared_ptrstr().size() > 0) { registryFile.write(&oss->str().at(0), oss->str().size()); @@ -131,6 +133,7 @@ void save(const std::string &fileName, std::shared_ptrsettings->restoreSettings(); connect(ui->actionOpenPolicyDirectory, &QAction::triggered, this, &MainWindow::onDirectoryOpen); - connect(ui->actionOpenUserRegistrySource, &QAction::triggered, this, &MainWindow::onUserRegistrySourceOpen); - connect(ui->actionOpenMachineRegistrySource, &QAction::triggered, this, &MainWindow::onMachineRegistrySourceOpen); connect(ui->actionSaveRegistrySource, &QAction::triggered, this, &MainWindow::onRegistrySourceSave); connect(ui->treeView, &QTreeView::clicked, d->contentWidget, &ContentWidget::modelItemSelected); @@ -241,24 +242,6 @@ void MainWindow::onDirectoryOpen() loadPolicyBundleFolder(d->options.policyBundle, d->localeName); } -void MainWindow::onUserRegistrySourceOpen() -{ - onRegistrySourceOpen(d->userRegistry, d->userRegistrySource, - [&](model::registry::AbstractRegistrySource* source) - { - d->contentWidget->setUserRegistrySource(source); - }); -} - -void MainWindow::onMachineRegistrySourceOpen() -{ - onRegistrySourceOpen(d->machineRegistry, d->machineRegistrySource, - [&](model::registry::AbstractRegistrySource* source) - { - d->contentWidget->setMachineRegistrySource(source); - }); -} - void MainWindow::onRegistrySourceSave() { if (!d->machineRegistryPath.isEmpty()) @@ -315,20 +298,6 @@ void MainWindow::onLanguageChanged(QAction *action) ui->treeView->selectionModel()->clearSelection(); } -void MainWindow::onRegistrySourceOpen(std::shared_ptr& registry, - std::unique_ptr& source, - std::function callback) -{ - SmbFileBrowser browser(this); - - connect(&browser, &SmbFileBrowser::onPolOpen, this, [&](const QString& path) - { - onPolFileOpen(path, registry, source, callback); - }); - - browser.exec(); -} - void MainWindow::onPolFileOpen(const QString &path, std::shared_ptr ®istry, std::unique_ptr &source, @@ -342,7 +311,7 @@ void MainWindow::onPolFileOpen(const QString &path, if (path.startsWith("smb://")) { - SmbLocationItemFile smbLocationItemFile(path); + gpui::smb::SmbFile smbLocationItemFile(path); smbLocationItemFile.open(QFile::ReadWrite); stringvalues->resize(smbLocationItemFile.size(), 0); smbLocationItemFile.read(&stringvalues->at(0), smbLocationItemFile.size()); diff --git a/src/gui/mainwindow.h b/src/gui/mainwindow.h index 1380428..cb01382 100644 --- a/src/gui/mainwindow.h +++ b/src/gui/mainwindow.h @@ -60,8 +60,6 @@ namespace gpui { private slots: void onDirectoryOpen(); - void onMachineRegistrySourceOpen(); - void onUserRegistrySourceOpen(); void onRegistrySourceSave(); void on_actionExit_triggered(); @@ -69,10 +67,6 @@ namespace gpui { void onLanguageChanged(QAction *action); private: - void onRegistrySourceOpen(std::shared_ptr& registry, - std::unique_ptr& source, - std::function callback); - void onPolFileOpen(const QString& path, std::shared_ptr& registry, std::unique_ptr& source, diff --git a/src/gui/mainwindow.ui b/src/gui/mainwindow.ui index dfb1263..4dd0f11 100644 --- a/src/gui/mainwindow.ui +++ b/src/gui/mainwindow.ui @@ -74,7 +74,6 @@ - diff --git a/src/gui/smbfilebrowser.cpp b/src/gui/smbfilebrowser.cpp deleted file mode 100644 index 9e8d3a1..0000000 --- a/src/gui/smbfilebrowser.cpp +++ /dev/null @@ -1,78 +0,0 @@ -#include "smbfilebrowser.h" - -#include "ui_smbfilebrowser.h" - -#include -#include - -#include - -#include -#include -#include -#include -#include - -SmbFileBrowserPrivate::SmbFileBrowserPrivate() - : model(new DirModel()) -{} - -SmbFileBrowser::SmbFileBrowser(QWidget *parent) - : QDialog(parent) - , ui(new Ui::SmbFileBrowser()) - , d(new SmbFileBrowserPrivate()) -{ - ui->setupUi(this); - - ui->tableViewFM->horizontalHeader()->setSortIndicator(0, Qt::AscendingOrder); - - DirModel::registerMetaTypes(); - - ui->tableViewFM->setModel(d->model.get()); - - d->model->setEnabledExternalFSWatcher(true); - - d->selection = d->model->selectionObject(); - - ui->tableViewFM->setSelectionMode(QAbstractItemView::NoSelection); - - do_connections(); - - d->model->goHome(); -} - -SmbFileBrowser::~SmbFileBrowser() -{ - delete ui; - delete d; -} - -void SmbFileBrowser::do_connections() -{ - connect(ui->tableViewFM, &QTableView::clicked, this, &SmbFileBrowser::onRowClicked); - - connect(ui->tableViewFM, &QTableView::doubleClicked, this, &SmbFileBrowser::onOpenItem); - - connect(d->model.get(), &DirModel::pathChanged, this, &SmbFileBrowser::onPathChanged); - - connect(ui->toolButtonUp, &QToolButton::clicked, this, &SmbFileBrowser::cdUp); - connect(ui->toolButtonBack, &QToolButton::clicked, this, &SmbFileBrowser::goBack); - - connect(ui->comboBoxPath, SIGNAL(activated(int)), this, SLOT(onPathChoosedFromList(int))); - - connect(ui->comboBoxPath->lineEdit(), &QLineEdit::returnPressed, this, &SmbFileBrowser::onPathComboEdited); - - connect(ui->tableViewFM->horizontalHeader(), &QHeaderView::sortIndicatorChanged, this, &SmbFileBrowser::onSetSort); - - connect(d->model.get(), &DirModel::progress, this, &SmbFileBrowser::onProgress); - - connect(d->model.get(), &DirModel::clipboardChanged, this, &SmbFileBrowser::onClipboardChanged); - - connect(d->model.get(), &DirModel::error, this, &SmbFileBrowser::onError); - - connect(d->model.get(), &DirModel::awaitingResultsChanged, this, &SmbFileBrowser::onAwaitingResultsChanged); - - connect(d->model.get(), &DirModel::rowsInserted, this, &SmbFileBrowser::onRowsInserted); - - connect(d->selection, &DirSelection::selectionChanged, this, &SmbFileBrowser::onSelectionChanged); -} diff --git a/src/gui/smbfilebrowser.h b/src/gui/smbfilebrowser.h deleted file mode 100644 index 1f1621d..0000000 --- a/src/gui/smbfilebrowser.h +++ /dev/null @@ -1,65 +0,0 @@ -#ifndef GPUI_SMB_FILE_BROWSER_H -#define GPUI_SMB_FILE_BROWSER_H - -#include -#include - -#include - -namespace Ui { - class SmbFileBrowser; -} - -class DirModel; -class DirSelection; - -class QProgressBar; - -class SmbFileBrowserPrivate -{ -public: - std::unique_ptr model; - DirSelection *selection; - QString previousPath; - - SmbFileBrowserPrivate(); -}; - - -class SmbFileBrowser : public QDialog -{ - Q_OBJECT - -public: - explicit SmbFileBrowser(QWidget *parent = 0); - ~SmbFileBrowser(); - -signals: - void onPolOpen(const QString& path); - -private: - Ui::SmbFileBrowser *ui; - SmbFileBrowserPrivate *d; - -private slots: - void onRowClicked(QModelIndex); - void onOpenItem(QModelIndex index); - void onSetSort(int col, Qt::SortOrder order); - void onProgress(int, int,int); - void onClipboardChanged(); - void onError(QString title, QString message); - void onPathChanged(QString newPath); - void onPathChoosedFromList(int); - void onPathComboEdited(); - void onSelectionChanged(int); - void onAwaitingResultsChanged(); - void onRowsInserted(QModelIndex, int,int); - - void cdUp(); - void goBack(); - -private: - void do_connections(); -}; - -#endif // GPUI_SMB_FILE_BROWSER_H diff --git a/src/gui/smbfilebrowser.ui b/src/gui/smbfilebrowser.ui deleted file mode 100644 index 71df6fa..0000000 --- a/src/gui/smbfilebrowser.ui +++ /dev/null @@ -1,70 +0,0 @@ - - - SmbFileBrowser - - - - 0 - 0 - 942 - 460 - - - - Dialog - - - - - - - - - - - true - - - back - - - - ../../../../../../../../ - - - - - - - Up - - - - ../../../../../../../../ - - - - - - - true - - - QComboBox::NoInsert - - - - - - - - - 0 - - - - - - - - diff --git a/src/gui/smbfilebrowserslots.cpp b/src/gui/smbfilebrowserslots.cpp deleted file mode 100644 index d5ad3cf..0000000 --- a/src/gui/smbfilebrowserslots.cpp +++ /dev/null @@ -1,143 +0,0 @@ -#include "smbfilebrowser.h" -#include "ui_smbfilebrowser.h" - -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -void SmbFileBrowser::onRowClicked(QModelIndex index) -{ - if (index.isValid()) - { - d->selection->select(index.row(), false, false); - } -} - -void SmbFileBrowser::onSetSort(int col, Qt::SortOrder sortOrder) -{ - if (col == DirModel::SortByName || col == DirModel::SortByDate) - { - DirModel::SortOrder order = (DirModel::SortOrder)sortOrder; - d->model->setSortOrder(order); - } -} - -void SmbFileBrowser::onClipboardChanged() -{ - -} - -void SmbFileBrowser::onProgress(int cur, int total, int percent) -{ - Q_UNUSED(total); - - QString p; - ui->progressBar->setValue(percent); - if (cur == 0 && percent == 0) - { - ui->progressBar->reset(); - ui->progressBar->show(); - } - else if (percent == 100) - { - QTimer::singleShot(200, ui->progressBar, SLOT(hide())); - } -} - -void SmbFileBrowser::onError(QString title, QString message) -{ - QMessageBox::critical(this, title, message); -} - -void SmbFileBrowser::onOpenItem(QModelIndex index) -{ - if (index.isValid()) - { - QModelIndex idx = d->model->index(index.row(), 0); - QString item = d->model->data(idx).toString(); - - if (item.endsWith(".pol")) - { - onPolOpen(d->model->path() + QDir::separator() + item); - this->accept(); - return; - } - - d->model->openIndex(index.row()); - } -} - - -void SmbFileBrowser::onPathChanged(QString path) -{ - path = d->model->path(); - - int index = ui->comboBoxPath->findText(path); - if (index == -1) - { - ui->comboBoxPath->insertItem(0, path); - ui->comboBoxPath->setCurrentIndex(0); - } - else - { - ui->comboBoxPath->setCurrentIndex(index); - } - this->setWindowTitle(path); -} - - -void SmbFileBrowser::onPathChoosedFromList(int row) -{ - d->model->setPath(ui->comboBoxPath->itemText(row)); -} - - -void SmbFileBrowser::onPathComboEdited() -{ - d->model->openPath(ui->comboBoxPath->lineEdit()->text()); -} - - -void SmbFileBrowser::onSelectionChanged(int itemsCounter) -{ - Q_UNUSED(itemsCounter); -} - -void SmbFileBrowser::cdUp() -{ - d->model->cdUp(); -} - -void SmbFileBrowser::goBack() -{ - d->model->openPath(d->previousPath); -} - -void SmbFileBrowser::onAwaitingResultsChanged() -{ - if (d->model->awaitingResults()) - { - this->setCursor(Qt::BusyCursor); - } - else - { - this->setCursor(Qt::ArrowCursor); - } -} - - -void SmbFileBrowser::onRowsInserted(QModelIndex, int, int) -{ - ui->tableViewFM->resizeColumnToContents(0); -} - diff --git a/src/plugins/CMakeLists.txt b/src/plugins/CMakeLists.txt index 80eae63..d3f2d56 100644 --- a/src/plugins/CMakeLists.txt +++ b/src/plugins/CMakeLists.txt @@ -22,3 +22,4 @@ add_subdirectory(spol) add_subdirectory(pol) add_subdirectory(preferences) add_subdirectory(reg) +add_subdirectory(storage) diff --git a/src/plugins/storage/CMakeLists.txt b/src/plugins/storage/CMakeLists.txt new file mode 100644 index 0000000..f70f1fd --- /dev/null +++ b/src/plugins/storage/CMakeLists.txt @@ -0,0 +1,2 @@ +add_subdirectory(local) +add_subdirectory(smb) diff --git a/src/plugins/storage/local/CMakeLists.txt b/src/plugins/storage/local/CMakeLists.txt new file mode 100644 index 0000000..e69de29 diff --git a/src/plugins/storage/smb/CMakeLists.txt b/src/plugins/storage/smb/CMakeLists.txt new file mode 100644 index 0000000..fe86601 --- /dev/null +++ b/src/plugins/storage/smb/CMakeLists.txt @@ -0,0 +1,50 @@ +find_package(GPUI COMPONENTS io model REQUIRED) +include_directories(${GPUI_INCLUDE_DIRS}) + +find_package(Qt5 COMPONENTS Core REQUIRED) + +set(PLUGIN_NAME smb-storage-plugin) +set(PLUGIN_LIBRARY_NAME smb-storage-static) + +set(HEADERS + smbclient.h + smbdirectory.h + smbfile.h +) + +set(SOURCES + smbclient.cpp + smbdirectory.cpp + smbfile.cpp + smbstorageplugin.cpp +) + +add_gpui_plugin(${PLUGIN_NAME} ${SOURCES}) +target_link_libraries(${PLUGIN_NAME} Qt5::Core) + +add_library(${PLUGIN_LIBRARY_NAME} STATIC ${SOURCES}) +target_link_libraries(${PLUGIN_LIBRARY_NAME} Qt5::Core) + +## samba requires libsmbclient +find_path(SAMBA_INCLUDE_DIR + NAMES libsmbclient.h + HINTS /usr/include/smbclient + /usr/include/samba + /usr/include/samba-3.0 + /usr/include/samba-4.0 + ) +find_library(SAMBA_LIBRARIES NAMES smbclient ) +message(STATUS "samba include=${SAMBA_INCLUDE_DIR}") +message(STATUS "samba lib=${SAMBA_LIBRARIES}=${SAMBA_LIBRARIES}") + +if(SAMBA_INCLUDE_DIR AND SAMBA_LIBRARIES) + message(STATUS "Found samba: include=${SAMBA_INCLUDE_DIR} library=${SAMBA_LIBRARIES}") + include_directories(${SAMBA_INCLUDE_DIR}) + + target_link_libraries(${PLUGIN_NAME} ${SAMBA_LIBRARIES}) + target_link_libraries(${PLUGIN_LIBRARY_NAME} ${SAMBA_LIBRARIES}) +else(SAMBA_INCLUDE_DIR AND SAMBA_LIBRARIES) + message(FATAL_ERROR "Could not find Samba libsmbclient") +endif(SAMBA_INCLUDE_DIR AND SAMBA_LIBRARIES) +mark_as_advanced(SAMBA_INCLUDE_DIR SAMBA_LIBRARIES) +## end samba confiuration diff --git a/src/plugins/storage/smb/smbclient.cpp b/src/plugins/storage/smb/smbclient.cpp new file mode 100644 index 0000000..65fa1d3 --- /dev/null +++ b/src/plugins/storage/smb/smbclient.cpp @@ -0,0 +1,195 @@ +/*********************************************************************************************************************** +** +** Copyright (C) 2021 BaseALT Ltd. +** +** 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 2 +** 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, write to the Free Software +** Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +** +***********************************************************************************************************************/ + +#include "smbclient.h" + +namespace gpui +{ + +namespace smb +{ + +const int SMB_FREE_EVEN_IF_BUSY = 1; +const int SMB_DEBUG_LEVEL = 5; + +namespace +{ + +QByteArray userName("guest"); +QByteArray password(""); +QByteArray workGroup("WORKGROUP"); + +} + +SmbClient::SmbClient() + : SmbClient(userName, password) +{ +} + +SmbClient::SmbClient(const QString &userName, const QString &password) + : ctx(createContext(userName, password, &authenticationCallBack), freeContext) +{ +} + +SmbClient::SmbClient(const QString &userName, const QString &password, const QString &workGroup) + : ctx(createContext(userName, password, workGroup, &authenticationCallBack), freeContext) +{ +} + +ContextPtr SmbClient::createContext(AuthenticationFunction function) +{ + if (!function) + { + function = &authenticationCallBack; + } + + ContextPtr ctx = smbc_new_context(); + + if (ctx) + { + smbc_setDebug(ctx, SMB_DEBUG_LEVEL); + smbc_setOptionUseKerberos(ctx, true); + smbc_setOptionFallbackAfterKerberos(ctx, true); + smbc_setFunctionAuthData(ctx, function); + smbc_setOptionCaseSensitive(ctx, false); + + if (smbc_init_context(ctx) == nullptr) + { + smbc_free_context(ctx, SMB_FREE_EVEN_IF_BUSY); + ctx = nullptr; + } + } + + return ctx; +} + +ContextPtr SmbClient::createContext(const QString ¤tUserName, const QString ¤tPassword, + AuthenticationFunction function) +{ + userName = currentUserName.toLocal8Bit(); + password = currentPassword.toLocal8Bit(); + + return createContext(function); +} + +ContextPtr SmbClient::createContext(const QString ¤tUserName, const QString ¤tPassword, + const QString& currentWorkGroup, AuthenticationFunction function) +{ + workGroup = currentWorkGroup.toLocal8Bit(); + + return createContext(currentUserName, currentPassword, function); +} + +void SmbClient::freeContext(ContextPtr context) +{ + if (context) + { + smbc_free_context(context, SMB_FREE_EVEN_IF_BUSY); + } +} + +FileHandle SmbClient::openFile(const QString &fileName, int flags, mode_t mode) +{ + return smbc_getFunctionOpen(ctx.get())(ctx.get(), fileName.toLocal8Bit().constData(), flags, mode); +} + +FileHandle SmbClient::openFileReadOnly(const QString &fileName) +{ + return openFile(fileName); +} + +ssize_t SmbClient::readFile(FileHandle handle, void *buffer, size_t count) +{ + return smbc_getFunctionRead(ctx.get())(ctx.get(), handle, buffer, count); +} + +ssize_t SmbClient::writeFile(FileHandle handle, void *buffer, size_t count) +{ + return smbc_getFunctionWrite(ctx.get())(ctx.get(), handle, buffer, count); +} + +off_t SmbClient::seekFile(FileHandle handle, off_t offset, int whence) +{ + return smbc_getFunctionLseek(ctx.get())(ctx.get(), handle, offset, whence); +} + +int SmbClient::rename(const QString& oldName, const QString &newName) +{ + std::unique_ptr context(createContext(&authenticationCallBack), + freeContext); + int result = smbc_getFunctionRename(ctx.get()) + (ctx.get(), + oldName.toLocal8Bit().constData(), + context.get(), + newName.toLocal8Bit().constData() + ); + return result; +} + +int SmbClient::stat(const QString &path, struct stat& st) +{ + return smbc_getFunctionStat(ctx.get())(ctx.get(), path.toLocal8Bit().constData(), &st); +} + +int SmbClient::stat(FileHandle handle, struct stat& st) +{ + return smbc_getFunctionFstat(ctx.get())(ctx.get(), handle, &st); +} + +FileHandle SmbClient::openDir(const QString &directoryName) +{ + return smbc_getFunctionOpendir(ctx.get())(ctx.get(), directoryName.toLocal8Bit().constData()); +} + +int SmbClient::createDir(const QString &directoryName, mode_t mode) +{ + return smbc_getFunctionMkdir(ctx.get())(ctx.get(), directoryName.toLocal8Bit().constData(), mode); +} + +int SmbClient::deleteDir(const QString &directoryName) +{ + return smbc_getFunctionRmdir(ctx.get())(ctx.get(), directoryName.toLocal8Bit().constData()); +} + +bool SmbClient::setPermissions(const QString &path, mode_t mode) +{ + return smbc_getFunctionChmod(ctx.get())(ctx.get(), path.toLocal8Bit().constData(), mode); +} + +void SmbClient::authenticationCallBack(const char *server, const char *share, char *currentWorkGroup, + int workGroupLength, char *currentUser, int userLength, + char *currentPassword, int passwordLength) +{ + Q_UNUSED(server); + Q_UNUSED(share); + + strncpy(currentWorkGroup, workGroup.constData(), workGroupLength - 1); + strncpy(currentUser, userName.constData(), userLength - 1); + strncpy(currentPassword, password.constData(), passwordLength - 1); +} + +void SmbClient::closeFile(FileHandle handle) +{ + smbc_getFunctionClose(ctx.get())(ctx.get(), handle); +} + +} + +} diff --git a/src/plugins/storage/smb/smbclient.h b/src/plugins/storage/smb/smbclient.h new file mode 100644 index 0000000..516ceff --- /dev/null +++ b/src/plugins/storage/smb/smbclient.h @@ -0,0 +1,391 @@ +/*********************************************************************************************************************** +** +** Copyright (C) 2021 BaseALT Ltd. +** +** 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 2 +** 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, write to the Free Software +** Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +** +***********************************************************************************************************************/ + +#ifndef GPUI_SMB_CLIENT_H +#define GPUI_SMB_CLIENT_H + +#include + +#include + +#include + +namespace gpui +{ + namespace smb { + + typedef SMBCCTX Context; + typedef Context* ContextPtr; + typedef SMBCFILE* FileHandle; + + typedef smbc_get_auth_data_fn AuthenticationFunction; + + /*! + * \brief The SmbClient class wraps libsmbclient calls, provides handling of creation and deletion of samba + * context. + */ + class SmbClient final + { + public: + SmbClient(); + + /*! + * \brief SmbClient + * \param userName Username of user. + * \param password Password of user. + */ + SmbClient(const QString& userName, const QString& password); + + /*! + * \brief SmbClient + * \param userName Username of user. + * \param password Password of user. + * \param workGroup Work group to use. + */ + SmbClient(const QString& userName, const QString& password, const QString& workGroup); + + /*! + * \ingroup file + * \brief openFile Open a file on an SMB server. + * + * \param fileName The smb url of the file to be opened. + * + * \param flags Is one of O_RDONLY, O_WRONLY or O_RDWR which + * request opening the file read-only,write-only + * or read/write. flags may also be bitwise-or'd with + * one or more of the following: + * O_CREAT - If the file does not exist it will be + * created. + * O_EXCL - When used with O_CREAT, if the file + * already exists it is an error and the open will + * fail. + * O_TRUNC - If the file already exists it will be + * truncated. + * O_APPEND The file is opened in append mode + * + * \param mode mode specifies the permissions to use if a new + * file is created. It is modified by the + * process's umask in the usual way: the permissions + * of the created file are (mode & ~umask) + * + * Not currently use, but there for future use. + * We will map this to SYSTEM, HIDDEN, etc bits + * that reverses the mapping that smbc_fstat does. + * + * \return Valid file handle, < 0 on error with errno set: + * - ENOMEM Out of memory + * - EINVAL if an invalid parameter passed, like no + * file, or smbc_init not called. + * - EEXIST pathname already exists and O_CREAT and + * O_EXCL were used. + * - EISDIR pathname refers to a directory and + * the access requested involved writing. + * - EACCES The requested access to the file is not + * allowed + * - ENODEV The requested share does not exist + * - ENOTDIR A file on the path is not a directory + * - ENOENT A directory component in pathname does + * not exist. + * + * \note This call uses an underlying routine that may create + * a new connection to the server specified in the URL. + * If the credentials supplied in the URL, or via the + * auth_fn in the smbc_init call, fail, this call will + * try again with an empty username and password. This + * often gets mapped to the guest account on some machines. + */ + FileHandle openFile(const QString& fileName, int flags = O_RDONLY, mode_t mode = 0); + + /*! + * \ingroup file + * \brief openFileReadOnly Open file read only with mode = 0. + * \param fileName The smb url of the file to be opened. + * \return Valid file handle, < 0 on error with errno set: + * - ENOMEM Out of memory + * - EINVAL if an invalid parameter passed, like no + * file, or smbc_init not called. + * - EEXIST pathname already exists and O_CREAT and + * O_EXCL were used. + * - EISDIR pathname refers to a directory and + * the access requested involved writing. + * - EACCES The requested access to the file is not + * allowed + * - ENODEV The requested share does not exist + * - ENOTDIR A file on the path is not a directory + * - ENOENT A directory component in pathname does + * not exist. + */ + FileHandle openFileReadOnly(const QString& fileName); + + /*! + * \ingroup file + * \brief readFile Read from a file using an opened file handle. + * + * \param handle Open file handle from openFile(). + * + * \param buffer Pointer to buffer to receive read data. + * + * \param count Size of buffer in bytes. + * + * \return Number of bytes read; + * 0 upon EOF; + * < 0 on error, with errno set: + * - EISDIR handle refers to a directory + * - EBADF handle is not a valid file descriptor or + * is not open for reading. + * - EINVAL handle is attached to an object which is + * unsuitable for reading, or no buffer passed or + * smbc_init not called. + */ + ssize_t readFile(FileHandle handle, void* buffer, size_t count); + + /*! + * \ingroup file + * \brief writeFile Write to a file using an opened file handle. + * + * @param handle Open file handle from openFile(). + * + * @param buffer Pointer to buffer to recieve read data. + * + * @param count Size of buffer in bytes. + * + * @return Number of bytes written, < 0 on error with errno set: + * - EISDIR handle refers to a directory. + * - EBADF handle is not a valid file descriptor or + * is not open for reading. + * - EINVAL handle is attached to an object which is + * unsuitable for reading, or no buffer passed or + * smbc_init not called. + */ + ssize_t writeFile(FileHandle handle, void* buffer, size_t count); + + /*! + * \ingroup file + * \brief seekFile Seek to a specific location in a file. + * + * \param handle Open file handle from openFile + * + * \param offset Offset in bytes from whence + * + * \param whence A location in the file: + * - SEEK_SET The offset is set to offset bytes from + * the beginning of the file + * - SEEK_CUR The offset is set to current location + * plus offset bytes. + * - SEEK_END The offset is set to the size of the + * file plus offset bytes. + * + * \return Upon successful completion, lseek returns the + * resulting offset location as measured in bytes + * from the beginning of the file. Otherwise, a value + * of (off_t) - 1 is returned and errno is set to + * indicate the error: + * - EBADF Fildes is not an open file descriptor. + * - EINVAL Whence is not a proper value or smbc_init + * not called. + */ + off_t seekFile(FileHandle handle, off_t offset, int whence = SEEK_SET); + + /*! + * \ingroup directory + * \ingroup file + * \brief rename Rename or move a file or directory. + * + * \param oldName The original smb url (source url) of file or + * directory to be moved + * + * \param newName The new smb url (destination url) of the file + * or directory after the move. Currently newName must + * be on the same share as oldName. + * + * \return 0 on success, < 0 on error with errno set: + * - EISDIR nurl is an existing directory, but ourl is + * not a directory. + * - EEXIST nurl is a non-empty directory, + * i.e., contains entries other than "." and ".." + * - EINVAL The new url contained a path prefix + * of the old, or, more generally, an attempt was + * made to make a directory a subdirectory of itself + * or smbc_init not called. + * - ENOTDIR A component used as a directory in ourl + * or nurl path is not, in fact, a directory. Or, + * ourl is a directory, and newpath exists but is not + * a directory. + * - EACCES or EPERM Write access to the directory + * containing ourl or nurl is not allowed for the + * process's effective uid, or one of the + * directories in ourl or nurl did not allow search + * (execute) permission, or ourl was a directory + * and did not allow write permission. + * - ENOENT A directory component in ourl or nurl + * does not exist. + * - EXDEV Rename across shares not supported. + * - ENOMEM Insufficient kernel memory was available. + * - EEXIST The target file, nurl, already exists. + */ + int rename(const QString& oldName, const QString &newName); + + /*! + * \ingroup file + * \brief closeFile Close an open file handle. + * + * @param handle The file handle to close + * + * @return 0 on success, < 0 on error with errno set: + * - EBADF fd isn't a valid open file descriptor + * - EINVAL smbc_init() failed or has not been called + */ + void closeFile(FileHandle handle); + + /*! + * \ingroup stat + * \brief stat Get information about a file or directory. + * + * \param path The smb path to get information for. + * + * \param st pointer to a buffer that will be filled with + * standard Unix struct stat information. + * + * \return 0 on success, < 0 on error with errno set: + * - ENOENT A component of the path file_name does not + * exist. + * - EINVAL a NULL url was passed or smbc_init not called. + * - EACCES Permission denied. + * - ENOMEM Out of memory + * - ENOTDIR The target dir, url, is not a directory. + */ + int stat(const QString& path, struct stat& st); + + + /*! + * \ingroup stat + * \brief stat Get file information via an file descriptor. + * + * @param handle Open file handle from smbc_open() or smbc_creat() + * + * @param st pointer to a buffer that will be filled with + * standard Unix struct stat information. + * + * @return 0 on success, < 0 on error with errno set: + * - EBADF filedes is bad. + * - EACCES Permission denied. + * - EBADF fd is not a valid file descriptor + * - EINVAL Problems occurred in the underlying routines + * or smbc_init not called. + * - ENOMEM Out of memory + */ + int stat(FileHandle handle, struct stat& st); + + /*! + * \ingroup directory + * \brief openDir Open a directory used to obtain directory entries. + * + * @param directoryName The smb url of the directory to open + * + * @return Valid directory handle. < 0 on error with errno set: + * - EACCES Permission denied. + * - EINVAL A NULL file/URL was passed, or the URL would + * not parse, or was of incorrect form or smbc_init not + * called. + * - ENOENT durl does not exist, or name is an + * - ENOMEM Insufficient memory to complete the + * operation. + * - ENOTDIR name is not a directory. + * - EPERM the workgroup could not be found. + * - ENODEV the workgroup or server could not be found. + * + */ + FileHandle openDir(const QString& directoryName); + + /*! + * \ingroup directory + * \brief createDir Create a directory. + * \param directoryName The name of the directory to create + * \param mode Specifies the permissions to use. It is modified + * by the process's umask in the usual way: the + * permissions of the created file are (mode & ~umask). + * \return 0 on success, < 0 on error with errno set: + * - EEXIST directory already exists + * - EACCES The parent directory does not allow write + * permission to the process, or one of the directories + * - ENOENT A directory component in pathname does not + * exist. + * - EINVAL durl is NULL or smbc_init not called. + * - ENOMEM Insufficient memory was available. + */ + int createDir(const QString& directoryName, mode_t mode); + + /*! + * \ingroup directory + * \brief deleteDir Remove a directory. + * + * @param directoryName The smb url of the directory to remove + * + * @return 0 on success, < 0 on error with errno set: + * - EACCES or EPERM Write access to the directory + * containing pathname was not allowed. + * - EINVAL durl is NULL or smbc_init not called. + * - ENOENT A directory component in pathname does not + * exist. + * - ENOTEMPTY directory contains entries. + * - ENOMEM Insufficient kernel memory was available. + */ + int deleteDir(const QString& directoryName); + + /*! + * \ingroup attribute + * \brief Change the permissions of a file. + * + * \param path The smb url of the file or directory to change + * permissions of + * + * \param mode The permissions to set: + * - Put good explaination of permissions here! + * + * \return 0 on success, < 0 on error with errno set: + * - EPERM The effective UID does not match the owner + * of the file, and is not zero + * - ENOENT The file does not exist. + * - ENOMEM Insufficient was available. + * - ENOENT file or directory does not exist + */ + bool setPermissions(const QString& path, mode_t mode); + + private: + static void authenticationCallBack(const char* server, const char* share, char* workGroup, + int workGroupLength, char* user, int userLength, char* password, + int passwordLength); + + + inline static ContextPtr createContext(AuthenticationFunction function); + inline static ContextPtr createContext(const QString &userName, const QString &password, + AuthenticationFunction function); + inline static ContextPtr createContext(const QString &userName, const QString &password, + const QString& workGroup, AuthenticationFunction function); + + static void freeContext(ContextPtr context); + + private: + std::unique_ptr ctx; + }; + } +} + +#endif//GPUI_SMB_CLIENT_H diff --git a/src/plugins/storage/smb/smbdirectory.cpp b/src/plugins/storage/smb/smbdirectory.cpp new file mode 100644 index 0000000..0d8c90a --- /dev/null +++ b/src/plugins/storage/smb/smbdirectory.cpp @@ -0,0 +1,106 @@ +/*********************************************************************************************************************** +** +** Copyright (C) 2021 BaseALT Ltd. +** +** 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 2 +** 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, write to the Free Software +** Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +** +***********************************************************************************************************************/ + +#include "smbdirectory.h" + +#include "smbclient.h" + +#include + +namespace gpui +{ + +namespace smb +{ + +class SmbDirectoryPrivate +{ +public: + SmbClient client; + QString path; +}; + +SmbDirectory::SmbDirectory(const QString& dir) + : d(new SmbDirectoryPrivate(), &freePrivate) +{ + d->path = dir; +} + +bool SmbDirectory::exists() const +{ + bool result = false; + + if (!d->path.isEmpty()) + { + struct stat st; + + memset(&st, 0, sizeof(st)); + + if (d->client.stat(d->path, st) >= 0) + { + return true; + } + + qWarning() << "Directory: " << d->path << "Error: " << strerror(errno); + } + + return result; +} + +bool SmbDirectory::mkdir(const QString &dir) const +{ + int operationResult = d->client.createDir(dir, S_IRWXU | S_IRWXG | S_IRWXO); + + if (operationResult < 0) + { + qWarning() << "Directory: " << dir << "Error: " << strerror(errno); + + return false; + } + + d->path = dir; + + return true; +} + +bool SmbDirectory::rmdir(const QString &dir) const +{ + int operationResult = d->client.deleteDir(dir); + + if (operationResult < 0) + { + qWarning() << "Directory: " << dir << "Error: " << strerror(errno); + + return false; + } + + d->path.clear(); + + return true; +} + +void SmbDirectory::freePrivate(SmbDirectoryPrivate *p) +{ + delete p; +} + +} + +} diff --git a/src/plugins/storage/smb/smbdirectory.h b/src/plugins/storage/smb/smbdirectory.h new file mode 100644 index 0000000..e6eb02f --- /dev/null +++ b/src/plugins/storage/smb/smbdirectory.h @@ -0,0 +1,56 @@ +/*********************************************************************************************************************** +** +** Copyright (C) 2021 BaseALT Ltd. +** +** 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 2 +** 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, write to the Free Software +** Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +** +***********************************************************************************************************************/ +#ifndef GPUI_SMB_DIRECTORY_H +#define GPUI_SMB_DIRECTORY_H + +#include + +#include + +namespace gpui +{ + +namespace smb +{ + +class SmbDirectoryPrivate; + +class SmbDirectory final +{ +public: + SmbDirectory(const QString& dir); + ~SmbDirectory() = default; + +public: + bool exists() const; + bool mkdir(const QString& dir) const; + bool rmdir(const QString& dir) const; + +private: + static void freePrivate(SmbDirectoryPrivate* p); + + std::unique_ptr d; +}; + +} + +} + +#endif//GPUI_SMB_DIRECTORY_H diff --git a/src/plugins/storage/smb/smbfile.cpp b/src/plugins/storage/smb/smbfile.cpp new file mode 100644 index 0000000..3e1b392 --- /dev/null +++ b/src/plugins/storage/smb/smbfile.cpp @@ -0,0 +1,335 @@ +/*********************************************************************************************************************** +** +** Copyright (C) 2021 BaseALT Ltd. +** +** 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 2 +** 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, write to the Free Software +** Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +** +***********************************************************************************************************************/ + +#include "smbfile.h" + +#include "smbclient.h" + +#include + +namespace gpui +{ + +namespace smb +{ + +class SmbFilePrivate +{ +public: + SmbClient client; + FileHandle handle { nullptr }; + QString fileName { "" }; +}; + +SmbFile::SmbFile(const QString& name) + : d(new SmbFilePrivate(), &freePrivate) +{ + d->fileName = name; +} + +bool SmbFile::remove() +{ + return false; +} + +bool SmbFile::rename(const QString &newName) +{ + d->client.closeFile(d->handle); + + int result = d->client.rename(d->fileName, newName); + + if (result < 0) + { + qWarning() << "File" << d->fileName << "Error: " << strerror(errno); + + return false; + } + + d->fileName = newName; + + return true; +} + +bool SmbFile::link(const QString &newName) +{ + Q_UNUSED(newName); + + return false; +} + +bool SmbFile::copy(const QString &newName) +{ + Q_UNUSED(newName); + + return false; +} + +bool SmbFile::open(QFile::OpenMode flags) +{ + bool result = false; + if (d->fileName.isEmpty()) + { + int openFlags = createOpenFlags(flags); + int creationMode = 0; + + d->handle = d->client.openFile(d->fileName, openFlags, creationMode); + + if (d->handle == nullptr) + { + qWarning() << "File" << d->fileName << "Error: " << strerror(errno); + } + + result = d->handle != 0; + } + + return result; +} + +void SmbFile::close() +{ + if (d->handle != 0) + { + d->client.closeFile(d->handle); + } +} + +qint64 SmbFile::size() const +{ + struct stat st; + + memset(&st, 0, sizeof(st)); + + int result = d->client.stat(d->handle, st); + if (result < 0) + { + qWarning() << "File" << d->fileName << "Error: " << strerror(errno); + } + + return st.st_size; +} + +bool SmbFile::resize(qint64 sz) +{ + Q_UNUSED(sz); + + return false; +} + +QFileDevice::Permissions SmbFile::permissions() const +{ + struct stat st; + + memset(&st, 0, sizeof(st)); + + int result = d->client.stat(d->handle, st); + if (result < 0) + { + qWarning() << "File" << d->fileName << "Error: " << strerror(errno); + } + + return createPermissions(st.st_mode); +} + +bool SmbFile::setPermissions(const QFileDevice::Permissions &permissionSpec) +{ + mode_t permissions = createMode(permissionSpec); + int result = d->client.setPermissions(d->fileName, permissions); + + if (result < 0) + { + qWarning() << "File" << d->fileName << "Error: " << strerror(errno); + } + + return result >= 0; +} + +qint64 SmbFile::read(char* buffer, qint64 count) +{ + qint64 result = d->client.readFile(d->handle, buffer, count); + + if (result < 0) + { + qWarning() << "File" << d->fileName << "Error: " << strerror(errno); + } + + return result; +} + +qint64 SmbFile::write(const char *buffer, qint64 count) +{ + qint64 result = d->client.writeFile(d->handle, const_cast(buffer), count); + + if (result < 0) + { + qWarning() << "File" << d->fileName << "Error: " << strerror(errno); + } + + return result; +} + + +int SmbFile::createOpenFlags(QIODevice::OpenMode flags) +{ + int result = 0; + + if (flags & QIODevice::ReadOnly) + { + if (flags & QIODevice::WriteOnly) + { + result = O_RDWR | O_CREAT; + } + else + { + result = O_RDONLY; + } + } + else if (flags & QIODevice::WriteOnly) + { + result = O_WRONLY | O_CREAT; + } + + if (flags & QIODevice::Append) + { + result |= O_APPEND; + } + else + { + result |= O_TRUNC; + } + + return result; +} + +mode_t SmbFile::createMode(const QFileDevice::Permissions &permissionSpec) +{ + mode_t mode = 0; + + if (permissionSpec & QFileDevice::ReadOwner) + { + mode |= S_IRUSR; + } + if (permissionSpec & QFileDevice::WriteOwner) + { + mode |= S_IWUSR; + } + if (permissionSpec & QFileDevice::ExeOwner) + { + mode |= S_IXUSR; + } + + if (permissionSpec & QFileDevice::ReadUser) + { + mode |= S_IRUSR; + } + if (permissionSpec & QFileDevice::WriteUser) + { + mode |= S_IWUSR; + } + if (permissionSpec & QFileDevice::ExeUser) + { + mode |= S_IXUSR; + } + + if (permissionSpec & QFileDevice::ReadGroup) + { + mode |= S_IRGRP; + } + if (permissionSpec & QFileDevice::WriteGroup) + { + mode |= S_IWGRP; + } + if (permissionSpec & QFileDevice::ExeGroup) + { + mode |= S_IXGRP; + } + + if (permissionSpec & QFileDevice::ReadOther) + { + mode |= S_IROTH; + } + if (permissionSpec & QFileDevice::WriteOther) + { + mode |= S_IWOTH; + } + if (permissionSpec & QFileDevice::ExeOther) + { + mode |= S_IXOTH; + } + + return mode; +} + +QFileDevice::Permissions SmbFile::createPermissions(mode_t mode) const +{ + QFileDevice::Permissions currentPermissions = 0; + + if (mode & S_IRUSR) + { + currentPermissions |= QFileDevice::ReadOwner; + currentPermissions |= QFileDevice::ReadUser; + } + if (mode & S_IWUSR) + { + currentPermissions |= QFileDevice::WriteOwner; + currentPermissions |= QFileDevice::WriteUser; + } + if (mode & S_IXUSR) + { + currentPermissions |= QFileDevice::ExeOwner; + currentPermissions |= QFileDevice::ExeUser; + } + + if (mode & S_IRGRP) + { + currentPermissions |= QFileDevice::ReadGroup; + } + if (mode & S_IWGRP) + { + currentPermissions |= QFileDevice::WriteGroup; + } + if (mode & S_IXGRP) + { + currentPermissions |= QFileDevice::ExeGroup; + } + + if (mode & S_IROTH) + { + currentPermissions |= QFileDevice::ReadOther; + } + if (mode & S_IWOTH) + { + currentPermissions |= QFileDevice::WriteOther; + } + if (mode & S_IXOTH) + { + currentPermissions |= QFileDevice::ExeOther; + } + + return currentPermissions; +} + +void SmbFile::freePrivate(SmbFilePrivate* smbFilePrivate) +{ + delete smbFilePrivate; +} + +} + +} diff --git a/src/plugins/storage/smb/smbfile.h b/src/plugins/storage/smb/smbfile.h new file mode 100644 index 0000000..65e558d --- /dev/null +++ b/src/plugins/storage/smb/smbfile.h @@ -0,0 +1,66 @@ +/*********************************************************************************************************************** +** +** Copyright (C) 2021 BaseALT Ltd. +** +** 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 2 +** 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, write to the Free Software +** Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +** +***********************************************************************************************************************/ + +#ifndef GPUI_SMB_FILE_H +#define GPUI_SMB_FILE_H + +#include + +#include + +namespace gpui +{ + namespace smb + { + class SmbFilePrivate; + + class SmbFile final + { + public: + explicit SmbFile(const QString& name); + + bool remove(); + bool rename(const QString &newName); + bool link(const QString &newName); + bool copy(const QString &newName); + bool open(QFile::OpenMode flags); + void close(); + qint64 size() const; + bool resize(qint64 sz); + QFile::Permissions permissions() const; + bool setPermissions(const QFile::Permissions& permissionSpec); + + qint64 read(char* buffer, qint64 count); + qint64 write(const char* buffer, qint64 count); + + private: + static void freePrivate(SmbFilePrivate* smbFilePrivate); + + int createOpenFlags(QFile::OpenMode flags); + mode_t createMode(const QFile::Permissions& permissionSpec); + QFile::Permissions createPermissions(mode_t mode) const; + + private: + std::unique_ptr d; + }; + } +} + +#endif//GPUI_SMB_FILE_H diff --git a/src/plugins/storage/smb/smbstorageplugin.cpp b/src/plugins/storage/smb/smbstorageplugin.cpp new file mode 100644 index 0000000..e69de29 diff --git a/tests/auto/plugins/CMakeLists.txt b/tests/auto/plugins/CMakeLists.txt index 1acadcb..9d93438 100644 --- a/tests/auto/plugins/CMakeLists.txt +++ b/tests/auto/plugins/CMakeLists.txt @@ -8,3 +8,4 @@ add_subdirectory(adml) add_subdirectory(admx) add_subdirectory(pol) add_subdirectory(preferences) +add_subdirectory(storage) diff --git a/tests/auto/plugins/storage/CMakeLists.txt b/tests/auto/plugins/storage/CMakeLists.txt new file mode 100644 index 0000000..f70f1fd --- /dev/null +++ b/tests/auto/plugins/storage/CMakeLists.txt @@ -0,0 +1,2 @@ +add_subdirectory(local) +add_subdirectory(smb) diff --git a/tests/auto/plugins/storage/local/CMakeLists.txt b/tests/auto/plugins/storage/local/CMakeLists.txt new file mode 100644 index 0000000..e69de29 diff --git a/tests/auto/plugins/storage/smb/CMakeLists.txt b/tests/auto/plugins/storage/smb/CMakeLists.txt new file mode 100644 index 0000000..a7347fc --- /dev/null +++ b/tests/auto/plugins/storage/smb/CMakeLists.txt @@ -0,0 +1,46 @@ +find_package(Qt5 COMPONENTS Core Test REQUIRED) + +set(CMAKE_INCLUDE_CURRENT_DIR ON) + +set(TEST_NAME smbfiletest) + +set(SOURCES + smbfiletest.cpp + smbsharecreator.cpp + ../../../../../src/plugins/storage/smb/smbclient.cpp + ../../../../../src/plugins/storage/smb/smbdirectory.cpp + ../../../../../src/plugins/storage/smb/smbfile.cpp +) + +set(MOC_HEADERS + smbfiletest.h + smbsharecreator.h +) + +qt5_wrap_cpp(MOC_SOURCES ${MOC_HEADERS}) + +add_executable(${TEST_NAME} ${SOURCES} ${MOC_SOURCES}) +target_link_libraries(${TEST_NAME} ${GPUI_LIBRARIES} Qt5::Core Qt5::Test) +add_gpui_test(plugins.${TEST_NAME} ${TEST_NAME}) + +## samba requires libsmbclient +find_path(SAMBA_INCLUDE_DIR + NAMES libsmbclient.h + HINTS /usr/include/smbclient + /usr/include/samba + /usr/include/samba-3.0 + /usr/include/samba-4.0 + ) +find_library(SAMBA_LIBRARIES NAMES smbclient ) +message(STATUS "samba include=${SAMBA_INCLUDE_DIR}") +message(STATUS "samba lib=${SAMBA_LIBRARIES}=${SAMBA_LIBRARIES}") + +if(SAMBA_INCLUDE_DIR AND SAMBA_LIBRARIES) + message(STATUS "Found samba: include=${SAMBA_INCLUDE_DIR} library=${SAMBA_LIBRARIES}") + include_directories(${SAMBA_INCLUDE_DIR}) + target_link_libraries(${TEST_NAME} ${SAMBA_LIBRARIES}) +else(SAMBA_INCLUDE_DIR AND SAMBA_LIBRARIES) + message(FATAL_ERROR "Could not find Samba libsmbclient") +endif(SAMBA_INCLUDE_DIR AND SAMBA_LIBRARIES) +mark_as_advanced(SAMBA_INCLUDE_DIR SAMBA_LIBRARIES) +## end samba confiuration diff --git a/tests/auto/plugins/storage/smb/smbfiletest.cpp b/tests/auto/plugins/storage/smb/smbfiletest.cpp new file mode 100644 index 0000000..32fdfbb --- /dev/null +++ b/tests/auto/plugins/storage/smb/smbfiletest.cpp @@ -0,0 +1,156 @@ +/*********************************************************************************************************************** +** +** Copyright (C) 2021 BaseALT Ltd. +** +** 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 2 +** 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, write to the Free Software +** Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +** +***********************************************************************************************************************/ + +#include "smbfiletest.h" + +#include "../../../../../src/plugins/storage/smb/smbfile.h" + +namespace tests +{ + +using namespace gpui::smb; + +void SmbFileTest::remove() +{ + // 1. Remove a file with empty name. + + // 2. Remove a file that does not exist. + + // 3. Remove a file on a write only share. + + // 4. Remove a file on a read only share. + + // 5. Remove a file on a exec only share. +} + +void SmbFileTest::rename() +{ + // 1. Rename a file with empty name. + + // 2. Rename a file that does not exist. + + // 3. Rename a file on a write only share. + + // 4. Rename a file on a read only share. + + // 5. Rename a file on a exec only share. +} + +void SmbFileTest::link() +{ + // This method is not implemented in a smb file. +} + +void SmbFileTest::copy() +{ + // 1. Copy a file with empty name. + + // 2. Copy a file that does not exist. + + // 3. Copy a file on a write only share. + + // 4. Copy a file on a read only share. + + // 5. Copy a file on a exec only share. +} + +void SmbFileTest::open() +{ + // 1. Open file with empty file name. + + // 2. Open file on invalid share. + + // 3. Open file on valid share in folder that we have no permission to read, write or execute. + + // 4. Open file with read mode on a write only share. + + // 5. Open file with read mode on a share with read access. + + // 6. Open file with write mode on a read only share. + + // 7. Open file with write mode on exec only share. + + // 8. Open file with write mode on a share with write access. + + // 9. Open file with append mode on a read only share. +} + +void SmbFileTest::close() +{ + SmbFile emptyFileName(""); + // 1. Close file with empty file name that does not exists. + emptyFileName.close(); + + // 2. Close file that does not exists. + + // 3. Close file that has not been opened. + + // 4. Close file that has been opened and verify that is has been closed. +} + +void SmbFileTest::size() +{ + // 1. Size of a file with empty name. + + // 2. Size of a file which does not exist. + + // 3. Size of a file with 0 size. + + // 4. Size of a file on share we don't have access to. + + // 5. Size of a file we have access to and it has positive size. +} + +void SmbFileTest::resize() +{ + // TODO: Write plan. +} + +void SmbFileTest::permissions() +{ + // TODO: Write plan. +} + +void SmbFileTest::setPermissions() +{ + QFileDevice::Permissions permissions = QFileDevice::ReadOwner | QFileDevice::WriteOther; + + // Negative test cases. + // 1. Set permissions to file that does not exist. + SmbFile smbFile(""); + QCOMPARE(smbFile.setPermissions(permissions), false); + + // 2. Get permissions from file that does not exist. + QCOMPARE(smbFile.permissions(), QFileDevice::Permissions()); +} + +void SmbFileTest::read() +{ + // TODO: Write plan. +} + +void SmbFileTest::write() +{ + // TODO: Write plan. +} + +} + +QTEST_MAIN(tests::SmbFileTest) diff --git a/tests/auto/plugins/storage/smb/smbfiletest.h b/tests/auto/plugins/storage/smb/smbfiletest.h new file mode 100644 index 0000000..f4e57f7 --- /dev/null +++ b/tests/auto/plugins/storage/smb/smbfiletest.h @@ -0,0 +1,53 @@ +/*********************************************************************************************************************** +** +** Copyright (C) 2021 BaseALT Ltd. +** +** 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 2 +** 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, write to the Free Software +** Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +** +***********************************************************************************************************************/ + +#ifndef GPUI_SMB_FILE_TEST_H +#define GPUI_SMB_FILE_TEST_H + +#include + +namespace tests +{ + class SmbFileTest : public QObject + { + Q_OBJECT + + private slots: + void remove(); + void rename(); + + void link(); + void copy(); + + void open(); + void close(); + + void size(); + void resize(); + + void permissions(); + void setPermissions(); + + void read(); + void write(); + }; +} + +#endif // GPUI_SMB_FILE_TEST_H diff --git a/tests/auto/plugins/storage/smb/smbsharecreator.cpp b/tests/auto/plugins/storage/smb/smbsharecreator.cpp new file mode 100644 index 0000000..38bcaa6 --- /dev/null +++ b/tests/auto/plugins/storage/smb/smbsharecreator.cpp @@ -0,0 +1,33 @@ +/*********************************************************************************************************************** +** +** Copyright (C) 2021 BaseALT Ltd. +** +** 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 2 +** 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, write to the Free Software +** Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +** +***********************************************************************************************************************/ + +#include "smbsharecreator.h" + +namespace tests +{ + +bool SmbShareCreator::createShare(const QString &path) +{ + Q_UNUSED(path); + + return false; +} + +} diff --git a/tests/auto/plugins/storage/smb/smbsharecreator.h b/tests/auto/plugins/storage/smb/smbsharecreator.h new file mode 100644 index 0000000..7ebf064 --- /dev/null +++ b/tests/auto/plugins/storage/smb/smbsharecreator.h @@ -0,0 +1,37 @@ +/*********************************************************************************************************************** +** +** Copyright (C) 2021 BaseALT Ltd. +** +** 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 2 +** 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, write to the Free Software +** Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +** +***********************************************************************************************************************/ + +#ifndef SMB_SHARE_CREATOR_H +#define SMB_SHARE_CREATOR_H + +#include + +namespace tests +{ + +class SmbShareCreator +{ +public: + bool createShare(const QString& path); +}; + +} + +#endif//SMB_SHARE_CREATOR_H