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