1 /* $NetBSD: src/lib/libc/citrus/citrus_pivot_factory.c,v 1.4 2004/01/02 21:49:35 itojun Exp $ */ 2 /* $DragonFly: src/lib/libc/citrus/citrus_pivot_factory.c,v 1.1 2005/03/11 23:33:53 joerg Exp $ */ 3 4 /*- 5 * Copyright (c)2003 Citrus Project, 6 * All rights reserved. 7 * 8 * Redistribution and use in source and binary forms, with or without 9 * modification, are permitted provided that the following conditions 10 * are met: 11 * 1. Redistributions of source code must retain the above copyright 12 * notice, this list of conditions and the following disclaimer. 13 * 2. Redistributions in binary form must reproduce the above copyright 14 * notice, this list of conditions and the following disclaimer in the 15 * documentation and/or other materials provided with the distribution. 16 * 17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 20 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 27 * SUCH DAMAGE. 28 */ 29 30 #include <sys/endian.h> 31 #include <sys/queue.h> 32 #include <assert.h> 33 #include <ctype.h> 34 #include <errno.h> 35 #include <limits.h> 36 #include <stdio.h> 37 #include <stdlib.h> 38 #include <string.h> 39 40 #include "citrus_namespace.h" 41 #include "citrus_region.h" 42 #include "citrus_bcs.h" 43 #include "citrus_db_factory.h" 44 #include "citrus_db_hash.h" 45 #include "citrus_pivot_file.h" 46 #include "citrus_pivot_factory.h" 47 48 struct src_entry { 49 char *se_name; 50 struct _citrus_db_factory *se_df; 51 STAILQ_ENTRY(src_entry) se_entry; 52 }; 53 STAILQ_HEAD(src_head, src_entry); 54 55 static int 56 find_src(struct src_head *sh, struct src_entry **rse, const char *name) 57 { 58 int ret; 59 struct src_entry *se; 60 61 STAILQ_FOREACH(se, sh, se_entry) { 62 if (_bcs_strcasecmp(se->se_name, name) == 0) { 63 *rse = se; 64 return 0; 65 } 66 } 67 se = malloc(sizeof(*se)); 68 if (se == NULL) 69 return errno; 70 se->se_name = strdup(name); 71 if (se->se_name == NULL) { 72 ret = errno; 73 free(se); 74 return ret; 75 } 76 ret = _db_factory_create(&se->se_df, &_db_hash_std, NULL); 77 if (ret) { 78 free(se->se_name); 79 free(se); 80 return ret; 81 } 82 STAILQ_INSERT_TAIL(sh, se, se_entry); 83 *rse = se; 84 85 return 0; 86 } 87 88 static void 89 free_src(struct src_head *sh) 90 { 91 struct src_entry *se; 92 93 while ((se = STAILQ_FIRST(sh)) != NULL) { 94 STAILQ_REMOVE_HEAD(sh, se_entry); 95 _db_factory_free(se->se_df); 96 free(se->se_name); 97 free(se); 98 } 99 } 100 101 102 #define T_COMM '#' 103 static int 104 convert_line(struct src_head *sh, const char *line, size_t len) 105 { 106 int ret; 107 struct src_entry *se; 108 const char *p; 109 char key1[LINE_MAX], key2[LINE_MAX], data[LINE_MAX]; 110 uint32_t val; 111 112 /* cut off trailing comment */ 113 p = memchr(line, T_COMM, len); 114 if (p) 115 len = p - line; 116 117 /* key1 */ 118 line = _bcs_skip_ws_len(line, &len); 119 if (len == 0) 120 return 0; 121 p = _bcs_skip_nonws_len(line, &len); 122 if (p==line) 123 return 0; 124 snprintf(key1, sizeof(key1), "%.*s", (int)(p-line), line); 125 126 /* key2 */ 127 line = _bcs_skip_ws_len(p, &len); 128 if (len == 0) 129 return 0; 130 p = _bcs_skip_nonws_len(line, &len); 131 if (p==line) 132 return 0; 133 snprintf(key2, sizeof(key2), "%.*s", (int)(p-line), line); 134 135 /* data */ 136 line = _bcs_skip_ws_len(p, &len); 137 _bcs_trunc_rws_len(line, &len); 138 snprintf(data, sizeof(data), "%.*s", (int)len, line); 139 /* LINTED: discard const */ 140 val = strtoul(data, __DECONST(char **, &p), 0); 141 if (*p != '\0') 142 return EFTYPE; 143 144 /* insert to DB */ 145 ret = find_src(sh, &se, key1); 146 if (ret) 147 return ret; 148 149 return _db_factory_add32_by_s(se->se_df, key2, val); 150 } 151 152 static int 153 dump_db(struct src_head *sh, struct _region *r) 154 { 155 int ret; 156 struct _db_factory *df; 157 struct src_entry *se; 158 size_t size; 159 void *ptr; 160 struct _region subr; 161 162 ret = _db_factory_create(&df, &_db_hash_std, NULL); 163 if (ret) 164 return ret; 165 166 STAILQ_FOREACH(se, sh, se_entry) { 167 size = _db_factory_calc_size(se->se_df); 168 ptr = malloc(size); 169 if (ptr == NULL) 170 goto quit; 171 _region_init(&subr, ptr, size); 172 ret = _db_factory_serialize(se->se_df, _CITRUS_PIVOT_SUB_MAGIC, 173 &subr); 174 if (ret) 175 goto quit; 176 ret = _db_factory_add_by_s(df, se->se_name, &subr, 1); 177 if (ret) 178 goto quit; 179 } 180 181 size = _db_factory_calc_size(df); 182 ptr = malloc(size); 183 if (ptr == NULL) 184 goto quit; 185 _region_init(r, ptr, size); 186 187 ret = _db_factory_serialize(df, _CITRUS_PIVOT_MAGIC, r); 188 ptr = NULL; 189 190 quit: 191 free(ptr); 192 _db_factory_free(df); 193 return ret; 194 } 195 196 int 197 _citrus_pivot_factory_convert(FILE *out, FILE *in) 198 { 199 struct src_head sh; 200 struct _region r; 201 char *line; 202 size_t size; 203 int ret; 204 205 STAILQ_INIT(&sh); 206 207 while ((line = fgetln(in, &size)) != NULL) 208 if ((ret = convert_line(&sh, line, size))) { 209 free_src(&sh); 210 return ret; 211 } 212 213 ret = dump_db(&sh, &r); 214 free_src(&sh); 215 if (ret) 216 return ret; 217 218 if (fwrite(_region_head(&r), _region_size(&r), 1, out) != 1) 219 return errno; 220 221 return 0; 222 } 223