s4:torture: send the TCONX_FLAG_EXTENDED_RESPONSE flag
[Samba/gebeck_regimport.git] / source4 / ntvfs / common / opendb_tdb.c
blobed8fb9032a048dd65a790bd5810d54e556ddb5ed
1 /*
2 Unix SMB/CIFS implementation.
4 Copyright (C) Andrew Tridgell 2004
5 Copyright (C) Stefan Metzmacher 2008
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 3 of the License, or
10 (at your option) any later version.
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with this program. If not, see <http://www.gnu.org/licenses/>.
22 this is the open files database, tdb backend. It implements shared
23 storage of what files are open between server instances, and
24 implements the rules of shared access to files.
26 The caller needs to provide a file_key, which specifies what file
27 they are talking about. This needs to be a unique key across all
28 filesystems, and is usually implemented in terms of a device/inode
29 pair.
31 Before any operations can be performed the caller needs to establish
32 a lock on the record associated with file_key. That is done by
33 calling odb_lock(). The caller releases this lock by calling
34 talloc_free() on the returned handle.
36 All other operations on a record are done by passing the odb_lock()
37 handle back to this module. The handle contains internal
38 information about what file_key is being operated on.
41 #include "includes.h"
42 #include "system/filesys.h"
43 #include "../lib/tdb_compat/tdb_compat.h"
44 #include "messaging/messaging.h"
45 #include "lib/tdb_wrap/tdb_wrap.h"
46 #include "lib/messaging/irpc.h"
47 #include "librpc/gen_ndr/ndr_opendb.h"
48 #include "ntvfs/ntvfs.h"
49 #include "ntvfs/common/ntvfs_common.h"
50 #include "cluster/cluster.h"
51 #include "param/param.h"
52 #include "ntvfs/sysdep/sys_lease.h"
54 struct odb_context {
55 struct tdb_wrap *w;
56 struct ntvfs_context *ntvfs_ctx;
57 bool oplocks;
58 struct sys_lease_context *lease_ctx;
62 an odb lock handle. You must obtain one of these using odb_lock() before doing
63 any other operations.
65 struct odb_lock {
66 struct odb_context *odb;
67 TDB_DATA key;
69 struct opendb_file file;
71 struct {
72 struct opendb_entry *e;
73 bool attrs_only;
74 } can_open;
77 static NTSTATUS odb_oplock_break_send(struct imessaging_context *msg_ctx,
78 struct opendb_entry *e,
79 uint8_t level);
82 Open up the openfiles.tdb database. Close it down using
83 talloc_free(). We need the imessaging_ctx to allow for pending open
84 notifications.
86 static struct odb_context *odb_tdb_init(TALLOC_CTX *mem_ctx,
87 struct ntvfs_context *ntvfs_ctx)
89 struct odb_context *odb;
91 odb = talloc(mem_ctx, struct odb_context);
92 if (odb == NULL) {
93 return NULL;
96 odb->w = cluster_tdb_tmp_open(odb, ntvfs_ctx->lp_ctx, "openfiles.tdb", TDB_DEFAULT);
97 if (odb->w == NULL) {
98 talloc_free(odb);
99 return NULL;
102 odb->ntvfs_ctx = ntvfs_ctx;
104 odb->oplocks = share_bool_option(ntvfs_ctx->config, SHARE_OPLOCKS, SHARE_OPLOCKS_DEFAULT);
106 odb->lease_ctx = sys_lease_context_create(ntvfs_ctx->config, odb,
107 ntvfs_ctx->event_ctx,
108 ntvfs_ctx->msg_ctx,
109 odb_oplock_break_send);
111 return odb;
115 destroy a lock on the database
117 static int odb_lock_destructor(struct odb_lock *lck)
119 tdb_chainunlock(lck->odb->w->tdb, lck->key);
120 return 0;
123 static NTSTATUS odb_pull_record(struct odb_lock *lck, struct opendb_file *file);
126 get a lock on a entry in the odb. This call returns a lock handle,
127 which the caller should unlock using talloc_free().
129 static struct odb_lock *odb_tdb_lock(TALLOC_CTX *mem_ctx,
130 struct odb_context *odb, DATA_BLOB *file_key)
132 struct odb_lock *lck;
133 NTSTATUS status;
135 lck = talloc(mem_ctx, struct odb_lock);
136 if (lck == NULL) {
137 return NULL;
140 lck->odb = talloc_reference(lck, odb);
141 lck->key.dptr = talloc_memdup(lck, file_key->data, file_key->length);
142 lck->key.dsize = file_key->length;
143 if (lck->key.dptr == NULL) {
144 talloc_free(lck);
145 return NULL;
148 if (tdb_chainlock(odb->w->tdb, lck->key) != 0) {
149 talloc_free(lck);
150 return NULL;
153 ZERO_STRUCT(lck->can_open);
155 talloc_set_destructor(lck, odb_lock_destructor);
157 status = odb_pull_record(lck, &lck->file);
158 if (NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
159 /* initialise a blank structure */
160 ZERO_STRUCT(lck->file);
161 } else if (!NT_STATUS_IS_OK(status)) {
162 talloc_free(lck);
163 return NULL;
166 return lck;
169 static DATA_BLOB odb_tdb_get_key(TALLOC_CTX *mem_ctx, struct odb_lock *lck)
171 return data_blob_talloc(mem_ctx, lck->key.dptr, lck->key.dsize);
176 determine if two odb_entry structures conflict
178 return NT_STATUS_OK on no conflict
180 static NTSTATUS share_conflict(struct opendb_entry *e1,
181 uint32_t stream_id,
182 uint32_t share_access,
183 uint32_t access_mask)
185 /* if either open involves no read.write or delete access then
186 it can't conflict */
187 if (!(e1->access_mask & (SEC_FILE_WRITE_DATA |
188 SEC_FILE_APPEND_DATA |
189 SEC_FILE_READ_DATA |
190 SEC_FILE_EXECUTE |
191 SEC_STD_DELETE))) {
192 return NT_STATUS_OK;
194 if (!(access_mask & (SEC_FILE_WRITE_DATA |
195 SEC_FILE_APPEND_DATA |
196 SEC_FILE_READ_DATA |
197 SEC_FILE_EXECUTE |
198 SEC_STD_DELETE))) {
199 return NT_STATUS_OK;
202 /* data IO access masks. This is skipped if the two open handles
203 are on different streams (as in that case the masks don't
204 interact) */
205 if (e1->stream_id != stream_id) {
206 return NT_STATUS_OK;
209 #define CHECK_MASK(am, right, sa, share) \
210 if (((am) & (right)) && !((sa) & (share))) return NT_STATUS_SHARING_VIOLATION
212 CHECK_MASK(e1->access_mask, SEC_FILE_WRITE_DATA | SEC_FILE_APPEND_DATA,
213 share_access, NTCREATEX_SHARE_ACCESS_WRITE);
214 CHECK_MASK(access_mask, SEC_FILE_WRITE_DATA | SEC_FILE_APPEND_DATA,
215 e1->share_access, NTCREATEX_SHARE_ACCESS_WRITE);
217 CHECK_MASK(e1->access_mask, SEC_FILE_READ_DATA | SEC_FILE_EXECUTE,
218 share_access, NTCREATEX_SHARE_ACCESS_READ);
219 CHECK_MASK(access_mask, SEC_FILE_READ_DATA | SEC_FILE_EXECUTE,
220 e1->share_access, NTCREATEX_SHARE_ACCESS_READ);
222 CHECK_MASK(e1->access_mask, SEC_STD_DELETE,
223 share_access, NTCREATEX_SHARE_ACCESS_DELETE);
224 CHECK_MASK(access_mask, SEC_STD_DELETE,
225 e1->share_access, NTCREATEX_SHARE_ACCESS_DELETE);
226 #undef CHECK_MASK
227 return NT_STATUS_OK;
231 pull a record, translating from the db format to the opendb_file structure defined
232 in opendb.idl
234 static NTSTATUS odb_pull_record(struct odb_lock *lck, struct opendb_file *file)
236 struct odb_context *odb = lck->odb;
237 TDB_DATA dbuf;
238 DATA_BLOB blob;
239 enum ndr_err_code ndr_err;
241 dbuf = tdb_fetch_compat(odb->w->tdb, lck->key);
242 if (dbuf.dptr == NULL) {
243 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
246 blob.data = dbuf.dptr;
247 blob.length = dbuf.dsize;
249 ndr_err = ndr_pull_struct_blob(&blob, lck, file, (ndr_pull_flags_fn_t)ndr_pull_opendb_file);
250 free(dbuf.dptr);
251 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
252 return ndr_map_error2ntstatus(ndr_err);
255 return NT_STATUS_OK;
259 push a record, translating from the opendb_file structure defined in opendb.idl
261 static NTSTATUS odb_push_record(struct odb_lock *lck, struct opendb_file *file)
263 struct odb_context *odb = lck->odb;
264 TDB_DATA dbuf;
265 DATA_BLOB blob;
266 enum ndr_err_code ndr_err;
267 int ret;
269 if (file->num_entries == 0) {
270 ret = tdb_delete(odb->w->tdb, lck->key);
271 if (ret != 0) {
272 return NT_STATUS_INTERNAL_DB_CORRUPTION;
274 return NT_STATUS_OK;
277 ndr_err = ndr_push_struct_blob(&blob, lck, file, (ndr_push_flags_fn_t)ndr_push_opendb_file);
278 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
279 return ndr_map_error2ntstatus(ndr_err);
282 dbuf.dptr = blob.data;
283 dbuf.dsize = blob.length;
285 ret = tdb_store(odb->w->tdb, lck->key, dbuf, TDB_REPLACE);
286 data_blob_free(&blob);
287 if (ret != 0) {
288 return NT_STATUS_INTERNAL_DB_CORRUPTION;
291 return NT_STATUS_OK;
295 send an oplock break to a client
297 static NTSTATUS odb_oplock_break_send(struct imessaging_context *msg_ctx,
298 struct opendb_entry *e,
299 uint8_t level)
301 NTSTATUS status;
302 struct opendb_oplock_break op_break;
303 DATA_BLOB blob;
305 ZERO_STRUCT(op_break);
307 /* tell the server handling this open file about the need to send the client
308 a break */
309 op_break.file_handle = e->file_handle;
310 op_break.level = level;
312 blob = data_blob_const(&op_break, sizeof(op_break));
314 status = imessaging_send(msg_ctx, e->server,
315 MSG_NTVFS_OPLOCK_BREAK, &blob);
316 NT_STATUS_NOT_OK_RETURN(status);
318 return NT_STATUS_OK;
321 static bool access_attributes_only(uint32_t access_mask,
322 uint32_t open_disposition,
323 bool break_to_none)
325 switch (open_disposition) {
326 case NTCREATEX_DISP_SUPERSEDE:
327 case NTCREATEX_DISP_OVERWRITE_IF:
328 case NTCREATEX_DISP_OVERWRITE:
329 return false;
330 default:
331 break;
334 if (break_to_none) {
335 return false;
338 #define CHECK_MASK(m,g) ((m) && (((m) & ~(g))==0) && (((m) & (g)) != 0))
339 return CHECK_MASK(access_mask,
340 SEC_STD_SYNCHRONIZE |
341 SEC_FILE_READ_ATTRIBUTE |
342 SEC_FILE_WRITE_ATTRIBUTE);
343 #undef CHECK_MASK
346 static NTSTATUS odb_tdb_open_can_internal(struct odb_context *odb,
347 const struct opendb_file *file,
348 uint32_t stream_id, uint32_t share_access,
349 uint32_t access_mask, bool delete_on_close,
350 uint32_t open_disposition, bool break_to_none,
351 bool *_attrs_only)
353 NTSTATUS status;
354 uint32_t i;
355 bool attrs_only = false;
357 /* see if anyone has an oplock, which we need to break */
358 for (i=0;i<file->num_entries;i++) {
359 if (file->entries[i].oplock_level == OPLOCK_BATCH) {
360 bool oplock_return = OPLOCK_BREAK_TO_LEVEL_II;
361 /* if this is an attribute only access
362 * it doesn't conflict with a BACTCH oplock
363 * but we'll not grant the oplock below
365 attrs_only = access_attributes_only(access_mask,
366 open_disposition,
367 break_to_none);
368 if (attrs_only) {
369 break;
371 /* a batch oplock caches close calls, which
372 means the client application might have
373 already closed the file. We have to allow
374 this close to propogate by sending a oplock
375 break request and suspending this call
376 until the break is acknowledged or the file
377 is closed */
378 if (break_to_none ||
379 !file->entries[i].allow_level_II_oplock) {
380 oplock_return = OPLOCK_BREAK_TO_NONE;
382 odb_oplock_break_send(odb->ntvfs_ctx->msg_ctx,
383 &file->entries[i],
384 oplock_return);
385 return NT_STATUS_OPLOCK_NOT_GRANTED;
389 if (file->delete_on_close) {
390 /* while delete on close is set, no new opens are allowed */
391 return NT_STATUS_DELETE_PENDING;
394 if (file->num_entries != 0 && delete_on_close) {
395 return NT_STATUS_SHARING_VIOLATION;
398 /* check for sharing violations */
399 for (i=0;i<file->num_entries;i++) {
400 status = share_conflict(&file->entries[i], stream_id,
401 share_access, access_mask);
402 NT_STATUS_NOT_OK_RETURN(status);
405 /* we now know the open could succeed, but we need to check
406 for any exclusive oplocks. We can't grant a second open
407 till these are broken. Note that we check for batch oplocks
408 before checking for sharing violations, and check for
409 exclusive oplocks afterwards. */
410 for (i=0;i<file->num_entries;i++) {
411 if (file->entries[i].oplock_level == OPLOCK_EXCLUSIVE) {
412 bool oplock_return = OPLOCK_BREAK_TO_LEVEL_II;
413 /* if this is an attribute only access
414 * it doesn't conflict with an EXCLUSIVE oplock
415 * but we'll not grant the oplock below
417 attrs_only = access_attributes_only(access_mask,
418 open_disposition,
419 break_to_none);
420 if (attrs_only) {
421 break;
424 * send an oplock break to the holder of the
425 * oplock and tell caller to retry later
427 if (break_to_none ||
428 !file->entries[i].allow_level_II_oplock) {
429 oplock_return = OPLOCK_BREAK_TO_NONE;
431 odb_oplock_break_send(odb->ntvfs_ctx->msg_ctx,
432 &file->entries[i],
433 oplock_return);
434 return NT_STATUS_OPLOCK_NOT_GRANTED;
438 if (_attrs_only) {
439 *_attrs_only = attrs_only;
441 return NT_STATUS_OK;
445 register an open file in the open files database.
446 The share_access rules are implemented by odb_can_open()
447 and it's needed to call odb_can_open() before
448 odb_open_file() otherwise NT_STATUS_INTERNAL_ERROR is returned
450 Note that the path is only used by the delete on close logic, not
451 for comparing with other filenames
453 static NTSTATUS odb_tdb_open_file(struct odb_lock *lck,
454 void *file_handle, const char *path,
455 int *fd, NTTIME open_write_time,
456 bool allow_level_II_oplock,
457 uint32_t oplock_level, uint32_t *oplock_granted)
459 struct odb_context *odb = lck->odb;
461 if (!lck->can_open.e) {
462 return NT_STATUS_INTERNAL_ERROR;
465 if (odb->oplocks == false) {
466 oplock_level = OPLOCK_NONE;
469 if (!oplock_granted) {
470 oplock_level = OPLOCK_NONE;
473 if (lck->file.path == NULL) {
474 lck->file.path = talloc_strdup(lck, path);
475 NT_STATUS_HAVE_NO_MEMORY(lck->file.path);
478 if (lck->file.open_write_time == 0) {
479 lck->file.open_write_time = open_write_time;
483 possibly grant an exclusive, batch or level2 oplock
485 if (lck->can_open.attrs_only) {
486 oplock_level = OPLOCK_NONE;
487 } else if (oplock_level == OPLOCK_EXCLUSIVE) {
488 if (lck->file.num_entries == 0) {
489 oplock_level = OPLOCK_EXCLUSIVE;
490 } else if (allow_level_II_oplock) {
491 oplock_level = OPLOCK_LEVEL_II;
492 } else {
493 oplock_level = OPLOCK_NONE;
495 } else if (oplock_level == OPLOCK_BATCH) {
496 if (lck->file.num_entries == 0) {
497 oplock_level = OPLOCK_BATCH;
498 } else if (allow_level_II_oplock) {
499 oplock_level = OPLOCK_LEVEL_II;
500 } else {
501 oplock_level = OPLOCK_NONE;
503 } else if (oplock_level == OPLOCK_LEVEL_II) {
504 oplock_level = OPLOCK_LEVEL_II;
505 } else {
506 oplock_level = OPLOCK_NONE;
509 lck->can_open.e->file_handle = file_handle;
510 lck->can_open.e->fd = fd;
511 lck->can_open.e->allow_level_II_oplock = allow_level_II_oplock;
512 lck->can_open.e->oplock_level = oplock_level;
514 if (odb->lease_ctx && fd) {
515 NTSTATUS status;
516 status = sys_lease_setup(odb->lease_ctx, lck->can_open.e);
517 NT_STATUS_NOT_OK_RETURN(status);
520 if (oplock_granted) {
521 if (lck->can_open.e->oplock_level == OPLOCK_EXCLUSIVE) {
522 *oplock_granted = EXCLUSIVE_OPLOCK_RETURN;
523 } else if (lck->can_open.e->oplock_level == OPLOCK_BATCH) {
524 *oplock_granted = BATCH_OPLOCK_RETURN;
525 } else if (lck->can_open.e->oplock_level == OPLOCK_LEVEL_II) {
526 *oplock_granted = LEVEL_II_OPLOCK_RETURN;
527 } else {
528 *oplock_granted = NO_OPLOCK_RETURN;
532 /* it doesn't conflict, so add it to the end */
533 lck->file.entries = talloc_realloc(lck, lck->file.entries,
534 struct opendb_entry,
535 lck->file.num_entries+1);
536 NT_STATUS_HAVE_NO_MEMORY(lck->file.entries);
538 lck->file.entries[lck->file.num_entries] = *lck->can_open.e;
539 lck->file.num_entries++;
541 talloc_free(lck->can_open.e);
542 lck->can_open.e = NULL;
544 return odb_push_record(lck, &lck->file);
549 register a pending open file in the open files database
551 static NTSTATUS odb_tdb_open_file_pending(struct odb_lock *lck, void *private_data)
553 struct odb_context *odb = lck->odb;
555 if (lck->file.path == NULL) {
556 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
559 lck->file.pending = talloc_realloc(lck, lck->file.pending,
560 struct opendb_pending,
561 lck->file.num_pending+1);
562 NT_STATUS_HAVE_NO_MEMORY(lck->file.pending);
564 lck->file.pending[lck->file.num_pending].server = odb->ntvfs_ctx->server_id;
565 lck->file.pending[lck->file.num_pending].notify_ptr = private_data;
567 lck->file.num_pending++;
569 return odb_push_record(lck, &lck->file);
574 remove a opendb entry
576 static NTSTATUS odb_tdb_close_file(struct odb_lock *lck, void *file_handle,
577 const char **_delete_path)
579 struct odb_context *odb = lck->odb;
580 const char *delete_path = NULL;
581 int i;
583 if (lck->file.path == NULL) {
584 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
587 /* find the entry, and delete it */
588 for (i=0;i<lck->file.num_entries;i++) {
589 if (file_handle == lck->file.entries[i].file_handle &&
590 cluster_id_equal(&odb->ntvfs_ctx->server_id, &lck->file.entries[i].server)) {
591 if (lck->file.entries[i].delete_on_close) {
592 lck->file.delete_on_close = true;
594 if (odb->lease_ctx && lck->file.entries[i].fd) {
595 NTSTATUS status;
596 status = sys_lease_remove(odb->lease_ctx, &lck->file.entries[i]);
597 NT_STATUS_NOT_OK_RETURN(status);
599 if (i < lck->file.num_entries-1) {
600 memmove(lck->file.entries+i, lck->file.entries+i+1,
601 (lck->file.num_entries - (i+1)) *
602 sizeof(struct opendb_entry));
604 break;
608 if (i == lck->file.num_entries) {
609 return NT_STATUS_UNSUCCESSFUL;
612 /* send any pending notifications, removing them once sent */
613 for (i=0;i<lck->file.num_pending;i++) {
614 imessaging_send_ptr(odb->ntvfs_ctx->msg_ctx,
615 lck->file.pending[i].server,
616 MSG_PVFS_RETRY_OPEN,
617 lck->file.pending[i].notify_ptr);
619 lck->file.num_pending = 0;
621 lck->file.num_entries--;
623 if (lck->file.num_entries == 0 && lck->file.delete_on_close) {
624 delete_path = lck->file.path;
627 if (_delete_path) {
628 *_delete_path = delete_path;
631 return odb_push_record(lck, &lck->file);
635 update the oplock level of the client
637 static NTSTATUS odb_tdb_update_oplock(struct odb_lock *lck, void *file_handle,
638 uint32_t oplock_level)
640 struct odb_context *odb = lck->odb;
641 int i;
643 if (lck->file.path == NULL) {
644 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
647 /* find the entry, and update it */
648 for (i=0;i<lck->file.num_entries;i++) {
649 if (file_handle == lck->file.entries[i].file_handle &&
650 cluster_id_equal(&odb->ntvfs_ctx->server_id, &lck->file.entries[i].server)) {
651 lck->file.entries[i].oplock_level = oplock_level;
653 if (odb->lease_ctx && lck->file.entries[i].fd) {
654 NTSTATUS status;
655 status = sys_lease_update(odb->lease_ctx, &lck->file.entries[i]);
656 NT_STATUS_NOT_OK_RETURN(status);
659 break;
663 if (i == lck->file.num_entries) {
664 return NT_STATUS_UNSUCCESSFUL;
667 /* send any pending notifications, removing them once sent */
668 for (i=0;i<lck->file.num_pending;i++) {
669 imessaging_send_ptr(odb->ntvfs_ctx->msg_ctx,
670 lck->file.pending[i].server,
671 MSG_PVFS_RETRY_OPEN,
672 lck->file.pending[i].notify_ptr);
674 lck->file.num_pending = 0;
676 return odb_push_record(lck, &lck->file);
680 send oplocks breaks to none to all level2 holders
682 static NTSTATUS odb_tdb_break_oplocks(struct odb_lock *lck)
684 struct odb_context *odb = lck->odb;
685 int i;
686 bool modified = false;
688 /* see if anyone has an oplock, which we need to break */
689 for (i=0;i<lck->file.num_entries;i++) {
690 if (lck->file.entries[i].oplock_level == OPLOCK_LEVEL_II) {
692 * there could be multiple level2 oplocks
693 * and we just send a break to none to all of them
694 * without waiting for a release
696 odb_oplock_break_send(odb->ntvfs_ctx->msg_ctx,
697 &lck->file.entries[i],
698 OPLOCK_BREAK_TO_NONE);
699 lck->file.entries[i].oplock_level = OPLOCK_NONE;
700 modified = true;
704 if (modified) {
705 return odb_push_record(lck, &lck->file);
707 return NT_STATUS_OK;
711 remove a pending opendb entry
713 static NTSTATUS odb_tdb_remove_pending(struct odb_lock *lck, void *private_data)
715 struct odb_context *odb = lck->odb;
716 int i;
718 if (lck->file.path == NULL) {
719 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
722 /* find the entry, and delete it */
723 for (i=0;i<lck->file.num_pending;i++) {
724 if (private_data == lck->file.pending[i].notify_ptr &&
725 cluster_id_equal(&odb->ntvfs_ctx->server_id, &lck->file.pending[i].server)) {
726 if (i < lck->file.num_pending-1) {
727 memmove(lck->file.pending+i, lck->file.pending+i+1,
728 (lck->file.num_pending - (i+1)) *
729 sizeof(struct opendb_pending));
731 break;
735 if (i == lck->file.num_pending) {
736 return NT_STATUS_UNSUCCESSFUL;
739 lck->file.num_pending--;
741 return odb_push_record(lck, &lck->file);
746 rename the path in a open file
748 static NTSTATUS odb_tdb_rename(struct odb_lock *lck, const char *path)
750 if (lck->file.path == NULL) {
751 /* not having the record at all is OK */
752 return NT_STATUS_OK;
755 lck->file.path = talloc_strdup(lck, path);
756 NT_STATUS_HAVE_NO_MEMORY(lck->file.path);
758 return odb_push_record(lck, &lck->file);
762 get the path of an open file
764 static NTSTATUS odb_tdb_get_path(struct odb_lock *lck, const char **path)
766 *path = NULL;
768 /* we don't ignore NT_STATUS_OBJECT_NAME_NOT_FOUND here */
769 if (lck->file.path == NULL) {
770 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
773 *path = lck->file.path;
775 return NT_STATUS_OK;
779 update delete on close flag on an open file
781 static NTSTATUS odb_tdb_set_delete_on_close(struct odb_lock *lck, bool del_on_close)
783 if (lck->file.path == NULL) {
784 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
787 lck->file.delete_on_close = del_on_close;
789 return odb_push_record(lck, &lck->file);
793 update the write time on an open file
795 static NTSTATUS odb_tdb_set_write_time(struct odb_lock *lck,
796 NTTIME write_time, bool force)
798 if (lck->file.path == NULL) {
799 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
802 if (lck->file.changed_write_time != 0 && !force) {
803 return NT_STATUS_OK;
806 lck->file.changed_write_time = write_time;
808 return odb_push_record(lck, &lck->file);
812 return the current value of the delete_on_close bit, and how many
813 people still have the file open
815 static NTSTATUS odb_tdb_get_file_infos(struct odb_context *odb, DATA_BLOB *key,
816 bool *del_on_close, NTTIME *write_time)
818 struct odb_lock *lck;
820 if (del_on_close) {
821 *del_on_close = false;
823 if (write_time) {
824 *write_time = 0;
827 lck = odb_lock(odb, odb, key);
828 NT_STATUS_HAVE_NO_MEMORY(lck);
830 if (del_on_close) {
831 *del_on_close = lck->file.delete_on_close;
833 if (write_time) {
834 if (lck->file.changed_write_time == 0) {
835 *write_time = lck->file.open_write_time;
836 } else {
837 *write_time = lck->file.changed_write_time;
841 talloc_free(lck);
843 return NT_STATUS_OK;
848 determine if a file can be opened with the given share_access,
849 create_options and access_mask
851 static NTSTATUS odb_tdb_can_open(struct odb_lock *lck,
852 uint32_t stream_id, uint32_t share_access,
853 uint32_t access_mask, bool delete_on_close,
854 uint32_t open_disposition, bool break_to_none)
856 struct odb_context *odb = lck->odb;
857 NTSTATUS status;
859 status = odb_tdb_open_can_internal(odb, &lck->file, stream_id,
860 share_access, access_mask,
861 delete_on_close, open_disposition,
862 break_to_none, &lck->can_open.attrs_only);
863 NT_STATUS_NOT_OK_RETURN(status);
865 lck->can_open.e = talloc(lck, struct opendb_entry);
866 NT_STATUS_HAVE_NO_MEMORY(lck->can_open.e);
868 lck->can_open.e->server = odb->ntvfs_ctx->server_id;
869 lck->can_open.e->file_handle = NULL;
870 lck->can_open.e->fd = NULL;
871 lck->can_open.e->stream_id = stream_id;
872 lck->can_open.e->share_access = share_access;
873 lck->can_open.e->access_mask = access_mask;
874 lck->can_open.e->delete_on_close = delete_on_close;
875 lck->can_open.e->allow_level_II_oplock = false;
876 lck->can_open.e->oplock_level = OPLOCK_NONE;
878 return NT_STATUS_OK;
882 static const struct opendb_ops opendb_tdb_ops = {
883 .odb_init = odb_tdb_init,
884 .odb_lock = odb_tdb_lock,
885 .odb_get_key = odb_tdb_get_key,
886 .odb_open_file = odb_tdb_open_file,
887 .odb_open_file_pending = odb_tdb_open_file_pending,
888 .odb_close_file = odb_tdb_close_file,
889 .odb_remove_pending = odb_tdb_remove_pending,
890 .odb_rename = odb_tdb_rename,
891 .odb_get_path = odb_tdb_get_path,
892 .odb_set_delete_on_close = odb_tdb_set_delete_on_close,
893 .odb_set_write_time = odb_tdb_set_write_time,
894 .odb_get_file_infos = odb_tdb_get_file_infos,
895 .odb_can_open = odb_tdb_can_open,
896 .odb_update_oplock = odb_tdb_update_oplock,
897 .odb_break_oplocks = odb_tdb_break_oplocks
901 void odb_tdb_init_ops(void)
903 sys_lease_init();
904 odb_set_ops(&opendb_tdb_ops);