]> git.wh0rd.org - dump.git/blame - common/sqlite_indexer.c
Regenerate configure.
[dump.git] / common / sqlite_indexer.c
CommitLineData
70deb804
SP
1#include <config.h>
2#include <compatlfs.h>
3#include <ctype.h>
4#include <compaterr.h>
5#include <fcntl.h>
6#include <fstab.h>
7#include <signal.h>
8#include <stdio.h>
9#include <stdlib.h>
10#include <string.h>
11#include <unistd.h>
12#include <errno.h>
13#include <mntent.h>
14#include <stdarg.h>
15
16#include <sys/param.h>
17#include <sys/time.h>
18#include <time.h>
19#ifdef __linux__
20#include <linux/types.h>
21#ifdef HAVE_EXT2FS_EXT2_FS_H
22#include <ext2fs/ext2_fs.h>
23#else
24#include <linux/ext2_fs.h>
25#endif
26#include <ext2fs/ext2fs.h>
27#include <sys/stat.h>
28#include <bsdcompat.h>
29#include <linux/fs.h> /* for definition of BLKFLSBUF */
30#elif defined sunos
31#include <sys/vnode.h>
32
33#include <ufs/inode.h>
34#include <ufs/fs.h>
35#else
36#include <ufs/ufs/dinode.h>
37#include <ufs/ffs/fs.h>
38#endif
39
40#include <protocols/dumprestore.h>
41
42//#include "dump.h"
43#include "indexer.h"
44#include "pathnames.h"
45#include "bylabel.h"
46
47extern int tapeno;
48extern dump_ino_t volinfo[]; // TP_NINOS
49
50extern void msg __P((const char *fmt,...));
51
52#ifdef __linux__
53extern ext2_filsys fs;
54#else /* __linux__ */
55extern struct fs *sblock;
56#endif /* __linux__ */
57
58//#ifdef HAVE_SQLITE3
59#include <sqlite3.h>
60#include <uuid/uuid.h>
61
62static sqlite3 *db;
63
64// convenience macro that handles a basic sql statement.
65#define EXEC(db, buffer) \
66 rc = sqlite3_exec(db, buffer, NULL, 0, &errMsg); \
67 if (rc != SQLITE_OK) { \
68 msg("(%s:%d) SQL error: %s\n", __FILE__, __LINE__, sqlite3_errmsg(db)); \
69 msg(buffer); \
70 sqlite3_free(errMsg); \
71 sqlite3_close(db); \
72 db = NULL; \
73 return -1; \
74 }
75
76/* prepared statement that allows us to use placeholder values. */
77/* it also acts as sentinel to indicate if this is read or write mode. */
78sqlite3_stmt *stmt = NULL;
79
80/*
81 * Ppopulate the 'backup' table.
82 */
83static int
84sqlite_populate_backup_table()
85{
86 int rc;
87 char *errMsg = NULL;
88 char buffer[2000];
89 char vol_uuid[40];
90 char ts[40];
91 char nts[40];
92 char fs_uuid[40];
93 time_t now;
94 const char *tail;
95 uuid_t uuid;
96
97 time(&now);
98
99 // populate 'backup table'. There will only be one entry.
100 uuid_generate_time(uuid);
101 uuid_unparse_lower(uuid, vol_uuid);
102 uuid_unparse_lower(fs->super->s_uuid, fs_uuid);
103 strftime(ts, sizeof ts, "%FT%T", gmtime((const time_t *) &spcl.c_date));
104 strftime(nts, sizeof nts, "%FT%T", gmtime((const time_t *) &now));
105 snprintf(buffer, sizeof buffer,
106 "insert into backup(backup_id, vol_uuid, dt, start_dt, fs_uuid, dev, label, host, level) values (1, '%s', '%s', '%s', '%s', ?, ?, ?, %d)",
107 vol_uuid, ts, nts, fs_uuid, spcl.c_level);
108
109// spcl.c_dev, spcl.c_label, spcl.c_host,
110
111 // prepare statement.
112 rc = sqlite3_prepare_v2(db, buffer, strlen(buffer), &stmt, &tail);
113 if (rc != SQLITE_OK) {
114 msg("(%s:%d) SQL error: %s\n", __FILE__, __LINE__, sqlite3_errmsg(db));
115 msg(buffer);
116 sqlite3_free(errMsg);
117 sqlite3_close(db);
118 db = NULL;
119 return -1;
120 }
121
122 sqlite3_bind_text(stmt, 1, spcl.c_dev, strlen(spcl.c_dev), SQLITE_TRANSIENT);
123 sqlite3_bind_text(stmt, 2, spcl.c_label, strlen(spcl.c_label), SQLITE_TRANSIENT);
124 sqlite3_bind_text(stmt, 3, spcl.c_host, strlen(spcl.c_host), SQLITE_TRANSIENT);
125
126 while ((rc = sqlite3_step(stmt)) == SQLITE_BUSY) {
127 continue;
128 }
129
130 if (rc != SQLITE_DONE) {
131 msg("(%s:%d) SQL error: %s\n", __FILE__, __LINE__, sqlite3_errmsg(db));
132 msg("(%s:%d) %s\n", __FILE__, __LINE__, sqlite3_sql(stmt));
133 sqlite3_free(errMsg);
134 sqlite3_close(db);
135 db = NULL;
136 return -1;
137 }
138
139 rc = sqlite3_finalize(stmt);
140 if (rc != SQLITE_OK) {
141 msg("(%s:%d) SQL error: %s\n", __FILE__, __LINE__, sqlite3_errmsg(db));
142 msg("(%s:%d) %s\n", __FILE__, __LINE__, sqlite3_sql(stmt));
143 sqlite3_free(errMsg);
144 sqlite3_close(db);
145 db = NULL;
146 return -1;
147 }
148
149 return 0;
150}
151
152/*
153 * Create database schema
154 */
155static int
156sqlite_create_schema()
157{
158 int rc;
159 char *errMsg = NULL;
160 char buffer[2000];
161 const char *tail;
162
163 // turn on foreign keys
164 snprintf(buffer, sizeof buffer, "pragma foreign_keys = ON");
165
166 EXEC(db, buffer);
167
168 // turn off synchronous access. we have bigger problems
169 // if we lose power in the middle of a backup.
170 snprintf(buffer, sizeof buffer, "pragma synchronous = OFF\n");
171
172 EXEC(db, buffer);
173
174 // create 'backup' table.
175 snprintf(buffer, sizeof buffer,
176 "create table backup(backup_id int primary key not null, vol_uuid char[36] not null, dt timestamp not null, start_dt timestamp not null, end_dt timestamp, fs_uuid char[36] not null, dev varchar[%1$d] not null, label varchar[%1$d] not null, host varchar[%1$d] not null, level int not null, blocks int, volumes int)\n", EXT2_NAME_LEN);
177
178 EXEC(db, buffer);
179
180 snprintf(buffer, sizeof buffer,
181 "create unique index i1 on backup(backup_id)\n");
182 EXEC(db, buffer);
183
184 // create 'entry' table. This contains information about
185 // each directory entry
186 snprintf(buffer, sizeof buffer,
187 "create table entry(backup_id int not null, ino int not null, parent_ino int not null, type int not null, depth int, name varchar[%d] not null, path varchar[%d], foreign key(backup_id) references backup(backup_id))\n", EXT2_NAME_LEN, 1024);
188
189 // "create table entry(backup_id int not null, ino int not null, parent_ino int not null, type int not null, depth int, name varchar[%d] not null, path varchar[%d], foreign key(backup_id) references backup(backup_id), foreign key(parent_ino) references entry(ino))\n", EXT2_NAME_LEN, 1024);
190
191 EXEC(db, buffer);
192
193 // snprintf(buffer, sizeof buffer,
194 // "create unique index i2 on entry(ino)\n");
195
196 // EXEC(db, buffer);
197
198 snprintf(buffer, sizeof buffer,
199 "create trigger t1 after insert on entry begin update entry set path = coalesce((select '.' where name = '.'), (select A.path || '/' || new.name from entry A where A.ino = new.parent_ino)) where rowid = new.rowid; end;\n");
200
201 EXEC(db, buffer);
202
203 // create 'inode' table. This contains information about each inode.
204 snprintf(buffer, sizeof buffer,
205 "create table inode(backup_id int not null, ino int not null, is_deleted char[1] not null default 'N', mode int not null, nlink int not null, uid int not null, gid int not null, rdev int not null, size int not null, atime timestamp not null, mtime timestamp not null, ctime timestamp not null, has_xattr char[1] not null default 'N', has_acl char[1] not null default 'N', volume int not null, recno int not null, foreign key(backup_id) references backup(backup_id))\n");
206
207 // "create table inode(backup_id int not null, ino int not null, is_deleted char[1] not null default 'N', mode int not null, nlink int not null, uid int not null, gid int not null, rdev int not null, size int not null, atime timestamp not null, mtime timestamp not null, ctime timestamp not null, has_xattr char[1] not null default 'N', has_acl char[1] not null default 'N', volume int not null, recno int not null, foreign key(backup_id) references backup(backup_id), foreign key(ino) references entry(ino))\n");
208
209 EXEC(db, buffer);
210
211 sqlite_populate_backup_table();
212
213 // prepare statement for entry inserts.
214 snprintf(buffer, sizeof buffer,
215 "insert into entry(backup_id, ino, parent_ino, type, name) values(1, ?, ?, ?, ?)\n");
216
217 rc = sqlite3_prepare_v2(db, buffer, strlen(buffer), &stmt, &tail);
218 if (rc != SQLITE_OK) {
219 msg("(%s:%d) SQL error: %s\n", __FILE__, __LINE__, sqlite3_errmsg(db));
220 msg(buffer);
221 sqlite3_free(errMsg);
222 sqlite3_close(db);
223 db = NULL;
224 return;
225 }
226}
227
228/*
229 * Open database.
230 */
231static int
232sqlite_open(const char *filename, int mode)
233{
234 if (mode == 0) {
235 if (sqlite3_open(filename, &db)) {
236 msg("Unable to open database: %s\n", sqlite3_errmsg(db));
237 db = NULL;
238 return -1;
239 }
240 stmt = NULL;
241 } else if (mode == 1) {
242 unlink(filename);
243
244 /* sqlite will always create DB if it doesn't already exist. */
245 if (sqlite3_open(filename, &db)) {
246 msg("Unable to open database: %s\n", sqlite3_errmsg(db));
247 db = NULL;
248 return -1;
249 }
250
251 sqlite_create_schema();
252 }
253
254 return 0;
255}
256
257/*
258 * Close database.
259 */
260static int
261sqlite_close()
262{
263 int rc;
264 char *errMsg = NULL;
265 char buffer[2000];
266 char uuid[40];
267 char ts[40];
268 time_t now;
269
270 if (db == NULL) {
271 msg("database is already closed!");
272 return -1;
273 }
274
275 time(&now);
276
277 /* if stmt is not null we're creating database */
278 if (stmt != NULL) {
279 // close prepared statement.
280 rc = sqlite3_finalize(stmt);
281 if (rc != SQLITE_OK) {
282 msg("(%s:%d) SQL error: %s\n", __FILE__, __LINE__, sqlite3_errmsg(db));
283 msg("(%s:%d) %s\n", __FILE__, __LINE__, sqlite3_sql(stmt));
284 sqlite3_free(errMsg);
285 sqlite3_close(db);
286 db = NULL;
287 return -1;
288 }
289
290 // update 'tape header' with number of volumes and blocks.
291 uuid_unparse_lower(fs->super->s_uuid, uuid);
292 strftime(ts, sizeof ts, "%FT%T", gmtime((const time_t *) &now));
293 snprintf(buffer, sizeof buffer,
294 "update backup set end_dt = '%s', blocks=%d, volumes=%d where fs_uuid='%s'",
295 ts, spcl.c_tapea, spcl.c_volume, uuid);
296
297 EXEC(db, buffer);
298 }
299
300 // close database.
301 rc = sqlite3_close(db);
302 if (rc != SQLITE_OK) {
303 msg("(%s:%d) SQL error: %s\n", __FILE__, __LINE__, sqlite3_errmsg(db));
304 msg(buffer);
305 sqlite3_free(errMsg);
306 db = NULL;
307 return -1;
308 }
309 db = NULL;
310
311 return 0;
312}
313
314/*
315 * Add directory entry.
316 */
317static int
318sqlite_addDirEntry(struct direct *dp, dump_ino_t parent_ino)
319{
320 int rc;
321 char *errMsg = NULL;
322 char buffer[2000];
323 const char *tail;
324
325 if (db == NULL) {
326 return -1;
327 }
328
329 // don't include backlink.
330 if (!strcmp(dp->d_name, "..")) {
331 return -1;
332 }
333
334 sqlite3_bind_int(stmt, 1, dp->d_ino);
335 sqlite3_bind_int(stmt, 2, parent_ino);
336 sqlite3_bind_int(stmt, 3, dp->d_type);
337 sqlite3_bind_text(stmt, 4, dp->d_name, strlen(dp->d_name), SQLITE_TRANSIENT);
338
339 while ((rc = sqlite3_step(stmt)) == SQLITE_BUSY) {
340 continue;
341 }
342
343 if (rc != SQLITE_DONE) {
344 int i;
345 msg("(%s:%d) SQL error: %s\n", __FILE__, __LINE__, sqlite3_errmsg(db));
346 msg("(%s:%d) %s\n", __FILE__, __LINE__, sqlite3_sql(stmt));
347 sqlite3_free(errMsg);
348 sqlite3_close(db);
349 db = NULL;
350 return -1;
351 }
352
353 rc = sqlite3_reset(stmt);
354 if (rc != SQLITE_OK) {
355 msg("(%s:%d) SQL error: %s\n", __FILE__, __LINE__, sqlite3_errmsg(db));
356 msg(buffer);
357 sqlite3_free(errMsg);
358 sqlite3_close(db);
359 db = NULL;
360 return -1;
361 }
362
363 rc = sqlite3_clear_bindings(stmt);
364 if (rc != SQLITE_OK) {
365 msg("(%s:%d) SQL error: %s\n", __FILE__, __LINE__, sqlite3_errmsg(db));
366 msg(buffer);
367 sqlite3_free(errMsg);
368 sqlite3_close(db);
369 db = NULL;
370 return -1;
371 }
372
373 return 0;
374}
375
376/*
377 * Add inode entry.
378 */
379static int
380sqlite_addInode(struct dinode *dp, dump_ino_t ino, int metadata_only)
381{
382 int rc;
383 char *errMsg = NULL;
384 char buffer[2000];
385 char ats[40];
386 char mts[40];
387 char cts[40];
388 time_t t;
389
390 if (db == NULL) {
391 return -1;
392 }
393
394 ats[0] = 0;
395 mts[0] = 0;
396 cts[0] = 0;
397
398 t = dp->di_atime;
399 strftime(ats, sizeof ats, "%FT%T", gmtime(&t));
400 t = dp->di_mtime;
401 strftime(mts, sizeof ats, "%FT%T", gmtime(&t));
402 t = dp->di_ctime;
403 strftime(cts, sizeof ats, "%FT%T", gmtime(&t));
404
405 // xattr: dp->di_extraisize != 0
406 // acl: dp->di_file_acl (inode?)
407 // se linux?...
408
409 snprintf(buffer, sizeof buffer,
410 "insert into inode(backup_id, ino, is_deleted, mode, nlink, uid, gid, rdev, size, atime, mtime, ctime, has_xattr, has_acl, volume, recno) values(1, %d, '%s', %d, %d, %d, %d, %d, %d, '%s', '%s', '%s', '%s', '%s', %d, %d)\n",
411 ino, "N", dp->di_mode, dp->di_nlink, dp->di_uid, dp->di_gid, dp->di_rdev, dp->di_size, ats, mts, cts, (dp->di_extraisize == 0) ? "N" : "Y", (dp->di_file_acl != 0) ? "Y" : "N", spcl.c_volume, spcl.c_tapea);
412
413 EXEC(db, buffer);
414
415 return 0;
416}
417
418/*
419 *
420 */
421static int
422foo()
423{
424 return 0;
425}
426
427/*
428 *
429 */
430static int
431sqlite_foo()
432{
433 return 0;
434}
435
436/*
437 *
438 */
439static int
440sqlite_writerec(const void *dp, int isspcl)
441{
442 return 0;
443}
444
445/*
446 *
447 */
448static int
449sqlite_openQfa()
450{
451 return 0;
452}
453
454/*
455 *
456 */
457static int
458sqlite_closeQfa()
459{
460 return 0;
461}
462
463/*
464 *
465 */
466static int
467sqlite_openQfaState(QFA_State *state)
468{
469 return 0;
470}
471
472/*
473 *
474 */
475static int
476sqlite_updateQfaState(QFA_State *state)
477{
478 return 0;
479}
480
481/*
482 *
483 */
484static int
485sqlite_updateQfa(QFA_State *state)
486{
487 return 0;
488}
489
490
491/*
492 *
493 */
494Indexer indexer_sqlite =
495{
496 NULL,
497 &sqlite_open,
498 &sqlite_close,
499 &sqlite_foo,
500 &sqlite_writerec,
501 &sqlite_addInode,
502 &sqlite_addDirEntry,
503
504 &sqlite_openQfa,
505 &sqlite_closeQfa,
506 &sqlite_openQfaState,
507 &sqlite_updateQfa,
508 &sqlite_updateQfaState
509};
510
511//#endif