Whamcloud - gitweb
LU-10638 build: add support for Scientific
[tools/e2fsprogs.git] / e2scan / db.c
1 /*
2  * db.c
3  *
4  * Copyright (c) 2007, 2010 Oracle and/or its affiliates. All rights reserved.
5  * Use is subject to license terms.
6  *
7  * Author: Vladimir Saviliev <vladimir.saviliev@sun.com>
8  *         Andreas Dilger <adilger@sun.com>
9  *
10  * %Begin-Header%
11  * This file may be redistributed under the terms of the
12  * GNU General Public License version 2.
13  * %End-Header%
14  */
15 #define _GNU_SOURCE
16 #define _FILE_OFFSET_BITS 64
17
18 #include "config.h"
19 #include <stdio.h>
20 #include <time.h>
21 #include <unistd.h>
22 #include <ext2fs/ext2fs.h>
23 #include <sys/stat.h>
24
25 #if defined(HAVE_SQLITE3) && defined(HAVE_SQLITE3_H)
26
27 #include <sqlite3.h>
28
29 /* e2scan.c */
30 extern ext2_filsys fs;
31 extern struct {
32         int mode;
33         int nr;
34         union {
35                 struct {
36                         int fd;
37                         int nr_commands;
38                 } db;
39                 struct {
40                         /* number of files newer than specified time */
41                         ext2_ino_t nr_files;
42                         /* number of files reported */
43                         ext2_ino_t nr_reported;
44                         time_t mtimestamp;
45                         time_t ctimestamp;
46                 } fl;
47         };
48 } scan_data;
49
50 int block_iterate_cb(ext2_filsys fs, blk_t  *block_nr,
51                      e2_blkcnt_t blockcnt,
52                      blk_t ref_block EXT2FS_ATTR((unused)),
53                      int ref_offset EXT2FS_ATTR((unused)),
54                      void *priv_data);
55
56
57 static long count = 10000;
58
59 static void exec_one_sql_noreturn(sqlite3 *db, char *sqls)
60 {
61         char *errmsg = NULL;
62
63         if (sqlite3_exec(db, sqls, NULL, NULL, &errmsg) != SQLITE_OK) {
64                 fprintf(stderr, "SQL error: %s;\nrequest: %s", errmsg, sqls);
65                 sqlite3_free(errmsg);
66                 exit(1);
67         }
68 }
69
70 static void create_sql_table(sqlite3 *db, const char *table_name,
71                              const char *columns)
72 {
73         char *sqls;
74
75         if (asprintf(&sqls, "create table %s (%s)", table_name, columns) < 0) {
76                 perror("asprintf failed");
77                 exit(1);
78         }
79
80         exec_one_sql_noreturn(db, sqls);
81         free(sqls);
82 }
83
84 static void begin_one_transaction(sqlite3 *db)
85 {
86         exec_one_sql_noreturn(db, "BEGIN;");
87 }
88
89 static void commit_one_transaction(sqlite3 *db)
90 {
91         exec_one_sql_noreturn(db, "COMMIT;");
92 }
93
94 static void batch_one_transaction(sqlite3 *db)
95 {
96         static long num = 0;
97
98         num ++;
99         if (num % count == 0) {
100                 commit_one_transaction(db);
101                 begin_one_transaction(db);
102         }
103         /* else do nothing */
104 }
105
106 #define COLUMNS "ino, generation, parent, name, size, mtime, ctime, dtime"
107
108 static void create_full_db(const char *name, int fd)
109 {
110         sqlite3 *db;
111         int rd;
112         int nr;
113         char sqls[512];
114
115         if (sqlite3_open(name, &db) != SQLITE_OK) {
116                 fprintf(stderr, "failed to sqlite3_open: %s\n", name);
117                 sqlite3_close(db);
118                 exit(1);
119         }
120         create_sql_table(db, "dirs", COLUMNS);
121         create_sql_table(db, "files", COLUMNS);
122
123         begin_one_transaction(db);
124
125         nr = 0;
126         while (1) {
127                 rd = read(fd, sqls, 512);
128                 if (rd == -1) {
129                         perror("read failed\n");
130                         exit(1);
131                 }
132                 if (rd != 512)
133                         break;
134                 nr ++;
135                 exec_one_sql_noreturn(db, sqls);
136                 batch_one_transaction(db);
137         }
138         commit_one_transaction(db);
139         printf("database is created, %d records are inserted\n", nr);
140         sqlite3_close(db);
141 }
142
143 /* write sql command to pipe */
144 #define PIPECMDLEN 512
145 static void write_sql_command(int fd, const char *sqls)
146 {
147         char buf[PIPECMDLEN];
148
149         if (strlen(sqls) + 1 > PIPECMDLEN) {
150                 fprintf(stderr, "too long command");
151                 exit(1);
152         }
153         strcpy(buf, sqls);
154         if (write(fd, buf, PIPECMDLEN) != PIPECMDLEN) {
155                 perror("failed to write to pipe");
156                 exit(1);
157         }
158         scan_data.db.nr_commands ++;
159 }
160
161 pid_t fork_db_creation(const char *database)
162 {
163         int p[2];
164         struct stat st;
165         pid_t pid;
166
167         if (stat(database, &st) == 0) {
168                 fprintf(stderr, "%s exists. remove it first\n", database);
169                 exit(1);
170         }
171         if (pipe(p) == -1) {
172                 fprintf(stderr, "failed to pipe");
173                 exit(1);
174         }
175
176         pid = fork();
177         if (pid == (pid_t)-1) {
178                 fprintf(stderr, "failed to fork");
179                 exit(1);
180         }
181         if (pid == (pid_t)0) {
182                 /* child, read data written by parent and write to
183                  * database */
184                 close(p[1]);
185                 create_full_db(database, p[0]);
186                 close(p[0]);
187                 exit(0);
188         }
189
190         /* parent, read inodes and write them to pipe */
191         close(p[0]);
192         scan_data.db.fd = p[1];
193         return pid;
194 }
195
196 void database_iscan_action(ext2_ino_t ino, struct ext2_inode *inode,
197                            int fd, char *buf)
198 {
199         char *sqls;
200
201         if (LINUX_S_ISDIR(inode->i_mode)) {
202                 if (ino == EXT2_ROOT_INO) {
203                         sqls = sqlite3_mprintf("%s (%u,%u,%u,'%q',%u,%u,%u,%u)",
204                                                "insert into dirs values",
205                                                ino, inode->i_generation, ino, "/",
206                                                inode->i_size, inode->i_mtime,
207                                                inode->i_ctime, inode->i_dtime);
208                         write_sql_command(fd, sqls);
209                         sqlite3_free(sqls);
210                 }
211
212                 if (ext2fs_block_iterate2(fs, ino, 0, buf,
213                                           block_iterate_cb, &ino)) {
214                         fprintf(stderr, "ext2fs_block_iterate2 failed\n");
215                         exit(1);
216                 }
217         }
218 }
219
220 /*
221  * callback for ext2fs_dblist_dir_iterate to be called for each
222  * directory entry
223  */
224 int database_dblist_iterate_cb(ext2_ino_t dir, struct ext2_dir_entry *dirent,
225                                int namelen, int fd)
226 {
227         struct ext2_inode inode;
228         char *table;
229         char *sqls;
230         errcode_t retval;
231         char str[256];
232
233         if (!ext2fs_fast_test_inode_bitmap2(fs->inode_map, dirent->inode))
234                 /* entry of deleted file? can that ever happen */
235                 return 0;
236
237         retval = ext2fs_read_inode(fs, dirent->inode, &inode);
238         if (retval) {
239                 com_err("ext2fs_read_inode", retval, "while reading inode");
240                 exit(1);
241         }
242
243         if (LINUX_S_ISDIR(inode.i_mode))
244                 table = "dirs";
245         else
246                 table = "files";
247
248         sprintf(str, "%.*s", namelen, dirent->name);
249         sqls = sqlite3_mprintf("%s %s %s (%u,%u,%u,'%q',%u,%u,%u,%u)",
250                                "insert into", table, "values",
251                                dirent->inode, inode.i_generation, dir,
252                                str,
253                                inode.i_size, inode.i_mtime,
254                                inode.i_ctime, inode.i_dtime);
255         write_sql_command(fd, sqls);
256         sqlite3_free(sqls);
257
258         return 0;
259 }
260
261 #else
262
263 pid_t fork_db_creation(const char *database)
264 {
265         return 0;
266 }
267
268 void database_iscan_action(ext2_ino_t ino, struct ext2_inode *inode,
269                            int fd, char *buf)
270 {
271         return;
272 }
273
274 int database_dblist_iterate_cb(ext2_ino_t dir, struct ext2_dir_entry *dirent,
275                                int namelen, int fd)
276 {
277         return 0;
278 }
279
280 #endif