示例#1
0
bool
update_container_file(struct directory *directory,
                      const char *name,
                      const struct stat *st,
                      const struct decoder_plugin *plugin)
{
    if (plugin->container_scan == NULL)
        return false;

    db_lock();
    struct directory *contdir =
        make_directory_if_modified(directory, name, st);
    if (contdir == NULL) {
        /* not modified */
        db_unlock();
        return true;
    }

    contdir->device = DEVICE_CONTAINER;
    db_unlock();

    char *const pathname = map_directory_child_fs(directory, name);

    char *vtrack;
    unsigned int tnum = 0;
    while ((vtrack = plugin->container_scan(pathname, ++tnum)) != NULL) {
        struct song *song = song_file_new(vtrack, contdir);

        // shouldn't be necessary but it's there..
        song->mtime = st->st_mtime;

        char *child_path_fs = map_directory_child_fs(contdir, vtrack);

        song->tag = tag_new();
        decoder_plugin_scan_file(plugin, child_path_fs,
                                 &add_tag_handler, song->tag);
        g_free(child_path_fs);

        db_lock();
        directory_add_song(contdir, song);
        db_unlock();

        modified = true;

        g_message("added %s/%s",
                  directory_get_path(directory), vtrack);
        g_free(vtrack);
    }

    g_free(pathname);

    if (tnum == 1) {
        db_lock();
        delete_directory(contdir);
        db_unlock();
        return false;
    } else
        return true;
}
示例#2
0
char *
map_song_fs(const struct song *song)
{
	assert(song_is_file(song));

	if (song_in_database(song))
		return map_directory_child_fs(song->parent, song->uri);
	else
		return utf8_to_fs_charset(song->uri);
}
/**
 * Updates the file listing from an archive file.
 *
 * @param parent the parent directory the archive file resides in
 * @param name the UTF-8 encoded base name of the archive file
 * @param st stat() information on the archive file
 * @param plugin the archive plugin which fits this archive type
 */
static void
update_archive_file(struct directory *parent, const char *name,
		    const struct stat *st,
		    const struct archive_plugin *plugin)
{
	GError *error = NULL;
	char *path_fs;
	struct archive_file *file;
	struct directory *directory;
	char *filepath;

	directory = dirvec_find(&parent->children, name);
	if (directory != NULL && directory->mtime == st->st_mtime &&
	    !walk_discard)
		/* MPD has already scanned the archive, and it hasn't
		   changed since - don't consider updating it */
		return;

	path_fs = map_directory_child_fs(parent, name);

	/* open archive */
	file = archive_file_open(plugin, path_fs, &error);
	if (file == NULL) {
		g_free(path_fs);
		g_warning("%s", error->message);
		g_error_free(error);
		return;
	}

	g_debug("archive %s opened", path_fs);
	g_free(path_fs);

	if (directory == NULL) {
		g_debug("creating archive directory: %s", name);
		directory = make_subdir(parent, name);
		/* mark this directory as archive (we use device for
		   this) */
		directory->device = DEVICE_INARCHIVE;
	}

	directory->mtime = st->st_mtime;

	archive_file_scan_reset(file);

	while ((filepath = archive_file_scan_next(file)) != NULL) {
		/* split name into directory and file */
		g_debug("adding archive file: %s", filepath);
		update_archive_tree(directory, filepath);
	}

	archive_file_close(file);
}
示例#4
0
static bool
directory_child_is_regular(const struct directory *directory,
			   const char *name_utf8)
{
	char *path_fs = map_directory_child_fs(directory, name_utf8);
	if (path_fs == NULL)
		return false;

	struct stat st;
	bool is_regular = stat(path_fs, &st) == 0 && S_ISREG(st.st_mode);
	g_free(path_fs);

	return is_regular;
}
static int
stat_directory_child(const struct directory *parent, const char *name,
		     struct stat *st)
{
	char *path_fs;
	int ret;

	path_fs = map_directory_child_fs(parent, name);
	if (path_fs == NULL)
		return -1;

	ret = stat(path_fs, st);
	g_free(path_fs);
	return ret;
}
示例#6
0
static int
stat_directory_child(const struct directory *parent, const char *name,
		     struct stat *st)
{
	char *path_fs;
	int ret;

	path_fs = map_directory_child_fs(parent, name);
	if (path_fs == NULL)
		return -1;

	ret = stat(path_fs, st);
	if (ret < 0)
		g_warning("Failed to stat %s: %s", path_fs, g_strerror(errno));

	g_free(path_fs);
	return ret;
}
示例#7
0
/**
 * Checks if the given permissions on the mapped file are given.
 */
static bool
directory_child_access(const struct directory *directory,
		       const char *name, int mode)
{
#ifdef WIN32
	/* access() is useless on WIN32 */
	(void)directory;
	(void)name;
	(void)mode;
	return true;
#else
	char *path = map_directory_child_fs(directory, name);
	if (path == NULL)
		/* something went wrong, but that isn't a permission
		   problem */
		return true;

	bool success = access(path, mode) == 0 || errno != EACCES;
	g_free(path);
	return success;
#endif
}
static bool
skip_symlink(const struct directory *directory, const char *utf8_name)
{
#ifndef WIN32
	char buffer[MPD_PATH_MAX];
	char *path_fs;
	const char *p;
	ssize_t ret;

	path_fs = map_directory_child_fs(directory, utf8_name);
	if (path_fs == NULL)
		return true;

	ret = readlink(path_fs, buffer, sizeof(buffer));
	g_free(path_fs);
	if (ret < 0)
		/* don't skip if this is not a symlink */
		return errno != EINVAL;

	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;
	}

	if (buffer[0] == '/')
		return !follow_outside_symlinks;

	p = buffer;
	while (*p == '.') {
		if (p[1] == '.' && G_IS_DIR_SEPARATOR(p[2])) {
			/* "../" moves to parent directory */
			directory = directory->parent;
			if (directory == NULL) {
				/* we have moved outside the music
				   directory - skip this symlink
				   if such symlinks are not allowed */
				return !follow_outside_symlinks;
			}
			p += 3;
		} else if (G_IS_DIR_SEPARATOR(p[1]))
			/* eliminate "./" */
			p += 2;
		else
			break;
	}

	/* we are still in the music directory, so this symlink points
	   to a song which is already in the database - skip according
	   to the follow_inside_symlinks param*/
	return !follow_inside_symlinks;
#else
	/* no symlink checking on WIN32 */

	(void)directory;
	(void)utf8_name;

	return false;
#endif
}
static bool
update_container_file(	struct directory* directory,
			const char* name,
			const struct stat* st,
			const struct decoder_plugin* plugin)
{
	char* vtrack = NULL;
	unsigned int tnum = 0;
	char* pathname = map_directory_child_fs(directory, name);
	struct directory* contdir = dirvec_find(&directory->children, name);

	// directory exists already
	if (contdir != NULL)
	{
		// modification time not eq. file mod. time
		if (contdir->mtime != st->st_mtime || walk_discard)
		{
			g_message("removing container file: %s", pathname);

			delete_directory(contdir);
			contdir = NULL;

			modified = true;
		}
		else {
			g_free(pathname);
			return true;
		}
	}

	contdir = make_subdir(directory, name);
	contdir->mtime = st->st_mtime;
	contdir->device = DEVICE_CONTAINER;

	while ((vtrack = plugin->container_scan(pathname, ++tnum)) != NULL)
	{
		struct song* song = song_file_new(vtrack, contdir);
		char *child_path_fs;

		// shouldn't be necessary but it's there..
		song->mtime = st->st_mtime;

		child_path_fs = map_directory_child_fs(contdir, vtrack);

		song->tag = plugin->tag_dup(child_path_fs);
		g_free(child_path_fs);

		songvec_add(&contdir->songs, song);

		modified = true;

		g_message("added %s/%s",
			  directory_get_path(directory), vtrack);
		g_free(vtrack);
	}

	g_free(pathname);

	if (tnum == 1)
	{
		delete_directory(contdir);
		return false;
	}
	else
		return true;
}