Here's the specific patch as well.
-- Regards, Andres
Patch that allows for inotify support to be checked at runtime. =================================================================== --- mediatomb-0.10.0/src/config_manager.cc.bak 2008-02-19 13:44:03.000000000 -0500 +++ mediatomb-0.10.0/src/config_manager.cc 2008-02-19 13:53:04.000000000 -0500 @@ -44,6 +44,10 @@ #include "string_converter.h" #include "metadata_handler.h" +#ifdef HAVE_INOTIFY + #include "mt_inotify.h" +#endif + #if defined(HAVE_LANGINFO_H) && defined(HAVE_LOCALE_H) #include <langinfo.h> #include <locale.h> @@ -839,19 +843,61 @@ _("from"), _("to"))); SET_DICT_OPTION(CFG_IMPORT_MAPPINGS_MIMETYPE_TO_UPNP_CLASS_LIST); + temp = getOption(_("/import/autoscan/attribute::use-inotify"), _("auto")); + if ((temp != "auto") && !validateYesNo(temp)) + throw _Exception(_("Error in config file: incorrect parameter for " + "\"<autoscan use-inotify=\" attribute")); + el = getElement(_("/import/autoscan")); - if (el == nil) - { - getOption(_("/import/autoscan"), _("")); - } + NEW_AUTOSCANLIST_OPTION(createAutoscanListFromNodeset(el, TimedScanMode)); SET_AUTOSCANLIST_OPTION(CFG_IMPORT_AUTOSCAN_TIMED_LIST); + bool inotify_supported = false; + #ifdef HAVE_INOTIFY - NEW_AUTOSCANLIST_OPTION(createAutoscanListFromNodeset(el, InotifyScanMode)); - SET_AUTOSCANLIST_OPTION(CFG_IMPORT_AUTOSCAN_INOTIFY_LIST); + inotify_supported = Inotify::supported(); #endif - + + if (temp == _(YES)) + { +#ifdef HAVE_INOTIFY + if (!inotify_supported) + throw _Exception(_("You specified " + "\"yes\" in \"<autoscan use-inotify=\"" + " however your system does not have " + "inotify support")); +#else + throw _Exception(_("You specified \"yes\" in \"<autoscan use-inotify=\"" + " however this version of MediaTomb was compiled " + "without inotify support")); +#endif + } + +#ifdef HAVE_INOTIFY + if (temp == _("auto") || (temp == _(YES))) + { + if (inotify_supported) + { + NEW_AUTOSCANLIST_OPTION(createAutoscanListFromNodeset(el, InotifyScanMode)); + SET_AUTOSCANLIST_OPTION(CFG_IMPORT_AUTOSCAN_INOTIFY_LIST); + + NEW_BOOL_OPTION(true); + SET_BOOL_OPTION(CFG_IMPORT_AUTOSCAN_USE_INOTIFY); + } + else + { + NEW_BOOL_OPTION(false); + SET_BOOL_OPTION(CFG_IMPORT_AUTOSCAN_USE_INOTIFY); + } + } + else + { + NEW_BOOL_OPTION(false); + SET_BOOL_OPTION(CFG_IMPORT_AUTOSCAN_USE_INOTIFY); + } +#endif + el = getElement(_("/server/custom-http-headers")); NEW_STRARR_OPTION(createArrayFromNodeset(el, _("add"), _("header"))); SET_STRARR_OPTION(CFG_SERVER_CUSTOM_HTTP_HEADERS); --- mediatomb-0.10.0/src/mt_inotify.cc.bak 2008-02-19 13:41:48.000000000 -0500 +++ mediatomb-0.10.0/src/mt_inotify.cc 2008-02-19 13:54:02.000000000 -0500 @@ -46,6 +46,7 @@ #include <unistd.h> #include <errno.h> #include <assert.h> +#include <tools.h> #include "mt_inotify.h" @@ -73,10 +74,29 @@ close(inotify_fd); } +bool Inotify::supported() +{ + int test_fd = inotify_init(); + if (test_fd < 0) + return false; + else + { + close(test_fd); + return true; + } +} int Inotify::addWatch(String path, int events) { - return inotify_add_watch(inotify_fd, path.c_str(), events); + int wd = inotify_add_watch(inotify_fd, path.c_str(), events); + if (wd < 0 && errno != ENOENT) + { + if (errno == ENOSPC) + throw _Exception(_("The user limit on the total number of inotify watches was reached or the kernel failed to allocate a needed resource.")); + else + throw _Exception(mt_strerror(errno)); + } + return wd; } void Inotify::removeWatch(int wd) --- mediatomb-0.10.0/src/content_manager.cc.bak 2008-02-19 13:56:13.000000000 -0500 +++ mediatomb-0.10.0/src/content_manager.cc 2008-02-19 14:15:55.000000000 -0500 @@ -87,6 +87,7 @@ ContentManager::ContentManager() : TimerSubscriberSingleton<ContentManager>() { + int i; cond = Ref<Cond>(new Cond(mutex)); ignore_unknown_extensions = 0; @@ -143,24 +144,31 @@ autoscan_timed = storage->getAutoscanList(TimedScanMode); #ifdef HAVE_INOTIFY - Ref<AutoscanList> config_inotify_list = - cm->getAutoscanListOption(CFG_IMPORT_AUTOSCAN_INOTIFY_LIST); - - for (int i = 0; i < config_inotify_list->size(); i++) + if (cm->getBoolOption(CFG_IMPORT_AUTOSCAN_USE_INOTIFY)) { - Ref<AutoscanDirectory> dir = config_inotify_list->get(i); - if (dir != nil) + Ref<AutoscanList> config_inotify_list = + cm->getAutoscanListOption(CFG_IMPORT_AUTOSCAN_INOTIFY_LIST); + + for (i = 0; i < config_inotify_list->size(); i++) { - String path = dir->getLocation(); - if (check_path(path, true)) + Ref<AutoscanDirectory> dir = config_inotify_list->get(i); + if (dir != nil) { - dir->setObjectID(ensurePathExistence(path)); + String path = dir->getLocation(); + if (check_path(path, true)) + { + dir->setObjectID(ensurePathExistence(path)); + } } } - } - storage->updateAutoscanPersistentList(InotifyScanMode, config_inotify_list); - autoscan_inotify = storage->getAutoscanList(InotifyScanMode); + storage->updateAutoscanPersistentList(InotifyScanMode, + config_inotify_list); + autoscan_inotify = storage->getAutoscanList(InotifyScanMode); + } + else + // make an empty list so we do not have to do extra checks on shutdown + autoscan_inotify = Ref<AutoscanList>(new AutoscanList()); #endif /* init filemagic */ #ifdef HAVE_MAGIC @@ -233,15 +241,17 @@ autoscan_timed->notifyAll(AS_TIMER_SUBSCRIBER_SINGLETON(this)); #ifdef HAVE_INOTIFY - inotify = Ref<AutoscanInotify>(new AutoscanInotify()); - /// \todo change this for 0.9.1 (we need a new autoscan architecture) - for (int i = 0; i < autoscan_inotify->size(); i++) + if (ConfigManager::getInstance()->getBoolOption(CFG_IMPORT_AUTOSCAN_USE_INOTIFY)) { - Ref<AutoscanDirectory> dir = autoscan_inotify->get(i); - if (dir != nil) - inotify->monitor(dir); + inotify = Ref<AutoscanInotify>(new AutoscanInotify()); + /// \todo change this (we need a new autoscan architecture) + for (int i = 0; i < autoscan_inotify->size(); i++) + { + Ref<AutoscanDirectory> dir = autoscan_inotify->get(i); + if (dir != nil) + inotify->monitor(dir); + } } - #endif } @@ -1442,11 +1452,14 @@ Timer::getInstance()->removeTimerSubscriber(AS_TIMER_SUBSCRIBER_SINGLETON(this), rm_list->get(i)->getScanID(), true); } #ifdef HAVE_INOTIFY - rm_list = autoscan_inotify->removeIfSubdir(path); - for (i = 0; i < rm_list->size(); i++) + if (ConfigManager::getInstance()->getBoolOption(CFG_IMPORT_AUTOSCAN_USE_INOTIFY)) { - Ref<AutoscanDirectory> dir = rm_list->get(i); - inotify->unmonitor(dir); + rm_list = autoscan_inotify->removeIfSubdir(path); + for (i = 0; i < rm_list->size(); i++) + { + Ref<AutoscanDirectory> dir = rm_list->get(i); + inotify->unmonitor(dir); + } } #endif @@ -1580,16 +1593,19 @@ } #ifdef HAVE_INOTIFY - else if (scanMode == InotifyScanMode) + if (ConfigManager::getInstance()->getBoolOption(CFG_IMPORT_AUTOSCAN_USE_INOTIFY)) { - Ref<Storage> storage = Storage::getInstance(); - Ref<AutoscanDirectory> adir = autoscan_inotify->get(scanID); - if (adir == nil) - throw _Exception(_("can not remove autoscan directory - was not an autoscan")); - autoscan_inotify->remove(scanID); - storage->removeAutoscanDirectory(adir->getStorageID()); - SessionManager::getInstance()->containerChangedUI(adir->getObjectID()); - inotify->unmonitor(adir); + if (scanMode == InotifyScanMode) + { + Ref<Storage> storage = Storage::getInstance(); + Ref<AutoscanDirectory> adir = autoscan_inotify->get(scanID); + if (adir == nil) + throw _Exception(_("can not remove autoscan directory - was not an autoscan")); + autoscan_inotify->remove(scanID); + storage->removeAutoscanDirectory(adir->getStorageID()); + SessionManager::getInstance()->containerChangedUI(adir->getObjectID()); + inotify->unmonitor(adir); + } } #endif @@ -1610,12 +1626,15 @@ Timer::getInstance()->removeTimerSubscriber(AS_TIMER_SUBSCRIBER_SINGLETON(this), scanID, true); } #ifdef HAVE_INOTIFY - else if (adir->getScanMode() == InotifyScanMode) + if (ConfigManager::getInstance()->getBoolOption(CFG_IMPORT_AUTOSCAN_USE_INOTIFY)) { - autoscan_inotify->remove(adir->getLocation()); - storage->removeAutoscanDirectoryByObjectID(objectID); - SessionManager::getInstance()->containerChangedUI(objectID); - inotify->unmonitor(adir); + if (adir->getScanMode() == InotifyScanMode) + { + autoscan_inotify->remove(adir->getLocation()); + storage->removeAutoscanDirectoryByObjectID(objectID); + SessionManager::getInstance()->containerChangedUI(objectID); + inotify->unmonitor(adir); + } } #endif } @@ -1625,8 +1644,11 @@ /// \todo change this when more scanmodes become avaiable Ref<AutoscanDirectory> adir = autoscan_timed->get(location); #ifdef HAVE_INOTIFY - if (adir == nil) - adir = autoscan_inotify->get(location); + if (ConfigManager::getInstance()->getBoolOption(CFG_IMPORT_AUTOSCAN_USE_INOTIFY)) + { + if (adir == nil) + adir = autoscan_inotify->get(location); + } #endif if (adir == nil) throw _Exception(_("can not remove autoscan directory - was not an autoscan")); @@ -1667,8 +1689,11 @@ // We will have to change this for other scan modes original = autoscan_timed->getByObjectID(dir->getObjectID()); #ifdef HAVE_INOTIFY - if (original == nil) - original = autoscan_inotify->getByObjectID(dir->getObjectID()); + if (ConfigManager::getInstance()->getBoolOption(CFG_IMPORT_AUTOSCAN_USE_INOTIFY)) + { + if (original == nil) + original = autoscan_inotify->getByObjectID(dir->getObjectID()); + } #endif if (original != nil) @@ -1698,10 +1723,13 @@ timerNotify(scanID); } #ifdef HAVE_INOTIFY - else if (dir->getScanMode() == InotifyScanMode) + if (ConfigManager::getInstance()->getBoolOption(CFG_IMPORT_AUTOSCAN_USE_INOTIFY)) { - autoscan_inotify->add(dir); - inotify->monitor(dir); + if (dir->getScanMode() == InotifyScanMode) + { + autoscan_inotify->add(dir); + inotify->monitor(dir); + } } #endif SessionManager::getInstance()->containerChangedUI(dir->getObjectID()); @@ -1711,9 +1739,12 @@ if (original->getScanMode() == TimedScanMode) Timer::getInstance()->removeTimerSubscriber(AS_TIMER_SUBSCRIBER_SINGLETON(this), original->getScanID(), true); #ifdef HAVE_INOTIFY - else if (original->getScanMode() == InotifyScanMode) + if (ConfigManager::getInstance()->getBoolOption(CFG_IMPORT_AUTOSCAN_USE_INOTIFY)) { - inotify->unmonitor(original); + if (original->getScanMode() == InotifyScanMode) + { + inotify->unmonitor(original); + } } #endif @@ -1743,9 +1774,12 @@ autoscan_timed->remove(copy->getScanID()); } #ifdef HAVE_INOTIFY - else if (copy->getScanMode() == InotifyScanMode) + if (ConfigManager::getInstance()->getBoolOption(CFG_IMPORT_AUTOSCAN_USE_INOTIFY)) { - autoscan_inotify->remove(copy->getScanID()); + if (copy->getScanMode() == InotifyScanMode) + { + autoscan_inotify->remove(copy->getScanID()); + } } #endif @@ -1757,10 +1791,13 @@ timerNotify(scanID); } #ifdef HAVE_INOTIFY - else if (dir->getScanMode() == InotifyScanMode) + if (ConfigManager::getInstance()->getBoolOption(CFG_IMPORT_AUTOSCAN_USE_INOTIFY)) { - autoscan_inotify->add(copy); - inotify->monitor(copy); + if (dir->getScanMode() == InotifyScanMode) + { + autoscan_inotify->add(copy); + inotify->monitor(copy); + } } #endif --- mediatomb-0.10.0/src/mt_inotify.h.bak 2008-02-19 14:19:26.000000000 -0500 +++ mediatomb-0.10.0/src/mt_inotify.h 2008-02-19 14:20:14.000000000 -0500 @@ -67,6 +67,9 @@ /// \brief Unblock the next_event function. void stop(); + /// \brief Checks if inotify is supported on the system. + static bool supported(); + private: int inotify_fd; int stop_fds_pipe[2]; --- mediatomb-0.10.0/src/config_manager.h.bak 2008-02-19 14:20:52.000000000 -0500 +++ mediatomb-0.10.0/src/config_manager.h 2008-02-19 14:21:35.000000000 -0500 @@ -103,6 +103,7 @@ #endif CFG_IMPORT_AUTOSCAN_TIMED_LIST, #ifdef HAVE_INOTIFY + CFG_IMPORT_AUTOSCAN_USE_INOTIFY, CFG_IMPORT_AUTOSCAN_INOTIFY_LIST, #endif CFG_IMPORT_MAPPINGS_IGNORE_UNKNOWN_EXTENSIONS, --- mediatomb-0.10.0/src/tools.cc.bak 2008-02-19 19:03:59.000000000 -0500 +++ mediatomb-0.10.0/src/tools.cc 2008-02-19 19:04:53.000000000 -0500 @@ -380,6 +380,29 @@ return buf->toString(); } +String mt_strerror(int mt_errno) +{ +#ifdef DONT_USE_YET_HAVE_STRERROR_R + char *buffer = (char *)MALLOC(512); + char *err_str; + #ifdef STRERROR_R_CHAR_P + err_str = strerror_r(errno, buffer, 512); + if (err_str == NULL) + err_str = buffer; + #else + int ret = strerror_r(errno, buffer, 512); + if (ret < 0) + return _("cannot get error string: error while calling XSI-compliant strerror_r"); + err_str = buffer; + #endif + String errStr(err_str); + FREE(buffer); + return errStr; +#else + return String(strerror(errno)); +#endif +} + String read_text_file(String path) { FILE *f = fopen(path.c_str(), "r"); --- mediatomb-0.10.0/src/tools.h.bak 2008-02-19 19:19:52.000000000 -0500 +++ mediatomb-0.10.0/src/tools.h 2008-02-19 19:20:24.000000000 -0500 @@ -134,6 +134,11 @@ /// \return string containing the CSV list zmm::String mime_types_to_CSV(zmm::Ref<zmm::Array<zmm::StringBase> > mimeTypes); +/// \brief a wrapper for the reentrant strerror_r() function +/// \param mt_errno the errno to get the error string from +/// \return the error string +zmm::String mt_strerror(int mt_errno); + /// \brief Reads the entire contents of a text file and returns it as a string. zmm::String read_text_file(zmm::String path); --- mediatomb-0.10.0/src/web/auth.cc.bak 2008-02-19 14:22:15.000000000 -0500 +++ mediatomb-0.10.0/src/web/auth.cc 2008-02-19 14:23:16.000000000 -0500 @@ -109,7 +109,10 @@ config->appendChild(ipp); #ifdef HAVE_INOTIFY - config->addAttribute(_("have-inotify"), _("1")); + if (cm->getBoolOption(CFG_IMPORT_AUTOSCAN_USE_INOTIFY)) + config->addAttribute(_("have-inotify"), _("1")); + else + config->addAttribute(_("have-inotify"), _("0")); #else config->addAttribute(_("have-inotify"), _("0")); #endif --- mediatomb-0.10.0/src/web/items.cc.bak 2008-02-19 14:24:18.000000000 -0500 +++ mediatomb-0.10.0/src/web/items.cc 2008-02-19 14:25:21.000000000 -0500 @@ -110,29 +110,31 @@ autoscanMode = 1; #ifdef HAVE_INOTIFY - int startpoint_id = INVALID_OBJECT_ID; - if (autoscanType == 0) + if (ConfigManager::getInstance()->getBoolOption(CFG_IMPORT_AUTOSCAN_USE_INOTIFY)) { - startpoint_id = storage->isAutoscanChild(parentID); - } - else - { - startpoint_id = parentID; - } - - if (startpoint_id != INVALID_OBJECT_ID) - { - Ref<AutoscanDirectory> adir = storage->getAutoscanDirectory(startpoint_id); - if ((adir != nil) && (adir->getScanMode() == InotifyScanMode)) + int startpoint_id = INVALID_OBJECT_ID; + if (autoscanType == 0) + { + startpoint_id = storage->isAutoscanChild(parentID); + } + else { - protectItems = 1; - if (autoscanType == 0 || adir->persistent()) - protectContainer = 1; + startpoint_id = parentID; + } - autoscanMode = 2; + if (startpoint_id != INVALID_OBJECT_ID) + { + Ref<AutoscanDirectory> adir = storage->getAutoscanDirectory(startpoint_id); + if ((adir != nil) && (adir->getScanMode() == InotifyScanMode)) + { + protectItems = 1; + if (autoscanType == 0 || adir->persistent()) + protectContainer = 1; + + autoscanMode = 2; + } } } - #endif items->addAttribute(_("protectContainer"), String::from(protectContainer)); --- mediatomb-0.10.0/src/web/containers.cc.bak 2008-02-19 14:25:56.000000000 -0500 +++ mediatomb-0.10.0/src/web/containers.cc 2008-02-19 14:26:28.000000000 -0500 @@ -94,9 +94,12 @@ { autoscanMode = 1; #ifdef HAVE_INOTIFY - Ref<AutoscanDirectory> adir = storage->getAutoscanDirectory(cont->getID()); - if ((adir != nil) && (adir->getScanMode() == InotifyScanMode)) - autoscanMode = 2; + if (ConfigManager::getInstance()->getBoolOption(CFG_IMPORT_AUTOSCAN_USE_INOTIFY)) + { + Ref<AutoscanDirectory> adir = storage->getAutoscanDirectory(cont->getID()); + if ((adir != nil) && (adir->getScanMode() == InotifyScanMode)) + autoscanMode = 2; + } #endif } ce->addAttribute(_("autoscanMode"), String::from(autoscanMode)); =================================================================== Part of the diff for configure.ac includes components to allow for using the MD5 implementation from dpkg (namely, unsigned int, unsigned long, and the big endian check. =================================================================== --- mediatomb-0.10.0/configure.ac.bak 2008-02-19 14:31:09.000000000 -0500 +++ mediatomb-0.10.0/configure.ac 2008-02-19 15:09:31.000000000 -0500 @@ -682,6 +682,8 @@ AC_CHECK_SIZEOF(off_t, 4) AC_CHECK_SIZEOF(size_t, 4) AC_CHECK_SIZEOF(time_t, 4) +AC_CHECK_SIZEOF(unsigned int) +AC_CHECK_SIZEOF(unsigned long) AC_CHECK_FUNCS(strtoll nl_langinfo setlocale,[],[]) AC_CHECK_FUNCS(backtrace backtrace_symbols,[],[]) # Checks for typedefs, structures, and compiler characteristics. @@ -691,6 +693,7 @@ AC_TYPE_PID_T AC_TYPE_SIZE_T AC_STRUCT_TM +AC_C_BIGENDIAN AC_ARG_ENABLE(rpl-malloc, AC_HELP_STRING([--disable-rpl-malloc], [disable redefinition of malloc to rpl_malloc and realloc to rpl_realloc. Use this if you are sure that you are compiling for the GNU C library (default: enabled)]), @@ -2283,10 +2286,10 @@ ), [ AC_MSG_RESULT([yes]); - AC_DEFINE([SYS_INOTIFY_H_OK],[1],[sys/inotify.h exists and works correctly])], + AC_DEFINE([SYS_INOTIFY_H_OK],[1],[sys/inotify.h exists and works on this system])], [ AC_MSG_RESULT([no, using own inotify headers]) - AC_MSG_CHECKING([whether inotify-nosys.h works]) + AC_MSG_CHECKING([whether inotify-nosys.h works on this system]) AC_RUN_IFELSE( AC_LANG_PROGRAM([[#include "src/inotify-nosys.h"]], [[return (-1 == inotify_init());]] @@ -2296,7 +2299,11 @@ INOTIFY_OK=yes ], [ - AC_MSG_RESULT([no, disabling inotify support]) + if test "x$INOTIFY_EN" != xyes; then + AC_MSG_RESULT([no, disabling inotify support]) + else + AC_MSG_RESULT([no]) + fi INOTIFY_OK=missing ]) @@ -2308,7 +2315,14 @@ AC_SUBST(INOTIFY_CXXFLAGS) else if test "x$INOTIFY_EN" = xyes; then - AC_MSG_ERROR(unable to configure inotify support) + AC_MSG_NOTICE([enabling runtime inotify detection]) + # if system inotify header exists, go with it, otherwise take our own + if test "x$ac_cv_header_sys_inotify_h" = xyes; then + AC_DEFINE([SYS_INOTIFY_H_OK],[1],[sys/inotify.h exists]) + fi + AC_DEFINE([HAVE_INOTIFY], [1], [inotify presence]) + AC_SUBST(INOTIFY_CXXFLAGS) + INOTIFY_OK=yes fi fi