librpc: Shorten dcerpc_binding_handle_call a bit
[Samba/gebeck_regimport.git] / source4 / ntvfs / common / opendb_tdb.c
blob2047a0b3145c1976edcc71b406aa3eb74b9cbbe9
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/dbwrap/dbwrap.h"
44 #include "messaging/messaging.h"
45 #include "lib/messaging/irpc.h"
46 #include "librpc/gen_ndr/ndr_opendb.h"
47 #include "ntvfs/ntvfs.h"
48 #include "ntvfs/common/ntvfs_common.h"
49 #include "cluster/cluster.h"
50 #include "param/param.h"
51 #include "ntvfs/sysdep/sys_lease.h"
53 struct odb_context {
54 struct db_context *db;
55 struct ntvfs_context *ntvfs_ctx;
56 bool oplocks;
57 struct sys_lease_context *lease_ctx;
61 an odb lock handle. You must obtain one of these using odb_lock() before doing
62 any other operations.
64 struct odb_lock {
65 struct odb_context *odb;
66 struct db_record *locked;
68 struct opendb_file file;
70 struct {
71 struct opendb_entry *e;
72 bool attrs_only;
73 } can_open;
76 static NTSTATUS odb_oplock_break_send(struct imessaging_context *msg_ctx,
77 struct opendb_entry *e,
78 uint8_t level);
81 Open up the openfiles.tdb database. Close it down using
82 talloc_free(). We need the imessaging_ctx to allow for pending open
83 notifications.
85 static struct odb_context *odb_tdb_init(TALLOC_CTX *mem_ctx,
86 struct ntvfs_context *ntvfs_ctx)
88 struct odb_context *odb;
90 odb = talloc(mem_ctx, struct odb_context);
91 if (odb == NULL) {
92 return NULL;
95 odb->db = cluster_db_tmp_open(odb, ntvfs_ctx->lp_ctx,
96 "openfiles", TDB_DEFAULT);
97 if (odb->db == 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;
114 static NTSTATUS odb_pull_record(struct odb_lock *lck, struct opendb_file *file);
117 get a lock on a entry in the odb. This call returns a lock handle,
118 which the caller should unlock using talloc_free().
120 static struct odb_lock *odb_tdb_lock(TALLOC_CTX *mem_ctx,
121 struct odb_context *odb, DATA_BLOB *file_key)
123 struct odb_lock *lck;
124 NTSTATUS status;
125 TDB_DATA key;
127 lck = talloc(mem_ctx, struct odb_lock);
128 if (lck == NULL) {
129 return NULL;
132 lck->odb = talloc_reference(lck, odb);
133 key.dptr = talloc_memdup(lck, file_key->data, file_key->length);
134 key.dsize = file_key->length;
135 if (key.dptr == NULL) {
136 talloc_free(lck);
137 return NULL;
140 lck->locked = dbwrap_fetch_locked(odb->db, lck, key);
141 if (!lck->locked) {
142 talloc_free(lck);
143 return NULL;
146 ZERO_STRUCT(lck->can_open);
148 status = odb_pull_record(lck, &lck->file);
149 if (NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
150 /* initialise a blank structure */
151 ZERO_STRUCT(lck->file);
152 } else if (!NT_STATUS_IS_OK(status)) {
153 talloc_free(lck);
154 return NULL;
157 return lck;
160 static DATA_BLOB odb_tdb_get_key(TALLOC_CTX *mem_ctx, struct odb_lock *lck)
162 TDB_DATA key = dbwrap_record_get_key(lck->locked);
163 return data_blob_talloc(mem_ctx, key.dptr, key.dsize);
168 determine if two odb_entry structures conflict
170 return NT_STATUS_OK on no conflict
172 static NTSTATUS share_conflict(struct opendb_entry *e1,
173 uint32_t stream_id,
174 uint32_t share_access,
175 uint32_t access_mask)
177 /* if either open involves no read.write or delete access then
178 it can't conflict */
179 if (!(e1->access_mask & (SEC_FILE_WRITE_DATA |
180 SEC_FILE_APPEND_DATA |
181 SEC_FILE_READ_DATA |
182 SEC_FILE_EXECUTE |
183 SEC_STD_DELETE))) {
184 return NT_STATUS_OK;
186 if (!(access_mask & (SEC_FILE_WRITE_DATA |
187 SEC_FILE_APPEND_DATA |
188 SEC_FILE_READ_DATA |
189 SEC_FILE_EXECUTE |
190 SEC_STD_DELETE))) {
191 return NT_STATUS_OK;
194 /* data IO access masks. This is skipped if the two open handles
195 are on different streams (as in that case the masks don't
196 interact) */
197 if (e1->stream_id != stream_id) {
198 return NT_STATUS_OK;
201 #define CHECK_MASK(am, right, sa, share) \
202 if (((am) & (right)) && !((sa) & (share))) return NT_STATUS_SHARING_VIOLATION
204 CHECK_MASK(e1->access_mask, SEC_FILE_WRITE_DATA | SEC_FILE_APPEND_DATA,
205 share_access, NTCREATEX_SHARE_ACCESS_WRITE);
206 CHECK_MASK(access_mask, SEC_FILE_WRITE_DATA | SEC_FILE_APPEND_DATA,
207 e1->share_access, NTCREATEX_SHARE_ACCESS_WRITE);
209 CHECK_MASK(e1->access_mask, SEC_FILE_READ_DATA | SEC_FILE_EXECUTE,
210 share_access, NTCREATEX_SHARE_ACCESS_READ);
211 CHECK_MASK(access_mask, SEC_FILE_READ_DATA | SEC_FILE_EXECUTE,
212 e1->share_access, NTCREATEX_SHARE_ACCESS_READ);
214 CHECK_MASK(e1->access_mask, SEC_STD_DELETE,
215 share_access, NTCREATEX_SHARE_ACCESS_DELETE);
216 CHECK_MASK(access_mask, SEC_STD_DELETE,
217 e1->share_access, NTCREATEX_SHARE_ACCESS_DELETE);
218 #undef CHECK_MASK
219 return NT_STATUS_OK;
223 pull a record, translating from the db format to the opendb_file structure defined
224 in opendb.idl
226 static NTSTATUS odb_pull_record(struct odb_lock *lck, struct opendb_file *file)
228 TDB_DATA dbuf;
229 DATA_BLOB blob;
230 enum ndr_err_code ndr_err;
232 dbuf = dbwrap_record_get_value(lck->locked);
233 if (!dbuf.dptr) {
234 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
237 blob.data = dbuf.dptr;
238 blob.length = dbuf.dsize;
240 ndr_err = ndr_pull_struct_blob(&blob, lck, file, (ndr_pull_flags_fn_t)ndr_pull_opendb_file);
241 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
242 return ndr_map_error2ntstatus(ndr_err);
245 return NT_STATUS_OK;
249 push a record, translating from the opendb_file structure defined in opendb.idl
251 static NTSTATUS odb_push_record(struct odb_lock *lck, struct opendb_file *file)
253 TDB_DATA dbuf;
254 DATA_BLOB blob;
255 enum ndr_err_code ndr_err;
256 NTSTATUS status;
258 if (file->num_entries == 0) {
259 return dbwrap_record_delete(lck->locked);
262 ndr_err = ndr_push_struct_blob(&blob, lck, file, (ndr_push_flags_fn_t)ndr_push_opendb_file);
263 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
264 return ndr_map_error2ntstatus(ndr_err);
267 dbuf.dptr = blob.data;
268 dbuf.dsize = blob.length;
270 status = dbwrap_record_store(lck->locked, dbuf, TDB_REPLACE);
271 data_blob_free(&blob);
272 return status;
276 send an oplock break to a client
278 static NTSTATUS odb_oplock_break_send(struct imessaging_context *msg_ctx,
279 struct opendb_entry *e,
280 uint8_t level)
282 NTSTATUS status;
283 struct opendb_oplock_break op_break;
284 DATA_BLOB blob;
286 ZERO_STRUCT(op_break);
288 /* tell the server handling this open file about the need to send the client
289 a break */
290 op_break.file_handle = e->file_handle;
291 op_break.level = level;
293 blob = data_blob_const(&op_break, sizeof(op_break));
295 status = imessaging_send(msg_ctx, e->server,
296 MSG_NTVFS_OPLOCK_BREAK, &blob);
297 NT_STATUS_NOT_OK_RETURN(status);
299 return NT_STATUS_OK;
302 static bool access_attributes_only(uint32_t access_mask,
303 uint32_t open_disposition,
304 bool break_to_none)
306 switch (open_disposition) {
307 case NTCREATEX_DISP_SUPERSEDE:
308 case NTCREATEX_DISP_OVERWRITE_IF:
309 case NTCREATEX_DISP_OVERWRITE:
310 return false;
311 default:
312 break;
315 if (break_to_none) {
316 return false;
319 #define CHECK_MASK(m,g) ((m) && (((m) & ~(g))==0) && (((m) & (g)) != 0))
320 return CHECK_MASK(access_mask,
321 SEC_STD_SYNCHRONIZE |
322 SEC_FILE_READ_ATTRIBUTE |
323 SEC_FILE_WRITE_ATTRIBUTE);
324 #undef CHECK_MASK
327 static NTSTATUS odb_tdb_open_can_internal(struct odb_context *odb,
328 const struct opendb_file *file,
329 uint32_t stream_id, uint32_t share_access,
330 uint32_t access_mask, bool delete_on_close,
331 uint32_t open_disposition, bool break_to_none,
332 bool *_attrs_only)
334 NTSTATUS status;
335 uint32_t i;
336 bool attrs_only = false;
338 /* see if anyone has an oplock, which we need to break */
339 for (i=0;i<file->num_entries;i++) {
340 if (file->entries[i].oplock_level == OPLOCK_BATCH) {
341 bool oplock_return = OPLOCK_BREAK_TO_LEVEL_II;
342 /* if this is an attribute only access
343 * it doesn't conflict with a BACTCH oplock
344 * but we'll not grant the oplock below
346 attrs_only = access_attributes_only(access_mask,
347 open_disposition,
348 break_to_none);
349 if (attrs_only) {
350 break;
352 /* a batch oplock caches close calls, which
353 means the client application might have
354 already closed the file. We have to allow
355 this close to propogate by sending a oplock
356 break request and suspending this call
357 until the break is acknowledged or the file
358 is closed */
359 if (break_to_none ||
360 !file->entries[i].allow_level_II_oplock) {
361 oplock_return = OPLOCK_BREAK_TO_NONE;
363 odb_oplock_break_send(odb->ntvfs_ctx->msg_ctx,
364 &file->entries[i],
365 oplock_return);
366 return NT_STATUS_OPLOCK_NOT_GRANTED;
370 if (file->delete_on_close) {
371 /* while delete on close is set, no new opens are allowed */
372 return NT_STATUS_DELETE_PENDING;
375 if (file->num_entries != 0 && delete_on_close) {
376 return NT_STATUS_SHARING_VIOLATION;
379 /* check for sharing violations */
380 for (i=0;i<file->num_entries;i++) {
381 status = share_conflict(&file->entries[i], stream_id,
382 share_access, access_mask);
383 NT_STATUS_NOT_OK_RETURN(status);
386 /* we now know the open could succeed, but we need to check
387 for any exclusive oplocks. We can't grant a second open
388 till these are broken. Note that we check for batch oplocks
389 before checking for sharing violations, and check for
390 exclusive oplocks afterwards. */
391 for (i=0;i<file->num_entries;i++) {
392 if (file->entries[i].oplock_level == OPLOCK_EXCLUSIVE) {
393 bool oplock_return = OPLOCK_BREAK_TO_LEVEL_II;
394 /* if this is an attribute only access
395 * it doesn't conflict with an EXCLUSIVE oplock
396 * but we'll not grant the oplock below
398 attrs_only = access_attributes_only(access_mask,
399 open_disposition,
400 break_to_none);
401 if (attrs_only) {
402 break;
405 * send an oplock break to the holder of the
406 * oplock and tell caller to retry later
408 if (break_to_none ||
409 !file->entries[i].allow_level_II_oplock) {
410 oplock_return = OPLOCK_BREAK_TO_NONE;
412 odb_oplock_break_send(odb->ntvfs_ctx->msg_ctx,
413 &file->entries[i],
414 oplock_return);
415 return NT_STATUS_OPLOCK_NOT_GRANTED;
419 if (_attrs_only) {
420 *_attrs_only = attrs_only;
422 return NT_STATUS_OK;
426 register an open file in the open files database.
427 The share_access rules are implemented by odb_can_open()
428 and it's needed to call odb_can_open() before
429 odb_open_file() otherwise NT_STATUS_INTERNAL_ERROR is returned
431 Note that the path is only used by the delete on close logic, not
432 for comparing with other filenames
434 static NTSTATUS odb_tdb_open_file(struct odb_lock *lck,
435 void *file_handle, const char *path,
436 int *fd, NTTIME open_write_time,
437 bool allow_level_II_oplock,
438 uint32_t oplock_level, uint32_t *oplock_granted)
440 struct odb_context *odb = lck->odb;
442 if (!lck->can_open.e) {
443 return NT_STATUS_INTERNAL_ERROR;
446 if (odb->oplocks == false) {
447 oplock_level = OPLOCK_NONE;
450 if (!oplock_granted) {
451 oplock_level = OPLOCK_NONE;
454 if (lck->file.path == NULL) {
455 lck->file.path = talloc_strdup(lck, path);
456 NT_STATUS_HAVE_NO_MEMORY(lck->file.path);
459 if (lck->file.open_write_time == 0) {
460 lck->file.open_write_time = open_write_time;
464 possibly grant an exclusive, batch or level2 oplock
466 if (lck->can_open.attrs_only) {
467 oplock_level = OPLOCK_NONE;
468 } else if (oplock_level == OPLOCK_EXCLUSIVE) {
469 if (lck->file.num_entries == 0) {
470 oplock_level = OPLOCK_EXCLUSIVE;
471 } else if (allow_level_II_oplock) {
472 oplock_level = OPLOCK_LEVEL_II;
473 } else {
474 oplock_level = OPLOCK_NONE;
476 } else if (oplock_level == OPLOCK_BATCH) {
477 if (lck->file.num_entries == 0) {
478 oplock_level = OPLOCK_BATCH;
479 } else if (allow_level_II_oplock) {
480 oplock_level = OPLOCK_LEVEL_II;
481 } else {
482 oplock_level = OPLOCK_NONE;
484 } else if (oplock_level == OPLOCK_LEVEL_II) {
485 oplock_level = OPLOCK_LEVEL_II;
486 } else {
487 oplock_level = OPLOCK_NONE;
490 lck->can_open.e->file_handle = file_handle;
491 lck->can_open.e->fd = fd;
492 lck->can_open.e->allow_level_II_oplock = allow_level_II_oplock;
493 lck->can_open.e->oplock_level = oplock_level;
495 if (odb->lease_ctx && fd) {
496 NTSTATUS status;
497 status = sys_lease_setup(odb->lease_ctx, lck->can_open.e);
498 NT_STATUS_NOT_OK_RETURN(status);
501 if (oplock_granted) {
502 if (lck->can_open.e->oplock_level == OPLOCK_EXCLUSIVE) {
503 *oplock_granted = EXCLUSIVE_OPLOCK_RETURN;
504 } else if (lck->can_open.e->oplock_level == OPLOCK_BATCH) {
505 *oplock_granted = BATCH_OPLOCK_RETURN;
506 } else if (lck->can_open.e->oplock_level == OPLOCK_LEVEL_II) {
507 *oplock_granted = LEVEL_II_OPLOCK_RETURN;
508 } else {
509 *oplock_granted = NO_OPLOCK_RETURN;
513 /* it doesn't conflict, so add it to the end */
514 lck->file.entries = talloc_realloc(lck, lck->file.entries,
515 struct opendb_entry,
516 lck->file.num_entries+1);
517 NT_STATUS_HAVE_NO_MEMORY(lck->file.entries);
519 lck->file.entries[lck->file.num_entries] = *lck->can_open.e;
520 lck->file.num_entries++;
522 talloc_free(lck->can_open.e);
523 lck->can_open.e = NULL;
525 return odb_push_record(lck, &lck->file);
530 register a pending open file in the open files database
532 static NTSTATUS odb_tdb_open_file_pending(struct odb_lock *lck, void *private_data)
534 struct odb_context *odb = lck->odb;
536 if (lck->file.path == NULL) {
537 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
540 lck->file.pending = talloc_realloc(lck, lck->file.pending,
541 struct opendb_pending,
542 lck->file.num_pending+1);
543 NT_STATUS_HAVE_NO_MEMORY(lck->file.pending);
545 lck->file.pending[lck->file.num_pending].server = odb->ntvfs_ctx->server_id;
546 lck->file.pending[lck->file.num_pending].notify_ptr = private_data;
548 lck->file.num_pending++;
550 return odb_push_record(lck, &lck->file);
555 remove a opendb entry
557 static NTSTATUS odb_tdb_close_file(struct odb_lock *lck, void *file_handle,
558 const char **_delete_path)
560 struct odb_context *odb = lck->odb;
561 const char *delete_path = NULL;
562 int i;
564 if (lck->file.path == NULL) {
565 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
568 /* find the entry, and delete it */
569 for (i=0;i<lck->file.num_entries;i++) {
570 if (file_handle == lck->file.entries[i].file_handle &&
571 cluster_id_equal(&odb->ntvfs_ctx->server_id, &lck->file.entries[i].server)) {
572 if (lck->file.entries[i].delete_on_close) {
573 lck->file.delete_on_close = true;
575 if (odb->lease_ctx && lck->file.entries[i].fd) {
576 NTSTATUS status;
577 status = sys_lease_remove(odb->lease_ctx, &lck->file.entries[i]);
578 NT_STATUS_NOT_OK_RETURN(status);
580 if (i < lck->file.num_entries-1) {
581 memmove(lck->file.entries+i, lck->file.entries+i+1,
582 (lck->file.num_entries - (i+1)) *
583 sizeof(struct opendb_entry));
585 break;
589 if (i == lck->file.num_entries) {
590 return NT_STATUS_UNSUCCESSFUL;
593 /* send any pending notifications, removing them once sent */
594 for (i=0;i<lck->file.num_pending;i++) {
595 imessaging_send_ptr(odb->ntvfs_ctx->msg_ctx,
596 lck->file.pending[i].server,
597 MSG_PVFS_RETRY_OPEN,
598 lck->file.pending[i].notify_ptr);
600 lck->file.num_pending = 0;
602 lck->file.num_entries--;
604 if (lck->file.num_entries == 0 && lck->file.delete_on_close) {
605 delete_path = lck->file.path;
608 if (_delete_path) {
609 *_delete_path = delete_path;
612 return odb_push_record(lck, &lck->file);
616 update the oplock level of the client
618 static NTSTATUS odb_tdb_update_oplock(struct odb_lock *lck, void *file_handle,
619 uint32_t oplock_level)
621 struct odb_context *odb = lck->odb;
622 int i;
624 if (lck->file.path == NULL) {
625 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
628 /* find the entry, and update it */
629 for (i=0;i<lck->file.num_entries;i++) {
630 if (file_handle == lck->file.entries[i].file_handle &&
631 cluster_id_equal(&odb->ntvfs_ctx->server_id, &lck->file.entries[i].server)) {
632 lck->file.entries[i].oplock_level = oplock_level;
634 if (odb->lease_ctx && lck->file.entries[i].fd) {
635 NTSTATUS status;
636 status = sys_lease_update(odb->lease_ctx, &lck->file.entries[i]);
637 NT_STATUS_NOT_OK_RETURN(status);
640 break;
644 if (i == lck->file.num_entries) {
645 return NT_STATUS_UNSUCCESSFUL;
648 /* send any pending notifications, removing them once sent */
649 for (i=0;i<lck->file.num_pending;i++) {
650 imessaging_send_ptr(odb->ntvfs_ctx->msg_ctx,
651 lck->file.pending[i].server,
652 MSG_PVFS_RETRY_OPEN,
653 lck->file.pending[i].notify_ptr);
655 lck->file.num_pending = 0;
657 return odb_push_record(lck, &lck->file);
661 send oplocks breaks to none to all level2 holders
663 static NTSTATUS odb_tdb_break_oplocks(struct odb_lock *lck)
665 struct odb_context *odb = lck->odb;
666 int i;
667 bool modified = false;
669 /* see if anyone has an oplock, which we need to break */
670 for (i=0;i<lck->file.num_entries;i++) {
671 if (lck->file.entries[i].oplock_level == OPLOCK_LEVEL_II) {
673 * there could be multiple level2 oplocks
674 * and we just send a break to none to all of them
675 * without waiting for a release
677 odb_oplock_break_send(odb->ntvfs_ctx->msg_ctx,
678 &lck->file.entries[i],
679 OPLOCK_BREAK_TO_NONE);
680 lck->file.entries[i].oplock_level = OPLOCK_NONE;
681 modified = true;
685 if (modified) {
686 return odb_push_record(lck, &lck->file);
688 return NT_STATUS_OK;
692 remove a pending opendb entry
694 static NTSTATUS odb_tdb_remove_pending(struct odb_lock *lck, void *private_data)
696 struct odb_context *odb = lck->odb;
697 int i;
699 if (lck->file.path == NULL) {
700 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
703 /* find the entry, and delete it */
704 for (i=0;i<lck->file.num_pending;i++) {
705 if (private_data == lck->file.pending[i].notify_ptr &&
706 cluster_id_equal(&odb->ntvfs_ctx->server_id, &lck->file.pending[i].server)) {
707 if (i < lck->file.num_pending-1) {
708 memmove(lck->file.pending+i, lck->file.pending+i+1,
709 (lck->file.num_pending - (i+1)) *
710 sizeof(struct opendb_pending));
712 break;
716 if (i == lck->file.num_pending) {
717 return NT_STATUS_UNSUCCESSFUL;
720 lck->file.num_pending--;
722 return odb_push_record(lck, &lck->file);
727 rename the path in a open file
729 static NTSTATUS odb_tdb_rename(struct odb_lock *lck, const char *path)
731 if (lck->file.path == NULL) {
732 /* not having the record at all is OK */
733 return NT_STATUS_OK;
736 lck->file.path = talloc_strdup(lck, path);
737 NT_STATUS_HAVE_NO_MEMORY(lck->file.path);
739 return odb_push_record(lck, &lck->file);
743 get the path of an open file
745 static NTSTATUS odb_tdb_get_path(struct odb_lock *lck, const char **path)
747 *path = NULL;
749 /* we don't ignore NT_STATUS_OBJECT_NAME_NOT_FOUND here */
750 if (lck->file.path == NULL) {
751 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
754 *path = lck->file.path;
756 return NT_STATUS_OK;
760 update delete on close flag on an open file
762 static NTSTATUS odb_tdb_set_delete_on_close(struct odb_lock *lck, bool del_on_close)
764 if (lck->file.path == NULL) {
765 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
768 lck->file.delete_on_close = del_on_close;
770 return odb_push_record(lck, &lck->file);
774 update the write time on an open file
776 static NTSTATUS odb_tdb_set_write_time(struct odb_lock *lck,
777 NTTIME write_time, bool force)
779 if (lck->file.path == NULL) {
780 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
783 if (lck->file.changed_write_time != 0 && !force) {
784 return NT_STATUS_OK;
787 lck->file.changed_write_time = write_time;
789 return odb_push_record(lck, &lck->file);
793 return the current value of the delete_on_close bit, and how many
794 people still have the file open
796 static NTSTATUS odb_tdb_get_file_infos(struct odb_context *odb, DATA_BLOB *key,
797 bool *del_on_close, NTTIME *write_time)
799 struct odb_lock *lck;
801 if (del_on_close) {
802 *del_on_close = false;
804 if (write_time) {
805 *write_time = 0;
808 lck = odb_lock(odb, odb, key);
809 NT_STATUS_HAVE_NO_MEMORY(lck);
811 if (del_on_close) {
812 *del_on_close = lck->file.delete_on_close;
814 if (write_time) {
815 if (lck->file.changed_write_time == 0) {
816 *write_time = lck->file.open_write_time;
817 } else {
818 *write_time = lck->file.changed_write_time;
822 talloc_free(lck);
824 return NT_STATUS_OK;
829 determine if a file can be opened with the given share_access,
830 create_options and access_mask
832 static NTSTATUS odb_tdb_can_open(struct odb_lock *lck,
833 uint32_t stream_id, uint32_t share_access,
834 uint32_t access_mask, bool delete_on_close,
835 uint32_t open_disposition, bool break_to_none)
837 struct odb_context *odb = lck->odb;
838 NTSTATUS status;
840 status = odb_tdb_open_can_internal(odb, &lck->file, stream_id,
841 share_access, access_mask,
842 delete_on_close, open_disposition,
843 break_to_none, &lck->can_open.attrs_only);
844 NT_STATUS_NOT_OK_RETURN(status);
846 lck->can_open.e = talloc(lck, struct opendb_entry);
847 NT_STATUS_HAVE_NO_MEMORY(lck->can_open.e);
849 lck->can_open.e->server = odb->ntvfs_ctx->server_id;
850 lck->can_open.e->file_handle = NULL;
851 lck->can_open.e->fd = NULL;
852 lck->can_open.e->stream_id = stream_id;
853 lck->can_open.e->share_access = share_access;
854 lck->can_open.e->access_mask = access_mask;
855 lck->can_open.e->delete_on_close = delete_on_close;
856 lck->can_open.e->allow_level_II_oplock = false;
857 lck->can_open.e->oplock_level = OPLOCK_NONE;
859 return NT_STATUS_OK;
863 static const struct opendb_ops opendb_tdb_ops = {
864 .odb_init = odb_tdb_init,
865 .odb_lock = odb_tdb_lock,
866 .odb_get_key = odb_tdb_get_key,
867 .odb_open_file = odb_tdb_open_file,
868 .odb_open_file_pending = odb_tdb_open_file_pending,
869 .odb_close_file = odb_tdb_close_file,
870 .odb_remove_pending = odb_tdb_remove_pending,
871 .odb_rename = odb_tdb_rename,
872 .odb_get_path = odb_tdb_get_path,
873 .odb_set_delete_on_close = odb_tdb_set_delete_on_close,
874 .odb_set_write_time = odb_tdb_set_write_time,
875 .odb_get_file_infos = odb_tdb_get_file_infos,
876 .odb_can_open = odb_tdb_can_open,
877 .odb_update_oplock = odb_tdb_update_oplock,
878 .odb_break_oplocks = odb_tdb_break_oplocks
882 void odb_tdb_init_ops(void)
884 sys_lease_init();
885 odb_set_ops(&opendb_tdb_ops);