@@ -62,7 +62,10 @@ OF SUCH DAMAGE.
6262
6363
6464
65+ #include <errno.h>
66+ #include <fcntl.h>
6567#include <string.h>
68+ #include <unistd.h>
6669
6770#include "external.h"
6871#include "utils.h"
@@ -108,11 +111,11 @@ int create_external_tables(const char *name, sqlite3 *db, void *args) {
108111}
109112
110113/* SELECT <cols> FROM <table> [WHERE (type == '<type>') AND [extra]]; */
111- size_t external_create_query (char * sql , const size_t sql_size ,
112- const char * cols , const size_t cols_len ,
113- const char * table , const size_t table_len ,
114- const refstr_t * type ,
115- const refstr_t * extra ) {
114+ static size_t external_create_query (char * sql , const size_t sql_size ,
115+ const char * cols , const size_t cols_len ,
116+ const char * table , const size_t table_len ,
117+ const refstr_t * type ,
118+ const refstr_t * extra ) {
116119 size_t len = SNFORMAT_S (sql , sql_size , 4 ,
117120 "SELECT " , (size_t ) 7 ,
118121 cols , cols_len ,
@@ -166,6 +169,90 @@ int external_insert(sqlite3 *db, const char *type, const long long int pinode, c
166169 return 0 ;
167170}
168171
172+ /* returns 1 for good/not checked, 0 for error */
173+ static int check_is_db (const int check_extdb_valid , const char * path ) {
174+ int rc = !check_extdb_valid ;
175+
176+ if (check_extdb_valid ) {
177+ /* open the path to make sure it eventually resolves to a file */
178+ sqlite3 * extdb = opendb (path , SQLITE_OPEN_READONLY , 0 , 0 , NULL , NULL );
179+ if (extdb ) {
180+ /* make sure this file is a sqlite3 db */
181+ /* can probably skip this check */
182+ char * err = NULL ;
183+ if (sqlite3_exec (extdb , "SELECT '' FROM sqlite_master;" , NULL , NULL , & err ) == SQLITE_OK ) {
184+ rc = 1 ;
185+ }
186+ else {
187+ fprintf (stderr , "Warning: %s is not a db: %s\n" ,
188+ path , err );
189+ sqlite3_free (err );
190+ }
191+
192+ closedb (extdb );
193+ }
194+ }
195+
196+ return rc ;
197+ }
198+
199+ size_t external_read_file (struct input * in ,
200+ struct work * child ,
201+ external_process_db_f func ,
202+ void * args ) {
203+ int extdb_list = open (child -> name , O_RDONLY );
204+ if (extdb_list < 0 ) {
205+ const int err = errno ;
206+ fprintf (stderr , "Error: Could not open user external database list in %s: %s (%d)\n" ,
207+ child -> name , strerror (err ), err );
208+ return 0 ;
209+ }
210+
211+ size_t rc = 0 ;
212+
213+ char * line = NULL ;
214+ size_t len = 0 ;
215+ off_t offset = 0 ;
216+ while (getline_fd (& line , & len , extdb_list , & offset , 512 ) > 0 ) {
217+ char extdb_path_stack [MAXPATH ];
218+ char * extdb_path = line ;
219+
220+ /* resolve relative paths */
221+ if (line [0 ] != '/' ) {
222+ char path [MAXPATH ];
223+ SNFORMAT_S (path , sizeof (path ), 2 ,
224+ child -> name , child -> name_len - child -> basename_len ,
225+ /* basename does not include slash, so don't need to add another one */
226+ line , len );
227+
228+ if (!realpath (path , extdb_path_stack )) {
229+ const int err = errno ;
230+ fprintf (stderr , "Error: Could not resolve external database path %s: %s (%d)\n" ,
231+ path , strerror (err ), err );
232+ free (line );
233+ line = NULL ;
234+ continue ;
235+ }
236+
237+ extdb_path = extdb_path_stack ;
238+ }
239+
240+ if (check_is_db (in -> check_extdb_valid , extdb_path ) == 1 ){
241+ rc += !func (in , args , child -> pinode , extdb_path );
242+ }
243+
244+ free (line );
245+ line = NULL ;
246+ }
247+
248+ free (line );
249+ line = NULL ;
250+
251+ close (extdb_list );
252+
253+ return rc ;
254+ }
255+
169256int external_concatenate (sqlite3 * db ,
170257 const refstr_t * type ,
171258 const refstr_t * extra ,
0 commit comments