[SCM] Samba Shared Repository - branch master updated

Jeremy Allison jra at samba.org
Fri Sep 18 01:05:03 UTC 2015


The branch, master has been updated
       via  ea53e86 tdb: Add tdbdump -u
      from  1d2a1a6 s4:lib/messaging: use 'msg.lock' and 'msg.sock' for messaging related subdirs

https://git.samba.org/?p=samba.git;a=shortlog;h=master


- Log -----------------------------------------------------------------
commit ea53e86c256bec08373dbe86e190a7f5a06eff9d
Author: Volker Lendecke <vl at samba.org>
Date:   Tue Sep 15 17:08:24 2015 +0200

    tdb: Add tdbdump -u
    
    The reverse of tdbdump
    
    Signed-off-by: Volker Lendecke <vl at samba.org>
    Reviewed-by: Jeremy Allison <jra at samba.org>
    
    Autobuild-User(master): Jeremy Allison <jra at samba.org>
    Autobuild-Date(master): Fri Sep 18 03:04:35 CEST 2015 on sn-devel-104

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

Summary of changes:
 lib/tdb/man/tdbdump.8.xml |   9 ++
 lib/tdb/tools/tdbdump.c   | 285 +++++++++++++++++++++++++++++++++++++++++++++-
 2 files changed, 293 insertions(+), 1 deletion(-)


Changeset truncated at 500 lines:

diff --git a/lib/tdb/man/tdbdump.8.xml b/lib/tdb/man/tdbdump.8.xml
index 31e6888..238e881 100644
--- a/lib/tdb/man/tdbdump.8.xml
+++ b/lib/tdb/man/tdbdump.8.xml
@@ -22,6 +22,7 @@
 		<command>tdbdump</command>
 		<arg choice="opt">-k <replaceable>keyname</replaceable></arg>
 		<arg choice="opt">-e</arg>
+		<arg choice="opt">-u</arg>
 		<arg choice="opt">-h</arg>
 		<arg choice="req">filename</arg>
 	</cmdsynopsis>
@@ -69,6 +70,14 @@
 		</para></listitem>
 		</varlistentry>
 
+		<varlistentry>
+		<term>-u</term>
+		<listitem><para>
+		  'Undumps' a database, turning the tdbdump output on stdin
+		  into a tdb again.
+		</para></listitem>
+		</varlistentry>
+
 	</variablelist>
 </refsect1>
 
diff --git a/lib/tdb/tools/tdbdump.c b/lib/tdb/tools/tdbdump.c
index 9a0a7fe..aa50540 100644
--- a/lib/tdb/tools/tdbdump.c
+++ b/lib/tdb/tools/tdbdump.c
@@ -23,6 +23,7 @@
 #include "system/filesys.h"
 #include "system/wait.h"
 #include "tdb.h"
+#include <regex.h>
 
 static void print_data(TDB_DATA d)
 {
@@ -134,18 +135,293 @@ static int dump_tdb(const char *fname, const char *keyname, bool emergency)
 	return 0;
 }
 
+static bool file_parse_lines(FILE *f,
+			     bool (*cb)(char *buf, size_t buflen,
+					void *private_data),
+			     void *private_data)
+{
+	char *buf;
+	size_t buflen;
+
+	buflen = 1024;
+	buf = malloc(1024);
+	if (buf == NULL) {
+		return false;
+	}
+
+	while (true) {
+		size_t pos = 0;
+		int c;
+		bool ok;
+
+		while ((c = fgetc(f)) != EOF) {
+
+			buf[pos++] = c;
+
+			if (pos == (buflen-1)) {
+				char *tmp;
+				tmp = realloc(buf, buflen*2);
+				if (tmp == NULL) {
+					free(buf);
+					return false;
+				}
+				buf = tmp;
+				buflen *= 2;
+			}
+
+			if (c == '\n') {
+				break;
+			}
+		}
+
+		if (c == EOF) {
+			free(buf);
+			return (pos == 0);
+		}
+
+		buf[pos] = '\0';
+
+		ok = cb(buf, buflen, private_data);
+		if (!ok) {
+			break;
+		}
+	}
+	free(buf);
+	return true;
+}
+
+struct undump_state {
+	struct tdb_context *tdb;
+	TDB_DATA key;
+	TDB_DATA data;
+	int line;
+};
+
+static ssize_t match_len(const regmatch_t *m, size_t buflen)
+{
+	if ((m->rm_eo < m->rm_so) ||
+	    (m->rm_eo > buflen) || (m->rm_so > buflen)) {
+		return -1;
+	}
+	return m->rm_eo - m->rm_so;
+}
+
+static int nibble(char c)
+{
+	if ((c >= '0') && (c <= '9')) {
+		return c - '0';
+	}
+	if ((c >= 'A') && (c <= 'F')) {
+		return c - 'A' + 10;
+	}
+	if ((c >= 'a') && (c <= 'f')) {
+		return c - 'a' + 10;
+	}
+	return -1;
+}
+
+static bool undump_regmatch(int line, char *buf, size_t buflen,
+			    const regmatch_t *nummatch,
+			    const regmatch_t *datamatch,
+			    TDB_DATA *pret)
+{
+	ssize_t numlen = match_len(nummatch, buflen);
+	ssize_t datalen = match_len(datamatch, buflen);
+	long long num;
+	size_t col;
+
+	TDB_DATA ret = {0};
+
+	if ((numlen == -1) || (datalen == -1)) {
+		fprintf(stderr, "No matches in line %d\n", line);
+		return false;
+	}
+
+	{
+		char numbuf[numlen+1];
+		memcpy(numbuf, buf+nummatch->rm_so, numlen);
+		numbuf[numlen] = '\0';
+		num = atoll(numbuf);
+	}
+
+	if (num == 0) {
+		*pret = ret;
+		return true;
+	}
+
+	ret.dptr = malloc(datalen);
+	if (ret.dptr == NULL) {
+		fprintf(stderr, "malloc failed for line %d\n", line);
+		return false;
+	}
+
+	col = datamatch->rm_so;
+	while (col < datamatch->rm_eo) {
+		int n;
+
+		if (buf[col] != '\\') {
+			ret.dptr[ret.dsize++] = buf[col++];
+			continue;
+		}
+
+		if ((datamatch->rm_eo - col) < 3) {
+			fprintf(stderr, "hex char too short in line %d, "
+				"col %d\n", line, (int)col);
+			goto fail;
+		}
+
+		n = nibble(buf[col+1]);
+		if (n == -1) {
+			fprintf(stderr, "Could not convert '%c' in line %d "
+				"col %d\n", buf[col+1], line, (int)col);
+			goto fail;
+		}
+		ret.dptr[ret.dsize] = n << 4;
+
+		n = nibble(buf[col+2]);
+		if (n == -1) {
+			fprintf(stderr, "Could not convert '%c' in line %d, "
+				"col %d\n", buf[col+2], line, (int)col);
+			goto fail;
+		}
+		ret.dptr[ret.dsize] |= n;
+
+		ret.dsize += 1;
+		col += 3;
+	}
+
+	if (ret.dsize != num) {
+		fprintf(stderr, "Expected %d chars, got %d in line %d\n",
+			(int)num, (int)ret.dsize, line);
+		goto fail;
+	}
+
+	*pret = ret;
+	return true;
+
+fail:
+	free(ret.dptr);
+	return false;
+}
+
+static bool undump_cb(char *buf, size_t buflen, void *private_data)
+{
+	struct undump_state *state = private_data;
+	regex_t regex;
+	regmatch_t matches[3];
+	int ret;
+	bool ok;
+
+	state->line++;
+
+	ret = regcomp(&regex, "^key(\\([[:digit:]]*\\)) = \"\\(.*\\)\"\n$", 0);
+	if (ret != 0) {
+		return false;
+	}
+
+	ret = regexec(&regex, buf, 3, matches, 0);
+	if (ret == 0) {
+		if (state->key.dsize != 0) {
+			fprintf(stderr, "line %d has duplicate key\n",
+				state->line);
+			regfree(&regex);
+			return false;
+		}
+		ok = undump_regmatch(state->line, buf, buflen,
+				     &matches[1], &matches[2],
+				     &state->key);
+		if (!ok) {
+			regfree(&regex);
+			return false;
+		}
+	}
+	regfree(&regex);
+
+	ret = regcomp(&regex, "^data(\\([[:digit:]]*\\)) = \"\\(.*\\)\"\n$",
+		      0);
+	if (ret != 0) {
+		return false;
+	}
+
+	ret = regexec(&regex, buf, 3, matches, 0);
+	if (ret == 0) {
+		if (state->key.dsize == 0) {
+			fprintf(stderr, "line %d has data without key\n",
+				state->line);
+			regfree(&regex);
+			return false;
+		}
+		if (state->data.dsize != 0) {
+			fprintf(stderr, "line %d has duplicate data\n",
+				state->line);
+			regfree(&regex);
+			return false;
+		}
+		ok = undump_regmatch(state->line, buf, buflen,
+				     &matches[1], &matches[2],
+				     &state->data);
+		if (!ok) {
+			return false;
+		}
+
+		ret = tdb_store(state->tdb, state->key, state->data, 0);
+
+		free(state->key.dptr);
+		state->key = (TDB_DATA) {0};
+
+		free(state->data.dptr);
+		state->data = (TDB_DATA) {0};
+
+		if (ret == -1) {
+			fprintf(stderr, "tdb_store for line %d failed: %s\n",
+				state->line, tdb_errorstr(state->tdb));
+			return false;
+		}
+	}
+
+	regfree(&regex);
+
+	return true;
+}
+
+static int undump_tdb(const char *fname)
+{
+	struct tdb_logging_context logfn = { log_stderr };
+	struct undump_state state = {0};
+	bool ok;
+
+	state.tdb = tdb_open_ex(fname, 0, TDB_DEFAULT, O_RDWR|O_CREAT, 0600,
+				&logfn, NULL);
+	if (state.tdb == NULL) {
+		printf("Failed to open %s\n", fname);
+		return 1;
+	}
+
+	ok = file_parse_lines(stdin, undump_cb, &state);
+	if (!ok) {
+		printf("Failed to parse stdin\n");
+		return 1;
+	}
+
+	tdb_close(state.tdb);
+
+	return 0;
+}
+
 static void usage( void)
 {
 	printf( "Usage: tdbdump [options] <filename>\n\n");
 	printf( "   -h          this help message\n");
 	printf( "   -k keyname  dumps value of keyname\n");
 	printf( "   -e          emergency dump, for corrupt databases\n");
+	printf( "   -u          undump stdin\n");
 }
 
  int main(int argc, char *argv[])
 {
 	char *fname, *keyname=NULL;
 	bool emergency = false;
+	bool undump = false;
 	int c;
 
 	if (argc < 2) {
@@ -153,7 +429,7 @@ static void usage( void)
 		exit(1);
 	}
 
-	while ((c = getopt( argc, argv, "hk:e")) != -1) {
+	while ((c = getopt( argc, argv, "hk:eu")) != -1) {
 		switch (c) {
 		case 'h':
 			usage();
@@ -164,6 +440,9 @@ static void usage( void)
 		case 'e':
 			emergency = true;
 			break;
+		case 'u':
+			undump = true;
+			break;
 		default:
 			usage();
 			exit( 1);
@@ -172,5 +451,9 @@ static void usage( void)
 
 	fname = argv[optind];
 
+	if (undump) {
+		return undump_tdb(fname);
+	}
+
 	return dump_tdb(fname, keyname, emergency);
 }


-- 
Samba Shared Repository



More information about the samba-cvs mailing list