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 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 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 172 void 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 194 void dict_jmp_alloc(DICT *dict) 195 { 196 if (dict->jbuf == 0) 197 dict->jbuf = (DICT_JMP_BUF *) mymalloc(sizeof(DICT_JMP_BUF)); 198 } 199