blob: 167dd32e532cdbe638232661aafb3af18ec8b7bd [file] [log] [blame]
The Android Open Source Project23580ca2008-10-21 07:00:00 -07001/*
2 * Copyright (C) 2007 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#include <stdlib.h>
18#include <stdio.h>
19#include <string.h>
20#undef NDEBUG
21#include <assert.h>
22#include "commands.h"
23
24#include "register.h"
25
26#define UNUSED(p) ((void)(p))
27
28#define CHECK_BOOL() \
29 do { \
30 assert(argv == NULL); \
31 if (argv != NULL) return -1; \
32 assert(argc == true || argc == false); \
33 if (argc != true && argc != false) return -1; \
34 } while (false)
35
36#define CHECK_WORDS() \
37 do { \
38 assert(argc >= 0); \
39 if (argc < 0) return -1; \
40 assert(argc == 0 || argv != NULL); \
41 if (argc != 0 && argv == NULL) return -1; \
42 if (permissions != NULL) { \
43 int CW_I_; \
44 for (CW_I_ = 0; CW_I_ < argc; CW_I_++) { \
45 assert(argv[CW_I_] != NULL); \
46 if (argv[CW_I_] == NULL) return -1; \
47 } \
48 } \
49 } while (false)
50
51#define CHECK_FN() \
52 do { \
53 CHECK_WORDS(); \
54 if (permissions != NULL) { \
55 assert(result == NULL); \
56 if (result != NULL) return -1; \
57 } else { \
58 assert(result != NULL); \
59 if (result == NULL) return -1; \
60 } \
61 } while (false)
62
63#define NO_PERMS(perms) \
64 do { \
65 PermissionRequestList *NP_PRL_ = (perms); \
66 if (NP_PRL_ != NULL) { \
67 int NP_RET_ = addPermissionRequestToList(NP_PRL_, \
68 "", false, PERM_NONE); \
69 if (NP_RET_ < 0) { \
70 /* Returns from the calling function. \
71 */ \
72 return NP_RET_; \
73 } \
74 } \
75 } while (false)
76
77/*
78 * Command definitions
79 */
80
81/* assert <boolexpr>
82 */
83static int
84cmd_assert(const char *name, void *cookie, int argc, const char *argv[],
85 PermissionRequestList *permissions)
86{
87 UNUSED(name);
88 UNUSED(cookie);
89 CHECK_BOOL();
90 NO_PERMS(permissions);
91
92 /* If our argument is false, return non-zero (failure)
93 * If our argument is true, return zero (success)
94 */
95 if (argc) {
96 return 0;
97 } else {
98 return 1;
99 }
100}
101
102/* format <root>
103 */
104static int
105cmd_format(const char *name, void *cookie, int argc, const char *argv[],
106 PermissionRequestList *permissions)
107{
108 UNUSED(name);
109 UNUSED(cookie);
110 CHECK_WORDS();
111//xxx
112 return -1;
113}
114
115/* copy_dir <srcdir> <dstdir>
116 */
117static int
118cmd_copy_dir(const char *name, void *cookie, int argc, const char *argv[],
119 PermissionRequestList *permissions)
120{
121 UNUSED(name);
122 UNUSED(cookie);
123 CHECK_WORDS();
124//xxx
125 return -1;
126}
127
128/* mark <resource> dirty|clean
129 */
130static int
131cmd_mark(const char *name, void *cookie, int argc, const char *argv[],
132 PermissionRequestList *permissions)
133{
134 UNUSED(name);
135 UNUSED(cookie);
136 CHECK_WORDS();
137//xxx when marking, save the top-level hash at the mark point
138// so we can retry on failure. Otherwise the hashes won't match,
139// or someone could intentionally dirty the FS to force a downgrade
140//xxx
141 return -1;
142}
143
144/* done
145 */
146static int
147cmd_done(const char *name, void *cookie, int argc, const char *argv[],
148 PermissionRequestList *permissions)
149{
150 UNUSED(name);
151 UNUSED(cookie);
152 CHECK_WORDS();
153//xxx
154 return -1;
155}
156
157int
158registerUpdateCommands()
159{
160 int ret;
161
162 ret = registerCommand("assert", CMD_ARGS_BOOLEAN, cmd_assert, NULL);
163 if (ret < 0) return ret;
164
165 ret = registerCommand("copy_dir", CMD_ARGS_WORDS, cmd_copy_dir, NULL);
166 if (ret < 0) return ret;
167
168 ret = registerCommand("format", CMD_ARGS_WORDS, cmd_format, NULL);
169 if (ret < 0) return ret;
170
171 ret = registerCommand("mark", CMD_ARGS_WORDS, cmd_mark, NULL);
172 if (ret < 0) return ret;
173
174 ret = registerCommand("done", CMD_ARGS_WORDS, cmd_done, NULL);
175 if (ret < 0) return ret;
176
177//xxx some way to fix permissions
178//xxx could have "installperms" commands that build the fs_config list
179//xxx along with a "commitperms", and any copy_dir etc. needs to see
180// a commitperms before it will work
181
182 return 0;
183}
184
185
186/*
187 * Function definitions
188 */
189
190/* update_forced()
191 *
192 * Returns "true" if some system setting has determined that
193 * the update should happen no matter what.
194 */
195static int
196fn_update_forced(const char *name, void *cookie, int argc, const char *argv[],
197 char **result, size_t *resultLen,
198 PermissionRequestList *permissions)
199{
200 UNUSED(name);
201 UNUSED(cookie);
202 CHECK_FN();
203 NO_PERMS(permissions);
204
205 if (argc != 0) {
206 fprintf(stderr, "%s: wrong number of arguments (%d)\n",
207 name, argc);
208 return 1;
209 }
210
211 //xxx check some global or property
212 bool force = true;
213 if (force) {
214 *result = strdup("true");
215 } else {
216 *result = strdup("");
217 }
218 if (resultLen != NULL) {
219 *resultLen = strlen(*result);
220 }
221
222 return 0;
223}
224
225/* get_mark(<resource>)
226 *
227 * Returns the current mark associated with the provided resource.
228 */
229static int
230fn_get_mark(const char *name, void *cookie, int argc, const char *argv[],
231 char **result, size_t *resultLen,
232 PermissionRequestList *permissions)
233{
234 UNUSED(name);
235 UNUSED(cookie);
236 CHECK_FN();
237 NO_PERMS(permissions);
238
239 if (argc != 1) {
240 fprintf(stderr, "%s: wrong number of arguments (%d)\n",
241 name, argc);
242 return 1;
243 }
244
245 //xxx look up the value
246 *result = strdup("");
247 if (resultLen != NULL) {
248 *resultLen = strlen(*result);
249 }
250
251 return 0;
252}
253
254/* hash_dir(<path-to-directory>)
255 */
256static int
257fn_hash_dir(const char *name, void *cookie, int argc, const char *argv[],
258 char **result, size_t *resultLen,
259 PermissionRequestList *permissions)
260{
261 int ret = -1;
262
263 UNUSED(name);
264 UNUSED(cookie);
265 CHECK_FN();
266
267 const char *dir;
268 if (argc != 1) {
269 fprintf(stderr, "%s: wrong number of arguments (%d)\n",
270 name, argc);
271 return 1;
272 } else {
273 dir = argv[0];
274 }
275
276 if (permissions != NULL) {
277 if (dir == NULL) {
278 /* The argument is the result of another function.
279 * Assume the worst case, where the function returns
280 * the root.
281 */
282 dir = "/";
283 }
284 ret = addPermissionRequestToList(permissions, dir, true, PERM_READ);
285 } else {
286//xxx build and return the string
287 *result = strdup("hashvalue");
288 if (resultLen != NULL) {
289 *resultLen = strlen(*result);
290 }
291 ret = 0;
292 }
293
294 return ret;
295}
296
297/* matches(<str>, <str1> [, <strN>...])
298 * If <str> matches (strcmp) any of <str1>...<strN>, returns <str>,
299 * otherwise returns "".
300 *
301 * E.g., assert matches(hash_dir("/path"), "hash1", "hash2")
302 */
303static int
304fn_matches(const char *name, void *cookie, int argc, const char *argv[],
305 char **result, size_t *resultLen,
306 PermissionRequestList *permissions)
307{
308 UNUSED(name);
309 UNUSED(cookie);
310 CHECK_FN();
311 NO_PERMS(permissions);
312
313 if (argc < 2) {
314 fprintf(stderr, "%s: not enough arguments (%d < 2)\n",
315 name, argc);
316 return 1;
317 }
318
319 int i;
320 for (i = 1; i < argc; i++) {
321 if (strcmp(argv[0], argv[i]) == 0) {
322 *result = strdup(argv[0]);
323 if (resultLen != NULL) {
324 *resultLen = strlen(*result);
325 }
326 return 0;
327 }
328 }
329
330 *result = strdup("");
331 if (resultLen != NULL) {
332 *resultLen = 1;
333 }
334 return 0;
335}
336
337/* concat(<str>, <str1> [, <strN>...])
338 * Returns the concatenation of all strings.
339 */
340static int
341fn_concat(const char *name, void *cookie, int argc, const char *argv[],
342 char **result, size_t *resultLen,
343 PermissionRequestList *permissions)
344{
345 UNUSED(name);
346 UNUSED(cookie);
347 CHECK_FN();
348 NO_PERMS(permissions);
349
350 size_t totalLen = 0;
351 int i;
352 for (i = 0; i < argc; i++) {
353 totalLen += strlen(argv[i]);
354 }
355
356 char *s = (char *)malloc(totalLen + 1);
357 if (s == NULL) {
358 return -1;
359 }
360 s[totalLen] = '\0';
361 for (i = 0; i < argc; i++) {
362 //TODO: keep track of the end to avoid walking the string each time
363 strcat(s, argv[i]);
364 }
365 *result = s;
366 if (resultLen != NULL) {
367 *resultLen = strlen(s);
368 }
369
370 return 0;
371}
372
373int
374registerUpdateFunctions()
375{
376 int ret;
377
378 ret = registerFunction("update_forced", fn_update_forced, NULL);
379 if (ret < 0) return ret;
380
381 ret = registerFunction("get_mark", fn_get_mark, NULL);
382 if (ret < 0) return ret;
383
384 ret = registerFunction("hash_dir", fn_hash_dir, NULL);
385 if (ret < 0) return ret;
386
387 ret = registerFunction("matches", fn_matches, NULL);
388 if (ret < 0) return ret;
389
390 ret = registerFunction("concat", fn_concat, NULL);
391 if (ret < 0) return ret;
392
393 return 0;
394}