s3: Move the share_mode_lock handling to its own file
[Samba/gebeck_regimport.git] / source3 / locking / locking.c
blob9199591d9e86dcd9c55313c096f32343c6f1ec0e
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
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.
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.
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/>.
21 Revision History:
23 12 aug 96: Erik.Devriendt@te6.siemens.be
24 added support for shared memory implementation of share mode locking
26 May 1997. Jeremy Allison (jallison@whistle.com). Modified share mode
27 locking to deal with multiple share modes per open file.
29 September 1997. Jeremy Allison (jallison@whistle.com). Added oplock
30 support.
32 rewritten completely to use new tdb code. Tridge, Dec '99
34 Added POSIX locking support. Jeremy Allison (jeremy@valinux.com), Apr. 2000.
35 Added Unix Extensions POSIX locking support. Jeremy Allison Mar 2006.
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"
50 #undef DBGC_CLASS
51 #define DBGC_CLASS DBGC_LOCKING
53 #define NO_LOCKING_COUNT (-1)
55 /****************************************************************************
56 Debugging aids :-).
57 ****************************************************************************/
59 const char *lock_type_name(enum brl_type lock_type)
61 switch (lock_type) {
62 case READ_LOCK:
63 return "READ";
64 case WRITE_LOCK:
65 return "WRITE";
66 case PENDING_READ_LOCK:
67 return "PENDING_READ";
68 case PENDING_WRITE_LOCK:
69 return "PENDING_WRITE";
70 default:
71 return "other";
75 const char *lock_flav_name(enum brl_flavour lock_flav)
77 return (lock_flav == WINDOWS_LOCK) ? "WINDOWS_LOCK" : "POSIX_LOCK";
80 /****************************************************************************
81 Utility function called to see if a file region is locked.
82 Called in the read/write codepath.
83 ****************************************************************************/
85 void init_strict_lock_struct(files_struct *fsp,
86 uint64_t smblctx,
87 br_off start,
88 br_off size,
89 enum brl_type lock_type,
90 struct lock_struct *plock)
92 SMB_ASSERT(lock_type == READ_LOCK || lock_type == WRITE_LOCK);
94 plock->context.smblctx = smblctx;
95 plock->context.tid = fsp->conn->cnum;
96 plock->context.pid = messaging_server_id(fsp->conn->sconn->msg_ctx);
97 plock->start = start;
98 plock->size = size;
99 plock->fnum = fsp->fnum;
100 plock->lock_type = lock_type;
101 plock->lock_flav = lp_posix_cifsu_locktype(fsp);
104 bool strict_lock_default(files_struct *fsp, struct lock_struct *plock)
106 int strict_locking = lp_strict_locking(fsp->conn->params);
107 bool ret = False;
109 if (plock->size == 0) {
110 return True;
113 if (!lp_locking(fsp->conn->params) || !strict_locking) {
114 return True;
117 if (strict_locking == Auto) {
118 if (EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type) && (plock->lock_type == READ_LOCK || plock->lock_type == WRITE_LOCK)) {
119 DEBUG(10,("is_locked: optimisation - exclusive oplock on file %s\n", fsp_str_dbg(fsp)));
120 ret = True;
121 } else if ((fsp->oplock_type == LEVEL_II_OPLOCK) &&
122 (plock->lock_type == READ_LOCK)) {
123 DEBUG(10,("is_locked: optimisation - level II oplock on file %s\n", fsp_str_dbg(fsp)));
124 ret = True;
125 } else {
126 struct byte_range_lock *br_lck;
128 br_lck = brl_get_locks_readonly(fsp);
129 if (!br_lck) {
130 return True;
132 ret = brl_locktest(br_lck,
133 plock->context.smblctx,
134 plock->context.pid,
135 plock->start,
136 plock->size,
137 plock->lock_type,
138 plock->lock_flav);
140 } else {
141 struct byte_range_lock *br_lck;
143 br_lck = brl_get_locks_readonly(fsp);
144 if (!br_lck) {
145 return True;
147 ret = brl_locktest(br_lck,
148 plock->context.smblctx,
149 plock->context.pid,
150 plock->start,
151 plock->size,
152 plock->lock_type,
153 plock->lock_flav);
156 DEBUG(10,("strict_lock_default: flavour = %s brl start=%.0f "
157 "len=%.0f %s for fnum %d file %s\n",
158 lock_flav_name(plock->lock_flav),
159 (double)plock->start, (double)plock->size,
160 ret ? "unlocked" : "locked",
161 plock->fnum, fsp_str_dbg(fsp)));
163 return ret;
166 void strict_unlock_default(files_struct *fsp, struct lock_struct *plock)
170 /****************************************************************************
171 Find out if a lock could be granted - return who is blocking us if we can't.
172 ****************************************************************************/
174 NTSTATUS query_lock(files_struct *fsp,
175 uint64_t *psmblctx,
176 uint64_t *pcount,
177 uint64_t *poffset,
178 enum brl_type *plock_type,
179 enum brl_flavour lock_flav)
181 struct byte_range_lock *br_lck = NULL;
183 if (!fsp->can_lock) {
184 return fsp->is_directory ? NT_STATUS_INVALID_DEVICE_REQUEST : NT_STATUS_INVALID_HANDLE;
187 if (!lp_locking(fsp->conn->params)) {
188 return NT_STATUS_OK;
191 br_lck = brl_get_locks_readonly(fsp);
192 if (!br_lck) {
193 return NT_STATUS_NO_MEMORY;
196 return brl_lockquery(br_lck,
197 psmblctx,
198 messaging_server_id(fsp->conn->sconn->msg_ctx),
199 poffset,
200 pcount,
201 plock_type,
202 lock_flav);
205 static void increment_current_lock_count(files_struct *fsp,
206 enum brl_flavour lock_flav)
208 if (lock_flav == WINDOWS_LOCK &&
209 fsp->current_lock_count != NO_LOCKING_COUNT) {
210 /* blocking ie. pending, locks also count here,
211 * as this is an efficiency counter to avoid checking
212 * the lock db. on close. JRA. */
214 fsp->current_lock_count++;
215 } else {
216 /* Notice that this has had a POSIX lock request.
217 * We can't count locks after this so forget them.
219 fsp->current_lock_count = NO_LOCKING_COUNT;
223 static void decrement_current_lock_count(files_struct *fsp,
224 enum brl_flavour lock_flav)
226 if (lock_flav == WINDOWS_LOCK &&
227 fsp->current_lock_count != NO_LOCKING_COUNT) {
228 SMB_ASSERT(fsp->current_lock_count > 0);
229 fsp->current_lock_count--;
233 /****************************************************************************
234 Utility function called by locking requests.
235 ****************************************************************************/
237 struct byte_range_lock *do_lock(struct messaging_context *msg_ctx,
238 files_struct *fsp,
239 uint64_t smblctx,
240 uint64_t count,
241 uint64_t offset,
242 enum brl_type lock_type,
243 enum brl_flavour lock_flav,
244 bool blocking_lock,
245 NTSTATUS *perr,
246 uint64_t *psmblctx,
247 struct blocking_lock_record *blr)
249 struct byte_range_lock *br_lck = NULL;
251 /* silently return ok on print files as we don't do locking there */
252 if (fsp->print_file) {
253 *perr = NT_STATUS_OK;
254 return NULL;
257 if (!fsp->can_lock) {
258 *perr = fsp->is_directory ? NT_STATUS_INVALID_DEVICE_REQUEST : NT_STATUS_INVALID_HANDLE;
259 return NULL;
262 if (!lp_locking(fsp->conn->params)) {
263 *perr = NT_STATUS_OK;
264 return NULL;
267 /* NOTE! 0 byte long ranges ARE allowed and should be stored */
269 DEBUG(10,("do_lock: lock flavour %s lock type %s start=%.0f len=%.0f "
270 "blocking_lock=%s requested for fnum %d file %s\n",
271 lock_flav_name(lock_flav), lock_type_name(lock_type),
272 (double)offset, (double)count, blocking_lock ? "true" :
273 "false", fsp->fnum, fsp_str_dbg(fsp)));
275 br_lck = brl_get_locks(talloc_tos(), fsp);
276 if (!br_lck) {
277 *perr = NT_STATUS_NO_MEMORY;
278 return NULL;
281 *perr = brl_lock(msg_ctx,
282 br_lck,
283 smblctx,
284 messaging_server_id(fsp->conn->sconn->msg_ctx),
285 offset,
286 count,
287 lock_type,
288 lock_flav,
289 blocking_lock,
290 psmblctx,
291 blr);
293 DEBUG(10, ("do_lock: returning status=%s\n", nt_errstr(*perr)));
295 increment_current_lock_count(fsp, lock_flav);
296 return br_lck;
299 /****************************************************************************
300 Utility function called by unlocking requests.
301 ****************************************************************************/
303 NTSTATUS do_unlock(struct messaging_context *msg_ctx,
304 files_struct *fsp,
305 uint64_t smblctx,
306 uint64_t count,
307 uint64_t offset,
308 enum brl_flavour lock_flav)
310 bool ok = False;
311 struct byte_range_lock *br_lck = NULL;
313 if (!fsp->can_lock) {
314 return fsp->is_directory ? NT_STATUS_INVALID_DEVICE_REQUEST : NT_STATUS_INVALID_HANDLE;
317 if (!lp_locking(fsp->conn->params)) {
318 return NT_STATUS_OK;
321 DEBUG(10,("do_unlock: unlock start=%.0f len=%.0f requested for fnum %d file %s\n",
322 (double)offset, (double)count, fsp->fnum,
323 fsp_str_dbg(fsp)));
325 br_lck = brl_get_locks(talloc_tos(), fsp);
326 if (!br_lck) {
327 return NT_STATUS_NO_MEMORY;
330 ok = brl_unlock(msg_ctx,
331 br_lck,
332 smblctx,
333 messaging_server_id(fsp->conn->sconn->msg_ctx),
334 offset,
335 count,
336 lock_flav);
338 TALLOC_FREE(br_lck);
340 if (!ok) {
341 DEBUG(10,("do_unlock: returning ERRlock.\n" ));
342 return NT_STATUS_RANGE_NOT_LOCKED;
345 decrement_current_lock_count(fsp, lock_flav);
346 return NT_STATUS_OK;
349 /****************************************************************************
350 Cancel any pending blocked locks.
351 ****************************************************************************/
353 NTSTATUS do_lock_cancel(files_struct *fsp,
354 uint64 smblctx,
355 uint64_t count,
356 uint64_t offset,
357 enum brl_flavour lock_flav,
358 struct blocking_lock_record *blr)
360 bool ok = False;
361 struct byte_range_lock *br_lck = NULL;
363 if (!fsp->can_lock) {
364 return fsp->is_directory ?
365 NT_STATUS_INVALID_DEVICE_REQUEST : NT_STATUS_INVALID_HANDLE;
368 if (!lp_locking(fsp->conn->params)) {
369 return NT_STATUS_DOS(ERRDOS, ERRcancelviolation);
372 DEBUG(10,("do_lock_cancel: cancel start=%.0f len=%.0f requested for fnum %d file %s\n",
373 (double)offset, (double)count, fsp->fnum,
374 fsp_str_dbg(fsp)));
376 br_lck = brl_get_locks(talloc_tos(), fsp);
377 if (!br_lck) {
378 return NT_STATUS_NO_MEMORY;
381 ok = brl_lock_cancel(br_lck,
382 smblctx,
383 messaging_server_id(fsp->conn->sconn->msg_ctx),
384 offset,
385 count,
386 lock_flav,
387 blr);
389 TALLOC_FREE(br_lck);
391 if (!ok) {
392 DEBUG(10,("do_lock_cancel: returning ERRcancelviolation.\n" ));
393 return NT_STATUS_DOS(ERRDOS, ERRcancelviolation);
396 decrement_current_lock_count(fsp, lock_flav);
397 return NT_STATUS_OK;
400 /****************************************************************************
401 Remove any locks on this fd. Called from file_close().
402 ****************************************************************************/
404 void locking_close_file(struct messaging_context *msg_ctx,
405 files_struct *fsp,
406 enum file_close_type close_type)
408 struct byte_range_lock *br_lck;
410 if (!lp_locking(fsp->conn->params)) {
411 return;
414 /* If we have not outstanding locks or pending
415 * locks then we don't need to look in the lock db.
418 if (fsp->current_lock_count == 0) {
419 return;
422 br_lck = brl_get_locks(talloc_tos(),fsp);
424 if (br_lck) {
425 cancel_pending_lock_requests_by_fid(fsp, br_lck, close_type);
426 brl_close_fnum(msg_ctx, br_lck);
427 TALLOC_FREE(br_lck);
431 /*******************************************************************
432 Print out a share mode.
433 ********************************************************************/
435 char *share_mode_str(TALLOC_CTX *ctx, int num, const struct share_mode_entry *e)
437 return talloc_asprintf(ctx, "share_mode_entry[%d]: "
438 "pid = %s, share_access = 0x%x, private_options = 0x%x, "
439 "access_mask = 0x%x, mid = 0x%llx, type= 0x%x, gen_id = %llu, "
440 "uid = %u, flags = %u, file_id %s, name_hash = 0x%x",
441 num,
442 procid_str_static(&e->pid),
443 e->share_access, e->private_options,
444 e->access_mask, (unsigned long long)e->op_mid,
445 e->op_type, (unsigned long long)e->share_file_id,
446 (unsigned int)e->uid, (unsigned int)e->flags,
447 file_id_string_tos(&e->id),
448 (unsigned int)e->name_hash);
451 struct share_mode_lock *get_share_mode_lock(TALLOC_CTX *mem_ctx,
452 const struct file_id id)
454 return get_share_mode_lock_fresh(mem_ctx, id, NULL, NULL, NULL);
457 /*******************************************************************
458 Sets the service name and filename for rename.
459 At this point we emit "file renamed" messages to all
460 process id's that have this file open.
461 Based on an initial code idea from SATOH Fumiyasu <fumiya@samba.gr.jp>
462 ********************************************************************/
464 bool rename_share_filename(struct messaging_context *msg_ctx,
465 struct share_mode_lock *lck,
466 const char *servicepath,
467 uint32_t orig_name_hash,
468 uint32_t new_name_hash,
469 const struct smb_filename *smb_fname_dst)
471 struct share_mode_data *d = lck->data;
472 size_t sp_len;
473 size_t bn_len;
474 size_t sn_len;
475 size_t msg_len;
476 char *frm = NULL;
477 int i;
478 bool strip_two_chars = false;
479 bool has_stream = smb_fname_dst->stream_name != NULL;
481 DEBUG(10, ("rename_share_filename: servicepath %s newname %s\n",
482 servicepath, smb_fname_dst->base_name));
485 * rename_internal_fsp() and rename_internals() add './' to
486 * head of newname if newname does not contain a '/'.
488 if (smb_fname_dst->base_name[0] &&
489 smb_fname_dst->base_name[1] &&
490 smb_fname_dst->base_name[0] == '.' &&
491 smb_fname_dst->base_name[1] == '/') {
492 strip_two_chars = true;
495 d->servicepath = talloc_strdup(d, servicepath);
496 d->base_name = talloc_strdup(d, smb_fname_dst->base_name +
497 (strip_two_chars ? 2 : 0));
498 d->stream_name = talloc_strdup(d, smb_fname_dst->stream_name);
499 if (d->base_name == NULL ||
500 (has_stream && d->stream_name == NULL) ||
501 d->servicepath == NULL) {
502 DEBUG(0, ("rename_share_filename: talloc failed\n"));
503 return False;
505 d->modified = True;
507 sp_len = strlen(d->servicepath);
508 bn_len = strlen(d->base_name);
509 sn_len = has_stream ? strlen(d->stream_name) : 0;
511 msg_len = MSG_FILE_RENAMED_MIN_SIZE + sp_len + 1 + bn_len + 1 +
512 sn_len + 1;
514 /* Set up the name changed message. */
515 frm = talloc_array(d, char, msg_len);
516 if (!frm) {
517 return False;
520 push_file_id_24(frm, &d->id);
522 DEBUG(10,("rename_share_filename: msg_len = %u\n", (unsigned int)msg_len ));
524 strlcpy(&frm[24],
525 d->servicepath ? d->servicepath : "",
526 sp_len+1);
527 strlcpy(&frm[24 + sp_len + 1],
528 d->base_name ? d->base_name : "",
529 bn_len+1);
530 strlcpy(&frm[24 + sp_len + 1 + bn_len + 1],
531 d->stream_name ? d->stream_name : "",
532 sn_len+1);
534 /* Send the messages. */
535 for (i=0; i<d->num_share_modes; i++) {
536 struct share_mode_entry *se = &d->share_modes[i];
537 if (!is_valid_share_mode_entry(se)) {
538 continue;
541 /* If this is a hardlink to the inode
542 with a different name, skip this. */
543 if (se->name_hash != orig_name_hash) {
544 continue;
547 se->name_hash = new_name_hash;
549 /* But not to ourselves... */
550 if (procid_is_me(&se->pid)) {
551 continue;
554 DEBUG(10,("rename_share_filename: sending rename message to "
555 "pid %s file_id %s sharepath %s base_name %s "
556 "stream_name %s\n",
557 procid_str_static(&se->pid),
558 file_id_string_tos(&d->id),
559 d->servicepath, d->base_name,
560 has_stream ? d->stream_name : ""));
562 messaging_send_buf(msg_ctx, se->pid, MSG_SMB_FILE_RENAME,
563 (uint8 *)frm, msg_len);
566 return True;
569 void get_file_infos(struct file_id id,
570 uint32_t name_hash,
571 bool *delete_on_close,
572 struct timespec *write_time)
574 struct share_mode_lock *lck;
576 if (delete_on_close) {
577 *delete_on_close = false;
580 if (write_time) {
581 ZERO_STRUCTP(write_time);
584 if (!(lck = fetch_share_mode_unlocked(talloc_tos(), id))) {
585 return;
588 if (delete_on_close) {
589 *delete_on_close = is_delete_on_close_set(lck, name_hash);
592 if (write_time) {
593 struct timespec wt;
595 wt = lck->data->changed_write_time;
596 if (null_timespec(wt)) {
597 wt = lck->data->old_write_time;
600 *write_time = wt;
603 TALLOC_FREE(lck);
606 bool is_valid_share_mode_entry(const struct share_mode_entry *e)
608 int num_props = 0;
610 num_props += ((e->op_type == NO_OPLOCK) ? 1 : 0);
611 num_props += (EXCLUSIVE_OPLOCK_TYPE(e->op_type) ? 1 : 0);
612 num_props += (LEVEL_II_OPLOCK_TYPE(e->op_type) ? 1 : 0);
614 SMB_ASSERT(num_props <= 1);
615 return (num_props != 0);
618 bool is_deferred_open_entry(const struct share_mode_entry *e)
620 return (e->op_type == DEFERRED_OPEN_ENTRY);
623 /*******************************************************************
624 Fill a share mode entry.
625 ********************************************************************/
627 static void fill_share_mode_entry(struct share_mode_entry *e,
628 files_struct *fsp,
629 uid_t uid, uint64_t mid, uint16 op_type)
631 ZERO_STRUCTP(e);
632 e->pid = messaging_server_id(fsp->conn->sconn->msg_ctx);
633 e->share_access = fsp->share_access;
634 e->private_options = fsp->fh->private_options;
635 e->access_mask = fsp->access_mask;
636 e->op_mid = mid;
637 e->op_type = op_type;
638 e->time.tv_sec = fsp->open_time.tv_sec;
639 e->time.tv_usec = fsp->open_time.tv_usec;
640 e->id = fsp->file_id;
641 e->share_file_id = fsp->fh->gen_id;
642 e->uid = (uint32)uid;
643 e->flags = fsp->posix_open ? SHARE_MODE_FLAG_POSIX_OPEN : 0;
644 e->name_hash = fsp->name_hash;
647 static void fill_deferred_open_entry(struct share_mode_entry *e,
648 const struct timeval request_time,
649 struct file_id id,
650 struct server_id pid,
651 uint64_t mid)
653 ZERO_STRUCTP(e);
654 e->pid = pid;
655 e->op_mid = mid;
656 e->op_type = DEFERRED_OPEN_ENTRY;
657 e->time.tv_sec = request_time.tv_sec;
658 e->time.tv_usec = request_time.tv_usec;
659 e->id = id;
660 e->uid = (uint32)-1;
661 e->flags = 0;
664 static void add_share_mode_entry(struct share_mode_data *d,
665 const struct share_mode_entry *entry)
667 ADD_TO_ARRAY(d, struct share_mode_entry, *entry,
668 &d->share_modes, &d->num_share_modes);
669 d->modified = True;
672 void set_share_mode(struct share_mode_lock *lck, files_struct *fsp,
673 uid_t uid, uint64_t mid, uint16 op_type)
675 struct share_mode_entry entry;
676 fill_share_mode_entry(&entry, fsp, uid, mid, op_type);
677 add_share_mode_entry(lck->data, &entry);
680 void add_deferred_open(struct share_mode_lock *lck, uint64_t mid,
681 struct timeval request_time,
682 struct server_id pid, struct file_id id)
684 struct share_mode_entry entry;
685 fill_deferred_open_entry(&entry, request_time, id, pid, mid);
686 add_share_mode_entry(lck->data, &entry);
689 /*******************************************************************
690 Check if two share mode entries are identical, ignoring oplock
691 and mid info and desired_access. (Removed paranoia test - it's
692 not automatically a logic error if they are identical. JRA.)
693 ********************************************************************/
695 static bool share_modes_identical(struct share_mode_entry *e1,
696 struct share_mode_entry *e2)
698 /* We used to check for e1->share_access == e2->share_access here
699 as well as the other fields but 2 different DOS or FCB opens
700 sharing the same share mode entry may validly differ in
701 fsp->share_access field. */
703 return (procid_equal(&e1->pid, &e2->pid) &&
704 file_id_equal(&e1->id, &e2->id) &&
705 e1->share_file_id == e2->share_file_id );
708 static bool deferred_open_identical(struct share_mode_entry *e1,
709 struct share_mode_entry *e2)
711 return (procid_equal(&e1->pid, &e2->pid) &&
712 (e1->op_mid == e2->op_mid) &&
713 file_id_equal(&e1->id, &e2->id));
716 static struct share_mode_entry *find_share_mode_entry(struct share_mode_data *d,
717 struct share_mode_entry *entry)
719 int i;
721 for (i=0; i<d->num_share_modes; i++) {
722 struct share_mode_entry *e = &d->share_modes[i];
723 if (is_valid_share_mode_entry(entry) &&
724 is_valid_share_mode_entry(e) &&
725 share_modes_identical(e, entry)) {
726 return e;
728 if (is_deferred_open_entry(entry) &&
729 is_deferred_open_entry(e) &&
730 deferred_open_identical(e, entry)) {
731 return e;
734 return NULL;
737 /*******************************************************************
738 Del the share mode of a file for this process. Return the number of
739 entries left.
740 ********************************************************************/
742 bool del_share_mode(struct share_mode_lock *lck, files_struct *fsp)
744 struct share_mode_entry entry, *e;
746 /* Don't care about the pid owner being correct here - just a search. */
747 fill_share_mode_entry(&entry, fsp, (uid_t)-1, 0, NO_OPLOCK);
749 e = find_share_mode_entry(lck->data, &entry);
750 if (e == NULL) {
751 return False;
753 *e = lck->data->share_modes[lck->data->num_share_modes-1];
754 lck->data->num_share_modes -= 1;
755 lck->data->modified = True;
756 return True;
759 void del_deferred_open_entry(struct share_mode_lock *lck, uint64_t mid,
760 struct server_id pid)
762 struct share_mode_entry entry, *e;
764 fill_deferred_open_entry(&entry, timeval_zero(),
765 lck->data->id, pid, mid);
767 e = find_share_mode_entry(lck->data, &entry);
768 if (e == NULL) {
769 return;
771 *e = lck->data->share_modes[lck->data->num_share_modes-1];
772 lck->data->num_share_modes -= 1;
773 lck->data->modified = True;
776 /*******************************************************************
777 Remove an oplock mid and mode entry from a share mode.
778 ********************************************************************/
780 bool remove_share_oplock(struct share_mode_lock *lck, files_struct *fsp)
782 struct share_mode_entry entry, *e;
784 /* Don't care about the pid owner being correct here - just a search. */
785 fill_share_mode_entry(&entry, fsp, (uid_t)-1, 0, NO_OPLOCK);
787 e = find_share_mode_entry(lck->data, &entry);
788 if (e == NULL) {
789 return False;
792 if (EXCLUSIVE_OPLOCK_TYPE(e->op_type)) {
794 * Going from exclusive or batch,
795 * we always go through FAKE_LEVEL_II
796 * first.
798 if (!EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
799 smb_panic("remove_share_oplock: logic error");
801 e->op_type = FAKE_LEVEL_II_OPLOCK;
802 } else {
803 e->op_type = NO_OPLOCK;
805 lck->data->modified = True;
806 return True;
809 /*******************************************************************
810 Downgrade a oplock type from exclusive to level II.
811 ********************************************************************/
813 bool downgrade_share_oplock(struct share_mode_lock *lck, files_struct *fsp)
815 struct share_mode_entry entry, *e;
817 /* Don't care about the pid owner being correct here - just a search. */
818 fill_share_mode_entry(&entry, fsp, (uid_t)-1, 0, NO_OPLOCK);
820 e = find_share_mode_entry(lck->data, &entry);
821 if (e == NULL) {
822 return False;
825 e->op_type = LEVEL_II_OPLOCK;
826 lck->data->modified = True;
827 return True;
830 /*************************************************************************
831 Return a talloced copy of a struct security_unix_token. NULL on fail.
832 (Should this be in locking.c.... ?).
833 *************************************************************************/
835 static struct security_unix_token *copy_unix_token(TALLOC_CTX *ctx, const struct security_unix_token *tok)
837 struct security_unix_token *cpy;
839 cpy = talloc(ctx, struct security_unix_token);
840 if (!cpy) {
841 return NULL;
844 cpy->uid = tok->uid;
845 cpy->gid = tok->gid;
846 cpy->ngroups = tok->ngroups;
847 if (tok->ngroups) {
848 /* Make this a talloc child of cpy. */
849 cpy->groups = (gid_t *)talloc_memdup(
850 cpy, tok->groups, tok->ngroups * sizeof(gid_t));
851 if (!cpy->groups) {
852 TALLOC_FREE(cpy);
853 return NULL;
856 return cpy;
859 /****************************************************************************
860 Adds a delete on close token.
861 ****************************************************************************/
863 static bool add_delete_on_close_token(struct share_mode_data *d,
864 uint32_t name_hash,
865 const struct security_unix_token *tok)
867 struct delete_token *tmp, *dtl;
869 tmp = talloc_realloc(d, d->delete_tokens, struct delete_token,
870 d->num_delete_tokens+1);
871 if (tmp == NULL) {
872 return false;
874 d->delete_tokens = tmp;
875 dtl = &d->delete_tokens[d->num_delete_tokens];
877 dtl->name_hash = name_hash;
878 dtl->delete_token = copy_unix_token(d->delete_tokens, tok);
879 if (dtl->delete_token == NULL) {
880 return false;
882 d->num_delete_tokens += 1;
883 d->modified = true;
884 return true;
887 /****************************************************************************
888 Sets the delete on close flag over all share modes on this file.
889 Modify the share mode entry for all files open
890 on this device and inode to tell other smbds we have
891 changed the delete on close flag. This will be noticed
892 in the close code, the last closer will delete the file
893 if flag is set.
894 This makes a copy of any struct security_unix_token into the
895 lck entry. This function is used when the lock is already granted.
896 ****************************************************************************/
898 void set_delete_on_close_lck(files_struct *fsp,
899 struct share_mode_lock *lck,
900 bool delete_on_close,
901 const struct security_unix_token *tok)
903 struct share_mode_data *d = lck->data;
904 int i;
905 bool ret;
907 if (delete_on_close) {
908 SMB_ASSERT(tok != NULL);
909 } else {
910 SMB_ASSERT(tok == NULL);
913 for (i=0; i<d->num_delete_tokens; i++) {
914 struct delete_token *dt = &d->delete_tokens[i];
915 if (dt->name_hash == fsp->name_hash) {
916 d->modified = true;
917 if (delete_on_close == false) {
918 /* Delete this entry. */
919 TALLOC_FREE(dt->delete_token);
920 *dt = d->delete_tokens[
921 d->num_delete_tokens-1];
922 d->num_delete_tokens -= 1;
923 return;
925 /* Replace this token with the
926 given tok. */
927 TALLOC_FREE(dt->delete_token);
928 dt->delete_token = copy_unix_token(dt, tok);
929 SMB_ASSERT(dt->delete_token != NULL);
933 if (!delete_on_close) {
934 /* Nothing to delete - not found. */
935 return;
938 ret = add_delete_on_close_token(lck->data, fsp->name_hash, tok);
939 SMB_ASSERT(ret);
942 bool set_delete_on_close(files_struct *fsp, bool delete_on_close, const struct security_unix_token *tok)
944 struct share_mode_lock *lck;
946 DEBUG(10,("set_delete_on_close: %s delete on close flag for "
947 "fnum = %d, file %s\n",
948 delete_on_close ? "Adding" : "Removing", fsp->fnum,
949 fsp_str_dbg(fsp)));
951 lck = get_share_mode_lock(talloc_tos(), fsp->file_id);
952 if (lck == NULL) {
953 return False;
956 set_delete_on_close_lck(fsp, lck, delete_on_close,
957 delete_on_close ? tok : NULL);
959 if (fsp->is_directory) {
960 SMB_ASSERT(!is_ntfs_stream_smb_fname(fsp->fsp_name));
961 send_stat_cache_delete_message(fsp->conn->sconn->msg_ctx,
962 fsp->fsp_name->base_name);
965 TALLOC_FREE(lck);
967 fsp->delete_on_close = delete_on_close;
969 return True;
972 const struct security_unix_token *get_delete_on_close_token(struct share_mode_lock *lck, uint32_t name_hash)
974 int i;
976 DEBUG(10,("get_delete_on_close_token: name_hash = 0x%x\n",
977 (unsigned int)name_hash ));
979 for (i=0; i<lck->data->num_delete_tokens; i++) {
980 struct delete_token *dt = &lck->data->delete_tokens[i];
981 DEBUG(10,("get_delete_on_close_token: dtl->name_hash = 0x%x\n",
982 (unsigned int)dt->name_hash ));
983 if (dt->name_hash == name_hash) {
984 return dt->delete_token;
987 return NULL;
990 bool is_delete_on_close_set(struct share_mode_lock *lck, uint32_t name_hash)
992 return (get_delete_on_close_token(lck, name_hash) != NULL);
995 bool set_sticky_write_time(struct file_id fileid, struct timespec write_time)
997 struct share_mode_lock *lck;
999 DEBUG(5,("set_sticky_write_time: %s id=%s\n",
1000 timestring(talloc_tos(),
1001 convert_timespec_to_time_t(write_time)),
1002 file_id_string_tos(&fileid)));
1004 lck = get_share_mode_lock(talloc_tos(), fileid);
1005 if (lck == NULL) {
1006 return False;
1009 if (timespec_compare(&lck->data->changed_write_time, &write_time) != 0) {
1010 lck->data->modified = True;
1011 lck->data->changed_write_time = write_time;
1014 TALLOC_FREE(lck);
1015 return True;
1018 bool set_write_time(struct file_id fileid, struct timespec write_time)
1020 struct share_mode_lock *lck;
1022 DEBUG(5,("set_write_time: %s id=%s\n",
1023 timestring(talloc_tos(),
1024 convert_timespec_to_time_t(write_time)),
1025 file_id_string_tos(&fileid)));
1027 lck = get_share_mode_lock(talloc_tos(), fileid);
1028 if (lck == NULL) {
1029 return False;
1032 if (timespec_compare(&lck->data->old_write_time, &write_time) != 0) {
1033 lck->data->modified = True;
1034 lck->data->old_write_time = write_time;
1037 TALLOC_FREE(lck);
1038 return True;