source: trunk/server/source3/locking/locking.c@ 751

Last change on this file since 751 was 751, checked in by Silvan Scherrer, 13 years ago

Samba Server: updated trunk to 3.6.9

File size: 48.5 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: [email protected]
24 added support for shared memory implementation of share mode locking
25
26 May 1997. Jeremy Allison ([email protected]). Modified share mode
27 locking to deal with multiple share modes per open file.
28
29 September 1997. Jeremy Allison ([email protected]). Added oplock
30 support.
31
32 rewrtten completely to use new tdb code. Tridge, Dec '99
33
34 Added POSIX locking support. Jeremy Allison ([email protected]), 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.h"
43#include "../libcli/security/security.h"
44#include "serverid.h"
45#include "messages.h"
46#include "util_tdb.h"
47#include "../librpc/gen_ndr/ndr_security.h"
48
49#undef DBGC_CLASS
50#define DBGC_CLASS DBGC_LOCKING
51
52#define NO_LOCKING_COUNT (-1)
53
54/* the locking database handle */
55static struct db_context *lock_db;
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 = sconn_server_id(fsp->conn->sconn);
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 int strict_locking = lp_strict_locking(fsp->conn->params);
109 bool ret = False;
110
111 if (plock->size == 0) {
112 return True;
113 }
114
115 if (!lp_locking(fsp->conn->params) || !strict_locking) {
116 return True;
117 }
118
119 if (strict_locking == Auto) {
120 if (EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type) && (plock->lock_type == READ_LOCK || plock->lock_type == WRITE_LOCK)) {
121 DEBUG(10,("is_locked: optimisation - exclusive oplock on file %s\n", fsp_str_dbg(fsp)));
122 ret = True;
123 } else if ((fsp->oplock_type == LEVEL_II_OPLOCK) &&
124 (plock->lock_type == READ_LOCK)) {
125 DEBUG(10,("is_locked: optimisation - level II oplock on file %s\n", fsp_str_dbg(fsp)));
126 ret = True;
127 } else {
128 struct byte_range_lock *br_lck;
129
130 br_lck = brl_get_locks_readonly(fsp);
131 if (!br_lck) {
132 return True;
133 }
134 ret = brl_locktest(br_lck,
135 plock->context.smblctx,
136 plock->context.pid,
137 plock->start,
138 plock->size,
139 plock->lock_type,
140 plock->lock_flav);
141 }
142 } else {
143 struct byte_range_lock *br_lck;
144
145 br_lck = brl_get_locks_readonly(fsp);
146 if (!br_lck) {
147 return True;
148 }
149 ret = brl_locktest(br_lck,
150 plock->context.smblctx,
151 plock->context.pid,
152 plock->start,
153 plock->size,
154 plock->lock_type,
155 plock->lock_flav);
156 }
157
158 DEBUG(10,("strict_lock_default: flavour = %s brl start=%.0f "
159 "len=%.0f %s for fnum %d file %s\n",
160 lock_flav_name(plock->lock_flav),
161 (double)plock->start, (double)plock->size,
162 ret ? "unlocked" : "locked",
163 plock->fnum, fsp_str_dbg(fsp)));
164
165 return ret;
166}
167
168void strict_unlock_default(files_struct *fsp, struct lock_struct *plock)
169{
170}
171
172/****************************************************************************
173 Find out if a lock could be granted - return who is blocking us if we can't.
174****************************************************************************/
175
176NTSTATUS query_lock(files_struct *fsp,
177 uint64_t *psmblctx,
178 uint64_t *pcount,
179 uint64_t *poffset,
180 enum brl_type *plock_type,
181 enum brl_flavour lock_flav)
182{
183 struct byte_range_lock *br_lck = NULL;
184
185 if (!fsp->can_lock) {
186 return fsp->is_directory ? NT_STATUS_INVALID_DEVICE_REQUEST : NT_STATUS_INVALID_HANDLE;
187 }
188
189 if (!lp_locking(fsp->conn->params)) {
190 return NT_STATUS_OK;
191 }
192
193 br_lck = brl_get_locks_readonly(fsp);
194 if (!br_lck) {
195 return NT_STATUS_NO_MEMORY;
196 }
197
198 return brl_lockquery(br_lck,
199 psmblctx,
200 sconn_server_id(fsp->conn->sconn),
201 poffset,
202 pcount,
203 plock_type,
204 lock_flav);
205}
206
207static void increment_current_lock_count(files_struct *fsp,
208 enum brl_flavour lock_flav)
209{
210 if (lock_flav == WINDOWS_LOCK &&
211 fsp->current_lock_count != NO_LOCKING_COUNT) {
212 /* blocking ie. pending, locks also count here,
213 * as this is an efficiency counter to avoid checking
214 * the lock db. on close. JRA. */
215
216 fsp->current_lock_count++;
217 } else {
218 /* Notice that this has had a POSIX lock request.
219 * We can't count locks after this so forget them.
220 */
221 fsp->current_lock_count = NO_LOCKING_COUNT;
222 }
223}
224
225static void decrement_current_lock_count(files_struct *fsp,
226 enum brl_flavour lock_flav)
227{
228 if (lock_flav == WINDOWS_LOCK &&
229 fsp->current_lock_count != NO_LOCKING_COUNT) {
230 SMB_ASSERT(fsp->current_lock_count > 0);
231 fsp->current_lock_count--;
232 }
233}
234
235/****************************************************************************
236 Utility function called by locking requests.
237****************************************************************************/
238
239struct byte_range_lock *do_lock(struct messaging_context *msg_ctx,
240 files_struct *fsp,
241 uint64_t smblctx,
242 uint64_t count,
243 uint64_t offset,
244 enum brl_type lock_type,
245 enum brl_flavour lock_flav,
246 bool blocking_lock,
247 NTSTATUS *perr,
248 uint64_t *psmblctx,
249 struct blocking_lock_record *blr)
250{
251 struct byte_range_lock *br_lck = NULL;
252
253 /* silently return ok on print files as we don't do locking there */
254 if (fsp->print_file) {
255 *perr = NT_STATUS_OK;
256 return NULL;
257 }
258
259 if (!fsp->can_lock) {
260 *perr = fsp->is_directory ? NT_STATUS_INVALID_DEVICE_REQUEST : NT_STATUS_INVALID_HANDLE;
261 return NULL;
262 }
263
264 if (!lp_locking(fsp->conn->params)) {
265 *perr = NT_STATUS_OK;
266 return NULL;
267 }
268
269 /* NOTE! 0 byte long ranges ARE allowed and should be stored */
270
271 DEBUG(10,("do_lock: lock flavour %s lock type %s start=%.0f len=%.0f "
272 "blocking_lock=%s requested for fnum %d file %s\n",
273 lock_flav_name(lock_flav), lock_type_name(lock_type),
274 (double)offset, (double)count, blocking_lock ? "true" :
275 "false", fsp->fnum, fsp_str_dbg(fsp)));
276
277 br_lck = brl_get_locks(talloc_tos(), fsp);
278 if (!br_lck) {
279 *perr = NT_STATUS_NO_MEMORY;
280 return NULL;
281 }
282
283 *perr = brl_lock(msg_ctx,
284 br_lck,
285 smblctx,
286 sconn_server_id(fsp->conn->sconn),
287 offset,
288 count,
289 lock_type,
290 lock_flav,
291 blocking_lock,
292 psmblctx,
293 blr);
294
295 DEBUG(10, ("do_lock: returning status=%s\n", nt_errstr(*perr)));
296
297 increment_current_lock_count(fsp, lock_flav);
298 return br_lck;
299}
300
301/****************************************************************************
302 Utility function called by unlocking requests.
303****************************************************************************/
304
305NTSTATUS do_unlock(struct messaging_context *msg_ctx,
306 files_struct *fsp,
307 uint64_t smblctx,
308 uint64_t count,
309 uint64_t offset,
310 enum brl_flavour lock_flav)
311{
312 bool ok = False;
313 struct byte_range_lock *br_lck = NULL;
314
315 if (!fsp->can_lock) {
316 return fsp->is_directory ? NT_STATUS_INVALID_DEVICE_REQUEST : NT_STATUS_INVALID_HANDLE;
317 }
318
319 if (!lp_locking(fsp->conn->params)) {
320 return NT_STATUS_OK;
321 }
322
323 DEBUG(10,("do_unlock: unlock start=%.0f len=%.0f requested for fnum %d file %s\n",
324 (double)offset, (double)count, fsp->fnum,
325 fsp_str_dbg(fsp)));
326
327 br_lck = brl_get_locks(talloc_tos(), fsp);
328 if (!br_lck) {
329 return NT_STATUS_NO_MEMORY;
330 }
331
332 ok = brl_unlock(msg_ctx,
333 br_lck,
334 smblctx,
335 sconn_server_id(fsp->conn->sconn),
336 offset,
337 count,
338 lock_flav);
339
340 TALLOC_FREE(br_lck);
341
342 if (!ok) {
343 DEBUG(10,("do_unlock: returning ERRlock.\n" ));
344 return NT_STATUS_RANGE_NOT_LOCKED;
345 }
346
347 decrement_current_lock_count(fsp, lock_flav);
348 return NT_STATUS_OK;
349}
350
351/****************************************************************************
352 Cancel any pending blocked locks.
353****************************************************************************/
354
355NTSTATUS do_lock_cancel(files_struct *fsp,
356 uint64 smblctx,
357 uint64_t count,
358 uint64_t offset,
359 enum brl_flavour lock_flav,
360 struct blocking_lock_record *blr)
361{
362 bool ok = False;
363 struct byte_range_lock *br_lck = NULL;
364
365 if (!fsp->can_lock) {
366 return fsp->is_directory ?
367 NT_STATUS_INVALID_DEVICE_REQUEST : NT_STATUS_INVALID_HANDLE;
368 }
369
370 if (!lp_locking(fsp->conn->params)) {
371 return NT_STATUS_DOS(ERRDOS, ERRcancelviolation);
372 }
373
374 DEBUG(10,("do_lock_cancel: cancel start=%.0f len=%.0f requested for fnum %d file %s\n",
375 (double)offset, (double)count, fsp->fnum,
376 fsp_str_dbg(fsp)));
377
378 br_lck = brl_get_locks(talloc_tos(), fsp);
379 if (!br_lck) {
380 return NT_STATUS_NO_MEMORY;
381 }
382
383 ok = brl_lock_cancel(br_lck,
384 smblctx,
385 sconn_server_id(fsp->conn->sconn),
386 offset,
387 count,
388 lock_flav,
389 blr);
390
391 TALLOC_FREE(br_lck);
392
393 if (!ok) {
394 DEBUG(10,("do_lock_cancel: returning ERRcancelviolation.\n" ));
395 return NT_STATUS_DOS(ERRDOS, ERRcancelviolation);
396 }
397
398 decrement_current_lock_count(fsp, lock_flav);
399 return NT_STATUS_OK;
400}
401
402/****************************************************************************
403 Remove any locks on this fd. Called from file_close().
404****************************************************************************/
405
406void locking_close_file(struct messaging_context *msg_ctx,
407 files_struct *fsp,
408 enum file_close_type close_type)
409{
410 struct byte_range_lock *br_lck;
411
412 if (!lp_locking(fsp->conn->params)) {
413 return;
414 }
415
416 /* If we have not outstanding locks or pending
417 * locks then we don't need to look in the lock db.
418 */
419
420 if (fsp->current_lock_count == 0) {
421 return;
422 }
423
424 br_lck = brl_get_locks(talloc_tos(),fsp);
425
426 if (br_lck) {
427 cancel_pending_lock_requests_by_fid(fsp, br_lck, close_type);
428 brl_close_fnum(msg_ctx, br_lck);
429 TALLOC_FREE(br_lck);
430 }
431}
432
433/****************************************************************************
434 Initialise the locking functions.
435****************************************************************************/
436
437static bool locking_init_internal(bool read_only)
438{
439 brl_init(read_only);
440
441 if (lock_db)
442 return True;
443
444 lock_db = db_open(NULL, lock_path("locking.tdb"),
445 lp_open_files_db_hash_size(),
446 TDB_DEFAULT|TDB_VOLATILE|TDB_CLEAR_IF_FIRST|TDB_INCOMPATIBLE_HASH,
447 read_only?O_RDONLY:O_RDWR|O_CREAT, 0644);
448
449 if (!lock_db) {
450 DEBUG(0,("ERROR: Failed to initialise locking database\n"));
451 return False;
452 }
453
454 if (!posix_locking_init(read_only))
455 return False;
456
457 return True;
458}
459
460bool locking_init(void)
461{
462 return locking_init_internal(false);
463}
464
465bool locking_init_readonly(void)
466{
467 return locking_init_internal(true);
468}
469
470/*******************************************************************
471 Deinitialize the share_mode management.
472******************************************************************/
473
474bool locking_end(void)
475{
476 brl_shutdown();
477 TALLOC_FREE(lock_db);
478 return true;
479}
480
481/*******************************************************************
482 Form a static locking key for a dev/inode pair.
483******************************************************************/
484
485static TDB_DATA locking_key(const struct file_id *id, struct file_id *tmp)
486{
487 *tmp = *id;
488 return make_tdb_data((const uint8_t *)tmp, sizeof(*tmp));
489}
490
491/*******************************************************************
492 Print out a share mode.
493********************************************************************/
494
495char *share_mode_str(TALLOC_CTX *ctx, int num, const struct share_mode_entry *e)
496{
497 return talloc_asprintf(ctx, "share_mode_entry[%d]: %s "
498 "pid = %s, share_access = 0x%x, private_options = 0x%x, "
499 "access_mask = 0x%x, mid = 0x%llx, type= 0x%x, gen_id = %lu, "
500 "uid = %u, flags = %u, file_id %s, name_hash = 0x%x",
501 num,
502 e->op_type == UNUSED_SHARE_MODE_ENTRY ? "UNUSED" : "",
503 procid_str_static(&e->pid),
504 e->share_access, e->private_options,
505 e->access_mask, (unsigned long long)e->op_mid,
506 e->op_type, e->share_file_id,
507 (unsigned int)e->uid, (unsigned int)e->flags,
508 file_id_string_tos(&e->id),
509 (unsigned int)e->name_hash);
510}
511
512/*******************************************************************
513 Print out a share mode table.
514********************************************************************/
515
516static void print_share_mode_table(struct locking_data *data)
517{
518 int num_share_modes = data->u.s.num_share_mode_entries;
519 struct share_mode_entry *shares =
520 (struct share_mode_entry *)(data + 1);
521 int i;
522
523 for (i = 0; i < num_share_modes; i++) {
524 struct share_mode_entry entry;
525 char *str;
526
527 /*
528 * We need to memcpy the entry here due to alignment
529 * restrictions that are not met when directly accessing
530 * shares[i]
531 */
532
533 memcpy(&entry, &shares[i], sizeof(struct share_mode_entry));
534 str = share_mode_str(talloc_tos(), i, &entry);
535
536 DEBUG(10,("print_share_mode_table: %s\n", str ? str : ""));
537 TALLOC_FREE(str);
538 }
539}
540
541static int parse_delete_tokens_list(struct share_mode_lock *lck,
542 struct locking_data *pdata,
543 const TDB_DATA dbuf)
544{
545 uint8_t *p = dbuf.dptr + sizeof(struct locking_data) +
546 (lck->num_share_modes *
547 sizeof(struct share_mode_entry));
548 uint8_t *end_ptr = dbuf.dptr + (dbuf.dsize - 2);
549 int delete_tokens_size = 0;
550 int i;
551
552 lck->delete_tokens = NULL;
553
554 for (i = 0; i < pdata->u.s.num_delete_token_entries; i++) {
555 DATA_BLOB blob;
556 enum ndr_err_code ndr_err;
557 struct delete_token_list *pdtl;
558 size_t token_len = 0;
559
560 pdtl = TALLOC_ZERO_P(lck, struct delete_token_list);
561 if (pdtl == NULL) {
562 DEBUG(0,("parse_delete_tokens_list: talloc failed"));
563 return -1;
564 }
565 /* Copy out the name_hash. */
566 memcpy(&pdtl->name_hash, p, sizeof(pdtl->name_hash));
567 p += sizeof(pdtl->name_hash);
568 delete_tokens_size += sizeof(pdtl->name_hash);
569
570 pdtl->delete_token = TALLOC_ZERO_P(pdtl, struct security_unix_token);
571 if (pdtl->delete_token == NULL) {
572 DEBUG(0,("parse_delete_tokens_list: talloc failed"));
573 return -1;
574 }
575
576 if (p >= end_ptr) {
577 DEBUG(0,("parse_delete_tokens_list: corrupt data"));
578 return -1;
579 }
580
581 blob.data = p;
582 blob.length = end_ptr - p;
583
584 ndr_err = ndr_pull_struct_blob(&blob,
585 pdtl,
586 pdtl->delete_token,
587 (ndr_pull_flags_fn_t)ndr_pull_security_unix_token);
588 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
589 DEBUG(1, ("parse_delete_tokens_list: "
590 "ndr_pull_security_unix_token failed\n"));
591 return -1;
592 }
593
594 token_len = ndr_size_security_unix_token(pdtl->delete_token, 0);
595
596 p += token_len;
597 delete_tokens_size += token_len;
598
599 if (p >= end_ptr) {
600 DEBUG(0,("parse_delete_tokens_list: corrupt data"));
601 return -1;
602 }
603
604 pdtl->delete_nt_token = TALLOC_ZERO_P(pdtl, struct security_token);
605 if (pdtl->delete_nt_token == NULL) {
606 DEBUG(0,("parse_delete_tokens_list: talloc failed"));
607 return -1;
608 }
609
610 blob.data = p;
611 blob.length = end_ptr - p;
612
613 ndr_err = ndr_pull_struct_blob(&blob,
614 pdtl,
615 pdtl->delete_nt_token,
616 (ndr_pull_flags_fn_t)ndr_pull_security_token);
617 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
618 DEBUG(1, ("parse_delete_tokens_list: "
619 "ndr_pull_security_token failed\n"));
620 return -1;
621 }
622
623 token_len = ndr_size_security_token(pdtl->delete_nt_token, 0);
624
625 p += token_len;
626 delete_tokens_size += token_len;
627
628 /* Add to the list. */
629 DLIST_ADD(lck->delete_tokens, pdtl);
630 }
631
632 return delete_tokens_size;
633}
634
635/*******************************************************************
636 Get all share mode entries for a dev/inode pair.
637********************************************************************/
638
639static bool parse_share_modes(const TDB_DATA dbuf, struct share_mode_lock *lck)
640{
641 struct locking_data data;
642 int delete_tokens_size;
643 int i;
644
645 if (dbuf.dsize < sizeof(struct locking_data)) {
646 smb_panic("parse_share_modes: buffer too short");
647 }
648
649 memcpy(&data, dbuf.dptr, sizeof(data));
650
651 lck->old_write_time = data.u.s.old_write_time;
652 lck->changed_write_time = data.u.s.changed_write_time;
653 lck->num_share_modes = data.u.s.num_share_mode_entries;
654
655 DEBUG(10, ("parse_share_modes: owrt: %s, "
656 "cwrt: %s, ntok: %u, num_share_modes: %d\n",
657 timestring(talloc_tos(),
658 convert_timespec_to_time_t(lck->old_write_time)),
659 timestring(talloc_tos(),
660 convert_timespec_to_time_t(
661 lck->changed_write_time)),
662 (unsigned int)data.u.s.num_delete_token_entries,
663 lck->num_share_modes));
664
665 if ((lck->num_share_modes < 0) || (lck->num_share_modes > 1000000)) {
666 DEBUG(0, ("invalid number of share modes: %d\n",
667 lck->num_share_modes));
668 smb_panic("parse_share_modes: invalid number of share modes");
669 }
670
671 lck->share_modes = NULL;
672
673 if (lck->num_share_modes != 0) {
674
675 if (dbuf.dsize < (sizeof(struct locking_data) +
676 (lck->num_share_modes *
677 sizeof(struct share_mode_entry)))) {
678 smb_panic("parse_share_modes: buffer too short");
679 }
680
681 lck->share_modes = (struct share_mode_entry *)
682 TALLOC_MEMDUP(lck,
683 dbuf.dptr+sizeof(struct locking_data),
684 lck->num_share_modes *
685 sizeof(struct share_mode_entry));
686
687 if (lck->share_modes == NULL) {
688 smb_panic("parse_share_modes: talloc failed");
689 }
690 }
691
692 /* Get any delete tokens. */
693 delete_tokens_size = parse_delete_tokens_list(lck, &data, dbuf);
694 if (delete_tokens_size < 0) {
695 smb_panic("parse_share_modes: parse_delete_tokens_list failed");
696 }
697
698 /* Save off the associated service path and filename. */
699 lck->servicepath = (const char *)dbuf.dptr + sizeof(struct locking_data) +
700 (lck->num_share_modes * sizeof(struct share_mode_entry)) +
701 delete_tokens_size;
702
703 lck->base_name = (const char *)dbuf.dptr + sizeof(struct locking_data) +
704 (lck->num_share_modes * sizeof(struct share_mode_entry)) +
705 delete_tokens_size +
706 strlen(lck->servicepath) + 1;
707
708 lck->stream_name = (const char *)dbuf.dptr + sizeof(struct locking_data) +
709 (lck->num_share_modes * sizeof(struct share_mode_entry)) +
710 delete_tokens_size +
711 strlen(lck->servicepath) + 1 +
712 strlen(lck->base_name) + 1;
713
714 /*
715 * Ensure that each entry has a real process attached.
716 */
717
718 for (i = 0; i < lck->num_share_modes; i++) {
719 struct share_mode_entry *entry_p = &lck->share_modes[i];
720 char *str = NULL;
721 if (DEBUGLEVEL >= 10) {
722 str = share_mode_str(NULL, i, entry_p);
723 }
724 DEBUG(10,("parse_share_modes: %s\n",
725 str ? str : ""));
726 if (!serverid_exists(&entry_p->pid)) {
727 DEBUG(10,("parse_share_modes: deleted %s\n",
728 str ? str : ""));
729 entry_p->op_type = UNUSED_SHARE_MODE_ENTRY;
730 lck->modified = True;
731 }
732 TALLOC_FREE(str);
733 }
734
735 return True;
736}
737
738static TDB_DATA unparse_share_modes(const struct share_mode_lock *lck)
739{
740 TDB_DATA result;
741 int num_valid = 0;
742 int i;
743 struct locking_data *data;
744 ssize_t offset;
745 ssize_t sp_len, bn_len, sn_len;
746 uint32_t delete_tokens_size = 0;
747 struct delete_token_list *pdtl = NULL;
748 uint32_t num_delete_token_entries = 0;
749
750 result.dptr = NULL;
751 result.dsize = 0;
752
753 for (i=0; i<lck->num_share_modes; i++) {
754 if (!is_unused_share_mode_entry(&lck->share_modes[i])) {
755 num_valid += 1;
756 }
757 }
758
759 if (num_valid == 0) {
760 return result;
761 }
762
763 sp_len = strlen(lck->servicepath);
764 bn_len = strlen(lck->base_name);
765 sn_len = lck->stream_name != NULL ? strlen(lck->stream_name) : 0;
766
767 for (pdtl = lck->delete_tokens; pdtl; pdtl = pdtl->next) {
768 num_delete_token_entries++;
769 delete_tokens_size += sizeof(uint32_t) +
770 ndr_size_security_unix_token(pdtl->delete_token, 0) +
771 ndr_size_security_token(pdtl->delete_nt_token, 0);
772 }
773
774 result.dsize = sizeof(*data) +
775 lck->num_share_modes * sizeof(struct share_mode_entry) +
776 delete_tokens_size +
777 sp_len + 1 +
778 bn_len + 1 +
779 sn_len + 1;
780 result.dptr = TALLOC_ARRAY(lck, uint8, result.dsize);
781
782 if (result.dptr == NULL) {
783 smb_panic("talloc failed");
784 }
785
786 data = (struct locking_data *)result.dptr;
787 ZERO_STRUCTP(data);
788 data->u.s.num_share_mode_entries = lck->num_share_modes;
789 data->u.s.old_write_time = lck->old_write_time;
790 data->u.s.changed_write_time = lck->changed_write_time;
791 data->u.s.num_delete_token_entries = num_delete_token_entries;
792
793 DEBUG(10,("unparse_share_modes: owrt: %s cwrt: %s, ntok: %u, "
794 "num: %d\n",
795 timestring(talloc_tos(),
796 convert_timespec_to_time_t(lck->old_write_time)),
797 timestring(talloc_tos(),
798 convert_timespec_to_time_t(
799 lck->changed_write_time)),
800 (unsigned int)data->u.s.num_delete_token_entries,
801 data->u.s.num_share_mode_entries));
802
803 memcpy(result.dptr + sizeof(*data), lck->share_modes,
804 sizeof(struct share_mode_entry)*lck->num_share_modes);
805 offset = sizeof(*data) +
806 sizeof(struct share_mode_entry)*lck->num_share_modes;