diff options
author | Jelmer Vernooij <jelmer@samba.org> | 2005-09-29 11:51:06 +0000 |
---|---|---|
committer | Gerald (Jerry) Carter <jerry@samba.org> | 2007-10-10 13:39:11 -0500 |
commit | 5e7a0fb5349422cfb782c0348f98505011d27391 (patch) | |
tree | 18f04740785403e0566ce3675178543b83ef9737 | |
parent | 0e90afb4e7737d60d902aee1df4cbeb85a7b693d (diff) | |
download | samba-5e7a0fb5349422cfb782c0348f98505011d27391.tar.gz samba-5e7a0fb5349422cfb782c0348f98505011d27391.tar.bz2 samba-5e7a0fb5349422cfb782c0348f98505011d27391.zip |
r10604: Put in the new registry "patchfile" code (similar to ldif
for LDB); not finished yet.
(This used to be commit b405b27ba4bf4ddbaff9ca58926d94d1b2fd09f6)
-rw-r--r-- | source4/gtk/tools/gregedit.c | 8 | ||||
-rw-r--r-- | source4/include/structs.h | 1 | ||||
-rw-r--r-- | source4/lib/registry/TODO | 5 | ||||
-rw-r--r-- | source4/lib/registry/common/reg_util.c | 40 | ||||
-rw-r--r-- | source4/lib/registry/config.mk | 3 | ||||
-rw-r--r-- | source4/lib/registry/registry.h | 23 | ||||
-rw-r--r-- | source4/lib/registry/tools/regdiff.c | 128 | ||||
-rw-r--r-- | source4/lib/registry/tools/regpatch.c | 741 | ||||
-rw-r--r-- | source4/lib/registry/tools/regshell.c | 6 |
9 files changed, 77 insertions, 878 deletions
diff --git a/source4/gtk/tools/gregedit.c b/source4/gtk/tools/gregedit.c index 5de09eb84e..ae34bf2745 100644 --- a/source4/gtk/tools/gregedit.c +++ b/source4/gtk/tools/gregedit.c @@ -538,7 +538,7 @@ static void on_value_activate(GtkTreeView *treeview, GtkTreePath *arg1, gtk_widget_set_sensitive(entry_name, FALSE); gtk_entry_set_text(GTK_ENTRY(entry_name), value->name); - gtk_entry_set_text(GTK_ENTRY(entry_value), reg_val_data_string(mem_ctx, value)); + gtk_entry_set_text(GTK_ENTRY(entry_value), reg_val_data_string(mem_ctx, value->data_type, &value->data)); gtk_combo_box_set_active(GTK_COMBO_BOX(entry_type), value->data_type); result = gtk_dialog_run(addwin); @@ -547,7 +547,7 @@ static void on_value_activate(GtkTreeView *treeview, GtkTreePath *arg1, WERROR error; struct registry_value *val; - reg_string_to_val(mem_ctx,str_regtype(gtk_combo_box_get_active(GTK_COMBO_BOX(entry_type))), gtk_entry_get_text(GTK_ENTRY(entry_value)), &val); + reg_string_to_val(mem_ctx,str_regtype(gtk_combo_box_get_active(GTK_COMBO_BOX(entry_type))), gtk_entry_get_text(GTK_ENTRY(entry_value)), &val->data_type, &val->data); error = reg_val_set(current_key, gtk_entry_get_text(GTK_ENTRY(entry_name)), val->data_type, val->data); @@ -568,7 +568,7 @@ static void on_set_value_activate(GtkMenuItem *menuitem, gpointer user_data) WERROR error; struct registry_value *val; - reg_string_to_val(mem_ctx,str_regtype(gtk_combo_box_get_active(GTK_COMBO_BOX(entry_type))), gtk_entry_get_text(GTK_ENTRY(entry_value)), &val); + reg_string_to_val(mem_ctx,str_regtype(gtk_combo_box_get_active(GTK_COMBO_BOX(entry_type))), gtk_entry_get_text(GTK_ENTRY(entry_value)), &val->data_type, &val->data); error = reg_val_set(current_key, gtk_entry_get_text(GTK_ENTRY(entry_name)), val->data_type, val->data); @@ -636,7 +636,7 @@ static gboolean on_key_activate(GtkTreeSelection *selection, 1, str_regtype(val->data_type), 2, - reg_val_data_string(mem_ctx, val), + reg_val_data_string(mem_ctx, val->data_type, &val->data), 3, val, -1); diff --git a/source4/include/structs.h b/source4/include/structs.h index ca28c1fc7a..9d30e64dbc 100644 --- a/source4/include/structs.h +++ b/source4/include/structs.h @@ -135,6 +135,7 @@ struct rw_buffer; struct registry_context; struct registry_key; struct registry_value; +struct reg_diff_file; struct rap_NetShareEnum; struct rap_NetServerEnum2; diff --git a/source4/lib/registry/TODO b/source4/lib/registry/TODO index 3f48d031e1..518edf6795 100644 --- a/source4/lib/registry/TODO +++ b/source4/lib/registry/TODO @@ -24,12 +24,11 @@ reg_backend_wine.c: regshell: - support for security descriptors - regdiff: - - fix - gregedit.c: - support for editing values / adding values / deleting values - support for adding/deleting keys - support for security descriptors - pass parsed paths around rather then strings (i.e. just a list of strings) +- integrate various registry tools ? +- finish new patchfile code diff --git a/source4/lib/registry/common/reg_util.c b/source4/lib/registry/common/reg_util.c index ae30839cca..75f9d3cf00 100644 --- a/source4/lib/registry/common/reg_util.c +++ b/source4/lib/registry/common/reg_util.c @@ -46,27 +46,27 @@ const char *str_regtype(int type) return "Unknown"; } -char *reg_val_data_string(TALLOC_CTX *mem_ctx, struct registry_value *v) +char *reg_val_data_string(TALLOC_CTX *mem_ctx, uint32_t type, DATA_BLOB *data) { char *ret = NULL; - if(v->data.length == 0) return talloc_strdup(mem_ctx, ""); + if(data->length == 0) return talloc_strdup(mem_ctx, ""); - switch (v->data_type) { + switch (type) { case REG_EXPAND_SZ: case REG_SZ: - convert_string_talloc(mem_ctx, CH_UTF16, CH_UNIX, v->data.data, v->data.length, (void **)&ret); + convert_string_talloc(mem_ctx, CH_UTF16, CH_UNIX, data->data, data->length, (void **)&ret); return ret; case REG_BINARY: - ret = data_blob_hex_string(mem_ctx, &v->data); + ret = data_blob_hex_string(mem_ctx, data); return ret; case REG_DWORD: - if (*(int *)v->data.data == 0) + if (*(int *)data->data == 0) return talloc_strdup(mem_ctx, "0"); - return talloc_asprintf(mem_ctx, "0x%x", *(int *)v->data.data); + return talloc_asprintf(mem_ctx, "0x%x", *(int *)data->data); case REG_MULTI_SZ: /* FIXME */ @@ -81,47 +81,51 @@ char *reg_val_data_string(TALLOC_CTX *mem_ctx, struct registry_value *v) char *reg_val_description(TALLOC_CTX *mem_ctx, struct registry_value *val) { - return talloc_asprintf(mem_ctx, "%s = %s : %s", val->name?val->name:"<No Name>", str_regtype(val->data_type), reg_val_data_string(mem_ctx, val)); + return talloc_asprintf(mem_ctx, "%s = %s : %s", val->name?val->name:"<No Name>", str_regtype(val->data_type), reg_val_data_string(mem_ctx, val->data_type, &val->data)); } -BOOL reg_string_to_val(TALLOC_CTX *mem_ctx, const char *type_str, const char *data_str, struct registry_value **value) +BOOL reg_string_to_val(TALLOC_CTX *mem_ctx, const char *type_str, const char *data_str, uint32_t *type, DATA_BLOB *data) { int i; - *value = talloc(mem_ctx, struct registry_value); - (*value)->data_type = -1; + *type = -1; /* Find the correct type */ for (i = 0; reg_value_types[i].name; i++) { if (!strcmp(reg_value_types[i].name, type_str)) { - (*value)->data_type = reg_value_types[i].id; + *type = reg_value_types[i].id; break; } } - if ((*value)->data_type == -1) + if (*type == -1) return False; /* Convert data appropriately */ - switch ((*value)->data_type) + switch (*type) { case REG_SZ: case REG_EXPAND_SZ: - (*value)->data.length = convert_string_talloc(mem_ctx, CH_UNIX, CH_UTF16, data_str, strlen(data_str), (void **)&(*value)->data.data); + data->length = convert_string_talloc(mem_ctx, CH_UNIX, CH_UTF16, data_str, strlen(data_str), (void **)&data->data); break; case REG_DWORD: { uint32_t tmp = strtol(data_str, NULL, 0); - (*value)->data = data_blob_talloc(mem_ctx, &tmp, 4); + *data = data_blob_talloc(mem_ctx, &tmp, 4); } break; case REG_NONE: - ZERO_STRUCT((*value)->data); + ZERO_STRUCT(data); break; + case REG_BINARY: + *data = strhex_to_data_blob(data_str); + talloc_steal(mem_ctx, data->data); + break; + default: - case REG_BINARY: /* FIXME */ + /* FIXME */ return False; } return True; diff --git a/source4/lib/registry/config.mk b/source4/lib/registry/config.mk index 87e0779007..8a579d4564 100644 --- a/source4/lib/registry/config.mk +++ b/source4/lib/registry/config.mk @@ -83,7 +83,8 @@ INIT_OBJ_FILES = \ lib/registry/common/reg_interface.o ADD_OBJ_FILES = \ lib/registry/common/reg_util.o \ - lib/registry/reg_samba.o + lib/registry/reg_samba.o \ + lib/registry/patchfile.o REQUIRED_SUBSYSTEMS = \ LIBBASIC # End MODULE registry_ldb diff --git a/source4/lib/registry/registry.h b/source4/lib/registry/registry.h index 69f3606736..ebfb2caf5c 100644 --- a/source4/lib/registry/registry.h +++ b/source4/lib/registry/registry.h @@ -138,4 +138,27 @@ struct reg_init_function_entry { struct reg_init_function_entry *prev, *next; }; +struct reg_diff_value +{ + char *name; + enum { REG_DIFF_DEL_VAL, REG_DIFF_SET_VAL } changetype; + uint32_t type; + DATA_BLOB data; +}; + +struct reg_diff_key +{ + char *name; + enum { REG_DIFF_CHANGE_KEY, REG_DIFF_DEL_KEY } changetype; + uint32_t numvalues; + struct reg_diff_value *values; +}; + +struct reg_diff +{ + char *format; + uint32_t numkeys; + struct reg_diff_key *keys; +}; + #endif /* _REGISTRY_H */ diff --git a/source4/lib/registry/tools/regdiff.c b/source4/lib/registry/tools/regdiff.c index 3d8201330e..92fe53ff67 100644 --- a/source4/lib/registry/tools/regdiff.c +++ b/source4/lib/registry/tools/regdiff.c @@ -2,7 +2,7 @@ Unix SMB/CIFS implementation. simple registry frontend - Copyright (C) Jelmer Vernooij 2004 + Copyright (C) Jelmer Vernooij 2004-2005 This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -24,101 +24,15 @@ #include "lib/registry/registry.h" #include "lib/cmdline/popt_common.h" -static void writediff(struct registry_key *oldkey, struct registry_key *newkey, FILE *out) -{ - int i; - struct registry_key *t1, *t2; - struct registry_value *v1, *v2; - WERROR error1, error2; - TALLOC_CTX *mem_ctx = talloc_init("writediff"); - - for(i = 0; W_ERROR_IS_OK(error1 = reg_key_get_subkey_by_index(mem_ctx, oldkey, i, &t1)); i++) { - error2 = reg_key_get_subkey_by_name(mem_ctx, newkey, t1->name, &t2); - if(W_ERROR_EQUAL(error2, WERR_DEST_NOT_FOUND)) { - fprintf(out, "-%s\n", t1->path+1); - } else if(!W_ERROR_IS_OK(error2)) { - DEBUG(0, ("Error occured while getting subkey by name: %d\n", W_ERROR_V(error2))); - } - } - - talloc_free(mem_ctx); - - if(!W_ERROR_EQUAL(error1, WERR_NO_MORE_ITEMS)) { - DEBUG(0, ("Error occured while getting subkey by index: %d\n", W_ERROR_V(error1))); - return; - } - - mem_ctx = talloc_init("writediff"); - - for(i = 0; W_ERROR_IS_OK(error1 = reg_key_get_subkey_by_index(mem_ctx, newkey, i, &t1)); i++) { - error2 = reg_key_get_subkey_by_name(mem_ctx, oldkey, t1->name, &t2); - if(W_ERROR_EQUAL(error2, WERR_DEST_NOT_FOUND)) { - fprintf(out, "\n[%s]\n", t1->path+1); - } else if(!W_ERROR_IS_OK(error2)) { - DEBUG(0, ("Error occured while getting subkey by name: %d\n", W_ERROR_V(error2))); - } - writediff(t2, t1, out); - } - - talloc_free(mem_ctx); - - if(!W_ERROR_EQUAL(error1, WERR_NO_MORE_ITEMS)) { - DEBUG(0, ("Error occured while getting subkey by index: %d\n", W_ERROR_V(error1))); - return; - } - - - mem_ctx = talloc_init("writediff"); - - for(i = 0; W_ERROR_IS_OK(error1 = reg_key_get_value_by_index(mem_ctx, newkey, i, &v1)); i++) { - error2 = reg_key_get_value_by_name(mem_ctx, oldkey, v1->name, &v2); - if ((W_ERROR_IS_OK(error2) && data_blob_equal(&v1->data, &v2->data)) - || W_ERROR_EQUAL(error2, WERR_DEST_NOT_FOUND)) { - fprintf(out, "\"%s\"=%s:%s\n", v1->name, str_regtype(v1->data_type), reg_val_data_string(mem_ctx, v1)); - } - - if(!W_ERROR_IS_OK(error2) && !W_ERROR_EQUAL(error2, WERR_DEST_NOT_FOUND)) { - DEBUG(0, ("Error occured while getting value by name: %d\n", W_ERROR_V(error2))); - } - } - - talloc_free(mem_ctx); - - if(!W_ERROR_EQUAL(error1, WERR_NO_MORE_ITEMS)) { - DEBUG(0, ("Error occured while getting value by index: %d\n", W_ERROR_V(error1))); - return; - } - - mem_ctx = talloc_init("writediff"); - - for(i = 0; W_ERROR_IS_OK(error1 = reg_key_get_value_by_index(mem_ctx, oldkey, i, &v1)); i++) { - error2 = reg_key_get_value_by_name(mem_ctx, newkey, v1->name, &v2); - if(W_ERROR_IS_OK(error2)) { - } else if(W_ERROR_EQUAL(error2, WERR_DEST_NOT_FOUND)) { - fprintf(out, "\"%s\"=-\n", v1->name); - } else { - DEBUG(0, ("Error occured while getting value by name: %d\n", W_ERROR_V(error2))); - } - } - - talloc_free(mem_ctx); - - if(!W_ERROR_EQUAL(error1, WERR_NO_MORE_ITEMS)) { - DEBUG(0, ("Error occured while getting value by index: %d\n", W_ERROR_V(error1))); - return; - } -} - - int main(int argc, char **argv) +int main(int argc, char **argv) { int opt; poptContext pc; char *outputfile = NULL; - FILE *fd = stdout; struct registry_context *h1 = NULL, *h2 = NULL; int from_null = 0; - int i; - WERROR error, error2; + WERROR error; + struct reg_diff *diff; struct poptOption long_options[] = { POPT_AUTOHELP {"output", 'o', POPT_ARG_STRING, &outputfile, 'o', "output file to use", NULL }, @@ -159,37 +73,13 @@ static void writediff(struct registry_key *oldkey, struct registry_key *newkey, poptFreeContext(pc); - if(outputfile) { - fd = fopen(outputfile, "w+"); - if(!fd) { - fprintf(stderr, "Unable to open '%s'\n", outputfile); - return 1; - } - } - - fprintf(fd, "REGEDIT4\n\n"); - fprintf(fd, "; Generated using regdiff, part of Samba\n"); - - error2 = error = WERR_OK; - - for(i = HKEY_CLASSES_ROOT; i <= HKEY_PERFORMANCE_NLSTEXT; i++) { - struct registry_key *r1, *r2; - error = reg_get_predefined_key(h1, i, &r1); - if (!W_ERROR_IS_OK(error)) { - DEBUG(0, ("Unable to open hive %s for backend 1\n", reg_get_predef_name(i))); - continue; - } - - error = reg_get_predefined_key(h2, i, &r2); - if (!W_ERROR_IS_OK(error)) { - DEBUG(0, ("Unable to open hive %s for backend 2\n", reg_get_predef_name(i))); - continue; - } - - writediff(r1, r2, fd); + diff = reg_generate_diff(NULL, h1, h2); + if (!diff) { + fprintf(stderr, "Unable to generate diff between keys\n"); + return -1; } - fclose(fd); + reg_diff_save(diff, outputfile); return 0; } diff --git a/source4/lib/registry/tools/regpatch.c b/source4/lib/registry/tools/regpatch.c index 98e6c0ff5d..eca14741a5 100644 --- a/source4/lib/registry/tools/regpatch.c +++ b/source4/lib/registry/tools/regpatch.c @@ -2,8 +2,7 @@ Unix SMB/CIFS implementation. simple registry frontend - Copyright (C) 2002, Richard Sharpe, rsharpe@richardsharpe.com - Copyright (C) 2004, Jelmer Vernooij, jelmer@samba.org + Copyright (C) 2004-2005 Jelmer Vernooij, jelmer@samba.org This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -27,737 +26,14 @@ #include "system/filesys.h" #include "librpc/gen_ndr/winreg.h" -/* - * Routines to parse a REGEDIT4 file - * - * The file consists of: - * - * REGEDIT4 - * \[[-]key-path\]\n - * <value-spec>* - * - * Format: - * [cmd:]name=type:value - * - * cmd = a|d|c|add|delete|change|as|ds|cs - * - * There can be more than one key-path and value-spec. - * - * Since we want to support more than one type of file format, we - * construct a command-file structure that keeps info about the command file - */ - -#define FMT_UNREC -1 -#define FMT_REGEDIT4 0 -#define FMT_EDITREG1_1 1 - -#define FMT_STRING_REGEDIT4 "REGEDIT4" -#define FMT_STRING_EDITREG1_0 "EDITREG1.0" - -#define CMD_NONE 0 -#define CMD_ADD_KEY 1 -#define CMD_DEL_KEY 2 - -#define CMD_KEY 1 -#define CMD_VAL 2 - -typedef struct val_spec_list { - struct val_spec_list *next; - char *name; - int type; - char *val; /* Kept as a char string, really? */ -} VAL_SPEC_LIST; - -typedef struct command_s { - int cmd; - char *key; - int val_count; - VAL_SPEC_LIST *val_spec_list, *val_spec_last; -} CMD; - -typedef struct cmd_line { - int len, line_len; - char *line; -} CMD_LINE; - -static void free_val_spec_list(VAL_SPEC_LIST *vl) -{ - if (!vl) return; - if (vl->name) free(vl->name); - if (vl->val) free(vl->val); - free(vl); - -} - -/* - * Some routines to handle lines of info in the command files - */ -static void skip_to_eol(int fd) -{ - int rc; - char ch = 0; - - while ((rc = read(fd, &ch, 1)) == 1) { - if (ch == 0x0A) return; - } - if (rc < 0) { - DEBUG(0, ("Could not read file descriptor: %d, %s\n", - fd, strerror(errno))); - exit(1); - } -} - -static void free_cmd(CMD *cmd) -{ - if (!cmd) return; - - while (cmd->val_spec_list) { - VAL_SPEC_LIST *tmp; - - tmp = cmd->val_spec_list; - cmd->val_spec_list = tmp->next; - free(tmp); - } - - free(cmd); - -} - -static void free_cmd_line(CMD_LINE *cmd_line) -{ - if (cmd_line) { - if (cmd_line->line) free(cmd_line->line); - free(cmd_line); - } -} - -static void print_line(struct cmd_line *cl) -{ - char *pl; - - if (!cl) return; - - pl = smb_xmalloc(cl->line_len + 1); - - strncpy(pl, cl->line, cl->line_len); - pl[cl->line_len] = 0; - - fprintf(stdout, "%s\n", pl); - free(pl); -} - -#define INIT_ALLOC 10 - -/* - * Read a line from the input file. - * NULL returned when EOF and no chars read - * Otherwise we return a cmd_line * - * Exit if other errors - */ -static struct cmd_line *get_cmd_line(int fd) -{ - CMD_LINE *cl = malloc_p(CMD_LINE); - int i = 0, rc; - uint8_t ch; - - if (!cl) - return NULL; - - cl->len = INIT_ALLOC; - - /* - * Allocate some space for the line. We extend later if needed. - */ - - cl->line = (char *)smb_xmalloc(INIT_ALLOC); - - /* - * Now read in the chars to EOL. Don't store the EOL in the - * line. What about CR? - */ - - while ((rc = read(fd, &ch, 1)) == 1 && ch != '\n') { - if (ch == '\r') continue; /* skip CR */ - if (i == cl->len-1) { - /* - * Allocate some more memory - */ - if ((cl->line = realloc(cl->line, cl->len + INIT_ALLOC)) == NULL) { - DEBUG(0, ("Unable to realloc space for line: %s\n", - strerror(errno))); - exit(1); - } - cl->len += INIT_ALLOC; - } - cl->line[i] = ch; - i++; - } - - /* read 0 and we were at loc'n 0, return NULL */ - if (rc == 0 && i == 0) { - free_cmd_line(cl); - return NULL; - } - - cl->line[i] = '\0'; - cl->line_len = i; - - return cl; - -} - -/* - * parse_value: parse out a value. We pull it apart as: - * - * <value> ::= <value-name>=<type>:<value-string> - * - * <value-name> ::= char-string-without-spaces | '"' char-string '"' - * - * If it parsed OK, return the <value-name> as a string, and the - * value type and value-string in parameters. - * - * The value name can be empty. There can only be one empty name in - * a list of values. A value of - removes the value entirely. - */ - -static char *parse_name(char *nstr) -{ - int len = 0, start = 0; - if (!nstr) return NULL; - - len = strlen(nstr); - - while (len && nstr[len - 1] == ' ') len--; - - nstr[len] = 0; /* Trim any spaces ... if there were none, doesn't matter */ - - /* - * Beginning and end should be '"' or neither should be so - */ - if ((nstr[0] == '"' && nstr[len - 1] != '"') || - (nstr[0] != '"' && nstr[len - 1] == '"')) - return NULL; - - if (nstr[0] == '"') { - start = 1; - len -= 2; - } - - return strndup(&nstr[start], len); -} - -static int parse_value_type(char *tstr) -{ - int len = strlen(tstr); - - while (len && tstr[len - 1] == ' ') len--; - tstr[len] = 0; - - if (strcmp(tstr, "REG_DWORD") == 0) - return REG_DWORD; - else if (strcmp(tstr, "dword") == 0) - return REG_DWORD; - else if (strcmp(tstr, "REG_EXPAND_SZ") == 0) - return REG_EXPAND_SZ; - else if (strcmp(tstr, "REG_BIN") == 0) - return REG_BINARY; - else if (strcmp(tstr, "REG_SZ") == 0) - return REG_SZ; - else if (strcmp(tstr, "REG_MULTI_SZ") == 0) - return REG_MULTI_SZ; - else if (strcmp(tstr, "-") == 0) - return REG_DELETE; - - return 0; -} - -static char *parse_val_str(char *vstr) -{ - - return strndup(vstr, strlen(vstr)); - -} - -static char *parse_value(struct cmd_line *cl, int *vtype, char **val) -{ - char *p1 = NULL, *p2 = NULL, *nstr = NULL, *tstr = NULL, *vstr = NULL; - - if (!cl || !vtype || !val) return NULL; - if (!cl->line[0]) return NULL; - - p1 = strdup(cl->line); - /* FIXME: Better return codes etc ... */ - if (!p1) return NULL; - p2 = strchr(p1, '='); - if (!p2) return NULL; - - *p2 = 0; p2++; /* Split into two strings at p2 */ - - /* Now, parse the name ... */ - - nstr = parse_name(p1); - if (!nstr) goto error; - - /* Now, split the remainder and parse on type and val ... */ - - tstr = p2; - while (*tstr == ' ') tstr++; /* Skip leading white space */ - p2 = strchr(p2, ':'); - - if (p2) { - *p2 = 0; p2++; /* split on the : */ - } - - *vtype = parse_value_type(tstr); - - if (!vtype) goto error; - - if (!p2 || !*p2) return nstr; - - /* Now, parse the value string. It should return a newly malloc'd string */ - - while (*p2 == ' ') p2++; /* Skip leading space */ - vstr = parse_val_str(p2); - - if (!vstr) goto error; - - *val = vstr; - - return nstr; - - error: - if (p1) free(p1); - if (nstr) free(nstr); - if (vstr) free(vstr); - return NULL; -} - -/* - * Parse out a key. Look for a correctly formatted key [...] - * and whether it is a delete or add? A delete is signalled - * by a - in front of the key. - * Assumes that there are no leading and trailing spaces - */ - -static char *parse_key(struct cmd_line *cl, int *cmd) -{ - int start = 1; - char *tmp; - - if (cl->line[0] != '[' || - cl->line[cl->line_len - 1] != ']') return NULL; - if (cl->line_len == 2) return NULL; - *cmd = CMD_ADD_KEY; - if (cl->line[1] == '-') { - if (cl->line_len == 3) return NULL; - start = 2; - *cmd = CMD_DEL_KEY; - } - tmp = smb_xmalloc(cl->line_len - 1 - start + 1); - strncpy(tmp, &cl->line[start], cl->line_len - 1 - start); - tmp[cl->line_len - 1 - start] = 0; - return tmp; -} - -/* - * Parse a line to determine if we have a key or a value - * We only check for key or val ... - */ - -static int parse_line(struct cmd_line *cl) -{ - - if (!cl || cl->len == 0) return 0; - - if (cl->line[0] == '[') /* No further checking for now */ - return CMD_KEY; - else - return CMD_VAL; -} - -/* - * We seek to offset 0, read in the required number of bytes, - * and compare to the correct value. - * We then seek back to the original location - */ -static int regedit4_file_type(int fd) -{ - int cur_ofs = 0; - char desc[9]; - - cur_ofs = lseek(fd, 0, SEEK_CUR); /* Get current offset */ - if (cur_ofs < 0) { - DEBUG(0, ("Unable to get current offset: (%d) %s\n", cur_ofs, strerror(errno))); - exit(1); /* FIXME */ - } - - if (cur_ofs) { - lseek(fd, 0, SEEK_SET); - } - - if (read(fd, desc, 8) < 8) { - DEBUG(0, ("Unable to read command file format\n")); - exit(2); /* FIXME */ - } - - desc[8] = 0; - - if (strcmp(desc, FMT_STRING_REGEDIT4) == 0) { - if (cur_ofs) { - lseek(fd, cur_ofs, SEEK_SET); - } else { - skip_to_eol(fd); - } - return FMT_REGEDIT4; - } - - return FMT_UNREC; -} - -/* - * Run though the data in the line and strip anything after a comment - * char. - */ -static void strip_comment(struct cmd_line *cl) -{ - int i; - - if (!cl) return; - - for (i = 0; i < cl->line_len; i++) { - if (cl->line[i] == ';') { - cl->line[i] = '\0'; - cl->line_len = i; - return; - } - } -} - -/* - * Get a command ... This consists of possibly multiple lines: - * [key] - * values* - * possibly Empty line - * - * value ::= <value-name>=<value-type>':'<value-string> - * <value-name> is some path, possibly enclosed in quotes ... - * We alctually look for the next key to terminate a previous key - * if <value-type> == '-', then it is a delete type. - */ -static CMD *regedit4_get_cmd(int fd) -{ - struct command_s *cmd = NULL; - struct cmd_line *cl = NULL; - struct val_spec_list *vl = NULL; - - cmd = malloc_p(struct command_s); - if (!cmd) - return NULL; - - cmd->cmd = CMD_NONE; - cmd->key = NULL; - cmd->val_count = 0; - cmd->val_spec_list = cmd->val_spec_last = NULL; - while ((cl = get_cmd_line(fd))) { - - /* - * If it is an empty command line, and we already have a key - * then exit from here ... FIXME: Clean up the parser - */ - - if (cl->line_len == 0 && cmd->key) { - free_cmd_line(cl); - break; - } - - strip_comment(cl); /* remove anything beyond a comment char */ - trim_string(cl->line, " \t", " \t"); - - if (!cl->line[0]) { /* An empty line */ - free_cmd_line(cl); - } - else { /* Else, non-empty ... */ - /* - * Parse out the bits ... - */ - switch (parse_line(cl)) { - case CMD_KEY: - if ((cmd->key = parse_key(cl, &cmd->cmd)) == NULL) { - DEBUG(0, ("Error parsing key from line: ")); - print_line(cl); - DEBUG(0, ("\n")); - } - break; - - case CMD_VAL: - /* - * We need to add the value stuff to the list - * There could be a \ on the end which we need to - * handle at some time - */ - vl = malloc_p(struct val_spec_list); - if (!vl) - return NULL; - vl->next = NULL; - vl->val = NULL; - vl->name = parse_value(cl, &vl->type, &vl->val); - if (!vl->name) goto error; - if (cmd->val_spec_list == NULL) { - cmd->val_spec_list = cmd->val_spec_last = vl; - } - else { - cmd->val_spec_last->next = vl; - cmd->val_spec_last = vl; - } - cmd->val_count++; - break; - - default: - DEBUG(0, ("Unrecognized line in command file: \n")); - print_line(cl); - break; - } - } - - } - if (!cmd->cmd) goto error; /* End of file ... */ - - return cmd; - - error: - if (vl) free(vl); - if (cmd) free_cmd(cmd); - return NULL; -} - -static int regedit4_exec_cmd(CMD *cmd) -{ - - return 0; -} - -static int editreg_1_0_file_type(int fd) -{ - int cur_ofs = 0; - char desc[11]; - - cur_ofs = lseek(fd, 0, SEEK_CUR); /* Get current offset */ - if (cur_ofs < 0) { - DEBUG(0, ("Unable to get current offset: %s\n", strerror(errno))); - exit(1); /* FIXME */ - } - - if (cur_ofs) { - lseek(fd, 0, SEEK_SET); - } - - if (read(fd, desc, 10) < 10) { - DEBUG(0, ("Unable to read command file format\n")); - exit(2); /* FIXME */ - } - - desc[10] = 0; - - if (strcmp(desc, FMT_STRING_EDITREG1_0) == 0) { - lseek(fd, cur_ofs, SEEK_SET); - return FMT_REGEDIT4; - } - - return FMT_UNREC; -} - -static CMD *editreg_1_0_get_cmd(int fd) +int main(int argc, char **argv) { - return NULL; -} - -static int editreg_1_0_exec_cmd(CMD *cmd) -{ - - return -1; -} - -typedef struct command_ops_s { - int type; - int (*file_type)(int fd); - CMD *(*get_cmd)(int fd); - int (*exec_cmd)(CMD *cmd); -} CMD_OPS; - -static CMD_OPS default_cmd_ops[] = { - {0, regedit4_file_type, regedit4_get_cmd, regedit4_exec_cmd}, - {1, editreg_1_0_file_type, editreg_1_0_get_cmd, editreg_1_0_exec_cmd}, - {-1, NULL, NULL, NULL} -}; - -typedef struct command_file_s { - char *name; - int type, fd; - CMD_OPS cmd_ops; -} CMD_FILE; - -/* - * Create a new command file structure - */ - -static CMD_FILE *cmd_file_create(const char *file) -{ - CMD_FILE *tmp; - struct stat sbuf; - int i = 0; - - /* - * Let's check if the file exists ... - * No use creating the cmd_file structure if the file does not exist - */ - - if (stat(file, &sbuf) < 0) { /* Not able to access file */ - DEBUG(0,("Stat on %s failed\n", file)); - return NULL; - } - - tmp = malloc_p(CMD_FILE); - if (!tmp) - return NULL; - - /* - * Let's fill in some of the fields; - */ - - tmp->name = strdup(file); - - if ((tmp->fd = open(file, O_RDONLY, 666)) < 0) { - DEBUG(0,("Error opening %s\n", file)); - free(tmp); - return NULL; - } - - /* - * Now, try to find the format by indexing through the table - */ - while (default_cmd_ops[i].type != -1) { - if ((tmp->type = default_cmd_ops[i].file_type(tmp->fd)) >= 0) { - tmp->cmd_ops = default_cmd_ops[i]; - return tmp; - } - i++; - } - - /* - * If we got here, return NULL, as we could not figure out the type - * of command file. - * - * What about errors? - */ - - free(tmp); - DEBUG(0,("Unknown type\n")); - return NULL; -} - -/* - * Extract commands from the command file, and execute them. - * We pass a table of command callbacks for that - */ - -/* FIXME */ - -/* - * Main code from here on ... - */ - -/* - * key print function here ... - */ - -/* - * Sec Desc print functions - */ - -char *str_type(uint8_t type); - -static int nt_apply_reg_command_file(struct registry_context *r, const char *cmd_file_name) -{ - CMD *cmd; - BOOL modified = False; - CMD_FILE *cmd_file = NULL; - TALLOC_CTX *mem_ctx = talloc_init("apply_cmd_file"); - struct registry_key *tmp = NULL; - WERROR error; - cmd_file = cmd_file_create(cmd_file_name); - - while ((cmd = cmd_file->cmd_ops.get_cmd(cmd_file->fd)) != NULL) { - - /* - * Now, apply the requests to the tree ... - */ - switch (cmd->cmd) { - case CMD_ADD_KEY: - error = reg_open_key_abs(mem_ctx, r, cmd->key, &tmp); - - /* If we found it, apply the other bits, else create such a key */ - if (W_ERROR_EQUAL(error, WERR_DEST_NOT_FOUND)) { - if(!W_ERROR_IS_OK(reg_key_add_abs(mem_ctx, r, cmd->key, 0, NULL, &tmp))) { - DEBUG(0, ("Error adding new key '%s'\n", cmd->key)); - continue; - } - modified = True; - } - - while (cmd->val_count) { - VAL_SPEC_LIST *val = cmd->val_spec_list; - - if (val->type == REG_DELETE) { - error = reg_del_value(tmp, val->name); - if(!W_ERROR_IS_OK(error)) { - DEBUG(0, ("Error removing value '%s'\n", val->name)); - } - modified = True; - } else { - DATA_BLOB blob; - blob.data = (uint8_t *)val->val; - blob.length = strlen(val->val); - if(!W_ERROR_IS_OK(reg_val_set(tmp, val->name, val->type, blob))) { - DEBUG(0, ("Error adding new value '%s'\n", val->name)); - continue; - } - modified = True; - } - - cmd->val_spec_list = val->next; - free_val_spec_list(val); - cmd->val_count--; - } - - break; - - case CMD_DEL_KEY: - /* - * Any value does not matter ... - * Find the key if it exists, and delete it ... - */ - - error = reg_key_del_abs(r, cmd->key); - if(!W_ERROR_IS_OK(error)) { - DEBUG(0, ("Unable to delete key '%s'\n", cmd->key)); - continue; - } - modified = True; - break; - } - } - free_cmd(cmd); - - return modified; -} - - int main(int argc, char **argv) -{ - int opt; + int opt; poptContext pc; const char *patch; struct registry_context *h; const char *remote = NULL; + struct reg_diff *diff; WERROR error; struct poptOption long_options[] = { POPT_AUTOHELP @@ -786,10 +62,15 @@ static int nt_apply_reg_command_file(struct registry_context *r, const char *cmd } patch = poptGetArg(pc); - if(!patch) patch = "/dev/stdin"; poptFreeContext(pc); - nt_apply_reg_command_file(h, patch); + diff = reg_diff_load(NULL, patch); + if (!diff) { + fprintf(stderr, "Unable to load registry patch from `%s'\n", patch); + return 1; + } + + reg_diff_apply(diff, h); return 0; } diff --git a/source4/lib/registry/tools/regshell.c b/source4/lib/registry/tools/regshell.c index 24979943b3..cd67f09c33 100644 --- a/source4/lib/registry/tools/regshell.c +++ b/source4/lib/registry/tools/regshell.c @@ -92,7 +92,7 @@ static struct registry_key *cmd_set(TALLOC_CTX *mem_ctx, struct registry_context fprintf(stderr, "Usage: set value-name type value\n"); } else { struct registry_value *val; - if (reg_string_to_val(mem_ctx, argv[2], argv[3], &val)) { + if (reg_string_to_val(mem_ctx, argv[2], argv[3], &val->data_type, &val->data)) { WERROR error = reg_val_set(cur, argv[1], val->data_type, val->data); if (!W_ERROR_IS_OK(error)) { fprintf(stderr, "Error setting value: %s\n", win_errstr(error)); @@ -140,7 +140,7 @@ static struct registry_key *cmd_print(TALLOC_CTX *mem_ctx, struct registry_conte return NULL; } - printf("%s\n%s\n", str_regtype(value->data_type), reg_val_data_string(mem_ctx, value)); + printf("%s\n%s\n", str_regtype(value->data_type), reg_val_data_string(mem_ctx, value->data_type, &value->data)); return NULL; } @@ -159,7 +159,7 @@ static struct registry_key *cmd_ls(TALLOC_CTX *mem_ctx, struct registry_context } for(i = 0; W_ERROR_IS_OK(error = reg_key_get_value_by_index(mem_ctx, cur, i, &value)); i++) { - printf("V \"%s\" %s %s\n", value->name, str_regtype(value->data_type), reg_val_data_string(mem_ctx, value)); + printf("V \"%s\" %s %s\n", value->name, str_regtype(value->data_type), reg_val_data_string(mem_ctx, value->data_type, &value->data)); } return NULL; |