aboutsummaryrefslogtreecommitdiffstats
path: root/amend/register.c
diff options
context:
space:
mode:
Diffstat (limited to 'amend/register.c')
-rw-r--r--amend/register.c394
1 files changed, 394 insertions, 0 deletions
diff --git a/amend/register.c b/amend/register.c
new file mode 100644
index 0000000..167dd32
--- /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;
+}