1 /*
2    ldb database library
3 
4    Copyright (C) Andrew Tridgell  2004
5 
6      ** NOTE! The following LGPL license applies to the ldb
7      ** library. This does NOT imply that all of Samba is released
8      ** under the LGPL
9 
10    This library is free software; you can redistribute it and/or
11    modify it under the terms of the GNU Lesser General Public
12    License as published by the Free Software Foundation; either
13    version 3 of the License, or (at your option) any later version.
14 
15    This library is distributed in the hope that it will be useful,
16    but WITHOUT ANY WARRANTY; without even the implied warranty of
17    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
18    Lesser General Public License for more details.
19 
20    You should have received a copy of the GNU Lesser General Public
21    License along with this library; if not, see <http://www.gnu.org/licenses/>.
22 */
23 
24 /*
25  *  Name: ldb
26  *
27  *  Component: ldbadd
28  *
29  *  Description: utility to add records - modelled on ldapadd
30  *
31  *  Author: Andrew Tridgell
32  */
33 
34 #include "replace.h"
35 #include "ldb.h"
36 #include "tools/cmdline.h"
37 #include "ldbutil.h"
38 #include "include/ldb_private.h"
39 
40 static struct ldb_cmdline *options;
41 
usage(struct ldb_context * ldb)42 static void usage(struct ldb_context *ldb)
43 {
44 	printf("Usage: ldbadd <options> <ldif...>\n");
45 	printf("Adds records to a ldb, reading ldif the specified list of files\n\n");
46 	ldb_cmdline_help(ldb, "ldbadd", stdout);
47 	exit(LDB_ERR_OPERATIONS_ERROR);
48 }
49 
50 
51 /*
52   add records from an opened file
53 */
process_file(struct ldb_context * ldb,FILE * f,unsigned int * count)54 static int process_file(struct ldb_context *ldb, FILE *f, unsigned int *count)
55 {
56 	struct ldb_ldif *ldif;
57 	int fun_ret = LDB_SUCCESS, ret;
58         struct ldb_control **req_ctrls = ldb_parse_control_strings(ldb, ldb, (const char **)options->controls);
59 	struct ldif_read_file_state state = {
60 		.f = f
61 	};
62 
63 	if (options->controls != NULL &&  req_ctrls== NULL) {
64 		printf("parsing controls failed: %s\n", ldb_errstring(ldb));
65 		return LDB_ERR_OPERATIONS_ERROR;
66 	}
67 
68 	fun_ret = ldb_transaction_start(ldb);
69 	if (fun_ret != LDB_SUCCESS) {
70 		fprintf(stderr, "ERR: (%s) on transaction start\n",
71 			ldb_errstring(ldb));
72 		return fun_ret;
73 	}
74 
75 	while ((ldif = ldb_ldif_read_file_state(ldb, &state))) {
76 		if (ldif->changetype != LDB_CHANGETYPE_ADD &&
77 		    ldif->changetype != LDB_CHANGETYPE_NONE) {
78 			fprintf(stderr, "Only CHANGETYPE_ADD records allowed\n");
79 			break;
80 		}
81 
82 		ret = ldb_msg_normalize(ldb, ldif, ldif->msg, &ldif->msg);
83 		if (ret != LDB_SUCCESS) {
84 			fprintf(stderr,
85 			        "ERR: Message canonicalize failed - %s\n",
86 			        ldb_strerror(ret));
87 			fun_ret = ret;
88 			ldb_ldif_read_free(ldb, ldif);
89 			continue;
90 		}
91 
92 		ret = ldb_add_ctrl(ldb, ldif->msg,req_ctrls);
93 		if (ret != LDB_SUCCESS) {
94 			fprintf(stderr, "ERR: %s : \"%s\" on DN %s at block before line %llu\n",
95 				ldb_strerror(ret), ldb_errstring(ldb),
96 				ldb_dn_get_linearized(ldif->msg->dn),
97 				(unsigned long long)state.line_no);
98 			fun_ret = ret;
99 		} else {
100 			(*count)++;
101 			if (options->verbose) {
102 				printf("Added %s\n", ldb_dn_get_linearized(ldif->msg->dn));
103 			}
104 		}
105 		ldb_ldif_read_free(ldb, ldif);
106 		if (ret) {
107 			break;
108 		}
109 	}
110 
111 	if (fun_ret == LDB_SUCCESS && !feof(f)) {
112 		fprintf(stderr, "Failed to parse ldif\n");
113 		fun_ret = LDB_ERR_OPERATIONS_ERROR;
114 	}
115 
116 	if (fun_ret == LDB_SUCCESS) {
117 		fun_ret = ldb_transaction_commit(ldb);
118 		if (fun_ret != LDB_SUCCESS) {
119 			fprintf(stderr, "ERR: (%s) on transaction commit\n",
120 				ldb_errstring(ldb));
121 		}
122 	} else {
123 		ldb_transaction_cancel(ldb);
124 	}
125 
126 	return fun_ret;
127 }
128 
129 
130 
main(int argc,const char ** argv)131 int main(int argc, const char **argv)
132 {
133 	struct ldb_context *ldb;
134 	unsigned int i, count = 0;
135 	int ret = LDB_SUCCESS;
136 	TALLOC_CTX *mem_ctx = talloc_new(NULL);
137 
138 	ldb = ldb_init(mem_ctx, NULL);
139 	if (ldb == NULL) {
140 		return LDB_ERR_OPERATIONS_ERROR;
141 	}
142 
143 	options = ldb_cmdline_process(ldb, argc, argv, usage);
144 
145 	ret = ldb_transaction_start(ldb);
146 	if (ret != LDB_SUCCESS) {
147 		printf("Failed to start transaction: %s\n", ldb_errstring(ldb));
148 		return ret;
149 	}
150 
151 	if (options->argc == 0) {
152 		ret = process_file(ldb, stdin, &count);
153 	} else {
154 		for (i=0;i<options->argc;i++) {
155 			const char *fname = options->argv[i];
156 			FILE *f;
157 			f = fopen(fname, "r");
158 			if (!f) {
159 				perror(fname);
160 				return LDB_ERR_OPERATIONS_ERROR;
161 			}
162 			ret = process_file(ldb, f, &count);
163 			fclose(f);
164 		}
165 	}
166 
167 	if (count != 0) {
168 		ret = ldb_transaction_commit(ldb);
169 		if (ret != LDB_SUCCESS) {
170 			printf("Failed to commit transaction: %s\n", ldb_errstring(ldb));
171 			return ret;
172 		}
173 	} else {
174 		ldb_transaction_cancel(ldb);
175 	}
176 
177 	talloc_free(mem_ctx);
178 
179 	if (ret) {
180 		printf("Add failed after processing %u records\n", count);
181 	} else {
182 		printf("Added %u records successfully\n", count);
183 	}
184 
185 	return ret;
186 }
187