On Mon, Jan 19, 2015 at 12:06 AM, LÉVAI Dániel <l...@ecentrum.hu> wrote:
>> It might be better to look at the kqueue patch that FreeBSD are using. > > Now this seems to work for me on i386, at least. It applied almost > clean, but I've taken the liberty and removed the whitespace-only > changes from FreeBSD's diff(s). I'll be honest, it got a bit slower, but > this could very well be because of my rusty hard drives. > > Here is my diff: I do not use MiniDLNA, but your diff below looks good and, if it works, then it's ok with me if Stuart wants to commit it. ciao, David > > Index: Makefile > =================================================================== > RCS file: /cvs/ports/multimedia/minidlna/Makefile,v > retrieving revision 1.10 > diff -p -u -r1.10 Makefile > --- Makefile 3 Sep 2014 21:15:43 -0000 1.10 > +++ Makefile 18 Jan 2015 22:45:10 -0000 > @@ -3,6 +3,7 @@ > COMMENT= lightweight DLNA/UPnP-AV media server > > V= 1.1.4 > +REVISION= 0 > DISTNAME= minidlna-$V > PKGNAME= minidlna-$V > > @@ -34,9 +35,15 @@ LIB_DEPENDS= audio/flac \ > graphics/jpeg \ > graphics/libexif > > +AUTOCONF_VERSION= 2.69 > +AUTOMAKE_VERSION= 1.14 > + > NO_TEST= Yes > E= ${PREFIX}/share/examples/minidlna > > +post-patch: > + @cd ${WRKSRC} && env AUTOCONF_VERSION=${AUTOCONF_VERSION} \ > + AUTOMAKE_VERSION=${AUTOMAKE_VERSION} ./autogen.sh > post-install: > ${INSTALL_DATA_DIR} $E > ${INSTALL_DATA} ${WRKSRC}/minidlna.conf $E > Index: patches/patch-configure_ac > =================================================================== > RCS file: patches/patch-configure_ac > diff -N patches/patch-configure_ac > --- /dev/null 1 Jan 1970 00:00:00 -0000 > +++ patches/patch-configure_ac 18 Jan 2015 22:45:10 -0000 > @@ -0,0 +1,12 @@ > +$OpenBSD$ > +--- configure.ac.orig Tue Aug 26 23:09:22 2014 > ++++ configure.ac Sun Jan 18 22:45:07 2015 > +@@ -481,7 +481,7 @@ AC_CHECK_LIB(vorbisfile, vorbis_comment_query, > + > ################################################################################################################ > + ### Header checks > + > +-AC_CHECK_HEADERS([arpa/inet.h asm/unistd.h endian.h machine/endian.h > fcntl.h libintl.h locale.h netdb.h netinet/in.h stddef.h stdlib.h string.h > sys/file.h sys/inotify.h sys/ioctl.h sys/param.h sys/socket.h sys/time.h > unistd.h]) > ++AC_CHECK_HEADERS([arpa/inet.h asm/unistd.h endian.h machine/endian.h > fcntl.h libintl.h locale.h netdb.h netinet/in.h stddef.h stdlib.h string.h > sys/file.h sys/inotify.h sys/ioctl.h sys/param.h sys/socket.h sys/time.h > unistd.h sys/event.h]) > + > + AC_CHECK_FUNCS(inotify_init, AC_DEFINE(HAVE_INOTIFY,1,[Whether kernel has > inotify support]), [ > + AC_MSG_CHECKING([for __NR_inotify_init syscall]) > Index: patches/patch-inotify_c > =================================================================== > RCS file: patches/patch-inotify_c > diff -N patches/patch-inotify_c > --- /dev/null 1 Jan 1970 00:00:00 -0000 > +++ patches/patch-inotify_c 18 Jan 2015 22:45:10 -0000 > @@ -0,0 +1,569 @@ > +$OpenBSD$ > +--- inotify.c.orig Sun Jan 18 22:45:24 2015 > ++++ inotify.c Sun Jan 18 22:45:27 2015 > +@@ -15,9 +15,9 @@ > + * You should have received a copy of the GNU General Public License > + * along with MiniDLNA. If not, see <http://www.gnu.org/licenses/>. > + */ > + #include "config.h" > + > +-#ifdef HAVE_INOTIFY > ++#if defined(HAVE_INOTIFY) || defined(HAVE_SYS_EVENT_H) > + #include <stdio.h> > + #include <string.h> > + #include <stdlib.h> > +@@ -31,11 +31,16 @@ > + #include <sys/time.h> > + #include <sys/resource.h> > + #include <poll.h> > ++#ifdef HAVE_INOTIFY > + #ifdef HAVE_SYS_INOTIFY_H > + #include <sys/inotify.h> > +-#else > ++#else /*HAVE_SYS_INOTIFY_H*/ > + #include "linux/inotify.h" > + #include "linux/inotify-syscalls.h" > ++#endif /*HAVE_SYS_INOTIFY_H*/ > ++#else > ++#include <sys/event.h> > ++#include <fcntl.h> > + #endif > + #include "libav.h" > + > +@@ -49,11 +54,13 @@ > + #include "playlist.h" > + #include "log.h" > + > ++#ifdef HAVE_INOTIFY > + #define EVENT_SIZE ( sizeof (struct inotify_event) ) > + #define BUF_LEN ( 1024 * ( EVENT_SIZE + 16 ) ) > + #define DESIRED_WATCH_LIMIT 65536 > + > + #define PATH_BUF_SIZE PATH_MAX > ++#endif > + > + struct watch > + { > +@@ -86,13 +93,35 @@ add_watch(int fd, const char * path) > + struct watch *nw; > + int wd; > + > ++#ifdef HAVE_INOTIFY > + wd = inotify_add_watch(fd, path, > IN_CREATE|IN_CLOSE_WRITE|IN_DELETE|IN_MOVE); > + if( wd < 0 ) > + { > + DPRINTF(E_ERROR, L_INOTIFY, "inotify_add_watch(%s) [%s]\n", > path, strerror(errno)); > + return -1; > + } > ++#else /*HAVE_INOTIFY*/ > ++ wd = open(path, O_RDONLY); > ++ if (wd == -1) > ++ { > ++ DPRINTF(E_ERROR, L_INOTIFY, > "inotify_add_watch[kqueue,open](%s) [%s]\n", path, strerror(errno)); > ++ return -1; > ++ } > + > ++ struct kevent ke; > ++ EV_SET(&ke, wd, > ++ EVFILT_VNODE, > ++ EV_ADD | EV_ENABLE | EV_CLEAR, > ++ NOTE_DELETE | NOTE_WRITE | NOTE_EXTEND /*| NOTE_ATTRB*/, > ++ 0, NULL); > ++ > ++ if( kevent(fd, &ke, 1, NULL, 0, NULL) == -1 ) > ++ { > ++ DPRINTF(E_ERROR, L_INOTIFY, "inotify_add_watch[kqueue](%s) > [%s]\n", path, strerror(errno)); > ++ return -1; > ++ } > ++#endif > ++ > + nw = malloc(sizeof(struct watch)); > + if( nw == NULL ) > + { > +@@ -125,7 +154,12 @@ remove_watch(int fd, const char * path) > + for( w = watches; w; w = w->next ) > + { > + if( strcmp(path, w->path) == 0 ) > ++#ifdef HAVE_INOTIFY > + return(inotify_rm_watch(fd, w->wd)); > ++#else > ++ close(w->wd); /* kqueue cleans up events when handle > dies*/ > ++ return(0); > ++#endif > + } > + > + return 1; > +@@ -145,15 +179,14 @@ next_highest(unsigned int num) > + int > + inotify_create_watches(int fd) > + { > +- FILE * max_watches; > +- unsigned int num_watches = 0, watch_limit; > ++ unsigned int num_watches = 0; > + char **result; > + int i, rows = 0; > + struct media_dir_s * media_path; > + > + for( media_path = media_dirs; media_path != NULL; media_path = > media_path->next ) > + { > +- DPRINTF(E_DEBUG, L_INOTIFY, "Add watch to %s\n", > media_path->path); > ++ DPRINTF(E_DEBUG, L_INOTIFY, "Setting up monitoring on %s\n", > media_path->path); > + add_watch(fd, media_path->path); > + num_watches++; > + } > +@@ -165,7 +198,11 @@ inotify_create_watches(int fd) > + num_watches++; > + } > + sqlite3_free_table(result); > + > ++#ifdef HAVE_INOTIFY > ++ FILE * max_watches; > ++ unsigned int watch_limit; > ++ > + max_watches = fopen("/proc/sys/fs/inotify/max_user_watches", "r"); > + if( max_watches ) > + { > +@@ -194,16 +231,17 @@ inotify_create_watches(int fd) > + else > + { > + DPRINTF(E_WARN, L_INOTIFY, "WARNING: Inotify > max_user_watches [%u] is low or close to the number of used watches [%u] " > + "and I do not have > permission to increase this limit. Please do so manually by " > + "writing a higher > value into /proc/sys/fs/inotify/max_user_watches.\n", watch_limit, > num_watches); > + } > + } > + } > + else > + { > + DPRINTF(E_WARN, L_INOTIFY, "WARNING: Could not read inotify > max_user_watches! " > + "Hopefully it is enough to cover %u > current directories plus any new ones added.\n", num_watches); > + } > ++#endif > + > + return rows; > + } > +@@ -218,7 +256,11 @@ inotify_remove_watches(int fd) > + while( w ) > + { > + last_w = w; > ++#ifdef HAVE_INOTIFY > + inotify_rm_watch(fd, w->wd); > ++#else > ++ close(w->wd); /*kqueue cleans up after fhandle dies*/ > ++#endif > + free(w->path); > + rm_watches++; > + w = w->next; > +@@ -261,10 +303,10 @@ int add_dir_watch(int fd, char * path, char * filename > + while( (e = readdir(ds)) ) > + { > + if( strcmp(e->d_name, ".") == 0 || > + strcmp(e->d_name, "..") == 0 ) > + continue; > + if( (e->d_type == DT_DIR) || > + (e->d_type == DT_UNKNOWN && > resolve_unknown_type(dir, NO_MEDIA) == TYPE_DIR) ) > + i += add_dir_watch(fd, dir, e->d_name); > + } > + } > +@@ -293,7 +335,10 @@ inotify_insert_file(char * name, const char * path) > + media_types types = ALL_MEDIA; > + struct media_dir_s * media_path = media_dirs; > + struct stat st; > ++ struct timeval now; > + > ++ DPRINTF(E_DEBUG, L_INOTIFY, "inotify_insert_file: %s @ %s\n", name, > path); > ++ > + /* Is it cover art for another file? */ > + if( is_image(path) ) > + update_if_album_art(path); > +@@ -357,6 +402,16 @@ inotify_insert_file(char * name, const char * path) > + if( stat(path, &st) != 0 ) > + return -1; > + > ++ (void)gettimeofday(&now, NULL); > ++ while (now.tv_sec < st.st_mtime + 3) > ++ { > ++ DPRINTF(E_DEBUG, L_INOTIFY, "Sleeping until %s is stable for > a few seconds ...\n", path); > ++ sleep(1); > ++ (void)gettimeofday(&now, NULL); > ++ if (stat(path, &st) != 0) > ++ return -1; > ++ } > ++ > + ts = sql_get_int_field(db, "SELECT TIMESTAMP from DETAILS where PATH > = '%q'", path); > + if( !ts && is_playlist(path) && (sql_get_int_field(db, "SELECT ID > from PLAYLISTS where PATH = '%q'", path) > 0) ) > + { > +@@ -386,9 +441,9 @@ inotify_insert_file(char * name, const char * path) > + > + do > + { > +- //DEBUG DPRINTF(E_DEBUG, L_INOTIFY, "Checking %s\n", > parent_buf); > ++ /*DEBUG DPRINTF(E_DEBUG, L_INOTIFY, "Checking %s\n", > parent_buf);*/ > + id = sql_get_text_field(db, "SELECT OBJECT_ID from > OBJECTS o left join DETAILS d on (d.ID = o.DETAIL_ID)" > + " where d.PATH = '%q' and > REF_ID is NULL", parent_buf); > + if( id ) > + { > + if( !depth ) > +@@ -446,6 +501,8 @@ inotify_insert_directory(int fd, char *name, const cha > + struct media_dir_s* media_path; > + struct stat st; > + > ++ DPRINTF(E_DEBUG, L_INOTIFY, "inotify_insert_directory: %s @ %s\n", > name, path); > ++ > + if( access(path, R_OK|X_OK) != 0 ) > + { > + DPRINTF(E_WARN, L_INOTIFY, "Could not access %s [%s]\n", > path, strerror(errno)); > +@@ -459,7 +516,7 @@ inotify_insert_directory(int fd, char *name, const cha > + > + parent_buf = strdup(path); > + id = sql_get_text_field(db, "SELECT OBJECT_ID from OBJECTS o left > join DETAILS d on (d.ID = o.DETAIL_ID)" > + " where d.PATH = '%q' and REF_ID is > NULL", dirname(parent_buf)); > + if( !id ) > + id = sqlite3_mprintf("%s", BROWSEDIR_ID); > + insert_directory(name, path, BROWSEDIR_ID, id+2, > get_next_available_id("OBJECTS", id)); > +@@ -554,27 +611,25 @@ inotify_remove_file(const char * path) > + { > + sql_exec(db, "DELETE from PLAYLISTS where ID = %lld", > detailID); > + sql_exec(db, "DELETE from DETAILS where ID =" > + " (SELECT DETAIL_ID from OBJECTS where OBJECT_ID > = '%s$%llX')", > + MUSIC_PLIST_ID, detailID); > + sql_exec(db, "DELETE from OBJECTS where OBJECT_ID = '%s$%llX' > or PARENT_ID = '%s$%llX'", > + MUSIC_PLIST_ID, detailID, MUSIC_PLIST_ID, detailID); > + } > + else > + { > + /* Delete the parent containers if we are about to empty > them. */ > +- snprintf(sql, sizeof(sql), "SELECT PARENT_ID from OBJECTS > where DETAIL_ID = %lld" > +- " and PARENT_ID not like '64$%%'", > +- (long long int)detailID); > ++ snprintf(sql, sizeof(sql), "SELECT PARENT_ID from OBJECTS > where DETAIL_ID = %lld", (long long int)detailID); > + if( (sql_get_table(db, sql, &result, &rows, NULL) == > SQLITE_OK) ) > + { > + int i, children; > + for( i = 1; i <= rows; i++ ) > + { > + /* If it's a playlist item, adjust the item > count of the playlist */ > + if( strncmp(result[i], MUSIC_PLIST_ID, > strlen(MUSIC_PLIST_ID)) == 0 ) > + { > + sql_exec(db, "UPDATE PLAYLISTS set > FOUND = (FOUND-1) where ID = %d", > + atoi(strrchr(result[i], '$') > + 1)); > + } > + > + children = sql_get_int_field(db, "SELECT > count(*) from OBJECTS where PARENT_ID = '%s'", result[i]); > +@@ -582,6 +637,8 @@ inotify_remove_file(const char * path) > + continue; > + if( children < 2 ) > + { > ++ sql_exec(db, "DELETE from DETAILS > where ID =" > ++ > " (SELECT DETAIL_ID from OBJECTS where OBJECT_ID = '%s')", > result[i]); > + sql_exec(db, "DELETE from OBJECTS > where OBJECT_ID = '%s'", result[i]); > + > + ptr = strrchr(result[i], '$'); > +@@ -589,6 +646,8 @@ inotify_remove_file(const char * path) > + *ptr = '\0'; > + if( sql_get_int_field(db, "SELECT > count(*) from OBJECTS where PARENT_ID = '%s'", result[i]) == 0 ) > + { > ++ sql_exec(db, "DELETE from > DETAILS where ID =" > ++ > " (SELECT DETAIL_ID from OBJECTS where OBJECT_ID = '%s')", > result[i]); > + sql_exec(db, "DELETE from > OBJECTS where OBJECT_ID = '%s'", result[i]); > + } > + } > +@@ -613,11 +672,13 @@ inotify_remove_directory(int fd, const char * path) > + int64_t detailID = 0; > + int rows, i, ret = 1; > + > ++ DPRINTF(E_DEBUG, L_INOTIFY, "inotify_remove_directory: %s\n", path); > ++ > + /* Invalidate the scanner cache so we don't insert files into > non-existent containers */ > + valid_cache = 0; > + remove_watch(fd, path); > + sql = sqlite3_mprintf("SELECT ID from DETAILS where (PATH > '%q/' and > PATH <= '%q/%c')" > + " or PATH = '%q'", path, path, 0xFF, path); > + if( (sql_get_table(db, sql, &result, &rows, NULL) == SQLITE_OK) ) > + { > + if( rows ) > +@@ -639,6 +700,7 @@ inotify_remove_directory(int fd, const char * path) > + return ret; > + } > + > ++#ifdef HAVE_INOTIFY > + void * > + start_inotify() > + { > +@@ -649,7 +711,7 @@ start_inotify() > + int length, i = 0; > + char * esc_name = NULL; > + struct stat st; > + > + pollfds[0].fd = inotify_init(); > + pollfds[0].events = POLLIN; > + > +@@ -664,13 +726,13 @@ start_inotify() > + } > + inotify_create_watches(pollfds[0].fd); > + if (setpriority(PRIO_PROCESS, 0, 19) == -1) > + DPRINTF(E_WARN, L_INOTIFY, "Failed to reduce inotify thread > priority\n"); > + sqlite3_release_memory(1<<31); > + av_register_all(); > + > + while( !quitting ) > + { > + length = poll(pollfds, 1, timeout); > + if( !length ) > + { > + if( next_pl_fill && (time(NULL) >= next_pl_fill) ) > +@@ -708,12 +770,12 @@ start_inotify() > + snprintf(path_buf, sizeof(path_buf), "%s/%s", > get_path_from_wd(event->wd), event->name); > + if ( event->mask & IN_ISDIR && (event->mask & > (IN_CREATE|IN_MOVED_TO)) ) > + { > + DPRINTF(E_DEBUG, L_INOTIFY, "The > directory %s was %s.\n", > + path_buf, (event->mask & > IN_MOVED_TO ? "moved here" : "created")); > + > inotify_insert_directory(pollfds[0].fd, esc_name, path_buf); > + } > + else if ( (event->mask & > (IN_CLOSE_WRITE|IN_MOVED_TO|IN_CREATE)) && > + (lstat(path_buf, &st) == 0) ) > + { > + if( S_ISLNK(st.st_mode) ) > + { > +@@ -727,7 +789,7 @@ start_inotify() > + else if( event->mask & > (IN_CLOSE_WRITE|IN_MOVED_TO) && st.st_size > 0 ) > + { > + if( (event->mask & > IN_MOVED_TO) || > + (sql_get_int_field(db, > "SELECT TIMESTAMP from DETAILS where PATH = '%q'", path_buf) != st.st_mtime) ) > + { > + DPRINTF(E_DEBUG, > L_INOTIFY, "The file %s was %s.\n", > + path_buf, > (event->mask & IN_MOVED_TO ? "moved here" : "changed")); > +@@ -756,4 +818,234 @@ quitting: > + > + return 0; > + } > ++#else > ++void * > ++start_kqueue() > ++{ > ++ int global_kqueue_handle = -1; > ++ > ++ global_kqueue_handle = kqueue(); > ++ if ( global_kqueue_handle < 0 ) > ++ { > ++ DPRINTF(E_ERROR, L_INOTIFY, "kqueue() failed: %s\n", > strerror(errno)); > ++ return 0; > ++ } > ++ > ++ while( scanning ) > ++ { > ++ if( quitting ) > ++ goto quitting; > ++ > ++ DPRINTF(E_DEBUG, L_INOTIFY, "..waiting for scanning to > complete...\n"); > ++ sleep(1); > ++ } > ++ > ++ DPRINTF(E_DEBUG, L_INOTIFY, "GOING WILD!\n"); > ++ > ++ inotify_create_watches(global_kqueue_handle); > ++ if (setpriority(PRIO_PROCESS, 0, 19) == -1) > ++ DPRINTF(E_WARN, L_INOTIFY, "Failed to reduce kqueue > thread priority\n"); > ++ sqlite3_release_memory(1<<31); > ++ av_register_all(); > ++ > ++ while( !quitting ) > ++ { > ++ struct kevent ke; > ++ if ( kevent(global_kqueue_handle, NULL, 0, &ke, 1, NULL) == > -1 ) > ++ { > ++ DPRINTF(E_WARN, L_INOTIFY, "kevent polling > failure: %s\n", strerror(errno)); > ++ continue; > ++ } > ++ > ++ /*DPRINTF(E_DEBUG, L_INOTIFY, "GOT KEVENT:\n" > ++ "ident=0x%X, filter=0x%X, flags=0x%X, fflags=0x%X, > data=0x%X, udata=0x%X\n", > ++ ke.ident, ke.filter, ke.flags, ke.fflags, ke.data, > ke.udata);*/ > ++ > ++ char* dir_path = get_path_from_wd(ke.ident); > ++ if (dir_path == NULL) > ++ { > ++ DPRINTF(E_ERROR, L_INOTIFY, "Path with FD=0x%X can't > be resolved.\n", ke.ident); > ++ continue; > ++ } > ++ > ++ if (ke.fflags & NOTE_DELETE) > ++ { > ++ DPRINTF(E_DEBUG, L_INOTIFY, "Path [%s] deleted.\n", > dir_path); > ++ inotify_remove_directory(ke.ident, dir_path); > ++ } > ++ else if ((ke.fflags & (NOTE_WRITE | NOTE_LINK)) == > (NOTE_WRITE | NOTE_LINK)) > ++ { > ++ DPRINTF(E_DEBUG, L_INOTIFY, "Path [%s] content > updated (directory).\n", dir_path); > ++ > ++ char * sql; > ++ char **result; > ++ int i, rows; > ++ sql = sqlite3_mprintf("SELECT PATH from DETAILS where > (PATH > '%q/' and PATH <= '%q/%c')" > ++ " and SIZE = ''", dir_path, dir_path, 0xFF); > ++ if( (sql_get_table(db, sql, &result, &rows, NULL) != > SQLITE_OK) ) > ++ { > ++ DPRINTF(E_WARN, L_INOTIFY, "Read state [%s]: > Query failed, not updating\n", dir_path); > ++ sqlite3_free(sql); > ++ continue; > ++ } > ++ > ++ for( i=1; i <= rows; i++ ) > ++ { > ++ DPRINTF(E_DEBUG, L_INOTIFY, "Indexed content: > %s\n", result[i]); > ++ if (access(result[i], R_OK) == -1) > ++ { > ++ /* actually, global_kqueue_handle is > not used here */ > ++ > inotify_remove_directory(global_kqueue_handle, result[i]); > ++ } > ++ } > ++ > ++ DIR* d; > ++ struct dirent * entry; > ++ d = opendir(dir_path); > ++ if (!d) > ++ { > ++ DPRINTF(E_ERROR, L_INOTIFY, "Can't list [%s] > (%s)\n", dir_path, strerror(errno)); > ++ continue; > ++ } > ++ > ++ for ( entry = readdir(d); entry != NULL; entry = > readdir(d) ) > ++ { > ++ if ( (entry->d_type == DT_DIR) && > ++ (strcmp(entry->d_name, "..") != 0) && > ++ (strcmp(entry->d_name, ".") != 0) ) > ++ { > ++ char tmp_path[PATH_MAX]; > ++ int result_path_len; > ++ > ++ result_path_len = snprintf(tmp_path, > PATH_MAX, > ++ "%s/%s", dir_path, > entry->d_name); > ++ if (result_path_len >= PATH_MAX) > ++ { > ++ DPRINTF(E_ERROR, L_INOTIFY, > "File path too long for %s!", entry->d_name); > ++ continue; > ++ } > ++ > ++ DPRINTF(E_DEBUG, L_INOTIFY, "Walking > %s\n", tmp_path); > ++ char found_flag = 0; > ++ for( i=1; i <= rows; i++ ) > ++ { > ++ if (strcmp(result[i], > tmp_path) == 0) > ++ { > ++ found_flag = 1; > ++ break; > ++ } > ++ } > ++ > ++ if ( !found_flag ) > ++ { > ++ char * esc_name = NULL; > ++ esc_name = > modifyString(strdup(entry->d_name), "&", "&amp;", 0); > ++ > inotify_insert_directory(global_kqueue_handle, esc_name, tmp_path); > ++ free(esc_name); > ++ } > ++ } > ++ } > ++ > ++ closedir(d); > ++ > ++ sqlite3_free_table(result); > ++ sqlite3_free(sql); > ++ } > ++ else if (ke.fflags & NOTE_WRITE) > ++ { > ++ DPRINTF(E_DEBUG, L_INOTIFY, "Path [%s] content > updated (file).\n", dir_path); > ++ > ++ char * sql; > ++ char **result; > ++ int i, rows; > ++ sql = sqlite3_mprintf("SELECT PATH from DETAILS where > (PATH > '%q/' and PATH <= '%q/%c')" > ++ " and SIZE <> ''", dir_path, dir_path, 0xFF); > ++ if( (sql_get_table(db, sql, &result, &rows, NULL) != > SQLITE_OK) ) > ++ { > ++ DPRINTF(E_WARN, L_INOTIFY, "Read state [%s]: > Query failed, not updating\n", dir_path); > ++ sqlite3_free(sql); > ++ continue; > ++ } > ++ > ++ for( i=1; i <= rows; i++ ) > ++ { > ++ DPRINTF(E_DEBUG, L_INOTIFY, "Indexed content: > %s\n", result[i]); > ++ if (access(result[i], R_OK) == -1) /*oops, > our file is gone*/ > ++ { > ++ inotify_remove_file(result[i]); > ++ } > ++ } > ++ > ++ DIR* d; > ++ struct dirent * entry; > ++ d = opendir(dir_path); > ++ if (!d) > ++ { > ++ DPRINTF(E_ERROR, L_INOTIFY, "Can't list [%s] > (%s)\n", dir_path, strerror(errno)); > ++ continue; > ++ } > ++ > ++ for ( entry = readdir(d); entry != NULL; entry = > readdir(d) ) > ++ { > ++ if ( (entry->d_type == DT_REG) || > ++ (entry->d_type == DT_LNK) ) > ++ { > ++ char tmp_path[PATH_MAX]; > ++ int result_path_len; > ++ > ++ result_path_len = snprintf(tmp_path, > PATH_MAX, > ++ "%s/%s", dir_path, > entry->d_name); > ++ if (result_path_len >= PATH_MAX) > ++ { > ++ DPRINTF(E_ERROR, L_INOTIFY, > "File path too long for %s!", entry->d_name); > ++ continue; > ++ } > ++ > ++ DPRINTF(E_DEBUG, L_INOTIFY, "Walking > %s\n", tmp_path); > ++ > ++ char found_flag = 0; > ++ for( i=1; i <= rows; i++ ) > ++ { > ++ if (strcmp(result[i], > tmp_path) == 0) > ++ { > ++ found_flag = 1; > ++ break; > ++ } > ++ } > ++ > ++ if ( !found_flag ) > ++ { > ++ char * esc_name = NULL; > ++ struct stat st; > ++ > ++ if( stat(tmp_path, &st) != 0 ) > ++ { > ++ DPRINTF(E_ERROR, > L_INOTIFY, "'%s' disappeared!", tmp_path); > ++ continue; > ++ } > ++ > ++ esc_name = > modifyString(strdup(entry->d_name), "&", "&amp;", 0); > ++ if ( S_ISDIR(st.st_mode) ) > ++ > inotify_insert_directory(global_kqueue_handle, esc_name, tmp_path); > ++ else > ++ > inotify_insert_file(esc_name, tmp_path); > ++ free(esc_name); > ++ } > ++ } > ++ } > ++ > ++ closedir(d); > ++ > ++ sqlite3_free_table(result); > ++ sqlite3_free(sql); > ++ } > ++ } > ++ inotify_remove_watches(global_kqueue_handle); > ++quitting: > ++ > ++ return 0; > ++} > + #endif > ++ > ++#endif // defined(HAVE_INOTIFY) || defined(HAVE_SYS_EVENT_H) > ++ > Index: patches/patch-inotify_h > =================================================================== > RCS file: patches/patch-inotify_h > diff -N patches/patch-inotify_h > --- /dev/null 1 Jan 1970 00:00:00 -0000 > +++ patches/patch-inotify_h 18 Jan 2015 22:45:10 -0000 > @@ -0,0 +1,14 @@ > +$OpenBSD$ > +--- inotify.h.orig Tue Aug 26 23:09:22 2014 > ++++ inotify.h Sun Jan 18 22:45:07 2015 > +@@ -4,4 +4,10 @@ inotify_remove_file(const char * path); > + > + void * > + start_inotify(); > ++#elif defined(HAVE_SYS_EVENT_H) > ++int > ++inotify_remove_file(const char* path); > ++ > ++void * > ++start_kqueue(); > + #endif > Index: patches/patch-metadata_c > =================================================================== > RCS file: patches/patch-metadata_c > diff -N patches/patch-metadata_c > --- /dev/null 1 Jan 1970 00:00:00 -0000 > +++ patches/patch-metadata_c 18 Jan 2015 22:45:10 -0000 > @@ -0,0 +1,12 @@ > +$OpenBSD$ > +--- metadata.c.orig Tue Aug 26 23:09:22 2014 > ++++ metadata.c Sun Jan 18 22:45:07 2015 > +@@ -149,7 +149,7 @@ check_for_captions(const char *path, int64_t detailID) > + > + if (ret == 0) > + { > +- sql_exec(db, "INSERT into CAPTIONS" > ++ sql_exec(db, "INSERT OR REPLACE into CAPTIONS" > + " (ID, PATH) " > + "VALUES" > + " (%lld, %Q)", detailID, file); > Index: patches/patch-minidlna_c > =================================================================== > RCS file: patches/patch-minidlna_c > diff -N patches/patch-minidlna_c > --- /dev/null 1 Jan 1970 00:00:00 -0000 > +++ patches/patch-minidlna_c 18 Jan 2015 22:45:10 -0000 > @@ -0,0 +1,43 @@ > +$OpenBSD$ > +--- minidlna.c.orig Tue Aug 26 23:09:22 2014 > ++++ minidlna.c Sun Jan 18 22:45:07 2015 > +@@ -46,6 +46,7 @@ > + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF > THE > + * POSSIBILITY OF SUCH DAMAGE. > + */ > ++#define FD_SETSIZE 8192 > + #include <stdlib.h> > + #include <unistd.h> > + #include <string.h> > +@@ -376,6 +377,7 @@ rescan: > + open_db(&db); > + if (*scanner_pid == 0) /* child (scanner) process */ > + { > ++ DPRINTF(E_DEBUG, L_GENERAL, "Starting scanner in > forked child\n"); > + start_scanner(); > + sqlite3_close(db); > + log_close(); > +@@ -384,6 +386,7 @@ rescan: > + } > + else if (*scanner_pid < 0) > + { > ++ DPRINTF(E_DEBUG, L_GENERAL, "Starting scanner in > parent\n"); > + start_scanner(); > + } > + #else > +@@ -1047,6 +1050,15 @@ main(int argc, char **argv) > + "Inotify will be > disabled.\n"); > + else if (pthread_create(&inotify_thread, NULL, start_inotify, > NULL) != 0) > + DPRINTF(E_FATAL, L_GENERAL, "ERROR: pthread_create() > failed for start_inotify. EXITING\n"); > ++ } > ++#elif defined(HAVE_SYS_EVENT_H) > ++ if( GETFLAG(INOTIFY_MASK) ) > ++ { > ++ if (!sqlite3_threadsafe() || sqlite3_libversion_number() < > 3005001) > ++ DPRINTF(E_ERROR, L_GENERAL, "SQLite library is not > threadsafe! " > ++ "Kqueue will be disabled.\n"); > ++ else if (pthread_create(&inotify_thread, NULL, start_kqueue, > NULL) != 0) > ++ DPRINTF(E_FATAL, L_GENERAL, "ERROR: pthread_create() > failed for start_kqueue. EXITING\n"); > + } > + #endif > + smonitor = OpenAndConfMonitorSocket(); > Index: patches/patch-minidlna_conf > =================================================================== > RCS file: /cvs/ports/multimedia/minidlna/patches/patch-minidlna_conf,v > retrieving revision 1.4 > diff -p -u -r1.4 patch-minidlna_conf > --- patches/patch-minidlna_conf 11 Jun 2014 00:26:59 -0000 1.4 > +++ patches/patch-minidlna_conf 18 Jan 2015 22:45:10 -0000 > @@ -28,7 +28,7 @@ default directories, plus we don't use i > > # set this to merge all media_dir base contents into the root container > # note: the default is no > -@@ -25,22 +26,18 @@ media_dir=/opt > +@@ -25,22 +26,22 @@ media_dir=/opt > #friendly_name=My DLNA Server > > # set this if you would like to specify the directory where you want > MiniDLNA to store its database and album art cache > @@ -47,10 +47,10 @@ default directories, plus we don't use i > # this should be a list of file names to check for when searching for album > art > # note: names should be delimited with a forward slash ("/") > > album_art_names=Cover.jpg/cover.jpg/AlbumArtSmall.jpg/albumartsmall.jpg/AlbumArt.jpg/albumart.jpg/Album.jpg/album.jpg/Folder.jpg/folder.jpg/Thumb.jpg/thumb.jpg > -- > --# set this to no to disable inotify monitoring to automatically discover > new files > --# note: the default is yes > --inotify=yes > + > + # set this to no to disable inotify monitoring to automatically discover > new files > + # note: the default is yes > + inotify=yes > > # set this to yes to enable support for streaming .jpg and .mp3 files to a > TiVo supporting HMO > enable_tivo=no > Index: patches/patch-upnpevents_c > =================================================================== > RCS file: patches/patch-upnpevents_c > diff -N patches/patch-upnpevents_c > --- /dev/null 1 Jan 1970 00:00:00 -0000 > +++ patches/patch-upnpevents_c 18 Jan 2015 22:45:10 -0000 > @@ -0,0 +1,14 @@ > +$OpenBSD$ > +--- upnpevents.c.orig Tue Aug 26 23:09:22 2014 > ++++ upnpevents.c Sun Jan 18 22:45:07 2015 > +@@ -417,6 +417,10 @@ void upnpevents_selectfds(fd_set *readset, fd_set *wri > + { > + struct upnp_event_notify * obj; > + for(obj = notifylist.lh_first; obj != NULL; obj = > obj->entries.le_next) { > ++ if (obj->s > FD_SETSIZE) > ++ DPRINTF(E_FATAL, L_HTTP, > ++ "upnpevents_selectfds: file descriptor %d too big > for select, limit is %d\n", > ++ obj->s, FD_SETSIZE); > + DPRINTF(E_DEBUG, L_HTTP, "upnpevents_selectfds: %p %d %d\n", > + obj, obj->state, obj->s); > + if(obj->s >= 0) { > > > Comments, tests? > > > Daniel > > -- > LÉVAI Dániel > PGP key ID = 0x83B63A8F > Key fingerprint = DBEC C66B A47A DFA2 792D 650C C69B BE4C 83B6 3A8F > -- "If you try a few times and give up, you'll never get there. But if you keep at it... There's a lot of problems in the world which can really be solved by applying two or three times the persistence that other people will." -- Stewart Nelson