allow scanning a single file instead of a directory.
authorGustavo Sverzut Barbieri <barbieri@profusion.mobi>
Tue, 27 Aug 2013 18:21:37 +0000 (15:21 -0300)
committerLucas De Marchi <lucas.demarchi@intel.com>
Fri, 30 Aug 2013 14:29:56 +0000 (11:29 -0300)
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
src/lib/lightmediascanner_check.c
src/lib/lightmediascanner_process.c

index a1ea004..cfff90c 100644 (file)
@@ -29,6 +29,7 @@
 #include <limits.h>
 #include <sqlite3.h>
 #include <errno.h>
+#include <sys/stat.h>
 
 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);
index 3026c88..33b3b07 100644 (file)
@@ -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;
index 119caab..3d78ed1 100644 (file)
@@ -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.
  */