6c6d8ed239af9a16768b8f5964341cb43ebff0e4
[samba.git] / source3 / lib / server_id_db_util.c
1 /*
2  * Unix SMB/CIFS implementation.
3  * Utils around server_id_db with more dependencies
4  * Copyright (C) Volker Lendecke 2014
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 "server_id_db_util.h"
22 #include "serverid.h"
23 #include "lib/util/samba_util.h"
24
25 static int server_id_db_check_exclusive(
26         struct server_id_db *db, const char *name,
27         unsigned num_servers, struct server_id *servers);
28
29 int server_id_db_set_exclusive(struct server_id_db *db, const char *name)
30 {
31         int ret;
32         unsigned num_servers;
33         struct server_id *servers;
34
35         ret = server_id_db_add(db, name);
36         if (ret != 0) {
37                 return ret;
38         }
39
40         ret = server_id_db_lookup(db, name, talloc_tos(),
41                                   &num_servers, &servers);
42         if (ret != 0) {
43                 goto done;
44         }
45
46         /*
47          * Remove entries from the server_id_db for processes that have died
48          * and could not clean up. This is racy, as two processes could
49          * simultaneously try to register a name. Both would succeed in the
50          * server_id_db_add call, and both would see their peer active during
51          * the check_exclusive call. Both would get an EEXIST, and nobody
52          * would be able to register itself. But this is okay, as this is
53          * meant to be a cleanup routine, and normally only one daemon should
54          * start up at a time anyway. Getting this "right" would mean we would
55          * have to add locking to server_id_db, or add a dependency on
56          * serverids_exist to server_id_db. Both are too heavy-weight for my
57          * taste.
58          */
59
60         ret = server_id_db_check_exclusive(db, name, num_servers, servers);
61         TALLOC_FREE(servers);
62
63 done:
64         if (ret != 0) {
65                 server_id_db_remove(db, name);
66         }
67         return ret;
68 }
69
70 static int server_id_db_check_exclusive(
71         struct server_id_db *db, const char *name,
72         unsigned num_servers, struct server_id *servers)
73 {
74         struct server_id me = server_id_db_pid(db);
75         unsigned i;
76
77         for (i=0; i<num_servers; i++) {
78                 int ret;
79
80                 if (server_id_same_process(&me, &servers[i])) {
81                         /*
82                          * I am always around ... :-)
83                          */
84                         continue;
85                 }
86
87                 if (serverid_exists(&servers[i])) {
88                         return EEXIST;
89                 }
90
91                 ret = server_id_db_prune_name(db, name, servers[i]);
92                 if (ret != 0) {
93                         return ret;
94                 }
95         }
96
97         return 0;
98 }