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
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.
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"
54 struct db_context
*db
;
55 struct ntvfs_context
*ntvfs_ctx
;
57 struct sys_lease_context
*lease_ctx
;
61 an odb lock handle. You must obtain one of these using odb_lock() before doing
65 struct odb_context
*odb
;
66 struct db_record
*locked
;
68 struct opendb_file file
;
71 struct opendb_entry
*e
;
76 static NTSTATUS
odb_oplock_break_send(struct imessaging_context
*msg_ctx
,
77 struct opendb_entry
*e
,
81 Open up the openfiles.tdb database. Close it down using
82 talloc_free(). We need the imessaging_ctx to allow for pending open
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
);
95 odb
->db
= cluster_db_tmp_open(odb
, ntvfs_ctx
->lp_ctx
,
96 "openfiles", TDB_DEFAULT
);
97 if (odb
->db
== 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
,
109 odb_oplock_break_send
);
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
;
127 lck
= talloc(mem_ctx
, struct odb_lock
);
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
) {
140 lck
->locked
= dbwrap_fetch_locked(odb
->db
, lck
, key
);
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
)) {
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
,
174 uint32_t share_access
,
175 uint32_t access_mask
)
177 /* if either open involves no read.write or delete access then
179 if (!(e1
->access_mask
& (SEC_FILE_WRITE_DATA
|
180 SEC_FILE_APPEND_DATA
|
186 if (!(access_mask
& (SEC_FILE_WRITE_DATA
|
187 SEC_FILE_APPEND_DATA
|
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
197 if (e1
->stream_id
!= stream_id
) {
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
);
223 pull a record, translating from the db format to the opendb_file structure defined
226 static NTSTATUS
odb_pull_record(struct odb_lock
*lck
, struct opendb_file
*file
)
230 enum ndr_err_code ndr_err
;
232 dbuf
= dbwrap_record_get_value(lck
->locked
);
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
);
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
)
255 enum ndr_err_code ndr_err
;
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
);
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
,
283 struct opendb_oplock_break op_break
;
286 ZERO_STRUCT(op_break
);
288 /* tell the server handling this open file about the need to send the client
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
);
302 static bool access_attributes_only(uint32_t access_mask
,
303 uint32_t open_disposition
,
306 switch (open_disposition
) {
307 case NTCREATEX_DISP_SUPERSEDE
:
308 case NTCREATEX_DISP_OVERWRITE_IF
:
309 case NTCREATEX_DISP_OVERWRITE
:
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
);
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
,
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
,
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 propagate by sending a oplock
356 break request and suspending this call
357 until the break is acknowledged or the file
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
,
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
,
405 * send an oplock break to the holder of the
406 * oplock and tell caller to retry later
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
,
415 return NT_STATUS_OPLOCK_NOT_GRANTED
;
420 *_attrs_only
= attrs_only
;
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
;
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
;
482 oplock_level
= OPLOCK_NONE
;
484 } else if (oplock_level
== OPLOCK_LEVEL_II
) {
485 oplock_level
= OPLOCK_LEVEL_II
;
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
) {
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
;
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
,
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
;
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
) {
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
));
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
,
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
;
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
;
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
) {
636 status
= sys_lease_update(odb
->lease_ctx
, &lck
->file
.entries
[i
]);
637 NT_STATUS_NOT_OK_RETURN(status
);
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
,
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
;
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
;
686 return odb_push_record(lck
, &lck
->file
);
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
;
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
));
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 */
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
)
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
;
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
) {
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
;
802 *del_on_close
= false;
808 lck
= odb_lock(odb
, odb
, key
);
809 NT_STATUS_HAVE_NO_MEMORY(lck
);
812 *del_on_close
= lck
->file
.delete_on_close
;
815 if (lck
->file
.changed_write_time
== 0) {
816 *write_time
= lck
->file
.open_write_time
;
818 *write_time
= lck
->file
.changed_write_time
;
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
;
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
;
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)
885 odb_set_ops(&opendb_tdb_ops
);