source: vendor/current/source3/locking/locking.c

Last change on this file was 988, checked in by Silvan Scherrer, 9 years ago

Samba Server: update vendor to version 4.4.3

File size: 33.3 KB
Line 
1/*
2 Unix SMB/CIFS implementation.
3 Locking functions
4 Copyright (C) Andrew Tridgell 1992-2000
5 Copyright (C) Jeremy Allison 1992-2006
6 Copyright (C) Volker Lendecke 2005
7
8 This program is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 3 of the License, or
11 (at your option) any later version.
12
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
17
18 You should have received a copy of the GNU General Public License
19 along with this program. If not, see <http://www.gnu.org/licenses/>.
20
21 Revision History:
22
23 12 aug 96: Erik.Devriendt@te6.siemens.be
24 added support for shared memory implementation of share mode locking
25
26 May 1997. Jeremy Allison (jallison@whistle.com). Modified share mode
27 locking to deal with multiple share modes per open file.
28
29 September 1997. Jeremy Allison (jallison@whistle.com). Added oplock
30 support.
31
32 rewritten completely to use new tdb code. Tridge, Dec '99
33
34 Added POSIX locking support. Jeremy Allison (jeremy@valinux.com), Apr. 2000.
35 Added Unix Extensions POSIX locking support. Jeremy Allison Mar 2006.
36*/
37
38#include "includes.h"
39#include "system/filesys.h"
40#include "locking/proto.h"
41#include "smbd/globals.h"
42#include "dbwrap/dbwrap.h"
43#include "dbwrap/dbwrap_open.h"
44#include "../libcli/security/security.h"
45#include "serverid.h"
46#include "messages.h"
47#include "util_tdb.h"
48#include "../librpc/gen_ndr/ndr_open_files.h"
49#include "librpc/gen_ndr/ndr_file_id.h"
50#include "locking/leases_db.h"
51
52#undef DBGC_CLASS
53#define DBGC_CLASS DBGC_LOCKING
54
55#define NO_LOCKING_COUNT (-1)
56
57/****************************************************************************
58 Debugging aids :-).
59****************************************************************************/
60
61const char *lock_type_name(enum brl_type lock_type)
62{
63 switch (lock_type) {
64 case READ_LOCK:
65 return "READ";
66 case WRITE_LOCK:
67 return "WRITE";
68 case PENDING_READ_LOCK:
69 return "PENDING_READ";
70 case PENDING_WRITE_LOCK:
71 return "PENDING_WRITE";
72 default:
73 return "other";
74 }
75}
76
77const char *lock_flav_name(enum brl_flavour lock_flav)
78{
79 return (lock_flav == WINDOWS_LOCK) ? "WINDOWS_LOCK" : "POSIX_LOCK";
80}
81
82/****************************************************************************
83 Utility function called to see if a file region is locked.
84 Called in the read/write codepath.
85****************************************************************************/
86
87void init_strict_lock_struct(files_struct *fsp,
88 uint64_t smblctx,
89 br_off start,
90 br_off size,
91 enum brl_type lock_type,
92 struct lock_struct *plock)
93{
94 SMB_ASSERT(lock_type == READ_LOCK || lock_type == WRITE_LOCK);
95
96 plock->context.smblctx = smblctx;
97 plock->context.tid = fsp->conn->cnum;
98 plock->context.pid = messaging_server_id(fsp->conn->sconn->msg_ctx);
99 plock->start = start;
100 plock->size = size;
101 plock->fnum = fsp->fnum;
102 plock->lock_type = lock_type;
103 plock->lock_flav = lp_posix_cifsu_locktype(fsp);
104}
105
106bool strict_lock_default(files_struct *fsp, struct lock_struct *plock)
107{
108 struct byte_range_lock *br_lck;
109 int strict_locking = lp_strict_locking(fsp->conn->params);
110 bool ret = False;
111
112 if (plock->size == 0) {
113 return True;
114 }
115
116 if (!lp_locking(fsp->conn->params) || !strict_locking) {
117 return True;
118 }
119
120 if (strict_locking == Auto) {
121 if (EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type) &&
122 (plock->lock_type == READ_LOCK ||
123 plock->lock_type == WRITE_LOCK)) {
124 DEBUG(10, ("is_locked: optimisation - exclusive oplock "
125 "on file %s\n", fsp_str_dbg(fsp)));
126 return true;
127 }
128 if ((fsp->oplock_type == LEVEL_II_OPLOCK) &&
129 (plock->lock_type == READ_LOCK)) {
130 DEBUG(10, ("is_locked: optimisation - level II oplock "
131 "on file %s\n", fsp_str_dbg(fsp)));
132 return true;
133 }
134 }
135
136 br_lck = brl_get_locks_readonly(fsp);
137 if (!br_lck) {
138 return true;
139 }
140 ret = brl_locktest(br_lck, plock);
141
142 if (!ret) {
143 /*
144 * We got a lock conflict. Retry with rw locks to enable
145 * autocleanup. This is the slow path anyway.
146 */
147 br_lck = brl_get_locks(talloc_tos(), fsp);
148 ret = brl_locktest(br_lck, plock);
149 TALLOC_FREE(br_lck);
150 }
151
152 DEBUG(10, ("strict_lock_default: flavour = %s brl start=%ju "
153 "len=%ju %s for fnum %ju file %s\n",
154 lock_flav_name(plock->lock_flav),
155 (uintmax_t)plock->start, (uintmax_t)plock->size,
156 ret ? "unlocked" : "locked",
157 (uintmax_t)plock->fnum, fsp_str_dbg(fsp)));
158
159 return ret;
160}
161
162void strict_unlock_default(files_struct *fsp, struct lock_struct *plock)
163{
164}
165
166/****************************************************************************
167 Find out if a lock could be granted - return who is blocking us if we can't.
168****************************************************************************/
169
170NTSTATUS query_lock(files_struct *fsp,
171 uint64_t *psmblctx,
172 uint64_t *pcount,
173 uint64_t *poffset,
174 enum brl_type *plock_type,
175 enum brl_flavour lock_flav)
176{
177 struct byte_range_lock *br_lck = NULL;
178
179 if (!fsp->can_lock) {
180 return fsp->is_directory ? NT_STATUS_INVALID_DEVICE_REQUEST : NT_STATUS_INVALID_HANDLE;
181 }
182
183 if (!lp_locking(fsp->conn->params)) {
184 return NT_STATUS_OK;
185 }
186
187 br_lck = brl_get_locks_readonly(fsp);
188 if (!br_lck) {
189 return NT_STATUS_NO_MEMORY;
190 }
191
192 return brl_lockquery(br_lck,
193 psmblctx,
194 messaging_server_id(fsp->conn->sconn->msg_ctx),
195 poffset,
196 pcount,
197 plock_type,
198 lock_flav);
199}
200
201static void increment_current_lock_count(files_struct *fsp,
202 enum brl_flavour lock_flav)
203{
204 if (lock_flav == WINDOWS_LOCK &&
205 fsp->current_lock_count != NO_LOCKING_COUNT) {
206 /* blocking ie. pending, locks also count here,
207 * as this is an efficiency counter to avoid checking
208 * the lock db. on close. JRA. */
209
210 fsp->current_lock_count++;
211 } else {
212 /* Notice that this has had a POSIX lock request.
213 * We can't count locks after this so forget them.
214 */
215 fsp->current_lock_count = NO_LOCKING_COUNT;
216 }
217}
218
219static void decrement_current_lock_count(files_struct *fsp,
220 enum brl_flavour lock_flav)
221{
222 if (lock_flav == WINDOWS_LOCK &&
223 fsp->current_lock_count != NO_LOCKING_COUNT) {
224 SMB_ASSERT(fsp->current_lock_count > 0);
225 fsp->current_lock_count--;
226 }
227}
228
229/****************************************************************************
230 Utility function called by locking requests.
231****************************************************************************/
232
233struct byte_range_lock *do_lock(struct messaging_context *msg_ctx,
234 files_struct *fsp,
235 uint64_t smblctx,
236 uint64_t count,
237 uint64_t offset,
238 enum brl_type lock_type,
239 enum brl_flavour lock_flav,
240 bool blocking_lock,
241 NTSTATUS *perr,
242 uint64_t *psmblctx)
243{
244 struct byte_range_lock *br_lck = NULL;
245
246 /* silently return ok on print files as we don't do locking there */
247 if (fsp->print_file) {
248 *perr = NT_STATUS_OK;
249 return NULL;
250 }
251
252 if (!fsp->can_lock) {
253 *perr = fsp->is_directory ? NT_STATUS_INVALID_DEVICE_REQUEST : NT_STATUS_INVALID_HANDLE;
254 return NULL;
255 }
256
257 if (!lp_locking(fsp->conn->params)) {
258 *perr = NT_STATUS_OK;
259 return NULL;
260 }
261
262 /* NOTE! 0 byte long ranges ARE allowed and should be stored */
263
264 DEBUG(10,("do_lock: lock flavour %s lock type %s start=%ju len=%ju "
265 "blocking_lock=%s requested for %s file %s\n",
266 lock_flav_name(lock_flav), lock_type_name(lock_type),
267 (uintmax_t)offset, (uintmax_t)count, blocking_lock ? "true" :
268 "false", fsp_fnum_dbg(fsp), fsp_str_dbg(fsp)));
269
270 br_lck = brl_get_locks(talloc_tos(), fsp);
271 if (!br_lck) {
272 *perr = NT_STATUS_NO_MEMORY;
273 return NULL;
274 }
275
276 *perr = brl_lock(msg_ctx,
277 br_lck,
278 smblctx,
279 messaging_server_id(fsp->conn->sconn->msg_ctx),
280 offset,
281 count,
282 lock_type,
283 lock_flav,
284 blocking_lock,
285 psmblctx);
286
287 DEBUG(10, ("do_lock: returning status=%s\n", nt_errstr(*perr)));
288
289 increment_current_lock_count(fsp, lock_flav);
290 return br_lck;
291}
292
293/****************************************************************************
294 Utility function called by unlocking requests.
295****************************************************************************/
296
297NTSTATUS do_unlock(struct messaging_context *msg_ctx,
298 files_struct *fsp,
299 uint64_t smblctx,
300 uint64_t count,
301 uint64_t offset,
302 enum brl_flavour lock_flav)
303{
304 bool ok = False;
305 struct byte_range_lock *br_lck = NULL;
306
307 if (!fsp->can_lock) {
308 return fsp->is_directory ? NT_STATUS_INVALID_DEVICE_REQUEST : NT_STATUS_INVALID_HANDLE;
309 }
310
311 if (!lp_locking(fsp->conn->params)) {
312 return NT_STATUS_OK;
313 }
314
315 DEBUG(10, ("do_unlock: unlock start=%ju len=%ju requested for %s file "
316 "%s\n", (uintmax_t)offset, (uintmax_t)count,
317 fsp_fnum_dbg(fsp), fsp_str_dbg(fsp)));
318
319 br_lck = brl_get_locks(talloc_tos(), fsp);
320 if (!br_lck) {
321 return NT_STATUS_NO_MEMORY;
322 }
323
324 ok = brl_unlock(msg_ctx,
325 br_lck,
326 smblctx,
327 messaging_server_id(fsp->conn->sconn->msg_ctx),
328 offset,
329 count,
330 lock_flav);
331
332 TALLOC_FREE(br_lck);
333
334 if (!ok) {
335 DEBUG(10,("do_unlock: returning ERRlock.\n" ));
336 return NT_STATUS_RANGE_NOT_LOCKED;
337 }
338
339 decrement_current_lock_count(fsp, lock_flav);
340 return NT_STATUS_OK;
341}
342
343/****************************************************************************
344 Cancel any pending blocked locks.
345****************************************************************************/
346
347NTSTATUS do_lock_cancel(files_struct *fsp,
348 uint64_t smblctx,
349 uint64_t count,
350 uint64_t offset,
351 enum brl_flavour lock_flav)
352{
353 bool ok = False;
354 struct byte_range_lock *br_lck = NULL;
355
356 if (!fsp->can_lock) {
357 return fsp->is_directory ?
358 NT_STATUS_INVALID_DEVICE_REQUEST : NT_STATUS_INVALID_HANDLE;
359 }
360
361 if (!lp_locking(fsp->conn->params)) {
362 return NT_STATUS_DOS(ERRDOS, ERRcancelviolation);
363 }
364
365 DEBUG(10, ("do_lock_cancel: cancel start=%ju len=%ju requested for "
366 "%s file %s\n", (uintmax_t)offset, (uintmax_t)count,
367 fsp_fnum_dbg(fsp), fsp_str_dbg(fsp)));
368
369 br_lck = brl_get_locks(talloc_tos(), fsp);
370 if (!br_lck) {
371 return NT_STATUS_NO_MEMORY;
372 }
373
374 ok = brl_lock_cancel(br_lck,
375 smblctx,
376 messaging_server_id(fsp->conn->sconn->msg_ctx),
377 offset,
378 count,
379 lock_flav);
380
381 TALLOC_FREE(br_lck);
382
383 if (!ok) {
384 DEBUG(10,("do_lock_cancel: returning ERRcancelviolation.\n" ));
385 return NT_STATUS_DOS(ERRDOS, ERRcancelviolation);
386 }
387
388 decrement_current_lock_count(fsp, lock_flav);
389 return NT_STATUS_OK;
390}
391
392/****************************************************************************
393 Remove any locks on this fd. Called from file_close().
394****************************************************************************/
395
396void locking_close_file(struct messaging_context *msg_ctx,
397 files_struct *fsp,
398 enum file_close_type close_type)
399{
400 struct byte_range_lock *br_lck;
401
402 if (!lp_locking(fsp->conn->params)) {
403 return;
404 }
405
406 /* If we have no outstanding locks or pending
407 * locks then we don't need to look in the lock db.
408 */
409
410 if (fsp->current_lock_count == 0) {
411 return;
412 }
413
414 br_lck = brl_get_locks(talloc_tos(),fsp);
415
416 if (br_lck) {
417 cancel_pending_lock_requests_by_fid(fsp, br_lck, close_type);
418 brl_close_fnum(msg_ctx, br_lck);
419 TALLOC_FREE(br_lck);
420 }
421}
422
423/*******************************************************************
424 Print out a share mode.
425********************************************************************/
426
427char *share_mode_str(TALLOC_CTX *ctx, int num, const struct share_mode_entry *e)
428{
429 struct server_id_buf tmp;
430
431 return talloc_asprintf(ctx, "share_mode_entry[%d]: "
432 "pid = %s, share_access = 0x%x, private_options = 0x%x, "
433 "access_mask = 0x%x, mid = 0x%llx, type= 0x%x, gen_id = %llu, "
434 "uid = %u, flags = %u, file_id %s, name_hash = 0x%x",
435 num,
436 server_id_str_buf(e->pid, &tmp),
437 e->share_access, e->private_options,
438 e->access_mask, (unsigned long long)e->op_mid,
439 e->op_type, (unsigned long long)e->share_file_id,
440 (unsigned int)e->uid, (unsigned int)e->flags,
441 file_id_string_tos(&e->id),
442 (unsigned int)e->name_hash);
443}
444
445/*******************************************************************
446 Fetch a share mode where we know one MUST exist. This call reference
447 counts it internally to allow for nested lock fetches.
448********************************************************************/
449
450struct share_mode_lock *get_existing_share_mode_lock(TALLOC_CTX *mem_ctx,
451 const struct file_id id)
452{
453 return get_share_mode_lock(mem_ctx, id, NULL, NULL, NULL);
454}
455
456/*******************************************************************
457 Sets the service name and filename for rename.
458 At this point we emit "file renamed" messages to all
459 process id's that have this file open.
460 Based on an initial code idea from SATOH Fumiyasu <fumiya@samba.gr.jp>
461********************************************************************/
462
463bool rename_share_filename(struct messaging_context *msg_ctx,
464 struct share_mode_lock *lck,
465 struct file_id id,
466 const char *servicepath,
467 uint32_t orig_name_hash,
468 uint32_t new_name_hash,
469 const struct smb_filename *smb_fname_dst)
470{
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 uint32_t i;
478 bool strip_two_chars = false;
479 bool has_stream = smb_fname_dst->stream_name != NULL;
480 struct server_id self_pid = messaging_server_id(msg_ctx);
481
482 DEBUG(10, ("rename_share_filename: servicepath %s newname %s\n",
483 servicepath, smb_fname_dst->base_name));
484
485 /*
486 * rename_internal_fsp() and rename_internals() add './' to
487 * head of newname if newname does not contain a '/'.
488 */
489 if (smb_fname_dst->base_name[0] &&
490 smb_fname_dst->base_name[1] &&
491 smb_fname_dst->base_name[0] == '.' &&
492 smb_fname_dst->base_name[1] == '/') {
493 strip_two_chars = true;
494 }
495
496 d->servicepath = talloc_strdup(d, servicepath);
497 d->base_name = talloc_strdup(d, smb_fname_dst->base_name +
498 (strip_two_chars ? 2 : 0));
499 d->stream_name = talloc_strdup(d, smb_fname_dst->stream_name);
500 if (d->base_name == NULL ||
501 (has_stream && d->stream_name == NULL) ||
502 d->servicepath == NULL) {
503 DEBUG(0, ("rename_share_filename: talloc failed\n"));
504 return False;
505 }
506 d->modified = True;
507
508 sp_len = strlen(d->servicepath);
509 bn_len = strlen(d->base_name);
510 sn_len = has_stream ? strlen(d->stream_name) : 0;
511
512 msg_len = MSG_FILE_RENAMED_MIN_SIZE + sp_len + 1 + bn_len + 1 +
513 sn_len + 1;
514
515 /* Set up the name changed message. */
516 frm = talloc_array(d, char, msg_len);
517 if (!frm) {
518 return False;
519 }
520
521 push_file_id_24(frm, &id);
522
523 DEBUG(10,("rename_share_filename: msg_len = %u\n", (unsigned int)msg_len ));
524
525 strlcpy(&frm[24],
526 d->servicepath ? d->servicepath : "",
527 sp_len+1);
528 strlcpy(&frm[24 + sp_len + 1],
529 d->base_name ? d->base_name : "",
530 bn_len+1);
531 strlcpy(&frm[24 + sp_len + 1 + bn_len + 1],
532 d->stream_name ? d->stream_name : "",
533 sn_len+1);
534
535 /* Send the messages. */
536 for (i=0; i<d->num_share_modes; i++) {
537 struct share_mode_entry *se = &d->share_modes[i];
538 struct server_id_buf tmp;
539
540 if (!is_valid_share_mode_entry(se)) {
541 continue;
542 }
543
544 /* If this is a hardlink to the inode
545 with a different name, skip this. */
546 if (se->name_hash != orig_name_hash) {
547 continue;
548 }
549
550 se->name_hash = new_name_hash;
551
552 /* But not to ourselves... */
553 if (serverid_equal(&se->pid, &self_pid)) {
554 continue;
555 }
556
557 if (share_mode_stale_pid(d, i)) {
558 continue;
559 }
560
561 DEBUG(10,("rename_share_filename: sending rename message to "
562 "pid %s file_id %s sharepath %s base_name %s "
563 "stream_name %s\n",
564 server_id_str_buf(se->pid, &tmp),
565 file_id_string_tos(&id),
566 d->servicepath, d->base_name,
567 has_stream ? d->stream_name : ""));
568
569 messaging_send_buf(msg_ctx, se->pid, MSG_SMB_FILE_RENAME,
570 (uint8_t *)frm, msg_len);
571 }
572
573 for (i=0; i<d->num_leases; i++) {
574 /* Update the filename in leases_db. */
575 NTSTATUS status;
576 struct share_mode_lease *l;
577
578 l = &d->leases[i];
579
580 status = leases_db_rename(&l->client_guid,
581 &l->lease_key,
582 &id,
583 d->servicepath,
584 d->base_name,
585 d->stream_name);
586 if (!NT_STATUS_IS_OK(status)) {
587 /* Any error recovery possible here ? */
588 DEBUG(1,("Failed to rename lease key for "
589 "renamed file %s:%s. %s\n",
590 d->base_name,
591 d->stream_name,
592 nt_errstr(status)));
593 continue;
594 }
595 }
596
597 return True;
598}
599
600void get_file_infos(struct file_id id,
601 uint32_t name_hash,
602 bool *delete_on_close,
603 struct timespec *write_time)
604{
605 struct share_mode_lock *lck;
606
607 if (delete_on_close) {
608 *delete_on_close = false;
609 }
610
611 if (write_time) {
612 ZERO_STRUCTP(write_time);
613 }
614
615 if (!(lck = fetch_share_mode_unlocked(talloc_tos(), id))) {
616 return;
617 }
618
619 if (delete_on_close) {
620 *delete_on_close = is_delete_on_close_set(lck, name_hash);
621 }
622
623 if (write_time) {
624 *write_time = get_share_mode_write_time(lck);
625 }
626
627 TALLOC_FREE(lck);
628}
629
630bool is_valid_share_mode_entry(const struct share_mode_entry *e)
631{
632 int num_props = 0;
633
634 if (e->stale) {
635 return false;
636 }
637
638 num_props += ((e->op_type == NO_OPLOCK) ? 1 : 0);
639 num_props += (EXCLUSIVE_OPLOCK_TYPE(e->op_type) ? 1 : 0);
640 num_props += (LEVEL_II_OPLOCK_TYPE(e->op_type) ? 1 : 0);
641 num_props += (e->op_type == LEASE_OPLOCK);
642
643 if ((num_props > 1) && serverid_exists(&e->pid)) {
644 smb_panic("Invalid share mode entry");
645 }
646 return (num_props != 0);
647}
648
649/*
650 * See if we need to remove a lease being referred to by a
651 * share mode that is being marked stale or deleted.
652 */
653
654static void remove_share_mode_lease(struct share_mode_data *d,
655 struct share_mode_entry *e)
656{
657 struct GUID client_guid;
658 struct smb2_lease_key lease_key;
659 uint16_t op_type;
660 uint32_t lease_idx;
661 uint32_t i;
662
663 op_type = e->op_type;
664 e->op_type = NO_OPLOCK;
665
666 d->modified = true;
667
668 if (op_type != LEASE_OPLOCK) {
669 return;
670 }
671
672 /*
673 * This used to reference a lease. If there's no other one referencing
674 * it, remove it.
675 */
676
677 lease_idx = e->lease_idx;
678 e->lease_idx = UINT32_MAX;
679
680 for (i=0; i<d->num_share_modes; i++) {
681 if (d->share_modes[i].stale) {
682 continue;
683 }
684 if (e == &d->share_modes[i]) {
685 /* Not ourselves. */
686 continue;
687 }
688 if (d->share_modes[i].lease_idx == lease_idx) {
689 break;
690 }
691 }
692 if (i < d->num_share_modes) {
693 /*
694 * Found another one
695 */
696 return;
697 }
698
699 memcpy(&client_guid,
700 &d->leases[lease_idx].client_guid,
701 sizeof(client_guid));
702 lease_key = d->leases[lease_idx].lease_key;
703
704 d->num_leases -= 1;
705 d->leases[lease_idx] = d->leases[d->num_leases];
706
707 /*
708 * We changed the lease array. Fix all references to it.
709 */
710 for (i=0; i<d->num_share_modes; i++) {
711 if (d->share_modes[i].lease_idx == d->num_leases) {
712 d->share_modes[i].lease_idx = lease_idx;
713 d->share_modes[i].lease = &d->leases[lease_idx];
714 }
715 }
716
717 {
718 NTSTATUS status;
719
720 status = leases_db_del(&client_guid,
721 &lease_key,
722 &e->id);
723
724 DEBUG(10, ("%s: leases_db_del returned %s\n", __func__,
725 nt_errstr(status)));
726 }
727}
728
729/*
730 * In case d->share_modes[i] conflicts with something or otherwise is
731 * being used, we need to make sure the corresponding process still
732 * exists.
733 */
734bool share_mode_stale_pid(struct share_mode_data *d, uint32_t idx)
735{
736 struct server_id_buf tmp;
737 struct share_mode_entry *e;
738
739 if (idx > d->num_share_modes) {
740 DEBUG(1, ("Asking for index %u, only %u around\n",
741 idx, (unsigned)d->num_share_modes));
742 return false;
743 }
744 e = &d->share_modes[idx];
745 if (e->stale) {
746 /*
747 * Checked before
748 */
749 return true;
750 }
751 if (serverid_exists(&e->pid)) {
752 DEBUG(10, ("PID %s (index %u out of %u) still exists\n",
753 server_id_str_buf(e->pid, &tmp), idx,
754 (unsigned)d->num_share_modes));
755 return false;
756 }
757 DEBUG(10, ("PID %s (index %u out of %u) does not exist anymore\n",
758 server_id_str_buf(e->pid, &tmp), idx,
759 (unsigned)d->num_share_modes));
760
761 e->stale = true;
762
763 if (d->num_delete_tokens != 0) {
764 uint32_t i, num_stale;
765
766 /*
767 * We cannot have any delete tokens
768 * if there are no valid share modes.
769 */
770
771 num_stale = 0;
772
773 for (i=0; i<d->num_share_modes; i++) {
774 if (d->share_modes[i].stale) {
775 num_stale += 1;
776 }
777 }
778
779 if (num_stale == d->num_share_modes) {
780 /*
781 * No non-stale share mode found
782 */
783 TALLOC_FREE(d->delete_tokens);
784 d->num_delete_tokens = 0;
785 }
786 }
787
788 remove_share_mode_lease(d, e);
789
790 d->modified = true;
791 return true;
792}
793
794void remove_stale_share_mode_entries(struct share_mode_data *d)
795{
796 uint32_t i;
797
798 i = 0;
799 while (i < d->num_share_modes) {
800 if (d->share_modes[i].stale) {
801 struct share_mode_entry *m = d->share_modes;
802 m[i] = m[d->num_share_modes-1];
803 d->num_share_modes -= 1;
804 } else {
805 i += 1;
806 }
807 }
808}
809
810bool set_share_mode(struct share_mode_lock *lck, struct files_struct *fsp,
811 uid_t uid, uint64_t mid, uint16_t op_type,
812 uint32_t lease_idx)
813{
814 struct share_mode_data *d = lck->data;
815 struct share_mode_entry *tmp, *e;
816 struct share_mode_lease *lease = NULL;
817
818 if (lease_idx == UINT32_MAX) {
819 lease = NULL;
820 } else if (lease_idx >= d->num_leases) {
821 return false;
822 } else {
823 lease = &d->leases[lease_idx];
824 }
825
826 tmp = talloc_realloc(d, d->share_modes, struct share_mode_entry,
827 d->num_share_modes+1);
828 if (tmp == NULL) {
829 return false;
830 }
831 d->share_modes = tmp;
832 e = &d->share_modes[d->num_share_modes];
833 d->num_share_modes += 1;
834 d->modified = true;
835
836 ZERO_STRUCTP(e);
837 e->pid = messaging_server_id(fsp->conn->sconn->msg_ctx);
838 e->share_access = fsp->share_access;
839 e->private_options = fsp->fh->private_options;
840 e->access_mask = fsp->access_mask;
841 e->op_mid = mid;
842 e->op_type = op_type;
843 e->lease_idx = lease_idx;
844 e->lease = lease;
845 e->time.tv_sec = fsp->open_time.tv_sec;
846 e->time.tv_usec = fsp->open_time.tv_usec;
847 e->id = fsp->file_id;
848 e->share_file_id = fsp->fh->gen_id;
849 e->uid = (uint32_t)uid;
850 e->flags = (fsp->posix_flags & FSP_POSIX_FLAGS_OPEN) ?
851 SHARE_MODE_FLAG_POSIX_OPEN : 0;
852 e->name_hash = fsp->name_hash;
853
854 return true;
855}
856
857static struct share_mode_entry *find_share_mode_entry(
858 struct share_mode_lock *lck, files_struct *fsp)
859{
860 struct share_mode_data *d = lck->data;
861 struct server_id pid;
862 int i;
863
864 pid = messaging_server_id(fsp->conn->sconn->msg_ctx);
865
866 for (i=0; i<d->num_share_modes; i++) {
867 struct share_mode_entry *e = &d->share_modes[i];
868
869 if (!is_valid_share_mode_entry(e)) {
870 continue;
871 }
872 if (!serverid_equal(&pid, &e->pid)) {
873 continue;
874 }
875 if (!file_id_equal(&fsp->file_id, &e->id)) {
876 continue;
877 }
878 if (fsp->fh->gen_id != e->share_file_id) {
879 continue;
880 }
881 return e;
882 }
883 return NULL;
884}
885
886/*******************************************************************
887 Del the share mode of a file for this process. Return the number of
888 entries left.
889********************************************************************/
890
891bool del_share_mode(struct share_mode_lock *lck, files_struct *fsp)
892{
893 struct share_mode_entry *e;
894
895 e = find_share_mode_entry(lck, fsp);
896 if (e == NULL) {
897 return False;
898 }
899 remove_share_mode_lease(lck->data, e);
900 *e = lck->data->share_modes[lck->data->num_share_modes-1];
901 lck->data->num_share_modes -= 1;
902 lck->data->modified = True;
903 return True;
904}
905
906bool mark_share_mode_disconnected(struct share_mode_lock *lck,
907 struct files_struct *fsp)
908{
909 struct share_mode_entry *e;
910
911 if (lck->data->num_share_modes != 1) {
912 return false;
913 }
914
915 if (fsp->op == NULL) {
916 return false;
917 }
918 if (!fsp->op->global->durable) {
919 return false;
920 }
921
922 e = find_share_mode_entry(lck, fsp);
923 if (e == NULL) {
924 return false;
925 }
926
927 DEBUG(10, ("Marking share mode entry disconnected for durable handle\n"));
928
929 server_id_set_disconnected(&e->pid);
930
931 /*
932 * On reopen the caller needs to check that
933 * the client comes with the correct handle.
934 */
935 e->share_file_id = fsp->op->global->open_persistent_id;
936
937 lck->data->modified = true;
938 return true;
939}
940
941/*******************************************************************
942 Remove an oplock mid and mode entry from a share mode.
943********************************************************************/
944
945bool remove_share_oplock(struct share_mode_lock *lck, files_struct *fsp)
946{
947 struct share_mode_data *d = lck->data;
948 struct share_mode_entry *e;
949
950 e = find_share_mode_entry(lck, fsp);
951 if (e == NULL) {
952 return False;
953 }
954
955 remove_share_mode_lease(d, e);
956 d->modified = True;
957 return true;
958}
959
960/*******************************************************************
961 Downgrade a oplock type from exclusive to level II.
962********************************************************************/
963
964bool downgrade_share_oplock(struct share_mode_lock *lck, files_struct *fsp)
965{
966 struct share_mode_entry *e;
967
968 e = find_share_mode_entry(lck, fsp);
969 if (e == NULL) {
970 return False;
971 }
972
973 e->op_type = LEVEL_II_OPLOCK;
974 lck->data->modified = True;
975 return True;
976}
977
978NTSTATUS downgrade_share_lease(struct smbd_server_connection *sconn,
979 struct share_mode_lock *lck,
980 const struct smb2_lease_key *key,
981 uint32_t new_lease_state,
982 struct share_mode_lease **_l)
983{
984 struct share_mode_data *d = lck->data;
985 struct share_mode_lease *l;
986 uint32_t i;
987
988 *_l = NULL;
989
990 for (i=0; i<d->num_leases; i++) {
991 if (smb2_lease_equal(&sconn->client->connections->smb2.client.guid,
992 key,
993 &d->leases[i].client_guid,
994 &d->leases[i].lease_key)) {
995 break;
996 }
997 }
998 if (i == d->num_leases) {
999 DEBUG(10, ("lease not found\n"));
1000 return NT_STATUS_INVALID_PARAMETER;
1001 }
1002
1003 l = &d->leases[i];
1004
1005 if (!l->breaking) {
1006 DEBUG(1, ("Attempt to break from %d to %d - but we're not in breaking state\n",
1007 (int)l->current_state, (int)new_lease_state));
1008 return NT_STATUS_UNSUCCESSFUL;
1009 }
1010
1011 /*
1012 * Can't upgrade anything: l->breaking_to_requested (and l->current_state)
1013 * must be a strict bitwise superset of new_lease_state
1014 */
1015 if ((new_lease_state & l->breaking_to_requested) != new_lease_state) {
1016 DEBUG(1, ("Attempt to upgrade from %d to %d - expected %d\n",
1017 (int)l->current_state, (int)new_lease_state,
1018 (int)l->breaking_to_requested));
1019 return NT_STATUS_REQUEST_NOT_ACCEPTED;
1020 }
1021
1022 if (l->current_state != new_lease_state) {
1023 l->current_state = new_lease_state;
1024 d->modified = true;
1025 }
1026
1027 if ((new_lease_state & ~l->breaking_to_required) != 0) {
1028 DEBUG(5, ("lease state %d not fully broken from %d to %d\n",
1029 (int)new_lease_state,
1030 (int)l->current_state,
1031 (int)l->breaking_to_required));
1032 l->breaking_to_requested = l->breaking_to_required;
1033 if (l->current_state & (~SMB2_LEASE_READ)) {
1034 /*
1035 * Here we break in steps, as windows does
1036 * see the breaking3 and v2_breaking3 tests.
1037 */
1038 l->breaking_to_requested |= SMB2_LEASE_READ;
1039 }
1040 d->modified = true;
1041 *_l = l;
1042 return NT_STATUS_OPLOCK_BREAK_IN_PROGRESS;
1043 }
1044
1045 DEBUG(10, ("breaking from %d to %d - expected %d\n",
1046 (int)l->current_state, (int)new_lease_state,
1047 (int)l->breaking_to_requested));
1048
1049 l->breaking_to_requested = 0;
1050 l->breaking_to_required = 0;
1051 l->breaking = false;
1052
1053 d->modified = true;
1054
1055 return NT_STATUS_OK;
1056}
1057
1058/****************************************************************************
1059 Adds a delete on close token.
1060****************************************************************************/
1061
1062static bool add_delete_on_close_token(struct share_mode_data *d,
1063 uint32_t name_hash,
1064 const struct security_token *nt_tok,
1065 const struct security_unix_token *tok)
1066{
1067 struct delete_token *tmp, *dtl;
1068
1069 tmp = talloc_realloc(d, d->delete_tokens, struct delete_token,
1070 d->num_delete_tokens+1);
1071 if (tmp == NULL) {
1072 return false;
1073 }
1074 d->delete_tokens = tmp;
1075 dtl = &d->delete_tokens[d->num_delete_tokens];
1076
1077 dtl->name_hash = name_hash;
1078 dtl->delete_nt_token = dup_nt_token(d->delete_tokens, nt_tok);
1079 if (dtl->delete_nt_token == NULL) {
1080 return false;
1081 }
1082 dtl->delete_token = copy_unix_token(d->delete_tokens, tok);
1083 if (dtl->delete_token == NULL) {
1084 return false;
1085 }
1086 d->num_delete_tokens += 1;
1087 d->modified = true;
1088 return true;
1089}
1090
1091void reset_delete_on_close_lck(files_struct *fsp,
1092 struct share_mode_lock *lck)
1093{
1094 struct share_mode_data *d = lck->data;
1095 uint32_t i;
1096
1097 for (i=0; i<d->num_delete_tokens; i++) {
1098 struct delete_token *dt = &d->delete_tokens[i];
1099
1100 if (dt->name_hash == fsp->name_hash) {
1101 d->modified = true;
1102
1103 /* Delete this entry. */
1104 TALLOC_FREE(dt->delete_nt_token);
1105 TALLOC_FREE(dt->delete_token);
1106 *dt = d->delete_tokens[d->num_delete_tokens-1];
1107 d->num_delete_tokens -= 1;
1108 }
1109 }
1110}
1111
1112/****************************************************************************
1113 Sets the delete on close flag over all share modes on this file.
1114 Modify the share mode entry for all files open
1115 on this device and inode to tell other smbds we have
1116 changed the delete on close flag. This will be noticed
1117 in the close code, the last closer will delete the file
1118 if flag is set.
1119 This makes a copy of any struct security_unix_token into the
1120 lck entry. This function is used when the lock is already granted.
1121****************************************************************************/
1122
1123void set_delete_on_close_lck(files_struct *fsp,
1124 struct share_mode_lock *lck,
1125 const struct security_token *nt_tok,
1126 const struct security_unix_token *tok)
1127{
1128 struct messaging_context *msg_ctx = fsp->conn->sconn->msg_ctx;
1129 struct share_mode_data *d = lck->data;
1130 uint32_t i;
1131 bool ret;
1132 DATA_BLOB fid_blob = {};
1133 enum ndr_err_code ndr_err;
1134
1135 SMB_ASSERT(nt_tok != NULL);
1136 SMB_ASSERT(tok != NULL);
1137
1138 for (i=0; i<d->num_delete_tokens; i++) {
1139 struct delete_token *dt = &d->delete_tokens[i];
1140 if (dt->name_hash == fsp->name_hash) {
1141 d->modified = true;
1142
1143 /* Replace this token with the given tok. */
1144 TALLOC_FREE(dt->delete_nt_token);
1145 dt->delete_nt_token = dup_nt_token(dt, nt_tok);
1146 SMB_ASSERT(dt->delete_nt_token != NULL);
1147 TALLOC_FREE(dt->delete_token);
1148 dt->delete_token = copy_unix_token(dt, tok);
1149 SMB_ASSERT(dt->delete_token != NULL);
1150
1151 return;
1152 }
1153 }
1154
1155 ret = add_delete_on_close_token(lck->data, fsp->name_hash, nt_tok, tok);
1156 SMB_ASSERT(ret);
1157
1158 ndr_err = ndr_push_struct_blob(&fid_blob, talloc_tos(), &fsp->file_id,
1159 (ndr_push_flags_fn_t)ndr_push_file_id);
1160 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
1161 DEBUG(10, ("ndr_push_file_id failed: %s\n",
1162 ndr_errstr(ndr_err)));
1163 }
1164
1165 for (i=0; i<d->num_share_modes; i++) {
1166 struct share_mode_entry *e = &d->share_modes[i];
1167 NTSTATUS status;
1168
1169 status = messaging_send(
1170 msg_ctx, e->pid, MSG_SMB_NOTIFY_CANCEL_DELETED,
1171 &fid_blob);
1172
1173 if (!NT_STATUS_IS_OK(status)) {
1174 struct server_id_buf tmp;
1175 DEBUG(10, ("%s: messaging_send to %s returned %s\n",
1176 __func__, server_id_str_buf(e->pid, &tmp),
1177 nt_errstr(status)));
1178 }
1179 }
1180
1181 TALLOC_FREE(fid_blob.data);
1182}
1183
1184bool set_delete_on_close(files_struct *fsp, bool delete_on_close,
1185 const struct security_token *nt_tok,
1186 const struct security_unix_token *tok)
1187{
1188 struct share_mode_lock *lck;
1189
1190 DEBUG(10,("set_delete_on_close: %s delete on close flag for "
1191 "%s, file %s\n",
1192 delete_on_close ? "Adding" : "Removing", fsp_fnum_dbg(fsp),
1193 fsp_str_dbg(fsp)));
1194
1195 lck = get_existing_share_mode_lock(talloc_tos(), fsp->file_id);
1196 if (lck == NULL) {
1197 return False;
1198 }
1199
1200 if (delete_on_close) {
1201 set_delete_on_close_lck(fsp, lck, nt_tok, tok);
1202 } else {
1203 reset_delete_on_close_lck(fsp, lck);
1204 }
1205
1206 if (fsp->is_directory) {
1207 SMB_ASSERT(!is_ntfs_stream_smb_fname(fsp->fsp_name));
1208 send_stat_cache_delete_message(fsp->conn->sconn->msg_ctx,
1209 fsp->fsp_name->base_name);
1210 }
1211
1212 TALLOC_FREE(lck);
1213
1214 fsp->delete_on_close = delete_on_close;
1215
1216 return True;
1217}
1218
1219static struct delete_token *find_delete_on_close_token(
1220 struct share_mode_data *d, uint32_t name_hash)
1221{
1222 uint32_t i;
1223
1224 DEBUG(10, ("find_delete_on_close_token: name_hash = 0x%x\n",
1225 (unsigned int)name_hash));
1226
1227 for (i=0; i<d->num_delete_tokens; i++) {
1228 struct delete_token *dt = &d->delete_tokens[i];
1229
1230 DEBUG(10, ("find__delete_on_close_token: dt->name_hash = 0x%x\n",
1231 (unsigned int)dt->name_hash ));
1232 if (dt->name_hash == name_hash) {
1233 return dt;
1234 }
1235 }
1236 return NULL;
1237}
1238
1239/****************************************************************************
1240 Return the NT token and UNIX token if there's a match. Return true if
1241 found, false if not.
1242****************************************************************************/
1243
1244bool get_delete_on_close_token(struct share_mode_lock *lck,
1245 uint32_t name_hash,
1246 const struct security_token **pp_nt_tok,
1247 const struct security_unix_token **pp_tok)
1248{
1249 struct delete_token *dt;
1250
1251 dt = find_delete_on_close_token(lck->data, name_hash);
1252 if (dt == NULL) {
1253 return false;
1254 }
1255 *pp_nt_tok = dt->delete_nt_token;
1256 *pp_tok = dt->delete_token;
1257 return true;
1258}
1259
1260bool is_delete_on_close_set(struct share_mode_lock *lck, uint32_t name_hash)
1261{
1262 return find_delete_on_close_token(lck->data, name_hash) != NULL;
1263}
1264
1265bool set_sticky_write_time(struct file_id fileid, struct timespec write_time)
1266{
1267 struct share_mode_lock *lck;
1268
1269 DEBUG(5,("set_sticky_write_time: %s id=%s\n",
1270 timestring(talloc_tos(),
1271 convert_timespec_to_time_t(write_time)),
1272 file_id_string_tos(&fileid)));
1273
1274 lck = get_existing_share_mode_lock(talloc_tos(), fileid);
1275 if (lck == NULL) {
1276 return False;
1277 }
1278
1279 if (timespec_compare(&lck->data->changed_write_time, &write_time) != 0) {
1280 lck->data->modified = True;
1281 lck->data->changed_write_time = write_time;
1282 }
1283
1284 TALLOC_FREE(lck);
1285 return True;
1286}
1287
1288bool set_write_time(struct file_id fileid, struct timespec write_time)
1289{
1290 struct share_mode_lock *lck;
1291
1292 DEBUG(5,("set_write_time: %s id=%s\n",
1293 timestring(talloc_tos(),
1294 convert_timespec_to_time_t(write_time)),
1295 file_id_string_tos(&fileid)));
1296
1297 lck = get_existing_share_mode_lock(talloc_tos(), fileid);
1298 if (lck == NULL) {
1299 return False;
1300 }
1301
1302 if (timespec_compare(&lck->data->old_write_time, &write_time) != 0) {
1303 lck->data->modified = True;
1304 lck->data->old_write_time = write_time;
1305 }
1306
1307 TALLOC_FREE(lck);
1308 return True;
1309}
1310
1311struct timespec get_share_mode_write_time(struct share_mode_lock *lck)
1312{
1313 struct share_mode_data *d = lck->data;
1314
1315 if (!null_timespec(d->changed_write_time)) {
1316 return d->changed_write_time;
1317 }
1318 return d->old_write_time;
1319}
Note: See TracBrowser for help on using the repository browser.