2 Unix SMB/CIFS implementation.
6 Copyright (C) Rusty Russell 2012
8 This program is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 3 of the License, or
11 (at your option) any later version.
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with this program. If not, see <http://www.gnu.org/licenses/>.
22 #include "util_ntdb.h"
23 #include "lib/param/param.h"
25 #include "system/filesys.h"
28 * This handles NTDB_CLEAR_IF_FIRST.
30 * It's a bad idea for new code, but S3 uses it quite a bit.
32 static enum NTDB_ERROR clear_if_first(int fd, void *unused)
34 /* We hold a lock offset 4 always, so we can tell if anyone else is. */
38 fl.l_whence = SEEK_SET;
39 fl.l_start = 4; /* ACTIVE_LOCK */
42 if (fcntl(fd, F_SETLK, &fl) == 0) {
43 /* We must be first ones to open it w/ NTDB_CLEAR_IF_FIRST! */
44 if (ftruncate(fd, 0) != 0) {
49 if (fcntl(fd, F_SETLKW, &fl) != 0) {
55 /* We only need these for the CLEAR_IF_FIRST lock. */
56 static int reacquire_cif_lock(struct ntdb_context *ntdb, bool *fail)
59 union ntdb_attribute cif;
61 cif.openhook.base.attr = NTDB_ATTRIBUTE_OPENHOOK;
62 cif.openhook.base.next = NULL;
64 if (ntdb_get_attribute(ntdb, &cif) != NTDB_SUCCESS
65 || cif.openhook.fn != clear_if_first) {
69 /* We hold a lock offset 4 always, so we can tell if anyone else is. */
71 fl.l_whence = SEEK_SET;
72 fl.l_start = 4; /* ACTIVE_LOCK */
74 if (fcntl(ntdb_fd(ntdb), F_SETLKW, &fl) != 0) {
81 /* You only need this on databases with NTDB_CLEAR_IF_FIRST */
82 int ntdb_reopen(struct ntdb_context *ntdb)
85 return reacquire_cif_lock(ntdb, &unused);
88 /* You only need to do this if you have NTDB_CLEAR_IF_FIRST databases, and
89 * the parent will go away before this child. */
90 int ntdb_reopen_all(void)
94 ntdb_foreach(reacquire_cif_lock, &fail);
100 static void *ntdb_talloc(const void *owner, size_t len, void *priv_data)
102 return talloc_size(owner, len);
105 static void *ntdb_expand(void *old, size_t newlen, void *priv_data)
107 return talloc_realloc_size(NULL, old, newlen);
110 static void ntdb_free(void *old, void *priv_data)
115 static int ntdb_destroy(struct ntdb_context *ntdb)
121 static void ntdb_log(struct ntdb_context *ntdb,
122 enum ntdb_log_level level,
123 enum NTDB_ERROR ecode,
128 const char *name = ntdb_name(ntdb);
131 case NTDB_LOG_USE_ERROR:
135 case NTDB_LOG_WARNING:
142 DEBUG(dl, ("ntdb(%s):%s: %s\n", name ? name : "unnamed",
143 ntdb_errorstr(ecode), message));
146 struct ntdb_context *ntdb_new(TALLOC_CTX *ctx,
147 const char *name, int ntdb_flags,
148 int open_flags, mode_t mode,
149 union ntdb_attribute *attr,
150 struct loadparm_context *lp_ctx)
152 union ntdb_attribute log_attr, alloc_attr, open_attr;
153 struct ntdb_context *ntdb;
155 if (lp_ctx && !lpcfg_use_mmap(lp_ctx)) {
156 ntdb_flags |= NTDB_NOMMAP;
159 /* Great hack for speeding testing! */
160 if (getenv("TDB_NO_FSYNC")) {
161 ntdb_flags |= NTDB_NOSYNC;
164 log_attr.base.next = attr;
165 log_attr.base.attr = NTDB_ATTRIBUTE_LOG;
166 log_attr.log.fn = ntdb_log;
168 alloc_attr.base.next = &log_attr;
169 alloc_attr.base.attr = NTDB_ATTRIBUTE_ALLOCATOR;
170 alloc_attr.alloc.alloc = ntdb_talloc;
171 alloc_attr.alloc.expand = ntdb_expand;
172 alloc_attr.alloc.free = ntdb_free;
174 if (ntdb_flags & NTDB_CLEAR_IF_FIRST) {
175 log_attr.base.next = &open_attr;
176 open_attr.openhook.base.attr = NTDB_ATTRIBUTE_OPENHOOK;
177 open_attr.openhook.base.next = attr;
178 open_attr.openhook.fn = clear_if_first;
179 ntdb_flags &= ~NTDB_CLEAR_IF_FIRST;
182 ntdb = ntdb_open(name, ntdb_flags, open_flags, mode, &alloc_attr);
187 /* We can re-use the tdb's path name for the talloc name */
188 name = ntdb_name(ntdb);
190 talloc_set_name_const(ntdb, name);
192 talloc_set_name_const(ntdb, "unnamed ntdb");
194 talloc_set_destructor(ntdb, ntdb_destroy);
196 return talloc_steal(ctx, ntdb);