dad591d562511eff9a1b27af06d946ebfb4cbad9
[ddiss/samba.git] / lib / ntdb / tools / ntdbrestore.c
1 /*
2    ntdbrestore -- construct a ntdb 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 "config.h"
21 #include "ntdb.h"
22 #include <assert.h>
23 #ifdef HAVE_LIBREPLACE
24 #include <replace.h>
25 #include <system/filesys.h>
26 #else
27 #include <sys/types.h>
28 #include <sys/stat.h>
29 #include <fcntl.h>
30 #include <stdio.h>
31 #include <stdlib.h>
32 #endif
33
34 static int read_linehead(FILE *f)
35 {
36         int i, c;
37         int num_bytes;
38         char prefix[128];
39
40         while (1) {
41                 c = getc(f);
42                 if (c == EOF) {
43                         return -1;
44                 }
45                 if (c == '(') {
46                         break;
47                 }
48         }
49         for (i=0; i<sizeof(prefix); i++) {
50                 c = getc(f);
51                 if (c == EOF) {
52                         return -1;
53                 }
54                 prefix[i] = c;
55                 if (c == '"') {
56                         break;
57                 }
58         }
59         if (i == sizeof(prefix)) {
60                 return -1;
61         }
62         prefix[i] = '\0';
63
64         if (sscanf(prefix, "%d) = ", &num_bytes) != 1) {
65                 return -1;
66         }
67         return num_bytes;
68 }
69
70 static int read_hex(void) {
71         int c;
72         c = getchar();
73         if (c == EOF) {
74                 fprintf(stderr, "Unexpected EOF in data\n");
75                 return -1;
76         } else if (c == '"') {
77                 fprintf(stderr, "Unexpected \\\" sequence\n");
78                 return -1;
79         } else if ('0' <= c && c <= '9')  {
80                 return c - '0';
81         } else if ('A' <= c && c <= 'F')  {
82                 return c - 'A' + 10;
83         } else if ('a' <= c && c <= 'f')  {
84                 return c - 'a' + 10;
85         } else {
86                 fprintf(stderr, "Invalid hex: %c\n", c);
87                 return -1;
88         }
89 }
90
91 static int read_data(FILE *f, NTDB_DATA *d, size_t size) {
92         int c, low, high;
93         int i;
94
95         d->dptr = (unsigned char *)malloc(size);
96         if (d->dptr == NULL) {
97                 return -1;
98         }
99         d->dsize = size;
100
101         for (i=0; i<size; i++) {
102                 c = getc(f);
103                 if (c == EOF) {
104                         fprintf(stderr, "Unexpected EOF in data\n");
105                         return 1;
106                 } else if (c == '"') {
107                         return 0;
108                 } else if (c == '\\') {
109                         high = read_hex();
110                         if (high < 0) {
111                                 return -1;
112                         }
113                         high = high << 4;
114                         assert(high == (high & 0xf0));
115                         low = read_hex();
116                         if (low < 0) {
117                                 return -1;
118                         }
119                         assert(low == (low & 0x0f));
120                         d->dptr[i] = (low|high);
121                 } else {
122                         d->dptr[i] = c;
123                 }
124         }
125         return 0;
126 }
127
128 static int swallow(FILE *f, const char *s, int *eof)
129 {
130         char line[128];
131
132         if (fgets(line, sizeof(line), f) == NULL) {
133                 if (eof != NULL) {
134                         *eof = 1;
135                 }
136                 return -1;
137         }
138         if (strcmp(line, s) != 0) {
139                 return -1;
140         }
141         return 0;
142 }
143
144 static bool read_rec(FILE *f, struct ntdb_context *ntdb, int *eof)
145 {
146         int length;
147         NTDB_DATA key, data;
148         bool ret = false;
149         enum NTDB_ERROR e;
150
151         key.dptr = NULL;
152         data.dptr = NULL;
153
154         if (swallow(f, "{\n", eof) == -1) {
155                 goto fail;
156         }
157         length = read_linehead(f);
158         if (length == -1) {
159                 goto fail;
160         }
161         if (read_data(f, &key, length) == -1) {
162                 goto fail;
163         }
164         if (swallow(f, "\"\n", NULL) == -1) {
165                 goto fail;
166         }
167         length = read_linehead(f);
168         if (length == -1) {
169                 goto fail;
170         }
171         if (read_data(f, &data, length) == -1) {
172                 goto fail;
173         }
174         if ((swallow(f, "\"\n", NULL) == -1)
175             || (swallow(f, "}\n", NULL) == -1)) {
176                 goto fail;
177         }
178         e = ntdb_store(ntdb, key, data, NTDB_INSERT);
179         if (e != NTDB_SUCCESS) {
180                 fprintf(stderr, "NTDB error: %s\n", ntdb_errorstr(e));
181                 goto fail;
182         }
183
184         ret = true;
185 fail:
186         free(key.dptr);
187         free(data.dptr);
188         return ret;
189 }
190
191 static int restore_ntdb(const char *fname)
192 {
193         struct ntdb_context *ntdb;
194
195         ntdb = ntdb_open(fname, 0, O_RDWR|O_CREAT|O_EXCL, 0666, NULL);
196         if (!ntdb) {
197                 perror("ntdb_open");
198                 fprintf(stderr, "Failed to open %s\n", fname);
199                 return 1;
200         }
201
202         while (1) {
203                 int eof = 0;
204                 if (!read_rec(stdin, ntdb, &eof)) {
205                         if (eof) {
206                                 break;
207                         }
208                         return 1;
209                 }
210         }
211         if (ntdb_close(ntdb)) {
212                 fprintf(stderr, "Error closing ntdb\n");
213                 return 1;
214         }
215         fprintf(stderr, "EOF\n");
216         return 0;
217 }
218
219 int main(int argc, char *argv[])
220 {
221         char *fname;
222
223         if (argc < 2) {
224                 printf("Usage: %s dbname < tdbdump_output\n", argv[0]);
225                 exit(1);
226         }
227
228         fname = argv[1];
229
230         return restore_ntdb(fname);
231 }