barbieri pushed a commit to branch master.

http://git.enlightenment.org/core/efl.git/commit/?id=2f919345028ae54d7d8fa0b1460ab42bc929e6fd

commit 2f919345028ae54d7d8fa0b1460ab42bc929e6fd
Author: Gustavo Sverzut Barbieri <[email protected]>
Date:   Wed Nov 23 12:10:31 2016 -0200

    ecore_con: export function to create local path string.
    
    The new efl_net code won't compose any path own its own, allowing the
    user to connect to non-EFL systems.
    
    However we need a way to use the same path Ecore_Con_Server does, so
    we can reach it. Then export and use ecore_con_local_path_new() to do
    exactly that.
---
 src/lib/ecore_con/Ecore_Con.h             |  40 ++++++
 src/lib/ecore_con/ecore_con_local.c       | 220 ++++++++++++++++--------------
 src/lib/ecore_con/ecore_con_local_win32.c |  52 ++++---
 3 files changed, 184 insertions(+), 128 deletions(-)

diff --git a/src/lib/ecore_con/Ecore_Con.h b/src/lib/ecore_con/Ecore_Con.h
index 7ed3b48..cc2dd2b 100644
--- a/src/lib/ecore_con/Ecore_Con.h
+++ b/src/lib/ecore_con/Ecore_Con.h
@@ -1098,6 +1098,42 @@ EAPI void             
ecore_con_socks_apply_always(Ecore_Con_Socks *ecs);
  */
 
 /**
+ * @brief Create a local path to connect the socket.
+ *
+ * In the old API, ecore_con_server_add() and
+ * ecore_con_server_connect() calculated a local path for connections
+ * using @c ECORE_CON_LOCAL_USER and @c ECORE_CON_LOCAL_SYSTEM, this
+ * function returns that path allocated so it can be used in
+ * applications that want to connect to that path without replicating
+ * its logic.
+ *
+ * @li If @a type is @c ECORE_CON_LOCAL_USER, the server will conect to
+ *     the Unix socket. The path to the socket is taken from XDG_RUNTIME_DIR,
+ *     if that is not set, then from HOME, even if this is not set, then from
+ *     TMPDIR. If none is set, then path would be /tmp. From this path the
+ *     function would connect to socket at "[path]/.ecore/[name]/[port]". If
+ *     port is negetive, then to socket at "[path]/.ecore/[name]".
+ * @li If @a type is @c ECORE_CON_LOCAL_SYSTEM, the server will connect to
+ *     Unix socket at "/tmp/.ecore_service|[name]|[port]". If port is negetive,
+ *     then to Unix socket at "/tmp/.ecore_service|[name]".
+ *
+ * @param  is_system  If #EINA_TRUE, will be a system wide socket
+ *                    similar to @c ECORE_CON_LOCAL_SYSTEM. If #EINA_FALSE,
+ *                    then it's similar to @c ECORE_CON_LOCAL_USER.
+ * @param  name       Name to associate with the socket.  It is used when
+ *                    generating the socket name of a Unix socket,
+ *                    @c NULL will not be accepted.
+ * @param  port       Number to identify socket.  When a Unix socket is used,
+ *                    it becomes part of the socket name.
+ *
+ * @return NULL on failure or newly allocated path string on success,
+ * remember to free() it after usage.
+ *
+ * @since 1.19
+ */
+EAPI char *ecore_con_local_path_new(Eina_Bool is_system, const char *name, int 
port) EINA_WARN_UNUSED_RESULT EINA_MALLOC EINA_ARG_NONNULL(2);
+
+/**
  * @brief Create a server to listen for connections.
  *
  * @param  type The connection type.
@@ -1132,6 +1168,8 @@ EAPI void             
ecore_con_socks_apply_always(Ecore_Con_Socks *ecs);
  *
  * The @p data parameter can be fetched later using ecore_con_server_data_get()
  * or changed with ecore_con_server_data_set().
+ *
+ * @see ecore_con_local_path_new()
  */
 EAPI Ecore_Con_Server *ecore_con_server_add(Ecore_Con_Type type,
                                             const char *name, int port,
@@ -1182,6 +1220,8 @@ EAPI Ecore_Con_Server 
*ecore_con_server_add(Ecore_Con_Type type,
  *
  * The @p data parameter can be fetched later using ecore_con_server_data_get()
  * or changed with ecore_con_server_data_set().
+ *
+ * @see ecore_con_local_path_new()
  */
 EAPI Ecore_Con_Server *ecore_con_server_connect(Ecore_Con_Type type,
                                                 const char *name, int port,
diff --git a/src/lib/ecore_con/ecore_con_local.c 
b/src/lib/ecore_con/ecore_con_local.c
index 546b6e0..3bf9b97 100644
--- a/src/lib/ecore_con/ecore_con_local.c
+++ b/src/lib/ecore_con/ecore_con_local.c
@@ -64,24 +64,15 @@ ecore_con_local_shutdown(void)
    return _ecore_con_local_init_count;
 }
 
-int
-ecore_con_local_connect(Ecore_Con_Server *obj,
-                        Eina_Bool (*cb_done)(void *data, Ecore_Fd_Handler 
*fd_handler),
-                        void *data EINA_UNUSED)
+EAPI char *
+ecore_con_local_path_new(Eina_Bool is_system, const char *name, int port)
 {
-#ifndef HAVE_LOCAL_SOCKETS
-   return 0;
-#else
-   Efl_Network_Server_Data *svr = efl_data_scope_get(obj, 
EFL_NETWORK_SERVER_CLASS);
    char buf[4096];
-   struct sockaddr_un socket_unix;
-   int curstate = 0;
    const char *homedir;
-   int socket_unix_len;
 
-   buf[0] = '\0';
+   EINA_SAFETY_ON_NULL_RETURN_VAL(name, NULL);
 
-   if ((svr->type & ECORE_CON_TYPE) == ECORE_CON_LOCAL_USER)
+   if (!is_system)
      {
 #if defined(HAVE_GETUID) && defined(HAVE_GETEUID)
         if (getuid() == geteuid())
@@ -97,50 +88,78 @@ ecore_con_local_connect(Ecore_Con_Server *obj,
           }
 #endif
 
-        if (svr->port < 0)
+        if (port < 0)
            snprintf(buf, sizeof(buf), "%s/.ecore/%s",
-                    homedir, svr->name);
+                    homedir, name);
         else
            snprintf(buf, sizeof(buf), "%s/.ecore/%s/%i",
-                    homedir, svr->name, svr->port);
+                    homedir, name, port);
+        return strdup(buf);
      }
-   else if ((svr->type & ECORE_CON_TYPE) == ECORE_CON_LOCAL_SYSTEM)
+   else
      {
-        if (svr->port < 0)
+        if (port < 0)
           {
-             if (svr->name[0] == '/')
-               {
-                  strncpy(buf, svr->name, sizeof(buf) - 1);
-                  buf[sizeof(buf) - 1] = 0;
-               }
+             if (name[0] == '/')
+               return strdup(name);
              else
                {
                   homedir = eina_environment_tmp_get();
                   snprintf(buf, sizeof(buf), "%s/.ecore_service|%s",
-                           homedir, svr->name);
+                           homedir, name);
+                  return strdup(buf);
                }
           }
         else
           {
-             if (svr->name[0] == '/')
-               snprintf(buf, sizeof(buf), "%s|%i", svr->name, svr->port);
+             if (name[0] == '/')
+               snprintf(buf, sizeof(buf), "%s|%i", name, port);
              else
                {
                   homedir = eina_environment_tmp_get();
                   snprintf(buf, sizeof(buf), "%s/.ecore_service|%s|%i",
-                           homedir, svr->name, svr->port);
+                           homedir, name, port);
                }
+             return strdup(buf);
           }
      }
+}
+
+int
+ecore_con_local_connect(Ecore_Con_Server *obj,
+                        Eina_Bool (*cb_done)(void *data, Ecore_Fd_Handler 
*fd_handler),
+                        void *data EINA_UNUSED)
+{
+#ifndef HAVE_LOCAL_SOCKETS
+   return 0;
+#else
+   Efl_Network_Server_Data *svr = efl_data_scope_get(obj, 
EFL_NETWORK_SERVER_CLASS);
+   char *buf = NULL;
+   struct sockaddr_un socket_unix;
+   int curstate = 0;
+   int socket_unix_len;
+
+   if ((svr->type & ECORE_CON_TYPE) == ECORE_CON_LOCAL_USER)
+     {
+        buf = ecore_con_local_path_new(EINA_FALSE, svr->name, svr->port);
+     }
+   else if ((svr->type & ECORE_CON_TYPE) == ECORE_CON_LOCAL_SYSTEM)
+     {
+        buf = ecore_con_local_path_new(EINA_TRUE, svr->name, svr->port);
+     }
    else if ((svr->type & ECORE_CON_TYPE) == ECORE_CON_LOCAL_ABSTRACT)
      {
-        strncpy(buf, svr->name, sizeof(buf) - 1);
-        buf[sizeof(buf) - 1] = 0;
+        buf = strdup(svr->name);
      }
 
+   EINA_SAFETY_ON_NULL_RETURN_VAL(buf, 0);
+
    svr->fd = socket(AF_UNIX, SOCK_STREAM, 0);
    if (svr->fd < 0)
-     return 0;
+     {
+        free(buf);
+        return 0;
+     }
 
    if (fcntl(svr->fd, F_SETFL, O_NONBLOCK) < 0)
      goto error;
@@ -182,9 +201,8 @@ ecore_con_local_connect(Ecore_Con_Server *obj,
         goto error;
      }
 
-   svr->path = strdup(buf);
-   if (!svr->path)
-     goto error;
+   svr->path = buf;
+   buf = NULL;
 
    if (svr->type & ECORE_CON_SSL)
      {
@@ -199,14 +217,65 @@ ecore_con_local_connect(Ecore_Con_Server *obj,
 
    if (!svr->delete_me) ecore_con_event_server_add(obj);
 
+   free(buf);
+
    return 1;
 error:
    if (svr->fd) close(svr->fd);
    svr->fd = -1;
+   free(buf);
    return 0;
 #endif
 }
 
+#ifdef HAVE_LOCAL_SOCKETS
+static void
+_ecore_con_local_mkpath(const char *path, mode_t mode)
+{
+   char *s, *d, *itr;
+
+   if (!path) return;
+   EINA_SAFETY_ON_TRUE_RETURN(path[0] != '/');
+
+   s = strdup(path);
+   EINA_SAFETY_ON_NULL_RETURN(s);
+   d = dirname(s);
+   EINA_SAFETY_ON_NULL_RETURN(d);
+
+   for (itr = d + 1; *itr != '\0'; itr++)
+     {
+        if (*itr == '/')
+          {
+             *itr = '\0';
+             if (mkdir(d, mode) != 0)
+               {
+                  if (errno != EEXIST)
+                    {
+                       ERR("could not create parent directory '%s' of path 
'%s': %s", d, path, strerror(errno));
+                       goto end;
+                    }
+               }
+             *itr = '/';
+          }
+     }
+
+   if (mkdir(d, mode) != 0)
+     {
+        if (errno != EEXIST)
+          ERR("could not create parent directory '%s' of path '%s': %s", d, 
path, strerror(errno));
+        else
+          {
+             struct stat st;
+             if ((stat(d, &st) != 0) || (!S_ISDIR(st.st_mode)))
+               ERR("could not create parent directory '%s' of path '%s': 
exists but is not a directory", d, path);
+          }
+     }
+
+ end:
+   free(s);
+}
+#endif
+
 int
 ecore_con_local_listen(
   Ecore_Con_Server *obj,
@@ -219,11 +288,10 @@ ecore_con_local_listen(
 {
 #ifdef HAVE_LOCAL_SOCKETS
    Efl_Network_Server_Data *svr = efl_data_scope_get(obj, 
EFL_NETWORK_SERVER_CLASS);
-   char buf[4096];
+   char *buf = NULL;
    struct sockaddr_un socket_unix;
    struct linger lin;
    mode_t pmode;
-   const char *homedir;
    mode_t mask;
    int socket_unix_len;
    Eina_Bool abstract_socket;
@@ -232,87 +300,25 @@ ecore_con_local_listen(
 
    if ((svr->type & ECORE_CON_TYPE) == ECORE_CON_LOCAL_USER)
      {
-#if defined(HAVE_GETUID) && defined(HAVE_GETEUID)
-        if (getuid() == geteuid())
-#endif
-          homedir = _ecore_con_local_path_get();
+        buf = ecore_con_local_path_new(EINA_FALSE, svr->name, svr->port);
 
-#if defined(HAVE_GETUID) && defined(HAVE_GETEUID)
-        else
-          {
-             struct passwd *pw = getpwent();
-
-             if ((!pw) || (!pw->pw_dir)) homedir = "/tmp";
-             else homedir = pw->pw_dir;
-          }
-#endif
         mask = S_IRUSR | S_IWUSR | S_IXUSR;
-        snprintf(buf, sizeof(buf), "%s/.ecore", homedir);
-        if (mkdir(buf, mask) < 0)
-          {
-             if (errno != EEXIST)
-               {
-                  ERR("mkdir '%s' failed", buf);
-               }
-          }
-
-        snprintf(buf, sizeof(buf), "%s/.ecore/%s", homedir, svr->name);
-        if (mkdir(buf, mask) < 0)
-          {
-             if (errno != EEXIST)
-               {
-                  ERR("mkdir '%s' failed", buf);
-               }
-          }
-
-        if (svr->port < 0)
-           snprintf(buf, sizeof(buf), "%s/.ecore/%s",
-                    homedir, svr->name);
-        else
-           snprintf(buf, sizeof(buf), "%s/.ecore/%s/%i",
-                    homedir, svr->name, svr->port);
+        _ecore_con_local_mkpath(buf, mask);
 
         mask = S_IRGRP | S_IWGRP | S_IXGRP | S_IROTH | S_IWOTH | S_IXOTH;
      }
    else if ((svr->type & ECORE_CON_TYPE) == ECORE_CON_LOCAL_SYSTEM)
      {
         mask = 0;
-        if (svr->port < 0)
-          {
-             if (svr->name[0] == '/')
-               {
-                  strncpy(buf, svr->name, sizeof(buf) - 1);
-                  buf[sizeof(buf) - 1] = 0;
-               }
-             else
-               {
-                  homedir = eina_environment_tmp_get();
-                  snprintf(buf, sizeof(buf), "%s/.ecore_service|%s",
-                           homedir, svr->name);
-               }
-          }
-        else
-          {
-             if (svr->name[0] == '/')
-               snprintf(buf, sizeof(buf), "%s|%i", svr->name, svr->port);
-             else
-               {
-                  homedir = eina_environment_tmp_get();
-                  snprintf(buf, sizeof(buf), "%s/.ecore_service|%s|%i",
-                           homedir, svr->name, svr->port);
-               }
-          }
+        buf = ecore_con_local_path_new(EINA_TRUE, svr->name, svr->port);
      }
    else if ((svr->type & ECORE_CON_TYPE) == ECORE_CON_LOCAL_ABSTRACT)
      {
-        strncpy(buf, svr->name, sizeof(buf) - 1);
-        buf[sizeof(buf) - 1] = 0;
-     }
-   else
-     {
-        buf[0] = '\0';
+        buf = strdup(svr->name);
      }
 
+   EINA_SAFETY_ON_NULL_RETURN_VAL(buf, 0);
+
    pmode = umask(mask);
 start:
    socket_unix.sun_family = AF_UNIX;
@@ -408,9 +414,8 @@ start:
 #ifdef HAVE_SYSTEMD
 fd_ready:
 #endif
-   svr->path = strdup(buf);
-   if (!svr->path)
-     goto error_umask;
+   svr->path = buf;
+   buf = NULL;
 
    svr->fd_handler =
      ecore_main_fd_handler_add(svr->fd, ECORE_FD_READ,
@@ -419,6 +424,8 @@ fd_ready:
    if (!svr->fd_handler)
      goto error;
 
+   free(buf);
+
    return 1;
 
 error_fd:
@@ -427,6 +434,7 @@ error_fd:
 error_umask:
    umask(pmode);
 error:
+   free(buf);
 #endif /* HAVE_LOCAL_SOCKETS */
    return 0;
 }
diff --git a/src/lib/ecore_con/ecore_con_local_win32.c 
b/src/lib/ecore_con/ecore_con_local_win32.c
index 09aa566..b322d9a 100644
--- a/src/lib/ecore_con/ecore_con_local_win32.c
+++ b/src/lib/ecore_con/ecore_con_local_win32.c
@@ -386,11 +386,29 @@ _ecore_con_local_win32_listening(void *data)
    return 0;
 }
 
+EAPI char *
+ecore_con_local_path_new(Eina_Bool is_system, const char *name, int port)
+{
+   char buf[256];
+
+   if (!is_system)
+     snprintf(buf, sizeof(buf), "\\\\.\\pipe\\%s%ld", name, 
GetProcessId(GetCurrentProcess()));
+   else
+     {
+        const char *computername;
+
+        computername = getenv("COMPUTERNAME");
+        snprintf(buf, sizeof(buf), "\\\\%s\\pipe\\%s%ld", computername, name, 
GetProcessId(GetCurrentProcess()));
+     }
+
+   return strdup(buf);
+   (void)port; // CHECK-ME: shouldn't we use port to be similar to UNIX?
+}
+
 Eina_Bool
 ecore_con_local_listen(Ecore_Con_Server *obj)
 {
    Efl_Network_Server_Data *svr = efl_data_scope_get(obj, 
EFL_NETWORK_SERVER_CLASS);
-   char buf[256];
    HANDLE thread_listening;
    Ecore_Win32_Handler *handler;
 
@@ -401,16 +419,10 @@ ecore_con_local_listen(Ecore_Con_Server *obj)
      }
 
    if ((svr->type & ECORE_CON_TYPE) == ECORE_CON_LOCAL_USER)
-     snprintf(buf, sizeof(buf), "\\\\.\\pipe\\%s%ld", svr->name, 
GetProcessId(GetCurrentProcess()));
+     svr->path = ecore_con_local_path_new(EINA_FALSE, svr->name, svr->port);
    else if ((svr->type & ECORE_CON_TYPE) == ECORE_CON_LOCAL_SYSTEM)
-     {
-        const char *computername;
-
-        computername = getenv("COMPUTERNAME");
-        snprintf(buf, sizeof(buf), "\\\\%s\\pipe\\%s%ld", computername, 
svr->name, GetProcessId(GetCurrentProcess()));
-     }
+     svr->path = ecore_con_local_path_new(EINA_TRUE, svr->name, svr->port);
 
-   svr->path = strdup(buf);
    if (!svr->path)
      {
         ERR("Allocation failed");
@@ -540,7 +552,7 @@ ecore_con_local_connect(Ecore_Con_Server *obj,
 {
 #warning "I am pretty sure cb_done should be used."
    Efl_Network_Server_Data *svr = efl_data_scope_get(obj, 
EFL_NETWORK_SERVER_CLASS);
-   char buf[256];
+   char buf = NULL;
    Ecore_Win32_Handler *handler_read;
    Ecore_Win32_Handler *handler_peek;
 
@@ -551,14 +563,11 @@ ecore_con_local_connect(Ecore_Con_Server *obj,
      }
 
    if ((svr->type & ECORE_CON_TYPE) == ECORE_CON_LOCAL_USER)
-     snprintf(buf, sizeof(buf), "\\\\.\\pipe\\%s", svr->name);
+     buf = ecore_con_local_path_new(EINA_FALSE, svr->name, svr->port);
    else if ((svr->type & ECORE_CON_TYPE) == ECORE_CON_LOCAL_SYSTEM)
-     {
-        const char *computername;
+     buf = ecore_con_local_path_new(EINA_TRUE, svr->name, svr->port);
 
-        computername = getenv("COMPUTERNAME");
-        snprintf(buf, sizeof(buf), "\\\\%s\\pipe\\%s", computername, 
svr->name);
-     }
+   EINA_SAFETY_ON_NULL_RETURN_VAL(buf, EINA_FALSE);
 
    while (1)
      {
@@ -576,6 +585,7 @@ ecore_con_local_connect(Ecore_Con_Server *obj,
         if (GetLastError() != ERROR_PIPE_BUSY)
           {
              DBG("Connection to a server failed");
+             free(buf);
              return EINA_FALSE;
           }
 
@@ -587,12 +597,8 @@ ecore_con_local_connect(Ecore_Con_Server *obj,
           }
      }
 
-   svr->path = strdup(buf);
-   if (!svr->path)
-     {
-        ERR("Allocation failed");
-        goto close_pipe;
-     }
+   svr->path = buf;
+   buf = NULL;
 
    svr->event_read = CreateEvent(NULL, TRUE, FALSE, NULL);
    if (!svr->event_read)
@@ -636,6 +642,7 @@ ecore_con_local_connect(Ecore_Con_Server *obj,
    if (!svr->delete_me) ecore_con_event_server_add(obj);
 
    ResumeThread(svr->thread_read);
+   free(buf);
 
    return EINA_TRUE;
 
@@ -652,6 +659,7 @@ free_path:
    svr->path = NULL;
 close_pipe:
    CloseHandle(svr->pipe);
+   free(buf);
 
    return EINA_FALSE;
 }

-- 


Reply via email to