1/* 2 * $Id: db_param.c,v 1.9 2009-11-23 19:04:14 franklahm Exp $ 3 * 4 * Copyright (C) Joerg Lenneis 2003 5 * Copyright (c) Frank Lahm 2009 6 * All Rights Reserved. See COPYING. 7 */ 8 9#ifdef HAVE_CONFIG_H 10#include "config.h" 11#endif /* HAVE_CONFIG_H */ 12 13#include <unistd.h> 14#include <string.h> 15#include <stdio.h> 16#include <stdlib.h> 17#include <errno.h> 18#include <sys/param.h> 19#include <sys/un.h> 20#include <sys/select.h> 21#include <atalk/logger.h> 22 23#include "db_param.h" 24 25#define DB_PARAM_FN "db_param" 26#define MAXKEYLEN 64 27 28static struct db_param params; 29static int parse_err; 30 31static size_t usock_maxlen(void) 32{ 33 struct sockaddr_un addr; 34 return sizeof(addr.sun_path) - 1; 35} 36 37static int make_pathname(char *path, char *dir, char *fn, size_t maxlen) 38{ 39 size_t len; 40 41 if (fn[0] != '/') { 42 len = strlen(dir); 43 if (len + 1 + strlen(fn) > maxlen) 44 return -1; 45 strcpy(path, dir); 46 if (path[len - 1] != '/') 47 strcat(path, "/"); 48 strcat(path, fn); 49 } else { 50 if (strlen(fn) > maxlen) 51 return -1; 52 strcpy(path, fn); 53 } 54 return 0; 55} 56 57static void default_params(struct db_param *dbp, char *dir) 58{ 59 dbp->logfile_autoremove = DEFAULT_LOGFILE_AUTOREMOVE; 60 dbp->cachesize = DEFAULT_CACHESIZE; 61 dbp->maxlocks = DEFAULT_MAXLOCKS; 62 dbp->maxlockobjs = DEFAULT_MAXLOCKOBJS; 63 dbp->flush_frequency = DEFAULT_FLUSH_FREQUENCY; 64 dbp->flush_interval = DEFAULT_FLUSH_INTERVAL; 65 if (make_pathname(dbp->usock_file, dir, DEFAULT_USOCK_FILE, usock_maxlen()) < 0) { 66 /* Not an error yet, it might be set in the config file */ 67 dbp->usock_file[0] = '\0'; 68 } 69 dbp->fd_table_size = DEFAULT_FD_TABLE_SIZE; 70 if ( dbp->fd_table_size > FD_SETSIZE -1) 71 dbp->fd_table_size = FD_SETSIZE -1; 72 dbp->idle_timeout = DEFAULT_IDLE_TIMEOUT; 73 74 return; 75} 76 77static int parse_int(char *val) 78{ 79 char *tmp; 80 int result = 0; 81 82 result = strtol(val, &tmp, 10); 83 if (tmp[0] != '\0') { 84 LOG(log_error, logtype_cnid, "invalid characters in token %s", val); 85 parse_err++; 86 } 87 return result; 88} 89 90 91/* TODO: This configuration file reading routine is neither very robust (%s 92 buffer overflow) nor elegant, we need to add support for whitespace in 93 filenames as well. */ 94 95struct db_param *db_param_read(char *dir) 96{ 97 FILE *fp; 98 static char key[MAXKEYLEN + 1]; 99 static char val[MAXPATHLEN + 1]; 100 static char pfn[MAXPATHLEN + 1]; 101 int items; 102 103 default_params(¶ms, dir); 104 params.dir = dir; 105 106 if (make_pathname(pfn, dir, DB_PARAM_FN, MAXPATHLEN) < 0) { 107 LOG(log_error, logtype_cnid, "Parameter filename too long"); 108 return NULL; 109 } 110 111 if ((fp = fopen(pfn, "r")) == NULL) { 112 if (errno == ENOENT) { 113 if (strlen(params.usock_file) == 0) { 114 LOG(log_error, logtype_cnid, "default usock filename too long"); 115 return NULL; 116 } else { 117 return ¶ms; 118 } 119 } else { 120 LOG(log_error, logtype_cnid, "error opening %s: %s", pfn, strerror(errno)); 121 return NULL; 122 } 123 } 124 parse_err = 0; 125 126 while ((items = fscanf(fp, " %s %s", key, val)) != EOF) { 127 if (items != 2) { 128 LOG(log_error, logtype_cnid, "error parsing config file"); 129 parse_err++; 130 break; 131 } 132 133 /* Config for both cnid_meta and dbd */ 134 if (! strcmp(key, "usock_file")) { 135 if (make_pathname(params.usock_file, dir, val, usock_maxlen()) < 0) { 136 LOG(log_error, logtype_cnid, "usock filename %s too long", val); 137 parse_err++; 138 } else 139 LOG(log_info, logtype_cnid, "db_param: setting UNIX domain socket filename to %s", params.usock_file); 140 } 141 142 if (! strcmp(key, "fd_table_size")) { 143 params.fd_table_size = parse_int(val); 144 LOG(log_info, logtype_cnid, "db_param: setting max number of concurrent afpd connections per volume (fd_table_size) to %d", params.fd_table_size); 145 } else if (! strcmp(key, "logfile_autoremove")) { 146 params.logfile_autoremove = parse_int(val); 147 LOG(log_info, logtype_cnid, "db_param: setting logfile_autoremove to %d", params.logfile_autoremove); 148 } else if (! strcmp(key, "cachesize")) { 149 params.cachesize = parse_int(val); 150 LOG(log_info, logtype_cnid, "db_param: setting cachesize to %d", params.cachesize); 151 } else if (! strcmp(key, "maxlocks")) { 152 params.maxlocks = parse_int(val); 153 LOG(log_info, logtype_cnid, "db_param: setting maxlocks to %d", params.maxlocks); 154 } else if (! strcmp(key, "maxlockobjs")) { 155 params.maxlockobjs = parse_int(val); 156 LOG(log_info, logtype_cnid, "db_param: setting maxlockobjs to %d", params.maxlockobjs); 157 } else if (! strcmp(key, "flush_frequency")) { 158 params.flush_frequency = parse_int(val); 159 LOG(log_info, logtype_cnid, "db_param: setting flush_frequency to %d", params.flush_frequency); 160 } else if (! strcmp(key, "flush_interval")) { 161 params.flush_interval = parse_int(val); 162 LOG(log_info, logtype_cnid, "db_param: setting flush_interval to %d", params.flush_interval); 163 } else if (! strcmp(key, "idle_timeout")) { 164 params.idle_timeout = parse_int(val); 165 LOG(log_info, logtype_cnid, "db_param: setting idle timeout to %d", params.idle_timeout); 166 } 167 168 if (parse_err) 169 break; 170 } 171 172 if (strlen(params.usock_file) == 0) { 173 LOG(log_error, logtype_cnid, "default usock filename too long"); 174 parse_err++; 175 } 176 177 fclose(fp); 178 if (! parse_err) { 179 /* sanity checks */ 180 if (params.flush_frequency <= 0) 181 params.flush_frequency = 86400; 182 183 if (params.flush_interval <= 0) 184 params.flush_interval = 1000000; 185 186 if (params.fd_table_size <= 2) 187 params.fd_table_size = 32; 188 189 if (params.idle_timeout <= 0) 190 params.idle_timeout = 86400; 191 192 return ¶ms; 193 } 194 else 195 return NULL; 196} 197 198 199 200