Hello community,

here is the log from the commit of package menu-cache for openSUSE:Factory 
checked in at 2017-09-13 22:38:11
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/menu-cache (Old)
 and      /work/SRC/openSUSE:Factory/.menu-cache.new (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Package is "menu-cache"

Wed Sep 13 22:38:11 2017 rev:29 rq:525865 version:1.0.2

Changes:
--------
--- /work/SRC/openSUSE:Factory/menu-cache/menu-cache.changes    2017-01-12 
15:55:56.498600930 +0100
+++ /work/SRC/openSUSE:Factory/.menu-cache.new/menu-cache.changes       
2017-09-13 22:38:30.722535795 +0200
@@ -1,0 +2,8 @@
+Wed Sep 13 12:57:27 UTC 2017 - [email protected]
+
+- boo#boo#1044483:
+  - Add menu-cache-1.0.2-until-fd52af6.patch
+  We need a6763eb which tests for multiple daemons.
+  Other fixes are also important/related/good-to-have
+
+-------------------------------------------------------------------

New:
----
  menu-cache-1.0.2-until-fd52af6.patch

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Other differences:
------------------
++++++ menu-cache.spec ++++++
--- /var/tmp/diff_new_pack.keepb7/_old  2017-09-13 22:38:31.246462028 +0200
+++ /var/tmp/diff_new_pack.keepb7/_new  2017-09-13 22:38:31.250461465 +0200
@@ -24,6 +24,7 @@
 Group:          System/GUI/LXDE
 Url:            http://www.lxde.org
 Source0:        %{name}-%{version}.tar.xz
+Patch0:         menu-cache-1.0.2-until-fd52af6.patch
 BuildRequires:  fdupes
 BuildRequires:  gtk-doc
 BuildRequires:  gtk2-devel
@@ -57,6 +58,7 @@
 
 %prep
 %setup -q
+%patch0 -p1
 
 %build
 export CFLAGS="%{optflags}"

++++++ menu-cache-1.0.2-until-fd52af6.patch ++++++
diff --git a/NEWS b/NEWS
index dcc572a..0de60f8 100644
--- a/NEWS
+++ b/NEWS
@@ -1,3 +1,26 @@
+* Fixed crash with invalid <Name> tag in a menu.
+
+* Added new API menu_cache_app_get_generic_name() to get generic
+    name for application.
+
+* Fixed potential access violation, use runtime user dir instead of tmp dir.
+    It limits libmenu-cache compatibility to menu-cached >= 0.7.0.
+
+* Directory $XDG_DATA_HOME/applications will be created if it does not
+    exist so it will be monitored in any case.
+
+* Fixed issue when subdirectories added would be skipped in monitoring.
+
+* Fixed potential file descriptors leak.
+
+* Reduced inactivity timer to 6 seconds (from 600 seconds).
+
+* Fixed an issue with multiple daemons started: test if daemon is already
+    running on socket before killing old socket file.
+
+* Fixed 100% CPU load by menu-cached due to invalid dup2() call.
+
+
 Changes in 1.0.2 since 1.0.1:
 
 * Fixed crash in menu-cached if cache regeneration fails.
diff --git a/libmenu-cache/menu-cache.c b/libmenu-cache/menu-cache.c
index 3bc9cfc..5025d72 100644
--- a/libmenu-cache/menu-cache.c
+++ b/libmenu-cache/menu-cache.c
@@ -3,7 +3,7 @@
  *
  *      Copyright 2008 PCMan <[email protected]>
  *      Copyright 2009 Jürgen Hötzel <[email protected]>
- *      Copyright 2012-2015 Andriy Grytsenko (LStranger) <[email protected]>
+ *      Copyright 2012-2017 Andriy Grytsenko (LStranger) <[email protected]>
  *
  *      This library is free software; you can redistribute it and/or
  *      modify it under the terms of the GNU Lesser General Public
@@ -1233,6 +1233,22 @@ gboolean menu_cache_dir_is_visible(MenuCacheDir *dir)
     return ((dir->flags & FLAG_IS_NODISPLAY) == 0);
 }
 
+/**
+ * menu_cache_app_get_generic_name
+ * @app: a menu cache item
+ *
+ * Retrieves generic name for @app. Returned data are owned by menu
+ * cache and should not be freed by caller.
+ *
+ * Returns: (transfer none): app's generic name or %NULL.
+ *
+ * Since: 1.0.3
+ */
+const char* menu_cache_app_get_generic_name( MenuCacheApp* app )
+{
+       return app->generic_name;
+}
+
 /**
  * menu_cache_app_get_exec
  * @app: a menu cache item
@@ -1522,8 +1538,13 @@ static void get_socket_name( char* buf, int len )
         if(*p)
             *p = '\0';
     }
+#if GLIB_CHECK_VERSION(2, 28, 0)
+    g_snprintf( buf, len, "%s/menu-cached-%s", g_get_user_runtime_dir(),
+                dpy ? dpy : ":0" );
+#else
     g_snprintf( buf, len, "%s/.menu-cached-%s-%s", g_get_tmp_dir(),
                 dpy ? dpy : ":0", g_get_user_name() );
+#endif
     g_free(dpy);
 }
 
@@ -1698,6 +1719,9 @@ retry:
         G_UNLOCK(connect);
         return FALSE;
     }
+
+    fcntl (fd, F_SETFD, FD_CLOEXEC);
+
     memset(&addr, 0, sizeof(addr));
     addr.sun_family = AF_UNIX;
 
diff --git a/libmenu-cache/menu-cache.h.in b/libmenu-cache/menu-cache.h.in
index 76ea7b4..cded59d 100644
--- a/libmenu-cache/menu-cache.h.in
+++ b/libmenu-cache/menu-cache.h.in
@@ -151,6 +151,7 @@ MenuCacheItem *menu_cache_find_child_by_name(MenuCacheDir 
*dir, const char *name
 
 char* menu_cache_dir_make_path( MenuCacheDir* dir );
 
+const char* menu_cache_app_get_generic_name( MenuCacheApp* app );
 const char* menu_cache_app_get_exec( MenuCacheApp* app );
 const char* menu_cache_app_get_working_dir( MenuCacheApp* app );
 const char* const *menu_cache_app_get_categories(MenuCacheApp* app);
diff --git a/menu-cache-daemon/menu-cached.c b/menu-cache-daemon/menu-cached.c
index a6895ee..bda766a 100644
--- a/menu-cache-daemon/menu-cached.c
+++ b/menu-cache-daemon/menu-cached.c
@@ -3,7 +3,7 @@
  *
  *      Copyright 2008 - 2010 PCMan <[email protected]>
  *      Copyright 2009 Jürgen Hötzel <[email protected]>
- *      Copyright 2012-2015 Andriy Grytsenko (LStranger) <[email protected]>
+ *      Copyright 2012-2017 Andriy Grytsenko (LStranger) <[email protected]>
  *      Copyright 2016 Mamoru TASAKA <[email protected]>
  *
  *      This file is a part of libmenu-cache package and created program
@@ -34,6 +34,7 @@
 #include <stdio.h>
 #include <stdlib.h>
 #include <glib.h>
+#include <glib/gstdio.h>
 #include <gio/gio.h>
 #include <sys/types.h>
 #include <sys/socket.h>
@@ -131,12 +132,12 @@ static gboolean delayed_cache_free(gpointer data)
 
 static void cache_free(Cache* cache)
 {
-    /* shutdown cache in 10 minutes of inactivity */
+    /* shutdown cache in 6 seconds of inactivity */
     if(!cache->delayed_free_handler)
-        cache->delayed_free_handler = g_timeout_add_seconds(600,
+        cache->delayed_free_handler = g_timeout_add_seconds(6,
                                                             delayed_cache_free,
                                                             cache);
-    DEBUG("menu %p cache unused, removing in 600s", cache);
+    DEBUG("menu %p cache unused, removing in 6s", cache);
 }
 
 static gboolean read_all_used_files( FILE* f, int* n_files, char*** used_files 
)
@@ -221,6 +222,7 @@ static gboolean regenerate_cache( const char* menu_name,
     FILE* f;
     int n_files, status = 0;
     char** files;
+    const char *user_data_dir = env[5];
     const char* argv[] = {
         MENUCACHE_LIBEXECDIR "/menu-cache-gen",
         "-l", NULL,
@@ -233,6 +235,18 @@ static gboolean regenerate_cache( const char* menu_name,
 
     /* DEBUG("cmd: %s", g_strjoinv(" ", argv)); */
 
+    /* create $XDG_DATA_HOME/applications if it does not exist yet */
+    if (!user_data_dir || !user_data_dir[0])
+        user_data_dir = g_get_user_data_dir();
+    if (g_file_test(user_data_dir, G_FILE_TEST_IS_DIR) ||
+        g_mkdir(user_data_dir, 0700) == 0)
+    {
+        char *local_app_path = g_build_filename(user_data_dir, "applications", 
NULL);
+        if (!g_file_test(local_app_path, G_FILE_TEST_IS_DIR))
+            g_mkdir(local_app_path, 0700);
+        g_free(local_app_path);
+    }
+
     /* run menu-cache-gen */
     /* FIXME: is cast to (char**) valid here? */
     if( !g_spawn_sync(NULL, (char **)argv, NULL, 0,
@@ -376,25 +390,39 @@ void on_file_changed( GFileMonitor* mon, GFile* gf, 
GFile* other,
         if( G_LIKELY(idx < cache->n_files) && cache->files[idx][0] == 'D' )
         {
             char* changed_file = g_file_get_path(gf);
-            char* dir_path = cache->files[idx]+1;
-            int len = strlen(dir_path);
-            /* if the changed file is a file in the monitored dir */
-            if( strncmp(changed_file, dir_path, len) == 0 && changed_file[len] 
== '/' )
+            /* Regenerate the cache if the changed file is a directory.
+             *
+             * The file monitor isn't recursive, so imagine we add a
+             * subdirectory to /usr/share/applications, and subsequently
+             * add a desktop entry to that. If we ignore the new
+             * subdirectory, we won't notice when the desktop entry is
+             * added. By regenerating the cache, the subdirectory will
+             * be mentioned there, picked up by read_all_used_files(),
+             * and monitored for subsequent changes.
+             */
+            if (!g_file_test(changed_file, G_FILE_TEST_IS_DIR))
             {
-                char* base_name = changed_file + len + 1;
-                gboolean skip = TRUE;
-                /* only *.desktop and *.directory files can affect the content 
of the menu. */
-                if( g_str_has_suffix(base_name, ".desktop") )
+                char* dir_path = cache->files[idx]+1;
+                int len = strlen(dir_path);
+                /* if the changed file is a file in the monitored dir */
+                if( strncmp(changed_file, dir_path, len) == 0 && 
changed_file[len] == '/' )
                 {
+                    char* base_name = changed_file + len + 1;
+                    gboolean skip = TRUE;
+                    /* only *.desktop and *.directory files can affect the 
content of the menu. */
+                    if( g_str_has_suffix(base_name, ".desktop") )
+                    {
+                            skip = FALSE;
+                    }
+                    else if( g_str_has_suffix(base_name, ".directory") )
                         skip = FALSE;
-                }
-                else if( g_str_has_suffix(base_name, ".directory") )
-                    skip = FALSE;
 
-                if( skip )
-                {
-                    DEBUG("files are changed, but no re-generation is 
needed.");
-                    return;
+                    if( skip )
+                    {
+                        DEBUG("files are changed, but no re-generation is 
needed.");
+                        g_free(changed_file);
+                        return;
+                    }
                 }
             }
             g_free(changed_file);
@@ -473,21 +501,33 @@ static void get_socket_name( char* buf, int len )
         if(*p)
             *p = '\0';
     }
+    /* NOTE: this socket name is incompatible with versions > 1.0.2,
+            although this function is never used since 0.7.0 but
+            libmenu-cache always requests exact socket name instead */
     g_snprintf( buf, len, "%s/.menu-cached-%s-%s", g_get_tmp_dir(),
                 dpy ? dpy : ":0", g_get_user_name() );
     g_free(dpy);
 }
 
-static int create_socket(struct sockaddr_un *addr)
+static gboolean socket_is_alive(struct sockaddr_un *addr)
 {
-    int fd = -1;
+    int fd = socket(PF_UNIX, SOCK_STREAM, 0);
+    socklen_t len = sizeof(sa_family_t) + strlen(addr->sun_path) + 1;
 
-    fd = socket(PF_UNIX, SOCK_STREAM, 0);
     if (fd < 0)
     {
         DEBUG("Failed to create socket");
-        return -1;
+        /* still return TRUE to drop attempt */
+        return TRUE;
+    }
+    if (connect(fd, (struct sockaddr*)addr, len) >= 0)
+    {
+        /* there is a listener on the socket */
+        close(fd);
+        DEBUG("Another menu-cached seems to reside on the socket");
+        return TRUE;
     }
+    close(fd);
 
     /* remove previous socket file */
     if (unlink(addr->sun_path) < 0) {
@@ -497,19 +537,57 @@ static int create_socket(struct sockaddr_un *addr)
     /* remove of previous socket file successful */
     else
         g_warning("removed previous socket file %s", addr->sun_path);
+    return FALSE;
+}
+
+static int create_socket(struct sockaddr_un *addr)
+{
+    int fd = -1;
+    char *lockfile;
 
-    if(bind(fd, (struct sockaddr *)addr, sizeof(*addr)) < 0)
+    lockfile = g_strconcat(addr->sun_path, ".lock", NULL);
+    fd = open(lockfile, O_CREAT | O_EXCL | O_WRONLY, 0700);
+    if (fd < 0)
+    {
+        DEBUG("Cannot create lock file %s: %s", lockfile, strerror(errno));
+        g_free(lockfile);
+        return -1;
+    }
+    close(fd);
+
+    fd = socket(PF_UNIX, SOCK_STREAM, 0);
+    if (fd < 0)
+    {
+        DEBUG("Failed to create socket");
+    }
+
+    /* remove previous socket file */
+    else if (g_file_test(addr->sun_path, G_FILE_TEST_EXISTS) &&
+             socket_is_alive(addr))
+    {
+        close(fd);
+        fd = -1;
+    }
+
+    else if(bind(fd, (struct sockaddr *)addr, sizeof(*addr)) < 0)
     {
         DEBUG("Failed to bind to socket");
         close(fd);
-        return -1;
+        fd = -1;
     }
-    if(listen(fd, 30) < 0)
+
+    else if(listen(fd, 30) < 0)
     {
         DEBUG( "Failed to listen to socket" );
         close(fd);
-        return -1;
+        fd = -1;
     }
+
+    else
+        fcntl(fd, F_SETFD, FD_CLOEXEC);
+
+    unlink(lockfile);
+    g_free(lockfile);
     return fd;
 }
 
@@ -717,6 +795,14 @@ retry:
     return ret;
 }
 
+static void terminate(int sig)
+{
+/* #ifndef HAVE_ABSTRACT_SOCKETS */
+    unlink(socket_file);
+    exit(0);
+/* #endif */
+}
+
 static gboolean on_new_conn_incoming(GIOChannel* ch, GIOCondition cond, 
gpointer user_data)
 {
     int server, client;
@@ -732,9 +818,16 @@ static gboolean on_new_conn_incoming(GIOChannel* ch, 
GIOCondition cond, gpointer
     if( client == -1 )
     {
         DEBUG("accept error");
-        return TRUE;
+        if (errno == ECONNABORTED)
+            /* client failed, just continue */
+            return TRUE;
+        /* else it's socket error, terminate server */
+        terminate(SIGTERM);
+        return FALSE;
     }
 
+    fcntl (client, F_SETFD, FD_CLOEXEC);
+
     child = g_io_channel_unix_new(client);
     g_io_channel_set_close_on_unref( child, TRUE );
 
@@ -749,14 +842,6 @@ static gboolean on_new_conn_incoming(GIOChannel* ch, 
GIOCondition cond, gpointer
     return TRUE;
 }
 
-static void terminate(int sig)
-{
-/* #ifndef HAVE_ABSTRACT_SOCKETS */
-    unlink(socket_file);
-    exit(0);
-/* #endif */
-}
-
 static gboolean on_server_conn_close(GIOChannel* ch, GIOCondition cond, 
gpointer user_data)
 {
     /* FIXME: is this possible? */
@@ -771,7 +856,7 @@ int main(int argc, char** argv)
     int server_fd;
     struct sockaddr_un addr;
 #ifndef DISABLE_DAEMONIZE
-    int fd, pid;
+    pid_t pid;
 
     long open_max;
     long i;
@@ -815,28 +900,18 @@ int main(int argc, char** argv)
         g_error("can't change directory to /");
     }
 
+    /* don't hold open fd opened besides server socket and std{in,out,err} */
     open_max = sysconf (_SC_OPEN_MAX);
-    for (i = 0; i < open_max; i++)
+    for (i = 3; i < open_max; i++)
     {
-        /* don't hold open fd opened besides server socket */
         if (i != server_fd)
-            fcntl (i, F_SETFD, FD_CLOEXEC);
+            close (i);
     }
 
     /* /dev/null for stdin, stdout, stderr */
-    fd = open ("/dev/null", O_RDONLY);
-    if (fd != -1)
-    {
-        dup2 (fd, 0);
-        close (fd);
-    }
-    fd = open ("/dev/null", O_WRONLY);
-    if (fd != -1)
-    {
-        dup2 (fd, 1);
-        dup2 (fd, 2);
-        close (fd);
-    }
+    if (freopen("/dev/null", "r", stdin)) i = i;
+    if (freopen("/dev/null", "w", stdout)) i = i;
+    if (freopen("/dev/null", "w", stderr)) i = i;
 #endif
 
     signal(SIGHUP, terminate);
diff --git a/menu-cache-gen/menu-merge.c b/menu-cache-gen/menu-merge.c
index 816cf96..31f05b0 100644
--- a/menu-cache-gen/menu-merge.c
+++ b/menu-cache-gen/menu-merge.c
@@ -1,7 +1,7 @@
 /*
  *      menu-file.c : parses <name>.menu file and merges all XML tags.
  *
- *      Copyright 2013-2016 Andriy Grytsenko (LStranger) <[email protected]>
+ *      Copyright 2013-2017 Andriy Grytsenko (LStranger) <[email protected]>
  *
  *      This file is a part of libmenu-cache package and created program
  *      should be not used without the library.
@@ -138,11 +138,13 @@ static gboolean _menu_xml_handler_Name(FmXmlFileItem 
*item, GList *children,
                                        guint n_attributes, gint line, gint pos,
                                        GError **error, gpointer user_data)
 {
+    FmXmlFileItem *name_item;
     const char *name;
 
     RETURN_IF_IN_LAYOUT(item, error);
-    item = fm_xml_file_item_find_child(item, FM_XML_FILE_TEXT);
-    if (item == NULL || (name = fm_xml_file_item_get_data(item, NULL)) == NULL 
||
+    name_item = fm_xml_file_item_find_child(item, FM_XML_FILE_TEXT);
+    if (name_item == NULL ||
+        (name = fm_xml_file_item_get_data(name_item, NULL)) == NULL ||
         strchr(name, '/') != NULL) /* empty or invalid tag */
     {
         RETURN_TRUE_AND_DESTROY_IF_QUIET(item);

Reply via email to