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