]>
git.wh0rd.org - dump.git/blob - common/sqlite_indexer.c
4008341ce515a57c340e1aca1e3d8e2d9ed42cc3
16 #include <sys/param.h>
20 #include <linux/types.h>
21 #ifdef HAVE_EXT2FS_EXT2_FS_H
22 #include <ext2fs/ext2_fs.h>
24 #include <linux/ext2_fs.h>
26 #include <ext2fs/ext2fs.h>
28 #include <bsdcompat.h>
29 #include <linux/fs.h> /* for definition of BLKFLSBUF */
31 #include <sys/vnode.h>
33 #include <ufs/inode.h>
36 #include <ufs/ufs/dinode.h>
37 #include <ufs/ffs/fs.h>
40 #include <protocols/dumprestore.h>
44 #include "pathnames.h"
48 extern dump_ino_t volinfo
[]; // TP_NINOS
50 extern void msg
__P (( const char * fmt
,...));
53 extern ext2_filsys fs
;
55 extern struct fs
* sblock
;
56 #endif /* __linux__ */
60 #include <uuid/uuid.h>
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)); \
70 sqlite3_free(errMsg); \
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. */
78 sqlite3_stmt
* stmt
= NULL
;
81 * Ppopulate the 'backup' table.
84 sqlite_populate_backup_table ()
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
);
109 // spcl.c_dev, spcl.c_label, spcl.c_host,
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
));
116 sqlite3_free ( errMsg
);
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
);
126 while (( rc
= sqlite3_step ( stmt
)) == SQLITE_BUSY
) {
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
);
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
);
153 * Create database schema
156 sqlite_create_schema ()
163 // turn on foreign keys
164 snprintf ( buffer
, sizeof buffer
, "pragma foreign_keys = ON" );
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 " );
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
);
180 snprintf ( buffer
, sizeof buffer
,
181 "create unique index i1 on backup(backup_id) \n " );
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 );
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);
193 // snprintf(buffer, sizeof buffer,
194 // "create unique index i2 on entry(ino)\n");
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 " );
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 " );
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");
211 sqlite_populate_backup_table ();
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 " );
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
));
221 sqlite3_free ( errMsg
);
232 sqlite_open ( const char * filename
, int mode
)
235 if ( sqlite3_open ( filename
, & db
)) {
236 msg ( "Unable to open database: %s \n " , sqlite3_errmsg ( db
));
241 } else if ( mode
== 1 ) {
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
));
251 sqlite_create_schema ();
271 msg ( "database is already closed!" );
277 /* if stmt is not null we're creating database */
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
);
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
);
301 rc
= sqlite3_close ( db
);
302 if ( rc
!= SQLITE_OK
) {
303 msg ( "(%s:%d) SQL error: %s \n " , __FILE__
, __LINE__
, sqlite3_errmsg ( db
));
305 sqlite3_free ( errMsg
);
315 * Add directory entry.
318 sqlite_addDirEntry ( struct direct
* dp
, dump_ino_t parent_ino
)
329 // don't include backlink.
330 if (! strcmp ( dp
-> d_name
, ".." )) {
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
);
339 while (( rc
= sqlite3_step ( stmt
)) == SQLITE_BUSY
) {
343 if ( rc
!= SQLITE_DONE
) {
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
);
353 rc
= sqlite3_reset ( stmt
);
354 if ( rc
!= SQLITE_OK
) {
355 msg ( "(%s:%d) SQL error: %s \n " , __FILE__
, __LINE__
, sqlite3_errmsg ( db
));
357 sqlite3_free ( errMsg
);
363 rc
= sqlite3_clear_bindings ( stmt
);
364 if ( rc
!= SQLITE_OK
) {
365 msg ( "(%s:%d) SQL error: %s \n " , __FILE__
, __LINE__
, sqlite3_errmsg ( db
));
367 sqlite3_free ( errMsg
);
380 sqlite_addInode ( struct dinode
* dp
, dump_ino_t ino
, int metadata_only
)
399 strftime ( ats
, sizeof ats
, "%FT%T" , gmtime (& t
));
401 strftime ( mts
, sizeof ats
, "%FT%T" , gmtime (& t
));
403 strftime ( cts
, sizeof ats
, "%FT%T" , gmtime (& t
));
405 // xattr: dp->di_extraisize != 0
406 // acl: dp->di_file_acl (inode?)
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
);
440 sqlite_writerec ( const void * dp
, int isspcl
)
467 sqlite_openQfaState ( QFA_State
* state
)
476 sqlite_updateQfaState ( QFA_State
* state
)
485 sqlite_updateQfa ( QFA_State
* state
)
494 Indexer indexer_sqlite
=
506 & sqlite_openQfaState
,
508 & sqlite_updateQfaState