input/nfs: new plugin using libnfs

This commit is contained in:
Max Kellermann 2014-02-06 07:29:26 +01:00
parent 90886c0760
commit e4322a716c
8 changed files with 287 additions and 0 deletions

View File

@ -914,6 +914,7 @@ libinput_a_SOURCES = \
libinput_a_CPPFLAGS = $(AM_CPPFLAGS) \
$(CURL_CFLAGS) \
$(SMBCLIENT_CFLAGS) \
$(NFS_CFLAGS) \
$(CDIO_PARANOIA_CFLAGS) \
$(FFMPEG_CFLAGS) \
$(DESPOTIFY_CFLAGS) \
@ -923,6 +924,7 @@ INPUT_LIBS = \
libinput.a \
$(CURL_LIBS) \
$(SMBCLIENT_LIBS) \
$(NFS_LIBS) \
$(CDIO_PARANOIA_LIBS) \
$(FFMPEG_LIBS) \
$(DESPOTIFY_LIBS) \
@ -948,6 +950,11 @@ libinput_a_SOURCES += \
src/input/plugins/SmbclientInputPlugin.cxx src/input/plugins/SmbclientInputPlugin.hxx
endif
if ENABLE_NFS
libinput_a_SOURCES += \
src/input/plugins/NfsInputPlugin.cxx src/input/plugins/NfsInputPlugin.hxx
endif
if ENABLE_CDIO_PARANOIA
libinput_a_SOURCES += \
src/input/plugins/CdioParanoiaInputPlugin.cxx \

1
NEWS
View File

@ -14,6 +14,7 @@ ver 0.19 (not yet released)
- read tags from songs in an archive
* input
- alsa: new input plugin
- nfs: new input plugin
- smbclient: new input plugin
* filter
- volume: improved software volume dithering

View File

@ -310,6 +310,11 @@ AC_ARG_ENABLE(smbclient,
[enable support for libsmbclient (default: auto)]),,
[enable_smbclient=auto])
AC_ARG_ENABLE(nfs,
AS_HELP_STRING([--enable-nfs],
[enable support for libnfs (default: auto)]),,
[enable_nfs=auto])
AC_ARG_ENABLE(debug,
AS_HELP_STRING([--enable-debug],
[enable debugging (default: disabled)]),,
@ -859,6 +864,14 @@ if test x$enable_smbclient = xyes; then
fi
AM_CONDITIONAL(ENABLE_SMBCLIENT, test x$enable_smbclient = xyes)
dnl ----------------------------------- NFS -----------------------------
MPD_AUTO_PKG(nfs, NFS, [libnfs],
[NFS input plugin], [libnfs not found])
if test x$enable_nfs = xyes; then
AC_DEFINE(ENABLE_NFS, 1, [Define when libnfs is used])
fi
AM_CONDITIONAL(ENABLE_NFS, test x$enable_nfs = xyes)
dnl --------------------------------- Despotify ---------------------------------
MPD_AUTO_PKG(despotify, DESPOTIFY, [despotify],
[Despotify support], [despotify not found])

View File

@ -1152,6 +1152,35 @@ systemctl start mpd.socket</programlisting>
</para>
</section>
<section>
<title><varname>nfs</varname></title>
<para>
Allows MPD to access files on NFSv3 servers without actually
mounting them (i.e. in userspace, without help from the
kernel's VFS layer). All URIs with the
<filename>nfs://</filename> scheme are used according to
<ulink
url="http://tools.ietf.org/html/rfc2224">RFC2224</ulink>.
Example:
</para>
<para>
<filename>mpc add nfs://servername/path/filename.ogg</filename>
</para>
<para>
Note that this usually requires enabling the "insecure" flag
in the server's <filename>/etc/exports</filename> file,
because MPD cannot bind to so-called "privileged" ports.
Don't fear: this will not make your file server insecure;
the flag was named in a time long ago when privileged ports
were thought to be meaningful for security. By today's
standards, NFSv3 is not secure at all, and if you believe it
is, you're already doomed.
</para>
</section>
<section>
<title><varname>smbclient</varname></title>

View File

@ -42,6 +42,10 @@
#include "plugins/SmbclientInputPlugin.hxx"
#endif
#ifdef ENABLE_NFS
#include "plugins/NfsInputPlugin.hxx"
#endif
#ifdef ENABLE_MMS
#include "plugins/MmsInputPlugin.hxx"
#endif
@ -71,6 +75,9 @@ const InputPlugin *const input_plugins[] = {
#ifdef ENABLE_SMBCLIENT
&input_plugin_smbclient,
#endif
#ifdef ENABLE_NFS
&input_plugin_nfs,
#endif
#ifdef ENABLE_MMS
&input_plugin_mms,
#endif

View File

@ -0,0 +1,202 @@
/*
* 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 "NfsInputPlugin.hxx"
#include "../InputStream.hxx"
#include "../InputPlugin.hxx"
#include "util/StringUtil.hxx"
#include "util/Error.hxx"
#include "util/Domain.hxx"
extern "C" {
#include <nfsc/libnfs.h>
}
#include <sys/stat.h>
#include <fcntl.h>
static constexpr Domain nfs_domain("nfs");
class NfsInputStream {
InputStream base;
nfs_context *ctx;
nfsfh *fh;
public:
NfsInputStream(const char *uri,
Mutex &mutex, Cond &cond,
nfs_context *_ctx, nfsfh *_fh,
InputStream::offset_type size)
:base(input_plugin_nfs, uri, mutex, cond),
ctx(_ctx), fh(_fh) {
base.ready = true;
base.seekable = true;
base.size = size;
}
~NfsInputStream() {
nfs_close(ctx, fh);
nfs_destroy_context(ctx);
}
InputStream *GetBase() {
return &base;
}
bool IsEOF() const {
return base.offset >= base.size;
}
size_t Read(void *ptr, size_t size, Error &error) {
int nbytes = nfs_read(ctx, fh, size, (char *)ptr);
if (nbytes < 0) {
error.SetErrno(-nbytes, "nfs_read() failed");
nbytes = 0;
}
return nbytes;
}
bool Seek(InputStream::offset_type offset, int whence, Error &error) {
uint64_t current_offset;
int result = nfs_lseek(ctx, fh, offset, whence, &current_offset);
if (result < 0) {
error.SetErrno(-result, "smbc_lseek() failed");
return false;
}
base.offset = current_offset;
return true;
}
};
/*
* InputPlugin methods
*
*/
static InputStream *
input_nfs_open(const char *uri,
Mutex &mutex, Cond &cond,
Error &error)
{
if (!StringStartsWith(uri, "nfs://"))
return nullptr;
uri += 6;
const char *slash = strchr(uri, '/');
if (slash == nullptr) {
error.Set(nfs_domain, "Malformed nfs:// URI");
return nullptr;
}
const std::string server(uri, slash);
uri = slash;
slash = strrchr(uri + 1, '/');
if (slash == nullptr || slash[1] == 0) {
error.Set(nfs_domain, "Malformed nfs:// URI");
return nullptr;
}
const std::string mount(uri, slash);
uri = slash;
nfs_context *ctx = nfs_init_context();
if (ctx == nullptr) {
error.Set(nfs_domain, "nfs_init_context() failed");
return nullptr;
}
int result = nfs_mount(ctx, server.c_str(), mount.c_str());
if (result < 0) {
nfs_destroy_context(ctx);
error.SetErrno(-result, "nfs_mount() failed");
return nullptr;
}
nfsfh *fh;
result = nfs_open(ctx, uri, O_RDONLY, &fh);
if (result < 0) {
nfs_destroy_context(ctx);
error.SetErrno(-result, "nfs_open() failed");
return nullptr;
}
struct stat st;
result = nfs_fstat(ctx, fh, &st);
if (result < 0) {
nfs_close(ctx, fh);
nfs_destroy_context(ctx);
error.SetErrno(-result, "nfs_fstat() failed");
return nullptr;
}
auto is = new NfsInputStream(uri, mutex, cond, ctx, fh, st.st_size);
return is->GetBase();
}
static size_t
input_nfs_read(InputStream *is, void *ptr, size_t size,
Error &error)
{
NfsInputStream &s = *(NfsInputStream *)is;
return s.Read(ptr, size, error);
}
static void
input_nfs_close(InputStream *is)
{
NfsInputStream *s = (NfsInputStream *)is;
delete s;
}
static bool
input_nfs_eof(InputStream *is)
{
NfsInputStream &s = *(NfsInputStream *)is;
return s.IsEOF();
}
static bool
input_nfs_seek(InputStream *is,
InputPlugin::offset_type offset, int whence,
Error &error)
{
NfsInputStream &s = *(NfsInputStream *)is;
return s.Seek(offset, whence, error);
}
const InputPlugin input_plugin_nfs = {
"nfs",
nullptr,
nullptr,
input_nfs_open,
input_nfs_close,
nullptr,
nullptr,
nullptr,
nullptr,
input_nfs_read,
input_nfs_eof,
input_nfs_seek,
};

View File

@ -0,0 +1,25 @@
/*
* 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_INPUT_NFS_H
#define MPD_INPUT_NFS_H
extern const struct InputPlugin input_plugin_nfs;
#endif

View File

@ -52,6 +52,9 @@ static const char *remoteUrlPrefixes[] = {
#ifdef ENABLE_SMBCLIENT
"smb://",
#endif
#ifdef ENABLE_NFS
"nfs://",
#endif
#ifdef ENABLE_CDIO_PARANOIA
"cdda://",
#endif