]> git.ipfire.org Git - thirdparty/systemd.git/blob - src/libsystemd/sd-bus/bus-signature.c
libsystemd: split up into subdirs
[thirdparty/systemd.git] / src / libsystemd / sd-bus / bus-signature.c
1 /*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
2
3 /***
4 This file is part of systemd.
5
6 Copyright 2013 Lennart Poettering
7
8 systemd is free software; you can redistribute it and/or modify it
9 under the terms of the GNU Lesser General Public License as published by
10 the Free Software Foundation; either version 2.1 of the License, or
11 (at your option) any later version.
12
13 systemd is distributed in the hope that it will be useful, but
14 WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 Lesser General Public License for more details.
17
18 You should have received a copy of the GNU Lesser General Public License
19 along with systemd; If not, see <http://www.gnu.org/licenses/>.
20 ***/
21
22 #include <util.h>
23
24 #include "bus-signature.h"
25 #include "bus-type.h"
26
27 static int signature_element_length_internal(
28 const char *s,
29 bool allow_dict_entry,
30 unsigned array_depth,
31 unsigned struct_depth,
32 size_t *l) {
33
34 int r;
35
36 if (!s)
37 return -EINVAL;
38
39 assert(l);
40
41 if (bus_type_is_basic(*s) || *s == SD_BUS_TYPE_VARIANT) {
42 *l = 1;
43 return 0;
44 }
45
46 if (*s == SD_BUS_TYPE_ARRAY) {
47 size_t t;
48
49 if (array_depth >= 32)
50 return -EINVAL;
51
52 r = signature_element_length_internal(s + 1, true, array_depth+1, struct_depth, &t);
53 if (r < 0)
54 return r;
55
56 *l = t + 1;
57 return 0;
58 }
59
60 if (*s == SD_BUS_TYPE_STRUCT_BEGIN) {
61 const char *p = s + 1;
62
63 if (struct_depth >= 32)
64 return -EINVAL;
65
66 while (*p != SD_BUS_TYPE_STRUCT_END) {
67 size_t t;
68
69 r = signature_element_length_internal(p, false, array_depth, struct_depth+1, &t);
70 if (r < 0)
71 return r;
72
73 p += t;
74 }
75
76 *l = p - s + 1;
77 return 0;
78 }
79
80 if (*s == SD_BUS_TYPE_DICT_ENTRY_BEGIN && allow_dict_entry) {
81 const char *p = s + 1;
82 unsigned n = 0;
83
84 if (struct_depth >= 32)
85 return -EINVAL;
86
87 while (*p != SD_BUS_TYPE_DICT_ENTRY_END) {
88 size_t t;
89
90 if (n == 0 && !bus_type_is_basic(*p))
91 return -EINVAL;
92
93 r = signature_element_length_internal(p, false, array_depth, struct_depth+1, &t);
94 if (r < 0)
95 return r;
96
97 p += t;
98 n++;
99 }
100
101 if (n != 2)
102 return -EINVAL;
103
104 *l = p - s + 1;
105 return 0;
106 }
107
108 return -EINVAL;
109 }
110
111
112 int signature_element_length(const char *s, size_t *l) {
113 return signature_element_length_internal(s, true, 0, 0, l);
114 }
115
116 bool signature_is_single(const char *s, bool allow_dict_entry) {
117 int r;
118 size_t t;
119
120 if (!s)
121 return false;
122
123 r = signature_element_length_internal(s, allow_dict_entry, 0, 0, &t);
124 if (r < 0)
125 return false;
126
127 return s[t] == 0;
128 }
129
130 bool signature_is_pair(const char *s) {
131
132 if (!s)
133 return false;
134
135 if (!bus_type_is_basic(*s))
136 return false;
137
138 return signature_is_single(s + 1, false);
139 }
140
141 bool signature_is_valid(const char *s, bool allow_dict_entry) {
142 const char *p;
143 int r;
144
145 if (!s)
146 return false;
147
148 p = s;
149 while (*p) {
150 size_t t;
151
152 r = signature_element_length_internal(p, allow_dict_entry, 0, 0, &t);
153 if (r < 0)
154 return false;
155
156 p += t;
157 }
158
159 return p - s <= 255;
160 }