smbstatus: Fix an uninitialized variable
[samba.git] / source3 / locking / share_mode_lock.c
1 /*
2    Unix SMB/CIFS implementation.
3    Locking functions
4    Copyright (C) Andrew Tridgell 1992-2000
5    Copyright (C) Jeremy Allison 1992-2006
6    Copyright (C) Volker Lendecke 2005
7
8    This program is free software; you can redistribute it and/or modify
9    it under the terms of the GNU General Public License as published by
10    the Free Software Foundation; either version 3 of the License, or
11    (at your option) any later version.
12
13    This program is distributed in the hope that it will be useful,
14    but WITHOUT ANY WARRANTY; without even the implied warranty of
15    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16    GNU General Public License for more details.
17
18    You should have received a copy of the GNU General Public License
19    along with this program.  If not, see <http://www.gnu.org/licenses/>.
20
21    Revision History:
22
23    12 aug 96: Erik.Devriendt@te6.siemens.be
24    added support for shared memory implementation of share mode locking
25
26    May 1997. Jeremy Allison (jallison@whistle.com). Modified share mode
27    locking to deal with multiple share modes per open file.
28
29    September 1997. Jeremy Allison (jallison@whistle.com). Added oplock
30    support.
31
32    rewritten completely to use new tdb code. Tridge, Dec '99
33
34    Added POSIX locking support. Jeremy Allison (jeremy@valinux.com), Apr. 2000.
35    Added Unix Extensions POSIX locking support. Jeremy Allison Mar 2006.
36 */
37
38 #include "includes.h"
39 #include "system/filesys.h"
40 #include "locking/proto.h"
41 #include "smbd/globals.h"
42 #include "dbwrap/dbwrap.h"
43 #include "dbwrap/dbwrap_open.h"
44 #include "../libcli/security/security.h"
45 #include "serverid.h"
46 #include "messages.h"
47 #include "util_tdb.h"
48 #include "../librpc/gen_ndr/ndr_open_files.h"
49
50 #undef DBGC_CLASS
51 #define DBGC_CLASS DBGC_LOCKING
52
53 #define NO_LOCKING_COUNT (-1)
54
55 /* the locking database handle */
56 static struct db_context *lock_db;
57
58 static bool locking_init_internal(bool read_only)
59 {
60         brl_init(read_only);
61
62         if (lock_db)
63                 return True;
64
65         lock_db = db_open(NULL, lock_path("locking.tdb"),
66                           lp_open_files_db_hash_size(),
67                           TDB_DEFAULT|TDB_VOLATILE|TDB_CLEAR_IF_FIRST|TDB_INCOMPATIBLE_HASH,
68                           read_only?O_RDONLY:O_RDWR|O_CREAT, 0644,
69                           DBWRAP_LOCK_ORDER_1);
70
71         if (!lock_db) {
72                 DEBUG(0,("ERROR: Failed to initialise locking database\n"));
73                 return False;
74         }
75
76         if (!posix_locking_init(read_only))
77                 return False;
78
79         return True;
80 }
81
82 bool locking_init(void)
83 {
84         return locking_init_internal(false);
85 }
86
87 bool locking_init_readonly(void)
88 {
89         return locking_init_internal(true);
90 }
91
92 /*******************************************************************
93  Deinitialize the share_mode management.
94 ******************************************************************/
95
96 bool locking_end(void)
97 {
98         brl_shutdown();
99         TALLOC_FREE(lock_db);
100         return true;
101 }
102
103 /*******************************************************************
104  Form a static locking key for a dev/inode pair.
105 ******************************************************************/
106
107 static TDB_DATA locking_key(const struct file_id *id)
108 {
109         return make_tdb_data((const uint8_t *)id, sizeof(*id));
110 }
111
112 /*******************************************************************
113  Get all share mode entries for a dev/inode pair.
114 ********************************************************************/
115
116 static struct share_mode_data *parse_share_modes(TALLOC_CTX *mem_ctx,
117                                                  const TDB_DATA dbuf)
118 {
119         struct share_mode_data *d;
120         enum ndr_err_code ndr_err;
121         uint32_t i;
122         DATA_BLOB blob;
123
124         d = talloc(mem_ctx, struct share_mode_data);
125         if (d == NULL) {
126                 DEBUG(0, ("talloc failed\n"));
127                 goto fail;
128         }
129
130         blob.data = dbuf.dptr;
131         blob.length = dbuf.dsize;
132
133         ndr_err = ndr_pull_struct_blob(
134                 &blob, d, d, (ndr_pull_flags_fn_t)ndr_pull_share_mode_data);
135         if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
136                 DEBUG(1, ("ndr_pull_share_mode_lock failed: %s\n",
137                           ndr_errstr(ndr_err)));
138                 goto fail;
139         }
140
141         /*
142          * Initialize the values that are [skip] in the idl. The NDR code does
143          * not initialize them.
144          */
145
146         for (i=0; i<d->num_share_modes; i++) {
147                 d->share_modes[i].stale = false;
148         }
149         d->modified = false;
150         d->fresh = false;
151
152         if (DEBUGLEVEL >= 10) {
153                 DEBUG(10, ("parse_share_modes:\n"));
154                 NDR_PRINT_DEBUG(share_mode_data, d);
155         }
156
157         return d;
158 fail:
159         TALLOC_FREE(d);
160         return NULL;
161 }
162
163 /*******************************************************************
164  Create a storable data blob from a modified share_mode_data struct.
165 ********************************************************************/
166
167 static TDB_DATA unparse_share_modes(struct share_mode_data *d)
168 {
169         DATA_BLOB blob;
170         enum ndr_err_code ndr_err;
171         uint32_t i;
172
173         if (DEBUGLEVEL >= 10) {
174                 DEBUG(10, ("unparse_share_modes:\n"));
175                 NDR_PRINT_DEBUG(share_mode_data, d);
176         }
177
178         i = 0;
179         while (i < d->num_share_modes) {
180                 if (d->share_modes[i].stale) {
181                         /*
182                          * Remove the stale entries before storing
183                          */
184                         struct share_mode_entry *m = d->share_modes;
185                         m[i] = m[d->num_share_modes-1];
186                         d->num_share_modes -= 1;
187                 } else {
188                         i += 1;
189                 }
190         }
191
192         if (d->num_share_modes == 0) {
193                 DEBUG(10, ("No used share mode found\n"));
194                 return make_tdb_data(NULL, 0);
195         }
196
197         ndr_err = ndr_push_struct_blob(
198                 &blob, d, d, (ndr_push_flags_fn_t)ndr_push_share_mode_data);
199         if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
200                 smb_panic("ndr_push_share_mode_lock failed");
201         }
202
203         return make_tdb_data(blob.data, blob.length);
204 }
205
206 /*******************************************************************
207  If modified, store the share_mode_data back into the database.
208 ********************************************************************/
209
210 static int share_mode_data_destructor(struct share_mode_data *d)
211 {
212         NTSTATUS status;
213         TDB_DATA data;
214
215         if (!d->modified) {
216                 return 0;
217         }
218
219         data = unparse_share_modes(d);
220
221         if (data.dptr == NULL) {
222                 if (!d->fresh) {
223                         /* There has been an entry before, delete it */
224
225                         status = dbwrap_record_delete(d->record);
226                         if (!NT_STATUS_IS_OK(status)) {
227                                 char *errmsg;
228
229                                 DEBUG(0, ("delete_rec returned %s\n",
230                                           nt_errstr(status)));
231
232                                 if (asprintf(&errmsg, "could not delete share "
233                                              "entry: %s\n",
234                                              nt_errstr(status)) == -1) {
235                                         smb_panic("could not delete share"
236                                                   "entry");
237                                 }
238                                 smb_panic(errmsg);
239                         }
240                 }
241                 goto done;
242         }
243
244         status = dbwrap_record_store(d->record, data, TDB_REPLACE);
245         if (!NT_STATUS_IS_OK(status)) {
246                 char *errmsg;
247
248                 DEBUG(0, ("store returned %s\n", nt_errstr(status)));
249
250                 if (asprintf(&errmsg, "could not store share mode entry: %s",
251                              nt_errstr(status)) == -1) {
252                         smb_panic("could not store share mode entry");
253                 }
254                 smb_panic(errmsg);
255         }
256
257  done:
258
259         return 0;
260 }
261
262 /*******************************************************************
263  Allocate a new share_mode_data struct, mark it unmodified.
264  fresh is set to note that currently there is no database entry.
265 ********************************************************************/
266
267 static struct share_mode_data *fresh_share_mode_lock(
268         TALLOC_CTX *mem_ctx, const char *servicepath,
269         const struct smb_filename *smb_fname,
270         const struct timespec *old_write_time)
271 {
272         struct share_mode_data *d;
273
274         if ((servicepath == NULL) || (smb_fname == NULL) ||
275             (old_write_time == NULL)) {
276                 return NULL;
277         }
278
279         d = talloc_zero(mem_ctx, struct share_mode_data);
280         if (d == NULL) {
281                 goto fail;
282         }
283         d->base_name = talloc_strdup(d, smb_fname->base_name);
284         if (d->base_name == NULL) {
285                 goto fail;
286         }
287         if (smb_fname->stream_name != NULL) {
288                 d->stream_name = talloc_strdup(d, smb_fname->stream_name);
289                 if (d->stream_name == NULL) {
290                         goto fail;
291                 }
292         }
293         d->servicepath = talloc_strdup(d, servicepath);
294         if (d->servicepath == NULL) {
295                 goto fail;
296         }
297         d->old_write_time = *old_write_time;
298         d->modified = false;
299         d->fresh = true;
300         return d;
301 fail:
302         DEBUG(0, ("talloc failed\n"));
303         TALLOC_FREE(d);
304         return NULL;
305 }
306
307 /*******************************************************************
308  Either fetch a share mode from the database, or allocate a fresh
309  one if the record doesn't exist.
310 ********************************************************************/
311
312 static struct share_mode_lock *get_share_mode_lock_internal(
313         TALLOC_CTX *mem_ctx, struct file_id id,
314         const char *servicepath, const struct smb_filename *smb_fname,
315         const struct timespec *old_write_time)
316 {
317         struct share_mode_lock *lck;
318         struct share_mode_data *d;
319         struct db_record *rec;
320         TDB_DATA key = locking_key(&id);
321         TDB_DATA value;
322
323         rec = dbwrap_fetch_locked(lock_db, mem_ctx, key);
324         if (rec == NULL) {
325                 DEBUG(3, ("Could not lock share entry\n"));
326                 return NULL;
327         }
328
329         value = dbwrap_record_get_value(rec);
330
331         if (value.dptr == NULL) {
332                 d = fresh_share_mode_lock(mem_ctx, servicepath, smb_fname,
333                                           old_write_time);
334         } else {
335                 d = parse_share_modes(mem_ctx, value);
336         }
337
338         if (d == NULL) {
339                 DEBUG(5, ("get_share_mode_lock_internal: "
340                         "Could not get share mode lock\n"));
341                 TALLOC_FREE(rec);
342                 return NULL;
343         }
344         d->id = id;
345         d->record = talloc_move(d, &rec);
346         talloc_set_destructor(d, share_mode_data_destructor);
347
348         lck = talloc(mem_ctx, struct share_mode_lock);
349         if (lck == NULL) {
350                 DEBUG(1, ("talloc failed\n"));
351                 TALLOC_FREE(d);
352                 return NULL;
353         }
354         lck->data = talloc_move(lck, &d);
355         return lck;
356 }
357
358 /*
359  * We can only ever have one share mode locked. Users of
360  * get_share_mode_lock never see this, it will be refcounted by
361  * talloc_reference.
362  */
363 static struct share_mode_lock *the_lock;
364
365 static int the_lock_destructor(struct share_mode_lock *l)
366 {
367         the_lock = NULL;
368         return 0;
369 }
370
371 /*******************************************************************
372  Get a share_mode_lock, Reference counted to allow nested calls.
373 ********************************************************************/
374
375 struct share_mode_lock *get_share_mode_lock(
376         TALLOC_CTX *mem_ctx,
377         struct file_id id,
378         const char *servicepath,
379         const struct smb_filename *smb_fname,
380         const struct timespec *old_write_time)
381 {
382         TALLOC_CTX *frame = talloc_stackframe();
383
384         struct share_mode_lock *lck;
385
386         if (the_lock == NULL) {
387                 the_lock = get_share_mode_lock_internal(
388                         frame, id, servicepath, smb_fname, old_write_time);
389                 if (the_lock == NULL) {
390                         goto fail;
391                 }
392                 talloc_set_destructor(the_lock, the_lock_destructor);
393         }
394         if (!file_id_equal(&the_lock->data->id, &id)) {
395                 DEBUG(1, ("Can not lock two share modes simultaneously\n"));
396                 goto fail;
397         }
398         lck = talloc(mem_ctx, struct share_mode_lock);
399         if (lck == NULL) {
400                 DEBUG(1, ("talloc failed\n"));
401                 goto fail;
402         }
403         if (talloc_reference(lck, the_lock) == NULL) {
404                 DEBUG(1, ("talloc_reference failed\n"));
405                 goto fail;
406         }
407         lck->data = the_lock->data;
408         TALLOC_FREE(frame);
409         return lck;
410 fail:
411         TALLOC_FREE(frame);
412         return NULL;
413 }
414
415 /*******************************************************************
416  Get a share_mode_lock without locking the database or reference
417  counting. Used by smbstatus to display existing share modes.
418 ********************************************************************/
419
420 struct share_mode_lock *fetch_share_mode_unlocked(TALLOC_CTX *mem_ctx,
421                                                   struct file_id id)
422 {
423         struct share_mode_lock *lck;
424         TDB_DATA key = locking_key(&id);
425         TDB_DATA data;
426         NTSTATUS status;
427
428         status = dbwrap_fetch(lock_db, talloc_tos(), key, &data);
429         if (!NT_STATUS_IS_OK(status)) {
430                 DEBUG(3, ("Could not fetch share entry\n"));
431                 return NULL;
432         }
433         if (data.dptr == NULL) {
434                 return NULL;
435         }
436         lck = talloc(mem_ctx, struct share_mode_lock);
437         if (lck == NULL) {
438                 TALLOC_FREE(data.dptr);
439                 return NULL;
440         }
441         lck->data = parse_share_modes(lck, data);
442         TALLOC_FREE(data.dptr);
443         if (lck->data == NULL) {
444                 TALLOC_FREE(lck);
445                 return NULL;
446         }
447         return lck;
448 }
449
450 struct forall_state {
451         void (*fn)(const struct share_mode_entry *entry,
452                    const char *sharepath,
453                    const char *fname,
454                    void *private_data);
455         void *private_data;
456 };
457
458 static int traverse_fn(struct db_record *rec, void *_state)
459 {
460         struct forall_state *state = (struct forall_state *)_state;
461         uint32_t i;
462         TDB_DATA key;
463         TDB_DATA value;
464         DATA_BLOB blob;
465         enum ndr_err_code ndr_err;
466         struct share_mode_data *d;
467
468         key = dbwrap_record_get_key(rec);
469         value = dbwrap_record_get_value(rec);
470
471         /* Ensure this is a locking_key record. */
472         if (key.dsize != sizeof(struct file_id))
473                 return 0;
474
475         d = talloc(talloc_tos(), struct share_mode_data);
476         if (d == NULL) {
477                 return 0;
478         }
479
480         blob.data = value.dptr;
481         blob.length = value.dsize;
482
483         ndr_err = ndr_pull_struct_blob(
484                 &blob, d, d, (ndr_pull_flags_fn_t)ndr_pull_share_mode_data);
485         if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
486                 DEBUG(1, ("ndr_pull_share_mode_lock failed\n"));
487                 return 0;
488         }
489         for (i=0; i<d->num_share_modes; i++) {
490                 d->share_modes[i].stale = false; /* [skip] in idl */
491                 state->fn(&d->share_modes[i],
492                           d->servicepath, d->base_name,
493                           state->private_data);
494         }
495         TALLOC_FREE(d);
496
497         return 0;
498 }
499
500 /*******************************************************************
501  Call the specified function on each entry under management by the
502  share mode system.
503 ********************************************************************/
504
505 int share_mode_forall(void (*fn)(const struct share_mode_entry *, const char *,
506                                  const char *, void *),
507                       void *private_data)
508 {
509         struct forall_state state;
510         NTSTATUS status;
511         int count;
512
513         if (lock_db == NULL)
514                 return 0;
515
516         state.fn = fn;
517         state.private_data = private_data;
518
519         status = dbwrap_traverse_read(lock_db, traverse_fn, (void *)&state,
520                                       &count);
521
522         if (!NT_STATUS_IS_OK(status)) {
523                 return -1;
524         } else {
525                 return count;
526         }
527 }
528
529 bool share_mode_cleanup_disconnected(struct file_id fid,
530                                      uint64_t open_persistent_id)
531 {
532         bool ret = false;
533         TALLOC_CTX *frame = talloc_stackframe();
534         unsigned n;
535         struct share_mode_data *data;
536         struct share_mode_lock *lck;
537         bool ok;
538
539         lck = get_existing_share_mode_lock(frame, fid);
540         if (lck == NULL) {
541                 DEBUG(5, ("share_mode_cleanup_disconnected: "
542                           "Could not fetch share mode entry for %s\n",
543                           file_id_string(frame, &fid)));
544                 goto done;
545         }
546         data = lck->data;
547
548         for (n=0; n < data->num_share_modes; n++) {
549                 struct share_mode_entry *entry = &data->share_modes[n];
550
551                 if (!server_id_is_disconnected(&entry->pid)) {
552                         DEBUG(5, ("share_mode_cleanup_disconnected: "
553                                   "file (file-id='%s', servicepath='%s', "
554                                   "base_name='%s%s%s') "
555                                   "is used by server %s ==> do not cleanup\n",
556                                   file_id_string(frame, &fid),
557                                   data->servicepath,
558                                   data->base_name,
559                                   (data->stream_name == NULL)
560                                   ? "" : "', stream_name='",
561                                   (data->stream_name == NULL)
562                                   ? "" : data->stream_name,
563                                   server_id_str(frame, &entry->pid)));
564                         goto done;
565                 }
566                 if (open_persistent_id != entry->share_file_id) {
567                         DEBUG(5, ("share_mode_cleanup_disconnected: "
568                                   "entry for file "
569                                   "(file-id='%s', servicepath='%s', "
570                                   "base_name='%s%s%s') "
571                                   "has share_file_id %llu but expected %llu"
572                                   "==> do not cleanup\n",
573                                   file_id_string(frame, &fid),
574                                   data->servicepath,
575                                   data->base_name,
576                                   (data->stream_name == NULL)
577                                   ? "" : "', stream_name='",
578                                   (data->stream_name == NULL)
579                                   ? "" : data->stream_name,
580                                   (unsigned long long)entry->share_file_id,
581                                   (unsigned long long)open_persistent_id));
582                         goto done;
583                 }
584         }
585
586         ok = brl_cleanup_disconnected(fid, open_persistent_id);
587         if (!ok) {
588                 DEBUG(10, ("share_mode_cleanup_disconnected: "
589                            "failed to clean up byte range locks associated "
590                            "with file (file-id='%s', servicepath='%s', "
591                            "base_name='%s%s%s') and open_persistent_id %llu "
592                            "==> do not cleanup\n",
593                            file_id_string(frame, &fid),
594                            data->servicepath,
595                            data->base_name,
596                            (data->stream_name == NULL)
597                            ? "" : "', stream_name='",
598                            (data->stream_name == NULL)
599                            ? "" : data->stream_name,
600                            (unsigned long long)open_persistent_id));
601                 goto done;
602         }
603
604         DEBUG(10, ("share_mode_cleanup_disconnected: "
605                    "cleaning up %u entries for file "
606                    "(file-id='%s', servicepath='%s', "
607                    "base_name='%s%s%s') "
608                    "from open_persistent_id %llu\n",
609                    data->num_share_modes,
610                    file_id_string(frame, &fid),
611                    data->servicepath,
612                    data->base_name,
613                    (data->stream_name == NULL)
614                    ? "" : "', stream_name='",
615                    (data->stream_name == NULL)
616                    ? "" : data->stream_name,
617                    (unsigned long long)open_persistent_id));
618
619         data->num_share_modes = 0;
620         data->modified = true;
621
622         ret = true;
623 done:
624         talloc_free(frame);
625         return ret;
626 }