From 729523ec80f35a683c982054628cd47d2161d3d4 Mon Sep 17 00:00:00 2001 From: Max Kellermann Date: Wed, 8 Oct 2008 11:07:35 +0200 Subject: directory: moved code to database.c Taming the directory.c monster, part II: move the database management stuff to database. directory.c should only contain code which works on directory objects. --- src/directory.c | 324 +++----------------------------------------------------- 1 file changed, 12 insertions(+), 312 deletions(-) (limited to 'src/directory.c') diff --git a/src/directory.c b/src/directory.c index 25a6bcec8..b38d3b52c 100644 --- a/src/directory.c +++ b/src/directory.c @@ -17,43 +17,14 @@ */ #include "directory.h" +#include "database.h" -#include "conf.h" #include "log.h" -#include "ls.h" #include "path.h" -#include "stats.h" #include "utils.h" #include "ack.h" #include "myfprintf.h" -#include "dbUtils.h" #include "dirvec.h" -#include "update.h" - -#define DIRECTORY_DIR "directory: " -#define DIRECTORY_MTIME "mtime: " /* DEPRECATED, noop-read-only */ -#define DIRECTORY_BEGIN "begin: " -#define DIRECTORY_END "end: " -#define DIRECTORY_INFO_BEGIN "info_begin" -#define DIRECTORY_INFO_END "info_end" -#define DIRECTORY_MPD_VERSION "mpd_version: " -#define DIRECTORY_FS_CHARSET "fs_charset: " - -static struct directory *music_root; - -static time_t directory_dbModTime; - -static void deleteEmptyDirectoriesInDirectory(struct directory * directory); - -static char *getDbFile(void) -{ - ConfigParam *param = parseConfigFilePath(CONF_DB_FILE, 1); - - assert(param); - assert(param->value); - - return param->value; -} struct directory * newDirectory(const char *dirname, struct directory * parent) { @@ -79,7 +50,7 @@ void freeDirectory(struct directory * directory) /*getDirectoryPath(NULL); */ } -static void deleteEmptyDirectoriesInDirectory(struct directory * directory) +void deleteEmptyDirectoriesInDirectory(struct directory * directory) { int i; struct dirvec *dv = &directory->children; @@ -93,19 +64,7 @@ static void deleteEmptyDirectoriesInDirectory(struct directory * directory) dirvec_destroy(dv); } -void directory_finish(void) -{ - freeDirectory(music_root); -} - -struct directory * directory_get_root(void) -{ - assert(music_root != NULL); - - return music_root; -} - -static struct directory * +struct directory * getSubDirectory(struct directory * directory, const char *name) { struct directory *cur = directory; @@ -138,15 +97,7 @@ getSubDirectory(struct directory * directory, const char *name) return found; } -struct directory * getDirectory(const char *name) -{ - if (name == NULL) - return music_root; - - return getSubDirectory(music_root, name); -} - -static int printDirectoryList(int fd, struct dirvec *dv) +static int printDirectoryList(int fd, const struct dirvec *dv) { size_t i; @@ -159,17 +110,13 @@ static int printDirectoryList(int fd, struct dirvec *dv) return 0; } -int printDirectoryInfo(int fd, const char *name) +int directory_print(int fd, const struct directory *directory) { - struct directory *directory; - - if ((directory = getDirectory(name)) == NULL) + if (printDirectoryList(fd, &directory->children) < 0) + return -1; + if (songvec_for_each(&directory->songs, song_print_info_x, + (void *)(size_t)fd) < 0) return -1; - - printDirectoryList(fd, &directory->children); - songvec_for_each(&directory->songs, - song_print_info_x, (void *)(size_t)fd); - return 0; } @@ -188,7 +135,7 @@ static int directory_song_write(struct mpd_song *song, void *data) } /* TODO error checking */ -static int writeDirectoryInfo(int fd, struct directory * directory) +int writeDirectoryInfo(int fd, struct directory * directory) { struct dirvec *children = &directory->children; size_t i; @@ -225,7 +172,7 @@ static int writeDirectoryInfo(int fd, struct directory * directory) return 0; } -static void readDirectoryInfo(FILE * fp, struct directory * directory) +void readDirectoryInfo(FILE * fp, struct directory * directory) { char buffer[MPD_PATH_MAX * 2]; int bufferSize = MPD_PATH_MAX * 2; @@ -275,193 +222,7 @@ void sortDirectory(struct directory * directory) sortDirectory(dv->base[i]); } -int checkDirectoryDB(void) -{ - struct stat st; - char *dbFile = getDbFile(); - - /* Check if the file exists */ - if (access(dbFile, F_OK)) { - /* If the file doesn't exist, we can't check if we can write - * it, so we are going to try to get the directory path, and - * see if we can write a file in that */ - char dirPath[MPD_PATH_MAX]; - parent_path(dirPath, dbFile); - if (*dirPath == '\0') - strcpy(dirPath, "/"); - - /* Check that the parent part of the path is a directory */ - if (stat(dirPath, &st) < 0) { - ERROR("Couldn't stat parent directory of db file " - "\"%s\": %s\n", dbFile, strerror(errno)); - return -1; - } - - if (!S_ISDIR(st.st_mode)) { - ERROR("Couldn't create db file \"%s\" because the " - "parent path is not a directory\n", dbFile); - return -1; - } - - /* Check if we can write to the directory */ - if (access(dirPath, R_OK | W_OK)) { - ERROR("Can't create db file in \"%s\": %s\n", dirPath, - strerror(errno)); - return -1; - } - - return 0; - } - - /* Path exists, now check if it's a regular file */ - if (stat(dbFile, &st) < 0) { - ERROR("Couldn't stat db file \"%s\": %s\n", dbFile, - strerror(errno)); - return -1; - } - - if (!S_ISREG(st.st_mode)) { - ERROR("db file \"%s\" is not a regular file\n", dbFile); - return -1; - } - - /* And check that we can write to it */ - if (access(dbFile, R_OK | W_OK)) { - ERROR("Can't open db file \"%s\" for reading/writing: %s\n", - dbFile, strerror(errno)); - return -1; - } - - return 0; -} - -int writeDirectoryDB(void) -{ - int fd; - char *dbFile = getDbFile(); - struct stat st; - - DEBUG("removing empty directories from DB\n"); - deleteEmptyDirectoriesInDirectory(music_root); - - DEBUG("sorting DB\n"); - - sortDirectory(music_root); - - DEBUG("writing DB\n"); - - fd = open(dbFile, O_WRONLY|O_TRUNC|O_CREAT, 0666); - if (fd < 0) { - ERROR("unable to write to db file \"%s\": %s\n", - dbFile, strerror(errno)); - return -1; - } - - /* - * TODO: block signals when writing the db so we don't get a corrupted - * db (or unexpected failures). fdprintf() needs better error handling - */ - fdprintf(fd, - DIRECTORY_INFO_BEGIN "\n" - DIRECTORY_MPD_VERSION VERSION "\n" - DIRECTORY_FS_CHARSET "%s\n" - DIRECTORY_INFO_END "\n", getFsCharset()); - - if (writeDirectoryInfo(fd, music_root) < 0) { - ERROR("Failed to write to database file: %s\n", - strerror(errno)); - xclose(fd); - return -1; - } - xclose(fd); - - if (stat(dbFile, &st) == 0) - directory_dbModTime = st.st_mtime; - - return 0; -} - -int readDirectoryDB(void) -{ - FILE *fp = NULL; - char *dbFile = getDbFile(); - struct stat st; - - if (!music_root) - music_root = newDirectory(NULL, NULL); - while (!(fp = fopen(dbFile, "r")) && errno == EINTR) ; - if (fp == NULL) { - ERROR("unable to open db file \"%s\": %s\n", - dbFile, strerror(errno)); - return -1; - } - - /* get initial info */ - { - char buffer[100]; - int bufferSize = 100; - int foundFsCharset = 0; - int foundVersion = 0; - - if (!myFgets(buffer, bufferSize, fp)) - FATAL("Error reading db, fgets\n"); - if (0 == strcmp(DIRECTORY_INFO_BEGIN, buffer)) { - while (myFgets(buffer, bufferSize, fp) && - 0 != strcmp(DIRECTORY_INFO_END, buffer)) { - if (!prefixcmp(buffer, DIRECTORY_MPD_VERSION)) - { - if (foundVersion) - FATAL("already found version in db\n"); - foundVersion = 1; - } else if (!prefixcmp(buffer, - DIRECTORY_FS_CHARSET)) { - char *fsCharset; - char *tempCharset; - - if (foundFsCharset) - FATAL("already found fs charset in db\n"); - - foundFsCharset = 1; - - fsCharset = &(buffer[strlen(DIRECTORY_FS_CHARSET)]); - if ((tempCharset = getConfigParamValue(CONF_FS_CHARSET)) - && strcmp(fsCharset, tempCharset)) { - WARNING("Using \"%s\" for the " - "filesystem charset " - "instead of \"%s\"\n", - fsCharset, tempCharset); - WARNING("maybe you need to " - "recreate the db?\n"); - setFsCharset(fsCharset); - } - } else { - FATAL("directory: unknown line in db info: %s\n", - buffer); - } - } - } else { - ERROR("db info not found in db file\n"); - ERROR("you should recreate the db using --create-db\n"); - while (fclose(fp) && errno == EINTR) ; - return -1; - } - } - - DEBUG("reading DB\n"); - - readDirectoryInfo(fp, music_root); - while (fclose(fp) && errno == EINTR) ; - - stats.numberOfSongs = countSongsIn(NULL); - stats.dbPlayTime = sumSongTimesIn(NULL); - - if (stat(dbFile, &st) == 0) - directory_dbModTime = st.st_mtime; - - return 0; -} - -static int +int traverseAllInSubDirectory(struct directory * directory, int (*forEachSong) (struct mpd_song *, void *), int (*forEachDir) (struct directory *, void *), @@ -486,64 +247,3 @@ traverseAllInSubDirectory(struct directory * directory, return err; } - -int -traverseAllIn(const char *name, - int (*forEachSong) (struct mpd_song *, void *), - int (*forEachDir) (struct directory *, void *), void *data) -{ - struct directory *directory; - - if ((directory = getDirectory(name)) == NULL) { - struct mpd_song *song; - if ((song = getSongFromDB(name)) && forEachSong) { - return forEachSong(song, data); - } - return -1; - } - - return traverseAllInSubDirectory(directory, forEachSong, forEachDir, - data); -} - -void directory_init(void) -{ - music_root = newDirectory(NULL, NULL); - updateDirectory(music_root); - stats.numberOfSongs = countSongsIn(NULL); - stats.dbPlayTime = sumSongTimesIn(NULL); -} - -struct mpd_song *getSongFromDB(const char *file) -{ - struct mpd_song *song = NULL; - struct directory *directory; - char *dir = NULL; - char *duplicated = xstrdup(file); - char *shortname = strrchr(duplicated, '/'); - - DEBUG("get song: %s\n", file); - - if (!shortname) { - shortname = duplicated; - } else { - *shortname = '\0'; - ++shortname; - dir = duplicated; - } - - if (!(directory = getDirectory(dir))) - goto out; - if (!(song = songvec_find(&directory->songs, shortname))) - goto out; - assert(song->parent == directory); - -out: - free(duplicated); - return song; -} - -time_t getDbModTime(void) -{ - return directory_dbModTime; -} -- cgit v1.2.3