update: added options which control symlink behaviour

The configuration options "follow_outside_symlinks" and
"follow_inside_symlinks" let the user control whether MPD should
follow symbolic links in the music directory.

[mk: converted variables to "bool"; moved configuration to
update_global_init()]
This commit is contained in:
Raphaël Rigo 2008-11-28 10:57:39 +01:00 committed by Max Kellermann
parent 011855d22b
commit 5b089f85fd
5 changed files with 50 additions and 7 deletions

View File

@ -35,6 +35,17 @@ This specifies the directory where music is located.
.B playlist_directory <directory> .B playlist_directory <directory>
This specifies the directory where saved playlists are stored. This specifies the directory where saved playlists are stored.
.TP .TP
.B follow_outside_symlinks <yes or no>
Control if MPD will follow symbolic links pointing outside the music dir.
You must recreate the database after changing this option.
The default is "no".
.TP
.B follow_inside_symlinks <yes or no>
Control if MPD will follow symbolic links pointing outside the music dir, potentially
adding duplicates to the database.
You must recreate the database after changing this option.
The default is "yes".
.TP
.B db_file <file> .B db_file <file>
This specifies where the db file will be stored. This specifies where the db file will be stored.
.TP .TP

View File

@ -7,6 +7,8 @@ playlist_directory "~/.mpd/playlists"
db_file "~/.mpd/mpd.db" db_file "~/.mpd/mpd.db"
log_file "~/.mpd/mpd.log" log_file "~/.mpd/mpd.log"
error_file "~/.mpd/mpd.error" error_file "~/.mpd/mpd.error"
#follow_outside_symlinks "no"
#follow_inside_symlinks "yes"
################################################################ ################################################################

View File

@ -145,6 +145,8 @@ void initConf(void)
/* registerConfigParam(name, repeatable, block); */ /* registerConfigParam(name, repeatable, block); */
registerConfigParam(CONF_MUSIC_DIR, 0, 0); registerConfigParam(CONF_MUSIC_DIR, 0, 0);
registerConfigParam(CONF_PLAYLIST_DIR, 0, 0); registerConfigParam(CONF_PLAYLIST_DIR, 0, 0);
registerConfigParam(CONF_FOLLOW_INSIDE_SYMLINKS, 0, 0);
registerConfigParam(CONF_FOLLOW_OUTSIDE_SYMLINKS, 0, 0);
registerConfigParam(CONF_DB_FILE, 0, 0); registerConfigParam(CONF_DB_FILE, 0, 0);
registerConfigParam(CONF_LOG_FILE, 0, 0); registerConfigParam(CONF_LOG_FILE, 0, 0);
registerConfigParam(CONF_ERROR_FILE, 0, 0); registerConfigParam(CONF_ERROR_FILE, 0, 0);

View File

@ -23,6 +23,8 @@
#define CONF_MUSIC_DIR "music_directory" #define CONF_MUSIC_DIR "music_directory"
#define CONF_PLAYLIST_DIR "playlist_directory" #define CONF_PLAYLIST_DIR "playlist_directory"
#define CONF_FOLLOW_INSIDE_SYMLINKS "follow_inside_symlinks"
#define CONF_FOLLOW_OUTSIDE_SYMLINKS "follow_outside_symlinks"
#define CONF_DB_FILE "db_file" #define CONF_DB_FILE "db_file"
#define CONF_LOG_FILE "log_file" #define CONF_LOG_FILE "log_file"
#define CONF_ERROR_FILE "error_file" #define CONF_ERROR_FILE "error_file"

View File

@ -31,6 +31,7 @@
#include "condition.h" #include "condition.h"
#include "update.h" #include "update.h"
#include "idle.h" #include "idle.h"
#include "conf.h"
#include <glib.h> #include <glib.h>
@ -56,6 +57,14 @@ static struct song *delete;
static struct condition delete_cond; static struct condition delete_cond;
enum {
DEFAULT_FOLLOW_INSIDE_SYMLINKS = true,
DEFAULT_FOLLOW_OUTSIDE_SYMLINKS = false,
};
static bool follow_inside_symlinks;
static bool follow_outside_symlinks;
unsigned unsigned
isUpdatingDB(void) isUpdatingDB(void)
{ {
@ -337,19 +346,28 @@ skip_symlink(const struct directory *directory, const char *utf8_name)
/* don't skip if this is not a symlink */ /* don't skip if this is not a symlink */
return errno != EINVAL; return errno != EINVAL;
if (buffer[0] == '/') if (!follow_inside_symlinks && !follow_outside_symlinks) {
/* ignore all symlinks */
return true;
} else if (follow_inside_symlinks && follow_outside_symlinks) {
/* consider all symlinks */
return false; return false;
}
if (buffer[0] == '/')
return !follow_outside_symlinks;
p = buffer; p = buffer;
while (*p == '.') { while (*p == '.') {
if (p[1] == '.' && p[2] == '/') { if (p[1] == '.' && p[2] == '/') {
/* "../" moves to parent directory */ /* "../" moves to parent directory */
directory = directory->parent; directory = directory->parent;
if (directory == NULL) if (directory == NULL) {
/* we have moved outside the music /* we have moved outside the music
directory - don't skip this directory - skip this symlink
symlink */ if such symlinks are not allowed */
return false; return !follow_outside_symlinks;
}
p += 3; p += 3;
} else if (p[1] == '/') } else if (p[1] == '/')
/* eliminate "./" */ /* eliminate "./" */
@ -359,8 +377,9 @@ skip_symlink(const struct directory *directory, const char *utf8_name)
} }
/* we are still in the music directory, so this symlink points /* we are still in the music directory, so this symlink points
to a song which is already in the database - skip it */ to a song which is already in the database - skip according
return true; to the follow_inside_symlinks param*/
return !follow_inside_symlinks;
} }
static bool static bool
@ -583,6 +602,13 @@ void reap_update_task(void)
void update_global_init(void) void update_global_init(void)
{ {
follow_inside_symlinks =
config_get_bool(CONF_FOLLOW_INSIDE_SYMLINKS,
DEFAULT_FOLLOW_INSIDE_SYMLINKS);
follow_outside_symlinks =
config_get_bool(CONF_FOLLOW_OUTSIDE_SYMLINKS,
DEFAULT_FOLLOW_OUTSIDE_SYMLINKS);
} }
void update_global_finish(void) void update_global_finish(void)