r10604: Put in the new registry "patchfile" code (similar to ldif
authorJelmer Vernooij <jelmer@samba.org>
Thu, 29 Sep 2005 11:51:06 +0000 (11:51 +0000)
committerGerald (Jerry) Carter <jerry@samba.org>
Wed, 10 Oct 2007 18:39:11 +0000 (13:39 -0500)
for LDB); not finished yet.

source/gtk/tools/gregedit.c
source/include/structs.h
source/lib/registry/TODO
source/lib/registry/common/reg_util.c
source/lib/registry/config.mk
source/lib/registry/registry.h
source/lib/registry/tools/regdiff.c
source/lib/registry/tools/regpatch.c
source/lib/registry/tools/regshell.c

index 5de09eb84e1060bf9481cf4015f478f386dcb948..ae34bf274540eb34438e7cddbee0f2efb582db14 100644 (file)
@@ -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);
index ca28c1fc7af2e52997fd62af01da4d3ac78fe330..9d30e64dbc2ad2758e8b421b9cfa56a4a9a4a20e 100644 (file)
@@ -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;
index 3f48d031e1293f184393996b4b0c0e4eea365888..518edf6795868b6de745e062761616379105aca9 100644 (file)
@@ -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
index ae30839cca29b6132b618ada9ab6b92129909b95..75f9d3cf003fc463b42732a24f1bdf675a902b79 100644 (file)
@@ -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;
index 87e0779007b9a06b3d0b632bc5631026df588a93..8a579d45646058095dc71f5560fddbba128710f5 100644 (file)
@@ -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
index 69f360673688b0fb24d061893118b88cc9daf61d..ebfb2caf5c7008e211020e3fec4aad5e27ae7e69 100644 (file)
@@ -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 */
index 3d8201330eaab40b22b9995e2565b447340d3da3..92fe53ff67b754094162acc2727293cc7741382b 100644 (file)
@@ -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
 #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;
 }
index 98e6c0ff5d26d67ecc7fbb20022fcd8942a6103c..eca14741a599211d4361e84f7751bdb9e91d8f6b 100644 (file)
@@ -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
 #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;
 }
index 24979943b32bae67657eda3dc115da031dc69bd1..cd67f09c33f72bb9b13ea4fccb4671b2b15e11ab 100644 (file)
@@ -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;