485c440df1f9c871078ce889adab94cc98ccbb47
[kai/samba.git] / lib / tdb / tools / tdbrestore.c
1 /*
2    tdbrestore -- 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 2 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, write to the Free Software
18    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
19 */
20
21 #include <assert.h>
22 #include "replace.h"
23 #include "system/locale.h"
24 #include "system/time.h"
25 #include "system/filesys.h"
26 #include "system/wait.h"
27 #include "tdb.h"
28
29 #define debug_fprintf(file, fmt, ...) do {/*nothing*/} while (0)
30
31 static int read_linehead(FILE *f)
32 {
33         int i, c;
34         int num_bytes;
35         char prefix[128];
36
37         while (1) {
38                 c = getc(f);
39                 if (c == EOF) {
40                         return -1;
41                 }
42                 if (c == '\(') {
43                         break;
44                 }
45         }
46         for (i=0; i<sizeof(prefix); i++) {
47                 c = getc(f);
48                 if (c == EOF) {
49                         return -1;
50                 }
51                 prefix[i] = c;
52                 if (c == '"') {
53                         break;
54                 }
55         }
56         if (i == sizeof(prefix)) {
57                 return -1;
58         }
59         prefix[i] = '\0';
60
61         if (sscanf(prefix, "%d) = ", &num_bytes) != 1) {
62                 return -1;
63         }
64         return num_bytes;
65 }
66
67 static int read_hex(void) {
68         int c;
69         c = getchar();
70         if (c == EOF) {
71                 fprintf(stderr, "Unexpected EOF in data\n");
72                 return -1;
73         } else if (c == '"') {
74                 fprintf(stderr, "Unexpected \\\" sequence\n");
75                 return -1;
76         } else if ('0' <= c && c <= '9')  {
77                 return c - '0';
78         } else if ('A' <= c && c <= 'F')  {
79                 return c - 'A' + 10;
80         } else if ('a' <= c && c <= 'f')  {
81                 return c - 'a' + 10;
82         } else {
83                 fprintf(stderr, "Invalid hex: %c\n", c);
84                 return -1;
85         }
86 }
87
88 static int read_data(FILE *f, TDB_DATA *d, size_t size) {
89         int c, low, high;
90         int i;
91
92         d->dptr = (unsigned char *)malloc(size);
93         if (d->dptr == NULL) {
94                 return -1;
95         }
96         d->dsize = size;
97
98         for (i=0; i<size; i++) {
99                 c = getc(f);
100                 if (c == EOF) {
101                         fprintf(stderr, "Unexpected EOF in data\n");
102                         return 1;
103                 } else if (c == '"') {
104                         return 0;
105                 } else if (c == '\\') {
106                         high = read_hex();
107                         if (high < 0) {
108                                 return -1;
109                         }
110                         high = high << 4;
111                         assert(high == (high & 0xf0));
112                         low = read_hex();
113                         if (low < 0) {
114                                 return -1;
115                         }
116                         assert(low == (low & 0x0f));
117                         d->dptr[i] = (low|high);
118                 } else {
119                         d->dptr[i] = c;
120                 }
121         }
122         return 0;
123 }
124
125 static int swallow(FILE *f, const char *s, int *eof)
126 {
127         char line[128];
128
129         if (fgets(line, sizeof(line), f) == NULL) {
130                 if (eof != NULL) {
131                         *eof = 1;
132                 }
133                 return -1;
134         }
135         if (strcmp(line, s) != 0) {
136                 return -1;
137         }
138         return 0;
139 }
140
141 static int read_rec(FILE *f, TDB_CONTEXT *tdb, int *eof)
142 {
143         int length;
144         TDB_DATA key, data;
145         int ret = -1;
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         if (tdb_store(tdb, key, data, TDB_INSERT) == -1) {
175                 fprintf(stderr, "TDB error: %s\n", tdb_errorstr(tdb));
176                 goto fail;
177         }
178
179         ret = 0;
180 fail:
181         free(key.dptr);
182         free(data.dptr);
183         return ret;
184 }
185
186 static int restore_tdb(const char *fname)
187 {
188         TDB_CONTEXT *tdb;
189
190         tdb = tdb_open(fname, 0, 0, O_RDWR|O_CREAT|O_EXCL, 0666);
191         if (!tdb) {
192                 perror("tdb_open");
193                 fprintf(stderr, "Failed to open %s\n", fname);
194                 return 1;
195         }
196
197         while (1) {
198                 int eof = 0;
199                 if (read_rec(stdin, tdb, &eof) == -1) {
200                         if (eof) {
201                                 break;
202                         }
203                         return 1;
204                 }
205         }
206         if (tdb_close(tdb)) {
207                 fprintf(stderr, "Error closing tdb\n");
208                 return 1;
209         }
210         fprintf(stderr, "EOF\n");
211         return 0;
212 }
213
214 int main(int argc, char *argv[])
215 {
216         char *fname;
217
218         if (argc < 2) {
219                 printf("Usage: %s dbname < tdbdump_output\n", argv[0]);
220                 exit(1);
221         }
222
223         fname = argv[1];
224
225         return restore_tdb(fname);
226 }