rpc_server3: Use fdopen_keepfd()
[Samba.git] / source3 / lib / cleanupdb.c
blob1b3c5a21f1d32a736c75628b0f6608da9b658d30
1 /*
2 Unix SMB/CIFS implementation.
3 Implementation of reliable cleanup events
4 Copyright (C) Ralph Boehme 2016
6 This program 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 of the License, or
9 (at your option) any later version.
11 This program 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.
16 You should have received a copy of the GNU General Public License
17 along with this program. If not, see <http://www.gnu.org/licenses/>.
20 #include "replace.h"
21 #include "system/filesys.h"
22 #include "lib/tdb_wrap/tdb_wrap.h"
23 #include "lib/util/talloc_stack.h"
24 #include "lib/util/debug.h"
25 #include "source3/lib/cleanupdb.h"
26 #include "source3/lib/util_path.h"
28 struct cleanup_key {
29 pid_t pid;
32 struct cleanup_rec {
33 bool unclean;
36 static struct tdb_wrap *cleanup_db(void)
38 static struct tdb_wrap *db;
39 char *db_path = NULL;
40 int tdbflags = TDB_INCOMPATIBLE_HASH | TDB_CLEAR_IF_FIRST |
41 TDB_MUTEX_LOCKING;
43 if (db != NULL) {
44 return db;
47 db_path = lock_path(talloc_tos(), "smbd_cleanupd.tdb");
48 if (db_path == NULL) {
49 return NULL;
52 db = tdb_wrap_open(NULL, db_path, 0, tdbflags,
53 O_CREAT | O_RDWR, 0644);
54 if (db == NULL) {
55 DBG_ERR("Failed to open smbd_cleanupd.tdb\n");
58 TALLOC_FREE(db_path);
59 return db;
62 bool cleanupdb_store_child(const pid_t pid, const bool unclean)
64 struct tdb_wrap *db;
65 struct cleanup_key key = { .pid = pid };
66 struct cleanup_rec rec = { .unclean = unclean };
67 TDB_DATA tdbkey = { .dptr = (uint8_t *)&key, .dsize = sizeof(key) };
68 TDB_DATA tdbdata = { .dptr = (uint8_t *)&rec, .dsize = sizeof(rec) };
69 int result;
71 db = cleanup_db();
72 if (db == NULL) {
73 return false;
76 result = tdb_store(db->tdb, tdbkey, tdbdata, TDB_REPLACE);
77 if (result != 0) {
78 DBG_ERR("tdb_store failed for pid %d\n", (int)pid);
79 return false;
82 return true;
85 bool cleanupdb_delete_child(const pid_t pid)
87 struct tdb_wrap *db;
88 struct cleanup_key key = { .pid = pid };
89 TDB_DATA tdbkey = { .dptr = (uint8_t *)&key, .dsize = sizeof(key) };
90 int result;
92 db = cleanup_db();
93 if (db == NULL) {
94 return false;
97 result = tdb_delete(db->tdb, tdbkey);
98 if (result != 0) {
99 DBG_ERR("tdb_delete failed for pid %d\n", (int)pid);
100 return false;
103 return true;
106 struct cleanup_read_state {
107 int (*fn)(const pid_t pid, const bool cleanup, void *private_data);
108 void *private_data;
111 static int cleanup_traverse_fn(struct tdb_context *tdb,
112 TDB_DATA key, TDB_DATA value,
113 void *private_data)
115 struct cleanup_read_state *state =
116 (struct cleanup_read_state *)private_data;
117 struct cleanup_key ckey;
118 struct cleanup_rec rec;
119 int result;
121 if (key.dsize != sizeof(struct cleanup_key)) {
122 DBG_ERR("Found invalid key length %zu in cleanup.tdb\n",
123 key.dsize);
124 return -1;
126 memcpy(&ckey, key.dptr, sizeof(struct cleanup_key));
128 if (value.dsize != sizeof(struct cleanup_rec)) {
129 DBG_ERR("Found invalid value length %zu in cleanup.tdb\n",
130 value.dsize);
131 return -1;
133 memcpy(&rec, value.dptr, sizeof(struct cleanup_rec));
135 result = state->fn(ckey.pid, rec.unclean, state->private_data);
136 if (result != 0) {
137 return -1;
140 return 0;
143 int cleanupdb_traverse_read(int (*fn)(const pid_t pid,
144 const bool cleanup,
145 void *private_data),
146 void *private_data)
148 struct tdb_wrap *db;
149 struct cleanup_read_state state;
150 int result;
152 db = cleanup_db();
153 if (db == NULL) {
154 return -1;
157 state = (struct cleanup_read_state) {
158 .fn = fn,
159 .private_data = private_data
162 result = tdb_traverse_read(db->tdb, cleanup_traverse_fn, &state);
163 if (result < 0) {
164 DBG_ERR("tdb_traverse_read failed\n");
165 return -1;
168 return result;