diff options
Diffstat (limited to 'amend/register.c')
-rw-r--r-- | amend/register.c | 394 |
1 files changed, 394 insertions, 0 deletions
diff --git a/amend/register.c b/amend/register.c new file mode 100644 index 000000000..167dd32e5 --- /dev/null +++ b/amend/register.c @@ -0,0 +1,394 @@ +/* + * Copyright (C) 2007 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include <stdlib.h> +#include <stdio.h> +#include <string.h> +#undef NDEBUG +#include <assert.h> +#include "commands.h" + +#include "register.h" + +#define UNUSED(p) ((void)(p)) + +#define CHECK_BOOL() \ + do { \ + assert(argv == NULL); \ + if (argv != NULL) return -1; \ + assert(argc == true || argc == false); \ + if (argc != true && argc != false) return -1; \ + } while (false) + +#define CHECK_WORDS() \ + do { \ + assert(argc >= 0); \ + if (argc < 0) return -1; \ + assert(argc == 0 || argv != NULL); \ + if (argc != 0 && argv == NULL) return -1; \ + if (permissions != NULL) { \ + int CW_I_; \ + for (CW_I_ = 0; CW_I_ < argc; CW_I_++) { \ + assert(argv[CW_I_] != NULL); \ + if (argv[CW_I_] == NULL) return -1; \ + } \ + } \ + } while (false) + +#define CHECK_FN() \ + do { \ + CHECK_WORDS(); \ + if (permissions != NULL) { \ + assert(result == NULL); \ + if (result != NULL) return -1; \ + } else { \ + assert(result != NULL); \ + if (result == NULL) return -1; \ + } \ + } while (false) + +#define NO_PERMS(perms) \ + do { \ + PermissionRequestList *NP_PRL_ = (perms); \ + if (NP_PRL_ != NULL) { \ + int NP_RET_ = addPermissionRequestToList(NP_PRL_, \ + "", false, PERM_NONE); \ + if (NP_RET_ < 0) { \ + /* Returns from the calling function. \ + */ \ + return NP_RET_; \ + } \ + } \ + } while (false) + +/* + * Command definitions + */ + +/* assert <boolexpr> + */ +static int +cmd_assert(const char *name, void *cookie, int argc, const char *argv[], + PermissionRequestList *permissions) +{ + UNUSED(name); + UNUSED(cookie); + CHECK_BOOL(); + NO_PERMS(permissions); + + /* If our argument is false, return non-zero (failure) + * If our argument is true, return zero (success) + */ + if (argc) { + return 0; + } else { + return 1; + } +} + +/* format <root> + */ +static int +cmd_format(const char *name, void *cookie, int argc, const char *argv[], + PermissionRequestList *permissions) +{ + UNUSED(name); + UNUSED(cookie); + CHECK_WORDS(); +//xxx + return -1; +} + +/* copy_dir <srcdir> <dstdir> + */ +static int +cmd_copy_dir(const char *name, void *cookie, int argc, const char *argv[], + PermissionRequestList *permissions) +{ + UNUSED(name); + UNUSED(cookie); + CHECK_WORDS(); +//xxx + return -1; +} + +/* mark <resource> dirty|clean + */ +static int +cmd_mark(const char *name, void *cookie, int argc, const char *argv[], + PermissionRequestList *permissions) +{ + UNUSED(name); + UNUSED(cookie); + CHECK_WORDS(); +//xxx when marking, save the top-level hash at the mark point +// so we can retry on failure. Otherwise the hashes won't match, +// or someone could intentionally dirty the FS to force a downgrade +//xxx + return -1; +} + +/* done + */ +static int +cmd_done(const char *name, void *cookie, int argc, const char *argv[], + PermissionRequestList *permissions) +{ + UNUSED(name); + UNUSED(cookie); + CHECK_WORDS(); +//xxx + return -1; +} + +int +registerUpdateCommands() +{ + int ret; + + ret = registerCommand("assert", CMD_ARGS_BOOLEAN, cmd_assert, NULL); + if (ret < 0) return ret; + + ret = registerCommand("copy_dir", CMD_ARGS_WORDS, cmd_copy_dir, NULL); + if (ret < 0) return ret; + + ret = registerCommand("format", CMD_ARGS_WORDS, cmd_format, NULL); + if (ret < 0) return ret; + + ret = registerCommand("mark", CMD_ARGS_WORDS, cmd_mark, NULL); + if (ret < 0) return ret; + + ret = registerCommand("done", CMD_ARGS_WORDS, cmd_done, NULL); + if (ret < 0) return ret; + +//xxx some way to fix permissions +//xxx could have "installperms" commands that build the fs_config list +//xxx along with a "commitperms", and any copy_dir etc. needs to see +// a commitperms before it will work + + return 0; +} + + +/* + * Function definitions + */ + +/* update_forced() + * + * Returns "true" if some system setting has determined that + * the update should happen no matter what. + */ +static int +fn_update_forced(const char *name, void *cookie, int argc, const char *argv[], + char **result, size_t *resultLen, + PermissionRequestList *permissions) +{ + UNUSED(name); + UNUSED(cookie); + CHECK_FN(); + NO_PERMS(permissions); + + if (argc != 0) { + fprintf(stderr, "%s: wrong number of arguments (%d)\n", + name, argc); + return 1; + } + + //xxx check some global or property + bool force = true; + if (force) { + *result = strdup("true"); + } else { + *result = strdup(""); + } + if (resultLen != NULL) { + *resultLen = strlen(*result); + } + + return 0; +} + +/* get_mark(<resource>) + * + * Returns the current mark associated with the provided resource. + */ +static int +fn_get_mark(const char *name, void *cookie, int argc, const char *argv[], + char **result, size_t *resultLen, + PermissionRequestList *permissions) +{ + UNUSED(name); + UNUSED(cookie); + CHECK_FN(); + NO_PERMS(permissions); + + if (argc != 1) { + fprintf(stderr, "%s: wrong number of arguments (%d)\n", + name, argc); + return 1; + } + + //xxx look up the value + *result = strdup(""); + if (resultLen != NULL) { + *resultLen = strlen(*result); + } + + return 0; +} + +/* hash_dir(<path-to-directory>) + */ +static int +fn_hash_dir(const char *name, void *cookie, int argc, const char *argv[], + char **result, size_t *resultLen, + PermissionRequestList *permissions) +{ + int ret = -1; + + UNUSED(name); + UNUSED(cookie); + CHECK_FN(); + + const char *dir; + if (argc != 1) { + fprintf(stderr, "%s: wrong number of arguments (%d)\n", + name, argc); + return 1; + } else { + dir = argv[0]; + } + + if (permissions != NULL) { + if (dir == NULL) { + /* The argument is the result of another function. + * Assume the worst case, where the function returns + * the root. + */ + dir = "/"; + } + ret = addPermissionRequestToList(permissions, dir, true, PERM_READ); + } else { +//xxx build and return the string + *result = strdup("hashvalue"); + if (resultLen != NULL) { + *resultLen = strlen(*result); + } + ret = 0; + } + + return ret; +} + +/* matches(<str>, <str1> [, <strN>...]) + * If <str> matches (strcmp) any of <str1>...<strN>, returns <str>, + * otherwise returns "". + * + * E.g., assert matches(hash_dir("/path"), "hash1", "hash2") + */ +static int +fn_matches(const char *name, void *cookie, int argc, const char *argv[], + char **result, size_t *resultLen, + PermissionRequestList *permissions) +{ + UNUSED(name); + UNUSED(cookie); + CHECK_FN(); + NO_PERMS(permissions); + + if (argc < 2) { + fprintf(stderr, "%s: not enough arguments (%d < 2)\n", + name, argc); + return 1; + } + + int i; + for (i = 1; i < argc; i++) { + if (strcmp(argv[0], argv[i]) == 0) { + *result = strdup(argv[0]); + if (resultLen != NULL) { + *resultLen = strlen(*result); + } + return 0; + } + } + + *result = strdup(""); + if (resultLen != NULL) { + *resultLen = 1; + } + return 0; +} + +/* concat(<str>, <str1> [, <strN>...]) + * Returns the concatenation of all strings. + */ +static int +fn_concat(const char *name, void *cookie, int argc, const char *argv[], + char **result, size_t *resultLen, + PermissionRequestList *permissions) +{ + UNUSED(name); + UNUSED(cookie); + CHECK_FN(); + NO_PERMS(permissions); + + size_t totalLen = 0; + int i; + for (i = 0; i < argc; i++) { + totalLen += strlen(argv[i]); + } + + char *s = (char *)malloc(totalLen + 1); + if (s == NULL) { + return -1; + } + s[totalLen] = '\0'; + for (i = 0; i < argc; i++) { + //TODO: keep track of the end to avoid walking the string each time + strcat(s, argv[i]); + } + *result = s; + if (resultLen != NULL) { + *resultLen = strlen(s); + } + + return 0; +} + +int +registerUpdateFunctions() +{ + int ret; + + ret = registerFunction("update_forced", fn_update_forced, NULL); + if (ret < 0) return ret; + + ret = registerFunction("get_mark", fn_get_mark, NULL); + if (ret < 0) return ret; + + ret = registerFunction("hash_dir", fn_hash_dir, NULL); + if (ret < 0) return ret; + + ret = registerFunction("matches", fn_matches, NULL); + if (ret < 0) return ret; + + ret = registerFunction("concat", fn_concat, NULL); + if (ret < 0) return ret; + + return 0; +} |