s3: piddir creation fix part 2.
[ira/wip.git] / source3 / utils / dbwrap_tool.c
1 /*
2    Samba Unix/Linux CIFS implementation
3
4    low level TDB/CTDB tool using the dbwrap interface
5
6    Copyright (C) 2009 Michael Adam <obnox@samba.org>
7    Copyright (C) 2011 Bjoern Baumbach <bb@sernet.de>
8
9    This program is free software; you can redistribute it and/or modify
10    it under the terms of the GNU General Public License as published by
11    the Free Software Foundation; either version 3 of the License, or
12    (at your option) any later version.
13
14    This program is distributed in the hope that it will be useful,
15    but WITHOUT ANY WARRANTY; without even the implied warranty of
16    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17    GNU General Public License for more details.
18
19    You should have received a copy of the GNU General Public License
20    along with this program.  If not, see <http://www.gnu.org/licenses/>.
21 */
22
23 #include "includes.h"
24 #include "system/filesys.h"
25 #include "popt_common.h"
26 #include "dbwrap/dbwrap.h"
27 #include "dbwrap/dbwrap_open.h"
28 #include "messages.h"
29 #include "util_tdb.h"
30
31 enum dbwrap_op { OP_FETCH, OP_STORE, OP_DELETE, OP_ERASE, OP_LISTKEYS };
32
33 enum dbwrap_type { TYPE_INT32, TYPE_UINT32, TYPE_STRING, TYPE_HEX };
34
35 static int dbwrap_tool_fetch_int32(struct db_context *db,
36                                    const char *keyname,
37                                    const char *data)
38 {
39         int32_t value;
40         NTSTATUS status;
41
42         status = dbwrap_fetch_int32(db, keyname, &value);
43         if (!NT_STATUS_IS_OK(status)) {
44                 d_printf("Error fetching int32 from key '%s': %s\n",
45                          keyname, nt_errstr(status));
46                 return -1;
47         }
48         d_printf("%d\n", value);
49
50         return 0;
51 }
52
53 static int dbwrap_tool_fetch_uint32(struct db_context *db,
54                                     const char *keyname,
55                                     const char *data)
56 {
57         uint32_t value;
58         NTSTATUS ret;
59
60         ret = dbwrap_fetch_uint32(db, keyname, &value);
61         if (NT_STATUS_IS_OK(ret)) {
62                 d_printf("%u\n", value);
63                 return 0;
64         } else {
65                 d_fprintf(stderr, "ERROR: could not fetch uint32 key '%s': "
66                           "%s\n", nt_errstr(ret), keyname);
67                 return -1;
68         }
69 }
70
71 static int dbwrap_tool_fetch_string(struct db_context *db,
72                                     const char *keyname,
73                                     const char *data)
74 {
75         TDB_DATA tdbdata;
76         NTSTATUS status;
77         TALLOC_CTX *tmp_ctx = talloc_stackframe();
78         int ret;
79
80         status = dbwrap_fetch_bystring(db, tmp_ctx, keyname, &tdbdata);
81         if (NT_STATUS_IS_OK(status)) {
82                 d_printf("%-*.*s\n", (int)tdbdata.dsize, (int)tdbdata.dsize,
83                          tdbdata.dptr);
84                 ret = 0;
85         } else {
86                 d_fprintf(stderr, "ERROR: could not fetch string key '%s': "
87                           "%s\n", nt_errstr(status), keyname);
88                 ret = -1;
89         }
90
91         talloc_free(tmp_ctx);
92         return ret;
93 }
94
95 static int dbwrap_tool_fetch_hex(struct db_context *db,
96                                  const char *keyname,
97                                  const char *data)
98 {
99         TDB_DATA tdbdata;
100         DATA_BLOB datablob;
101         NTSTATUS status;
102         TALLOC_CTX *tmp_ctx = talloc_stackframe();
103         char *hex_string;
104         int ret;
105
106         status = dbwrap_fetch_bystring(db, tmp_ctx, keyname, &tdbdata);
107         if (NT_STATUS_IS_OK(status)) {
108                 datablob.data = tdbdata.dptr;
109                 datablob.length = tdbdata.dsize;
110
111                 hex_string = data_blob_hex_string_upper(tmp_ctx, &datablob);
112                 if (hex_string == NULL) {
113                         d_fprintf(stderr, "ERROR: could not get hex string "
114                                   "from data blob\n");
115                         ret = -1;
116                 } else {
117                         d_printf("%s\n", hex_string);
118                         ret =  0;
119                 }
120         } else {
121                 d_fprintf(stderr, "ERROR: could not fetch hex key '%s': "
122                           "%s\n", nt_errstr(status), keyname);
123                 ret = -1;
124         }
125
126         talloc_free(tmp_ctx);
127         return ret;
128 }
129
130 static int dbwrap_tool_store_int32(struct db_context *db,
131                                    const char *keyname,
132                                    const char *data)
133 {
134         NTSTATUS status;
135         int32_t value = (int32_t)strtol(data, NULL, 10);
136
137         status = dbwrap_trans_store_int32(db, keyname, value);
138
139         if (!NT_STATUS_IS_OK(status)) {
140                 d_fprintf(stderr, "ERROR: could not store int32 key '%s': %s\n",
141                           keyname, nt_errstr(status));
142                 return -1;
143         }
144
145         return 0;
146 }
147
148 static int dbwrap_tool_store_uint32(struct db_context *db,
149                                     const char *keyname,
150                                     const char *data)
151 {
152         NTSTATUS status;
153         uint32_t value = (uint32_t)strtol(data, NULL, 10);
154
155         status = dbwrap_trans_store_uint32(db, keyname, value);
156
157         if (!NT_STATUS_IS_OK(status)) {
158                 d_fprintf(stderr,
159                           "ERROR: could not store uint32 key '%s': %s\n",
160                           keyname, nt_errstr(status));
161                 return -1;
162         }
163
164         return 0;
165 }
166
167 static int dbwrap_tool_store_string(struct db_context *db,
168                                     const char *keyname,
169                                     const char *data)
170 {
171         NTSTATUS status;
172
173         status = dbwrap_trans_store_bystring(db, keyname,
174                            string_term_tdb_data(data), TDB_REPLACE);
175
176         if (!NT_STATUS_IS_OK(status)) {
177                 d_fprintf(stderr,
178                           "ERROR: could not store string key '%s': %s\n",
179                           keyname, nt_errstr(status));
180                 return -1;
181         }
182
183         return 0;
184 }
185
186 static int dbwrap_tool_store_hex(struct db_context *db,
187                                     const char *keyname,
188                                     const char *data)
189 {
190         NTSTATUS status;
191         DATA_BLOB datablob;
192         TDB_DATA tdbdata;
193         TALLOC_CTX *tmp_ctx = talloc_stackframe();
194
195         datablob = strhex_to_data_blob(tmp_ctx, data);
196         if(strlen(data) > 0 && datablob.length == 0) {
197                 d_fprintf(stderr,
198                           "ERROR: could not convert hex string to data blob\n"
199                           "       Not a valid hex string?\n");
200                 talloc_free(tmp_ctx);
201                 return -1;
202         }
203
204         tdbdata.dptr = (unsigned char *)datablob.data;
205         tdbdata.dsize = datablob.length;
206
207         status = dbwrap_trans_store_bystring(db, keyname,
208                                              tdbdata,
209                                              TDB_REPLACE);
210         if (!NT_STATUS_IS_OK(status)) {
211                 d_fprintf(stderr,
212                           "ERROR: could not store string key '%s': %s\n",
213                           keyname, nt_errstr(status));
214                 talloc_free(tmp_ctx);
215                 return -1;
216         }
217
218         talloc_free(tmp_ctx);
219         return 0;
220 }
221
222 static int dbwrap_tool_delete(struct db_context *db,
223                               const char *keyname,
224                               const char *data)
225 {
226         NTSTATUS status;
227
228         status = dbwrap_trans_delete_bystring(db, keyname);
229
230         if (!NT_STATUS_IS_OK(status)) {
231                 d_fprintf(stderr, "ERROR deleting record %s : %s\n",
232                           keyname, nt_errstr(status));
233                 return -1;
234         }
235
236         return 0;
237 }
238
239 static int delete_fn(struct db_record *rec, void *priv)
240 {
241         dbwrap_record_delete(rec);
242         return 0;
243 }
244
245 /**
246  * dbwrap_tool_erase: erase the whole data base
247  * the keyname argument is not used.
248  */
249 static int dbwrap_tool_erase(struct db_context *db,
250                              const char *keyname,
251                              const char *data)
252 {
253         NTSTATUS status;
254
255         status = dbwrap_traverse(db, delete_fn, NULL, NULL);
256
257         if (!NT_STATUS_IS_OK(status)) {
258                 d_fprintf(stderr, "ERROR erasing the database\n");
259                 return -1;
260         }
261
262         return 0;
263 }
264
265 static int listkey_fn(struct db_record *rec, void *private_data)
266 {
267         int length = dbwrap_record_get_key(rec).dsize;
268         unsigned char *p = (unsigned char *)dbwrap_record_get_key(rec).dptr;
269
270         while (length--) {
271                 if (isprint(*p) && !strchr("\"\\", *p)) {
272                         d_printf("%c", *p);
273                 } else {
274                         d_printf("\\%02X", *p);
275                 }
276                 p++;
277         }
278
279         d_printf("\n");
280
281         return 0;
282 }
283
284 static int dbwrap_tool_listkeys(struct db_context *db,
285                                 const char *keyname,
286                                 const char *data)
287 {
288         NTSTATUS status;
289
290         status = dbwrap_traverse_read(db, listkey_fn, NULL, NULL);
291
292         if (!NT_STATUS_IS_OK(status)) {
293                 d_fprintf(stderr, "ERROR listing db keys\n");
294                 return -1;
295         }
296
297         return 0;
298 }
299
300 struct dbwrap_op_dispatch_table {
301         enum dbwrap_op op;
302         enum dbwrap_type type;
303         int (*cmd)(struct db_context *db,
304                    const char *keyname,
305                    const char *data);
306 };
307
308 struct dbwrap_op_dispatch_table dispatch_table[] = {
309         { OP_FETCH,  TYPE_INT32,  dbwrap_tool_fetch_int32 },
310         { OP_FETCH,  TYPE_UINT32, dbwrap_tool_fetch_uint32 },
311         { OP_FETCH,  TYPE_STRING, dbwrap_tool_fetch_string },
312         { OP_FETCH,  TYPE_HEX,    dbwrap_tool_fetch_hex },
313         { OP_STORE,  TYPE_INT32,  dbwrap_tool_store_int32 },
314         { OP_STORE,  TYPE_UINT32, dbwrap_tool_store_uint32 },
315         { OP_STORE,  TYPE_STRING, dbwrap_tool_store_string },
316         { OP_STORE,  TYPE_HEX,    dbwrap_tool_store_hex },
317         { OP_DELETE, TYPE_INT32,  dbwrap_tool_delete },
318         { OP_ERASE,  TYPE_INT32,  dbwrap_tool_erase },
319         { OP_LISTKEYS, TYPE_INT32, dbwrap_tool_listkeys },
320         { 0, 0, NULL },
321 };
322
323 int main(int argc, const char **argv)
324 {
325         struct tevent_context *evt_ctx;
326         struct messaging_context *msg_ctx;
327         struct db_context *db;
328
329         uint16_t count;
330
331         const char *dbname;
332         const char *opname;
333         enum dbwrap_op op;
334         const char *keyname = "";
335         const char *keytype = "int32";
336         enum dbwrap_type type;
337         const char *valuestr = "0";
338
339         TALLOC_CTX *mem_ctx = talloc_stackframe();
340
341         int ret = 1;
342
343         struct poptOption popt_options[] = {
344                 POPT_AUTOHELP
345                 POPT_COMMON_SAMBA
346                 POPT_TABLEEND
347         };
348         int opt;
349         const char **extra_argv;
350         int extra_argc = 0;
351         poptContext pc;
352
353         load_case_tables();
354         lp_set_cmdline("log level", "0");
355         setup_logging(argv[0], DEBUG_STDERR);
356
357         pc = poptGetContext(argv[0], argc, argv, popt_options, POPT_CONTEXT_KEEP_FIRST);
358
359         while ((opt = poptGetNextOpt(pc)) != -1) {
360                 switch (opt) {
361                 default:
362                         fprintf(stderr, "Invalid option %s: %s\n",
363                                 poptBadOption(pc, 0), poptStrerror(opt));
364                         goto done;
365                 }
366         }
367
368         /* setup the remaining options for the main program to use */
369         extra_argv = poptGetArgs(pc);
370         if (extra_argv) {
371                 extra_argv++;
372                 while (extra_argv[extra_argc]) extra_argc++;
373         }
374
375         lp_load_global(get_dyn_CONFIGFILE());
376
377         if ((extra_argc < 2) || (extra_argc > 5)) {
378                 d_fprintf(stderr,
379                           "USAGE: %s <database> <op> [<key> [<type> [<value>]]]\n"
380                           "       ops: fetch, store, delete, erase, listkeys\n"
381                           "       types: int32, uint32, string, hex\n",
382                          argv[0]);
383                 goto done;
384         }
385
386         dbname = extra_argv[0];
387         opname = extra_argv[1];
388
389         if (strcmp(opname, "store") == 0) {
390                 if (extra_argc != 5) {
391                         d_fprintf(stderr, "ERROR: operation 'store' requires "
392                                   "value argument\n");
393                         goto done;
394                 }
395                 valuestr = extra_argv[4];
396                 keytype = extra_argv[3];
397                 keyname = extra_argv[2];
398                 op = OP_STORE;
399         } else if (strcmp(opname, "fetch") == 0) {
400                 if (extra_argc != 4) {
401                         d_fprintf(stderr, "ERROR: operation 'fetch' requires "
402                                   "type but not value argument\n");
403                         goto done;
404                 }
405                 op = OP_FETCH;
406                 keytype = extra_argv[3];
407                 keyname = extra_argv[2];
408         } else if (strcmp(opname, "delete") == 0) {
409                 if (extra_argc != 3) {
410                         d_fprintf(stderr, "ERROR: operation 'delete' does "
411                                   "not allow type nor value argument\n");
412                         goto done;
413                 }
414                 keyname = extra_argv[2];
415                 op = OP_DELETE;
416         } else if (strcmp(opname, "erase") == 0) {
417                 if (extra_argc != 2) {
418                         d_fprintf(stderr, "ERROR: operation 'erase' does "
419                                   "not take a key argument\n");
420                         goto done;
421                 }
422                 op = OP_ERASE;
423         } else if (strcmp(opname, "listkeys") == 0) {
424                 if (extra_argc != 2) {
425                         d_fprintf(stderr, "ERROR: operation 'listkeys' does "
426                                   "not take a key argument\n");
427                         goto done;
428                 }
429                 op = OP_LISTKEYS;
430         } else {
431                 d_fprintf(stderr,
432                           "ERROR: invalid op '%s' specified\n"
433                           "       supported ops: fetch, store, delete\n",
434                           opname);
435                 goto done;
436         }
437
438         if (strcmp(keytype, "int32") == 0) {
439                 type = TYPE_INT32;
440         } else if (strcmp(keytype, "uint32") == 0) {
441                 type = TYPE_UINT32;
442         } else if (strcmp(keytype, "string") == 0) {
443                 type = TYPE_STRING;
444         } else if (strcmp(keytype, "hex") == 0) {
445                 type = TYPE_HEX;
446         } else {
447                 d_fprintf(stderr, "ERROR: invalid type '%s' specified.\n"
448                                   "       supported types: int32, uint32, "
449                                   "string, hex\n",
450                                   keytype);
451                 goto done;
452         }
453
454         evt_ctx = tevent_context_init(mem_ctx);
455         if (evt_ctx == NULL) {
456                 d_fprintf(stderr, "ERROR: could not init event context\n");
457                 goto done;
458         }
459
460         msg_ctx = messaging_init(mem_ctx, evt_ctx);
461         if (msg_ctx == NULL) {
462                 d_fprintf(stderr, "ERROR: could not init messaging context\n");
463                 goto done;
464         }
465
466         db = db_open(mem_ctx, dbname, 0, TDB_DEFAULT, O_RDWR | O_CREAT, 0644,
467                      DBWRAP_LOCK_ORDER_1);
468         if (db == NULL) {
469                 d_fprintf(stderr, "ERROR: could not open dbname\n");
470                 goto done;
471         }
472
473         for (count = 0; dispatch_table[count].cmd != NULL; count++) {
474                 if ((op == dispatch_table[count].op) &&
475                     (type == dispatch_table[count].type))
476                 {
477                         ret = dispatch_table[count].cmd(db, keyname, valuestr);
478                         break;
479                 }
480         }
481
482 done:
483         TALLOC_FREE(mem_ctx);
484         return ret;
485 }