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.
This commit is contained in:
Wim Taymans 2020-08-21 11:15:24 +02:00
parent 157b15d643
commit 39513fb681

View file

@ -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,
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;
}