Commit c8f0c7e9 authored by Max Kellermann's avatar Max Kellermann

*/smbclient: protect all libsmbclient calls with a mutex

libsmbclient is not thread-safe nor reentrant. We must protect all function calls with a global mutex, unfortunately.
parent a7989077
......@@ -415,6 +415,7 @@ libfs_a_SOURCES = \
SMBCLIENT_SOURCES = \
src/lib/smbclient/Domain.cxx src/lib/smbclient/Domain.hxx \
src/lib/smbclient/Mutex.cxx src/lib/smbclient/Mutex.hxx \
src/lib/smbclient/Init.cxx src/lib/smbclient/Init.hxx
if ENABLE_DATABASE
......
......@@ -20,6 +20,7 @@
#include "config.h"
#include "SmbclientInputPlugin.hxx"
#include "lib/smbclient/Init.hxx"
#include "lib/smbclient/Mutex.hxx"
#include "../InputStream.hxx"
#include "../InputPlugin.hxx"
#include "util/StringUtil.hxx"
......@@ -45,8 +46,10 @@ public:
}
~SmbclientInputStream() {
smbclient_mutex.lock();
smbc_close(fd);
smbc_free_context(ctx, 1);
smbclient_mutex.unlock();
}
InputStream *GetBase() {
......@@ -58,7 +61,9 @@ public:
}
size_t Read(void *ptr, size_t size, Error &error) {
smbclient_mutex.lock();
ssize_t nbytes = smbc_read(fd, ptr, size);
smbclient_mutex.unlock();
if (nbytes < 0) {
error.SetErrno("smbc_read() failed");
nbytes = 0;
......@@ -68,7 +73,9 @@ public:
}
bool Seek(InputStream::offset_type offset, int whence, Error &error) {
smbclient_mutex.lock();
off_t result = smbc_lseek(fd, offset, whence);
smbclient_mutex.unlock();
if (result < 0) {
error.SetErrno("smbc_lseek() failed");
return false;
......@@ -105,6 +112,8 @@ input_smbclient_open(const char *uri,
if (!StringStartsWith(uri, "smb://"))
return nullptr;
const ScopeLock protect(smbclient_mutex);
SMBCCTX *ctx = smbc_new_context();
if (ctx == nullptr) {
error.SetErrno("smbc_new_context() failed");
......
......@@ -19,6 +19,8 @@
#include "config.h"
#include "Init.hxx"
#include "Mutex.hxx"
#include "thread/Mutex.hxx"
#include "util/Error.hxx"
#include <libsmbclient.h>
......@@ -41,6 +43,8 @@ mpd_smbc_get_auth_data(gcc_unused const char *srv,
bool
SmbclientInit(Error &error)
{
const ScopeLock protect(smbclient_mutex);
constexpr int debug = 0;
if (smbc_init(mpd_smbc_get_auth_data, debug) < 0) {
error.SetErrno("smbc_init() failed");
......
/*
* Copyright (C) 2003-2014 The Music Player Daemon Project
* http://www.musicpd.org
*
* 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 "config.h"
#include "Mutex.hxx"
#include "thread/Mutex.hxx"
Mutex smbclient_mutex;
/*
* Copyright (C) 2003-2014 The Music Player Daemon Project
* http://www.musicpd.org
*
* 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 MPD_SMBCLIENT_MUTEX_HXX
#define MPD_SMBCLIENT_MUTEX_HXX
class Mutex;
/**
* Since libsmbclient is not thread-safe, this mutex must be locked
* during all libsmbclient function calls.
*/
extern Mutex smbclient_mutex;
#endif
......@@ -21,6 +21,7 @@
#include "SmbclientNeighborPlugin.hxx"
#include "lib/smbclient/Init.hxx"
#include "lib/smbclient/Domain.hxx"
#include "lib/smbclient/Mutex.hxx"
#include "neighbor/NeighborPlugin.hxx"
#include "neighbor/Explorer.hxx"
#include "neighbor/Listener.hxx"
......@@ -175,6 +176,7 @@ static NeighborExplorer::List
DetectServers()
{
NeighborExplorer::List list;
const ScopeLock protect(smbclient_mutex);
ReadServers(list, "smb://");
return list;
}
......
......@@ -22,7 +22,9 @@
#include "storage/StorageInterface.hxx"
#include "storage/FileInfo.hxx"
#include "lib/smbclient/Init.hxx"
#include "lib/smbclient/Mutex.hxx"
#include "util/Error.hxx"
#include "thread/Mutex.hxx"
#include <libsmbclient.h>
......@@ -54,7 +56,9 @@ public:
:base(_base), ctx(_ctx) {}
virtual ~SmbclientStorage() {
smbclient_mutex.lock();
smbc_free_context(ctx, 1);
smbclient_mutex.unlock();
}
/* virtual methods from class Storage */
......@@ -82,7 +86,10 @@ static bool
GetInfo(const char *path, FileInfo &info, Error &error)
{
struct stat st;
if (smbc_stat(path, &st) < 0) {
smbclient_mutex.lock();
bool success = smbc_stat(path, &st) == 0;
smbclient_mutex.unlock();
if (!success) {
error.SetErrno();
return false;
}
......@@ -113,7 +120,9 @@ StorageDirectoryReader *
SmbclientStorage::OpenDirectory(const char *uri_utf8, Error &error)
{
std::string mapped = MapUTF8(uri_utf8);
smbclient_mutex.lock();
int handle = smbc_opendir(mapped.c_str());
smbclient_mutex.unlock();
if (handle < 0) {
error.SetErrno();
return nullptr;
......@@ -133,12 +142,16 @@ SkipNameFS(const char *name)
SmbclientDirectoryReader::~SmbclientDirectoryReader()
{
smbclient_mutex.lock();
smbc_close(handle);
smbclient_mutex.unlock();
}
const char *
SmbclientDirectoryReader::Read()
{
const ScopeLock protect(smbclient_mutex);
struct smbc_dirent *e;
while ((e = smbc_readdir(handle)) != nullptr) {
name = e->name;
......@@ -163,6 +176,7 @@ CreateSmbclientStorage(const char *base, Error &error)
if (!SmbclientInit(error))
return nullptr;
const ScopeLock protect(smbclient_mutex);
SMBCCTX *ctx = smbc_new_context();
if (ctx == nullptr) {
error.SetErrno("smbc_new_context() failed");
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment