Home | History | Annotate | Line # | Download | only in util
      1 /*	$NetBSD: dict_alloc.c,v 1.4 2026/05/09 18:49:22 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 
     89 static 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 
     97 static 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 
    106 static 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 
    114 static 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 
    123 static 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 
    134 static 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 
    142 DICT   *dict_alloc(const char *dict_type, const char *dict_name, ssize_t size)
    143 {
    144     DICT   *dict = (DICT *) mymalloc(size);
    145 
    146     if (msg_verbose > 2)
    147 	msg_info("dict_alloc(\"%s\", \"%s\", %ld)",
    148 		 dict_type, dict_name, (long) size);
    149 
    150     dict->type = mystrdup(dict_type);
    151     dict->name = mystrdup(dict_name);
    152     dict->flags = 0;
    153     dict->lookup = dict_default_lookup;
    154     dict->update = dict_default_update;
    155     dict->delete = dict_default_delete;
    156     dict->sequence = dict_default_sequence;
    157     dict->close = dict_default_close;
    158     dict->lock = dict_default_lock;
    159     dict->lock_type = INTERNAL_LOCK;
    160     dict->lock_fd = -1;
    161     dict->stat_fd = -1;
    162     dict->mtime = 0;
    163     dict->fold_buf = 0;
    164     dict->owner.status = DICT_OWNER_UNKNOWN;
    165     dict->owner.uid = INT_MAX;
    166     dict->error = DICT_ERR_NONE;
    167     dict->jbuf = 0;
    168     dict->utf8_backup = 0;
    169     dict->file_buf = 0;
    170     dict->file_b64 = 0;
    171     dict->reg_name = 0;
    172     dict->saved_close = 0;
    173     return dict;
    174 }
    175 
    176 /* dict_free - super-class destructor */
    177 
    178 void    dict_free(DICT *dict)
    179 {
    180     if (msg_verbose > 2)
    181 	msg_info("dict_free type=\"%s\" name=\"%s\" reg_name=\"%s\")",
    182 		 dict->type, dict->name, dict->reg_name ?
    183 		 dict->reg_name : "(null)");
    184 
    185     myfree(dict->type);
    186     myfree(dict->name);
    187     if (dict->jbuf)
    188 	myfree((void *) dict->jbuf);
    189     if (dict->utf8_backup)
    190 	myfree((void *) dict->utf8_backup);
    191     if (dict->file_buf)
    192 	vstring_free(dict->file_buf);
    193     if (dict->file_b64)
    194 	vstring_free(dict->file_b64);
    195     if (dict->reg_name)
    196 	myfree(dict->reg_name);
    197     myfree((void *) dict);
    198 }
    199 
    200  /*
    201   * TODO: add a dict_flags() argument to dict_alloc() and handle jump buffer
    202   * allocation there.
    203   */
    204 
    205 /* dict_jmp_alloc - enable exception handling */
    206 
    207 void    dict_jmp_alloc(DICT *dict)
    208 {
    209     if (dict->jbuf == 0)
    210 	dict->jbuf = (DICT_JMP_BUF *) mymalloc(sizeof(DICT_JMP_BUF));
    211 }
    212