1 /* $NetBSD: output_cdb.c,v 1.1 2010/04/25 00:54:46 joerg Exp $ */ 2 3 /*- 4 * Copyright (c) 2010 The NetBSD Foundation, Inc. 5 * All rights reserved. 6 * 7 * This code is derived from software contributed to The NetBSD Foundation 8 * by Joerg Sonnenberger. 9 * 10 * Redistribution and use in source and binary forms, with or without 11 * modification, are permitted provided that the following conditions 12 * are met: 13 * 1. Redistributions of source code must retain the above copyright 14 * notice, this list of conditions and the following disclaimer. 15 * 2. Redistributions in binary form must reproduce the above copyright 16 * notice, this list of conditions and the following disclaimer in the 17 * documentation and/or other materials provided with the distribution. 18 * 19 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 20 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 21 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 22 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 23 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 29 * POSSIBILITY OF SUCH DAMAGE. 30 */ 31 32 33 #include <sys/endian.h> 34 #include <cdbw.h> 35 #include <err.h> 36 #include <errno.h> 37 #include <fcntl.h> 38 #include <stdlib.h> 39 #include <string.h> 40 #include <stringlist.h> 41 #include <unistd.h> 42 43 #include "extern.h" 44 45 static struct cdbw *cdbw; 46 static int cdbw_fd = -1; 47 48 int 49 cdb_open(const char *tname) 50 { 51 52 if ((cdbw = cdbw_open()) == NULL) 53 return -1; 54 55 if ((cdbw_fd = open(tname, O_WRONLY | O_CREAT | O_TRUNC, 0666)) == -1) { 56 cdbw_close(cdbw); 57 cdbw = NULL; 58 return -1; 59 } 60 return 0; 61 } 62 63 void 64 cdb_add(StringList *sl, size_t port, const char *proto, size_t *cnt, 65 int warndup) 66 { 67 uint8_t key[255 * 2 + 2]; 68 uint8_t *data, *data_iter; 69 size_t len, protolen, datalen, keylen; 70 uint32_t idx; 71 size_t i; 72 73 protolen = strlen(proto); 74 if (protolen == 0 || protolen > 255) 75 errx(1, "Invalid protocol ``%s'', entry skipped", proto); 76 77 datalen = 4 + protolen; 78 for (i = 0; i < sl->sl_cur; ++i) { 79 len = strlen(sl->sl_str[i]); 80 if (len == 0 || len > 255) 81 errx(1, "Service alias ``%s'' invalid", sl->sl_str[i]); 82 datalen += len + 2; 83 } 84 85 data = malloc(datalen); 86 if (data == NULL) 87 err(1, "malloc failed"); 88 be16enc(data, port); 89 data[2] = protolen; 90 data_iter = data + 3; 91 memcpy(data_iter, proto, protolen + 1); 92 data_iter += protolen + 1; 93 for (i = 0; i < sl->sl_cur; ++i) { 94 len = strlen(sl->sl_str[i]); 95 *data_iter++ = len; 96 memcpy(data_iter, sl->sl_str[i], len + 1); 97 data_iter += len + 1; 98 } 99 100 if (cdbw_put_data(cdbw, data, datalen, &idx)) 101 err(1, "cdbw_put_data failed"); 102 103 free(data); 104 105 key[0] = 0; 106 key[1] = protolen; 107 be16enc(key + 2, port); 108 memcpy(key + 4, proto, protolen); 109 keylen = 4 + protolen; 110 if (cdbw_put_key(cdbw, key, keylen, idx) && warndup) 111 warnx("duplicate service: `%zu/%s'", port, proto); 112 113 key[1] = 0; 114 keylen = 4; 115 if (cdbw_put_key(cdbw, key, keylen, idx) && warndup) 116 warnx("duplicate service: `%zu'", port); 117 118 /* add references for service and all aliases */ 119 for (i = 0; i < sl->sl_cur; i++) { 120 len = strlen(sl->sl_str[i]); 121 key[0] = len; 122 key[1] = protolen; 123 memcpy(key + 2, sl->sl_str[i], len); 124 memcpy(key + 2 + len, proto, protolen); 125 keylen = 2 + len + protolen; 126 if (cdbw_put_key(cdbw, key, keylen, idx) && warndup) 127 warnx("duplicate service: `%s/%s'", sl->sl_str[i], proto); 128 129 key[1] = 0; 130 keylen = 2 + len; 131 if (cdbw_put_key(cdbw, key, keylen, idx) && warndup) 132 warnx("duplicate service: `%s'", sl->sl_str[i]); 133 } 134 135 sl_free(sl, 1); 136 } 137 138 int 139 cdb_close(void) 140 { 141 int rv, serrno; 142 143 rv = 0; 144 serrno = errno; 145 146 if (cdbw_output(cdbw, cdbw_fd, "services(5)", NULL)) { 147 rv = -1; 148 serrno = errno; 149 } 150 151 cdbw_close(cdbw); 152 cdbw = NULL; 153 154 if (close(cdbw_fd)) { 155 if (rv == 0) 156 serrno = errno; 157 rv = -1; 158 } 159 cdbw_fd = -1; 160 161 errno = serrno; 162 return rv; 163 } 164