ccan/ntdb: demote to junkcode.
[ccan] / junkcode / rusty@rustcorp.com.au-ntdb / tools / ntdbrestore.c
1 /*
2    ntdbrestore -- construct a ntdb from (n)tdbdump output.
3    Copyright (C) Rusty Russell                  2012
4    Copyright (C) Volker Lendecke                2010
5    Copyright (C) Simon McVittie                 2005
6
7    This program is free software; you can redistribute it and/or modify
8    it under the terms of the GNU General Public License as published by
9    the Free Software Foundation; either version 3 of the License, or
10    (at your option) any later version.
11
12    This program is distributed in the hope that it will be useful,
13    but WITHOUT ANY WARRANTY; without even the implied warranty of
14    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15    GNU General Public License for more details.
16
17    You should have received a copy of the GNU General Public License
18    along with this program.  If not, see <http://www.gnu.org/licenses/>.
19 */
20
21 #include "config.h"
22 #include "ntdb.h"
23 #include "private.h"
24 #include <assert.h>
25
26 static int read_linehead(FILE *f)
27 {
28         int i, c;
29         int num_bytes;
30         char prefix[128];
31
32         while (1) {
33                 c = getc(f);
34                 if (c == EOF) {
35                         return -1;
36                 }
37                 if (c == '(') {
38                         break;
39                 }
40         }
41         for (i=0; i<sizeof(prefix); i++) {
42                 c = getc(f);
43                 if (c == EOF) {
44                         return -1;
45                 }
46                 prefix[i] = c;
47                 if (c == '"') {
48                         break;
49                 }
50         }
51         if (i == sizeof(prefix)) {
52                 return -1;
53         }
54         prefix[i] = '\0';
55
56         if (sscanf(prefix, "%d) = ", &num_bytes) != 1) {
57                 return -1;
58         }
59         return num_bytes;
60 }
61
62 static int read_hex(void) {
63         int c;
64         c = getchar();
65         if (c == EOF) {
66                 fprintf(stderr, "Unexpected EOF in data\n");
67                 return -1;
68         } else if (c == '"') {
69                 fprintf(stderr, "Unexpected \\\" sequence\n");
70                 return -1;
71         } else if ('0' <= c && c <= '9')  {
72                 return c - '0';
73         } else if ('A' <= c && c <= 'F')  {
74                 return c - 'A' + 10;
75         } else if ('a' <= c && c <= 'f')  {
76                 return c - 'a' + 10;
77         } else {
78                 fprintf(stderr, "Invalid hex: %c\n", c);
79                 return -1;
80         }
81 }
82
83 static int read_data(FILE *f, NTDB_DATA *d, size_t size) {
84         int c, low, high;
85         int i;
86
87         d->dptr = (unsigned char *)malloc(size);
88         if (d->dptr == NULL) {
89                 return -1;
90         }
91         d->dsize = size;
92
93         for (i=0; i<size; i++) {
94                 c = getc(f);
95                 if (c == EOF) {
96                         fprintf(stderr, "Unexpected EOF in data\n");
97                         return 1;
98                 } else if (c == '"') {
99                         return 0;
100                 } else if (c == '\\') {
101                         high = read_hex();
102                         if (high < 0) {
103                                 return -1;
104                         }
105                         high = high << 4;
106                         assert(high == (high & 0xf0));
107                         low = read_hex();
108                         if (low < 0) {
109                                 return -1;
110                         }
111                         assert(low == (low & 0x0f));
112                         d->dptr[i] = (low|high);
113                 } else {
114                         d->dptr[i] = c;
115                 }
116         }
117         return 0;
118 }
119
120 static int swallow(FILE *f, const char *s, int *eof)
121 {
122         char line[128];
123
124         if (fgets(line, sizeof(line), f) == NULL) {
125                 if (eof != NULL) {
126                         *eof = 1;
127                 }
128                 return -1;
129         }
130         if (strcmp(line, s) != 0) {
131                 return -1;
132         }
133         return 0;
134 }
135
136 static bool read_rec(FILE *f, struct ntdb_context *ntdb, int *eof)
137 {
138         int length;
139         NTDB_DATA key, data;
140         bool ret = false;
141         enum NTDB_ERROR e;
142
143         key.dptr = NULL;
144         data.dptr = NULL;
145
146         if (swallow(f, "{\n", eof) == -1) {
147                 goto fail;
148         }
149         length = read_linehead(f);
150         if (length == -1) {
151                 goto fail;
152         }
153         if (read_data(f, &key, length) == -1) {
154                 goto fail;
155         }
156         if (swallow(f, "\"\n", NULL) == -1) {
157                 goto fail;
158         }
159         length = read_linehead(f);
160         if (length == -1) {
161                 goto fail;
162         }
163         if (read_data(f, &data, length) == -1) {
164                 goto fail;
165         }
166         if ((swallow(f, "\"\n", NULL) == -1)
167             || (swallow(f, "}\n", NULL) == -1)) {
168                 goto fail;
169         }
170         e = ntdb_store(ntdb, key, data, NTDB_INSERT);
171         if (e != NTDB_SUCCESS) {
172                 fprintf(stderr, "NTDB error: %s\n", ntdb_errorstr(e));
173                 goto fail;
174         }
175
176         ret = true;
177 fail:
178         free(key.dptr);
179         free(data.dptr);
180         return ret;
181 }
182
183 static int restore_ntdb(const char *fname, unsigned int hsize)
184 {
185         struct ntdb_context *ntdb;
186         union ntdb_attribute hashsize;
187
188         hashsize.base.attr = NTDB_ATTRIBUTE_HASHSIZE;
189         hashsize.base.next = NULL;
190         hashsize.hashsize.size = hsize;
191
192         ntdb = ntdb_open(fname, 0, O_RDWR|O_CREAT|O_EXCL, 0666,
193                          hsize ? &hashsize : NULL);
194         if (!ntdb) {
195                 perror("ntdb_open");
196                 fprintf(stderr, "Failed to open %s\n", fname);
197                 return 1;
198         }
199
200         while (1) {
201                 int eof = 0;
202                 if (!read_rec(stdin, ntdb, &eof)) {
203                         if (eof) {
204                                 break;
205                         }
206                         return 1;
207                 }
208         }
209         if (ntdb_close(ntdb)) {
210                 fprintf(stderr, "Error closing ntdb\n");
211                 return 1;
212         }
213         fprintf(stderr, "EOF\n");
214         return 0;
215 }
216
217 int main(int argc, char *argv[])
218 {
219         unsigned int hsize = 0;
220         const char *execname = argv[0];
221
222         if (argv[1] && strcmp(argv[1], "-h") == 0) {
223                 if (argv[2]) {
224                         hsize = atoi(argv[2]);
225                 }
226                 if (hsize == 0) {
227                         fprintf(stderr, "-h requires a integer value"
228                                 " (eg. 128 or 131072)\n");
229                         exit(1);
230                 }
231                 argv += 2;
232                 argc -= 2;
233         }
234         if (argc != 2) {
235                 printf("Usage: %s [-h <hashsize>] dbname < tdbdump_output\n",
236                        execname);
237                 exit(1);
238         }
239
240
241         return restore_ntdb(argv[1], hsize);
242 }