Line data Source code
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: ldbmodify
28 : *
29 : * Description: utility to modify records - modelled on ldapmodify
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 :
42 1 : static void usage(struct ldb_context *ldb)
43 : {
44 1 : printf("Usage: ldbmodify <options> <ldif...>\n");
45 1 : printf("Modifies a ldb based upon ldif change records\n\n");
46 1 : ldb_cmdline_help(ldb, "ldbmodify", stdout);
47 1 : exit(LDB_ERR_OPERATIONS_ERROR);
48 : }
49 :
50 : /*
51 : process modifies for one file
52 : */
53 348 : static int process_file(struct ldb_context *ldb, FILE *f, unsigned int *count)
54 : {
55 : struct ldb_ldif *ldif;
56 348 : int fun_ret = LDB_SUCCESS, ret;
57 348 : struct ldb_control **req_ctrls = ldb_parse_control_strings(ldb, ldb, (const char **)options->controls);
58 348 : struct ldif_read_file_state state = {
59 : .f = f
60 : };
61 :
62 348 : if (options->controls != NULL && req_ctrls== NULL) {
63 0 : printf("parsing controls failed: %s\n", ldb_errstring(ldb));
64 0 : exit(LDB_ERR_OPERATIONS_ERROR);
65 : }
66 :
67 348 : fun_ret = ldb_transaction_start(ldb);
68 348 : if (fun_ret != LDB_SUCCESS) {
69 0 : fprintf(stderr, "ERR: (%s) on transaction start\n",
70 : ldb_errstring(ldb));
71 0 : return fun_ret;
72 : }
73 :
74 946 : while ((ldif = ldb_ldif_read_file_state(ldb, &state))) {
75 : struct ldb_dn *olddn;
76 357 : bool deleteoldrdn = false;
77 : struct ldb_dn *newdn;
78 357 : const char *errstr = NULL;
79 :
80 357 : switch (ldif->changetype) {
81 14 : case LDB_CHANGETYPE_NONE:
82 : case LDB_CHANGETYPE_ADD:
83 14 : ret = ldb_add_ctrl(ldb, ldif->msg,req_ctrls);
84 14 : break;
85 2 : case LDB_CHANGETYPE_DELETE:
86 2 : ret = ldb_delete_ctrl(ldb, ldif->msg->dn,req_ctrls);
87 2 : break;
88 338 : case LDB_CHANGETYPE_MODIFY:
89 338 : ret = ldb_modify_ctrl(ldb, ldif->msg,req_ctrls);
90 338 : break;
91 3 : case LDB_CHANGETYPE_MODRDN:
92 3 : ret = ldb_ldif_parse_modrdn(ldb, ldif, ldif, &olddn,
93 : NULL, &deleteoldrdn,
94 : NULL, &newdn);
95 3 : if (ret == LDB_SUCCESS) {
96 3 : if (deleteoldrdn) {
97 3 : ret = ldb_rename(ldb, olddn, newdn);
98 : } else {
99 0 : errstr = "modrdn: deleteoldrdn=0 "
100 : "not supported.";
101 0 : ret = LDB_ERR_CONSTRAINT_VIOLATION;
102 : }
103 : }
104 3 : break;
105 : }
106 357 : if (ret != LDB_SUCCESS) {
107 1 : if (errstr == NULL) {
108 1 : errstr = ldb_errstring(ldb);
109 : }
110 2 : fprintf(stderr,
111 : "ERR: (%s) \"%s\" on DN %s at block before "
112 : "line %zu\n",
113 : ldb_strerror(ret),
114 : errstr,
115 1 : ldb_dn_get_linearized(ldif->msg->dn),
116 : state.line_no);
117 1 : fun_ret = ret;
118 : } else {
119 356 : (*count)++;
120 356 : if (options->verbose) {
121 0 : printf("Modified %s\n", ldb_dn_get_linearized(ldif->msg->dn));
122 : }
123 : }
124 357 : ldb_ldif_read_free(ldb, ldif);
125 357 : if (ret) {
126 1 : break;
127 : }
128 : }
129 :
130 348 : if (fun_ret == LDB_SUCCESS && !feof(f)) {
131 0 : fprintf(stderr, "Failed to parse ldif\n");
132 0 : fun_ret = LDB_ERR_OPERATIONS_ERROR;
133 : }
134 :
135 348 : if (fun_ret == LDB_SUCCESS) {
136 347 : fun_ret = ldb_transaction_commit(ldb);
137 347 : if (fun_ret != LDB_SUCCESS) {
138 0 : fprintf(stderr, "ERR: (%s) on transaction commit\n",
139 : ldb_errstring(ldb));
140 : }
141 : } else {
142 1 : ldb_transaction_cancel(ldb);
143 : }
144 :
145 348 : return fun_ret;
146 : }
147 :
148 340 : int main(int argc, const char **argv)
149 : {
150 : struct ldb_context *ldb;
151 340 : unsigned int i, count = 0;
152 340 : int ret = LDB_SUCCESS;
153 340 : TALLOC_CTX *mem_ctx = talloc_new(NULL);
154 :
155 340 : ldb = ldb_init(mem_ctx, NULL);
156 340 : if (ldb == NULL) {
157 0 : return LDB_ERR_OPERATIONS_ERROR;
158 : }
159 :
160 340 : options = ldb_cmdline_process(ldb, argc, argv, usage);
161 :
162 338 : if (options->argc == 0) {
163 280 : ret = process_file(ldb, stdin, &count);
164 : } else {
165 126 : for (i=0;i<options->argc;i++) {
166 68 : const char *fname = options->argv[i];
167 : FILE *f;
168 68 : f = fopen(fname, "r");
169 68 : if (!f) {
170 0 : perror(fname);
171 0 : return LDB_ERR_OPERATIONS_ERROR;
172 : }
173 68 : ret = process_file(ldb, f, &count);
174 68 : fclose(f);
175 : }
176 : }
177 :
178 338 : talloc_free(mem_ctx);
179 :
180 338 : if (ret) {
181 1 : printf("Modify failed after processing %u records\n", count);
182 : } else {
183 337 : printf("Modified %u records successfully\n", count);
184 : }
185 :
186 338 : return ret;
187 : }
|