lib/tdb: Sync tdb from samba git tree
[vlendec/samba-autobuild/.git] / ctdb / 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 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 <assert.h>
21 #include "replace.h"
22 #include "system/locale.h"
23 #include "system/time.h"
24 #include "system/filesys.h"
25 #include "system/wait.h"
26 #include "tdb.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, 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 int read_rec(FILE *f, TDB_CONTEXT *tdb, int *eof)
141 {
142         int length;
143         TDB_DATA key, data;
144         int ret = -1;
145
146         key.dptr = NULL;
147         data.dptr = NULL;
148
149         if (swallow(f, "{\n", eof) == -1) {
150                 goto fail;
151         }
152         length = read_linehead(f);
153         if (length == -1) {
154                 goto fail;
155         }
156         if (read_data(f, &key, length) == -1) {
157                 goto fail;
158         }
159         if (swallow(f, "\"\n", NULL) == -1) {
160                 goto fail;
161         }
162         length = read_linehead(f);
163         if (length == -1) {
164                 goto fail;
165         }
166         if (read_data(f, &data, length) == -1) {
167                 goto fail;
168         }
169         if ((swallow(f, "\"\n", NULL) == -1)
170             || (swallow(f, "}\n", NULL) == -1)) {
171                 goto fail;
172         }
173         if (tdb_store(tdb, key, data, TDB_INSERT) != 0) {
174                 fprintf(stderr, "TDB error: %s\n", tdb_errorstr(tdb));
175                 goto fail;
176         }
177
178         ret = 0;
179 fail:
180         free(key.dptr);
181         free(data.dptr);
182         return ret;
183 }
184
185 static int restore_tdb(const char *fname)
186 {
187         TDB_CONTEXT *tdb;
188
189         tdb = tdb_open(fname, 0, 0, O_RDWR|O_CREAT|O_EXCL, 0666);
190         if (!tdb) {
191                 perror("tdb_open");
192                 fprintf(stderr, "Failed to open %s\n", fname);
193                 return 1;
194         }
195
196         while (1) {
197                 int eof = 0;
198                 if (read_rec(stdin, tdb, &eof) == -1) {
199                         if (eof) {
200                                 break;
201                         }
202                         return 1;
203                 }
204         }
205         if (tdb_close(tdb)) {
206                 fprintf(stderr, "Error closing tdb\n");
207                 return 1;
208         }
209         return 0;
210 }
211
212 int main(int argc, char *argv[])
213 {
214         char *fname;
215
216         if (argc < 2) {
217                 printf("Usage: %s dbname < tdbdump_output\n", argv[0]);
218                 exit(1);
219         }
220
221         fname = argv[1];
222
223         return restore_tdb(fname);
224 }