Line data Source code
1 : /*
2 : Unix SMB/CIFS implementation.
3 : Implementation of reliable cleanup events
4 : Copyright (C) Ralph Boehme 2016
5 :
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.
10 :
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.
15 :
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/>.
18 : */
19 :
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"
27 :
28 : struct cleanup_key {
29 : pid_t pid;
30 : };
31 :
32 : struct cleanup_rec {
33 : bool unclean;
34 : };
35 :
36 0 : static struct tdb_wrap *cleanup_db(void)
37 : {
38 0 : static struct tdb_wrap *db;
39 0 : char *db_path = NULL;
40 0 : int tdbflags = TDB_INCOMPATIBLE_HASH | TDB_CLEAR_IF_FIRST |
41 : TDB_MUTEX_LOCKING;
42 :
43 0 : if (db != NULL) {
44 0 : return db;
45 : }
46 :
47 0 : db_path = lock_path(talloc_tos(), "smbd_cleanupd.tdb");
48 0 : if (db_path == NULL) {
49 0 : return NULL;
50 : }
51 :
52 0 : db = tdb_wrap_open(NULL, db_path, 0, tdbflags,
53 : O_CREAT | O_RDWR, 0644);
54 0 : if (db == NULL) {
55 0 : DBG_ERR("Failed to open smbd_cleanupd.tdb\n");
56 : }
57 :
58 0 : TALLOC_FREE(db_path);
59 0 : return db;
60 : }
61 :
62 0 : bool cleanupdb_store_child(const pid_t pid, const bool unclean)
63 : {
64 0 : struct tdb_wrap *db;
65 0 : struct cleanup_key key = { .pid = pid };
66 0 : struct cleanup_rec rec = { .unclean = unclean };
67 0 : TDB_DATA tdbkey = { .dptr = (uint8_t *)&key, .dsize = sizeof(key) };
68 0 : TDB_DATA tdbdata = { .dptr = (uint8_t *)&rec, .dsize = sizeof(rec) };
69 0 : int result;
70 :
71 0 : db = cleanup_db();
72 0 : if (db == NULL) {
73 0 : return false;
74 : }
75 :
76 0 : result = tdb_store(db->tdb, tdbkey, tdbdata, TDB_REPLACE);
77 0 : if (result != 0) {
78 0 : DBG_ERR("tdb_store failed for pid %d\n", (int)pid);
79 0 : return false;
80 : }
81 :
82 0 : return true;
83 : }
84 :
85 0 : bool cleanupdb_delete_child(const pid_t pid)
86 : {
87 0 : struct tdb_wrap *db;
88 0 : struct cleanup_key key = { .pid = pid };
89 0 : TDB_DATA tdbkey = { .dptr = (uint8_t *)&key, .dsize = sizeof(key) };
90 0 : int result;
91 :
92 0 : db = cleanup_db();
93 0 : if (db == NULL) {
94 0 : return false;
95 : }
96 :
97 0 : result = tdb_delete(db->tdb, tdbkey);
98 0 : if (result != 0) {
99 0 : DBG_ERR("tdb_delete failed for pid %d\n", (int)pid);
100 0 : return false;
101 : }
102 :
103 0 : return true;
104 : }
105 :
106 : struct cleanup_read_state {
107 : int (*fn)(const pid_t pid, const bool cleanup, void *private_data);
108 : void *private_data;
109 : };
110 :
111 0 : static int cleanup_traverse_fn(struct tdb_context *tdb,
112 : TDB_DATA key, TDB_DATA value,
113 : void *private_data)
114 : {
115 0 : struct cleanup_read_state *state =
116 : (struct cleanup_read_state *)private_data;
117 0 : struct cleanup_key ckey;
118 0 : struct cleanup_rec rec;
119 0 : int result;
120 :
121 0 : if (key.dsize != sizeof(struct cleanup_key)) {
122 0 : DBG_ERR("Found invalid key length %zu in cleanup.tdb\n",
123 : key.dsize);
124 0 : return -1;
125 : }
126 0 : memcpy(&ckey, key.dptr, sizeof(struct cleanup_key));
127 :
128 0 : if (value.dsize != sizeof(struct cleanup_rec)) {
129 0 : DBG_ERR("Found invalid value length %zu in cleanup.tdb\n",
130 : value.dsize);
131 0 : return -1;
132 : }
133 0 : memcpy(&rec, value.dptr, sizeof(struct cleanup_rec));
134 :
135 0 : result = state->fn(ckey.pid, rec.unclean, state->private_data);
136 0 : if (result != 0) {
137 0 : return -1;
138 : }
139 :
140 0 : return 0;
141 : }
142 :
143 0 : int cleanupdb_traverse_read(int (*fn)(const pid_t pid,
144 : const bool cleanup,
145 : void *private_data),
146 : void *private_data)
147 : {
148 0 : struct tdb_wrap *db;
149 0 : struct cleanup_read_state state;
150 0 : int result;
151 :
152 0 : db = cleanup_db();
153 0 : if (db == NULL) {
154 0 : return -1;
155 : }
156 :
157 0 : state = (struct cleanup_read_state) {
158 : .fn = fn,
159 : .private_data = private_data
160 : };
161 :
162 0 : result = tdb_traverse_read(db->tdb, cleanup_traverse_fn, &state);
163 0 : if (result < 0) {
164 0 : DBG_ERR("tdb_traverse_read failed\n");
165 0 : return -1;
166 : }
167 :
168 0 : return result;
169 : }
|