1/*	$NetBSD: dict_alloc.c,v 1.3 2020/03/18 19:05:21 christos Exp $	*/
2
3/*++
4/* NAME
5/*	dict_alloc 3
6/* SUMMARY
7/*	dictionary memory manager
8/* SYNOPSIS
9/*	#include <dict.h>
10/*
11/*	DICT	*dict_alloc(dict_type, dict_name, size)
12/*	const char *dict_type;
13/*	const char *dict_name;
14/*	ssize_t	size;
15/*
16/*	void	dict_free(dict)
17/*	DICT	*ptr;
18/*
19/*	void	dict_jmp_alloc(dict)
20/*	DICT	*ptr;
21/* DESCRIPTION
22/*	dict_alloc() allocates memory for a dictionary structure of
23/*	\fIsize\fR bytes, initializes all generic dictionary
24/*	properties to default settings,
25/*	and installs default methods that do not support any operation.
26/*	The caller is supposed to override the default methods with
27/*	ones that it supports.
28/*	The purpose of the default methods is to trap an attempt to
29/*	invoke an unsupported method.
30/*
31/*	One exception is the default lock function.  When the
32/*	dictionary provides a file handle for locking, the default
33/*	lock function returns the result from myflock with the
34/*	locking method specified in the lock_type member, otherwise
35/*	it returns 0. Presently, the lock function is used only to
36/*	implement the DICT_FLAG_OPEN_LOCK feature (lock the database
37/*	exclusively after it is opened) for databases that are not
38/*	multi-writer safe.
39/*
40/*	dict_free() releases memory and cleans up after dict_alloc().
41/*	It is up to the caller to dispose of any memory that was allocated
42/*	by the caller.
43/*
44/*	dict_jmp_alloc() implements preliminary support for exception
45/*	handling. This will eventually be built into dict_alloc().
46/*
47/*	Arguments:
48/* .IP dict_type
49/*	The official name for this type of dictionary, as used by
50/*	dict_open(3) etc. This is stored under the \fBtype\fR
51/*	member.
52/* .IP dict_name
53/*	Dictionary name. This is stored as the \fBname\fR member.
54/* .IP size
55/*	The size in bytes of the dictionary subclass structure instance.
56/* SEE ALSO
57/*	dict(3)
58/* DIAGNOSTICS
59/*	Fatal errors: the process invokes a default method.
60/* LICENSE
61/* .ad
62/* .fi
63/*	The Secure Mailer license must be distributed with this software.
64/* AUTHOR(S)
65/*	Wietse Venema
66/*	IBM T.J. Watson Research
67/*	P.O. Box 704
68/*	Yorktown Heights, NY 10598, USA
69/*
70/*	Wietse Venema
71/*	Google, Inc.
72/*	111 8th Avenue
73/*	New York, NY 10011, USA
74/*--*/
75
76/* System libraries. */
77
78#include "sys_defs.h"
79
80/* Utility library. */
81
82#include "msg.h"
83#include "mymalloc.h"
84#include "myflock.h"
85#include "dict.h"
86
87/* dict_default_lookup - trap unimplemented operation */
88
89static const char *dict_default_lookup(DICT *dict, const char *unused_key)
90{
91    msg_fatal("table %s:%s: lookup operation is not supported",
92	      dict->type, dict->name);
93}
94
95/* dict_default_update - trap unimplemented operation */
96
97static int dict_default_update(DICT *dict, const char *unused_key,
98			               const char *unused_value)
99{
100    msg_fatal("table %s:%s: update operation is not supported",
101	      dict->type, dict->name);
102}
103
104/* dict_default_delete - trap unimplemented operation */
105
106static int dict_default_delete(DICT *dict, const char *unused_key)
107{
108    msg_fatal("table %s:%s: delete operation is not supported",
109	      dict->type, dict->name);
110}
111
112/* dict_default_sequence - trap unimplemented operation */
113
114static int dict_default_sequence(DICT *dict, int unused_function,
115		         const char **unused_key, const char **unused_value)
116{
117    msg_fatal("table %s:%s: sequence operation is not supported",
118	      dict->type, dict->name);
119}
120
121/* dict_default_lock - default lock handler */
122
123static int dict_default_lock(DICT *dict, int operation)
124{
125    if (dict->lock_fd >= 0) {
126	return (myflock(dict->lock_fd, dict->lock_type, operation));
127    } else {
128	return (0);
129    }
130}
131
132/* dict_default_close - trap unimplemented operation */
133
134static void dict_default_close(DICT *dict)
135{
136    msg_fatal("table %s:%s: close operation is not supported",
137	      dict->type, dict->name);
138}
139
140/* dict_alloc - allocate dictionary object, initialize super-class */
141
142DICT   *dict_alloc(const char *dict_type, const char *dict_name, ssize_t size)
143{
144    DICT   *dict = (DICT *) mymalloc(size);
145
146    dict->type = mystrdup(dict_type);
147    dict->name = mystrdup(dict_name);
148    dict->flags = DICT_FLAG_FIXED;
149    dict->lookup = dict_default_lookup;
150    dict->update = dict_default_update;
151    dict->delete = dict_default_delete;
152    dict->sequence = dict_default_sequence;
153    dict->close = dict_default_close;
154    dict->lock = dict_default_lock;
155    dict->lock_type = INTERNAL_LOCK;
156    dict->lock_fd = -1;
157    dict->stat_fd = -1;
158    dict->mtime = 0;
159    dict->fold_buf = 0;
160    dict->owner.status = DICT_OWNER_UNKNOWN;
161    dict->owner.uid = INT_MAX;
162    dict->error = DICT_ERR_NONE;
163    dict->jbuf = 0;
164    dict->utf8_backup = 0;
165    dict->file_buf = 0;
166    dict->file_b64 = 0;
167    return dict;
168}
169
170/* dict_free - super-class destructor */
171
172void    dict_free(DICT *dict)
173{
174    myfree(dict->type);
175    myfree(dict->name);
176    if (dict->jbuf)
177	myfree((void *) dict->jbuf);
178    if (dict->utf8_backup)
179	myfree((void *) dict->utf8_backup);
180    if (dict->file_buf)
181	vstring_free(dict->file_buf);
182    if (dict->file_b64)
183	vstring_free(dict->file_b64);
184    myfree((void *) dict);
185}
186
187 /*
188  * TODO: add a dict_flags() argument to dict_alloc() and handle jump buffer
189  * allocation there.
190  */
191
192/* dict_jmp_alloc - enable exception handling */
193
194void    dict_jmp_alloc(DICT *dict)
195{
196    if (dict->jbuf == 0)
197	dict->jbuf = (DICT_JMP_BUF *) mymalloc(sizeof(DICT_JMP_BUF));
198}
199