[SCM] Samba Shared Repository - branch v3-6-test updated

Michael Adam obnox at samba.org
Mon Apr 4 15:59:21 MDT 2011


The branch, v3-6-test has been updated
       via  0c3a359 s3-net: add command "net idmap check"
       via  0d537ea s3: add function srprs_quoted to parse strings written with cbuf_print_quoted
       via  c3cdbe5 s3: add function cbuf_print_quoted
       via  4b1c0bc s3: add function dbwrap_traverse
       via  d059345 s3: add function dbwrap_trans_traverse
       via  246dab7 s3: fix cbuf_swapptr
      from  25312f6 Move SET_STAT_INVALID call added by Volker as fix for bug 8042 - Newly create files are always failed with NT_STATUS_FILE_IS_A_DIRECTORY

http://gitweb.samba.org/?p=samba.git;a=shortlog;h=v3-6-test


- Log -----------------------------------------------------------------
commit 0c3a359de1491828439ee5bbe4b05364b814d068
Author: Gregor Beck <gbeck at sernet.de>
Date:   Fri Jan 28 10:55:58 2011 +0100

    s3-net: add command "net idmap check"
    
    This is a tool to check the consistency of an idmap tdb database.
    
    The default mode is to scan the database and list invalid entries,
    e.g. records with an invalid format, or records which are valid
    but for which the reverse mapping entry is missing.
    
    With the "--repair" switch, one can enter an interactive
    repair mode which will prompt for each invalid entry found
    with the option to delete, skip or edit the record.
    
    There is also a non-interactive repair mode triggered by "--auto"
    which will remove all records with invalid content and fill up
    mappings which are missing the reverse entry.
    
    The "--test" parameter lets "net idmap check" only list the
    changes that would be written and not actually commit them to
    the database.
    
    The "--lock" option allows to lock the database already in the
    first reading traverse, in order to remove the race when the
    database has to be closed and reopened again before writing
    the changes.
    
    Signed-off-by: Michael Adam <obnox at samba.org>
    
    Autobuild-User: Michael Adam <obnox at samba.org>
    Autobuild-Date: Mon Apr  4 18:21:09 CEST 2011 on sn-devel-104

commit 0d537ea63885cfb2b9577785bae9305feb5d19c9
Author: Gregor Beck <gbeck at sernet.de>
Date:   Thu Mar 17 10:22:25 2011 +0100

    s3: add function srprs_quoted to parse strings written with cbuf_print_quoted

commit c3cdbe566e0611ec72515e0ca129575d14b4ce32
Author: Gregor Beck <gbeck at sernet.de>
Date:   Thu Mar 17 10:20:30 2011 +0100

    s3: add function cbuf_print_quoted

commit 4b1c0bc3f258438253d09e414972eb12856dda92
Author: Gregor Beck <gbeck at sernet.de>
Date:   Fri Mar 18 14:39:15 2011 +0100

    s3: add function dbwrap_traverse

commit d0593450374933c9ca8858370b2ed3e5d9ff0b7f
Author: Gregor Beck <gbeck at sernet.de>
Date:   Wed Mar 16 09:13:40 2011 +0100

    s3: add function dbwrap_trans_traverse

commit 246dab79a4eae3b69476fb11e48db609e2dc5aa8
Author: Gregor Beck <gbeck at sernet.de>
Date:   Wed Mar 16 09:12:28 2011 +0100

    s3: fix cbuf_swapptr

-----------------------------------------------------------------------

Summary of changes:
 source3/Makefile.in                                |    2 +-
 source3/include/dbwrap.h                           |    7 +
 source3/lib/cbuf.c                                 |   35 +
 source3/lib/cbuf.h                                 |   17 +-
 source3/lib/dbwrap_util.c                          |   38 +
 source3/lib/srprs.c                                |   40 +
 source3/lib/srprs.h                                |   13 +-
 source3/utils/net.c                                |    3 +
 source3/utils/net.h                                |    3 +
 source3/utils/net_idmap.c                          |   47 +-
 source3/utils/net_idmap_check.c                    | 1005 ++++++++++++++++++++
 .../srv_epmapper.h => utils/net_idmap_check.h}     |   38 +-
 source3/wscript_build                              |    3 +-
 13 files changed, 1234 insertions(+), 17 deletions(-)
 create mode 100644 source3/utils/net_idmap_check.c
 copy source3/{rpc_server/epmapper/srv_epmapper.h => utils/net_idmap_check.h} (56%)


Changeset truncated at 500 lines:

diff --git a/source3/Makefile.in b/source3/Makefile.in
index 34f5f82..2b89545 100644
--- a/source3/Makefile.in
+++ b/source3/Makefile.in
@@ -1146,7 +1146,7 @@ LIBNET_SAMSYNC_OBJ = libnet/libnet_samsync.o \
 NET_OBJ1 = utils/net.o utils/net_ads.o utils/net_help.o \
 	   utils/net_rap.o utils/net_rpc.o utils/net_rpc_samsync.o \
 	   utils/net_rpc_join.o utils/net_time.o utils/net_lookup.o \
-	   utils/net_cache.o utils/net_groupmap.o utils/net_idmap.o \
+	   utils/net_cache.o utils/net_groupmap.o utils/net_idmap.o utils/net_idmap_check.o\
 	   utils/net_status.o utils/net_rpc_printer.o utils/net_rpc_rights.o \
 	   utils/net_rpc_service.o utils/net_rpc_registry.o utils/net_usershare.o \
 	   utils/netlookup.o utils/net_sam.o utils/net_rpc_shell.o \
diff --git a/source3/include/dbwrap.h b/source3/include/dbwrap.h
index 8dba624..ef35b00 100644
--- a/source3/include/dbwrap.h
+++ b/source3/include/dbwrap.h
@@ -127,6 +127,13 @@ NTSTATUS dbwrap_trans_delete_bystring(struct db_context *db, const char *key);
 NTSTATUS dbwrap_trans_do(struct db_context *db,
 			 NTSTATUS (*action)(struct db_context *, void *),
 			 void *private_data);
+NTSTATUS dbwrap_trans_traverse(struct db_context *db,
+			       int (*f)(struct db_record*, void*),
+			       void *private_data);
+NTSTATUS dbwrap_traverse(struct db_context *db,
+			 int (*f)(struct db_record*, void*),
+			 void *private_data);
+
 NTSTATUS dbwrap_delete_bystring_upper(struct db_context *db, const char *key);
 NTSTATUS dbwrap_store_bystring_upper(struct db_context *db, const char *key,
 				     TDB_DATA data, int flags);
diff --git a/source3/lib/cbuf.c b/source3/lib/cbuf.c
index e9763ae..42353f8 100644
--- a/source3/lib/cbuf.c
+++ b/source3/lib/cbuf.c
@@ -116,8 +116,10 @@ cbuf* cbuf_takeover(cbuf* b1, cbuf* b2)
 
 cbuf* cbuf_swapptr(cbuf* b, char** ptr, size_t len)
 {
+	void* p = talloc_parent(*ptr);
 	SWAP(b->buf, *ptr, char*);
 	talloc_steal(b, b->buf);
+	talloc_steal(p, *ptr);
 	b->size = talloc_get_size(b->buf);
 	b->pos  = (len == -1) ? strlen(b->buf) : len;
 
@@ -284,3 +286,36 @@ int cbuf_print_quoted_string(cbuf* ost, const char* s)
 		s++;
 	}
 }
+
+
+int cbuf_print_quoted(cbuf* ost, const char* s, size_t len)
+{
+	int n = 1;
+	int ret;
+	cbuf_reserve(ost, len+2);
+
+	cbuf_putc(ost,'"');
+
+	while(len--) {
+		switch (*s) {
+		case '"':
+		case '\\':
+			ret = cbuf_printf(ost, "\\%c", *s);
+			break;
+		default:
+			if (isprint(*s) && ((*s == ' ') || !isspace(*s))) {
+				ret = cbuf_putc(ost, *s);
+			} else {
+				ret = cbuf_printf(ost, "\\%02x", *s);
+			}
+		}
+		s++;
+		if (ret == -1) {
+			return -1;
+		}
+		n += ret;
+	}
+	ret = cbuf_putc(ost,'"');
+
+	return (ret == -1) ? -1 : (n + ret);
+}
diff --git a/source3/lib/cbuf.h b/source3/lib/cbuf.h
index ffb52d7..90318ec 100644
--- a/source3/lib/cbuf.h
+++ b/source3/lib/cbuf.h
@@ -225,11 +225,26 @@ char* cbuf_gets(cbuf* b, size_t idx);
  * @see srprs_quoted_string
  *
  * @param[out] ost outstream
- * @param[in]  s string
+ * @param[in]  s '\0' terminated string of printable characters.
  *
  * @return numner of bytes written, -1 on error
  */
 int cbuf_print_quoted_string(cbuf* ost, const char* s);
 
+/**
+ * Print quoted string to stream.
+ * Escapes nonprintable characters.
+ *
+ * @todo check for ssputc failure
+ * @see srprs_quoted
+ *
+ * @param[out] ost outstream
+ * @param[in]  s string of bytes
+ * @param[in]  len number of bytes
+ *
+ * @return numner of bytes written, -1 on error
+ */
+int cbuf_print_quoted(cbuf* ost, const char* s, size_t len);
+
 
 #endif /*__CBUF_H*/
diff --git a/source3/lib/dbwrap_util.c b/source3/lib/dbwrap_util.c
index 0020fc6..35f8a14 100644
--- a/source3/lib/dbwrap_util.c
+++ b/source3/lib/dbwrap_util.c
@@ -416,6 +416,44 @@ NTSTATUS dbwrap_trans_do(struct db_context *db,
 	return NT_STATUS_INTERNAL_DB_CORRUPTION;
 }
 
+struct dbwrap_trans_traverse_action_ctx {
+	int (*f)(struct db_record* rec, void* private_data);
+	void* private_data;
+};
+
+
+static NTSTATUS dbwrap_trans_traverse_action(struct db_context* db, void* private_data)
+{
+	struct dbwrap_trans_traverse_action_ctx* ctx =
+		(struct dbwrap_trans_traverse_action_ctx*)private_data;
+
+	int ret = db->traverse(db, ctx->f, ctx->private_data);
+
+	return (ret == -1) ? NT_STATUS_INTERNAL_DB_CORRUPTION : NT_STATUS_OK;
+}
+
+NTSTATUS dbwrap_trans_traverse(struct db_context *db,
+			       int (*f)(struct db_record*, void*),
+			       void *private_data)
+{
+	struct dbwrap_trans_traverse_action_ctx ctx = {
+		.f = f,
+		.private_data = private_data,
+	};
+	return dbwrap_trans_do(db, dbwrap_trans_traverse_action, &ctx);
+}
+
+NTSTATUS dbwrap_traverse(struct db_context *db,
+			 int (*f)(struct db_record*, void*),
+			 void *private_data)
+{
+	int ret = db->traverse(db, f, private_data);
+	return (ret == -1) ? NT_STATUS_INTERNAL_DB_CORRUPTION : NT_STATUS_OK;
+}
+
+
+
+
 NTSTATUS dbwrap_delete_bystring_upper(struct db_context *db, const char *key)
 {
 	char *key_upper;
diff --git a/source3/lib/srprs.c b/source3/lib/srprs.c
index 77464f5..5a032d2 100644
--- a/source3/lib/srprs.c
+++ b/source3/lib/srprs.c
@@ -183,3 +183,43 @@ bool srprs_line(const char** ptr, cbuf* str)
 		;
 	return true;
 }
+
+bool srprs_quoted(const char** ptr, cbuf* str)
+{
+	const char* pos = *ptr;
+	const size_t spos = cbuf_getpos(str);
+
+	if (!srprs_char(&pos, '"')) {
+		goto fail;
+	}
+
+	while (true) {
+		while (srprs_charsetinv(&pos, "\\\"", str))
+			;
+
+		switch (*pos) {
+		case '\0':
+			goto fail;
+		case '"':
+			*ptr  = pos+1;
+			return true;
+
+		case '\\':
+			pos++;
+			if (!srprs_charset(&pos, "\\\"", str)) {
+				unsigned u;
+				if (!srprs_hex(&pos, 2, &u)) {
+					goto fail;
+				}
+				cbuf_putc(str, u);
+			}
+			break;
+		default:
+			assert(false);
+		}
+	}
+
+fail:
+	cbuf_setpos(str, spos);
+	return false;
+}
diff --git a/source3/lib/srprs.h b/source3/lib/srprs.h
index bbbcdc7..350e08c 100644
--- a/source3/lib/srprs.h
+++ b/source3/lib/srprs.h
@@ -113,9 +113,10 @@ bool srprs_charsetinv(const char** ptr, const char* set, struct cbuf* oss);
  * assert(*cont == false);
  * assert(strcmp(cbuf_gets(out, 0), "start...continued...end")==0);
  * @endcode
+ * @see cbuf_print_quoted_string
  *
  * @param[in,out] ptr parse position
- * @param[out] str output buffer where to put the match, may be NULL
+ * @param[out] str output buffer where to put the match
  * @param[in,out] cont
  *
  * @return true if matched
@@ -177,5 +178,15 @@ bool srprs_eol(const char** ptr, struct cbuf* nl);
  */
 bool srprs_line(const char** ptr, struct cbuf* str);
 
+/**
+ * Match a quoted string with escaped characters.
+ * @see cbuf_print_quoted
+ *
+ * @param[in,out] ptr parse position
+ * @param[out] str output buffer where to put the match
+ *
+ * @return true if matched
+ */
+bool srprs_quoted(const char** ptr, struct cbuf* str);
 
 #endif /* __SRPRS_H */
diff --git a/source3/utils/net.c b/source3/utils/net.c
index 965cd44..a646029 100644
--- a/source3/utils/net.c
+++ b/source3/utils/net.c
@@ -815,6 +815,9 @@ static struct functable net_func[] = {
 		{"clean-old-entries", 0, POPT_ARG_NONE, &c->opt_clean_old_entries},
 		/* Options for 'net idmap'*/
 		{"db", 0, POPT_ARG_STRING, &c->opt_db},
+		{"lock", 0, POPT_ARG_NONE,   &c->opt_lock},
+		{"auto", 'a', POPT_ARG_NONE,   &c->opt_auto},
+		{"repair", 0, POPT_ARG_NONE,   &c->opt_repair},
 		POPT_COMMON_SAMBA
 		{ 0, 0, 0, 0}
 	};
diff --git a/source3/utils/net.h b/source3/utils/net.h
index ac30010..9f50b42 100644
--- a/source3/utils/net.h
+++ b/source3/utils/net.h
@@ -75,6 +75,9 @@ struct net_context {
 	int opt_single_obj_repl;
 	int opt_clean_old_entries;
 	const char *opt_db;
+	int opt_lock;
+	int opt_auto;
+	int opt_repair;
 
 	int opt_have_ip;
 	struct sockaddr_storage opt_dest_ip;
diff --git a/source3/utils/net_idmap.c b/source3/utils/net_idmap.c
index e7bac53..4b50583 100644
--- a/source3/utils/net_idmap.c
+++ b/source3/utils/net_idmap.c
@@ -17,13 +17,13 @@
    along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */
 
-#define FOO(x) (x)
 #include "includes.h"
 #include "utils/net.h"
 #include "secrets.h"
 #include "idmap.h"
 #include "dbwrap.h"
 #include "../libcli/security/security.h"
+#include "net_idmap_check.h"
 
 #define ALLOC_CHECK(mem) do { \
 	if (!mem) { \
@@ -534,6 +534,43 @@ static int net_idmap_secret(struct net_context *c, int argc, const char **argv)
 	return 0;
 }
 
+static int net_idmap_check(struct net_context *c, int argc, const char **argv)
+{
+	const char* dbfile;
+	struct check_options opts;
+
+	if ( argc > 1 || c->display_usage) {
+		d_printf("%s\n%s",
+			 _("Usage:"),
+			 _("net idmap check [-f] [-a] [-T] [-v] [--auto] [[--db=]<TDB>]\n"
+			   "  Check an idmap database.\n"
+			   "    --repair,-r\trepair\n"
+			   "    --fore,-f\tforce\n"
+			   "    --auto,-a\tnoninteractive mode\n"
+			   "    --test,-T\tdry run\n"
+			   "    --lock\tlock db while doing the check\n"
+			   "    TDB\tidmap database\n"));
+		return c->display_usage ? 0 : -1;
+	}
+
+	dbfile = (argc > 0) ? argv[0] : net_idmap_dbfile(c);
+	if (dbfile == NULL) {
+		return -1;
+	}
+	d_fprintf(stderr, _("check database: %s\n"), dbfile);
+
+	opts = (struct check_options) {
+		.lock = c->opt_lock,
+		.test = c->opt_testmode,
+		.automatic = c->opt_auto,
+		.verbose = c->opt_verbose,
+		.force = c->opt_force,
+		.repair = c->opt_repair || c->opt_reboot,
+	};
+
+	return net_idmap_check_db(dbfile, &opts);
+}
+
 static int net_idmap_aclmapset(struct net_context *c, int argc, const char **argv)
 {
 	TALLOC_CTX *mem_ctx;
@@ -652,6 +689,14 @@ int net_idmap(struct net_context *c, int argc, const char **argv)
 			N_("net idmap aclmapset\n"
 			   "  Set acl map")
 		},
+		{
+			"check",
+			net_idmap_check,
+			NET_TRANSPORT_LOCAL,
+			N_("Check id mappings"),
+			N_("net idmap check\n"
+			   "  Check id mappings")
+		},
 		{NULL, NULL, 0, NULL, NULL}
 	};
 
diff --git a/source3/utils/net_idmap_check.c b/source3/utils/net_idmap_check.c
new file mode 100644
index 0000000..6c6bcd9
--- /dev/null
+++ b/source3/utils/net_idmap_check.c
@@ -0,0 +1,1005 @@
+/*
+ * Samba Unix/Linux SMB client library
+ *
+ * Copyright (C) Gregor Beck 2011
+ *
+ * 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
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/**
+ * @brief  Check the idmap database.
+ * @author Gregor Beck <gb at sernet.de>
+ * @date   Mar 2011
+ */
+
+#include "net_idmap_check.h"
+#include "includes.h"
+#include "dbwrap.h"
+#include "net.h"
+#include "../libcli/security/dom_sid.h"
+#include "cbuf.h"
+#include "srprs.h"
+#include <termios.h>
+
+static int traverse_commit(struct db_record *diff_rec, void* data);
+static int traverse_check(struct db_record *rec, void* data);
+
+static char* interact_edit(TALLOC_CTX* mem_ctx, const char* str);
+static int interact_prompt(const char* msg, const char* accept, char def);
+
+/* TDB_DATA *******************************************************************/
+static char*    print_data(TALLOC_CTX* mem_ctx, TDB_DATA d);
+static TDB_DATA parse_data(TALLOC_CTX* mem_ctx, const char** ptr);
+static TDB_DATA talloc_copy(TALLOC_CTX* mem_ctx, TDB_DATA data);
+static bool is_empty(TDB_DATA data) {
+	return (data.dsize == 0) || (data.dptr == NULL);
+}
+
+/* record *********************************************************************/
+
+enum DT {
+	DT_INV = 0,
+	DT_SID,	DT_UID,	DT_GID,
+	DT_HWM,	DT_VER
+};
+
+struct record {
+	enum DT key_type, val_type;
+	TDB_DATA key, val;
+	struct dom_sid sid;
+	long unsigned  id;
+};
+
+static struct record* parse_record(TALLOC_CTX* ctx, TDB_DATA key, TDB_DATA val);
+static struct record* reverse_record(struct record* rec);
+
+static bool is_invalid(const struct record* r) {
+	return (r->key_type == DT_INV) || (r->val_type == DT_INV);
+}
+
+static bool is_map(const struct record* r) {
+	return (r->key_type == DT_SID)
+		|| (r->key_type == DT_UID) || (r->key_type == DT_GID);
+}
+
+/* action *********************************************************************/
+
+typedef struct check_action {
+	const char* fmt;
+	const char* name;
+	const char* prompt;
+	const char* answers;
+	char auto_action;
+	char default_action;
+	bool verbose;
+} check_action;
+
+struct check_actions {
+	check_action invalid_record;
+	check_action missing_reverse;
+	check_action invalid_mapping;
+	check_action invalid_edit;
+	check_action record_exists;
+	check_action no_version;
+	check_action wrong_version;
+	check_action invalid_hwm;
+	check_action commit;
+	check_action valid_mapping;
+	check_action valid_other;
+	check_action invalid_diff;
+};
+
+static struct check_actions
+check_actions_init(const struct check_options* opts) {
+	struct check_actions ret = {
+		.invalid_record = (check_action) {
+			.name = "Invalid record",
+			.prompt = "[e]dit/[d]elete/[D]elete all"
+			"/[s]kip/[S]kip all",
+			.answers = "eds",
+			.default_action = 'e',
+			.verbose = true,
+		},
+		.missing_reverse = (check_action) {
+			.name = "Missing reverse mapping for",
+			.prompt = "[f]ix/[F]ix all/[e]dit/[d]elete/[D]elete all"
+			"/[s]kip/[S]kip all",
+			.answers = "feds",
+			.default_action = 'f',
+			.verbose = true,
+		},
+		.invalid_mapping = (check_action) {
+			.fmt = "%1$s: %2$s -> %3$s\n(%4$s <- %3$s)\n",
+			.name = "Invalid mapping",
+			.prompt = "[e]dit/[d]elete/[D]elete all"
+			"/[s]kip/[S]kip all",
+			.answers = "eds",
+			.default_action = 'd',
+			.verbose = true,
+		},
+		.invalid_edit = (check_action) {
+			.name = "Invalid record",
+			.prompt = "[e]dit/[d]elete/[D]elete all"
+			"/[s]kip/[S]kip all",
+			.answers = "eds",
+			.default_action = 'e',
+			.verbose = true,
+		},
+		.record_exists = (check_action) {
+			.fmt = "%1$s: %2$s\n-%4$s\n+%3$s\n",
+			.name = "Record exists",
+			.prompt = "[o]verwrite/[O]verwrite all/[e]dit"
+			"/[d]elete/[D]elete all/[s]kip/[S]kip all",
+			.answers = "oeds",


-- 
Samba Shared Repository


More information about the samba-cvs mailing list