f30ed331be8497c200fe563b63e4c4d21b97d7e9
[ira/wip.git] / source3 / utils / net_g_lock.c
1 /*
2  * Samba Unix/Linux SMB client library
3  * Interface to the g_lock facility
4  * Copyright (C) Volker Lendecke 2009
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 "includes.h"
21 #include "net.h"
22 #include "g_lock.h"
23
24 static bool net_g_lock_init(TALLOC_CTX *mem_ctx,
25                             struct tevent_context **pev,
26                             struct messaging_context **pmsg,
27                             struct g_lock_ctx **pg_ctx)
28 {
29         struct tevent_context *ev = NULL;
30         struct messaging_context *msg = NULL;
31         struct g_lock_ctx *g_ctx = NULL;
32
33         ev = tevent_context_init(talloc_tos());
34         if (ev == NULL) {
35                 d_fprintf(stderr, "ERROR: could not init event context\n");
36                 goto fail;
37         }
38         msg = messaging_init(talloc_tos(), server_id_self(), ev);
39         if (msg == NULL) {
40                 d_fprintf(stderr, "ERROR: could not init messaging context\n");
41                 goto fail;
42         }
43         g_ctx = g_lock_ctx_init(talloc_tos(), msg);
44         if (g_ctx == NULL) {
45                 d_fprintf(stderr, "ERROR: could not init g_lock context\n");
46                 goto fail;
47         }
48
49         *pev = ev;
50         *pmsg = msg;
51         *pg_ctx = g_ctx;
52         return true;
53 fail:
54         TALLOC_FREE(g_ctx);
55         TALLOC_FREE(msg);
56         TALLOC_FREE(ev);
57         return false;
58 }
59
60
61 static int net_g_lock_do(struct net_context *c, int argc, const char **argv)
62 {
63         struct tevent_context *ev = NULL;
64         struct messaging_context *msg = NULL;
65         struct g_lock_ctx *g_ctx = NULL;
66         const char *name, *cmd;
67         int timeout, res;
68         bool locked = false;
69         NTSTATUS status;
70         int ret = -1;
71
72         if (argc != 3) {
73                 d_printf("Usage: net g_lock do <lockname> <timeout> "
74                          "<command>\n");
75                 return -1;
76         }
77         name = argv[0];
78         timeout = atoi(argv[1]);
79         cmd = argv[2];
80
81         if (!net_g_lock_init(talloc_tos(), &ev, &msg, &g_ctx)) {
82                 goto done;
83         }
84
85         status = g_lock_lock(g_ctx, name, G_LOCK_WRITE,
86                              timeval_set(timeout / 1000, timeout % 1000));
87         if (!NT_STATUS_IS_OK(status)) {
88                 d_fprintf(stderr, "ERROR: Could not get lock: %s\n",
89                           nt_errstr(status));
90                 goto done;
91         }
92         locked = true;
93
94         res = system(cmd);
95
96         if (res == -1) {
97                 d_fprintf(stderr, "ERROR: system() returned %s\n",
98                           strerror(errno));
99                 goto done;
100         }
101         d_fprintf(stderr, "command returned %d\n", res);
102
103         ret = 0;
104
105 done:
106         if (locked) {
107                 g_lock_unlock(g_ctx, name);
108         }
109         TALLOC_FREE(g_ctx);
110         TALLOC_FREE(msg);
111         TALLOC_FREE(ev);
112         return ret;
113 }
114
115 static int net_g_lock_dump_fn(struct server_id pid, enum g_lock_type lock_type,
116                               void *private_data)
117 {
118         char *pidstr;
119
120         pidstr = procid_str(talloc_tos(), &pid);
121         d_printf("%s: %s (%s)\n", pidstr,
122                  (lock_type & 1) ? "WRITE" : "READ",
123                  (lock_type & G_LOCK_PENDING) ? "pending" : "holder");
124         TALLOC_FREE(pidstr);
125         return 0;
126 }
127
128 static int net_g_lock_dump(struct net_context *c, int argc, const char **argv)
129 {
130         struct tevent_context *ev = NULL;
131         struct messaging_context *msg = NULL;
132         struct g_lock_ctx *g_ctx = NULL;
133         NTSTATUS status;
134         int ret = -1;
135
136         if (argc != 1) {
137                 d_printf("Usage: net g_lock dump <lockname>\n");
138                 return -1;
139         }
140
141         if (!net_g_lock_init(talloc_tos(), &ev, &msg, &g_ctx)) {
142                 goto done;
143         }
144
145         status = g_lock_dump(g_ctx, argv[0], net_g_lock_dump_fn, NULL);
146
147         ret = 0;
148 done:
149         TALLOC_FREE(g_ctx);
150         TALLOC_FREE(msg);
151         TALLOC_FREE(ev);
152         return ret;
153 }
154
155 static int net_g_lock_locks_fn(const char *name, void *private_data)
156 {
157         d_printf("%s\n", name);
158         return 0;
159 }
160
161 static int net_g_lock_locks(struct net_context *c, int argc, const char **argv)
162 {
163         struct tevent_context *ev = NULL;
164         struct messaging_context *msg = NULL;
165         struct g_lock_ctx *g_ctx = NULL;
166         int ret = -1;
167
168         if (argc != 0) {
169                 d_printf("Usage: net g_lock locks\n");
170                 return -1;
171         }
172
173         if (!net_g_lock_init(talloc_tos(), &ev, &msg, &g_ctx)) {
174                 goto done;
175         }
176
177         ret = g_lock_locks(g_ctx, net_g_lock_locks_fn, NULL);
178 done:
179         TALLOC_FREE(g_ctx);
180         TALLOC_FREE(msg);
181         TALLOC_FREE(ev);
182         return ret;
183 }
184
185 int net_g_lock(struct net_context *c, int argc, const char **argv)
186 {
187         struct functable func[] = {
188                 {
189                         "do",
190                         net_g_lock_do,
191                         NET_TRANSPORT_LOCAL,
192                         N_("Execute a shell command under a lock"),
193                         N_("net g_lock do <lock name> <timeout> <command>\n")
194                 },
195                 {
196                         "locks",
197                         net_g_lock_locks,
198                         NET_TRANSPORT_LOCAL,
199                         N_("List all locknames"),
200                         N_("net g_lock locks\n")
201                 },
202                 {
203                         "dump",
204                         net_g_lock_dump,
205                         NET_TRANSPORT_LOCAL,
206                         N_("Dump a g_lock locking table"),
207                         N_("net g_lock dump <lock name>\n")
208                 },
209                 {NULL, NULL, 0, NULL, NULL}
210         };
211
212         return net_run_function(c, argc, argv, "net g_lock", func);
213 }