mirror of
https://gitlab.freedesktop.org/pipewire/pipewire.git
synced 2025-11-02 09:01:50 -05:00
permissions: pass pw_permission struct around
Use a pw_permission struct to express permissions of object. Improve client permissions, add/remove globals when permissions are changed.
This commit is contained in:
parent
f994b7eb70
commit
eb0a561f8c
13 changed files with 282 additions and 320 deletions
|
|
@ -509,21 +509,18 @@ static void on_state_changed(void *_data, enum pw_remote_state old, enum pw_remo
|
|||
|
||||
case PW_REMOTE_STATE_CONNECTED:
|
||||
{
|
||||
struct spa_dict_item items[5];
|
||||
int i = 0;
|
||||
struct pw_permission permissions[2];
|
||||
|
||||
/* set specific permissions on all existing objects without permissions */
|
||||
items[i++] = SPA_DICT_ITEM_INIT(PW_CORE_PROXY_PERMISSIONS_EXISTING, "r--");
|
||||
/* set default permission for new objects and objects without
|
||||
* specific permissions */
|
||||
items[i++] = SPA_DICT_ITEM_INIT(PW_CORE_PROXY_PERMISSIONS_DEFAULT, "---");
|
||||
/* an example, set specific permissions on one object, this is the
|
||||
* core object, we already have a binding to it that is not affected
|
||||
* by the removal of X permissions, only future bindings. */
|
||||
items[i++] = SPA_DICT_ITEM_INIT(PW_CORE_PROXY_PERMISSIONS_GLOBAL, "0:rw-");
|
||||
* core object. */
|
||||
permissions[0].id = 0;
|
||||
permissions[0].permissions = PW_PERM_R | PW_PERM_X;
|
||||
/* remove WX from all other objects */
|
||||
permissions[1].id = SPA_ID_INVALID;
|
||||
permissions[1].permissions = PW_PERM_R;
|
||||
|
||||
pw_core_proxy_permissions(pw_remote_get_core_proxy(data->remote),
|
||||
&SPA_DICT_INIT(items, i));
|
||||
2, permissions);
|
||||
|
||||
make_node(data);
|
||||
break;
|
||||
|
|
|
|||
|
|
@ -700,7 +700,7 @@ handle_client(struct impl *impl, uint32_t id, uint32_t parent_id,
|
|||
{
|
||||
struct pw_proxy *p;
|
||||
struct client *client;
|
||||
struct spa_dict_item items[2];
|
||||
struct pw_permission perms[2];
|
||||
const char *str;
|
||||
|
||||
p = pw_registry_proxy_bind(impl->registry_proxy,
|
||||
|
|
@ -727,10 +727,9 @@ handle_client(struct impl *impl, uint32_t id, uint32_t parent_id,
|
|||
return 0;
|
||||
|
||||
if (strcmp(str, "restricted") == 0) {
|
||||
items[0].key = PW_CORE_PROXY_PERMISSIONS_DEFAULT;
|
||||
items[0].value = "rwx";
|
||||
perms[0] = PW_PERMISSION_INIT(-1, PW_PERM_RWX);
|
||||
pw_client_proxy_update_permissions((struct pw_client_proxy*)p,
|
||||
&SPA_DICT_INIT(items, 1));
|
||||
1, perms);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -110,6 +110,7 @@ core_check_access(void *data, struct pw_client *client)
|
|||
{
|
||||
struct impl *impl = data;
|
||||
const struct ucred *ucred;
|
||||
struct pw_permission permissions[1];
|
||||
struct spa_dict_item items[2];
|
||||
const char *str;
|
||||
int res;
|
||||
|
|
@ -128,7 +129,8 @@ core_check_access(void *data, struct pw_client *client)
|
|||
if (res == 0)
|
||||
goto granted;
|
||||
if (res > 0)
|
||||
res = EACCES;
|
||||
res = -EACCES;
|
||||
items[0] = SPA_DICT_ITEM_INIT("pipewire.access", "blacklisted");
|
||||
goto blacklisted;
|
||||
}
|
||||
|
||||
|
|
@ -162,7 +164,8 @@ core_check_access(void *data, struct pw_client *client)
|
|||
|
||||
granted:
|
||||
pw_log_debug("module %p: client %p access granted", impl, client);
|
||||
pw_client_set_permissions(client, PW_PERM_RWX);
|
||||
permissions[0] = PW_PERMISSION_INIT(-1, PW_PERM_RWX);
|
||||
pw_client_update_permissions(client, 1, permissions);
|
||||
return;
|
||||
|
||||
wait_permissions:
|
||||
|
|
@ -172,7 +175,6 @@ core_check_access(void *data, struct pw_client *client)
|
|||
return;
|
||||
|
||||
blacklisted:
|
||||
items[0] = SPA_DICT_ITEM_INIT("pipewire.access", "blacklisted");
|
||||
pw_resource_error(pw_client_get_core_resource(client), 0, res, "blacklisted");
|
||||
pw_client_update_properties(client, &SPA_DICT_INIT(items, 1));
|
||||
return;
|
||||
|
|
|
|||
|
|
@ -64,22 +64,23 @@ static void core_marshal_client_update(void *object, const struct spa_dict *prop
|
|||
pw_protocol_native_end_proxy(proxy, b);
|
||||
}
|
||||
|
||||
static void core_marshal_permissions(void *object, const struct spa_dict *props)
|
||||
static void core_marshal_permissions(void *object, uint32_t n_permissions,
|
||||
const struct pw_permission *permissions)
|
||||
{
|
||||
struct pw_proxy *proxy = object;
|
||||
struct spa_pod_builder *b;
|
||||
int i, n_items;
|
||||
int i;
|
||||
|
||||
b = pw_protocol_native_begin_proxy(proxy, PW_CORE_PROXY_METHOD_PERMISSIONS);
|
||||
|
||||
n_items = props ? props->n_items : 0;
|
||||
spa_pod_builder_add(b, "[",
|
||||
"i", n_permissions,
|
||||
NULL);
|
||||
|
||||
spa_pod_builder_add(b, "[ i", n_items, NULL);
|
||||
|
||||
for (i = 0; i < n_items; i++) {
|
||||
for (i = 0; i < n_permissions; i++) {
|
||||
spa_pod_builder_add(b,
|
||||
"s", props->items[i].key,
|
||||
"s", props->items[i].value, NULL);
|
||||
"i", permissions[i].id,
|
||||
"i", permissions[i].permissions, NULL);
|
||||
}
|
||||
spa_pod_builder_add(b, "]", NULL);
|
||||
|
||||
|
|
@ -340,23 +341,25 @@ static int core_demarshal_client_update(void *object, void *data, size_t size)
|
|||
static int core_demarshal_permissions(void *object, void *data, size_t size)
|
||||
{
|
||||
struct pw_resource *resource = object;
|
||||
struct spa_dict props;
|
||||
struct spa_pod_parser prs;
|
||||
uint32_t i;
|
||||
struct pw_permission *permissions;
|
||||
uint32_t i, n_permissions;
|
||||
|
||||
spa_pod_parser_init(&prs, data, size, 0);
|
||||
if (spa_pod_parser_get(&prs, "[ i", &props.n_items, NULL) < 0)
|
||||
if (spa_pod_parser_get(&prs, "[",
|
||||
"i", &n_permissions, NULL) < 0)
|
||||
return -EINVAL;
|
||||
|
||||
props.items = alloca(props.n_items * sizeof(struct spa_dict_item));
|
||||
for (i = 0; i < props.n_items; i++) {
|
||||
permissions = alloca(n_permissions * sizeof(struct pw_permission));
|
||||
for (i = 0; i < n_permissions; i++) {
|
||||
if (spa_pod_parser_get(&prs,
|
||||
"s", &props.items[i].key,
|
||||
"s", &props.items[i].value,
|
||||
"i", &permissions[i].id,
|
||||
"i", &permissions[i].permissions,
|
||||
NULL) < 0)
|
||||
return -EINVAL;
|
||||
}
|
||||
pw_resource_do(resource, struct pw_core_proxy_methods, permissions, 0, &props);
|
||||
pw_resource_do(resource, struct pw_core_proxy_methods, permissions, 0,
|
||||
n_permissions, permissions);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
@ -1017,24 +1020,23 @@ static int client_demarshal_info(void *object, void *data, size_t size)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static void client_marshal_permissions(void *object, const struct spa_dict *dict)
|
||||
static void client_marshal_permissions(void *object, uint32_t index, uint32_t n_permissions,
|
||||
struct pw_permission *permissions)
|
||||
{
|
||||
struct pw_resource *resource = object;
|
||||
struct spa_pod_builder *b;
|
||||
uint32_t i, n_items;
|
||||
uint32_t i;
|
||||
|
||||
b = pw_protocol_native_begin_resource(resource, PW_CLIENT_PROXY_EVENT_PERMISSIONS);
|
||||
|
||||
n_items = dict ? dict->n_items : 0;
|
||||
|
||||
spa_pod_builder_add(b,
|
||||
"[",
|
||||
"i", n_items, NULL);
|
||||
"[ i", index,
|
||||
"i", n_permissions, NULL);
|
||||
|
||||
for (i = 0; i < n_items; i++) {
|
||||
for (i = 0; i < n_permissions; i++) {
|
||||
spa_pod_builder_add(b,
|
||||
"s", dict->items[i].key,
|
||||
"s", dict->items[i].value, NULL);
|
||||
"s", permissions[i].id,
|
||||
"s", permissions[i].permissions, NULL);
|
||||
}
|
||||
spa_pod_builder_add(b, "]", NULL);
|
||||
|
||||
|
|
@ -1044,23 +1046,24 @@ static void client_marshal_permissions(void *object, const struct spa_dict *dict
|
|||
static int client_demarshal_permissions(void *object, void *data, size_t size)
|
||||
{
|
||||
struct pw_proxy *proxy = object;
|
||||
struct spa_dict props;
|
||||
struct pw_permission *permissions;
|
||||
struct spa_pod_parser prs;
|
||||
uint32_t i;
|
||||
uint32_t i, index, n_permissions;
|
||||
|
||||
spa_pod_parser_init(&prs, data, size, 0);
|
||||
if (spa_pod_parser_get(&prs, "[ i", &props.n_items, NULL) < 0)
|
||||
if (spa_pod_parser_get(&prs, "[ i", &index,
|
||||
"i", &n_permissions, NULL) < 0)
|
||||
return -EINVAL;
|
||||
|
||||
props.items = alloca(props.n_items * sizeof(struct spa_dict_item));
|
||||
for (i = 0; i < props.n_items; i++) {
|
||||
permissions = alloca(n_permissions * sizeof(struct pw_permission));
|
||||
for (i = 0; i < n_permissions; i++) {
|
||||
if (spa_pod_parser_get(&prs,
|
||||
"s", &props.items[i].key,
|
||||
"s", &props.items[i].value,
|
||||
"i", &permissions[i].id,
|
||||
"i", &permissions[i].permissions,
|
||||
NULL) < 0)
|
||||
return -EINVAL;
|
||||
}
|
||||
pw_proxy_notify(proxy, struct pw_client_proxy_events, permissions, 0, &props);
|
||||
pw_proxy_notify(proxy, struct pw_client_proxy_events, permissions, 0, index, n_permissions, permissions);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
@ -1095,14 +1098,16 @@ static int client_demarshal_error(void *object, void *data, size_t size)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static void client_marshal_get_permissions(void *object)
|
||||
static void client_marshal_get_permissions(void *object, uint32_t index, uint32_t num)
|
||||
{
|
||||
struct pw_proxy *proxy = object;
|
||||
struct spa_pod_builder *b;
|
||||
|
||||
b = pw_protocol_native_begin_proxy(proxy, PW_CLIENT_PROXY_METHOD_GET_PERMISSIONS);
|
||||
|
||||
spa_pod_builder_add_struct(b, "P", NULL);
|
||||
spa_pod_builder_add_struct(b,
|
||||
"i", index,
|
||||
"i", num, NULL);
|
||||
|
||||
pw_protocol_native_end_proxy(proxy, b);
|
||||
}
|
||||
|
|
@ -1111,32 +1116,33 @@ static int client_demarshal_get_permissions(void *object, void *data, size_t siz
|
|||
{
|
||||
struct pw_resource *resource = object;
|
||||
struct spa_pod_parser prs;
|
||||
void *ptr;
|
||||
uint32_t index, num;
|
||||
|
||||
spa_pod_parser_init(&prs, data, size, 0);
|
||||
if (spa_pod_parser_get(&prs, "[P]", &ptr, NULL) < 0)
|
||||
if (spa_pod_parser_get(&prs,
|
||||
"[i", &index,
|
||||
"i", &num, NULL) < 0)
|
||||
return -EINVAL;
|
||||
|
||||
pw_resource_do(resource, struct pw_client_proxy_methods, get_permissions, 0);
|
||||
pw_resource_do(resource, struct pw_client_proxy_methods, get_permissions, 0, index, num);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void client_marshal_update_permissions(void *object, const struct spa_dict *props)
|
||||
static void client_marshal_update_permissions(void *object, uint32_t n_permissions,
|
||||
const struct pw_permission *permissions)
|
||||
{
|
||||
struct pw_proxy *proxy = object;
|
||||
struct spa_pod_builder *b;
|
||||
int i, n_items;
|
||||
int i;
|
||||
|
||||
b = pw_protocol_native_begin_proxy(proxy, PW_CLIENT_PROXY_METHOD_UPDATE_PERMISSIONS);
|
||||
|
||||
n_items = props ? props->n_items : 0;
|
||||
spa_pod_builder_add(b, "[ i", n_permissions, NULL);
|
||||
|
||||
spa_pod_builder_add(b, "[ i", n_items, NULL);
|
||||
|
||||
for (i = 0; i < n_items; i++) {
|
||||
for (i = 0; i < n_permissions; i++) {
|
||||
spa_pod_builder_add(b,
|
||||
"s", props->items[i].key,
|
||||
"s", props->items[i].value, NULL);
|
||||
"i", permissions[i].id,
|
||||
"i", permissions[i].permissions, NULL);
|
||||
}
|
||||
spa_pod_builder_add(b, "]", NULL);
|
||||
|
||||
|
|
@ -1146,23 +1152,24 @@ static void client_marshal_update_permissions(void *object, const struct spa_dic
|
|||
static int client_demarshal_update_permissions(void *object, void *data, size_t size)
|
||||
{
|
||||
struct pw_resource *resource = object;
|
||||
struct spa_dict props;
|
||||
struct pw_permission *permissions;
|
||||
struct spa_pod_parser prs;
|
||||
uint32_t i;
|
||||
uint32_t i, n_permissions;
|
||||
|
||||
spa_pod_parser_init(&prs, data, size, 0);
|
||||
if (spa_pod_parser_get(&prs, "[ i", &props.n_items, NULL) < 0)
|
||||
if (spa_pod_parser_get(&prs, "[ i", &n_permissions, NULL) < 0)
|
||||
return -EINVAL;
|
||||
|
||||
props.items = alloca(props.n_items * sizeof(struct spa_dict_item));
|
||||
for (i = 0; i < props.n_items; i++) {
|
||||
permissions = alloca(n_permissions * sizeof(struct pw_permission));
|
||||
for (i = 0; i < n_permissions; i++) {
|
||||
if (spa_pod_parser_get(&prs,
|
||||
"s", &props.items[i].key,
|
||||
"s", &props.items[i].value,
|
||||
"i", &permissions[i].id,
|
||||
"i", &permissions[i].permissions,
|
||||
NULL) < 0)
|
||||
return -EINVAL;
|
||||
}
|
||||
pw_resource_do(resource, struct pw_client_proxy_methods, update_permissions, 0, &props);
|
||||
pw_resource_do(resource, struct pw_client_proxy_methods, update_permissions, 0,
|
||||
n_permissions, permissions);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -27,11 +27,6 @@
|
|||
#include "pipewire/private.h"
|
||||
#include "pipewire/resource.h"
|
||||
|
||||
struct permission {
|
||||
uint32_t id;
|
||||
uint32_t permissions;
|
||||
};
|
||||
|
||||
/** \cond */
|
||||
struct impl {
|
||||
struct pw_client this;
|
||||
|
|
@ -46,40 +41,40 @@ struct resource_data {
|
|||
};
|
||||
|
||||
/** find a specific permission for a global or NULL when there is none */
|
||||
static struct permission *
|
||||
static struct pw_permission *
|
||||
find_permission(struct pw_client *client, uint32_t id)
|
||||
{
|
||||
struct impl *impl = SPA_CONTAINER_OF(client, struct impl, this);
|
||||
struct permission *p;
|
||||
struct pw_permission *p;
|
||||
|
||||
if (!pw_array_check_index(&impl->permissions, id, struct permission))
|
||||
if (!pw_array_check_index(&impl->permissions, id, struct pw_permission))
|
||||
return NULL;
|
||||
|
||||
p = pw_array_get_unchecked(&impl->permissions, id, struct permission);
|
||||
p = pw_array_get_unchecked(&impl->permissions, id, struct pw_permission);
|
||||
if (p->permissions == -1)
|
||||
return NULL;
|
||||
else
|
||||
return p;
|
||||
}
|
||||
|
||||
static struct permission *ensure_permissions(struct pw_client *client, uint32_t id)
|
||||
static struct pw_permission *ensure_permissions(struct pw_client *client, uint32_t id)
|
||||
{
|
||||
struct impl *impl = SPA_CONTAINER_OF(client, struct impl, this);
|
||||
struct permission *p;
|
||||
struct pw_permission *p;
|
||||
size_t len, i;
|
||||
|
||||
len = pw_array_get_len(&impl->permissions, struct permission);
|
||||
len = pw_array_get_len(&impl->permissions, struct pw_permission);
|
||||
if (len <= id) {
|
||||
size_t diff = id - len + 1;
|
||||
|
||||
p = pw_array_add(&impl->permissions, diff * sizeof(struct permission));
|
||||
p = pw_array_add(&impl->permissions, diff * sizeof(struct pw_permission));
|
||||
if (p == NULL)
|
||||
return NULL;
|
||||
|
||||
for (i = 0; i < diff; i++)
|
||||
p[i].permissions = -1;
|
||||
}
|
||||
p = pw_array_get_unchecked(&impl->permissions, id, struct permission);
|
||||
p = pw_array_get_unchecked(&impl->permissions, id, struct pw_permission);
|
||||
return p;
|
||||
}
|
||||
|
||||
|
|
@ -90,7 +85,7 @@ client_permission_func(struct pw_global *global,
|
|||
struct pw_client *client, void *data)
|
||||
{
|
||||
struct impl *impl = data;
|
||||
struct permission *p;
|
||||
struct pw_permission *p;
|
||||
|
||||
p = find_permission(client, global->id);
|
||||
if (p == NULL)
|
||||
|
|
@ -99,26 +94,6 @@ client_permission_func(struct pw_global *global,
|
|||
return p->permissions;
|
||||
}
|
||||
|
||||
static uint32_t parse_mask(const char *str)
|
||||
{
|
||||
uint32_t mask = 0;
|
||||
|
||||
while (*str != '\0') {
|
||||
switch (*str++) {
|
||||
case 'r':
|
||||
mask |= PW_PERM_R;
|
||||
break;
|
||||
case 'w':
|
||||
mask |= PW_PERM_W;
|
||||
break;
|
||||
case 'x':
|
||||
mask |= PW_PERM_X;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return mask;
|
||||
}
|
||||
|
||||
static void client_error(void *object, uint32_t id, int res, const char *error)
|
||||
{
|
||||
struct pw_resource *resource = object;
|
||||
|
|
@ -127,65 +102,21 @@ static void client_error(void *object, uint32_t id, int res, const char *error)
|
|||
pw_resource_error(client->core_resource, id, res, error);
|
||||
}
|
||||
|
||||
static void client_get_permissions(void *object)
|
||||
static void client_get_permissions(void *object, uint32_t index, uint32_t num)
|
||||
{
|
||||
struct pw_resource *resource = object;
|
||||
struct resource_data *data = pw_resource_get_user_data(resource);
|
||||
struct pw_client *client = data->client;
|
||||
pw_log_debug("client %p", client);
|
||||
}
|
||||
|
||||
static void client_update_permissions(void *object, const struct spa_dict *props)
|
||||
static void client_update_permissions(void *object,
|
||||
uint32_t n_permissions, const struct pw_permission *permissions)
|
||||
{
|
||||
struct pw_resource *resource = object;
|
||||
struct resource_data *data = pw_resource_get_user_data(resource);
|
||||
struct pw_client *client = data->client;
|
||||
struct impl *impl = SPA_CONTAINER_OF(client, struct impl, this);
|
||||
const char *str;
|
||||
int i, len;
|
||||
|
||||
for (i = 0; i < props->n_items; i++) {
|
||||
str = props->items[i].value;
|
||||
|
||||
pw_log_debug("client %p: %s %s", client, props->items[i].key, str);
|
||||
|
||||
if (strcmp(props->items[i].key, PW_CORE_PROXY_PERMISSIONS_DEFAULT) == 0) {
|
||||
impl->permissions_default = parse_mask(str);
|
||||
pw_log_debug("client %p: set default permissions to %08x",
|
||||
client, impl->permissions_default);
|
||||
}
|
||||
else if (strcmp(props->items[i].key, PW_CORE_PROXY_PERMISSIONS_GLOBAL) == 0) {
|
||||
struct pw_global *global;
|
||||
uint32_t global_id, old_perm, new_perm;
|
||||
struct permission *p;
|
||||
|
||||
/* permissions.update=<global-id>:[r][w][x] */
|
||||
len = strcspn(str, ":");
|
||||
if (len == 0)
|
||||
continue;
|
||||
|
||||
global_id = atoi(str);
|
||||
global = pw_core_find_global(client->core, global_id);
|
||||
if (global == NULL) {
|
||||
pw_log_warn("client %p: invalid global %d", client, global_id);
|
||||
continue;
|
||||
}
|
||||
|
||||
p = ensure_permissions(client, global_id);
|
||||
old_perm = p->permissions == -1 ? impl->permissions_default : p->permissions;
|
||||
new_perm = parse_mask(str + len);
|
||||
|
||||
pw_log_debug("client %p: %08x %08x", client, old_perm, new_perm);
|
||||
|
||||
p->permissions = new_perm;
|
||||
|
||||
if (PW_PERM_IS_R(old_perm) && !PW_PERM_IS_R(new_perm)) {
|
||||
pw_global_revoke(global, client);
|
||||
}
|
||||
else if (!PW_PERM_IS_R(old_perm) && PW_PERM_IS_R(new_perm)) {
|
||||
pw_global_grant(global, client);
|
||||
}
|
||||
}
|
||||
}
|
||||
pw_client_update_permissions(client, n_permissions, permissions);
|
||||
pw_client_set_busy(client, false);
|
||||
}
|
||||
|
||||
|
|
@ -246,7 +177,7 @@ core_global_removed(void *data, struct pw_global *global)
|
|||
{
|
||||
struct impl *impl = data;
|
||||
struct pw_client *client = &impl->this;
|
||||
struct permission *p;
|
||||
struct pw_permission *p;
|
||||
|
||||
p = find_permission(client, global->id);
|
||||
pw_log_debug("client %p: global %d removed, %p", client, global->id, p);
|
||||
|
|
@ -492,91 +423,61 @@ int pw_client_update_properties(struct pw_client *client, const struct spa_dict
|
|||
return changed;
|
||||
}
|
||||
|
||||
struct permissions_update {
|
||||
struct pw_client *client;
|
||||
uint32_t permissions;
|
||||
bool only_new;
|
||||
};
|
||||
|
||||
static int do_permissions(void *data, struct pw_global *global)
|
||||
{
|
||||
struct permissions_update *update = data;
|
||||
struct pw_client *client = update->client;
|
||||
struct impl *impl = SPA_CONTAINER_OF(client, struct impl, this);
|
||||
struct permission *p;
|
||||
|
||||
p = ensure_permissions(client, global->id);
|
||||
if (p == NULL)
|
||||
return -ENOMEM;
|
||||
if (p->permissions == -1)
|
||||
p->permissions = impl->permissions_default;
|
||||
else if (update->only_new)
|
||||
return 0;
|
||||
|
||||
p->permissions &= update->permissions;
|
||||
pw_log_debug("client %p: set global %d permissions to %08x", client, global->id, p->permissions);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int pw_client_update_permissions(struct pw_client *client, const struct spa_dict *dict)
|
||||
int pw_client_update_permissions(struct pw_client *client,
|
||||
uint32_t n_permissions, const struct pw_permission *permissions)
|
||||
{
|
||||
struct impl *impl = SPA_CONTAINER_OF(client, struct impl, this);
|
||||
struct pw_core *core = client->core;
|
||||
int i;
|
||||
const char *str;
|
||||
size_t len;
|
||||
struct permissions_update update = { client, 0 };
|
||||
uint32_t permissions_existing, permissions_default;
|
||||
|
||||
permissions_default = impl->permissions_default;
|
||||
permissions_existing = -1;
|
||||
|
||||
for (i = 0; i < dict->n_items; i++) {
|
||||
str = dict->items[i].value;
|
||||
|
||||
if (strcmp(dict->items[i].key, PW_CORE_PROXY_PERMISSIONS_DEFAULT) == 0) {
|
||||
permissions_default &= parse_mask(str);
|
||||
pw_log_debug("client %p: set default permissions to %08x",
|
||||
client, permissions_default);
|
||||
}
|
||||
else if (strcmp(dict->items[i].key, PW_CORE_PROXY_PERMISSIONS_GLOBAL) == 0) {
|
||||
for (i = 0; i < n_permissions; i++) {
|
||||
struct pw_permission *p;
|
||||
uint32_t old_perm, new_perm;
|
||||
struct pw_global *global;
|
||||
uint32_t global_id;
|
||||
|
||||
/* permissions.update=<global-id>:[r][w][x] */
|
||||
len = strcspn(str, ":");
|
||||
if (len == 0)
|
||||
if (permissions[i].id == SPA_ID_INVALID) {
|
||||
old_perm = impl->permissions_default;
|
||||
new_perm = permissions[i].permissions;
|
||||
|
||||
if (core->current_client == client)
|
||||
new_perm &= old_perm;
|
||||
|
||||
pw_log_debug("client %p: set default permissions %08x -> %08x",
|
||||
client, old_perm, new_perm);
|
||||
|
||||
spa_list_for_each(global, &core->global_list, link) {
|
||||
p = find_permission(client, global->id);
|
||||
if (p != NULL)
|
||||
continue;
|
||||
|
||||
global_id = atoi(str);
|
||||
global = pw_core_find_global(client->core, global_id);
|
||||
pw_global_update_permissions(global, client, old_perm, new_perm);
|
||||
}
|
||||
impl->permissions_default = new_perm;
|
||||
}
|
||||
else {
|
||||
struct pw_global *global;
|
||||
|
||||
global = pw_core_find_global(client->core, permissions[i].id);
|
||||
if (global == NULL) {
|
||||
pw_log_warn("client %p: invalid global %d", client, global_id);
|
||||
pw_log_warn("client %p: invalid global %d", client, permissions[i].id);
|
||||
continue;
|
||||
}
|
||||
p = ensure_permissions(client, global->id);
|
||||
old_perm = p->permissions == -1 ? impl->permissions_default : p->permissions;
|
||||
new_perm = permissions[i].permissions;
|
||||
|
||||
/* apply the specific updates in order. This is ok for now, we could add
|
||||
* a field to the permission struct later to accumulate the changes
|
||||
* and apply them out of this loop */
|
||||
update.permissions = parse_mask(str + len);
|
||||
update.only_new = false;
|
||||
do_permissions(&update, global);
|
||||
}
|
||||
else if (strcmp(dict->items[i].key, PW_CORE_PROXY_PERMISSIONS_EXISTING) == 0) {
|
||||
permissions_existing = parse_mask(str);
|
||||
pw_log_debug("client %p: set existing permissions to %08x",
|
||||
client, permissions_existing);
|
||||
}
|
||||
}
|
||||
/* apply default and existing permissions after specific ones to make the
|
||||
* permission update look like an atomic unordered set of changes. */
|
||||
if (permissions_existing != -1) {
|
||||
update.permissions = permissions_existing;
|
||||
update.only_new = true;
|
||||
pw_core_for_each_global(client->core, do_permissions, &update);
|
||||
}
|
||||
impl->permissions_default = permissions_default;
|
||||
if (core->current_client == client)
|
||||
new_perm &= old_perm;
|
||||
|
||||
pw_log_debug("client %p: set global %d permissions %08x -> %08x",
|
||||
client, global->id, old_perm, new_perm);
|
||||
|
||||
pw_global_update_permissions(global, client, old_perm, new_perm);
|
||||
p->permissions = new_perm;
|
||||
}
|
||||
}
|
||||
if (n_permissions > 0)
|
||||
pw_client_set_busy(client, false);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
@ -588,11 +489,3 @@ void pw_client_set_busy(struct pw_client *client, bool busy)
|
|||
pw_client_events_busy_changed(client, busy);
|
||||
}
|
||||
}
|
||||
|
||||
void pw_client_set_permissions(struct pw_client *client, uint32_t permissions)
|
||||
{
|
||||
struct impl *impl = SPA_CONTAINER_OF(client, struct impl, this);
|
||||
pw_log_debug("client %p: permissions %08x", client, permissions);
|
||||
impl->permissions_default = permissions;
|
||||
pw_client_set_busy(client, false);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -49,6 +49,7 @@ struct pw_client;
|
|||
#include <pipewire/introspect.h>
|
||||
#include <pipewire/properties.h>
|
||||
#include <pipewire/resource.h>
|
||||
#include <pipewire/permission.h>
|
||||
|
||||
#define PW_TYPE__Client PW_TYPE_OBJECT_BASE "Client"
|
||||
#define PW_TYPE_CLIENT_BASE PW_TYPE__Client ":"
|
||||
|
|
@ -146,7 +147,8 @@ const struct pw_client_info *pw_client_get_info(struct pw_client *client);
|
|||
int pw_client_update_properties(struct pw_client *client, const struct spa_dict *dict);
|
||||
|
||||
/** Update the client permissions */
|
||||
int pw_client_update_permissions(struct pw_client *client, const struct spa_dict *dict);
|
||||
int pw_client_update_permissions(struct pw_client *client, uint32_t n_permissions,
|
||||
const struct pw_permission *permissions);
|
||||
|
||||
/** Get the client properties */
|
||||
const struct pw_properties *pw_client_get_properties(struct pw_client *client);
|
||||
|
|
@ -177,8 +179,6 @@ void pw_client_add_listener(struct pw_client *client,
|
|||
* started and no further processing is allowed to happen for the client */
|
||||
void pw_client_set_busy(struct pw_client *client, bool busy);
|
||||
|
||||
void pw_client_set_permissions(struct pw_client *client, uint32_t permissions);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -64,11 +64,11 @@ static void registry_bind(void *object, uint32_t id,
|
|||
if (!PW_PERM_IS_R(permissions))
|
||||
goto no_id;
|
||||
|
||||
if (type != global->type)
|
||||
if (global->type != type)
|
||||
goto wrong_interface;
|
||||
|
||||
pw_log_debug("global %p: bind global id %d, iface %s to %d", global, id,
|
||||
spa_debug_type_find_name(pw_type_info(), type), new_id);
|
||||
pw_log_debug("global %p: bind global id %d, iface %s/%d to %d", global, id,
|
||||
spa_debug_type_find_name(pw_type_info(), type), version, new_id);
|
||||
|
||||
if (pw_global_bind(global, client, permissions, version, new_id) < 0)
|
||||
goto exit;
|
||||
|
|
@ -77,9 +77,13 @@ static void registry_bind(void *object, uint32_t id,
|
|||
|
||||
no_id:
|
||||
pw_log_debug("registry %p: no global with id %u to bind to %u", resource, id, new_id);
|
||||
pw_core_resource_error(client->core_resource, id,
|
||||
-ENOENT, "no such global %u", id);
|
||||
goto exit;
|
||||
wrong_interface:
|
||||
pw_log_debug("registry %p: global with id %u has no interface %u", resource, id, type);
|
||||
pw_core_resource_error(client->core_resource, id,
|
||||
-ENOENT, "no such interface %u", type);
|
||||
goto exit;
|
||||
exit:
|
||||
/* unmark the new_id the map, the client does not yet know about the failed
|
||||
|
|
@ -151,10 +155,11 @@ static void core_client_update(void *object, const struct spa_dict *props)
|
|||
pw_client_update_properties(resource->client, props);
|
||||
}
|
||||
|
||||
static void core_permissions(void *object, const struct spa_dict *props)
|
||||
static void core_permissions(void *object, uint32_t n_permissions,
|
||||
const struct pw_permission *permissions)
|
||||
{
|
||||
struct pw_resource *resource = object;
|
||||
pw_client_update_permissions(resource->client, props);
|
||||
pw_client_update_permissions(resource->client, n_permissions, permissions);
|
||||
}
|
||||
|
||||
static void core_sync(void *object, uint32_t seq)
|
||||
|
|
|
|||
|
|
@ -73,16 +73,6 @@ struct pw_core;
|
|||
* resources of a PipeWire instance.
|
||||
*/
|
||||
|
||||
#define PW_PERM_R 0400 /**< object can be seen and events can be received */
|
||||
#define PW_PERM_W 0200 /**< methods can be called that modify the object */
|
||||
#define PW_PERM_X 0100 /**< methods can be called on the object. The W flag must be
|
||||
* present in order to call methods that modify the object. */
|
||||
#define PW_PERM_RWX (PW_PERM_R|PW_PERM_W|PW_PERM_X)
|
||||
|
||||
#define PW_PERM_IS_R(p) (((p)&PW_PERM_R) == PW_PERM_R)
|
||||
#define PW_PERM_IS_W(p) (((p)&PW_PERM_W) == PW_PERM_W)
|
||||
#define PW_PERM_IS_X(p) (((p)&PW_PERM_X) == PW_PERM_X)
|
||||
|
||||
/** core events emited by the core object added with \ref pw_core_add_listener */
|
||||
struct pw_core_events {
|
||||
#define PW_VERSION_CORE_EVENTS 0
|
||||
|
|
|
|||
|
|
@ -147,17 +147,19 @@ static int global_unregister(struct pw_global *global)
|
|||
{
|
||||
struct impl *impl = SPA_CONTAINER_OF(global, struct impl, this);
|
||||
struct pw_core *core = global->core;
|
||||
struct pw_resource *registry;
|
||||
struct pw_resource *resource;
|
||||
|
||||
if (!impl->registered)
|
||||
return 0;
|
||||
|
||||
spa_list_for_each(registry, &core->registry_resource_list, link) {
|
||||
uint32_t permissions = pw_global_get_permissions(global, registry->client);
|
||||
pw_log_debug("registry %p: global %d %08x", registry, global->id, permissions);
|
||||
spa_list_for_each(resource, &core->registry_resource_list, link) {
|
||||
uint32_t permissions = pw_global_get_permissions(global, resource->client);
|
||||
pw_log_debug("registry %p: global %d %08x", resource, global->id, permissions);
|
||||
if (PW_PERM_IS_R(permissions))
|
||||
pw_registry_resource_global_remove(registry, global->id);
|
||||
pw_registry_resource_global_remove(resource, global->id);
|
||||
}
|
||||
spa_list_consume(resource, &global->resource_list, link)
|
||||
pw_resource_destroy(resource);
|
||||
|
||||
spa_list_remove(&global->link);
|
||||
pw_core_events_global_removed(core, global);
|
||||
|
|
@ -220,11 +222,11 @@ void pw_global_add_listener(struct pw_global *global,
|
|||
* \param global the global to bind to
|
||||
* \param client the client that binds
|
||||
* \param version the version
|
||||
* \param id the id
|
||||
* \param id the id of the resource
|
||||
*
|
||||
* Let \a client bind to \a global with the given version and id.
|
||||
* After binding, the client and the global object will be able to
|
||||
* exchange messages.
|
||||
* exchange messages on the proxy/resource with \a id.
|
||||
*
|
||||
* \memberof pw_global
|
||||
*/
|
||||
|
|
@ -249,47 +251,39 @@ pw_global_bind(struct pw_global *global, struct pw_client *client, uint32_t perm
|
|||
return res;
|
||||
}
|
||||
|
||||
int pw_global_grant(struct pw_global *global, struct pw_client *client)
|
||||
int pw_global_update_permissions(struct pw_global *global, struct pw_client *client,
|
||||
uint32_t old_permissions, uint32_t new_permissions)
|
||||
{
|
||||
struct pw_resource *registry;
|
||||
struct pw_core *core = global->core;
|
||||
struct pw_resource *resource, *t;
|
||||
|
||||
spa_list_for_each(registry, &core->registry_resource_list, link) {
|
||||
uint32_t permissions;
|
||||
|
||||
if (registry->client != client)
|
||||
spa_list_for_each(resource, &core->registry_resource_list, link) {
|
||||
if (resource->client != client)
|
||||
continue;
|
||||
|
||||
permissions = pw_global_get_permissions(global, client);
|
||||
|
||||
pw_log_debug("registry %p: global %d %08x", registry, global->id, permissions);
|
||||
if (PW_PERM_IS_R(permissions))
|
||||
pw_registry_resource_global(registry,
|
||||
if (PW_PERM_IS_R(old_permissions) && !PW_PERM_IS_R(new_permissions)) {
|
||||
pw_registry_resource_global_remove(resource, global->id);
|
||||
}
|
||||
else if (!PW_PERM_IS_R(old_permissions) && PW_PERM_IS_R(new_permissions)) {
|
||||
pw_registry_resource_global(resource,
|
||||
global->id,
|
||||
global->parent->id,
|
||||
permissions,
|
||||
new_permissions,
|
||||
global->type,
|
||||
global->version,
|
||||
global->properties ?
|
||||
&global->properties->dict : NULL);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int pw_global_revoke(struct pw_global *global, struct pw_client *client)
|
||||
{
|
||||
struct pw_resource *registry, *resource, *t;
|
||||
struct pw_core *core = global->core;
|
||||
|
||||
spa_list_for_each(registry, &core->registry_resource_list, link) {
|
||||
if (registry->client != client)
|
||||
continue;
|
||||
pw_registry_resource_global_remove(registry, global->id);
|
||||
}
|
||||
spa_list_for_each_safe(resource, t, &global->resource_list, link) {
|
||||
if (resource->client != client)
|
||||
continue;
|
||||
|
||||
/* don't ever destroy the core resource */
|
||||
if (!PW_PERM_IS_R(new_permissions) && global->id != 0)
|
||||
pw_resource_destroy(resource);
|
||||
else
|
||||
resource->permissions = new_permissions;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -128,13 +128,8 @@ int pw_global_bind(struct pw_global *global,
|
|||
uint32_t version,
|
||||
uint32_t id);
|
||||
|
||||
/** Revoke access to global for client, the global will be removed from
|
||||
* the client registry and all the bound resources for the client will be
|
||||
* destroyed */
|
||||
int pw_global_revoke(struct pw_global *global, struct pw_client *client);
|
||||
/** Grant access to a global for client. The client registry will be
|
||||
* notified of a new global */
|
||||
int pw_global_grant(struct pw_global *global, struct pw_client *client);
|
||||
int pw_global_update_permissions(struct pw_global *global, struct pw_client *client,
|
||||
uint32_t old_permissions, uint32_t new_permissions);
|
||||
|
||||
/** Destroy a global */
|
||||
void pw_global_destroy(struct pw_global *global);
|
||||
|
|
|
|||
|
|
@ -30,6 +30,7 @@ extern "C" {
|
|||
|
||||
#include <pipewire/introspect.h>
|
||||
#include <pipewire/proxy.h>
|
||||
#include <pipewire/permission.h>
|
||||
|
||||
struct pw_core_proxy;
|
||||
struct pw_registry_proxy;
|
||||
|
|
@ -143,18 +144,21 @@ struct pw_core_proxy_methods {
|
|||
*/
|
||||
void (*client_update) (void *object, const struct spa_dict *props);
|
||||
/**
|
||||
* Manage the permissions of the global objects
|
||||
* Manage the permissions of the global objects for this
|
||||
* client
|
||||
*
|
||||
* Update the permissions of the global objects using the
|
||||
* dictionary with properties.
|
||||
* provided array with permissions
|
||||
*
|
||||
* Globals can use the default permissions or can have specific
|
||||
* permissions assigned to them.
|
||||
*
|
||||
* \param id the global id to change
|
||||
* \param props dictionary with permission properties
|
||||
* \param n_permissions number of permissions
|
||||
* \param permissions array of permissions
|
||||
*/
|
||||
void (*permissions) (void *object, const struct spa_dict *props);
|
||||
void (*permissions) (void *object,
|
||||
uint32_t n_permissions,
|
||||
const struct pw_permission *permissions);
|
||||
/**
|
||||
* Create a new object on the PipeWire server from a factory.
|
||||
* Use a \a factory_name of "client-node" to create a
|
||||
|
|
@ -209,9 +213,9 @@ pw_core_proxy_client_update(struct pw_core_proxy *core, const struct spa_dict *p
|
|||
}
|
||||
|
||||
static inline void
|
||||
pw_core_proxy_permissions(struct pw_core_proxy *core, const struct spa_dict *props)
|
||||
pw_core_proxy_permissions(struct pw_core_proxy *core, uint32_t n_permissions, struct pw_permission *permissions)
|
||||
{
|
||||
pw_proxy_do((struct pw_proxy*)core, struct pw_core_proxy_methods, permissions, props);
|
||||
pw_proxy_do((struct pw_proxy*)core, struct pw_core_proxy_methods, permissions, n_permissions, permissions);
|
||||
}
|
||||
|
||||
static inline void *
|
||||
|
|
@ -696,9 +700,15 @@ struct pw_client_proxy_events {
|
|||
*
|
||||
* Event emited as a result of the get_permissions method.
|
||||
*
|
||||
* \param param the parameter
|
||||
* \param default_permissions the default permissions
|
||||
* \param index the index of the first permission entry
|
||||
* \param n_permissions the number of permissions
|
||||
* \param permissions the permissions
|
||||
*/
|
||||
void (*permissions) (void *object, const struct spa_dict *dict);
|
||||
void (*permissions) (void *object,
|
||||
uint32_t index,
|
||||
uint32_t n_permissions,
|
||||
struct pw_permission *permissions);
|
||||
};
|
||||
|
||||
/** Client */
|
||||
|
|
@ -736,15 +746,20 @@ struct pw_client_proxy_methods {
|
|||
* Get client permissions
|
||||
*
|
||||
* A permissions event will be emited with the permissions.
|
||||
*
|
||||
* \param index the first index to query, 0 for first
|
||||
* \param num the maximum number of items to get
|
||||
*/
|
||||
void (*get_permissions) (void *object);
|
||||
void (*get_permissions) (void *object, uint32_t index, uint32_t num);
|
||||
|
||||
/**
|
||||
* Update client permissions
|
||||
*
|
||||
* \param dict list of permissions to update
|
||||
* \param n_permissions number of permissions
|
||||
* \param permissions array of new permissions
|
||||
*/
|
||||
void (*update_permissions) (void *object, const struct spa_dict *dict);
|
||||
void (*update_permissions) (void *object, uint32_t n_permissions,
|
||||
const struct pw_permission *permissions);
|
||||
};
|
||||
|
||||
/** Client permissions */
|
||||
|
|
@ -755,15 +770,17 @@ pw_client_proxy_error(struct pw_client_proxy *client, uint32_t id, int res, cons
|
|||
}
|
||||
|
||||
static inline void
|
||||
pw_client_proxy_get_permissions(struct pw_client_proxy *client)
|
||||
pw_client_proxy_get_permissions(struct pw_client_proxy *client, uint32_t index, uint32_t num)
|
||||
{
|
||||
pw_proxy_do((struct pw_proxy*)client, struct pw_client_proxy_methods, get_permissions);
|
||||
pw_proxy_do((struct pw_proxy*)client, struct pw_client_proxy_methods, get_permissions, index, num);
|
||||
}
|
||||
|
||||
static inline void
|
||||
pw_client_proxy_update_permissions(struct pw_client_proxy *client, const struct spa_dict *dict)
|
||||
pw_client_proxy_update_permissions(struct pw_client_proxy *client, uint32_t n_permissions,
|
||||
const struct pw_permission *permissions)
|
||||
{
|
||||
pw_proxy_do((struct pw_proxy*)client, struct pw_client_proxy_methods, update_permissions, dict);
|
||||
pw_proxy_do((struct pw_proxy*)client, struct pw_client_proxy_methods, update_permissions,
|
||||
n_permissions, permissions);
|
||||
}
|
||||
|
||||
#define PW_VERSION_LINK 0
|
||||
|
|
|
|||
60
src/pipewire/permission.h
Normal file
60
src/pipewire/permission.h
Normal file
|
|
@ -0,0 +1,60 @@
|
|||
/* PipeWire
|
||||
* Copyright (C) 2015 Wim Taymans <wim.taymans@gmail.com>
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Library General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Library General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Library General Public
|
||||
* License along with this library; if not, write to the
|
||||
* Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
|
||||
* Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
#ifndef __PIPEWIRE_PERMISSION_H__
|
||||
#define __PIPEWIRE_PERMISSION_H__
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include <spa/utils/defs.h>
|
||||
|
||||
/** \class pw_permission
|
||||
*
|
||||
* \brief a PipeWire permission
|
||||
*
|
||||
* Permissions are kept for a client and describe what the client is
|
||||
* allowed to do with an object.
|
||||
*
|
||||
* See \ref page_core_api
|
||||
*/
|
||||
|
||||
#define PW_PERM_R 0400 /**< object can be seen and events can be received */
|
||||
#define PW_PERM_W 0200 /**< methods can be called that modify the object */
|
||||
#define PW_PERM_X 0100 /**< methods can be called on the object. The W flag must be
|
||||
* present in order to call methods that modify the object. */
|
||||
#define PW_PERM_RWX (PW_PERM_R|PW_PERM_W|PW_PERM_X)
|
||||
|
||||
#define PW_PERM_IS_R(p) (((p)&PW_PERM_R) == PW_PERM_R)
|
||||
#define PW_PERM_IS_W(p) (((p)&PW_PERM_W) == PW_PERM_W)
|
||||
#define PW_PERM_IS_X(p) (((p)&PW_PERM_X) == PW_PERM_X)
|
||||
|
||||
struct pw_permission {
|
||||
uint32_t id; /**< id of object, SPA_ID_INVALID for default permission */
|
||||
uint32_t permissions; /**< bitmask of above permissions */
|
||||
};
|
||||
|
||||
#define PW_PERMISSION_INIT(id,p) (struct pw_permission){ (id), (p) }
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* __PIPEWIRE_PERMISSION_H__ */
|
||||
|
|
@ -32,6 +32,7 @@
|
|||
#include <pipewire/command.h>
|
||||
#include <pipewire/interfaces.h>
|
||||
#include <pipewire/type.h>
|
||||
#include <pipewire/permission.h>
|
||||
|
||||
static const char WHITESPACE[] = " \t";
|
||||
|
||||
|
|
@ -1164,15 +1165,15 @@ static bool do_port_params(struct data *data, const char *cmd, char *args, char
|
|||
static bool do_permissions(struct data *data, const char *cmd, char *args, char **error)
|
||||
{
|
||||
struct remote_data *rd = data->current;
|
||||
char *a[2];
|
||||
char *a[3];
|
||||
int n;
|
||||
uint32_t id;
|
||||
struct global *global;
|
||||
struct spa_dict_item items[1];
|
||||
struct pw_permission permissions[1];
|
||||
|
||||
n = pw_split_ip(args, WHITESPACE, 2, a);
|
||||
if (n < 2) {
|
||||
asprintf(error, "%s <client-id> <permission>", cmd);
|
||||
n = pw_split_ip(args, WHITESPACE, 3, a);
|
||||
if (n < 3) {
|
||||
asprintf(error, "%s <client-id> <object> <permission>", cmd);
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
@ -1191,9 +1192,11 @@ static bool do_permissions(struct data *data, const char *cmd, char *args, char
|
|||
return false;
|
||||
}
|
||||
|
||||
items[0] = SPA_DICT_ITEM_INIT(PW_CORE_PROXY_PERMISSIONS_GLOBAL, a[1]);
|
||||
|
||||
permissions[0] = PW_PERMISSION_INIT(atoi(a[1]), atoi(a[2]));
|
||||
|
||||
pw_client_proxy_update_permissions((struct pw_client_proxy*)global->proxy,
|
||||
&SPA_DICT_INIT(items, 1));
|
||||
1, permissions);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue