c31cdd573d37397401e78afeaee02ab252467dab
[platform/upstream/gdbm.git] / src / gdbmsetopt.c
1 /* gdbmsetopt.c - set options pertaining to a GDBM descriptor. */
2
3 /* This file is part of GDBM, the GNU data base manager.
4    Copyright (C) 1993, 1994, 2007, 2011 Free Software Foundation, Inc.
5
6    GDBM is free software; you can redistribute it and/or modify
7    it under the terms of the GNU General Public License as published by
8    the Free Software Foundation; either version 3, or (at your option)
9    any later version.
10
11    GDBM is distributed in the hope that it will be useful,
12    but WITHOUT ANY WARRANTY; without even the implied warranty of
13    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14    GNU General Public License for more details.
15
16    You should have received a copy of the GNU General Public License
17    along with GDBM. If not, see <http://www.gnu.org/licenses/>.   */
18
19 /* Include system configuration before all else. */
20 #include "autoconf.h"
21
22 #include "gdbmdefs.h"
23
24 /* operate on an already open descriptor. */
25
26 static int
27 getbool (void *optval, int optlen)
28 {
29   int n;
30   
31   if (!optval || optlen != sizeof (int) ||
32       (((n = *(int*)optval) != TRUE) && n != FALSE))
33     {
34       gdbm_errno = GDBM_OPT_ILLEGAL;
35       return -1;
36     }
37   return n;
38 }
39
40 static int
41 get_size (void *optval, int optlen, size_t *ret)
42 {
43   if (!optval)
44     {
45       gdbm_errno = GDBM_OPT_ILLEGAL;
46       return -1;
47     }
48   if (optlen == sizeof (unsigned))
49     *ret = *(unsigned*) optval;
50   else if (optlen == sizeof (unsigned long))
51     *ret = *(unsigned long*) optval;
52   else if (optlen == sizeof (size_t))
53     *ret = *(size_t*) optval;
54   else
55     {
56       gdbm_errno = GDBM_OPT_ILLEGAL;
57       return -1;
58     }
59   return 0;
60 }
61
62 int
63 gdbm_setopt (GDBM_FILE dbf, int optflag, void *optval, int optlen)
64 {
65   int n;
66   size_t sz;
67   
68   switch (optflag)
69     {
70       /* Cache size: */
71       
72       case GDBM_SETCACHESIZE:
73         /* Optval will point to the new size of the cache. */
74         if (dbf->bucket_cache != NULL)
75           {
76             gdbm_errno = GDBM_OPT_ALREADY_SET;
77             return -1;
78           }
79
80         if (get_size (optval, optlen, &sz))
81           return -1;
82         return _gdbm_init_cache (dbf, (sz > 9) ? sz : 10);
83
84       case GDBM_GETCACHESIZE:
85         if (!optval || optlen != sizeof (size_t))
86           {
87             gdbm_errno = GDBM_OPT_ILLEGAL;
88             return -1;
89           }
90         *(size_t*) optval = dbf->cache_size;
91         break;
92 \f       
93         /* Obsolete form of GDBM_SETSYNCMODE. */
94       case GDBM_FASTMODE:
95         if ((n = getbool (optval, optlen)) == -1)
96           return -1;
97         dbf->fast_write = n;
98         break;
99 \f
100         /* SYNC mode: */
101         
102       case GDBM_SETSYNCMODE:
103         /* Optval will point to either true or false. */
104         if ((n = getbool (optval, optlen)) == -1)
105           return -1;
106         dbf->fast_write = !n;
107         break;
108
109       case GDBM_GETSYNCMODE:
110         if (!optval || optlen != sizeof (int))
111           {
112             gdbm_errno = GDBM_OPT_ILLEGAL;
113             return -1;
114           }
115         *(int*) optval = !dbf->fast_write;
116         break;
117 \f
118         /* CENTFREE - set or get the stat of the central block repository */
119       case GDBM_SETCENTFREE:
120         /* Optval will point to either true or false. */
121         if ((n = getbool (optval, optlen)) == -1)
122           return -1;
123         dbf->central_free = n;
124         break;
125
126       case GDBM_GETCENTFREE:
127         if (!optval || optlen != sizeof (int))
128           {
129             gdbm_errno = GDBM_OPT_ILLEGAL;
130             return -1;
131           }
132         *(int*) optval = !dbf->central_free;
133         break;
134 \f
135         /* Coalesce state: */
136       case GDBM_SETCOALESCEBLKS:
137         /* Optval will point to either true or false. */
138         if ((n = getbool (optval, optlen)) == -1)
139           return -1;
140         dbf->coalesce_blocks = n;
141         break;
142
143       case GDBM_GETCOALESCEBLKS:
144         if (!optval || optlen != sizeof (int))
145           {
146             gdbm_errno = GDBM_OPT_ILLEGAL;
147             return -1;
148           }
149         *(int*) optval = dbf->coalesce_blocks;
150         break;
151 \f
152         /* Mmap mode */
153       case GDBM_SETMMAP:
154 #if HAVE_MMAP
155         if ((n = getbool (optval, optlen)) == -1)
156           return -1;
157         __fsync (dbf);
158         if (n == dbf->memory_mapping)
159           return 0;
160         if (n)
161           {
162             if (_gdbm_mapped_init (dbf) == 0)
163               dbf->memory_mapping = TRUE;
164             else
165               return -1;
166           }
167         else
168           {
169             _gdbm_mapped_unmap (dbf);
170             dbf->memory_mapping = FALSE;
171           }
172 #else
173         gdbm_errno = GDBM_OPT_ILLEGAL;
174         return -1;
175 #endif
176         break;
177         
178       case GDBM_GETMMAP:
179         if (!optval || optlen != sizeof (int))
180           {
181             gdbm_errno = GDBM_OPT_ILLEGAL;
182             return -1;
183           }
184         *(int*) optval = dbf->memory_mapping;
185         break;
186 \f
187         /* Maximum size of a memory mapped region */
188       case GDBM_SETMAXMAPSIZE:
189 #if HAVE_MMAP
190         {
191           size_t page_size = sysconf (_SC_PAGESIZE);
192
193           if (get_size (optval, optlen, &sz))
194             return -1;
195           dbf->mapped_size_max = ((sz + page_size - 1) / page_size) *
196                                   page_size;
197           _gdbm_mapped_init (dbf);
198           break;
199         }
200 #else
201         gdbm_errno = GDBM_OPT_ILLEGAL;
202         return -1;
203 #endif
204         
205       case GDBM_GETMAXMAPSIZE:
206         if (!optval || optlen != sizeof (size_t))
207           {
208             gdbm_errno = GDBM_OPT_ILLEGAL;
209             return -1;
210           }
211         *(size_t*) optval = dbf->mapped_size_max;
212         break;
213 \f
214         /* Flags */
215       case GDBM_GETFLAGS:
216         if (!optval || optlen != sizeof (int))
217           {
218             gdbm_errno = GDBM_OPT_ILLEGAL;
219             return -1;
220           }
221         else
222           {
223             int flags = dbf->read_write;
224             if (!dbf->fast_write)
225               flags |= GDBM_SYNC;
226             if (!dbf->file_locking)
227               flags |= GDBM_NOLOCK;
228             if (!dbf->memory_mapping)
229               flags |= GDBM_NOMMAP;
230             *(int*) optval = flags;
231           }
232         break;
233 \f
234       case GDBM_GETDBNAME:
235         if (!optval || optlen != sizeof (char*))
236           {
237             gdbm_errno = GDBM_OPT_ILLEGAL;
238             return -1;
239           }
240         else
241           {
242             char *p = strdup (dbf->name);
243             if (!p)
244               {
245                 gdbm_errno = GDBM_MALLOC_ERROR;
246                 return -1;
247               }
248             *(char**) optval = p;
249           }
250         break;
251 \f       
252       default:
253         gdbm_errno = GDBM_OPT_ILLEGAL;
254         return -1;
255     }
256
257   return 0;
258 }