$OpenBSD: patch-scanner_c,v 1.5 2015/10/13 10:34:00 sthen Exp $

Support -r for incremental rescan
http://sourceforge.net/p/minidlna/patches/145/

--- scanner.c.orig	Thu Sep 10 20:24:09 2015
+++ scanner.c	Tue Oct 13 11:23:03 2015
@@ -46,6 +46,7 @@
 #include "albumart.h"
 #include "containers.h"
 #include "log.h"
+#include "inotify.h"
 
 #if SCANDIR_CONST
 typedef const struct dirent scan_filter;
@@ -836,7 +837,69 @@ _notify_stop(void)
 #endif
 }
 
+/* rescan functions added by shrimpkin@sourceforge.net */
+static int
+cb_orphans(void *args, int argc, char **argv, char **azColName)
+{
+	struct stat file;
+	char *path = argv[0], *mime = argv[1];
+	
+	/* If we can't stat path, remove it */
+	if (stat(path, &file) != 0)
+	{
+		DPRINTF(E_DEBUG, L_SCANNER, "Removing %s [%s]!\n", path, (mime) ? "file" : "dir");
+		if (mime)
+		{
+			inotify_remove_file(path);
+		}
+		else
+		{
+			inotify_remove_directory(0, path);
+		}
+	}
+	return 0;
+}
+
 void
+start_rescan()
+{
+	struct media_dir_s *media_path;
+	char path[MAXPATHLEN], buf[MAXPATHLEN], *esc_name = NULL, *zErrMsg;
+	char *sql_files = "SELECT path, mime FROM details WHERE path NOT NULL AND mime IS NOT NULL;", *sql_dir = "SELECT path, mime FROM details WHERE path NOT NULL AND mime IS NULL;";
+	int ret;
+
+	DPRINTF(E_INFO, L_SCANNER, "Starting rescan\n");
+
+	/* Find and remove any dead directory links */
+	ret = sqlite3_exec(db, sql_dir, cb_orphans, NULL, &zErrMsg);
+	if (ret != SQLITE_OK)
+	{
+		DPRINTF(E_MAXDEBUG, L_SCANNER, "SQL error: %s\nBAD SQL: %s\n", zErrMsg, sql_dir);
+		sqlite3_free(zErrMsg);
+	}
+	
+	/* Find and remove any dead file links */
+	ret = sqlite3_exec(db, sql_files, cb_orphans, NULL, &zErrMsg);
+	if (ret != SQLITE_OK)
+	{
+		DPRINTF(E_MAXDEBUG, L_SCANNER, "SQL error: %s\nBAD SQL: %s\n", zErrMsg, sql_files);
+		sqlite3_free(zErrMsg);
+	}
+	
+	/* Rescan media_paths for new and/or modified files */
+	for (media_path = media_dirs; media_path != NULL; media_path = media_path->next)
+	{
+		strncpyt(path, media_path->path, sizeof(path));
+		strncpyt(buf, media_path->path, sizeof(buf));
+		esc_name = escape_tag(basename(buf), 1);
+		inotify_insert_directory(0, esc_name, path);
+		free(esc_name);
+	}
+	DPRINTF(E_INFO, L_SCANNER, "Rescan completed\n");
+}
+/* end rescan functions */
+
+void
 start_scanner()
 {
 	struct media_dir_s *media_path;
@@ -844,12 +907,17 @@ start_scanner()
 
 	if (setpriority(PRIO_PROCESS, 0, 15) == -1)
 		DPRINTF(E_WARN, L_INOTIFY,  "Failed to reduce scanner thread priority\n");
-	_notify_start();
 
 	setlocale(LC_COLLATE, "");
 
 	av_register_all();
 	av_log_set_level(AV_LOG_PANIC);
+	if( rescan_db )
+	{
+		start_rescan();
+		return;
+	}
+	_notify_start();
 	for( media_path = media_dirs; media_path != NULL; media_path = media_path->next )
 	{
 		int64_t id;
