chiark / gitweb /
unit: use weaker dependencies between mount and device units in --user mode
[elogind.git] / src / core / bus-endpoint.c
1 /***
2   This file is part of systemd.
3
4   Copyright 2014 Daniel Mack
5
6   systemd is free software; you can redistribute it and/or modify it
7   under the terms of the GNU Lesser General Public License as published by
8   the Free Software Foundation; either version 2.1 of the License, or
9   (at your option) any later version.
10
11   systemd is distributed in the hope that it will be useful, but
12   WITHOUT ANY WARRANTY; without even the implied warranty of
13   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14   Lesser General Public License for more details.
15
16   You should have received a copy of the GNU Lesser General Public License
17   along with systemd; If not, see <http://www.gnu.org/licenses/>.
18 ***/
19
20 #include <stdlib.h>
21
22 #include "kdbus.h"
23 #include "bus-kernel.h"
24 #include "bus-policy.h"
25 #include "bus-endpoint.h"
26
27 int bus_kernel_set_endpoint_policy(int fd, uid_t uid, BusEndpoint *ep) {
28
29         struct kdbus_cmd *update;
30         struct kdbus_item *n;
31         BusEndpointPolicy *po;
32         Iterator i;
33         size_t size;
34         int r;
35
36         size = ALIGN8(offsetof(struct kdbus_cmd, items));
37
38         HASHMAP_FOREACH(po, ep->policy_hash, i) {
39                 size += ALIGN8(offsetof(struct kdbus_item, str) + strlen(po->name) + 1);
40                 size += ALIGN8(offsetof(struct kdbus_item, policy_access) + sizeof(struct kdbus_policy_access));
41         }
42
43         update = alloca0_align(size, 8);
44         update->size = size;
45
46         n = update->items;
47
48         HASHMAP_FOREACH(po, ep->policy_hash, i) {
49                 n->type = KDBUS_ITEM_NAME;
50                 n->size = offsetof(struct kdbus_item, str) + strlen(po->name) + 1;
51                 strcpy(n->str, po->name);
52                 n = KDBUS_ITEM_NEXT(n);
53
54                 n->type = KDBUS_ITEM_POLICY_ACCESS;
55                 n->size = offsetof(struct kdbus_item, policy_access) + sizeof(struct kdbus_policy_access);
56
57                 n->policy_access.type = KDBUS_POLICY_ACCESS_USER;
58                 n->policy_access.access = bus_kernel_translate_access(po->access);
59                 n->policy_access.id = uid;
60
61                 n = KDBUS_ITEM_NEXT(n);
62         }
63
64         r = ioctl(fd, KDBUS_CMD_ENDPOINT_UPDATE, update);
65         if (r < 0)
66                 return -errno;
67
68         return 0;
69 }
70
71 int bus_endpoint_new(BusEndpoint **ep) {
72         assert(ep);
73
74         *ep = new0(BusEndpoint, 1);
75         if (!*ep)
76                 return -ENOMEM;
77
78         return 0;
79 }
80
81 int bus_endpoint_add_policy(BusEndpoint *ep, const char *name, BusPolicyAccess access) {
82         _cleanup_free_ BusEndpointPolicy *po = NULL;
83         _cleanup_free_ char *key = NULL;
84         int r;
85
86         assert(ep);
87         assert(name);
88         assert(access > _BUS_POLICY_ACCESS_INVALID && access < _BUS_POLICY_ACCESS_MAX);
89
90         /* check if we already have this name in the policy list. If we do, see if the new access level
91          * is higher than the exising one, and upgrade the entry in that case. Otherwise, do nothing.
92          */
93
94         if (ep->policy_hash) {
95                 po = hashmap_get(ep->policy_hash, name);
96                 if (po) {
97                         if (po->access < access)
98                                 po->access = access;
99
100                         return 0;
101                 }
102         } else {
103                 ep->policy_hash = hashmap_new(&string_hash_ops);
104                 if (!ep->policy_hash)
105                         return -ENOMEM;
106         }
107
108         po = new0(BusEndpointPolicy, 1);
109         if (!po)
110                 return -ENOMEM;
111
112         key = strdup(name);
113         if (!key)
114                 return -ENOMEM;
115
116         po->name = key;
117         po->access = access;
118
119         r = hashmap_put(ep->policy_hash, key, po);
120         if (r < 0)
121                 return r;
122
123         po = NULL;
124         key = NULL;
125         return 0;
126 }
127
128 void bus_endpoint_free(BusEndpoint *endpoint) {
129         if (!endpoint)
130                 return;
131
132         hashmap_free_free_free(endpoint->policy_hash);
133         free(endpoint);
134 }