From 39513fb681b30709ce269c5008947c2fe039d70e Mon Sep 17 00:00:00 2001 From: Wim Taymans Date: Fri, 21 Aug 2020 11:15:24 +0200 Subject: [PATCH] protocol-native: fix error reporting Don't say that there is no runtime directory set when there is but the server is not running. Simplify things by first trying to connect to the user runtime directory when set and then try the system directory. There is no need to manually check the existance of the socket, connect wil that that and set the appropriate error. --- .../module-protocol-native/local-socket.c | 105 ++++++++---------- 1 file changed, 44 insertions(+), 61 deletions(-) diff --git a/src/modules/module-protocol-native/local-socket.c b/src/modules/module-protocol-native/local-socket.c index cfeb4c293..a21faefe6 100644 --- a/src/modules/module-protocol-native/local-socket.c +++ b/src/modules/module-protocol-native/local-socket.c @@ -57,40 +57,11 @@ get_remote(const struct spa_dict *props) return name; } -static bool -exists_in_dir(const char *name, const char *dir) -{ - bool exists = false; - - if (dir != NULL) { - int dirfd; - struct stat s; - - dirfd = open(dir, O_RDONLY); - if (dirfd < 0) - pw_log_debug("open dir '%s' failed: %m", dir); - else { - if (fstatat(dirfd, name, &s, 0) < 0) - pw_log_debug("fstatat '%s', dir '%s' failed: %m", name, dir); - else - exists = true; - if (close(dirfd) < 0) - pw_log_warn("close dir failed: %m"); - } - pw_log_debug("'%s' %s in dir '%s'", name, exists ? "exists" : "does not exist", dir); - } - - return exists; -} - static const char * -get_runtime_dir(const char *name) +get_runtime_dir(void) { const char *runtime_dir; - if (name == NULL || strlen(name) == 0 || name[0] == '/') - return NULL; - runtime_dir = getenv("PIPEWIRE_RUNTIME_DIR"); if (runtime_dir == NULL) runtime_dir = getenv("XDG_RUNTIME_DIR"); @@ -104,43 +75,26 @@ get_runtime_dir(const char *name) if (getpwuid_r(getuid(), &pwd, buffer, sizeof(buffer), &result) == 0) runtime_dir = result ? result->pw_dir : NULL; } - if (runtime_dir == NULL || !exists_in_dir(name, runtime_dir)) { - if (exists_in_dir(name, DEFAULT_SYSTEM_RUNTIME_DIR)) - runtime_dir = DEFAULT_SYSTEM_RUNTIME_DIR; - else - runtime_dir = NULL; - } - return runtime_dir; } -int pw_protocol_native_connect_local_socket(struct pw_protocol_client *client, - const struct spa_dict *props, - void (*done_callback) (void *data, int res), - void *data) +static const char * +get_system_dir(void) +{ + return DEFAULT_SYSTEM_RUNTIME_DIR; +} + +static int try_connect(struct pw_protocol_client *client, + const char *runtime_dir, const char *name, + void (*done_callback) (void *data, int res), + void *data) { struct sockaddr_un addr; socklen_t size; - const char *runtime_dir, *name; int res, name_size, fd; - bool path_is_absolute; - - name = get_remote(props); - - path_is_absolute = name[0] == '/'; - - runtime_dir = get_runtime_dir(name); pw_log_info("connecting to '%s' runtime_dir:%s", name, runtime_dir); - if (runtime_dir == NULL && !path_is_absolute) { - pw_log_error("client %p: name %s is not an absolute path and no runtime dir found." - "set one of PIPEWIRE_RUNTIME_DIR, XDG_RUNTIME_DIR, HOME or " - "USERPROFILE in the environment", client, name); - res = -ENOENT; - goto error; - } - if ((fd = socket(PF_LOCAL, SOCK_STREAM | SOCK_CLOEXEC | SOCK_NONBLOCK, 0)) < 0) { res = -errno; goto error; @@ -148,13 +102,13 @@ int pw_protocol_native_connect_local_socket(struct pw_protocol_client *client, memset(&addr, 0, sizeof(addr)); addr.sun_family = AF_LOCAL; - if (!path_is_absolute) - name_size = snprintf(addr.sun_path, sizeof(addr.sun_path), "%s/%s", runtime_dir, name) + 1; - else + if (runtime_dir == NULL) name_size = snprintf(addr.sun_path, sizeof(addr.sun_path), "%s", name) + 1; + else + name_size = snprintf(addr.sun_path, sizeof(addr.sun_path), "%s/%s", runtime_dir, name) + 1; if (name_size > (int) sizeof addr.sun_path) { - if (path_is_absolute) + if (runtime_dir == NULL) pw_log_error("client %p: socket path \"%s\" plus null terminator exceeds %i bytes", client, name, (int) sizeof(addr.sun_path)); else @@ -186,3 +140,32 @@ error_close: error: return res; } + +int pw_protocol_native_connect_local_socket(struct pw_protocol_client *client, + const struct spa_dict *props, + void (*done_callback) (void *data, int res), + void *data) +{ + const char *runtime_dir, *name; + int res; + + name = get_remote(props); + if (name == NULL) + return -EINVAL; + + if (name[0] == '/') { + res = try_connect(client, NULL, name, done_callback, data); + } else { + runtime_dir = get_runtime_dir(); + if (runtime_dir != NULL) { + res = try_connect(client, runtime_dir, name, done_callback, data); + if (res >= 0) + goto exit; + } + runtime_dir = get_system_dir(); + if (runtime_dir != NULL) + res = try_connect(client, runtime_dir, name, done_callback, data); + } +exit: + return res; +}