Thomas Guillem | 21 May 23:43 2015
Picon

[PATCH 0/6] Change the Ape/Riff/Aiff/Id3 scanners to use an InputStream

This set of patches modify the tag scanners to use an InputStream. That way
you can use these scanners with a remote input like NFS and SMB.

Waiting for your comments.

Best regards,
Thomas Guillem

Thomas Guillem (6):
  InputStream: add ReadFull method
  tag: Ape/Riff/Aiff/Id3 now use an InputStream
  SongUpdate: use an InputStream to scan from decoders and tag scanners
  FileCommands: use one InputStream for both scanners
  EmbeddedCuePlaylist: use one InputStream for both scanners
  Remove unused TagFile.cxx

 Makefile.am                                        |   2 -
 src/SongUpdate.cxx                                 |  83 +++++++++--------
 src/TagFile.cxx                                    | 100 ---------------------
 src/TagFile.hxx                                    |  38 --------
 src/command/FileCommands.cxx                       |  21 +++--
 src/input/InputStream.cxx                          |  31 ++++++-
 src/input/InputStream.hxx                          |  21 +++++
 src/playlist/plugins/EmbeddedCuePlaylistPlugin.cxx |  22 +++--
 src/tag/Aiff.cxx                                   |  29 ++----
 src/tag/Aiff.hxx                                   |   4 +-
 src/tag/ApeLoader.cxx                              |  43 ++++++---
 src/tag/ApeLoader.hxx                              |  11 +++
 src/tag/ApeTag.cxx                                 |  19 ++++
 src/tag/ApeTag.hxx                                 |  10 +++
(Continue reading)

Yclept Nemo | 21 May 05:31 2015
Picon

[PATCH] Workaround: open() ignores 'mode' with O_TMPFILE

From f530e59fd363722a7a4fa9fd60b2da2241c1a9fc Mon Sep 17 00:00:00 2001
From: Yclept Nemo <pscjtwjdjtAhnbjm/dpn>
Date: Wed, 20 May 2015 23:18:15 -0400
Subject: [PATCH] Workaround: open() ignores 'mode' with O_TMPFILE

---
 configure.ac                   | 51 ++++++++++++++++++++++++++++++++++++++++++
 src/fs/io/FileOutputStream.cxx |  8 ++-----
 src/system/FileDescriptor.cxx  |  4 ++++
 src/system/FileDescriptor.hxx  |  9 ++++++++
 4 files changed, 66 insertions(+), 6 deletions(-)

diff --git a/configure.ac b/configure.ac
index 82f814d..ed76f51 100644
--- a/configure.ac
+++ b/configure.ac
<at> <at> -561,6 +561,57 <at> <at> if test x$enable_largefile != xno; then
 fi
 
 dnl ---------------------------------------------------------------------------
+dnl LIBC Workarounds
+dnl ---------------------------------------------------------------------------
+if test "x$host_is_linux" = xyes && test "x$ac_cv_func_linkat" = xyes && test "x$enable_largefile" != xno; then
+    AC_MSG_CHECKING( [if O_TMPFILE requires fchmod])
+    AC_RUN_IFELSE(
+          [AC_LANG_PROGRAM(
+              [[#define _FILE_OFFSET_BITS 64
+                #include <fcntl.h>
+                #include <limits.h>
+                #include <sys/types.h>
+                #include <sys/stat.h>
+              ]] 
+            , [[struct stat statbuf;
+                int fd;
+                int mode = 0666;
+                if ((fd = open(".", O_TMPFILE|O_WRONLY, mode)) < 0)
+                    return 1;
+                if (fstat(fd, &statbuf) < 0)
+                    return 1;
+                if (close(fd) < 0)
+                    return 1;
+                if ((statbuf.st_mode & (S_IRWXU|S_IRWXG|S_IRWXO)) != mode)
+                    return 1;
+                return 0;
+              ]]
+            )
+          ]
+        , open_tmpfile_fchmod=no
+        , open_tmpfile_fchmod=yes
+        , open_tmpfile_fchmod=yes
+        )
+    if test "x$open_tmpfile_fchmod" = xyes; then
+        AC_MSG_RESULT([yes])
+        AC_CHECK_FUNCS(
+              [fchmod]
+            , [ AC_DEFINE([OPEN_TMPFILE_FCHMOD],
+                          [1],
+                          [Workaround: _LARGE_FILE + O_TMPFILE -> mode == 0])
+                AC_MSG_NOTICE([Enabling open/tmpfile workaround using fchmod])
+              ]
+            , [ AC_DEFINE([HAVE_LINKAT],
+                          [0])
+                AC_MSG_NOTICE([Disabling linkat support])
+              ]
+            )
+    else
+        AC_MSG_RESULT([no])
+    fi
+fi
+
+dnl ---------------------------------------------------------------------------
 dnl Miscellaneous Libraries
 dnl ---------------------------------------------------------------------------
 
diff --git a/src/fs/io/FileOutputStream.cxx b/src/fs/io/FileOutputStream.cxx
index a4ef8f6..6451b8c 100644
--- a/src/fs/io/FileOutputStream.cxx
+++ b/src/fs/io/FileOutputStream.cxx
<at> <at> -106,13 +106,10 <at> <at> FileOutputStream::Cancel()
 #include <errno.h>
 
 #ifdef HAVE_LINKAT
-#ifndef O_TMPFILE
-/* supported since Linux 3.11 */
-#define __O_TMPFILE 020000000
-#define O_TMPFILE (__O_TMPFILE | O_DIRECTORY)
 #include <stdio.h>
 #endif
 
+#ifdef HAVE_LINKAT
 /**
  * Open a file using Linux's O_TMPFILE for writing the given file.
  */
<at> <at> -125,8 +122,7 <at> <at> OpenTempFile(FileDescriptor &fd, Path path)
 
     return fd.Open(directory.c_str(), O_TMPFILE|O_WRONLY, 0666);
 }
-
-#endif /* HAVE_LINKAT */
+#endif
 
 FileOutputStream::FileOutputStream(Path _path, Error &error)
     :BaseFileOutputStream(_path)
diff --git a/src/system/FileDescriptor.cxx b/src/system/FileDescriptor.cxx
index db258e1..f30c9c2 100644
--- a/src/system/FileDescriptor.cxx
+++ b/src/system/FileDescriptor.cxx
<at> <at> -61,6 +61,10 <at> <at> bool
 FileDescriptor::Open(const char *pathname, int flags, mode_t mode)
 {
     fd = ::open(pathname, flags | O_NOCTTY | O_CLOEXEC, mode);
+#ifdef OPEN_TMPFILE_FCHMOD
+    if ((flags & O_TMPFILE) && IsDefined())
+        fchmod(fd, mode);
+#endif
     return IsDefined();
 }
 
diff --git a/src/system/FileDescriptor.hxx b/src/system/FileDescriptor.hxx
index 75a7684..43cb857 100644
--- a/src/system/FileDescriptor.hxx
+++ b/src/system/FileDescriptor.hxx
<at> <at> -36,11 +36,20 <at> <at>
 #include <assert.h>
 #include <unistd.h>
 #include <sys/types.h>
+#include <fcntl.h>
 
 #ifdef USE_SIGNALFD
 #include <signal.h>
 #endif
 
+#ifdef HAVE_LINKAT
+#ifndef O_TMPFILE
+/* supported since Linux 3.11 */
+#define __O_TMPFILE 020000000
+#define O_TMPFILE (__O_TMPFILE | O_DIRECTORY)
+#endif
+#endif
+
 /**
  * An OO wrapper for a UNIX file descriptor.
  *
--
2.1.4


_______________________________________________
mpd-devel mailing list
mpd-devel <at> musicpd.org
http://mailman.blarg.de/listinfo/mpd-devel
Yclept Nemo | 20 May 09:43 2015
Picon

Upstream MPD aborts on second run

/* Summary:
 *  O_TMPFILE linked with zero permissions when _FILE_OFFSET_BITS is 64
 *
 * Upstream MPD aborts on second run with the following message:
 *  errno: Failed to open ~/.mpd/database: Permission denied
 *  fatal_error: Can't open db file "~/.mpd/database" for reading/writing: Permission denied
 * The problem was introduced in the following commit:
 *  8b217d531305433df01c789dab4dc81d58f05eba
 *  fs/io/FileOutputStream: use O_TMPFILE if available
 * The problem only manifests under the following conditions:
 *  _FILE_OFFSET_BITS is set to 64 (presumably an value other than 32)
 *  open() a file with the O_TMPFILE flag and appropriate mode
 *  linkat() the file
 * The resulting linked file will have the permission bits set to 0.
 *
 * This is either related to or identical and fixed by the following bug-report (2015-02-24):
 *  https://sourceware.org/bugzilla/show_bug.cgi?id=17523
 * In any case, directly using SYS_open is a valid workaround.
 *
 * The following is a simple test-case.
 *
 * Run:
 *  bash -vc "$( sed -n 's#^ \*  \(rm .*\)$#\1#p' test.tmpfile2.cpp )"
 *
 * Command:
 *  rm -f /tmp/testfile? test.tmpfile2 && g++ test.tmpfile2.cpp -o test.tmpfile2 && ./test.tmpfile2 && ls -lah /tmp/testfile?
 *
 * System details:
 *  i686, Linux 3.19.0-16-generic, Ubuntu GLIBC 2.21-0ubuntu4, Ubuntu GCC 4.9.2-10ubuntu13
 *
 * Proposed solution:
 *  modify FileDescriptor.cxx:FileDescriptor::Open(...) to use syscall(SYS_open, ...) instead of open(...)
 *  version this to glibc <= 2.21 (__GLIBC__, __GLIBC_MINOR__ ?)
*/

#define _FILE_OFFSET_BITS 64

#include <fcntl.h>
#include <unistd.h>
#include <limits.h>
#include <stdio.h>
#include <unistd.h>
#include <sys/syscall.h>


int main() {
    int flags = O_WRONLY;

    char path[PATH_MAX];

    // problem: false
    int fd0 = open("/tmp/testfile0", O_CREAT|flags, 0666);
    close(fd0);

    // problem: true
    int fd1 = open("/tmp", O_TMPFILE|flags, 0666);
    snprintf(path, sizeof(path), "/proc/self/fd/%d", fd1);
    linkat
        ( AT_FDCWD, path
        , AT_FDCWD, "/tmp/testfile1"
        , AT_SYMLINK_FOLLOW
        );
    close(fd1);

    // problem: false
    int fd2 = syscall
        ( SYS_open
        , "/tmp"
        , O_TMPFILE|flags
        , 0666
        );
    snprintf(path, sizeof(path), "/proc/self/fd/%d", fd2);
    linkat
        ( AT_FDCWD, path
        , AT_FDCWD, "/tmp/testfile2"
        , AT_SYMLINK_FOLLOW
        );
    close(fd2);
}

_______________________________________________
mpd-devel mailing list
mpd-devel <at> musicpd.org
http://mailman.blarg.de/listinfo/mpd-devel
Yclept Nemo | 20 May 02:22 2015
Picon

[PATCH] smbclient auth support v2

From 000c5e7faaa233e0adf1ee550237bc79b706a6aa Mon Sep 17 00:00:00 2001
From: Yclept Nemo <pscjtwjdjtAhnbjm/dpn>
Date: Mon, 18 May 2015 14:07:13 -0400
Subject: [PATCH 2/2] smbclient auth support

There is now a backend block which in turns provides several password
configuration backends:

Configuration file:
    backend {
        name                "smbclient"
        password_backend    "config"
        username            "ExampleName"
        password            "ExamplePassword"
    }
Libsecret (keyring):
    backend {
        name                "smbclient"
        password_backend    "libsecret"
        username            "ExampleName"
    }

Some values are optional:
    backend {
        name        "smbclient"
        workgroup   "FANCYWORKGROUP"
        username    "ExampleName"
    }

Defaults:
    workgroup           "WORKGROUP"
    username            ""
    password            ""
    password_backend    "config"

Use scripts/mpd.secret.py to store a secret (password) and optionally
create a new collection (keyring).
---
 INSTALL                        |   3 +
 Makefile.am                    |  18 ++++-
 configure.ac                   |   5 ++
 doc/user.xml                   | 133 +++++++++++++++++++++++++++++++
 scripts/mpd.secret.py          | 111 ++++++++++++++++++++++++++
 src/config/ConfigOption.hxx    |   1 +
 src/config/ConfigTemplates.cxx |   1 +
 src/lib/smbclient/Init.cxx     | 176 ++++++++++++++++++++++++++++++++++++-----
 src/lib/smbclient/Init.hxx     |  89 ++++++++++++++++++++-
 9 files changed, 513 insertions(+), 24 deletions(-)
 create mode 100755 scripts/mpd.secret.py

diff --git a/INSTALL b/INSTALL
index 792bbd7..8de660d 100644
--- a/INSTALL
+++ b/INSTALL
<at> <at> -138,6 +138,9 <at> <at> For playing audio CDs.
 libsystemd-daemon - http://freedesktop.org/wiki/Software/systemd/
 For systemd activation.
 
+libsecret - https://wiki.gnome.org/Projects/Libsecret
+For smbclient libsecret authentication.
+
 
 pkg-config
 ----------
diff --git a/Makefile.am b/Makefile.am
index c6bcfa1..fc8cc51 100644
--- a/Makefile.am
+++ b/Makefile.am
<at> <at> -611,12 +611,14 <at> <at> libstorage_a_SOURCES = \
 
 libstorage_a_CPPFLAGS = $(AM_CPPFLAGS) \
     $(NFS_CFLAGS) \
-    $(SMBCLIENT_CFLAGS)
+    $(SMBCLIENT_CFLAGS) \
+    $(LIBSECRET_CFLAGS)
 
 STORAGE_LIBS = \
     libstorage.a \
     $(NFS_LIBS) \
-    $(SMBCLIENT_LIBS)
+    $(SMBCLIENT_LIBS) \
+    $(LIBSECRET_LIBS)
 
 if ENABLE_SMBCLIENT
 libstorage_a_SOURCES += \
<at> <at> -651,7 +653,8 <at> <at> libneighbor_a_SOURCES = \
     src/neighbor/NeighborPlugin.hxx
 
 libneighbor_a_CPPFLAGS = $(AM_CPPFLAGS) \
-    $(SMBCLIENT_CFLAGS)
+    $(SMBCLIENT_CFLAGS) \
+    $(LIBSECRET_CFLAGS)
 
 if ENABLE_SMBCLIENT
 libneighbor_a_SOURCES += \
<at> <at> -661,6 +664,7 <at> <at> endif
 
 NEIGHBOR_LIBS = \
     $(SMBCLIENT_LIBS) \
+    $(LIBSECRET_LIBS) \
     libneighbor.a
 
 if ENABLE_UPNP
<at> <at> -1165,6 +1169,7 <at> <at> libinput_a_SOURCES = \
 libinput_a_CPPFLAGS = $(AM_CPPFLAGS) \
     $(CURL_CFLAGS) \
     $(SMBCLIENT_CFLAGS) \
+    $(LIBSECRET_CFLAGS) \
     $(NFS_CFLAGS) \
     $(CDIO_PARANOIA_CFLAGS) \
     $(FFMPEG_CFLAGS) \
<at> <at> -1174,6 +1179,7 <at> <at> INPUT_LIBS = \
     libinput.a \
     $(CURL_LIBS) \
     $(SMBCLIENT_LIBS) \
+    $(LIBSECRET_LIBS) \
     $(NFS_LIBS) \
     $(CDIO_PARANOIA_LIBS) \
     $(FFMPEG_LIBS2) \
<at> <at> -2194,6 +2200,11 <at> <at> endif
 man_MANS = doc/mpd.1 doc/mpd.conf.5
 doc_DATA = AUTHORS COPYING NEWS README doc/mpdconf.example
 
+if ENABLE_LIBSECRET
+docscriptsdir = $(docdir)/scripts
+docscripts_SCRIPTS = scripts/mpd.secret.py
+endif
+
 DOCBOOK_FILES = doc/protocol.xml doc/user.xml doc/developer.xml
 
 if ENABLE_DOCUMENTATION
<at> <at> -2251,6 +2262,7 <at> <at> EXTRA_DIST = $(doc_DATA) autogen.sh \
     test/test_archive_zzip.sh \
     $(wildcard scripts/*.sh) \
     $(man_MANS) $(DOCBOOK_FILES) doc/mpdconf.example doc/doxygen.conf \
+    scripts/mpd.secret.py
     systemd/mpd.socket \
     android/AndroidManifest.xml \
     android/build.py \
diff --git a/configure.ac b/configure.ac
index dfd208a..82f814d 100644
--- a/configure.ac
+++ b/configure.ac
<at> <at> -709,6 +709,10 <at> <at> dnl ----------------------------------- CURL ----------------------------------
 MPD_ENABLE_AUTO_PKG(curl, CURL, [libcurl >= 7.18],
     [libcurl HTTP streaming], [libcurl not found])
 
+dnl --------------------------------- LIBSECRET -------------------------------
+MPD_ENABLE_AUTO_PKG(libsecret, LIBSECRET, [libsecret-1],
+    [libsecret password support], [libsecret not found])
+
 dnl ----------------------------------- smbclient -----------------------------
 MPD_ENABLE_AUTO_PKG_LIB(smbclient, SMBCLIENT, [smbclient >= 0.2],
     [smbclient], [smbc_init], [-lsmbclient], [],
<at> <at> -1421,6 +1425,7 <at> <at> results(soxr, [libsoxr])
 results(libmpdclient, [libmpdclient])
 results(inotify, [inotify])
 results(sqlite, [SQLite])
+results(libsecret, [LIBSECRET])
 
 printf '\nMetadata support:\n\t'
 results(id3,[ID3])
diff --git a/doc/user.xml b/doc/user.xml
index 7a60b04..1838485 100644
--- a/doc/user.xml
+++ b/doc/user.xml
<at> <at> -1025,6 +1025,64 <at> <at> database {
         plugin).
       </para>
     </section>
+
+    <section id="smbclient_auth">
+      <title>Smbclient Authentication</title>
+
+      <para>
+        <application>MPD</application> can can be configured to
+        authenticate itself to SMB/CIFS servers. This section
+        illustrates several setups.
+      </para>
+
+      <para>
+        Both of the following configurations use the
+        <filename>mpd.conf</filename> configuration file to store the
+        authentication information. Notice some values have been omitted from
+        the second section. See <link
+            linkend="smbclient_backend"><varname>smbclient</varname></link> for
+        default values:
+      </para>
+
+      <programlisting>
+backend {
+    name                "smbclient"
+    password_backend    "config"
+    username            "ExampleName"
+    password            "ExamplePassword"
+}
+
+backend {
+    name        "smbclient"
+    workgroup   "FANCYWORKGROUP"
+    username    "ExampleName"
+}
+      </programlisting>
+
+      <para>
+        This configuration queries the "Secret Service" via DBus. This can
+        obtain the password from multiple implementations, including
+        <application>gnome-keyring</application> and
+        <application>ksecretservice</application>.
+      </para>
+      <programlisting>
+backend {
+    name                "smbclient"
+    password_backend    "libsecret"
+    username            "ExampleName"
+}
+      </programlisting>
+
+      <para>
+        The provided <filename>python3</filename> script,
+        <filename>mpd.secret.py</filename>, aids in creating both the
+        collection (keyring) and secret (password). It is only installed if
+        <application>MPD</application> has been compiled with
+        <filename>libsecret</filename>, and requires the
+        <filename>gobject-introspection</filename> bindings to
+        <filename>libsecret</filename>.
+      </para>
+    </section>
   </chapter>
 
   <chapter id="use">
<at> <at> -3427,4 +3485,79 <at> <at> buffer_size: 16384</programlisting>
       </section>
     </section>
   </chapter>
+
+  <chapter id="backend_reference">
+    <title>Backend reference</title>
+
+    <para>
+      The <varname>backend</varname> block configures various backends
+      through the <varname>name</varname> setting. At the moment, only
+      <parameter>smbclient</parameter> can be configured in this
+      manner.
+    </para>
+
+    <section id="smbclient_backend">
+        <title><parameter>smbclient</parameter></title>
+
+      <para>
+        The <varname>smbclient</varname> backend supports
+        authentication if configured.
+      </para>
+
+      <informaltable>
+        <tgroup cols="2">
+          <thead>
+            <row>
+              <entry>Setting</entry>
+              <entry>Description</entry>
+            </row>
+          </thead>
+          <tbody>
+            <row>
+              <entry>
+                <varname>password_backend</varname>
+                <parameter>config|libsecret</parameter>
+              </entry>
+              <entry>
+                Source from which to read the password. When set to
+                <parameter>config</parameter>, the password will be
+                read from <varname>password</varname>. When set to
+                <parameter>libsecret</parameter>, the "Secret Service"
+                will be queried over DBus. Defaults to
+                <parameter>config</parameter>.
+              </entry>
+            </row>
+            <row>
+              <entry>
+                <varname>username</varname>
+                <parameter>NAME</parameter>
+              </entry>
+              <entry>
+                Username with which to authenticate. Defaults to "".
+              </entry>
+            </row>
+            <row>
+              <entry>
+                <varname>password</varname>
+                <parameter>WORD</parameter>
+              </entry>
+              <entry>
+                Password with which to authenticate. Defaults to "".
+              </entry>
+            </row>
+            <row>
+              <entry>
+                <varname>workgroup</varname>
+                <parameter>GROUP</parameter>
+              </entry>
+              <entry>
+                Workgroup with which to authenticate. Defaults to
+                "WORKGROUP".
+              </entry>
+            </row>
+          </tbody>
+        </tgroup>
+      </informaltable>
+    </section>
+  </chapter>
 </book>
diff --git a/scripts/mpd.secret.py b/scripts/mpd.secret.py
new file mode 100755
index 0000000..30cb497
--- /dev/null
+++ b/scripts/mpd.secret.py
<at> <at> -0,0 +1,111 <at> <at>
+#!/usr/bin/env python3
+#
+# Copyright (C) 2003-2015 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.
+#
+
+
+import getpass
+from gi.repository import Secret
+
+
+mpd_schema_attributes =\
+    { "server"    : Secret.SchemaAttributeType.STRING
+    , "share"     : Secret.SchemaAttributeType.STRING
+    , "workgroup" : Secret.SchemaAttributeType.STRING
+    , "username"  : Secret.SchemaAttributeType.STRING
+    }
+
+mpd_schema = Secret.Schema.new\
+    ( "org.mpd.smbclient.password"
+    , Secret.SchemaFlags.NONE
+    , mpd_schema_attributes
+    )
+
+mpd_default_input_data =\
+    { "collection"  : { "default": "MusicPD" }
+    , "password"    : { "secret": True }
+    , "server"      : { }
+    , "share"       : { }
+    , "workgroup"   : { "default": "WORKGROUP" }
+    , "username"    : { }
+    }
+
+
+def mpd_prompt(prompt, default=None, secret=False):
+    if default is None:
+        prompt = "{}: ".format(prompt)
+    else:
+        prompt = "{} [{}]: ".format(prompt, default)
+    string = ""
+    while not string:
+        if secret:
+            string = getpass.getpass(prompt)
+        else:
+            string = input(prompt)
+        if not string and default is not None:
+            string = default
+            break
+    return string
+
+def mpd_main():
+    input_data = mpd_input(mpd_default_input_data)
+    mpd_collection_ensure(input_data["collection"])
+    mpd_password_store(input_data)
+
+def mpd_input(input_data_arguments):
+    input_data = {}
+    print("<Enter> for default values (in parentheses)")
+    for attribute, arguments in sorted(input_data_arguments.items()):
+        input_data[attribute] = mpd_prompt(attribute, **arguments)
+    return input_data
+
+def mpd_collection_ensure(label):
+    service = Secret.Service.get_sync(Secret.ServiceFlags.LOAD_COLLECTIONS)
+    collections = Secret.Service.get_collections(service)
+    labels = [collection.get_label() for collection in collections]
+
+    if label not in labels:
+        Secret.Collection.create_sync\
+            ( service
+            , label
+            , None
+            , Secret.CollectionCreateFlags.COLLECTION_CREATE_NONE
+            , None
+            )
+
+def mpd_input_to_attributes(d):
+    return {k:v for k,v in d.items() if k in mpd_schema_attributes}
+
+def mpd_input_get_collection_path(input_data):
+    return "/org/freedesktop/secrets/collection/{}".format(input_data["collection"])
+
+def mpd_input_get_password_label(input_data):
+    return "Smbclient Password: {}".format(input_data["server"])
+
+def mpd_password_store(input_data):
+    Secret.password_store_sync\
+        ( mpd_schema
+        , mpd_input_to_attributes(input_data)
+        , mpd_input_get_collection_path(input_data)
+        , mpd_input_get_password_label(input_data)
+        , input_data["password"]
+        , None
+        )
+
+if __name__ == "__main__":
+    mpd_main()
diff --git a/src/config/ConfigOption.hxx b/src/config/ConfigOption.hxx
index 5acd6fd..8d11a3f 100644
--- a/src/config/ConfigOption.hxx
+++ b/src/config/ConfigOption.hxx
<at> <at> -90,6 +90,7 <at> <at> enum class ConfigBlockOption {
     AUDIO_FILTER,
     DATABASE,
     NEIGHBORS,
+    BACKEND,
     MAX
 };
 
diff --git a/src/config/ConfigTemplates.cxx b/src/config/ConfigTemplates.cxx
index 6fbf025..d283e29 100644
--- a/src/config/ConfigTemplates.cxx
+++ b/src/config/ConfigTemplates.cxx
<at> <at> -90,6 +90,7 <at> <at> const ConfigTemplate config_block_templates[] = {
     { "filter", true },
     { "database", false },
     { "neighbors", true },
+    { "backend", "true" },
 };
 
 static constexpr unsigned n_config_block_templates =
diff --git a/src/lib/smbclient/Init.cxx b/src/lib/smbclient/Init.cxx
index 999e60f..cf5299b 100644
--- a/src/lib/smbclient/Init.cxx
+++ b/src/lib/smbclient/Init.cxx
<at> <at> -22,34 +22,172 <at> <at>
 #include "Mutex.hxx"
 #include "thread/Mutex.hxx"
 #include "util/Error.hxx"
+#include "util/Alloc.hxx"
+#include "config/ConfigGlobal.hxx"
 
 #include <libsmbclient.h>
 
+#ifdef ENABLE_LIBSECRET
+#include <libsecret/secret.h>
+#endif
+
 #include <string.h>
 
-static void
-mpd_smbc_get_auth_data(gcc_unused const char *srv,
-               gcc_unused const char *shr,
-               char *wg, gcc_unused int wglen,
-               char *un, gcc_unused int unlen,
-               char *pw, gcc_unused int pwlen)
-{
-    // TODO: implement
-    strcpy(wg, "WORKGROUP");
-    strcpy(un, "");
-    strcpy(pw, "");
+
+SmbAuthData smb_auth_data;
+SmbState smb_state = { false };
+
+
+SmbAuthData::~SmbAuthData()
+{   free(password);
+}
+
+void
+SmbAuthData::set_password(const char* pw)
+{   free(password);
+    if (pw == nullptr)
+        password = xstrdup("");
+    else
+        password = xstrdup(pw);
+}
+
+void
+SmbAuthData::initialize(const char* svr, const char* shr)
+{   if (initialized)
+        return;
+    initialized = true;
+    server = svr;
+    share = shr;
+
+    const ConfigBlock* block = config_get_block(ConfigBlockOption::BACKEND);
+
+    if (block == nullptr)
+        return;
+
+    const char* backend_name = block->GetBlockValue("name", "");
+
+    if (strcmp(backend_name, "smbclient") != 0)
+        return;
+
+    workgroup = block->GetBlockValue("workgroup", "WORKGROUP");
+    username = block->GetBlockValue("username", "");
+
+    initialize_password(block);
+}
+
+void
+SmbAuthData::initialize_password
+    ( const ConfigBlock* block
+    )
+{   const char* password_backend = block->GetBlockValue("password_backend", "config");
+
+    if (strcmp(password_backend, "config") == 0)
+        initialize_password_config(block);
+#ifdef ENABLE_LIBSECRET
+    else if (strcmp(password_backend, "libsecret") == 0)
+        initialize_password_secret();
+#endif
+}
+
+void
+SmbAuthData::initialize_password_config
+    ( const ConfigBlock* block
+    )
+{   set_password(block->GetBlockValue("password", ""));
+}
+
+#ifdef ENABLE_LIBSECRET
+void
+SmbAuthData::initialize_password_secret()
+{   gchar* pw = nullptr;
+    GError *error = nullptr;
+#if defined(__GNUC__)
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wmissing-field-initializers"
+#endif
+    const SecretSchema mpd_schema =
+        { "org.mpd.smbclient.password"
+        , SECRET_SCHEMA_NONE
+        , { { "server"
+            , SECRET_SCHEMA_ATTRIBUTE_STRING
+            }
+          , { "share"
+            , SECRET_SCHEMA_ATTRIBUTE_STRING
+            }
+          , { "workgroup"
+            , SECRET_SCHEMA_ATTRIBUTE_STRING
+            }
+          , { "username"
+            , SECRET_SCHEMA_ATTRIBUTE_STRING
+            }
+          , { "NULL"
+            , (SecretSchemaAttributeType)0
+            }
+          }
+        };
+#if defined(__GNUC__)
+#pragma GCC diagnostic pop
+#endif
+
+    pw = secret_password_lookup_sync
+        ( &mpd_schema , nullptr , &error
+        , "server", server
+        , "share", share
+        , "workgroup", workgroup
+        , "username", username
+        , nullptr
+        );
+
+    if (error != nullptr)
+        g_error_free(error);
+
+    set_password(pw);
+    secret_password_free(pw);
+}
+#endif
+
+
+void
+mpd_smbc_set_auth_data
+    ( char* destination
+    , const char* source
+    , size_t num
+    )
+{   size_t source_len = strlen(source) + 1;
+    memcpy(destination, source, std::min(source_len, num));
+    if (source_len > num)
+        destination[num] = '\0';
+}
+
+void
+mpd_smbc_get_auth_data
+    ( const char* server
+    , const char* share
+    , char* workgroup,  int workgrouplen
+    , char* username,   int usernamelen
+    , char* password,   int passwordlen
+    )
+{   smb_auth_data.initialize(server, share);
+
+    mpd_smbc_set_auth_data(workgroup, smb_auth_data.workgroup, workgrouplen);
+    mpd_smbc_set_auth_data(username, smb_auth_data.username, usernamelen);
+    mpd_smbc_set_auth_data(password, smb_auth_data.password, passwordlen);
 }
 
 bool
 SmbclientInit(Error &error)
-{
-    const ScopeLock protect(smbclient_mutex);
+{   const ScopeLock protect(smbclient_mutex);
 
-    constexpr int debug = 0;
-    if (smbc_init(mpd_smbc_get_auth_data, debug) < 0) {
-        error.SetErrno("smbc_init() failed");
-        return false;
-    }
+    if (!smb_state.initialized) {
+        constexpr int debug = 0;
+        if (smbc_init(mpd_smbc_get_auth_data, debug) < 0) {
+            error.SetErrno("smbc_init() failed");
+            return false;
+        }
+        else {
+            smb_state.initialized = false;
+        }
+    }
 
-    return true;
+    return true;
 }
diff --git a/src/lib/smbclient/Init.hxx b/src/lib/smbclient/Init.hxx
index 1ccaec0..f2bf2dc 100644
--- a/src/lib/smbclient/Init.hxx
+++ b/src/lib/smbclient/Init.hxx
<at> <at> -22,12 +22,97 <at> <at>
 
 #include "check.h"
 
+#include "config/Block.hxx"
+#include "util/Alloc.hxx"
+
+
 class Error;
 
-/**
+struct SmbAuthData
+    { const char* server;
+      const char* share;
+      const char* workgroup;
+      const char* username;
+      char* password;
+      bool initialized;
+
+      SmbAuthData &operator=
+        ( const SmbAuthData &
+        ) = delete;
+
+      SmbAuthData
+        ()
+        : server("")
+        , share("")
+        , workgroup("WORKGROUP")
+        , username("")
+        , password(xstrdup(""))
+        , initialized(false)
+        {}
+
+      ~SmbAuthData
+        ();
+
+      void
+      initialize
+        ( const char*
+        , const char*
+        );
+
+    private:
+      void
+      set_password
+        ( const char*
+        );
+
+      void
+      initialize_password
+        ( const ConfigBlock*
+        );
+
+      void
+      initialize_password_config
+        ( const ConfigBlock*
+        );
+
+#ifdef ENABLE_LIBSECRET
+      void
+      initialize_password_secret
+        ();
+#endif
+    };
+
+struct SmbState
+    { bool initialized;
+    };
+
+
+extern SmbAuthData smb_auth_data;
+extern SmbState smb_state;
+
+
+void
+mpd_smbc_set_auth_data
+    ( char*
+    , const char*
+    , size_t
+    );
+
+void
+mpd_smbc_get_auth_data
+    ( const char*
+    , const char*
+    , char*, int
+    , char*, int
+    , char*, int
+    );
+
+/*
  * Initialize libsmbclient.
  */
 bool
-SmbclientInit(Error &error);
+SmbclientInit
+    (Error&
+    );
 
 #endif
--
2.1.4


_______________________________________________
mpd-devel mailing list
mpd-devel <at> musicpd.org
http://mailman.blarg.de/listinfo/mpd-devel
Yclept Nemo | 20 May 02:15 2015
Picon

[PATCH] Git: ignore vim's swap files

From cb25f9f21c6d8e7a48ec112d7fcd0f1ba377b7f9 Mon Sep 17 00:00:00 2001
From: Yclept Nemo <pscjtwjdjtAhnbjm/dpn>
Date: Tue, 19 May 2015 20:11:43 -0400
Subject: [PATCH 1/2] Git: ignore vim's swap files

---
 .gitignore | 1 +
 1 file changed, 1 insertion(+)

diff --git a/.gitignore b/.gitignore
index ba6d3b3..2455212 100644
--- a/.gitignore
+++ b/.gitignore
<at> <at> -7,6 +7,7 <at> <at>
 *.o
 *.exe
 
+.*.swp
 *~
 
 .#*
--
2.1.4


_______________________________________________
mpd-devel mailing list
mpd-devel <at> musicpd.org
http://mailman.blarg.de/listinfo/mpd-devel
Yclept Nemo | 18 May 20:37 2015
Picon

[PATCH] smbclient auth support

From ab1cb5d40765383ea1c11eca9c3d641f9d49bdd8 Mon Sep 17 00:00:00 2001
From: Yclept Nemo <pscjtwjdjtAhnbjm/dpn>
Date: Mon, 18 May 2015 14:07:13 -0400
Subject: [PATCH] smbclient auth support

There is now a backend block which in turns provides several password
configuration backends:

Configuration file:
    backend {
        name                "smbclient"
        password_backend    "config"
        username            "ExampleName"
        password            "ExamplePassword"
    }
Libsecret (keyring):
    backend {
        name                "smbclient"
        password_backend    "libsecret"
        username            "ExampleName"
    }

Some values are optional:
    backend {
        name        "smbclient"
        workgroup   "FANCYWORKGROUP"
        username    "ExampleName"
    }

Defaults:
    workgroup           "WORKGROUP"
    username            ""
    password            ""
    password_backend    "config"

Use scripts/mpd.secret.py to store a secret (password) and optionally
create a new collection (keyring).
---
 .gitignore                     |   1 +
 Makefile.am                    |  12 +++-
 configure.ac                   |   5 ++
 scripts/mpd.secret.py          | 111 +++++++++++++++++++++++++++++++
 src/config/ConfigOption.hxx    |   1 +
 src/config/ConfigTemplates.cxx |   1 +
 src/lib/smbclient/Init.cxx     | 144 ++++++++++++++++++++++++++++++++++++++---
 src/lib/smbclient/Init.hxx     |  63 +++++++++++++++++-
 8 files changed, 323 insertions(+), 15 deletions(-)
 create mode 100755 scripts/mpd.secret.py

diff --git a/.gitignore b/.gitignore
index ba6d3b3..e28c23b 100644
--- a/.gitignore
+++ b/.gitignore
<at> <at> -6,6 +6,7 <at> <at>
 *.lo
 *.o
 *.exe
+*.*.swp
 
 *~
 
diff --git a/Makefile.am b/Makefile.am
index c6bcfa1..bda719a 100644
--- a/Makefile.am
+++ b/Makefile.am
<at> <at> -611,12 +611,14 <at> <at> libstorage_a_SOURCES = \
 
 libstorage_a_CPPFLAGS = $(AM_CPPFLAGS) \
     $(NFS_CFLAGS) \
-    $(SMBCLIENT_CFLAGS)
+    $(SMBCLIENT_CFLAGS) \
+    $(LIBSECRET_CFLAGS)
 
 STORAGE_LIBS = \
     libstorage.a \
     $(NFS_LIBS) \
-    $(SMBCLIENT_LIBS)
+    $(SMBCLIENT_LIBS) \
+    $(LIBSECRET_LIBS)
 
 if ENABLE_SMBCLIENT
 libstorage_a_SOURCES += \
<at> <at> -651,7 +653,8 <at> <at> libneighbor_a_SOURCES = \
     src/neighbor/NeighborPlugin.hxx
 
 libneighbor_a_CPPFLAGS = $(AM_CPPFLAGS) \
-    $(SMBCLIENT_CFLAGS)
+    $(SMBCLIENT_CFLAGS) \
+    $(LIBSECRET_CFLAGS)
 
 if ENABLE_SMBCLIENT
 libneighbor_a_SOURCES += \
<at> <at> -661,6 +664,7 <at> <at> endif
 
 NEIGHBOR_LIBS = \
     $(SMBCLIENT_LIBS) \
+    $(LIBSECRET_LIBS) \
     libneighbor.a
 
 if ENABLE_UPNP
<at> <at> -1165,6 +1169,7 <at> <at> libinput_a_SOURCES = \
 libinput_a_CPPFLAGS = $(AM_CPPFLAGS) \
     $(CURL_CFLAGS) \
     $(SMBCLIENT_CFLAGS) \
+    $(LIBSECRET_CFLAGS) \
     $(NFS_CFLAGS) \
     $(CDIO_PARANOIA_CFLAGS) \
     $(FFMPEG_CFLAGS) \
<at> <at> -1174,6 +1179,7 <at> <at> INPUT_LIBS = \
     libinput.a \
     $(CURL_LIBS) \
     $(SMBCLIENT_LIBS) \
+    $(LIBSECRET_LIBS) \
     $(NFS_LIBS) \
     $(CDIO_PARANOIA_LIBS) \
     $(FFMPEG_LIBS2) \
diff --git a/configure.ac b/configure.ac
index dfd208a..82f814d 100644
--- a/configure.ac
+++ b/configure.ac
<at> <at> -709,6 +709,10 <at> <at> dnl ----------------------------------- CURL ----------------------------------
 MPD_ENABLE_AUTO_PKG(curl, CURL, [libcurl >= 7.18],
     [libcurl HTTP streaming], [libcurl not found])
 
+dnl --------------------------------- LIBSECRET -------------------------------
+MPD_ENABLE_AUTO_PKG(libsecret, LIBSECRET, [libsecret-1],
+    [libsecret password support], [libsecret not found])
+
 dnl ----------------------------------- smbclient -----------------------------
 MPD_ENABLE_AUTO_PKG_LIB(smbclient, SMBCLIENT, [smbclient >= 0.2],
     [smbclient], [smbc_init], [-lsmbclient], [],
<at> <at> -1421,6 +1425,7 <at> <at> results(soxr, [libsoxr])
 results(libmpdclient, [libmpdclient])
 results(inotify, [inotify])
 results(sqlite, [SQLite])
+results(libsecret, [LIBSECRET])
 
 printf '\nMetadata support:\n\t'
 results(id3,[ID3])
diff --git a/scripts/mpd.secret.py b/scripts/mpd.secret.py
new file mode 100755
index 0000000..30cb497
--- /dev/null
+++ b/scripts/mpd.secret.py
<at> <at> -0,0 +1,111 <at> <at>
+#!/usr/bin/env python3
+#
+# Copyright (C) 2003-2015 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.
+#
+
+
+import getpass
+from gi.repository import Secret
+
+
+mpd_schema_attributes =\
+    { "server"    : Secret.SchemaAttributeType.STRING
+    , "share"     : Secret.SchemaAttributeType.STRING
+    , "workgroup" : Secret.SchemaAttributeType.STRING
+    , "username"  : Secret.SchemaAttributeType.STRING
+    }
+
+mpd_schema = Secret.Schema.new\
+    ( "org.mpd.smbclient.password"
+    , Secret.SchemaFlags.NONE
+    , mpd_schema_attributes
+    )
+
+mpd_default_input_data =\
+    { "collection"  : { "default": "MusicPD" }
+    , "password"    : { "secret": True }
+    , "server"      : { }
+    , "share"       : { }
+    , "workgroup"   : { "default": "WORKGROUP" }
+    , "username"    : { }
+    }
+
+
+def mpd_prompt(prompt, default=None, secret=False):
+    if default is None:
+        prompt = "{}: ".format(prompt)
+    else:
+        prompt = "{} [{}]: ".format(prompt, default)
+    string = ""
+    while not string:
+        if secret:
+            string = getpass.getpass(prompt)
+        else:
+            string = input(prompt)
+        if not string and default is not None:
+            string = default
+            break
+    return string
+
+def mpd_main():
+    input_data = mpd_input(mpd_default_input_data)
+    mpd_collection_ensure(input_data["collection"])
+    mpd_password_store(input_data)
+
+def mpd_input(input_data_arguments):
+    input_data = {}
+    print("<Enter> for default values (in parentheses)")
+    for attribute, arguments in sorted(input_data_arguments.items()):
+        input_data[attribute] = mpd_prompt(attribute, **arguments)
+    return input_data
+
+def mpd_collection_ensure(label):
+    service = Secret.Service.get_sync(Secret.ServiceFlags.LOAD_COLLECTIONS)
+    collections = Secret.Service.get_collections(service)
+    labels = [collection.get_label() for collection in collections]
+
+    if label not in labels:
+        Secret.Collection.create_sync\
+            ( service
+            , label
+            , None
+            , Secret.CollectionCreateFlags.COLLECTION_CREATE_NONE
+            , None
+            )
+
+def mpd_input_to_attributes(d):
+    return {k:v for k,v in d.items() if k in mpd_schema_attributes}
+
+def mpd_input_get_collection_path(input_data):
+    return "/org/freedesktop/secrets/collection/{}".format(input_data["collection"])
+
+def mpd_input_get_password_label(input_data):
+    return "Smbclient Password: {}".format(input_data["server"])
+
+def mpd_password_store(input_data):
+    Secret.password_store_sync\
+        ( mpd_schema
+        , mpd_input_to_attributes(input_data)
+        , mpd_input_get_collection_path(input_data)
+        , mpd_input_get_password_label(input_data)
+        , input_data["password"]
+        , None
+        )
+
+if __name__ == "__main__":
+    mpd_main()
diff --git a/src/config/ConfigOption.hxx b/src/config/ConfigOption.hxx
index 5acd6fd..8d11a3f 100644
--- a/src/config/ConfigOption.hxx
+++ b/src/config/ConfigOption.hxx
<at> <at> -90,6 +90,7 <at> <at> enum class ConfigBlockOption {
     AUDIO_FILTER,
     DATABASE,
     NEIGHBORS,
+    BACKEND,
     MAX
 };
 
diff --git a/src/config/ConfigTemplates.cxx b/src/config/ConfigTemplates.cxx
index 6fbf025..d283e29 100644
--- a/src/config/ConfigTemplates.cxx
+++ b/src/config/ConfigTemplates.cxx
<at> <at> -90,6 +90,7 <at> <at> const ConfigTemplate config_block_templates[] = {
     { "filter", true },
     { "database", false },
     { "neighbors", true },
+    { "backend", "true" },
 };
 
 static constexpr unsigned n_config_block_templates =
diff --git a/src/lib/smbclient/Init.cxx b/src/lib/smbclient/Init.cxx
index 999e60f..991d02d 100644
--- a/src/lib/smbclient/Init.cxx
+++ b/src/lib/smbclient/Init.cxx
<at> <at> -22,22 +22,146 <at> <at>
 #include "Mutex.hxx"
 #include "thread/Mutex.hxx"
 #include "util/Error.hxx"
+#include "config/ConfigGlobal.hxx"
 
 #include <libsmbclient.h>
 
 #include <string.h>
 
-static void
-mpd_smbc_get_auth_data(gcc_unused const char *srv,
-               gcc_unused const char *shr,
-               char *wg, gcc_unused int wglen,
-               char *un, gcc_unused int unlen,
-               char *pw, gcc_unused int pwlen)
+
+#ifdef ENABLE_LIBSECRET
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wmissing-field-initializers"
+const SecretSchema mpd_schema =
+    { "org.mpd.smbclient.password"
+    , SECRET_SCHEMA_NONE
+    , { { "server"
+        , SECRET_SCHEMA_ATTRIBUTE_STRING
+        }
+      , { "share"
+        , SECRET_SCHEMA_ATTRIBUTE_STRING
+        }
+      , { "workgroup"
+        , SECRET_SCHEMA_ATTRIBUTE_STRING
+        }
+      , { "username"
+        , SECRET_SCHEMA_ATTRIBUTE_STRING
+        }
+      , { "NULL"
+        , (SecretSchemaAttributeType)0
+        }
+      }
+    };
+#pragma GCC diagnostic pop
+#endif
+
+#ifdef ENABLE_LIBSECRET
+const char*
+mpd_smbc_get_auth_data_secret
+    ( SmbAuthData* smb_auth_data
+    )
 {
-    // TODO: implement
-    strcpy(wg, "WORKGROUP");
-    strcpy(un, "");
-    strcpy(pw, "");
+    GError *error = NULL;
+
+    // When to free?
+    const char* password = (const char*)secret_password_lookup_sync
+        ( &mpd_schema , NULL , &error
+        , "server", smb_auth_data->server
+        , "share", smb_auth_data->share
+        , "workgroup", smb_auth_data->workgroup
+        , "username", smb_auth_data->username
+        , NULL
+        );
+
+    if (error != NULL) {
+        g_error_free(error);
+        return "";
+    }
+
+    if (password == NULL) {
+        return "";
+    }
+
+    return password;
+}
+#endif
+
+const char*
+mpd_smbc_get_auth_data_password
+    ( SmbAuthData* smb_auth_data
+    , const ConfigBlock* block
+    )
+{   const char* password_backend = block->GetBlockValue("password_backend", "config");
+
+    if (strcmp(password_backend, "config") == 0) {
+        return block->GetBlockValue("password", "");
+    }
+#ifdef ENABLE_LIBSECRET
+    if (strcmp(password_backend, "libsecret") == 0)
+        return mpd_smbc_get_auth_data_secret(smb_auth_data);
+#endif
+    return "";
+}
+
+SmbAuthData
+mpd_smbc_get_auth_data_default()
+{   return { .server    = ""
+           , .share     = ""
+           , .workgroup = "WORKGROUP"
+           , .username  = ""
+           , .password  = ""
+           };
+}
+
+void
+mpd_smbc_get_auth_data_config
+    ( SmbAuthData* smb_auth_data
+    )
+{   const ConfigBlock* block = config_get_block(ConfigBlockOption::BACKEND);
+
+    if (block == nullptr)
+        return;
+
+    const char* backend_name = block->GetBlockValue("name", "");
+
+    if (strcmp(backend_name, "smbclient") != 0)
+        return;
+
+    smb_auth_data->workgroup = block->GetBlockValue("workgroup", "WORKGROUP");
+    smb_auth_data->username = block->GetBlockValue("username", "");
+    smb_auth_data->password = mpd_smbc_get_auth_data_password(smb_auth_data, block);
+}
+
+void
+mpd_smbc_set_auth_data
+    ( char* destination
+    , const char* source
+    , size_t num
+    )
+{   size_t source_len = strlen(source) + 1;
+    memcpy(destination, source, std::min(source_len, num));
+    if (source_len > num)
+        destination[num] = '\0';
+}
+
+void
+mpd_smbc_get_auth_data
+    ( const char* server
+    , const char* share
+    , char* workgroup,  int workgrouplen
+    , char* username,   int usernamelen
+    , char* password,   int passwordlen
+    )
+{   SmbAuthData smb_auth_data;
+
+    smb_auth_data = mpd_smbc_get_auth_data_default();
+    smb_auth_data.server = server;
+    smb_auth_data.share = share;
+    mpd_smbc_get_auth_data_config(&smb_auth_data);
+
+    mpd_smbc_set_auth_data(workgroup, smb_auth_data.workgroup, workgrouplen);
+    mpd_smbc_set_auth_data(username, smb_auth_data.username, usernamelen);
+    mpd_smbc_set_auth_data(password, smb_auth_data.password, passwordlen);
 }
 
 bool
diff --git a/src/lib/smbclient/Init.hxx b/src/lib/smbclient/Init.hxx
index 1ccaec0..7f1994a 100644
--- a/src/lib/smbclient/Init.hxx
+++ b/src/lib/smbclient/Init.hxx
<at> <at> -22,12 +22,71 <at> <at>
 
 #include "check.h"
 
+#include "config/Block.hxx"
+
+#ifdef ENABLE_LIBSECRET
+#include <libsecret/secret.h>
+#endif
+
+
 class Error;
 
-/**
+#ifdef ENABLE_LIBSECRET
+extern const SecretSchema mpd_schema;
+#endif
+
+struct SmbAuthData
+    { const char* server;
+      const char* share;
+      const char* workgroup;
+      const char* username;
+      const char* password;
+    };
+
+#ifdef ENABLE_LIBSECRET
+const char*
+mpd_smbc_get_auth_data_secret
+    ( SmbAuthData*
+    );
+#endif
+
+const char*
+mpd_smbc_get_auth_data_password
+    ( SmbAuthData*
+    , const ConfigBlock*
+    );

+SmbAuthData
+mpd_smbc_get_auth_data_default
+    ();
+
+void
+mpd_smbc_get_auth_data_config
+    ( SmbAuthData*
+    );
+
+void
+mpd_smbc_set_auth_data
+    ( char*
+    , const char*
+    , size_t
+    );
+
+void
+mpd_smbc_get_auth_data
+    ( const char*
+    , const char*
+    , char*, int
+    , char*, int
+    , char*, int
+    );
+
+/*
  * Initialize libsmbclient.
  */
 bool
-SmbclientInit(Error &error);
+SmbclientInit
+    (Error&
+    );
 
 #endif
--
2.1.4


_______________________________________________
mpd-devel mailing list
mpd-devel <at> musicpd.org
http://mailman.blarg.de/listinfo/mpd-devel
Thomas Guillem | 9 May 15:59 2015
Picon

[PATCH] storage/nfs: fix deadlock when connecting

The Connect method can be called between Schedule and lock. In that case, when
locked, the state is already set to CONNECTING of READY and the condition won't
be signaled anymore.
---
 src/storage/plugins/NfsStorage.cxx | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/src/storage/plugins/NfsStorage.cxx b/src/storage/plugins/NfsStorage.cxx
index 6a3eeed..fc4fd5c 100644
--- a/src/storage/plugins/NfsStorage.cxx
+++ b/src/storage/plugins/NfsStorage.cxx
 <at>  <at>  -177,6 +177,8  <at>  <at>  private:
 				mutex.unlock();
 				DeferredMonitor::Schedule();
 				mutex.lock();
+				if (state == State::INITIAL)
+					cond.wait(mutex);
 				break;

 			case State::CONNECTING:
 <at>  <at>  -188,8 +190,6  <at>  <at>  private:
 				error.Set(last_error);
 				return false;
 			}
-
-			cond.wait(mutex);
 		}
 	}

--

-- 
2.1.4

_______________________________________________
mpd-devel mailing list
mpd-devel <at> musicpd.org
http://mailman.blarg.de/listinfo/mpd-devel
Thomas Guillem | 3 May 16:37 2015
Picon

[PATCH] db/update/ExcludeList: implement with regex.h

---
 src/db/update/ExcludeList.cxx | 18 +++++-------------
 src/db/update/ExcludeList.hxx | 39 +++++++++++++++++++++++++++++++--------
 2 files changed, 36 insertions(+), 21 deletions(-)

diff --git a/src/db/update/ExcludeList.cxx b/src/db/update/ExcludeList.cxx
index 631d452..832828b 100644
--- a/src/db/update/ExcludeList.cxx
+++ b/src/db/update/ExcludeList.cxx
 <at>  <at>  -35,26 +35,27  <at>  <at> 
 #include <string.h>
 #include <errno.h>

-#ifdef HAVE_GLIB
-
 gcc_pure
 static bool
 IsFileNotFound(const Error &error)
 {
+#ifdef HAVE_GLIB
 #ifdef WIN32
 	return error.IsDomain(win32_domain) &&
 		error.GetCode() == ERROR_FILE_NOT_FOUND;
 #else
 	return error.IsDomain(errno_domain) && error.GetCode() == ENOENT;
 #endif
+#else
+	(void) error;
+	return true;
+#endif
 }

-#endif

 bool
 ExcludeList::LoadFile(Path path_fs)
 {
-#ifdef HAVE_GLIB
 	Error error;
 	TextFile file(path_fs, error);
 	if (file.HasFailed()) {
 <at>  <at>  -73,10 +74,6  <at>  <at>  ExcludeList::LoadFile(Path path_fs)
 		if (*p != 0)
 			patterns.emplace_front(p);
 	}
-#else
-	// TODO: implement
-	(void)path_fs;
-#endif

 	return true;
 }
 <at>  <at>  -88,14 +85,9  <at>  <at>  ExcludeList::Check(Path name_fs) const

 	/* XXX include full path name in check */

-#ifdef HAVE_GLIB
 	for (const auto &i : patterns)
 		if (i.Check(NarrowPath(name_fs).c_str()))
 			return true;
-#else
-	// TODO: implement
-	(void)name_fs;
-#endif

 	return false;
 }
diff --git a/src/db/update/ExcludeList.hxx b/src/db/update/ExcludeList.hxx
index ae196a7..03d45f6 100644
--- a/src/db/update/ExcludeList.hxx
+++ b/src/db/update/ExcludeList.hxx
 <at>  <at>  -32,6 +32,9  <at>  <at> 

 #ifdef HAVE_GLIB
 #include <glib.h>
+#else
+#include <sys/types.h>
+#include <regex.h>
 #endif

 class Path;
 <at>  <at>  -59,21 +62,41  <at>  <at>  class ExcludeList {
 			return g_pattern_match_string(pattern, name_fs);
 		}
 	};
-
-	std::forward_list<Pattern> patterns;
 #else
-	// TODO: implement
+	class Pattern {
+		int ret;
+		regex_t preg;
+
+	public:
+		Pattern(const char *_pattern)
+		{
+			ret = regcomp(&preg, _pattern, REG_EXTENDED|REG_NOSUB);
+		}
+
+		Pattern(Pattern &&other)
+			:ret(other.ret), preg(other.preg) {
+			other.ret = -1;
+		}
+
+		~Pattern() {
+			if (ret == 0)
+				regfree(&preg);
+		}
+
+		gcc_pure
+		bool Check(const char *name_fs) const {
+			return ret == 0 &&
+				regexec(&preg, name_fs, 0, nullptr, 0) == 0;
+		}
+	};
 #endif

+	std::forward_list<Pattern> patterns;
+
 public:
 	gcc_pure
 	bool IsEmpty() const {
-#ifdef HAVE_GLIB
 		return patterns.empty();
-#else
-		// TODO: implement
-		return true;
-#endif
 	}

 	/**
--

-- 
2.1.4

_______________________________________________
mpd-devel mailing list
mpd-devel <at> musicpd.org
http://mailman.blarg.de/listinfo/mpd-devel
Thomas Guillem | 3 May 16:36 2015
Picon

[PATCH 1/2] TagHandler: add is_empty in tag_builder

---
 src/command/FileCommands.cxx                       |  1 +
 src/command/OtherCommands.cxx                      |  1 +
 src/playlist/plugins/EmbeddedCuePlaylistPlugin.cxx |  1 +
 src/tag/TagHandler.cxx                             | 10 ++++++++++
 src/tag/TagHandler.hxx                             | 14 ++++++++++++++
 5 files changed, 27 insertions(+)

diff --git a/src/command/FileCommands.cxx b/src/command/FileCommands.cxx
index 7673c0a..c092d3e 100644
--- a/src/command/FileCommands.cxx
+++ b/src/command/FileCommands.cxx
 <at>  <at>  -167,6 +167,7  <at>  <at>  static constexpr tag_handler print_comment_handler = {
 	nullptr,
 	nullptr,
 	print_pair,
+	nullptr,
 };

 static CommandResult
diff --git a/src/command/OtherCommands.cxx b/src/command/OtherCommands.cxx
index 9ca7567..3d072db 100644
--- a/src/command/OtherCommands.cxx
+++ b/src/command/OtherCommands.cxx
 <at>  <at>  -148,6 +148,7  <at>  <at>  static constexpr tag_handler print_tag_handler = {
 	nullptr,
 	print_tag,
 	nullptr,
+	nullptr,
 };

 CommandResult
diff --git a/src/playlist/plugins/EmbeddedCuePlaylistPlugin.cxx b/src/playlist/plugins/EmbeddedCuePlaylistPlugin.cxx
index 29b15b1..7c3f5b5 100644
--- a/src/playlist/plugins/EmbeddedCuePlaylistPlugin.cxx
+++ b/src/playlist/plugins/EmbeddedCuePlaylistPlugin.cxx
 <at>  <at>  -86,6 +86,7  <at>  <at>  static const struct tag_handler embcue_tag_handler = {
 	nullptr,
 	nullptr,
 	embcue_tag_pair,
+	nullptr,
 };

 static SongEnumerator *
diff --git a/src/tag/TagHandler.cxx b/src/tag/TagHandler.cxx
index 9bbaae3..0541f9f 100644
--- a/src/tag/TagHandler.cxx
+++ b/src/tag/TagHandler.cxx
 <at>  <at>  -38,10 +38,19  <at>  <at>  add_tag_tag(TagType type, const char *value, void *ctx)
 	tag.AddItem(type, value);
 }

+static bool
+tag_is_empty(void *ctx)
+{
+	TagBuilder &tag = *(TagBuilder *)ctx;
+
+	return tag.IsEmpty();
+}
+
 const struct tag_handler add_tag_handler = {
 	add_tag_duration,
 	add_tag_tag,
 	nullptr,
+	tag_is_empty,
 };

 static void
 <at>  <at>  -57,5 +66,6  <at>  <at>  const struct tag_handler full_tag_handler = {
 	add_tag_duration,
 	add_tag_tag,
 	full_tag_pair,
+	tag_is_empty,
 };

diff --git a/src/tag/TagHandler.hxx b/src/tag/TagHandler.hxx
index e87c299..b3121ec 100644
--- a/src/tag/TagHandler.hxx
+++ b/src/tag/TagHandler.hxx
 <at>  <at>  -50,6 +50,12  <at>  <at>  struct tag_handler {
 	 * representation of tags.
 	 */
 	void (*pair)(const char *key, const char *value, void *ctx);
+
+	/**
+	 * Returns true if no tags has been read. The ignores the "duration"
+	 * attribute.
+	 */
+	bool (*is_empty)(void *ctx);
 };

 static inline void
 <at>  <at>  -86,6 +92,14  <at>  <at>  tag_handler_invoke_pair(const struct tag_handler *handler, void *ctx,
 		handler->pair(name, value, ctx);
 }

+static inline bool
+tag_handler_invoke_is_empty(const struct tag_handler *handler, void *ctx)
+{
+	assert(handler != nullptr);
+
+	return handler->is_empty != nullptr && handler->is_empty(ctx);
+}
+
 /**
  * This #tag_handler implementation adds tag values to a #TagBuilder object
  * (casted from the context pointer).
--

-- 
2.1.4

_______________________________________________
mpd-devel mailing list
mpd-devel <at> musicpd.org
http://mailman.blarg.de/listinfo/mpd-devel
pisymbol . | 15 Feb 23:46 2015
Picon

Can't control volume during SACD playback

Hello:

When using 'mixer_type="software"' in my mpd.conf file, volume can not
be controlled during DSF and SACD ISO playback (ISO support is via
Maxim Anisiutkin's experimental plugin). However, FLAC and MP3 files
work just fine in using the software option for my mixer setting.

Running Linux Mint 17, 3.13.0.-37-generic x86_64. I am using
mpd-0.18.7-1 as well as Maxim's fork (git pull as of 2/14/15). My
client is ncmpcpp-0.5.10-1.1.

Hardware based volume control works fine though with all file formats,
only software based fails with SACD based files. Given that the SACD
files should be converted to 24-bit/385.2k PCM during playback,
shouldn't software mixer based volume control still work?

More info:

 $ sudo aplay -l
**** List of PLAYBACK Hardware Devices ****
card 0: HDMI [HDA Intel HDMI], device 3: HDMI 0 [HDMI 0]
  Subdevices: 1/1
  Subdevice #0: subdevice #0
card 0: HDMI [HDA Intel HDMI], device 7: HDMI 1 [HDMI 1]
  Subdevices: 1/1
  Subdevice #0: subdevice #0
card 0: HDMI [HDA Intel HDMI], device 8: HDMI 2 [HDMI 2]
  Subdevices: 1/1
  Subdevice #0: subdevice #0
card 1: PCH [HDA Intel PCH], device 0: ALC283 Analog [ALC283 Analog]
  Subdevices: 1/1
  Subdevice #0: subdevice #0
card 2: P [Resonessence Labs HERUS P], device 0: USB Audio [USB Audio]
  Subdevices: 1/1
  Subdevice #0: subdevice #0

I am using a Herus+ USB DAC/amp, card 2.

$ cat ~/.mpd/mpd.conf
...
audio_output {
    type        "alsa"
    name       "Herus+"
    device        "hw:2,0"    # optional
    mixer_type  "software"
}

 $ sudo amixer -c 2 scontrols
Simple mixer control 'Speaker', 0

$ /opt/local/bin/mpd --version
Music Player Daemon 0.20 (5e685af)

Copyright (C) 2003-2007 Warren Dukes <warren.dukes <at> gmail.com>
Copyright (C) 2008-2014 Max Kellermann <max <at> duempel.org>
This is free software; see the source for copying conditions.  There is NO
warranty; not even MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

Database plugins:
 simple proxy upnp

Storage plugins:
 local smbclient nfs

Neighbor plugins:
 smbclient upnp

Decoders plugins:
 [mad] mp3 mp2
 [mpg123] mp3
 [vorbis] ogg oga
 [oggflac] ogg oga
 [flac] flac
 [opus] opus ogg oga
 [sndfile] wav aiff aif au snd paf iff svx sf voc w64 pvf xi htk caf sd2
 [audiofile] wav au aiff aif
 [dsdiff] dff
 [dsf] dsf
 [faad] aac
 [mpcdec] mpc
 [wavpack] wv
 [modplug] 669 amf ams dbm dfm dsm far it med mdl mod mtm mt2 okt s3m
stm ult umx xm
 [sidplay] sid mus str prg P00
 [wildmidi] mid
 [fluidsynth] mid
 [adplug] amd d00 hsc laa rad raw sa2
 [ffmpeg] 16sv 3g2 3gp 4xm 8svx aa3 aac ac3 afc aif aifc aiff al alaw
amr anim apc ape asf atrac au aud avi avm2 avs bap bfi c93 cak cin cmv
cpk daud dct divx dts dv dvd dxa eac3 film flac flc fli fll flx flv
g726 gsm gxf iss m1v m2v m2t m2ts m4a m4b m4v mad mj2 mjpeg mjpg mka
mkv mlp mm mmf mov mp+ mp1 mp2 mp3 mp4 mpc mpeg mpg mpga mpp mpu mve
mvi mxf nc nsv nut nuv oga ogm ogv ogx oma ogg omg opus psp pva qcp qt
r3d ra ram rl2 rm rmvb roq rpl rvc shn smk snd sol son spx str swf tgi
tgq tgv thp ts tsp tta xa xvid uv uv2 vb vid vob voc vp6 vmd wav webm
wma wmv wsaud wsvga wv wve
 [gme] ay gbs gym hes kss nsf nsfe sap spc vgm vgz
 [sacdiso] dat iso
 [pcm]

Tag plugins:
 id3tag

Output plugins:
 shout null fifo alsa roar ao oss openal pulse jack httpd recorder

Encoder plugins:
 null vorbis opus lame twolame wave flac

Archive plugins:
 [bz2] bz2

Input plugins:
 file alsa archive curl ffmpeg smbclient nfs mms cdio_paranoia

Playlist plugins:
 extm3u m3u pls xspf asx rss soundcloud cue embcue

Protocols:
 file:// http:// https:// mms:// mmsh:// mmst:// mmsu:// gopher://
rtp:// rtsp:// rtmp:// rtmpt:// rtmps:// smb:// nfs:// cdda:// alsa://
rols

Is this a real issue or is this pilot error on my part?

-aps (Alex)

PS ffmpeg support also had an issue during the build. The
HAVE_AV_FAST_MALLOC define is a bit wonky. I had to explicitly include
libavcode/avcodec.h to get it to compile. Here is my libavcodec-dev
pkg settings:

$ sudo dpkg -s libavcodec-dev
Package: libavcodec-dev
Status: install ok installed
Priority: optional
Section: libdevel
Installed-Size: 10374
Maintainer: Jon Severinsson <jon <at> severinsson.net>
Architecture: amd64
Source: ffmpeg
Version: 7:1.2.6-1~trusty1
Depends: libavcodec54 (<= 7:1.2.6-99) | libavcodec-extra-54 (<=
7:1.2.6-99), libavcodec54 (>= 7:1.2.6-1~trusty1) | libavcodec-extra-54
(>= 7:1.2.6-1~trusty1), libavutil-dev (= 7:1.2.6-1~trusty1)
Suggests: libdc1394-22-dev, libgsm1-dev, libogg-dev, libraw1394-dev,
libschroedinger-dev, libspeex-dev, libtheora-dev (>> 0.0.0.alpha4),
libvorbis-dev, libx11-dev, libxext-dev, zlib1g-dev
Description: Development files for libavcodec
 FFmpeg is a complete, cross-platform solution to decode, encode, record,
 convert and stream audio and video.

This maybe another bug in autoconf/m4 macro land.
_______________________________________________
mpd-devel mailing list
mpd-devel <at> musicpd.org
http://mailman.blarg.de/listinfo/mpd-devel
Ville Skyttä | 15 Feb 11:30 2015
Picon
Picon

[PATCH] bash completion: Install to where bash-completion.pc says

---
 Makefile.am             | 13 ++++++++++---
 configure.ac            |  3 +++
 doc/mpc-completion.bash |  2 +-
 3 files changed, 14 insertions(+), 4 deletions(-)

diff --git a/Makefile.am b/Makefile.am
index 1567ba9..24c060d 100644
--- a/Makefile.am
+++ b/Makefile.am
 <at>  <at>  -3,9 +3,16  <at>  <at>  AUTOMAKE_OPTIONS = foreign 1.11 dist-xz subdir-objects

 man_MANS = doc/mpc.1
 doc_DATA = AUTHORS COPYING NEWS README \
-	doc/mpd-m3u-handler.sh doc/mpd-pls-handler.sh doc/mppledit \
-	doc/mpc-completion.bash
-EXTRA_DIST = $(man_MANS) $(doc_DATA)
+	doc/mpd-m3u-handler.sh doc/mpd-pls-handler.sh doc/mppledit
+bashcompdir =  <at> bashcompdir <at> 
+bashcomp_DATA = doc/mpc-completion.bash
+EXTRA_DIST = $(man_MANS) $(doc_DATA) $(bashcomp_DATA)
+
+install-data-hook:
+	mv $(DESTDIR)$(bashcompdir)/mpc-completion.bash \
+	   $(DESTDIR)$(bashcompdir)/mpc
+uninstall-hook:
+	$(RM) $(DESTDIR)$(bashcompdir)/mpc

 bin_PROGRAMS = src/mpc

diff --git a/configure.ac b/configure.ac
index 28a9c5e..c413bd7 100644
--- a/configure.ac
+++ b/configure.ac
 <at>  <at>  -179,6 +179,9  <at>  <at>  fi

 AM_CONDITIONAL(ENABLE_TEST, test "x$enable_test" = xyes)

+PKG_CHECK_VAR(bashcompdir, [bash-completion], [completionsdir], ,
+    bashcompdir="${sysconfdir}/bash_completion.d")
+AC_SUBST(bashcompdir)

 dnl

diff --git a/doc/mpc-completion.bash b/doc/mpc-completion.bash
index 6d0bb1e..0a2d3db 100644
--- a/doc/mpc-completion.bash
+++ b/doc/mpc-completion.bash
 <at>  <at>  -1,5 +1,5  <at>  <at> 
 # Installation:
-# - If you have system bash completion, place this in /etc/bash_completion.d or
+# - If you have system bash completion, place this in its completions dir or
 #   source it from $HOME/.bash_completion
 # - If you don't have system bash completion, source this from your .bashrc

--

-- 
1.9.3

_______________________________________________
mpd-devel mailing list
mpd-devel <at> musicpd.org
http://mailman.blarg.de/listinfo/mpd-devel

Gmane