1 /*
2 Copyright (C) 2015-2021, Dirk Krause
3 SPDX-License-Identifier: BSD-3-Clause
4 */
5 
6 /*
7 	WARNING: This file was generated by the dkct program (see
8 	http://dktools.sourceforge.net/ for details).
9 	Changes you make here will be lost if dkct is run again!
10 	You should modify the original source and run dkct on it.
11 	Original source: dk4dbi.ctr
12 */
13 
14 #ifndef DK4DBI_H_INCLUDED
15 /** Avoid multiple inclusions. */
16 #define DK4DBI_H_INCLUDED 1
17 
18 
19 /**	@file	dk4dbi.h	Interface to databases.
20 */
21 
22 #ifndef DK4CONF_H_INCLUDED
23 #if DK4_BUILDING_DKTOOLS4
24 #include "dk4conf.h"
25 #else
26 #include <dktools-4/dk4conf.h>
27 #endif
28 #endif
29 
30 #ifndef DK4TYPES_H_INCLUDED
31 #if DK4_BUILDING_DKTOOLS4
32 #include <libdk4base/dk4types.h>
33 #else
34 #include <dktools-4/dk4types.h>
35 #endif
36 #endif
37 
38 #if DK4_HAVE_UNISTD_H
39 #ifndef UNISTD_H_INCLUDED
40 #include <unistd.h>
41 #define	UNISTD_H_INCLUDED 1
42 #endif
43 #endif
44 
45 #if DK4_HAVE_SYS_TYPES_H
46 #ifndef SYS_TYPES_H_INCLUDED
47 #include <sys/types.h>
48 #define	SYS_TYPES_H_INCLUDED 1
49 #endif
50 #endif
51 
52 #if	DK4_HAVE_DB_H		&& (DK4_CHAR_SIZE == 1)
53 #include <db.h>
54 #endif
55 
56 #if	DK4_HAVE_NDBM_H		&& (DK4_CHAR_SIZE == 1)
57 #if DK4_HAVE_FCNTL_H
58 #ifndef FCNTL_H_INCLUDED
59 #include <fcntl.h>
60 #define	FCNTL_H_INCLUDED 1
61 #endif
62 #endif
63 #ifndef	NDBM_H_INCLUDED
64 #include <ndbm.h>
65 #define	NDBM_H_INCLUDED	1
66 #endif
67 #endif
68 
69 #ifndef DK4TYPES_H_INCLUDED
70 #if DK4_BUILDING_DKTOOLS4
71 #include <libdk4base/dk4types.h>
72 #else
73 #include <dktools-4/dk4types.h>
74 #endif
75 #endif
76 
77 #ifndef DK4ERROR_H_INCLUDED
78 #if DK4_BUILDING_DKTOOLS4
79 #include <libdk4base/dk4error.h>
80 #else
81 #include <dktools-4/dk4error.h>
82 #endif
83 #endif
84 
85 #ifndef	DK4STO_H_INCLUDED
86 #if DK4_BUILDING_DKTOOLS4
87 #include <libdk4c/dk4sto.h>
88 #else
89 #include <dktools-4/dk4sto.h>
90 #endif
91 #endif
92 
93 
94 
95 /**	Backend types.
96 */
97 enum {
98 			/**	No backend specified yet.
99 			*/
100   DK4_DB_BE_UNKNOWN	= -1 ,
101 
102   			/**	In-memory database.
103 			*/
104   DK4_DB_BE_MEMORY	=  0 ,
105 
106   			/**	Berkeley DB.
107 			*/
108   DK4_DB_BE_BDB		=  1 ,
109 
110   			/**	NDBM.
111 			*/
112   DK4_DB_BE_NDBM	=  2
113 };
114 
115 
116 
117 /**	Options.
118 */
119 enum {
120 				/**	Reset key data before releasing
121 					memory.
122 				*/
123   DK4_DB_OPT_RESET_KEY		= 1 ,
124 
125 				/**	Reset value data before releasing
126 					memory.
127 				*/
128   DK4_DB_OPT_RESET_VALUE	= 2 ,
129 };
130 
131 
132 
133 /**	Details for an in-memory database.
134 */
135 typedef struct {
136   dk4_sto_t	*s;	/**< Storage container. */
137   dk4_sto_it_t	*i;	/**< Storage iterator. */
138 } dk4_dbi_mem_t;
139 
140 
141 #if DK4_HAVE_DB_H		&& (DK4_CHAR_SIZE == 1)
142 /**	Details for a Berkeley DB database.
143 */
144 typedef struct {
145   DB		*db;	/**< DB structure. */
146 } dk4_dbi_bdb_t;
147 #endif
148 
149 #if DK4_HAVE_NDBM_H		&& (DK4_CHAR_SIZE == 1)
150 /**	Details for an NDBM database.
151 */
152 typedef struct {
153   DBM		*dbm;	/**< NDBM structure. */
154 } dk4_dbi_ndbm_t;
155 #endif
156 
157 /**	Details for one backend.
158 */
159 typedef union {
160   dk4_dbi_mem_t		mem;	/**< Details for in-memory database. */
161 #if DK4_HAVE_DB_H		&& (DK4_CHAR_SIZE == 1)
162   dk4_dbi_bdb_t		bdb;	/**< Details for Berkeley DB. */
163 #endif
164 #if DK4_HAVE_NDBM_H		&& (DK4_CHAR_SIZE == 1)
165   dk4_dbi_ndbm_t	ndbm;	/**< Details for NDBM. */
166 #endif
167   int			dummy;	/**< Just to have a second component. */
168 } dk4_dbi_det_t;
169 
170 /**	Database structure.
171 */
172 typedef struct {
173   dk4_dbi_det_t	 dt;	/**< Backend-specific details. */
174   dkChar	*fn;	/**< File name. */
175   size_t	 km;	/**< Maximum key size. */
176   size_t	 vm;	/**< Maximum value size. */
177   int		 tp;	/**< Backend type. */
178   int		 op;	/**< Options. */
179   int		 wa;	/**< Flag: Write access. */
180   int		 uc;	/**< Flag: Have unsynchronized changes. */
181 } dk4_dbi_t;
182 
183 /**	Function to traverse a simple database.
184 	The function must check the kb, ks, vb and vs arguments
185 	for validity, they are passed as found by the backend
186 	functions (this means pointers may be NULL, sizes may be 0).
187 	@param	Object modified during traversal, may be NULL.
188 	@param	kb	Key data.
189 	@param	ks	Key size.
190 	@param	vb	Value data.
191 	@param	vs	Value size.
192 	@return	1 on success, 0 on error (can continue), -1 on error (abort).
193 */
194 typedef
195 int
196 dk4dbi_traverse_fct_t(
197   void		*obj,
198   const void	*kb,
199   size_t	 ks,
200   const void	*vb,
201   size_t	 vs
202 );
203 
204 
205 #ifdef __cplusplus
206 extern "C" {
207 #endif
208 
209 /**	Open database.
210 	@param	fn	File name.
211 	@param	tp	Backend type.
212 	@param	wa	Flag: Write access required.
213 	@param	tr	Flag: Truncate existing database
214 			(only in conjunction with wa).
215 	@param	km	Maximum key size (0 for unlimited).
216 	@param	vm	Maximum value size (0 for unlimited).
217 			The limits are used on all backends for writing,
218 			on in-memory databases also for reading.
219 	@param	erp	Error report, may be NULL.
220 	@return	Pointer to new database structure on success, NULL on error.
221 
222 	Error codes:
223 	- DK4_E_INVALID_ARGUMENTS<br>
224 	  if fn is NULL or tp contains an invalid type number,
225 	- DK4_E_NOT_SUPPORTED<br>
226 	  if the database type is not supported,
227 	- DK4_E_MATH_OVERFLOW<br>
228 	  on numeric overflow when calculating size,
229 	- DK4_E_MEMORY_ALLOCATION_FAILED<br>
230 	  with mem.elsize and mem.nelem
231 	  set if there is not enough memory available,
232 	- DK4_E_SYNTAX<br>
233 	  if
234 	  - the database file name does not refer to a regular file
235 	  - or the file contents is not an in-memory database
236 	  - or key/value sizes in the file are in conflict with restrictions,
237 	- DK4_E_SEC_CHECK<br>
238 	  with failed check id in iDetails1 if access is denied by additional
239 	  security checks,
240 	- DK4_E_MEMORY_ALLOCATION_FAILED<br>
241 	  with mem.elsize and mem.nelem
242 	  set if there is not enough memory available,
243 	- DK4_E_OPEN_READ_FAILED<br>
244 	  if fopen() or fread() failed,
245 	- DK4_E_OPEN_WRITE_FAILED<br>
246 	  if fopen() or fwrite() failed,
247 	- DK4_E_CLOSE_FAILED<br>
248 	  with errno value in iDetails1 if fclose() failed.
249 
250 */
251 dk4_dbi_t *
252 dk4dbi_open_with_type(
253   const dkChar	*fn,
254   int		 tp,
255   int		 wa,
256   int		 tr,
257   size_t	 km,
258   size_t	 vm,
259   dk4_er_t	*erp
260 );
261 
262 /**	Open database.
263 	@param	fn	Database type and file name.
264 			The database type is one from "mem", "bdb" or "ndbm".
265 			Database type and file name are separated by two
266 			colons "::".
267 	@param	wa	Flag: Write access required.
268 	@param	tr	Flag: Truncate existing database
269 			(only in conjunction with wa).
270 	@param	km	Maximum key size (0 for unlimited).
271 	@param	vm	Maximum value size (0 for unlimited).
272 	@param	erp	Error report, may be NULL.
273 	@return	Pointer to new database structure on success, NULL on error.
274 
275 	Error codes:
276 	- DK4_E_INVALID_ARGUMENTS<br>
277 	  if fn is NULL or tp contains an invalid type number,
278 	- DK4_E_NOT_SUPPORTED<br>
279 	  if the database type is not supported,
280 	- DK4_E_MATH_OVERFLOW<br>
281 	  on numeric overflow when calculating size,
282 	- DK4_E_MEMORY_ALLOCATION_FAILED<br>
283 	  with mem.elsize and mem.nelem
284 	  set if there is not enough memory available,
285 	- DK4_E_SYNTAX<br>
286 	  if
287 	  - the specification contains an invalid backend type
288 	  - the database file name does not refer to a regular file
289 	  - or the file contents is not an in-memory database
290 	  - or key/value sizes in the file are in conflict with restrictions
291 	  - or an invalid database type was specified,
292 	- DK4_E_SEC_CHECK<br>
293 	  with failed check id in iDetails1 if access is denied by additional
294 	  security checks,
295 	- DK4_E_MEMORY_ALLOCATION_FAILED<br>
296 	  with mem.elsize and mem.nelem
297 	  set if there is not enough memory available,
298 	- DK4_E_OPEN_READ_FAILED<br>
299 	  if fopen() or fread() failed,
300 	- DK4_E_OPEN_WRITE_FAILED<br>
301 	  if fopen() or fwrite() failed,
302 	- DK4_E_CLOSE_FAILED<br>
303 	  with errno value in iDetails1 if fclose() failed.
304 */
305 dk4_dbi_t *
306 dk4dbi_open(
307   const dkChar	*fn,
308   int		 wa,
309   int		 tr,
310   size_t	 km,
311   size_t	 vm,
312   dk4_er_t	*erp
313 );
314 
315 /**	Find file name part from combined type/name.
316 	@param	filename	Combined database type and file name.
317 	@return	Valid pointer to file name part on success, NULL on error.
318 */
319 const dkChar *
320 dk4dbi_filename_part(const dkChar *filename);
321 
322 /**	Close database, release resources.
323 	@param	db	Database to close.
324 	@param	erp	Error report, may be NULL.
325 	@return	1 on success, 0 on error.
326 
327 	Error codes:
328 	- DK4_E_INVALID_ARGUMENTS<br>
329 	  if db is NULL,
330 	- DK4_E_NOT_SUPPORTED<br>
331 	  if db indicates an unsupported backend type,
332 	- DK4_E_SYNTAX<br>
333 	  if the database file name does not refer to a regular file,
334 	- DK4_E_SEC_CHECK<br>
335 	  with failed check id in iDetails1 if access is denied by additional
336 	  security checks,
337 	- DK4_E_OPEN_WRITE_FAILED<br>
338 	  with errno value in iDetails1 if fopen() or fwrite() failed,
339 	- DK4_E_CLOSE_FAILED<br>
340 	  with errno value in iDetails1 if fclose() failed.
341 */
342 int
343 dk4dbi_close(
344   dk4_dbi_t	*db,
345   dk4_er_t	*erp
346 );
347 
348 /**	Set or reset option.
349 	@param	db	Database.
350 	@param	opt	Option.
351 	@param	val	New value (1 or 0).
352 	@return	1 on success, 0 on error (unknown option).
353 */
354 int
355 dk4dbi_set_option(
356   dk4_dbi_t	*db,
357   int		 opt,
358   int		 val
359 );
360 
361 /**	Retrieve maximum key size.
362 	@param	db	Database to query.
363 	@param	erp	Error report, may be NULL.
364 	@return	Value on success (0 means unlimited),
365 	0 with erp set on error.
366 
367 	Error code:
368 	- DK4_E_INVALID_ARGUMENTS<br>
369 	  if db is NULL.
370 */
371 size_t
372 dk4dbi_get_key_max(
373   const dk4_dbi_t	*db,
374   dk4_er_t		*erp
375 );
376 
377 /**	Retrieve maximum value size.
378 	@param	db	Database to query.
379 	@param	erp	Error report, may be NULL.
380 	@return	Value on success (0 means unlimited),
381 	0 with erp set on error.
382 
383 
384 	Error code:
385 	- DK4_E_INVALID_ARGUMENTS<br>
386 	  if db is NULL.
387 */
388 size_t
389 dk4dbi_get_val_max(
390   const dk4_dbi_t	*db,
391   dk4_er_t		*erp
392 );
393 
394 /**	Set or overwrite record.
395 	@param	db	Database.
396 	@param 	kp	Pointer to key data.
397 	@param	ks	Key data size (number of bytes).
398 	@param	vp	Pointer to value data. Use NULL to delete a record.
399 	@param	vs	Value data size (number of bytes).
400 	@param	erp	Error report, may be NULL.
401 	@return	1 on success, 0 on error.
402 
403 	Error codes:
404 	- DK4_E_INVALID_ARGUMENTS<br>
405 	  if db or kp is NULL or ks is 0,
406 	- DK4_E_SYNTAX<br>
407 	  if the database was opened read-only or ks or vs
408 	  exceeds a size limit,
409 	- DK4_E_NOT_SUPPORTED<br>
410 	  if db indicates an unsupported backend,
411 	- DK4_E_NOT_FOUND<br>
412 	  if no record to delete was found,
413 	- DK4_E_MEMORY_ALLOCATION_FAILED<br>
414 	  with mem.elsize and mem.nelem
415 	  set if there is not enough memory available,
416 	- DK4_E_WRITE_FAILED<br>
417 	  if modification of the database failed.
418 */
419 int
420 dk4dbi_set(
421   dk4_dbi_t	*db,
422   const void	*kp,
423   size_t	 ks,
424   const void	*vp,
425   size_t	 vs,
426   dk4_er_t	*erp
427 );
428 
429 /**	Synchronize changes to file if supported by backend.
430 	@param	db	Database.
431 	@param	erp	error report, may be NULL.
432 	@return	1 on success, 0 on error.
433 
434 	Error codes:
435 	- DK4_E_INVALID_ARGUMENTS<br>
436 	  if db or a backend component is NULL,
437 	- DK4_E_NOT_SUPPORTED<br>
438 	  if db indicates an unsupported backend,
439 	- DK4_E_SYNTAX<br>
440 	  if the database file name does not refer to a regular file,
441 	- DK4_E_SEC_CHECK<br>
442 	  with failed check id in iDetails1 if access is denied by additional
443 	  security checks,
444 	- DK4_E_OPEN_WRITE_FAILED<br>
445 	  with errno value in iDetails1 if fopen() or fwrite() failed,
446 	- DK4_E_WRITE_FAILED<br>
447 	  if the backend failed to write to a database,
448 	- DK4_E_CLOSE_FAILED<br>
449 	  with errno value in iDetails1 if fclose() failed.
450 */
451 int
452 dk4dbi_sync(
453   dk4_dbi_t	*db,
454   dk4_er_t	*erp
455 );
456 
457 /**	Retrieve record.
458 	@param	db	Database.
459 	@param	kp	Pointer to key data.
460 	@param	ks	Key data size (number of bytes).
461 	@param	vp	Address of result buffer.
462 	@param	vs	Pointer to buffer size variable (in: size, out: used).
463 	@param	erp	Error report, may be NULL.
464 	@return	1 on success, 0 on error.
465 
466 	Error codes:
467 	- DK4_E_INVALID_ARGUMENTS<br>
468 	  if db, kp, vp or vs is NULL or ks is 0 or *vs is 0
469 	  or ks exceeds the key size limit,
470 	- DK4_E_NOT_SUPPORTED<br>
471 	  if db indicates an unsupported backend,
472 	- DK4_E_NOT_FOUND<br>
473 	  if no record was found for the key,
474 	- DK4_E_BUFFER_TOO_SMALL<br>
475 	  if the destination buffer is too small.
476 */
477 int
478 dk4dbi_get(
479   dk4_dbi_t	*db,
480   const void	*kp,
481   size_t	 ks,
482   void		*vp,
483   size_t	*vs,
484   dk4_er_t	*erp
485 );
486 
487 /**	Delete one record.
488 	@param	db	Database.
489 	@param	kp	Pointer to key data.
490 	@param	ks	Key data size (number of bytes).
491 	@param	erp	Error report, may be NULL.
492 	@return	1 on success, 0 on error.
493 
494 	Error codes:
495 	- DK4_E_INVALID_ARGUMENTS<br>
496 	  if db or kp is NULL or ks is 0,
497 	- DK4_E_SYNTAX<br>
498 	  if the database is opened read-only or ks exceeds the
499 	  key size limit,
500 	- DK4_E_NOT_SUPPORTED<br>
501 	  if db indicates an unsupported backend,
502 	- DK4_E_WRITE_FAILED<br>
503 	  if modification of the database failed,
504 	- DK4_E_NOT_FOUND<br>
505 	  if no record for the specified key is in the database.
506 */
507 int
508 dk4dbi_delete(
509   dk4_dbi_t	*db,
510   const void	*kp,
511   size_t	 ks,
512   dk4_er_t	*erp
513 );
514 
515 /**	Traverse database.
516 	@param	db	Database to traverse.
517 	@param	obj	Object to modify during traversal, may be NULL.
518 	@param	fct	Function to execute for all records.
519 	@return	1 on success, 0 on error (database traversed),
520 	-1 on error (traversal aborted).
521 */
522 int
523 dk4dbi_traverse(
524   dk4_dbi_t		*db,
525   void			*obj,
526   dk4dbi_traverse_fct_t	*fct
527 );
528 
529 /**	Retrieve backend type.
530 	@param	db	Database to check.
531 	@return	Backend type.
532 */
533 int
534 dk4dbi_get_type(const dk4_dbi_t *db);
535 
536 #if !DK4_ON_WINDOWS
537 #if DK4_CHAR_SIZE == 1
538 #if DK4_HAVE_CHOWN && DK4_HAVE_CHMOD
539 
540 /**	Change owner and mode for a database.
541 	@param	db	Database to modify.
542 	@param	user	New owner.
543 	@param	group	New owner group.
544 	@param	mode	New file permissions.
545 	@param	erp	Error report, may be NULL.
546 	@return	1 on success, 0 on error.
547 
548 	Error codes:
549 	- DK4_E_INVALID_ARGUMENTS<br>
550 	  if db is NULL,
551 	- DK4_E_NOT_SUPPORTED<br>
552 	  if db indicates an unsupported backend,
553 	- DK4_E_SYSTEM<br>
554 	  with errno value in iDetails1 if a chown or chmod
555 	  system call failed,
556 	- DK4_E_MATH_OVERFLOW<br>
557 	  if a mathematical overflow occured in size calculation,
558 	- DK4_E_BUFFER_TOO_SMALL<br>
559 	  if the file name is too large for an internal buffer.
560 */
561 int
562 dk4dbi_change_owner_and_mode(
563   dk4_dbi_t	*db,
564   uid_t		 user,
565   gid_t		 group,
566   mode_t	 mode,
567   dk4_er_t	*erp
568 );
569 
570 #endif
571 /* if DK4_HAVE_CHOWN && DK4_HAVE_CHMOD */
572 #endif
573 /* if DK4_CHAR_SIZE == 1 */
574 #endif
575 /* if !DK4_ON_WINDOWS */
576 
577 #ifdef __cplusplus
578 }
579 #endif
580 
581 
582 
583 
584 #endif
585