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