--- mpd-0.18.5.orig/src/db/SimpleDatabasePlugin.cxx 2013-11-22 00:33:30.000000000 +0100 +++ mpd-0.18.5/src/db/SimpleDatabasePlugin.cxx 2013-11-30 19:17:55.000000000 +0100 @@ -35,6 +35,9 @@ #include #include +#include +#include +#include static constexpr Domain simple_db_domain("simple_db"); @@ -95,8 +98,8 @@ SimpleDatabase::Check(Error &error) cons return false; } - /* Check if we can write to the directory */ - if (!CheckAccess(dirPath, X_OK | W_OK)) { + /* Check if we can change into the directory */ + if (!CheckAccess(dirPath, X_OK)) { const int e = errno; const std::string dirPath_utf8 = dirPath.ToUTF8(); error.FormatErrno(e, "Can't create db file in \"%s\"", @@ -122,9 +125,9 @@ SimpleDatabase::Check(Error &error) cons return false; } - /* And check that we can write to it */ - if (!CheckAccess(path, R_OK | W_OK)) { - error.FormatErrno("Can't open db file \"%s\" for reading/writing", + /* And check that we can read it */ + if (!CheckAccess(path, R_OK)) { + error.FormatErrno("Can't open db file \"%s\" for reading", path_utf8.c_str()); return false; } @@ -281,6 +284,10 @@ SimpleDatabase::GetStats(const DatabaseS bool SimpleDatabase::Save(Error &error) { + struct mntent *mnt; + int remount; + FILE *f; + db_lock(); LogDebug(simple_db_domain, "removing empty directories from DB"); @@ -293,6 +300,26 @@ SimpleDatabase::Save(Error &error) LogDebug(simple_db_domain, "writing DB"); + remount = 0; + /* check if /data is mounted read-only */ + if ((f = setmntent("/proc/mounts", "r")) == NULL) + error.Format(simple_db_domain, "Checking /proc/mounts failed"); + + while ((mnt = getmntent(f)) != NULL) { + if (strcmp(mnt->mnt_dir, "/data") == 0 && + hasmntopt(mnt, MNTOPT_RO) != NULL) { + remount = 1; + } + } + endmntent(f); + + if (remount) { + if (mount("","/data",0,MS_REMOUNT,0)<0) { + error.Format(simple_db_domain, "Remounting /data rw failed"); + } + LogDebug(simple_db_domain, "Mounted /data successfully in read-write mode"); + } + FILE *fp = FOpen(path, FOpenMode::WriteText); if (!fp) { error.FormatErrno("unable to write to db file \"%s\"", @@ -310,6 +337,16 @@ SimpleDatabase::Save(Error &error) fclose(fp); + if (remount) { + sync(); + if (mount("","/data",0,MS_REMOUNT|MS_RDONLY,0)<0) { + error.Format(simple_db_domain, "Remounting /data ro failed"); + } + LogDebug(simple_db_domain, "Mounted /data successfully in read-only mode"); + } + + LogDebug(simple_db_domain, "Successfully written database"); + struct stat st; if (StatFile(path, st)) mtime = st.st_mtime;