]> arthur.barton.de Git - netatalk.git/blob - etc/cnid_dbd/db_param.c
Merge from branch 2-1
[netatalk.git] / etc / cnid_dbd / db_param.c
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
28 static struct db_param params;
29 static int parse_err;
30
31 static size_t usock_maxlen(void)
32 {
33     struct sockaddr_un addr;
34     return sizeof(addr.sun_path) - 1;
35 }
36
37 static 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
57 static 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
77 static 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
95 struct 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(&params, 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 &params;
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 &params;
193     }
194     else
195         return NULL;
196 }
197
198
199