X-Git-Url: http://git.samba.org/samba.git/?a=blobdiff_plain;f=source4%2Flib%2Fregistry%2Fpatchfile.c;h=8069ed70f8a3cc9ae1592696b7e4001f401cf929;hb=HEAD;hp=d49d46250d3d7b5d70da6afe9069be84cdc1dc59;hpb=66092ced5e1dc4d35923a3c90bcb3214a885b17d;p=bbaumbach%2Fsamba-autobuild%2F.git diff --git a/source4/lib/registry/patchfile.c b/source4/lib/registry/patchfile.c index d49d46250d3..8069ed70f8a 100644 --- a/source4/lib/registry/patchfile.c +++ b/source4/lib/registry/patchfile.c @@ -4,7 +4,7 @@ Copyright (C) Jelmer Vernooij 2004-2007 Copyright (C) Wilco Baan Hofman 2006 - Copyright (C) Matthias Dieter Wallnöfer 2008 + Copyright (C) Matthias Dieter Wallnöfer 2008-2010 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 @@ -23,16 +23,13 @@ #include "includes.h" #include "lib/registry/registry.h" #include "system/filesys.h" -#include "param/param.h" _PUBLIC_ WERROR reg_preg_diff_load(int fd, - struct smb_iconv_convenience *iconv_convenience, const struct reg_diff_callbacks *callbacks, void *callback_data); _PUBLIC_ WERROR reg_dotreg_diff_load(int fd, - struct smb_iconv_convenience *iconv_convenience, const struct reg_diff_callbacks *callbacks, void *callback_data); @@ -45,7 +42,7 @@ WERROR reg_generate_diff_key(struct registry_key *oldkey, const struct reg_diff_callbacks *callbacks, void *callback_data) { - int i; + unsigned int i; struct registry_key *t1 = NULL, *t2 = NULL; char *tmppath; const char *keyname1; @@ -69,7 +66,7 @@ WERROR reg_generate_diff_key(struct registry_key *oldkey, old_num_values = 0; } - /* Subkeys that were deleted */ + /* Subkeys that were changed or deleted */ for (i = 0; i < old_num_subkeys; i++) { error1 = reg_key_get_subkey_by_index(mem_ctx, oldkey, i, &keyname1, NULL, NULL); @@ -81,29 +78,33 @@ WERROR reg_generate_diff_key(struct registry_key *oldkey, if (newkey != NULL) { error2 = reg_open_key(mem_ctx, newkey, keyname1, &t2); - - if (W_ERROR_IS_OK(error2)) - continue; } else { - error2 = WERR_BADFILE; + error2 = WERR_FILE_NOT_FOUND; t2 = NULL; } - if (!W_ERROR_EQUAL(error2, WERR_BADFILE)) { - DEBUG(0, ("Error occured while getting subkey by name: %s\n", + if (!W_ERROR_IS_OK(error2) && !W_ERROR_EQUAL(error2, WERR_FILE_NOT_FOUND)) { + DEBUG(0, ("Error occurred while getting subkey by name: %s\n", win_errstr(error2))); talloc_free(mem_ctx); return error2; } - /* newkey didn't have such a subkey, add del diff */ + /* if "error2" is going to be "WERR_FILE_NOT_FOUND", then newkey */ + /* didn't have such a subkey and therefore add a del diff */ tmppath = talloc_asprintf(mem_ctx, "%s\\%s", path, keyname1); - callbacks->del_key(callback_data, tmppath); + if (tmppath == NULL) { + DEBUG(0, ("Out of memory\n")); + talloc_free(mem_ctx); + return WERR_NOT_ENOUGH_MEMORY; + } + if (!W_ERROR_IS_OK(error2)) + callbacks->del_key(callback_data, tmppath); /* perform here also the recursive invocation */ error1 = reg_open_key(mem_ctx, oldkey, keyname1, &t1); if (!W_ERROR_IS_OK(error1)) { - DEBUG(0, ("Error occured while getting subkey by name: %s\n", + DEBUG(0, ("Error occurred while getting subkey by name: %s\n", win_errstr(error1))); talloc_free(mem_ctx); return error1; @@ -145,25 +146,30 @@ WERROR reg_generate_diff_key(struct registry_key *oldkey, if (W_ERROR_IS_OK(error2)) continue; } else { - error2 = WERR_BADFILE; + error2 = WERR_FILE_NOT_FOUND; t1 = NULL; } - if (!W_ERROR_EQUAL(error2, WERR_BADFILE)) { + if (!W_ERROR_EQUAL(error2, WERR_FILE_NOT_FOUND)) { DEBUG(0, ("Error occurred while getting subkey by name: %s\n", win_errstr(error2))); talloc_free(mem_ctx); return error2; } - /* oldkey didn't have such a subkey, add add diff */ + /* oldkey didn't have such a subkey, add a add diff */ tmppath = talloc_asprintf(mem_ctx, "%s\\%s", path, keyname1); + if (tmppath == NULL) { + DEBUG(0, ("Out of memory\n")); + talloc_free(mem_ctx); + return WERR_NOT_ENOUGH_MEMORY; + } callbacks->add_key(callback_data, tmppath); /* perform here also the recursive invocation */ error1 = reg_open_key(mem_ctx, newkey, keyname1, &t2); if (!W_ERROR_IS_OK(error1)) { - DEBUG(0, ("Error occured while getting subkey by name: %s\n", + DEBUG(0, ("Error occurred while getting subkey by name: %s\n", win_errstr(error1))); talloc_free(mem_ctx); return error1; @@ -177,7 +183,7 @@ WERROR reg_generate_diff_key(struct registry_key *oldkey, for(i = 0; i < new_num_values; i++) { const char *name; uint32_t type1, type2; - DATA_BLOB contents1, contents2; + DATA_BLOB contents1 = { NULL, 0 }, contents2 = { NULL, 0 }; error1 = reg_key_get_value_by_index(mem_ctx, newkey, i, &name, &type1, &contents1); @@ -193,10 +199,10 @@ WERROR reg_generate_diff_key(struct registry_key *oldkey, name, &type2, &contents2); } else - error2 = WERR_BADFILE; + error2 = WERR_FILE_NOT_FOUND; if (!W_ERROR_IS_OK(error2) - && !W_ERROR_EQUAL(error2, WERR_BADFILE)) { + && !W_ERROR_EQUAL(error2, WERR_FILE_NOT_FOUND)) { DEBUG(0, ("Error occurred while getting value by name: %s\n", win_errstr(error2))); talloc_free(mem_ctx); @@ -204,19 +210,27 @@ WERROR reg_generate_diff_key(struct registry_key *oldkey, } if (W_ERROR_IS_OK(error2) - && (data_blob_cmp(&contents1, &contents2) == 0) - && (type1 == type2)) + && (data_blob_cmp(&contents1, &contents2) == 0) + && (type1 == type2)) { + talloc_free(discard_const_p(char, name)); + talloc_free(contents1.data); + talloc_free(contents2.data); continue; + } callbacks->set_value(callback_data, path, name, type1, contents1); + + talloc_free(discard_const_p(char, name)); + talloc_free(contents1.data); + talloc_free(contents2.data); } /* Values that were deleted */ for (i = 0; i < old_num_values; i++) { const char *name; uint32_t type; - DATA_BLOB contents; + DATA_BLOB contents = { NULL, 0 }; error1 = reg_key_get_value_by_index(mem_ctx, oldkey, i, &name, &type, &contents); @@ -231,12 +245,15 @@ WERROR reg_generate_diff_key(struct registry_key *oldkey, error2 = reg_key_get_value_by_name(mem_ctx, newkey, name, &type, &contents); else - error2 = WERR_BADFILE; + error2 = WERR_FILE_NOT_FOUND; - if (W_ERROR_IS_OK(error2)) + if (W_ERROR_IS_OK(error2)) { + talloc_free(discard_const_p(char, name)); + talloc_free(contents.data); continue; + } - if (!W_ERROR_EQUAL(error2, WERR_BADFILE)) { + if (!W_ERROR_EQUAL(error2, WERR_FILE_NOT_FOUND)) { DEBUG(0, ("Error occurred while getting value by name: %s\n", win_errstr(error2))); talloc_free(mem_ctx); @@ -244,6 +261,9 @@ WERROR reg_generate_diff_key(struct registry_key *oldkey, } callbacks->del_value(callback_data, path, name); + + talloc_free(discard_const_p(char, name)); + talloc_free(contents.data); } talloc_free(mem_ctx); @@ -258,7 +278,7 @@ _PUBLIC_ WERROR reg_generate_diff(struct registry_context *ctx1, const struct reg_diff_callbacks *callbacks, void *callback_data) { - int i; + unsigned int i; WERROR error; for (i = 0; reg_predefined_keys[i].name; i++) { @@ -267,7 +287,7 @@ _PUBLIC_ WERROR reg_generate_diff(struct registry_context *ctx1, error = reg_get_predefined_key(ctx1, reg_predefined_keys[i].handle, &r1); if (!W_ERROR_IS_OK(error) && - !W_ERROR_EQUAL(error, WERR_BADFILE)) { + !W_ERROR_EQUAL(error, WERR_FILE_NOT_FOUND)) { DEBUG(0, ("Unable to open hive %s for backend 1\n", reg_predefined_keys[i].name)); continue; @@ -276,12 +296,27 @@ _PUBLIC_ WERROR reg_generate_diff(struct registry_context *ctx1, error = reg_get_predefined_key(ctx2, reg_predefined_keys[i].handle, &r2); if (!W_ERROR_IS_OK(error) && - !W_ERROR_EQUAL(error, WERR_BADFILE)) { + !W_ERROR_EQUAL(error, WERR_FILE_NOT_FOUND)) { DEBUG(0, ("Unable to open hive %s for backend 2\n", reg_predefined_keys[i].name)); continue; } + /* if "r1" is NULL (old hive) and "r2" isn't (new hive) then + * the hive doesn't exist yet and we have to generate an add + * diff */ + if ((r1 == NULL) && (r2 != NULL)) { + callbacks->add_key(callback_data, + reg_predefined_keys[i].name); + } + /* if "r1" isn't NULL (old hive) and "r2" is (new hive) then + * the hive shouldn't exist anymore and we have to generate a + * del diff */ + if ((r1 != NULL) && (r2 == NULL)) { + callbacks->del_key(callback_data, + reg_predefined_keys[i].name); + } + error = reg_generate_diff_key(r1, r2, reg_predefined_keys[i].name, callbacks, callback_data); @@ -301,7 +336,6 @@ _PUBLIC_ WERROR reg_generate_diff(struct registry_context *ctx1, * Load diff file */ _PUBLIC_ WERROR reg_diff_load(const char *filename, - struct smb_iconv_convenience *iconv_convenience, const struct reg_diff_callbacks *callbacks, void *callback_data) { @@ -312,13 +346,14 @@ _PUBLIC_ WERROR reg_diff_load(const char *filename, if (fd == -1) { DEBUG(0, ("Error opening registry patch file `%s'\n", filename)); - return WERR_GENERAL_FAILURE; + return WERR_GEN_FAILURE; } if (read(fd, &hdr, 4) != 4) { DEBUG(0, ("Error reading registry patch file `%s'\n", filename)); - return WERR_GENERAL_FAILURE; + close(fd); + return WERR_GEN_FAILURE; } /* Reset position in file */ @@ -334,10 +369,10 @@ _PUBLIC_ WERROR reg_diff_load(const char *filename, #endif if (strncmp(hdr, "PReg", 4) == 0) { /* Must be a GPO Registry.pol file */ - return reg_preg_diff_load(fd, iconv_convenience, callbacks, callback_data); + return reg_preg_diff_load(fd, callbacks, callback_data); } else { /* Must be a normal .REG file */ - return reg_dotreg_diff_load(fd, iconv_convenience, callbacks, callback_data); + return reg_dotreg_diff_load(fd, callbacks, callback_data); } } @@ -353,6 +388,7 @@ static WERROR reg_diff_apply_add_key(void *_ctx, const char *key_name) /* Recursively create the path */ buf = talloc_strdup(ctx, key_name); + W_ERROR_HAVE_NO_MEMORY(buf); buf_ptr = buf; while (*buf_ptr++ != '\0' ) { @@ -367,9 +403,12 @@ static WERROR reg_diff_apply_add_key(void *_ctx, const char *key_name) return error; } *buf_ptr++ = '\\'; + talloc_free(tmp); } } + talloc_free(buf); + /* Add the key */ error = reg_key_add_abs(ctx, ctx, key_name, 0, NULL, &tmp); @@ -379,20 +418,21 @@ static WERROR reg_diff_apply_add_key(void *_ctx, const char *key_name) key_name, win_errstr(error))); return error; } + talloc_free(tmp); + return WERR_OK; } static WERROR reg_diff_apply_del_key(void *_ctx, const char *key_name) { struct registry_context *ctx = (struct registry_context *)_ctx; - WERROR error; - error = reg_key_del_abs(ctx, key_name); + /* We can't proof here for success, because a common superkey could */ + /* have been deleted before the subkey's (diff order). This removed */ + /* therefore all children recursively and the "WERR_FILE_NOT_FOUND" result is */ + /* expected. */ - if(!W_ERROR_IS_OK(error)) { - DEBUG(0, ("Unable to delete key '%s'\n", key_name)); - return error; - } + reg_key_del_abs(ctx, key_name); return WERR_OK; } @@ -408,7 +448,7 @@ static WERROR reg_diff_apply_set_value(void *_ctx, const char *path, /* Open key */ error = reg_open_key_abs(ctx, ctx, path, &tmp); - if (W_ERROR_EQUAL(error, WERR_BADFILE)) { + if (W_ERROR_EQUAL(error, WERR_FILE_NOT_FOUND)) { DEBUG(0, ("Error opening key '%s'\n", path)); return error; } @@ -421,6 +461,8 @@ static WERROR reg_diff_apply_set_value(void *_ctx, const char *path, return error; } + talloc_free(tmp); + return WERR_OK; } @@ -439,12 +481,13 @@ static WERROR reg_diff_apply_del_value(void *_ctx, const char *key_name, return error; } - error = reg_del_value(tmp, value_name); + error = reg_del_value(ctx, tmp, value_name); if (!W_ERROR_IS_OK(error)) { DEBUG(0, ("Error deleting value '%s'\n", value_name)); return error; } + talloc_free(tmp); return WERR_OK; } @@ -454,8 +497,7 @@ static WERROR reg_diff_apply_del_all_values(void *_ctx, const char *key_name) struct registry_context *ctx = (struct registry_context *)_ctx; struct registry_key *key; WERROR error; - int i; - uint32_t num_values; + const char *value_name; error = reg_open_key_abs(ctx, ctx, key_name, &key); @@ -465,23 +507,28 @@ static WERROR reg_diff_apply_del_all_values(void *_ctx, const char *key_name) } W_ERROR_NOT_OK_RETURN(reg_key_get_info(ctx, key, NULL, - NULL, &num_values, NULL, NULL, NULL, NULL)); + NULL, NULL, NULL, NULL, NULL, NULL)); - for (i = 0; i < num_values; i++) { - const char *name; - W_ERROR_NOT_OK_RETURN(reg_key_get_value_by_index(ctx, key, i, - &name, - NULL, NULL)); - W_ERROR_NOT_OK_RETURN(reg_del_value(key, name)); + while (W_ERROR_IS_OK(reg_key_get_value_by_index( + ctx, key, 0, &value_name, NULL, NULL))) { + error = reg_del_value(ctx, key, value_name); + if (!W_ERROR_IS_OK(error)) { + DEBUG(0, ("Error deleting value '%s'\n", value_name)); + return error; + } + talloc_free(discard_const_p(char, value_name)); } + talloc_free(key); + return WERR_OK; } /** * Apply diff to a registry context */ -_PUBLIC_ WERROR reg_diff_apply(struct registry_context *ctx, const char *filename) +_PUBLIC_ WERROR reg_diff_apply(struct registry_context *ctx, + const char *filename) { struct reg_diff_callbacks callbacks; @@ -492,6 +539,5 @@ _PUBLIC_ WERROR reg_diff_apply(struct registry_context *ctx, const char *filenam callbacks.del_all_values = reg_diff_apply_del_all_values; callbacks.done = NULL; - return reg_diff_load(filename, lp_iconv_convenience(global_loadparm), - &callbacks, ctx); + return reg_diff_load(filename, &callbacks, ctx); }