feat, tests: add files for smb protocol

- implement classes to read files and directories
- implement routines to write files on smb shares
- remove nemofolderlist model
- add files for smb tests
This commit is contained in:
august-alt 2022-01-19 16:41:46 +04:00
parent ea7b444a9d
commit a2173ddbb8
30 changed files with 1546 additions and 458 deletions

View File

@ -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 <august@altlinux.org> 0.1.0-alt1
- Initial build

View File

@ -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' }}

View File

@ -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/

View File

@ -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)

View File

@ -37,9 +37,7 @@
#include "../io/registryfile.h"
#include "../io/registryfileformat.h"
#include "smbfilebrowser.h"
#include <libnemofolderlistmodel/qsambaclient/smblocationitemfile.h>
#include "../plugins/storage/smb/smbfile.h"
void registerResources()
{
@ -108,13 +106,13 @@ void save(const std::string &fileName, std::shared_ptr<model::registry::Registry
if (QString::fromStdString(fileName).startsWith("smb://"))
{
SmbLocationItemFile smbLocationItemFile(QString::fromStdString(fileName));
smbLocationItemFile.open(QFile::WriteOnly | QFile::Truncate);
if (!smbLocationItemFile.isOpen())
gpui::smb::SmbFile smbLocationItemFile(QString::fromStdString(fileName));
bool isOpen = smbLocationItemFile.open(QFile::WriteOnly | QFile::Truncate);
if (!isOpen)
{
smbLocationItemFile.open(QFile::NewOnly | QFile::WriteOnly);
isOpen = smbLocationItemFile.open(QFile::NewOnly | QFile::WriteOnly);
}
if (smbLocationItemFile.isOpen() && oss->str().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_ptr<model::registry::Registry
else
{
QFile registryFile(QString::fromStdString(fileName));
registryFile.open(QFile::ReadWrite);
registryFile.open(QFile::WriteOnly | QFile::Truncate);
if (!registryFile.isOpen())
{
registryFile.open(QFile::NewOnly | QFile::WriteOnly);
}
if (registryFile.isOpen() && registryFile.isWritable() && oss->str().size() > 0)
{
registryFile.write(&oss->str().at(0), oss->str().size());
@ -131,6 +133,7 @@ void save(const std::string &fileName, std::shared_ptr<model::registry::Registry
registryFile.close();
}
delete format;
}
@ -164,8 +167,6 @@ MainWindow::MainWindow(CommandLineOptions &options, QWidget *parent)
d->settings->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<model::registry::Registry>& registry,
std::unique_ptr<model::registry::AbstractRegistrySource>& source,
std::function<void(model::registry::AbstractRegistrySource* source)> 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<model::registry::Registry> &registry,
std::unique_ptr<model::registry::AbstractRegistrySource> &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());

View File

@ -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<model::registry::Registry>& registry,
std::unique_ptr<model::registry::AbstractRegistrySource>& source,
std::function<void(model::registry::AbstractRegistrySource* source)> callback);
void onPolFileOpen(const QString& path,
std::shared_ptr<model::registry::Registry>& registry,
std::unique_ptr<model::registry::AbstractRegistrySource>& source,

View File

@ -74,7 +74,6 @@
</property>
<addaction name="actionOpenPolicyDirectory"/>
<addaction name="separator"/>
<addaction name="actionOptions"/>
<addaction name="separator"/>
<addaction name="actionExit"/>
</widget>

View File

@ -1,78 +0,0 @@
#include "smbfilebrowser.h"
#include "ui_smbfilebrowser.h"
#include <libnemofolderlistmodel/dirmodel.h>
#include <libnemofolderlistmodel/dirselection.h>
#include <memory>
#include <QDir>
#include <QLineEdit>
#include <QDialog>
#include <QHeaderView>
#include <QTableView>
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);
}

View File

@ -1,65 +0,0 @@
#ifndef GPUI_SMB_FILE_BROWSER_H
#define GPUI_SMB_FILE_BROWSER_H
#include <QDialog>
#include <QModelIndex>
#include <memory>
namespace Ui {
class SmbFileBrowser;
}
class DirModel;
class DirSelection;
class QProgressBar;
class SmbFileBrowserPrivate
{
public:
std::unique_ptr<DirModel> 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

View File

@ -1,70 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>SmbFileBrowser</class>
<widget class="QDialog" name="SmbFileBrowser">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>942</width>
<height>460</height>
</rect>
</property>
<property name="windowTitle">
<string>Dialog</string>
</property>
<layout class="QGridLayout" name="gridLayout">
<item row="2" column="0">
<widget class="QTableView" name="tableViewFM"/>
</item>
<item row="1" column="0">
<layout class="QHBoxLayout" name="horizontalLayout">
<item>
<widget class="QToolButton" name="toolButtonBack">
<property name="enabled">
<bool>true</bool>
</property>
<property name="text">
<string>back</string>
</property>
<property name="icon">
<iconset theme="go-previous">
<normaloff>../../../../</normaloff>../../../../</iconset>
</property>
</widget>
</item>
<item>
<widget class="QToolButton" name="toolButtonUp">
<property name="text">
<string>Up</string>
</property>
<property name="icon">
<iconset theme="go-up">
<normaloff>../../../../</normaloff>../../../../</iconset>
</property>
</widget>
</item>
<item>
<widget class="QComboBox" name="comboBoxPath">
<property name="editable">
<bool>true</bool>
</property>
<property name="insertPolicy">
<enum>QComboBox::NoInsert</enum>
</property>
</widget>
</item>
</layout>
</item>
<item row="0" column="0">
<widget class="QProgressBar" name="progressBar">
<property name="value">
<number>0</number>
</property>
</widget>
</item>
</layout>
</widget>
<resources/>
<connections/>
</ui>

View File

@ -1,143 +0,0 @@
#include "smbfilebrowser.h"
#include "ui_smbfilebrowser.h"
#include <libnemofolderlistmodel/dirmodel.h>
#include <libnemofolderlistmodel/dirselection.h>
#include <QDir>
#include <QMetaType>
#include <QHeaderView>
#include <QDebug>
#include <QProgressBar>
#include <QMessageBox>
#include <QTimer>
#include <QLineEdit>
#include <QMouseEvent>
#include <QDialog>
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);
}

View File

@ -22,3 +22,4 @@ add_subdirectory(spol)
add_subdirectory(pol)
add_subdirectory(preferences)
add_subdirectory(reg)
add_subdirectory(storage)

View File

@ -0,0 +1,2 @@
add_subdirectory(local)
add_subdirectory(smb)

View File

View File

@ -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

View File

@ -0,0 +1,195 @@
/***********************************************************************************************************************
**
** Copyright (C) 2021 BaseALT Ltd. <org@basealt.ru>
**
** 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 &currentUserName, const QString &currentPassword,
AuthenticationFunction function)
{
userName = currentUserName.toLocal8Bit();
password = currentPassword.toLocal8Bit();
return createContext(function);
}
ContextPtr SmbClient::createContext(const QString &currentUserName, const QString &currentPassword,
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, decltype (&freeContext)> 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);
}
}
}

View File

@ -0,0 +1,391 @@
/***********************************************************************************************************************
**
** Copyright (C) 2021 BaseALT Ltd. <org@basealt.ru>
**
** 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 <memory>
#include <QUrl>
#include <libsmbclient.h>
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<Context, decltype(&freeContext)> ctx;
};
}
}
#endif//GPUI_SMB_CLIENT_H

View File

@ -0,0 +1,106 @@
/***********************************************************************************************************************
**
** Copyright (C) 2021 BaseALT Ltd. <org@basealt.ru>
**
** 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 <QDebug>
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;
}
}
}

View File

@ -0,0 +1,56 @@
/***********************************************************************************************************************
**
** Copyright (C) 2021 BaseALT Ltd. <org@basealt.ru>
**
** 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 <QString>
#include <memory>
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<SmbDirectoryPrivate, decltype(&freePrivate)> d;
};
}
}
#endif//GPUI_SMB_DIRECTORY_H

View File

@ -0,0 +1,335 @@
/***********************************************************************************************************************
**
** Copyright (C) 2021 BaseALT Ltd. <org@basealt.ru>
**
** 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 <QDebug>
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<char*>(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;
}
}
}

View File

@ -0,0 +1,66 @@
/***********************************************************************************************************************
**
** Copyright (C) 2021 BaseALT Ltd. <org@basealt.ru>
**
** 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 <QFile>
#include <memory>
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<SmbFilePrivate, decltype(&freePrivate)> d;
};
}
}
#endif//GPUI_SMB_FILE_H

View File

@ -8,3 +8,4 @@ add_subdirectory(adml)
add_subdirectory(admx)
add_subdirectory(pol)
add_subdirectory(preferences)
add_subdirectory(storage)

View File

@ -0,0 +1,2 @@
add_subdirectory(local)
add_subdirectory(smb)

View File

@ -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

View File

@ -0,0 +1,156 @@
/***********************************************************************************************************************
**
** Copyright (C) 2021 BaseALT Ltd. <org@basealt.ru>
**
** 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)

View File

@ -0,0 +1,53 @@
/***********************************************************************************************************************
**
** Copyright (C) 2021 BaseALT Ltd. <org@basealt.ru>
**
** 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 <QtTest>
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

View File

@ -0,0 +1,33 @@
/***********************************************************************************************************************
**
** Copyright (C) 2021 BaseALT Ltd. <org@basealt.ru>
**
** 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;
}
}

View File

@ -0,0 +1,37 @@
/***********************************************************************************************************************
**
** Copyright (C) 2021 BaseALT Ltd. <org@basealt.ru>
**
** 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 <QString>
namespace tests
{
class SmbShareCreator
{
public:
bool createShare(const QString& path);
};
}
#endif//SMB_SHARE_CREATOR_H