]> git.ipfire.org Git - thirdparty/systemd.git/blame - src/libsystemd/sd-bus/bus-signature.c
Merge pull request #2495 from heftig/master
[thirdparty/systemd.git] / src / libsystemd / sd-bus / bus-signature.c
CommitLineData
de1c301e
LP
1/***
2 This file is part of systemd.
3
4 Copyright 2013 Lennart Poettering
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 <util.h>
21
22#include "bus-signature.h"
23#include "bus-type.h"
24
25static int signature_element_length_internal(
26 const char *s,
27 bool allow_dict_entry,
813a4f93
LP
28 unsigned array_depth,
29 unsigned struct_depth,
de1c301e
LP
30 size_t *l) {
31
32 int r;
33
35460afc
LP
34 if (!s)
35 return -EINVAL;
36
718db961 37 assert(l);
de1c301e
LP
38
39 if (bus_type_is_basic(*s) || *s == SD_BUS_TYPE_VARIANT) {
40 *l = 1;
41 return 0;
42 }
43
44 if (*s == SD_BUS_TYPE_ARRAY) {
45 size_t t;
46
813a4f93
LP
47 if (array_depth >= 32)
48 return -EINVAL;
49
50 r = signature_element_length_internal(s + 1, true, array_depth+1, struct_depth, &t);
de1c301e
LP
51 if (r < 0)
52 return r;
53
54 *l = t + 1;
55 return 0;
56 }
57
58 if (*s == SD_BUS_TYPE_STRUCT_BEGIN) {
59 const char *p = s + 1;
60
813a4f93
LP
61 if (struct_depth >= 32)
62 return -EINVAL;
63
de1c301e
LP
64 while (*p != SD_BUS_TYPE_STRUCT_END) {
65 size_t t;
66
813a4f93 67 r = signature_element_length_internal(p, false, array_depth, struct_depth+1, &t);
de1c301e
LP
68 if (r < 0)
69 return r;
70
71 p += t;
72 }
73
74 *l = p - s + 1;
75 return 0;
76 }
77
78 if (*s == SD_BUS_TYPE_DICT_ENTRY_BEGIN && allow_dict_entry) {
79 const char *p = s + 1;
80 unsigned n = 0;
81
813a4f93
LP
82 if (struct_depth >= 32)
83 return -EINVAL;
84
de1c301e
LP
85 while (*p != SD_BUS_TYPE_DICT_ENTRY_END) {
86 size_t t;
87
88 if (n == 0 && !bus_type_is_basic(*p))
89 return -EINVAL;
90
813a4f93 91 r = signature_element_length_internal(p, false, array_depth, struct_depth+1, &t);
de1c301e
LP
92 if (r < 0)
93 return r;
94
95 p += t;
96 n++;
97 }
98
99 if (n != 2)
100 return -EINVAL;
101
102 *l = p - s + 1;
103 return 0;
104 }
105
106 return -EINVAL;
107}
108
813a4f93
LP
109
110int signature_element_length(const char *s, size_t *l) {
111 return signature_element_length_internal(s, true, 0, 0, l);
112}
113
29ddb38f 114bool signature_is_single(const char *s, bool allow_dict_entry) {
de1c301e
LP
115 int r;
116 size_t t;
117
35460afc
LP
118 if (!s)
119 return false;
de1c301e 120
29ddb38f 121 r = signature_element_length_internal(s, allow_dict_entry, 0, 0, &t);
de1c301e
LP
122 if (r < 0)
123 return false;
124
125 return s[t] == 0;
126}
127
128bool signature_is_pair(const char *s) {
718db961 129
35460afc
LP
130 if (!s)
131 return false;
de1c301e
LP
132
133 if (!bus_type_is_basic(*s))
134 return false;
135
29ddb38f 136 return signature_is_single(s + 1, false);
de1c301e
LP
137}
138
139bool signature_is_valid(const char *s, bool allow_dict_entry) {
140 const char *p;
141 int r;
142
35460afc
LP
143 if (!s)
144 return false;
de1c301e
LP
145
146 p = s;
147 while (*p) {
148 size_t t;
149
813a4f93 150 r = signature_element_length_internal(p, allow_dict_entry, 0, 0, &t);
de1c301e
LP
151 if (r < 0)
152 return false;
153
154 p += t;
155 }
156
157 return p - s <= 255;
158}