summaryrefslogtreecommitdiff
path: root/source4/lib/ldb
diff options
context:
space:
mode:
authorAndrew Tridgell <tridge@samba.org>2004-04-10 20:18:22 +0000
committerGerald (Jerry) Carter <jerry@samba.org>2007-10-10 12:51:11 -0500
commitac193579e7db00c7a2ea0aadaaf0d34c10dcf1a5 (patch)
treebcd9a0afdc2996df4a56479932b7d36d32c50f8d /source4/lib/ldb
parent91b30df39bfaec8bfa32be40a13fd62008f66b9e (diff)
downloadsamba-ac193579e7db00c7a2ea0aadaaf0d34c10dcf1a5.tar.gz
samba-ac193579e7db00c7a2ea0aadaaf0d34c10dcf1a5.tar.bz2
samba-ac193579e7db00c7a2ea0aadaaf0d34c10dcf1a5.zip
r152: a quick airport commit ....
added ldbedit, a _really_ useful command added ldbadd, ldbdel, ldbsearch and ldbmodify to build solved lots of timezone issues, we now pass the torture tests with client and server in different zones fixed several build issues I know this breaks the no-LDAP build. Wait till I arrive in San Jose for that fix. (This used to be commit af34710d4da1841653624fe304b1c8d812c0fdd9)
Diffstat (limited to 'source4/lib/ldb')
-rw-r--r--source4/lib/ldb/Makefile.ldb8
-rw-r--r--source4/lib/ldb/common/ldb.c2
-rw-r--r--source4/lib/ldb/common/ldb_ldif.c22
-rw-r--r--source4/lib/ldb/common/ldb_msg.c133
-rw-r--r--source4/lib/ldb/common/util.c6
-rw-r--r--source4/lib/ldb/config.m446
-rw-r--r--source4/lib/ldb/include/includes.h3
-rw-r--r--source4/lib/ldb/include/ldb.h2
-rw-r--r--source4/lib/ldb/ldb_ldap/ldb_ldap.c5
-rw-r--r--source4/lib/ldb/ldb_tdb/ldb_pack.c2
-rw-r--r--source4/lib/ldb/ldb_tdb/ldb_search.c36
-rw-r--r--source4/lib/ldb/ldb_tdb/ldb_tdb.c2
-rw-r--r--source4/lib/ldb/ldb_tdb/ldb_tdb.h4
-rw-r--r--source4/lib/ldb/tools/ldbadd.c99
-rw-r--r--source4/lib/ldb/tools/ldbdel.c41
-rw-r--r--source4/lib/ldb/tools/ldbedit.c365
-rw-r--r--source4/lib/ldb/tools/ldbmodify.c100
-rw-r--r--source4/lib/ldb/tools/ldbsearch.c32
18 files changed, 803 insertions, 105 deletions
diff --git a/source4/lib/ldb/Makefile.ldb b/source4/lib/ldb/Makefile.ldb
index 0610ccf19b..2a41629852 100644
--- a/source4/lib/ldb/Makefile.ldb
+++ b/source4/lib/ldb/Makefile.ldb
@@ -12,13 +12,14 @@ LDB_TDB_OBJ=ldb_tdb/ldb_match.o ldb_tdb/ldb_tdb.o \
LDB_LDAP_OBJ=ldb_ldap/ldb_ldap.o
-COMMON_OBJ=common/ldb.o common/ldb_ldif.o common/util.o common/ldb_parse.o
+COMMON_OBJ=common/ldb.o common/ldb_ldif.o common/util.o \
+ common/ldb_parse.o common/ldb_msg.o
OBJS = $(COMMON_OBJ) $(LDB_TDB_OBJ) $(TDB_OBJ) $(LDB_LDAP_OBJ)
LDB_LIB = lib/libldb.a
-BINS = bin/ldbadd bin/ldbsearch bin/ldbdel bin/ldbmodify
+BINS = bin/ldbadd bin/ldbsearch bin/ldbdel bin/ldbmodify bin/ldbedit
LIBS = $(LDB_LIB)($(OBJS))
@@ -46,6 +47,9 @@ bin/ldbdel: tools/ldbdel.o $(LIBS)
bin/ldbmodify: tools/ldbmodify.o $(LIBS)
$(CC) -o bin/ldbmodify tools/ldbmodify.o $(LIB_FLAGS)
+bin/ldbedit: tools/ldbedit.o $(LIBS)
+ $(CC) -o bin/ldbedit tools/ldbedit.o $(LIB_FLAGS)
+
clean:
rm -f */*.o *~ */*~ $(BINS) $(LDB_LIB)
diff --git a/source4/lib/ldb/common/ldb.c b/source4/lib/ldb/common/ldb.c
index 3ba4434e07..146745043f 100644
--- a/source4/lib/ldb/common/ldb.c
+++ b/source4/lib/ldb/common/ldb.c
@@ -80,7 +80,7 @@ int ldb_search(struct ldb_context *ldb,
const char *base,
enum ldb_scope scope,
const char *expression,
- const char *attrs[], struct ldb_message ***res)
+ char * const attrs[], struct ldb_message ***res)
{
return ldb->ops->search(ldb, base, scope, expression, attrs, res);
}
diff --git a/source4/lib/ldb/common/ldb_ldif.c b/source4/lib/ldb/common/ldb_ldif.c
index b4c27c3369..5f2fccfebc 100644
--- a/source4/lib/ldb/common/ldb_ldif.c
+++ b/source4/lib/ldb/common/ldb_ldif.c
@@ -90,7 +90,7 @@ char *ldb_base64_encode(const char *buf, int len)
{
const char *b64 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
int bit_offset, byte_offset, idx, i;
- unsigned char *d = (unsigned char *)buf;
+ const unsigned char *d = (const unsigned char *)buf;
int bytes = (len*8 + 5)/6;
char *out;
@@ -222,6 +222,23 @@ int ldif_write(int (*fprintf_fn)(void *, const char *, ...),
}
for (i=0;i<msg->num_elements;i++) {
+ if (ldif->changetype == LDB_CHANGETYPE_MODIFY) {
+ switch (msg->elements[i].flags & LDB_FLAG_MOD_MASK) {
+ case LDB_FLAG_MOD_ADD:
+ fprintf_fn(private, "add: %s\n",
+ msg->elements[i].name);
+ break;
+ case LDB_FLAG_MOD_DELETE:
+ fprintf_fn(private, "delete: %s\n",
+ msg->elements[i].name);
+ break;
+ case LDB_FLAG_MOD_REPLACE:
+ fprintf_fn(private, "replace: %s\n",
+ msg->elements[i].name);
+ break;
+ }
+ }
+
for (j=0;j<msg->elements[i].num_values;j++) {
if (ldb_should_b64_encode(&msg->elements[i].values[j])) {
ret = fprintf_fn(private, "%s:: ",
@@ -246,6 +263,9 @@ int ldif_write(int (*fprintf_fn)(void *, const char *, ...),
CHECK_RET;
}
}
+ if (ldif->changetype == LDB_CHANGETYPE_MODIFY) {
+ fprintf_fn(private, "-\n");
+ }
}
ret = fprintf_fn(private,"\n");
CHECK_RET;
diff --git a/source4/lib/ldb/common/ldb_msg.c b/source4/lib/ldb/common/ldb_msg.c
new file mode 100644
index 0000000000..633cc91f2c
--- /dev/null
+++ b/source4/lib/ldb/common/ldb_msg.c
@@ -0,0 +1,133 @@
+/*
+ ldb database library
+
+ Copyright (C) Andrew Tridgell 2004
+
+ ** NOTE! The following LGPL license applies to the ldb
+ ** library. This does NOT imply that all of Samba is released
+ ** under the LGPL
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library 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
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+*/
+
+/*
+ * Name: ldb
+ *
+ * Component: ldb message component utility functions
+ *
+ * Description: functions for manipulating ldb_message structures
+ *
+ * Author: Andrew Tridgell
+ */
+
+#include "includes.h"
+
+
+/*
+ find an element in a message by attribute name
+*/
+struct ldb_message_element *ldb_msg_find_element(const struct ldb_message *msg,
+ const char *attr_name)
+{
+ int i;
+ for (i=0;i<msg->num_elements;i++) {
+ if (strcmp(msg->elements[i].name, attr_name) == 0) {
+ return &msg->elements[i];
+ }
+ }
+ return NULL;
+}
+
+
+/*
+ find a value in an element
+*/
+struct ldb_val *ldb_msg_find_val(const struct ldb_message_element *el,
+ struct ldb_val *val)
+{
+ int i;
+ for (i=0;i<el->num_values;i++) {
+ if (ldb_val_equal(val, &el->values[i])) {
+ return &el->values[i];
+ }
+ }
+ return NULL;
+}
+
+
+/*
+ add an empty element to a message
+*/
+int ldb_msg_add_empty(struct ldb_message *msg, const char *attr_name, int flags)
+{
+ struct ldb_message_element *els;
+
+ els = realloc_p(msg->elements, struct ldb_message_element, msg->num_elements+1);
+ if (!els) {
+ errno = ENOMEM;
+ return -1;
+ }
+
+ els[msg->num_elements].values = NULL;
+ els[msg->num_elements].num_values = 0;
+ els[msg->num_elements].flags = flags;
+ els[msg->num_elements].name = strdup(attr_name);
+ if (!els[msg->num_elements].name) {
+ return -1;
+ }
+
+ msg->elements = els;
+ msg->num_elements++;
+
+ return 0;
+}
+
+/*
+ add an empty element to a message
+*/
+int ldb_msg_add(struct ldb_message *msg,
+ const struct ldb_message_element *el,
+ int flags)
+{
+ if (ldb_msg_add_empty(msg, el->name, flags) != 0) {
+ return -1;
+ }
+
+ msg->elements[msg->num_elements-1] = *el;
+ msg->elements[msg->num_elements-1].flags = flags;
+
+ return 0;
+}
+
+/*
+ compare two ldb_message_element structures
+*/
+int ldb_msg_element_compare(struct ldb_message_element *el1,
+ struct ldb_message_element *el2)
+{
+ int i;
+
+ if (el1->num_values != el2->num_values) {
+ return el1->num_values - el2->num_values;
+ }
+
+ for (i=0;i<el1->num_values;i++) {
+ if (!ldb_msg_find_val(el2, &el1->values[i])) {
+ return -1;
+ }
+ }
+
+ return 0;
+}
diff --git a/source4/lib/ldb/common/util.c b/source4/lib/ldb/common/util.c
index d198a1ad92..e1a7ada1c6 100644
--- a/source4/lib/ldb/common/util.c
+++ b/source4/lib/ldb/common/util.c
@@ -77,11 +77,11 @@ int list_find(const void *needle,
int r;
test_i = (min_i + max_i) / 2;
- r = comp_fn(needle, *(void **)(base_p + (size * test_i)));
+ r = comp_fn(needle, *(void * const *)(base_p + (size * test_i)));
if (r == 0) {
/* scan back for first element */
while (test_t > 0 &&
- comp_fn(needle, *(void **)(base_p + (size * (test_i-1)))) == 0) {
+ comp_fn(needle, *(void * const *)(base_p + (size * (test_i-1)))) == 0) {
test_i--;
}
return test_i;
@@ -94,7 +94,7 @@ int list_find(const void *needle,
}
}
- if (comp_fn(needle, *(void **)(base_p + (size * min_i))) == 0) {
+ if (comp_fn(needle, *(void * const *)(base_p + (size * min_i))) == 0) {
return min_i;
}
diff --git a/source4/lib/ldb/config.m4 b/source4/lib/ldb/config.m4
index 6fdfcf526a..7c4749ab02 100644
--- a/source4/lib/ldb/config.m4
+++ b/source4/lib/ldb/config.m4
@@ -1,17 +1,37 @@
-
-SMB_MODULE(libldb_tdb,LIBLDB,STATIC,
- [lib/ldb/ldb_tdb/ldb_tdb.o \
- lib/ldb/ldb_tdb/ldb_pack.o \
+SMB_SUBSYSTEM(LIBLDB,[lib/ldb/common/ldb.o],
+ [lib/ldb/common/ldb_ldif.o \
+ lib/ldb/common/ldb_parse.o \
+ lib/ldb/common/ldb_msg.o \
+ lib/ldb/common/util.o \
lib/ldb/ldb_tdb/ldb_search.o \
+ lib/ldb/ldb_tdb/ldb_tdb.o \
+ lib/ldb/ldb_tdb/ldb_pack.o \
lib/ldb/ldb_tdb/ldb_index.o \
- lib/ldb/ldb_tdb/ldb_match.o])
+ lib/ldb/ldb_tdb/ldb_match.o \
+ lib/ldb/ldb_ldap/ldb_ldap.o],
+ lib/ldb/include/ldb.h)
-if test x"$with_ldap_support" = x"yes"; then
- SMB_MODULE_DEFAULT(libldb_ldap,STATIC)
-fi
-SMB_MODULE(libldb_ldap,LIBLDB,NOT,[lib/ldb/ldb_ldap/ldb_ldap.o])
+SMB_SUBSYSTEM(LDBADD,[],
+ [lib/ldb/tools/ldbadd.o \
+ \$(LIBBASIC_OBJS) \$(LIBSMB_OBJS) \$(CONFIG_OBJS) \$(LIBLDB_OBJS)],
+ lib/ldb/include/proto.h)
-SMB_SUBSYSTEM(LIBLDB,[lib/ldb/common/ldb.o],
- [lib/ldb/common/ldb_ldif.o \
- lib/ldb/common/ldb_parse.o \
- lib/ldb/common/util.o])
+SMB_SUBSYSTEM(LDBDEL,[],
+ [lib/ldb/tools/ldbdel.o \
+ \$(LIBBASIC_OBJS) \$(LIBSMB_OBJS) \$(CONFIG_OBJS) \$(LIBLDB_OBJS)],
+ lib/ldb/include/proto.h)
+
+SMB_SUBSYSTEM(LDBMODIFY,[],
+ [lib/ldb/tools/ldbmodify.o \
+ \$(LIBBASIC_OBJS) \$(LIBSMB_OBJS) \$(CONFIG_OBJS) \$(LIBLDB_OBJS)],
+ lib/ldb/include/proto.h)
+
+SMB_SUBSYSTEM(LDBSEARCH,[],
+ [lib/ldb/tools/ldbsearch.o \
+ \$(LIBBASIC_OBJS) \$(LIBSMB_OBJS) \$(CONFIG_OBJS) \$(LIBLDB_OBJS)],
+ lib/ldb/include/proto.h)
+
+SMB_SUBSYSTEM(LDBEDIT,[],
+ [lib/ldb/tools/ldbedit.o \
+ \$(LIBBASIC_OBJS) \$(LIBSMB_OBJS) \$(CONFIG_OBJS) \$(LIBLDB_OBJS)],
+ lib/ldb/include/proto.h)
diff --git a/source4/lib/ldb/include/includes.h b/source4/lib/ldb/include/includes.h
index ea8540d330..70ad1f3588 100644
--- a/source4/lib/ldb/include/includes.h
+++ b/source4/lib/ldb/include/includes.h
@@ -2,7 +2,9 @@
a temporary includes file until I work on the ldb build system
*/
+#ifndef _GNU_SOURCE
#define _GNU_SOURCE
+#endif
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
@@ -11,6 +13,7 @@
#include <fcntl.h>
#include <stdarg.h>
#include <signal.h>
+#include <unistd.h>
#include "ldb.h"
#include "ldb_parse.h"
diff --git a/source4/lib/ldb/include/ldb.h b/source4/lib/ldb/include/ldb.h
index 12064bbf75..dc1b1d7732 100644
--- a/source4/lib/ldb/include/ldb.h
+++ b/source4/lib/ldb/include/ldb.h
@@ -174,7 +174,7 @@ int ldb_search(struct ldb_context *ldb,
const char *base,
enum ldb_scope scope,
const char *expression,
- const char *attrs[], struct ldb_message ***res);
+ char * const attrs[], struct ldb_message ***res);
/*
free a set of messages returned by ldb_search
diff --git a/source4/lib/ldb/ldb_ldap/ldb_ldap.c b/source4/lib/ldb/ldb_ldap/ldb_ldap.c
index 25dad914da..25af43c569 100644
--- a/source4/lib/ldb/ldb_ldap/ldb_ldap.c
+++ b/source4/lib/ldb/ldb_ldap/ldb_ldap.c
@@ -33,8 +33,7 @@
*/
#include "includes.h"
-#if HAVE_LDAP
-#include "ldb_ldap.h"
+#include "ldb/ldb_ldap/ldb_ldap.h"
#if 0
/*
@@ -519,4 +518,4 @@ failed:
if (ldb) free(ldb);
return NULL;
}
-#endif /*HAVE_LDAP*/
+
diff --git a/source4/lib/ldb/ldb_tdb/ldb_pack.c b/source4/lib/ldb/ldb_tdb/ldb_pack.c
index 5964e0751d..1196e561a2 100644
--- a/source4/lib/ldb/ldb_tdb/ldb_pack.c
+++ b/source4/lib/ldb/ldb_tdb/ldb_pack.c
@@ -33,7 +33,7 @@
*/
#include "includes.h"
-#include "ldb_tdb.h"
+#include "ldb/ldb_tdb/ldb_tdb.h"
/* change this if the data format ever changes */
#define LTDB_PACKING_FORMAT 0x26011966
diff --git a/source4/lib/ldb/ldb_tdb/ldb_search.c b/source4/lib/ldb/ldb_tdb/ldb_search.c
index 5905231b32..9cb5853c94 100644
--- a/source4/lib/ldb/ldb_tdb/ldb_search.c
+++ b/source4/lib/ldb/ldb_tdb/ldb_search.c
@@ -33,7 +33,7 @@
*/
#include "includes.h"
-#include "ldb_tdb.h"
+#include "ldb/ldb_tdb/ldb_tdb.h"
/*
free a message that has all parts separately allocated
@@ -56,22 +56,6 @@ static void msg_free_all_parts(struct ldb_message *msg)
/*
- TODO: this should take advantage of the sorted nature of the message
-
- return index of the attribute, or -1 if not found
-*/
-int ldb_msg_find_attr(const struct ldb_message *msg, const char *attr)
-{
- int i;
- for (i=0;i<msg->num_elements;i++) {
- if (strcmp(msg->elements[i].name, attr) == 0) {
- return i;
- }
- }
- return -1;
-}
-
-/*
duplicate a ldb_val structure
*/
struct ldb_val ldb_val_dup(const struct ldb_val *v)
@@ -193,7 +177,7 @@ static struct ldb_message *ltdb_pull_attrs(struct ldb_context *ldb,
}
for (i=0;attrs[i];i++) {
- int j;
+ struct ldb_message_element *el;
if (strcmp(attrs[i], "*") == 0) {
if (msg_add_all_elements(ret, msg) != 0) {
@@ -202,17 +186,15 @@ static struct ldb_message *ltdb_pull_attrs(struct ldb_context *ldb,
}
continue;
}
- j = ldb_msg_find_attr(msg, attrs[i]);
- if (j == -1) {
+
+ el = ldb_msg_find_element(msg, attrs[i]);
+ if (!el) {
continue;
}
- do {
- if (msg_add_element(ret, &msg->elements[j]) != 0) {
- msg_free_all_parts(ret);
- return NULL;
- }
- } while (++j < msg->num_elements &&
- strcmp(attrs[i], msg->elements[j].name) == 0);
+ if (msg_add_element(ret, el) != 0) {
+ msg_free_all_parts(ret);
+ return NULL;
+ }
}
return ret;
diff --git a/source4/lib/ldb/ldb_tdb/ldb_tdb.c b/source4/lib/ldb/ldb_tdb/ldb_tdb.c
index ec90eec03f..b28d73cbea 100644
--- a/source4/lib/ldb/ldb_tdb/ldb_tdb.c
+++ b/source4/lib/ldb/ldb_tdb/ldb_tdb.c
@@ -33,7 +33,7 @@
*/
#include "includes.h"
-#include "ldb_tdb.h"
+#include "ldb/ldb_tdb/ldb_tdb.h"
/*
form a TDB_DATA for a record key
diff --git a/source4/lib/ldb/ldb_tdb/ldb_tdb.h b/source4/lib/ldb/ldb_tdb/ldb_tdb.h
index 30afe223ea..efb0af1c9c 100644
--- a/source4/lib/ldb/ldb_tdb/ldb_tdb.h
+++ b/source4/lib/ldb/ldb_tdb/ldb_tdb.h
@@ -5,7 +5,9 @@ struct ltdb_private {
unsigned int connect_flags;
};
-#ifdef STANDALONE
+#ifndef IVAL
#define IVAL(p, ofs) (((unsigned *)((char *)(p) + (ofs)))[0])
+#endif
+#ifndef SIVAL
#define SIVAL(p, ofs, v) do { IVAL(p, ofs) = (v); } while (0)
#endif
diff --git a/source4/lib/ldb/tools/ldbadd.c b/source4/lib/ldb/tools/ldbadd.c
index 92ed29e6b8..446c0d80f9 100644
--- a/source4/lib/ldb/tools/ldbadd.c
+++ b/source4/lib/ldb/tools/ldbadd.c
@@ -34,28 +34,28 @@
#include "includes.h"
- int main(void)
-{
- static struct ldb_context *ldb;
- struct ldb_ldif *ldif;
- int ret;
- int count=0, failures=0;
- const char *ldb_url;
-
- ldb_url = getenv("LDB_URL");
- if (!ldb_url) {
- ldb_url = "tdb://test.ldb";
- }
+static int failures;
- ldb = ldb_connect(ldb_url, 0, NULL);
+static void usage(void)
+{
+ printf("Usage: ldbadd <options> <ldif...>\n");
+ printf("Options:\n");
+ printf(" -H ldb_url choose the database (or $LDB_URL)\n");
+ printf("\n");
+ printf("Adds records to a ldb, reading ldif the specified list of files\n\n");
+ exit(1);
+}
- if (!ldb) {
- perror("ldb_connect");
- exit(1);
- }
- while ((ldif = ldif_read_file(stdin))) {
+/*
+ add records from an opened file
+*/
+static int process_file(struct ldb_context *ldb, FILE *f)
+{
+ struct ldb_ldif *ldif;
+ int ret, count=0;
+ while ((ldif = ldif_read_file(f))) {
if (ldif->changetype != LDB_CHANGETYPE_ADD &&
ldif->changetype != LDB_CHANGETYPE_NONE) {
fprintf(stderr, "Only CHANGETYPE_ADD records allowed\n");
@@ -73,6 +73,69 @@
ldif_read_free(ldif);
}
+ return count;
+}
+
+
+
+ int main(int argc, char * const argv[])
+{
+ struct ldb_context *ldb;
+ int count=0;
+ const char *ldb_url;
+ int opt, i;
+
+ ldb_url = getenv("LDB_URL");
+
+ while ((opt = getopt(argc, argv, "hH:")) != EOF) {
+ switch (opt) {
+ case 'H':
+ ldb_url = optarg;
+ break;
+
+ case 'h':
+ default:
+ usage();
+ break;
+ }
+ }
+
+ if (!ldb_url) {
+ fprintf(stderr, "You must specify a ldb URL\n");
+ exit(1);
+ }
+
+ argc -= optind;
+ argv += optind;
+
+ ldb = ldb_connect(ldb_url, 0, NULL);
+
+ if (!ldb) {
+ perror("ldb_connect");
+ exit(1);
+ }
+
+ if (argc == 0) {
+ usage();
+ }
+
+ for (i=0;i<argc;i++) {
+ FILE *f;
+ if (strcmp(argv[i],"-") == 0) {
+ f = stdin;
+ } else {
+ f = fopen(argv[i], "r");
+ }
+ if (!f) {
+ perror(argv[i]);
+ exit(1);
+ }
+ count += process_file(ldb, f);
+ if (f != stdin) {
+ fclose(f);
+ }
+ }
+
ldb_close(ldb);
printf("Added %d records with %d failures\n", count, failures);
diff --git a/source4/lib/ldb/tools/ldbdel.c b/source4/lib/ldb/tools/ldbdel.c
index 177279d47a..0e50a68532 100644
--- a/source4/lib/ldb/tools/ldbdel.c
+++ b/source4/lib/ldb/tools/ldbdel.c
@@ -34,20 +34,48 @@
#include "includes.h"
- int main(int argc, const char *argv[])
+static void usage(void)
{
- static struct ldb_context *ldb;
+ printf("Usage: ldbdel <options> <DN...>\n");
+ printf("Options:\n");
+ printf(" -H ldb_url choose the database (or $LDB_URL)\n");
+ printf("\n");
+ printf("Deletes records from a ldb\n\n");
+ exit(1);
+}
+
+ int main(int argc, char * const argv[])
+{
+ struct ldb_context *ldb;
int ret, i;
const char *ldb_url;
+ int opt;
ldb_url = getenv("LDB_URL");
+
+ while ((opt = getopt(argc, argv, "hH:")) != EOF) {
+ switch (opt) {
+ case 'H':
+ ldb_url = optarg;
+ break;
+
+ case 'h':
+ default:
+ usage();
+ break;
+ }
+ }
+
if (!ldb_url) {
- ldb_url = "tdb://test.ldb";
+ fprintf(stderr, "You must specify a ldb URL\n");
+ exit(1);
}
+ argc -= optind;
+ argv += optind;
- if (argc < 2) {
- printf("Usage: ldbdel <dn...>\n");
+ if (argc < 1) {
+ usage();
exit(1);
}
@@ -57,7 +85,7 @@
exit(1);
}
- for (i=1;i<argc;i++) {
+ for (i=0;i<argc;i++) {
ret = ldb_delete(ldb, argv[i]);
if (ret != 0) {
printf("delete of '%s' failed\n", argv[i]);
@@ -65,5 +93,6 @@
}
ldb_close(ldb);
+
return 0;
}
diff --git a/source4/lib/ldb/tools/ldbedit.c b/source4/lib/ldb/tools/ldbedit.c
new file mode 100644
index 0000000000..c5eb1349dd
--- /dev/null
+++ b/source4/lib/ldb/tools/ldbedit.c
@@ -0,0 +1,365 @@
+/*
+ ldb database library
+
+ Copyright (C) Andrew Tridgell 2004
+
+ ** NOTE! The following LGPL license applies to the ldb
+ ** library. This does NOT imply that all of Samba is released
+ ** under the LGPL
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library 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
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+*/
+
+/*
+ * Name: ldb
+ *
+ * Component: ldbedit
+ *
+ * Description: utility for ldb editing
+ *
+ * Author: Andrew Tridgell
+ */
+
+#include "includes.h"
+
+/*
+ modify a database record so msg1 becomes msg2
+*/
+static int modify_record(struct ldb_context *ldb,
+ struct ldb_message *msg1,
+ struct ldb_message *msg2)
+{
+ struct ldb_message mod;
+ struct ldb_message_element *el;
+ int i;
+
+ mod.dn = msg1->dn;
+ mod.num_elements = 0;
+ mod.elements = NULL;
+
+ /* look in msg2 to find elements that need to be added
+ or modified */
+ for (i=0;i<msg2->num_elements;i++) {
+ el = ldb_msg_find_element(msg1, msg2->elements[i].name);
+
+ if (el && ldb_msg_element_compare(el, &msg2->elements[i]) == 0) {
+ continue;
+ }
+
+ if (ldb_msg_add(&mod,
+ &msg2->elements[i],
+ el?LDB_FLAG_MOD_REPLACE:LDB_FLAG_MOD_ADD) != 0) {
+ return -1;
+ }
+ }
+
+ /* look in msg1 to find elements that need to be deleted */
+ for (i=0;i<msg1->num_elements;i++) {
+ el = ldb_msg_find_element(msg2, msg1->elements[i].name);
+ if (!el) {
+ if (ldb_msg_add_empty(&mod,
+ msg1->elements[i].name,
+ LDB_FLAG_MOD_DELETE) != 0) {
+ return -1;
+ }
+ }
+ }
+
+ if (mod.num_elements == 0) {
+ return 0;
+ }
+
+ if (ldb_modify(ldb, &mod) != 0) {
+ fprintf(stderr, "failed to modify %s\n", msg1->dn);
+ return -1;
+ }
+
+ return 0;
+}
+
+/*
+ find dn in msgs[]
+*/
+static struct ldb_message *msg_find(struct ldb_message **msgs, int count,
+ const char *dn)
+{
+ int i;
+ for (i=0;i<count;i++) {
+ if (strcmp(dn, msgs[i]->dn) == 0) {
+ return msgs[i];
+ }
+ }
+ return NULL;
+}
+
+/*
+ merge the changes in msgs2 into the messages from msgs1
+*/
+static int merge_edits(struct ldb_context *ldb,
+ struct ldb_message **msgs1, int count1,
+ struct ldb_message **msgs2, int count2)
+{
+ int i;
+ struct ldb_message *msg;
+ int ret = 0;
+
+ /* do the adds and modifies */
+ for (i=0;i<count2;i++) {
+ msg = msg_find(msgs1, count1, msgs2[i]->dn);
+ if (!msg) {
+ if (ldb_add(ldb, msgs2[i]) != 0) {
+ fprintf(stderr, "failed to add %s\n",
+ msgs2[i]->dn);
+ return -1;
+ }
+ } else {
+ modify_record(ldb, msg, msgs2[i]);
+ }
+ }
+
+ /* do the deletes */
+ for (i=0;i<count1;i++) {
+ msg = msg_find(msgs2, count2, msgs1[i]->dn);
+ if (!msg) {
+ if (ldb_delete(ldb, msgs1[i]->dn) != 0) {
+ fprintf(stderr, "failed to delete %s\n",
+ msgs1[i]->dn);
+ return -1;
+ }
+ }
+ }
+
+ return ret;
+}
+
+/*
+ save a set of messages as ldif to a file
+*/
+static int save_ldif(FILE *f, struct ldb_message **msgs, int count)
+{
+ int i;
+
+ fprintf(f, "# returned %d records\n", count);
+
+ for (i=0;i<count;i++) {
+ struct ldb_ldif ldif;
+ fprintf(f, "# record %d\n", i+1);
+
+ ldif.changetype = LDB_CHANGETYPE_NONE;
+ ldif.msg = *msgs[i];
+
+ ldif_write_file(f, &ldif);
+ }
+
+ return 0;
+}
+
+
+/*
+ edit the ldb search results in msgs using the user selected editor
+*/
+static int do_edit(struct ldb_context *ldb, struct ldb_message **msgs1, int count1,
+ const char *editor)
+{
+ int fd, ret;
+ FILE *f;
+ char template[] = "/tmp/ldbedit.XXXXXX";
+ char *cmd;
+ struct ldb_ldif *ldif;
+ struct ldb_message **msgs2 = NULL;
+ int count2 = 0;
+
+ /* write out the original set of messages to a temporary
+ file */
+ fd = mkstemp(template);
+
+ if (fd == -1) {
+ perror(template);
+ return -1;
+ }
+
+ f = fdopen(fd, "r+");
+
+ if (!f) {
+ perror("fopen");
+ close(fd);
+ unlink(template);
+ return -1;
+ }
+
+ if (save_ldif(f, msgs1, count1) != 0) {
+ return -1;
+ }
+
+ fclose(f);
+
+ asprintf(&cmd, "%s %s", editor, template);
+
+ if (!cmd) {
+ unlink(template);
+ fprintf(stderr, "out of memory\n");
+ return -1;
+ }
+
+ /* run the editor */
+ ret = system(cmd);
+ free(cmd);
+
+ if (ret != 0) {
+ unlink(template);
+ fprintf(stderr, "edit with %s failed\n", editor);
+ return -1;
+ }
+
+ /* read the resulting ldif into msgs2 */
+ f = fopen(template, "r");
+ if (!f) {
+ perror(template);
+ return -1;
+ }
+
+ while ((ldif = ldif_read_file(f))) {
+ msgs2 = realloc_p(msgs2, struct ldb_message *, count2+1);
+ if (!msgs2) {
+ fprintf(stderr, "out of memory");
+ return -1;
+ }
+ msgs2[count2++] = &ldif->msg;
+ }
+
+ fclose(f);
+ unlink(template);
+
+ return merge_edits(ldb, msgs1, count1, msgs2, count2);
+}
+
+static void usage(void)
+{
+ printf("Usage: ldbedit <options> <expression>\n");
+ printf("Options:\n");
+ printf(" -H ldb_url choose the database (or $LDB_URL)\n");
+ printf(" -s base|sub|one choose search scope\n");
+ printf(" -b basedn choose baseDN\n");
+ printf(" -a edit all records (expression 'dn=*')\n");
+ printf(" -e editor choose editor (or $VISUAL or $EDITOR)\n");
+ exit(1);
+}
+
+ int main(int argc, char * const argv[])
+{
+ struct ldb_context *ldb;
+ struct ldb_message **msgs;
+ int ret;
+ const char *expression = NULL;
+ const char *ldb_url;
+ const char *basedn = NULL;
+ int opt;
+ enum ldb_scope scope = LDB_SCOPE_SUBTREE;
+ const char *editor;
+
+ ldb_url = getenv("LDB_URL");
+
+ /* build the editor command to run -
+ use the same editor priorities as vipw */
+ editor = getenv("VISUAL");
+ if (!editor) {
+ editor = getenv("EDITOR");
+ }
+ if (!editor) {
+ editor = "vi";
+ }
+
+ while ((opt = getopt(argc, argv, "ab:e:H:s:")) != EOF) {
+ switch (opt) {
+ case 'b':
+ basedn = optarg;
+ break;
+
+ case 'H':
+ ldb_url = optarg;
+ break;
+
+ case 's':
+ if (strcmp(optarg, "base") == 0) {
+ scope = LDB_SCOPE_BASE;
+ } else if (strcmp(optarg, "sub") == 0) {
+ scope = LDB_SCOPE_SUBTREE;
+ } else if (strcmp(optarg, "one") == 0) {
+ scope = LDB_SCOPE_ONELEVEL;
+ }
+ break;
+
+ case 'e':
+ editor = optarg;
+ break;
+
+ case 'a':
+ expression = "dn=*";
+ break;
+
+ case 'h':
+ default:
+ usage();
+ break;
+ }
+ }
+
+ if (!ldb_url) {
+ fprintf(stderr, "You must specify a ldb URL\n");
+ exit(1);
+ }
+
+ argc -= optind;
+ argv += optind;
+
+ if (!expression) {
+ if (argc == 0) {
+ usage();
+ }
+ expression = argv[0];
+ }
+
+ ldb = ldb_connect(ldb_url, 0, NULL);
+
+ if (!ldb) {
+ perror("ldb_connect");
+ exit(1);
+ }
+
+ ret = ldb_search(ldb, basedn, scope, expression, NULL, &msgs);
+
+ if (ret == -1) {
+ printf("search failed - %s\n", ldb_errstring(ldb));
+ exit(1);
+ }
+
+ if (ret == 0) {
+ printf("no matching records - cannot edit\n");
+ return 0;
+ }
+
+ do_edit(ldb, msgs, ret, editor);
+
+ if (ret > 0) {
+ ret = ldb_search_free(ldb, msgs);
+ if (ret == -1) {
+ fprintf(stderr, "search_free failed\n");
+ exit(1);
+ }
+ }
+
+ ldb_close(ldb);
+ return 0;
+}
diff --git a/source4/lib/ldb/tools/ldbmodify.c b/source4/lib/ldb/tools/ldbmodify.c
index e1cff655db..a93c710a7a 100644
--- a/source4/lib/ldb/tools/ldbmodify.c
+++ b/source4/lib/ldb/tools/ldbmodify.c
@@ -34,27 +34,27 @@
#include "includes.h"
- int main(void)
-{
- static struct ldb_context *ldb;
- struct ldb_ldif *ldif;
- int ret;
- int count=0, failures=0;
- const char *ldb_url;
-
- ldb_url = getenv("LDB_URL");
- if (!ldb_url) {
- ldb_url = "tdb://test.ldb";
- }
+static int failures;
- ldb = ldb_connect(ldb_url, 0, NULL);
-
- if (!ldb) {
- perror("ldb_connect");
- exit(1);
- }
+static void usage(void)
+{
+ printf("Usage: ldbmodify <options> <ldif...>\n");
+ printf("Options:\n");
+ printf(" -H ldb_url choose the database (or $LDB_URL)\n");
+ printf("\n");
+ printf("Modifies a ldb based upon ldif change records\n\n");
+ exit(1);
+}
- while ((ldif = ldif_read_file(stdin))) {
+/*
+ process modifies for one file
+*/
+static int process_file(struct ldb_context *ldb, FILE *f)
+{
+ struct ldb_ldif *ldif;
+ int ret, count = 0;
+
+ while ((ldif = ldif_read_file(f))) {
switch (ldif->changetype) {
case LDB_CHANGETYPE_NONE:
case LDB_CHANGETYPE_ADD:
@@ -77,6 +77,68 @@
ldif_read_free(ldif);
}
+ return count;
+}
+
+ int main(int argc, char * const argv[])
+{
+ struct ldb_context *ldb;
+ int count=0;
+ const char *ldb_url;
+ int opt, i;
+
+ ldb_url = getenv("LDB_URL");
+
+ while ((opt = getopt(argc, argv, "hH:")) != EOF) {
+ switch (opt) {
+ case 'H':
+ ldb_url = optarg;
+ break;
+
+ case 'h':
+ default:
+ usage();
+ break;
+ }
+ }
+
+ if (!ldb_url) {
+ fprintf(stderr, "You must specify a ldb URL\n");
+ exit(1);
+ }
+
+ argc -= optind;
+ argv += optind;
+
+ ldb = ldb_connect(ldb_url, 0, NULL);
+
+ if (!ldb) {
+ perror("ldb_connect");
+ exit(1);
+ }
+
+ if (argc == 0) {
+ usage();
+ exit(1);
+ }
+
+ for (i=0;i<argc;i++) {
+ FILE *f;
+ if (strcmp(argv[i],"-") == 0) {
+ f = stdin;
+ } else {
+ f = fopen(argv[i], "r");
+ }
+ if (!f) {
+ perror(argv[i]);
+ exit(1);
+ }
+ count += process_file(ldb, f);
+ if (f != stdin) {
+ fclose(f);
+ }
+ }
+
ldb_close(ldb);
printf("Modified %d records with %d failures\n", count, failures);
diff --git a/source4/lib/ldb/tools/ldbsearch.c b/source4/lib/ldb/tools/ldbsearch.c
index f4eb8f00db..327feb28ef 100644
--- a/source4/lib/ldb/tools/ldbsearch.c
+++ b/source4/lib/ldb/tools/ldbsearch.c
@@ -33,26 +33,32 @@
*/
#include "includes.h"
-#include <getopt.h>
+
+static void usage(void)
+{
+ printf("Usage: ldbsearch <options> <expression> <attrs...>\n");
+ printf("Options:\n");
+ printf(" -H ldb_url choose the database (or $LDB_URL)\n");
+ printf(" -s base|sub|one choose search scope\n");
+ printf(" -b basedn choose baseDN\n");
+ exit(1);
+}
int main(int argc, char * const argv[])
{
- static struct ldb_context *ldb;
+ struct ldb_context *ldb;
struct ldb_message **msgs;
int ret, i;
const char *expression;
- const char * const *attrs = NULL;
+ char * const *attrs = NULL;
const char *ldb_url;
const char *basedn = NULL;
int opt;
enum ldb_scope scope = LDB_SCOPE_SUBTREE;
ldb_url = getenv("LDB_URL");
- if (!ldb_url) {
- ldb_url = "tdb://test.ldb";
- }
- while ((opt = getopt(argc, argv, "b:H:s:")) != EOF) {
+ while ((opt = getopt(argc, argv, "b:H:s:h")) != EOF) {
switch (opt) {
case 'b':
basedn = optarg;
@@ -71,14 +77,24 @@
scope = LDB_SCOPE_ONELEVEL;
}
break;
+
+ case 'h':
+ default:
+ usage();
+ break;
}
}
+ if (!ldb_url) {
+ fprintf(stderr, "You must specify a ldb URL\n");
+ exit(1);
+ }
+
argc -= optind;
argv += optind;
if (argc < 1) {
- printf("Usage: ldbsearch <expression> [attrs...]\n");
+ usage();
exit(1);
}