1 /***************************************************************************
2  begin       : Wed Mar 31 2004
3  copyright   : (C) 2004-2010 by Martin Preuss
4  email       : martin@libchipcard.de
5 
6  ***************************************************************************
7  *                                                                         *
8  *   This library is free software; you can redistribute it and/or         *
9  *   modify it under the terms of the GNU Lesser General Public            *
10  *   License as published by the Free Software Foundation; either          *
11  *   version 2.1 of the License, or (at your option) any later version.    *
12  *                                                                         *
13  *   This library is distributed in the hope that it will be useful,       *
14  *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
15  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU     *
16  *   Lesser General Public License for more details.                       *
17  *                                                                         *
18  *   You should have received a copy of the GNU Lesser General Public      *
19  *   License along with this library; if not, write to the Free Software   *
20  *   Foundation, Inc., 59 Temple Place, Suite 330, Boston,                 *
21  *   MA  02111-1307  USA                                                   *
22  *                                                                         *
23  ***************************************************************************/
24 
25 
26 #ifdef HAVE_CONFIG_H
27 # include <config.h>
28 #endif
29 
30 #define DISABLE_DEBUGLOG
31 
32 #include "dbio_p.h"
33 #include <gwenhywfar/gwenhywfar.h>
34 #include <gwenhywfar/misc.h>
35 #include <gwenhywfar/debug.h>
36 #include <gwenhywfar/path.h>
37 #include <gwenhywfar/text.h>
38 #include <gwenhywfar/directory.h>
39 #include <gwenhywfar/syncio.h>
40 #include <gwenhywfar/syncio_file.h>
41 #include <gwenhywfar/syncio_memory.h>
42 #include <gwenhywfar/fslock.h>
43 #include <gwenhywfar/pathmanager.h>
44 
45 
46 /* TODO: #include <gwenhywfar/plugin.h> */
47 
48 #include <stdlib.h>
49 #include <assert.h>
50 #include <string.h>
51 #include <errno.h>
52 #include <ctype.h>
53 
54 #include <sys/types.h>
55 #ifdef HAVE_SYS_STAT_H
56 # include <sys/stat.h>
57 #endif
58 #ifdef HAVE_FCNTL_H
59 # include <fcntl.h>
60 #endif
61 #ifdef HAVE_UNISTD_H
62 # include <unistd.h>
63 #endif
64 
65 
66 #ifdef OS_WIN32
67 # define DIRSEP "\\"
68 # include <windows.h>
69 #else
70 # define DIRSEP "/"
71 #endif
72 
73 
74 
GWEN_LIST_FUNCTIONS(GWEN_DBIO,GWEN_DBIO)75 GWEN_LIST_FUNCTIONS(GWEN_DBIO, GWEN_DBIO)
76 GWEN_INHERIT_FUNCTIONS(GWEN_DBIO)
77 
78 GWEN_INHERIT(GWEN_PLUGIN, GWEN_DBIO_PLUGIN)
79 
80 
81 int GWEN_DBIO_ModuleInit(void)
82 {
83   GWEN_PLUGIN_MANAGER *pm;
84   int err;
85   GWEN_STRINGLIST *sl;
86 
87   pm=GWEN_PluginManager_new("dbio", GWEN_PM_LIBNAME);
88   err=GWEN_PluginManager_Register(pm);
89   if (err) {
90     DBG_ERROR(GWEN_LOGDOMAIN, "Could not register DBIO plugin manager");
91     return err;
92   }
93 
94   /* create plugin paths */
95   sl=GWEN_PathManager_GetPaths(GWEN_PM_LIBNAME, GWEN_PM_PLUGINDIR);
96   if (sl) {
97     GWEN_STRINGLISTENTRY *se;
98     GWEN_BUFFER *pbuf;
99 
100     pbuf=GWEN_Buffer_new(0, 256, 0, 1);
101 
102     se=GWEN_StringList_FirstEntry(sl);
103     while (se) {
104       GWEN_Buffer_AppendString(pbuf, GWEN_StringListEntry_Data(se));
105       GWEN_Buffer_AppendString(pbuf, DIRSEP GWEN_DBIO_FOLDER);
106       DBG_INFO(GWEN_LOGDOMAIN, "Adding plugin path [%s]",
107                GWEN_Buffer_GetStart(pbuf));
108       GWEN_PluginManager_AddPath(pm, GWEN_PM_LIBNAME,
109                                  GWEN_Buffer_GetStart(pbuf));
110       GWEN_Buffer_Reset(pbuf);
111       se=GWEN_StringListEntry_Next(se);
112     }
113     GWEN_Buffer_free(pbuf);
114     GWEN_StringList_free(sl);
115   }
116 
117   return 0;
118 }
119 
120 
121 
GWEN_DBIO_ModuleFini(void)122 int GWEN_DBIO_ModuleFini(void)
123 {
124   GWEN_PLUGIN_MANAGER *pm;
125 
126   pm=GWEN_PluginManager_FindPluginManager("dbio");
127   if (pm) {
128     int rv;
129 
130     rv=GWEN_PluginManager_Unregister(pm);
131     if (rv) {
132       DBG_ERROR(GWEN_LOGDOMAIN,
133                 "Could not unregister DBIO plugin manager (%d)", rv);
134       return rv;
135     }
136     else
137       GWEN_PluginManager_free(pm);
138   }
139 
140   return 0;
141 }
142 
143 
144 
145 
146 
GWEN_DBIO_Plugin_new(GWEN_PLUGIN_MANAGER * pm,const char * name,const char * fileName)147 GWEN_PLUGIN *GWEN_DBIO_Plugin_new(GWEN_PLUGIN_MANAGER *pm,
148                                   const char *name,
149                                   const char *fileName)
150 {
151   GWEN_PLUGIN *pl;
152   GWEN_DBIO_PLUGIN *pldbio;
153 
154   pl=GWEN_Plugin_new(pm, name, fileName);
155   GWEN_NEW_OBJECT(GWEN_DBIO_PLUGIN, pldbio);
156   GWEN_INHERIT_SETDATA(GWEN_PLUGIN, GWEN_DBIO_PLUGIN, pl, pldbio,
157                        GWEN_DBIO_Plugin_FreeData);
158 
159   return pl;
160 }
161 
162 
163 
GWEN_DBIO_Plugin_FreeData(GWEN_UNUSED void * bp,void * p)164 void GWENHYWFAR_CB GWEN_DBIO_Plugin_FreeData(GWEN_UNUSED void *bp, void *p)
165 {
166   GWEN_DBIO_PLUGIN *pldbio;
167 
168   pldbio=(GWEN_DBIO_PLUGIN *)p;
169   GWEN_FREE_OBJECT(pldbio);
170 }
171 
172 
173 
GWEN_DBIO_Plugin_Factory(GWEN_PLUGIN * pl)174 GWEN_DBIO *GWEN_DBIO_Plugin_Factory(GWEN_PLUGIN *pl)
175 {
176   GWEN_DBIO_PLUGIN *pldbio;
177 
178   assert(pl);
179   pldbio=GWEN_INHERIT_GETDATA(GWEN_PLUGIN, GWEN_DBIO_PLUGIN, pl);
180   assert(pldbio);
181 
182   assert(pldbio->factoryFn);
183   return pldbio->factoryFn(pl);
184 }
185 
186 
187 
GWEN_DBIO_Plugin_SetFactoryFn(GWEN_PLUGIN * pl,GWEN_DBIO_PLUGIN_FACTORYFN f)188 void GWEN_DBIO_Plugin_SetFactoryFn(GWEN_PLUGIN *pl,
189                                    GWEN_DBIO_PLUGIN_FACTORYFN f)
190 {
191   GWEN_DBIO_PLUGIN *pldbio;
192 
193   assert(pl);
194   pldbio=GWEN_INHERIT_GETDATA(GWEN_PLUGIN, GWEN_DBIO_PLUGIN, pl);
195   assert(pldbio);
196 
197   pldbio->factoryFn=f;
198 }
199 
200 
201 
202 
203 
204 
205 
206 
GWEN_DBIO_new(const char * name,const char * descr)207 GWEN_DBIO *GWEN_DBIO_new(const char *name, const char *descr)
208 {
209   GWEN_DBIO *dbio;
210 
211   assert(name);
212   GWEN_NEW_OBJECT(GWEN_DBIO, dbio);
213   GWEN_LIST_INIT(GWEN_DBIO, dbio);
214   GWEN_INHERIT_INIT(GWEN_DBIO, dbio);
215   dbio->name=strdup(name);
216   if (descr)
217     dbio->descr=strdup(descr);
218 
219   dbio->usage=1;
220   return dbio;
221 }
222 
223 
224 
GWEN_DBIO_free(GWEN_DBIO * dbio)225 void GWEN_DBIO_free(GWEN_DBIO *dbio)
226 {
227   if (dbio) {
228     assert(dbio->usage);
229     if (--(dbio->usage)==0) {
230       GWEN_INHERIT_FINI(GWEN_DBIO, dbio);
231       GWEN_LIST_FINI(GWEN_DBIO, dbio);
232 
233       free(dbio->name);
234       free(dbio->descr);
235 
236       GWEN_FREE_OBJECT(dbio);
237     }
238   }
239 }
240 
241 
242 
GWEN_DBIO_Attach(GWEN_DBIO * dbio)243 void GWEN_DBIO_Attach(GWEN_DBIO *dbio)
244 {
245   assert(dbio);
246   dbio->usage++;
247 }
248 
249 
250 
GWEN_DBIO_Import(GWEN_DBIO * dbio,GWEN_SYNCIO * sio,GWEN_DB_NODE * db,GWEN_DB_NODE * params,uint32_t flags)251 int GWEN_DBIO_Import(GWEN_DBIO *dbio,
252                      GWEN_SYNCIO *sio,
253                      GWEN_DB_NODE *db,
254                      GWEN_DB_NODE *params,
255                      uint32_t flags)
256 {
257   assert(dbio);
258   assert(sio);
259   assert(db);
260 
261   if (GWEN_SyncIo_GetStatus(sio) != GWEN_SyncIo_Status_Connected) {
262     DBG_ERROR(GWEN_LOGDOMAIN, "GWEN_SYNCIO %s not connected; did you forget to call GWEN_SyncIo_Connect()?",
263               GWEN_SyncIo_GetTypeName(sio));
264     return -1;
265   }
266 
267   if (dbio->importFn)
268     return dbio->importFn(dbio, sio, db, params, flags);
269   else {
270     DBG_INFO(GWEN_LOGDOMAIN, "No import function set");
271     return -1;
272   }
273 }
274 
275 
276 
GWEN_DBIO_Export(GWEN_DBIO * dbio,GWEN_SYNCIO * sio,GWEN_DB_NODE * db,GWEN_DB_NODE * params,uint32_t flags)277 int GWEN_DBIO_Export(GWEN_DBIO *dbio,
278                      GWEN_SYNCIO *sio,
279                      GWEN_DB_NODE *db,
280                      GWEN_DB_NODE *params,
281                      uint32_t flags)
282 {
283   assert(dbio);
284   assert(sio);
285   assert(db);
286 
287   if (dbio->exportFn)
288     return dbio->exportFn(dbio, sio, db, params, flags);
289   else {
290     DBG_INFO(GWEN_LOGDOMAIN, "No export function set");
291     return -1;
292   }
293 }
294 
295 
296 
GWEN_DBIO_CheckFile(GWEN_DBIO * dbio,const char * fname)297 GWEN_DBIO_CHECKFILE_RESULT GWEN_DBIO_CheckFile(GWEN_DBIO *dbio,
298                                                const char *fname)
299 {
300   assert(dbio);
301   assert(fname);
302 
303   if (dbio->checkFileFn)
304     return dbio->checkFileFn(dbio, fname);
305   else {
306     DBG_INFO(GWEN_LOGDOMAIN, "No checkFile function set");
307     return GWEN_DBIO_CheckFileResultUnknown;
308   }
309 }
310 
311 
312 
GWEN_DBIO_GetName(const GWEN_DBIO * dbio)313 const char *GWEN_DBIO_GetName(const GWEN_DBIO *dbio)
314 {
315   assert(dbio);
316   return dbio->name;
317 }
318 
319 
320 
GWEN_DBIO_GetDescription(const GWEN_DBIO * dbio)321 const char *GWEN_DBIO_GetDescription(const GWEN_DBIO *dbio)
322 {
323   assert(dbio);
324   return dbio->descr;
325 }
326 
327 
328 
GWEN_DBIO_SetImportFn(GWEN_DBIO * dbio,GWEN_DBIO_IMPORTFN f)329 void GWEN_DBIO_SetImportFn(GWEN_DBIO *dbio, GWEN_DBIO_IMPORTFN f)
330 {
331   assert(dbio);
332   dbio->importFn=f;
333 }
334 
335 
336 
GWEN_DBIO_SetExportFn(GWEN_DBIO * dbio,GWEN_DBIO_EXPORTFN f)337 void GWEN_DBIO_SetExportFn(GWEN_DBIO *dbio, GWEN_DBIO_EXPORTFN f)
338 {
339   assert(dbio);
340   dbio->exportFn=f;
341 }
342 
343 
GWEN_DBIO_SetCheckFileFn(GWEN_DBIO * dbio,GWEN_DBIO_CHECKFILEFN f)344 void GWEN_DBIO_SetCheckFileFn(GWEN_DBIO *dbio, GWEN_DBIO_CHECKFILEFN f)
345 {
346   assert(dbio);
347   dbio->checkFileFn=f;
348 }
349 
350 
351 
GWEN_DBIO_GetPlugin(const char * modname)352 GWEN_DBIO *GWEN_DBIO_GetPlugin(const char *modname)
353 {
354   GWEN_PLUGIN_MANAGER *pm;
355   GWEN_PLUGIN *pl;
356   GWEN_DBIO *dbio;
357 
358   pm=GWEN_PluginManager_FindPluginManager("dbio");
359   if (!pm) {
360     DBG_ERROR(GWEN_LOGDOMAIN, "No plugin manager for \"dbio\" found");
361     return 0;
362   }
363 
364   pl=GWEN_PluginManager_GetPlugin(pm, modname);
365   if (!pl) {
366     DBG_INFO(GWEN_LOGDOMAIN, "DBIO-Plugin \"%s\" not found", modname);
367     return 0;
368   }
369 
370   dbio=GWEN_DBIO_Plugin_Factory(pl);
371   if (!dbio) {
372     DBG_INFO(GWEN_LOGDOMAIN,
373              "Plugin did not create a GWEN_DBIO");
374   }
375   return dbio;
376 }
377 
378 
379 
GWEN_DBIO_ExportToFile(GWEN_DBIO * dbio,const char * fname,GWEN_DB_NODE * db,GWEN_DB_NODE * params,uint32_t dbflags)380 int GWEN_DBIO_ExportToFile(GWEN_DBIO *dbio,
381                            const char *fname,
382                            GWEN_DB_NODE *db,
383                            GWEN_DB_NODE *params,
384                            uint32_t dbflags)
385 {
386   int rv;
387   GWEN_FSLOCK *lck=0;
388   GWEN_SYNCIO *sio;
389 
390   /* if locking requested */
391   if (dbflags & GWEN_DB_FLAGS_LOCKFILE) {
392     GWEN_FSLOCK_RESULT res;
393 
394     lck=GWEN_FSLock_new(fname, GWEN_FSLock_TypeFile);
395     assert(lck);
396     res=GWEN_FSLock_Lock(lck, GWEN_DB_DEFAULT_LOCK_TIMEOUT, 0);
397     if (res!=GWEN_FSLock_ResultOk) {
398       DBG_ERROR(GWEN_LOGDOMAIN,
399                 "Could not apply lock to file \"%s\" (%d)",
400                 fname, res);
401       GWEN_FSLock_free(lck);
402       return -1;
403     }
404   }
405 
406   /* open file */
407   sio=GWEN_SyncIo_File_new(fname, GWEN_SyncIo_File_CreationMode_CreateAlways);
408   if (dbflags & GWEN_DB_FLAGS_APPEND_FILE)
409     GWEN_SyncIo_AddFlags(sio, GWEN_SYNCIO_FILE_FLAGS_APPEND);
410   GWEN_SyncIo_AddFlags(sio,
411                        GWEN_SYNCIO_FILE_FLAGS_READ |
412                        GWEN_SYNCIO_FILE_FLAGS_WRITE |
413                        GWEN_SYNCIO_FILE_FLAGS_UREAD |
414                        GWEN_SYNCIO_FILE_FLAGS_UWRITE);
415   rv=GWEN_SyncIo_Connect(sio);
416   if (rv<0) {
417     DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
418     GWEN_SyncIo_free(sio);
419     if (lck) {
420       GWEN_FSLock_Unlock(lck);
421       GWEN_FSLock_free(lck);
422     }
423     return rv;
424   }
425 
426   rv=GWEN_DBIO_Export(dbio, sio, db, params, dbflags);
427   if (rv<0) {
428     DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
429     GWEN_SyncIo_Disconnect(sio);
430     GWEN_SyncIo_free(sio);
431     if (lck) {
432       GWEN_FSLock_Unlock(lck);
433       GWEN_FSLock_free(lck);
434     }
435     return rv;
436   }
437 
438   rv=GWEN_SyncIo_Disconnect(sio);
439   if (rv<0) {
440     DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
441     GWEN_SyncIo_free(sio);
442     if (lck) {
443       GWEN_FSLock_Unlock(lck);
444       GWEN_FSLock_free(lck);
445     }
446     return rv;
447   }
448   GWEN_SyncIo_free(sio);
449 
450   /* remove lock, if any */
451   if (lck) {
452     GWEN_FSLOCK_RESULT res;
453 
454     res=GWEN_FSLock_Unlock(lck);
455     if (res!=GWEN_FSLock_ResultOk) {
456       DBG_WARN(GWEN_LOGDOMAIN,
457                "Could not remove lock on file \"%s\" (%d)",
458                fname, res);
459     }
460     GWEN_FSLock_free(lck);
461   }
462 
463   return 0;
464 }
465 
466 
467 
GWEN_DBIO_ExportToBuffer(GWEN_DBIO * dbio,GWEN_BUFFER * buf,GWEN_DB_NODE * db,GWEN_DB_NODE * params,uint32_t flags)468 int GWEN_DBIO_ExportToBuffer(GWEN_DBIO *dbio,
469                              GWEN_BUFFER *buf,
470                              GWEN_DB_NODE *db,
471                              GWEN_DB_NODE *params,
472                              uint32_t flags)
473 {
474   GWEN_SYNCIO *sio;
475   int rv;
476 
477   /* create SyncIO, don't take over buf */
478   sio=GWEN_SyncIo_Memory_new(buf, 0);
479   rv=GWEN_DBIO_Export(dbio, sio, db, params, flags);
480   if (rv<0) {
481     DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
482     GWEN_SyncIo_free(sio);
483     return rv;
484   }
485 
486   GWEN_SyncIo_free(sio);
487   return 0;
488 }
489 
490 
491 
GWEN_DBIO_ImportFromFile(GWEN_DBIO * dbio,const char * fname,GWEN_DB_NODE * db,GWEN_DB_NODE * params,uint32_t dbflags)492 int GWEN_DBIO_ImportFromFile(GWEN_DBIO *dbio,
493                              const char *fname,
494                              GWEN_DB_NODE *db,
495                              GWEN_DB_NODE *params,
496                              uint32_t dbflags)
497 {
498   GWEN_SYNCIO *sio;
499   int rv;
500   GWEN_FSLOCK *lck=0;
501 
502   /* if locking requested */
503   if (dbflags & GWEN_DB_FLAGS_LOCKFILE) {
504     GWEN_FSLOCK_RESULT res;
505 
506     lck=GWEN_FSLock_new(fname, GWEN_FSLock_TypeFile);
507     assert(lck);
508     res=GWEN_FSLock_Lock(lck, GWEN_DB_DEFAULT_LOCK_TIMEOUT, 0);
509     if (res!=GWEN_FSLock_ResultOk) {
510       DBG_ERROR(GWEN_LOGDOMAIN,
511                 "Could not apply lock to file \"%s\" (%d)",
512                 fname, res);
513       GWEN_FSLock_free(lck);
514       return GWEN_ERROR_IO;
515     }
516   }
517 
518   sio=GWEN_SyncIo_File_new(fname, GWEN_SyncIo_File_CreationMode_OpenExisting);
519   GWEN_SyncIo_AddFlags(sio, GWEN_SYNCIO_FILE_FLAGS_READ);
520   rv=GWEN_SyncIo_Connect(sio);
521   if (rv<0) {
522     DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
523     GWEN_SyncIo_free(sio);
524     if (lck) {
525       GWEN_FSLock_Unlock(lck);
526       GWEN_FSLock_free(lck);
527     }
528     return rv;
529   }
530 
531   /* read from file */
532   rv=GWEN_DBIO_Import(dbio, sio, db, params, dbflags);
533   if (rv<0) {
534     DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
535     GWEN_SyncIo_Disconnect(sio);
536     GWEN_SyncIo_free(sio);
537     if (lck) {
538       GWEN_FSLock_Unlock(lck);
539       GWEN_FSLock_free(lck);
540     }
541     return rv;
542   }
543 
544   /* close io layer */
545   GWEN_SyncIo_Disconnect(sio);
546   GWEN_SyncIo_free(sio);
547 
548   /* remove lock, if any */
549   if (lck) {
550     GWEN_FSLOCK_RESULT res;
551 
552     res=GWEN_FSLock_Unlock(lck);
553     if (res!=GWEN_FSLock_ResultOk) {
554       DBG_WARN(GWEN_LOGDOMAIN,
555                "Could not remove lock on file \"%s\" (%d)",
556                fname, res);
557     }
558     GWEN_FSLock_free(lck);
559   }
560 
561   return 0;
562 }
563 
564 
565 
566 
567 
568 
569 
570 
571 
572 
573 
574 
575 
576 
577