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