From d0c324019ea5392e1af66775554d25e4bead884c Mon Sep 17 00:00:00 2001 From: Gustavo Sverzut Barbieri Date: Tue, 27 Aug 2013 15:21:37 -0300 Subject: [PATCH] allow scanning a single file instead of a directory. The previous code assumed we always scan a directory, this is cumbersome if we know just one file changed and want to scan only that instance and not the whole dir recursively. It is now allowed to check a non-existent directory or file, this will mark any existing entry as deleted in the database. --- src/bin/test.c | 16 ++++++++-- src/lib/lightmediascanner_check.c | 63 ++++++++++++++++++++++++++----------- src/lib/lightmediascanner_process.c | 26 +++++++++------ 3 files changed, 73 insertions(+), 32 deletions(-) diff --git a/src/bin/test.c b/src/bin/test.c index a1ea004..cfff90c 100644 --- a/src/bin/test.c +++ b/src/bin/test.c @@ -29,6 +29,7 @@ #include #include #include +#include static int color = 0; static const char short_options[] = "s:S:p:P::c:i:t:m:v::h"; @@ -304,6 +305,7 @@ progress(lms_t *lms, const char *path, int path_len, lms_progress_status_t statu static int work(lms_t *lms, int method, int verbose, const char *path) { + struct stat st; int r; if (verbose) { @@ -325,6 +327,10 @@ work(lms_t *lms, int method, int verbose, const char *path) return r; } + if (stat(path, &st) != 0) { + printf("PROCESS skipped for '%s': doesn't exist.\n", path); + return 0; + } if (verbose) { lms_set_progress_callback(lms, progress, "PROGRESS", NULL); @@ -362,9 +368,13 @@ show(lms_t *lms, const char *orig_path) int r, len; if (!realpath(orig_path, path)) { - fprintf(stderr, "ERROR: could not realpath(\"%s\"): %s\n", - orig_path, strerror(errno)); - return -1; + len = strlen(orig_path); + if (len + 1 < PATH_MAX) + memcpy(path, orig_path, len + 1); + else { + fprintf(stderr, "ERROR: path is too long: %s\n", orig_path); + return -1; + } } len = strlen(path); diff --git a/src/lib/lightmediascanner_check.c b/src/lib/lightmediascanner_check.c index 3026c88..33b3b07 100644 --- a/src/lib/lightmediascanner_check.c +++ b/src/lib/lightmediascanner_check.c @@ -785,9 +785,18 @@ _db_files_loop(void *db_ptr, struct cinfo *info, check_row_callback_t check_row) } static int +_is_file(const char *path) +{ + struct stat st; + if (stat(path, &st) != 0) + return 0; + return S_ISREG(st.st_mode); +} + +static int _check(struct pinfo *pinfo, int len, char *path) { - char query[PATH_SIZE + 2]; + char query[PATH_SIZE + 3]; struct master_db *db; int ret; @@ -795,10 +804,14 @@ _check(struct pinfo *pinfo, int len, char *path) if (!db) return -1; - memcpy(query, path, len); - query[len] = '%'; - query[len + 1] = '\0'; - ret = lms_db_get_files(db->get_files, query, len + 1); + if (_is_file(path)) + memcpy(query, path, len + 1); + else { + memcpy(query, path, len); + memcpy(query + len, "/%", sizeof("/%")); + len += sizeof("/%") - 1; + } + ret = lms_db_get_files(db->get_files, query, len); if (ret != 0) goto end; @@ -843,10 +856,14 @@ _check_single_process(struct sinfo *sinfo, int len, char *path) if (!db) return -1; - memcpy(query, path, len); - query[len] = '%'; - query[len + 1] = '\0'; - ret = lms_db_get_files(db->get_files, query, len + 1); + if (_is_file(path)) + memcpy(query, path, len + 1); + else { + memcpy(query, path, len); + memcpy(query + len, "/%", sizeof("/%")); + len += sizeof("/%") - 1; + } + ret = lms_db_get_files(db->get_files, query, len); if (ret != 0) goto end; @@ -928,14 +945,14 @@ _lms_check_check_valid(lms_t *lms, const char *path) } /** - * Check consistency of given directory. + * Check consistency of given directory or file. * * This will update media in the given directory or its children. If files * are missing, they'll be marked as deleted (dtime is set), if they were * marked as deleted and are now present, they are unmarked (dtime is unset). * * @param lms previously allocated Light Media Scanner instance. - * @param top_path top directory to scan. + * @param top_path top directory or file to scan. * * @return On success 0 is returned. */ @@ -958,9 +975,13 @@ lms_check(lms_t *lms, const char *top_path) } if (realpath(top_path, path) == NULL) { - perror("realpath"); - r = -6; - goto close_pipes; + int len = strlen(top_path); + if (len + 1 < PATH_SIZE) + memcpy(path, top_path, len + 1); + else { + fprintf(stderr, "ERROR: path is too long: %s\n", top_path); + return -5; + } } lms->is_processing = 1; @@ -969,14 +990,13 @@ lms_check(lms_t *lms, const char *top_path) lms->is_processing = 0; lms->stop_processing = 0; - close_pipes: lms_close_pipes(&pinfo); end: return r; } /** - * Check consistency of given directory *without fork()-ing* into child process. + * Check consistency of given directory or file *without fork()-ing* into child process. * * This will update media in the given directory or its children. If files * are missing, they'll be marked as deleted (dtime is set), if they were @@ -984,7 +1004,7 @@ lms_check(lms_t *lms, const char *top_path) * Note that if a parser hangs in the check process, this call will also hang. * * @param lms previously allocated Light Media Scanner instance. - * @param top_path top directory to scan. + * @param top_path top directory or file to scan. * * @return On success 0 is returned. */ @@ -1004,8 +1024,13 @@ lms_check_single_process(lms_t *lms, const char *top_path) sinfo.total_committed = 0; if (realpath(top_path, path) == NULL) { - perror("realpath"); - return -6; + int len = strlen(top_path); + if (len + 1 < PATH_SIZE) + memcpy(path, top_path, len + 1); + else { + fprintf(stderr, "ERROR: path is too long: %s\n", top_path); + return -5; + } } lms->is_processing = 1; diff --git a/src/lib/lightmediascanner_process.c b/src/lib/lightmediascanner_process.c index 119caab..3d78ed1 100644 --- a/src/lib/lightmediascanner_process.c +++ b/src/lib/lightmediascanner_process.c @@ -906,11 +906,17 @@ _process_unknown(struct cinfo *info, int base, char *path, const char *name, pro return -2; } - if (S_ISREG(st.st_mode)) - return process_file(info, base, path, name); - else if (S_ISDIR(st.st_mode)) - return _process_dir(info, base, path, name, process_file); - else { + if (S_ISREG(st.st_mode)) { + int r = process_file(info, base, path, name); + if (r >= 0) /* if success and ignore non-fatal errors */ + return 0; + return r; + } else if (S_ISDIR(st.st_mode)) { + int r = _process_dir(info, base, path, name, process_file); + if (r >= 0) /* ignore non-fatal errors */ + return 0; + return r; + } else { fprintf(stderr, "INFO: %s is neither a directory nor a regular file.\n", path); return -3; @@ -1030,7 +1036,7 @@ _process_trigger(struct cinfo *info, const char *top_path, process_file_callback lms->is_processing = 1; lms->stop_processing = 0; - r = _process_dir(info, len, path, bname, process_file); + r = _process_unknown(info, len, path, bname, process_file); lms->is_processing = 0; lms->stop_processing = 0; free(bname); @@ -1039,12 +1045,12 @@ _process_trigger(struct cinfo *info, const char *top_path, process_file_callback } /** - * Process the given directory. + * Process the given directory or file. * * This will add or update media found in the given directory or its children. * * @param lms previously allocated Light Media Scanner instance. - * @param top_path top directory to scan. + * @param top_path top directory or file to scan. * * @return On success 0 is returned. */ @@ -1080,13 +1086,13 @@ lms_process(lms_t *lms, const char *top_path) } /** - * Process the given directory *without fork()-ing* into child process. + * Process the given directory or file *without fork()-ing* into child process. * * This will add or update media found in the given directory or its children. * Note that if a parser hangs during the process, this call will also hang. * * @param lms previously allocated Light Media Scanner instance. - * @param top_path top directory to scan. + * @param top_path top directory or file to scan. * * @return On success 0 is returned. */ -- 2.7.4