source: branches/samba-3.2.x/source/locking/locking.c@ 206

Last change on this file since 206 was 204, checked in by Herwig Bauernfeind, 16 years ago

Update 3.2 branch to 3.2.4

File size: 41.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: 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 rewrtten 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
40#undef DBGC_CLASS
41#define DBGC_CLASS DBGC_LOCKING
42
43#define NO_LOCKING_COUNT (-1)
44
45/* the locking database handle */
46static struct db_context *lock_db;
47
48/****************************************************************************
49 Debugging aids :-).
50****************************************************************************/
51
52const char *lock_type_name(enum brl_type lock_type)
53{
54 switch (lock_type) {
55 case READ_LOCK:
56 return "READ";
57 case WRITE_LOCK:
58 return "WRITE";
59 case PENDING_READ_LOCK:
60 return "PENDING_READ";
61 case PENDING_WRITE_LOCK:
62 return "PENDING_WRITE";
63 default:
64 return "other";
65 }
66}
67
68const char *lock_flav_name(enum brl_flavour lock_flav)
69{
70 return (lock_flav == WINDOWS_LOCK) ? "WINDOWS_LOCK" : "POSIX_LOCK";
71}
72
73/****************************************************************************
74 Utility function called to see if a file region is locked.
75 Called in the read/write codepath.
76****************************************************************************/
77
78bool is_locked(files_struct *fsp,
79 uint32 smbpid,
80 SMB_BIG_UINT count,
81 SMB_BIG_UINT offset,
82 enum brl_type lock_type)
83{
84 int strict_locking = lp_strict_locking(fsp->conn->params);
85 enum brl_flavour lock_flav = lp_posix_cifsu_locktype(fsp);
86 bool ret = True;
87
88 if (count == 0) {
89 return False;
90 }
91
92 if (!lp_locking(fsp->conn->params) || !strict_locking) {
93 return False;
94 }
95
96 if (strict_locking == Auto) {
97 if (EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type) && (lock_type == READ_LOCK || lock_type == WRITE_LOCK)) {
98 DEBUG(10,("is_locked: optimisation - exclusive oplock on file %s\n", fsp->fsp_name ));
99 ret = False;
100 } else if ((fsp->oplock_type == LEVEL_II_OPLOCK) &&
101 (lock_type == READ_LOCK)) {
102 DEBUG(10,("is_locked: optimisation - level II oplock on file %s\n", fsp->fsp_name ));
103 ret = False;
104 } else {
105 struct byte_range_lock *br_lck = brl_get_locks_readonly(talloc_tos(), fsp);
106 if (!br_lck) {
107 return False;
108 }
109 ret = !brl_locktest(br_lck,
110 smbpid,
111 procid_self(),
112 offset,
113 count,
114 lock_type,
115 lock_flav);
116 TALLOC_FREE(br_lck);
117 }
118 } else {
119 struct byte_range_lock *br_lck = brl_get_locks_readonly(talloc_tos(), fsp);
120 if (!br_lck) {
121 return False;
122 }
123 ret = !brl_locktest(br_lck,
124 smbpid,
125 procid_self(),
126 offset,
127 count,
128 lock_type,
129 lock_flav);
130 TALLOC_FREE(br_lck);
131 }
132
133 DEBUG(10,("is_locked: flavour = %s brl start=%.0f len=%.0f %s for fnum %d file %s\n",
134 lock_flav_name(lock_flav),
135 (double)offset, (double)count, ret ? "locked" : "unlocked",
136 fsp->fnum, fsp->fsp_name ));
137
138 return ret;
139}
140
141/****************************************************************************
142 Find out if a lock could be granted - return who is blocking us if we can't.
143****************************************************************************/
144
145NTSTATUS query_lock(files_struct *fsp,
146 uint32 *psmbpid,
147 SMB_BIG_UINT *pcount,
148 SMB_BIG_UINT *poffset,
149 enum brl_type *plock_type,
150 enum brl_flavour lock_flav)
151{
152 struct byte_range_lock *br_lck = NULL;
153 NTSTATUS status = NT_STATUS_LOCK_NOT_GRANTED;
154
155 if (!fsp->can_lock) {
156 return fsp->is_directory ? NT_STATUS_INVALID_DEVICE_REQUEST : NT_STATUS_INVALID_HANDLE;
157 }
158
159 if (!lp_locking(fsp->conn->params)) {
160 return NT_STATUS_OK;
161 }
162
163 br_lck = brl_get_locks_readonly(talloc_tos(), fsp);
164 if (!br_lck) {
165 return NT_STATUS_NO_MEMORY;
166 }
167
168 status = brl_lockquery(br_lck,
169 psmbpid,
170 procid_self(),
171 poffset,
172 pcount,
173 plock_type,
174 lock_flav);
175
176 TALLOC_FREE(br_lck);
177 return status;
178}
179
180/****************************************************************************
181 Utility function called by locking requests.
182****************************************************************************/
183
184struct byte_range_lock *do_lock(struct messaging_context *msg_ctx,
185 files_struct *fsp,
186 uint32 lock_pid,
187 SMB_BIG_UINT count,
188 SMB_BIG_UINT offset,
189 enum brl_type lock_type,
190 enum brl_flavour lock_flav,
191 bool blocking_lock,
192 NTSTATUS *perr,
193 uint32 *plock_pid)
194{
195 struct byte_range_lock *br_lck = NULL;
196
197 if (!fsp->can_lock) {
198 *perr = fsp->is_directory ? NT_STATUS_INVALID_DEVICE_REQUEST : NT_STATUS_INVALID_HANDLE;
199 return NULL;
200 }
201
202 if (!lp_locking(fsp->conn->params)) {
203 *perr = NT_STATUS_OK;
204 return NULL;
205 }
206
207 /* NOTE! 0 byte long ranges ARE allowed and should be stored */
208
209 DEBUG(10,("do_lock: lock flavour %s lock type %s start=%.0f len=%.0f requested for fnum %d file %s\n",
210 lock_flav_name(lock_flav), lock_type_name(lock_type),
211 (double)offset, (double)count, fsp->fnum, fsp->fsp_name ));
212
213 br_lck = brl_get_locks(talloc_tos(), fsp);
214 if (!br_lck) {
215 *perr = NT_STATUS_NO_MEMORY;
216 return NULL;
217 }
218
219 *perr = brl_lock(msg_ctx,
220 br_lck,
221 lock_pid,
222 procid_self(),
223 offset,
224 count,
225 lock_type,
226 lock_flav,
227 blocking_lock,
228 plock_pid);
229
230 if (lock_flav == WINDOWS_LOCK &&
231 fsp->current_lock_count != NO_LOCKING_COUNT) {
232 /* blocking ie. pending, locks also count here,
233 * as this is an efficiency counter to avoid checking
234 * the lock db. on close. JRA. */
235
236 fsp->current_lock_count++;
237 } else {
238 /* Notice that this has had a POSIX lock request.
239 * We can't count locks after this so forget them.
240 */
241 fsp->current_lock_count = NO_LOCKING_COUNT;
242 }
243
244 return br_lck;
245}
246
247/****************************************************************************
248 Utility function called by unlocking requests.
249****************************************************************************/
250
251NTSTATUS do_unlock(struct messaging_context *msg_ctx,
252 files_struct *fsp,
253 uint32 lock_pid,
254 SMB_BIG_UINT count,
255 SMB_BIG_UINT offset,
256 enum brl_flavour lock_flav)
257{
258 bool ok = False;
259 struct byte_range_lock *br_lck = NULL;
260
261 if (!fsp->can_lock) {
262 return fsp->is_directory ? NT_STATUS_INVALID_DEVICE_REQUEST : NT_STATUS_INVALID_HANDLE;
263 }
264
265 if (!lp_locking(fsp->conn->params)) {
266 return NT_STATUS_OK;
267 }
268
269 DEBUG(10,("do_unlock: unlock start=%.0f len=%.0f requested for fnum %d file %s\n",
270 (double)offset, (double)count, fsp->fnum, fsp->fsp_name ));
271
272 br_lck = brl_get_locks(talloc_tos(), fsp);
273 if (!br_lck) {
274 return NT_STATUS_NO_MEMORY;
275 }
276
277 ok = brl_unlock(msg_ctx,
278 br_lck,
279 lock_pid,
280 procid_self(),
281 offset,
282 count,
283 lock_flav);
284
285 TALLOC_FREE(br_lck);
286
287 if (!ok) {
288 DEBUG(10,("do_unlock: returning ERRlock.\n" ));
289 return NT_STATUS_RANGE_NOT_LOCKED;
290 }
291
292 if (lock_flav == WINDOWS_LOCK &&
293 fsp->current_lock_count != NO_LOCKING_COUNT) {
294 SMB_ASSERT(fsp->current_lock_count > 0);
295 fsp->current_lock_count--;
296 }
297
298 return NT_STATUS_OK;
299}
300
301/****************************************************************************
302 Cancel any pending blocked locks.
303****************************************************************************/
304
305NTSTATUS do_lock_cancel(files_struct *fsp,
306 uint32 lock_pid,
307 SMB_BIG_UINT count,
308 SMB_BIG_UINT offset,
309 enum brl_flavour lock_flav)
310{
311 bool ok = False;
312 struct byte_range_lock *br_lck = NULL;
313
314 if (!fsp->can_lock) {
315 return fsp->is_directory ?
316 NT_STATUS_INVALID_DEVICE_REQUEST : NT_STATUS_INVALID_HANDLE;
317 }
318
319 if (!lp_locking(fsp->conn->params)) {
320 return NT_STATUS_DOS(ERRDOS, ERRcancelviolation);
321 }
322
323 DEBUG(10,("do_lock_cancel: cancel start=%.0f len=%.0f requested for fnum %d file %s\n",
324 (double)offset, (double)count, fsp->fnum, fsp->fsp_name ));
325
326 br_lck = brl_get_locks(talloc_tos(), fsp);
327 if (!br_lck) {
328 return NT_STATUS_NO_MEMORY;
329 }
330
331 ok = brl_lock_cancel(br_lck,
332 lock_pid,
333 procid_self(),
334 offset,
335 count,
336 lock_flav);
337
338 TALLOC_FREE(br_lck);
339
340 if (!ok) {
341 DEBUG(10,("do_lock_cancel: returning ERRcancelviolation.\n" ));
342 return NT_STATUS_DOS(ERRDOS, ERRcancelviolation);
343 }
344
345 if (lock_flav == WINDOWS_LOCK &&
346 fsp->current_lock_count != NO_LOCKING_COUNT) {
347 SMB_ASSERT(fsp->current_lock_count > 0);
348 fsp->current_lock_count--;
349 }
350
351 return NT_STATUS_OK;
352}
353
354/****************************************************************************
355 Remove any locks on this fd. Called from file_close().
356****************************************************************************/
357
358void locking_close_file(struct messaging_context *msg_ctx,
359 files_struct *fsp)
360{
361 struct byte_range_lock *br_lck;
362
363 if (!lp_locking(fsp->conn->params)) {
364 return;
365 }
366
367 /* If we have not outstanding locks or pending
368 * locks then we don't need to look in the lock db.
369 */
370
371 if (fsp->current_lock_count == 0) {
372 return;
373 }
374
375 br_lck = brl_get_locks(talloc_tos(),fsp);
376
377 if (br_lck) {
378 cancel_pending_lock_requests_by_fid(fsp, br_lck);
379 brl_close_fnum(msg_ctx, br_lck);
380 TALLOC_FREE(br_lck);
381 }
382}
383
384/****************************************************************************
385 Initialise the locking functions.
386****************************************************************************/
387
388static bool locking_init_internal(bool read_only)
389{
390 brl_init(read_only);
391
392 if (lock_db)
393 return True;
394
395 lock_db = db_open(NULL, lock_path("locking.tdb"),
396 lp_open_files_db_hash_size(),
397 TDB_DEFAULT|TDB_VOLATILE|TDB_CLEAR_IF_FIRST,
398 read_only?O_RDONLY:O_RDWR|O_CREAT, 0644);
399
400 if (!lock_db) {
401 DEBUG(0,("ERROR: Failed to initialise locking database\n"));
402 return False;
403 }
404
405 if (!posix_locking_init(read_only))
406 return False;
407
408 return True;
409}
410
411bool locking_init(void)
412{
413 return locking_init_internal(false);
414}
415
416bool locking_init_readonly(void)
417{
418 return locking_init_internal(true);
419}
420
421/*******************************************************************
422 Deinitialize the share_mode management.
423******************************************************************/
424
425bool locking_end(void)
426{
427 brl_shutdown();
428 TALLOC_FREE(lock_db);
429 return true;
430}
431
432/*******************************************************************
433 Form a static locking key for a dev/inode pair.
434******************************************************************/
435
436static TDB_DATA locking_key(const struct file_id *id, struct file_id *tmp)
437{
438 *tmp = *id;
439 return make_tdb_data((const uint8_t *)tmp, sizeof(*tmp));
440}
441
442/*******************************************************************
443 Print out a share mode.
444********************************************************************/
445
446char *share_mode_str(TALLOC_CTX *ctx, int num, const struct share_mode_entry *e)
447{
448 return talloc_asprintf(ctx, "share_mode_entry[%d]: %s "
449 "pid = %s, share_access = 0x%x, private_options = 0x%x, "
450 "access_mask = 0x%x, mid = 0x%x, type= 0x%x, gen_id = %lu, "
451 "uid = %u, flags = %u, file_id %s",
452 num,
453 e->op_type == UNUSED_SHARE_MODE_ENTRY ? "UNUSED" : "",
454 procid_str_static(&e->pid),
455 e->share_access, e->private_options,
456 e->access_mask, e->op_mid, e->op_type, e->share_file_id,
457 (unsigned int)e->uid, (unsigned int)e->flags,
458 file_id_string_tos(&e->id));
459}
460
461/*******************************************************************
462 Print out a share mode table.
463********************************************************************/
464
465static void print_share_mode_table(struct locking_data *data)
466{
467 int num_share_modes = data->u.s.num_share_mode_entries;
468 struct share_mode_entry *shares =
469 (struct share_mode_entry *)(data + 1);
470 int i;
471
472 for (i = 0; i < num_share_modes; i++) {
473 struct share_mode_entry entry;
474 char *str;
475
476 /*
477 * We need to memcpy the entry here due to alignment
478 * restrictions that are not met when directly accessing
479 * shares[i]
480 */
481
482 memcpy(&entry, &shares[i], sizeof(struct share_mode_entry));
483 str = share_mode_str(talloc_tos(), i, &entry);
484
485 DEBUG(10,("print_share_mode_table: %s\n", str ? str : ""));
486 TALLOC_FREE(str);
487 }
488}
489
490/*******************************************************************
491 Get all share mode entries for a dev/inode pair.
492********************************************************************/
493
494static bool parse_share_modes(TDB_DATA dbuf, struct share_mode_lock *lck)
495{
496 struct locking_data data;
497 int i;
498
499 if (dbuf.dsize < sizeof(struct locking_data)) {
500 smb_panic("parse_share_modes: buffer too short");
501 }
502
503 memcpy(&data, dbuf.dptr, sizeof(data));
504
505 lck->delete_on_close = data.u.s.delete_on_close;
506 lck->old_write_time = data.u.s.old_write_time;
507 lck->changed_write_time = data.u.s.changed_write_time;
508 lck->num_share_modes = data.u.s.num_share_mode_entries;
509
510 DEBUG(10, ("parse_share_modes: delete_on_close: %d, owrt: %s, "
511 "cwrt: %s, tok: %u, num_share_modes: %d\n",
512 lck->delete_on_close,
513 timestring(debug_ctx(),
514 convert_timespec_to_time_t(lck->old_write_time)),
515 timestring(debug_ctx(),
516 convert_timespec_to_time_t(
517 lck->changed_write_time)),
518 (unsigned int)data.u.s.delete_token_size,
519 lck->num_share_modes));
520
521 if ((lck->num_share_modes < 0) || (lck->num_share_modes > 1000000)) {
522 DEBUG(0, ("invalid number of share modes: %d\n",
523 lck->num_share_modes));
524 smb_panic("parse_share_modes: invalid number of share modes");
525 }
526
527 lck->share_modes = NULL;
528
529 if (lck->num_share_modes != 0) {
530
531 if (dbuf.dsize < (sizeof(struct locking_data) +
532 (lck->num_share_modes *
533 sizeof(struct share_mode_entry)))) {
534 smb_panic("parse_share_modes: buffer too short");
535 }
536
537 lck->share_modes = (struct share_mode_entry *)
538 TALLOC_MEMDUP(lck,
539 dbuf.dptr+sizeof(struct locking_data),
540 lck->num_share_modes *
541 sizeof(struct share_mode_entry));
542
543 if (lck->share_modes == NULL) {
544 smb_panic("parse_share_modes: talloc failed");
545 }
546 }
547
548 /* Get any delete token. */
549 if (data.u.s.delete_token_size) {
550 uint8 *p = dbuf.dptr + sizeof(struct locking_data) +
551 (lck->num_share_modes *
552 sizeof(struct share_mode_entry));
553
554 if ((data.u.s.delete_token_size < sizeof(uid_t) + sizeof(gid_t)) ||
555 ((data.u.s.delete_token_size - sizeof(uid_t)) % sizeof(gid_t)) != 0) {
556 DEBUG(0, ("parse_share_modes: invalid token size %d\n",
557 data.u.s.delete_token_size));
558 smb_panic("parse_share_modes: invalid token size");
559 }
560
561 lck->delete_token = TALLOC_P(lck, UNIX_USER_TOKEN);
562 if (!lck->delete_token) {
563 smb_panic("parse_share_modes: talloc failed");
564 }
565
566 /* Copy out the uid and gid. */
567 memcpy(&lck->delete_token->uid, p, sizeof(uid_t));
568 p += sizeof(uid_t);
569 memcpy(&lck->delete_token->gid, p, sizeof(gid_t));
570 p += sizeof(gid_t);
571
572 /* Any supplementary groups ? */
573 lck->delete_token->ngroups = (data.u.s.delete_token_size > (sizeof(uid_t) + sizeof(gid_t))) ?
574 ((data.u.s.delete_token_size -
575 (sizeof(uid_t) + sizeof(gid_t)))/sizeof(gid_t)) : 0;
576
577 if (lck->delete_token->ngroups) {
578 /* Make this a talloc child of lck->delete_token. */
579 lck->delete_token->groups = TALLOC_ARRAY(lck->delete_token, gid_t,
580 lck->delete_token->ngroups);
581 if (!lck->delete_token) {
582 smb_panic("parse_share_modes: talloc failed");
583 }
584
585 for (i = 0; i < lck->delete_token->ngroups; i++) {
586 memcpy(&lck->delete_token->groups[i], p, sizeof(gid_t));
587 p += sizeof(gid_t);
588 }
589 }
590
591 } else {
592 lck->delete_token = NULL;
593 }
594
595 /* Save off the associated service path and filename. */
596 lck->servicepath = (const char *)dbuf.dptr + sizeof(struct locking_data) +
597 (lck->num_share_modes * sizeof(struct share_mode_entry)) +
598 data.u.s.delete_token_size;
599
600 lck->filename = (const char *)dbuf.dptr + sizeof(struct locking_data) +
601 (lck->num_share_modes * sizeof(struct share_mode_entry)) +
602 data.u.s.delete_token_size +
603 strlen(lck->servicepath) + 1;
604
605 /*
606 * Ensure that each entry has a real process attached.
607 */
608
609 for (i = 0; i < lck->num_share_modes; i++) {
610 struct share_mode_entry *entry_p = &lck->share_modes[i];
611 char *str = NULL;
612 if (DEBUGLEVEL >= 10) {
613 str = share_mode_str(NULL, i, entry_p);
614 }
615 DEBUG(10,("parse_share_modes: %s\n",
616 str ? str : ""));
617 if (!process_exists(entry_p->pid)) {
618 DEBUG(10,("parse_share_modes: deleted %s\n",
619 str ? str : ""));
620 entry_p->op_type = UNUSED_SHARE_MODE_ENTRY;
621 lck->modified = True;
622 }
623 TALLOC_FREE(str);
624 }
625
626 return True;
627}
628
629static TDB_DATA unparse_share_modes(struct share_mode_lock *lck)
630{
631 TDB_DATA result;
632 int num_valid = 0;
633 int i;
634 struct locking_data *data;
635 ssize_t offset;
636 ssize_t sp_len;
637 uint32 delete_token_size;
638
639 result.dptr = NULL;
640 result.dsize = 0;
641
642 for (i=0; i<lck->num_share_modes; i++) {
643 if (!is_unused_share_mode_entry(&lck->share_modes[i])) {
644 num_valid += 1;
645 }
646 }
647
648 if (num_valid == 0) {
649 return result;
650 }
651
652 sp_len = strlen(lck->servicepath);
653 delete_token_size = (lck->delete_token ?
654 (sizeof(uid_t) + sizeof(gid_t) + (lck->delete_token->ngroups*sizeof(gid_t))) : 0);
655
656 result.dsize = sizeof(*data) +
657 lck->num_share_modes * sizeof(struct share_mode_entry) +
658 delete_token_size +
659 sp_len + 1 +
660 strlen(lck->filename) + 1;
661 result.dptr = TALLOC_ARRAY(lck, uint8, result.dsize);
662
663 if (result.dptr == NULL) {
664 smb_panic("talloc failed");
665 }
666
667 data = (struct locking_data *)result.dptr;
668 ZERO_STRUCTP(data);
669 data->u.s.num_share_mode_entries = lck->num_share_modes;
670 data->u.s.delete_on_close = lck->delete_on_close;
671 data->u.s.old_write_time = lck->old_write_time;
672 data->u.s.changed_write_time = lck->changed_write_time;
673 data->u.s.delete_token_size = delete_token_size;
674
675 DEBUG(10,("unparse_share_modes: del: %d, owrt: %s cwrt: %s, tok: %u, "
676 "num: %d\n", data->u.s.delete_on_close,
677 timestring(debug_ctx(),
678 convert_timespec_to_time_t(lck->old_write_time)),
679 timestring(debug_ctx(),
680 convert_timespec_to_time_t(
681 lck->changed_write_time)),
682 (unsigned int)data->u.s.delete_token_size,
683 data->u.s.num_share_mode_entries));
684
685 memcpy(result.dptr + sizeof(*data), lck->share_modes,
686 sizeof(struct share_mode_entry)*lck->num_share_modes);
687 offset = sizeof(*data) +
688 sizeof(struct share_mode_entry)*lck->num_share_modes;
689
690 /* Store any delete on close token. */
691 if (lck->delete_token) {
692 uint8 *p = result.dptr + offset;
693
694 memcpy(p, &lck->delete_token->uid, sizeof(uid_t));
695 p += sizeof(uid_t);
696
697 memcpy(p, &lck->delete_token->gid, sizeof(gid_t));
698 p += sizeof(gid_t);
699
700 for (i = 0; i < lck->delete_token->ngroups; i++) {
701 memcpy(p, &lck->delete_token->groups[i], sizeof(gid_t));
702 p += sizeof(gid_t);
703 }
704 offset = p - result.dptr;
705 }
706
707 safe_strcpy((char *)result.dptr + offset, lck->servicepath,
708 result.dsize - offset - 1);
709 offset += sp_len + 1;
710 safe_strcpy((char *)result.dptr + offset, lck->filename,
711 result.dsize - offset - 1);
712
713 if (DEBUGLEVEL >= 10) {
714 print_share_mode_table(data);
715 }
716
717 return result;
718}
719
720static int share_mode_lock_destructor(struct share_mode_lock *lck)
721{
722 NTSTATUS status;
723 TDB_DATA data;
724
725 if (!lck->modified) {
726 return 0;
727 }
728
729 data = unparse_share_modes(lck);
730
731 if (data.dptr == NULL) {
732 if (!lck->fresh) {
733 /* There has been an entry before, delete it */
734
735 status = lck->record->delete_rec(lck->record);
736 if (!NT_STATUS_IS_OK(status)) {
737 DEBUG(0, ("delete_rec returned %s\n",
738 nt_errstr(status)));
739 smb_panic("could not delete share entry");
740 }
741 }
742 goto done;
743 }
744
745 status = lck->record->store(lck->record, data, TDB_REPLACE);
746 if (!NT_STATUS_IS_OK(status)) {
747 DEBUG(0, ("store returned %s\n", nt_errstr(status)));
748 smb_panic("could not store share mode entry");
749 }
750
751 done:
752
753 return 0;
754}
755
756static bool fill_share_mode_lock(struct share_mode_lock *lck,
757 struct file_id id,
758 const char *servicepath,
759 const char *fname,
760 TDB_DATA share_mode_data,
761 const struct timespec *old_write_time)
762{
763 /* Ensure we set every field here as the destructor must be
764 valid even if parse_share_modes fails. */
765
766 lck->servicepath = NULL;
767 lck->filename = NULL;
768 lck->id = id;
769 lck->num_share_modes = 0;
770 lck->share_modes = NULL;
771 lck->delete_token = NULL;
772 lck->delete_on_close = False;
773 ZERO_STRUCT(lck->old_write_time);
774 ZERO_STRUCT(lck->changed_write_time);
775 lck->fresh = False;
776 lck->modified = False;
777
778 lck->fresh = (share_mode_data.dptr == NULL);
779
780 if (lck->fresh) {
781 if (fname == NULL || servicepath == NULL
782 || old_write_time == NULL) {
783 return False;
784 }
785 lck->filename = talloc_strdup(lck, fname);
786 lck->servicepath = talloc_strdup(lck, servicepath);
787 if (lck->filename == NULL || lck->servicepath == NULL) {
788 DEBUG(0, ("talloc failed\n"));
789 return False;
790 }
791 lck->old_write_time = *old_write_time;
792 } else {
793 if (!parse_share_modes(share_mode_data, lck)) {
794 DEBUG(0, ("Could not parse share modes\n"));
795 return False;
796 }
797 }
798
799 return True;
800}
801
802struct share_mode_lock *get_share_mode_lock(TALLOC_CTX *mem_ctx,
803 const struct file_id id,
804 const char *servicepath,
805 const char *fname,
806 const struct timespec *old_write_time)
807{
808 struct share_mode_lock *lck;
809 struct file_id tmp;
810 TDB_DATA key = locking_key(&id, &tmp);
811
812 if (!(lck = TALLOC_P(mem_ctx, struct share_mode_lock))) {
813 DEBUG(0, ("talloc failed\n"));
814 return NULL;
815 }
816
817 if (!(lck->record = lock_db->fetch_locked(lock_db, lck, key))) {
818 DEBUG(3, ("Could not lock share entry\n"));
819 TALLOC_FREE(lck);
820 return NULL;
821 }
822
823 if (!fill_share_mode_lock(lck, id, servicepath, fname,
824 lck->record->value, old_write_time)) {
825 DEBUG(3, ("fill_share_mode_lock failed\n"));
826 TALLOC_FREE(lck);
827 return NULL;
828 }
829
830 talloc_set_destructor(lck, share_mode_lock_destructor);
831
832 return lck;
833}
834
835struct share_mode_lock *fetch_share_mode_unlocked(TALLOC_CTX *mem_ctx,
836 const struct file_id id,
837 const char *servicepath,
838 const char *fname)
839{
840 struct share_mode_lock *lck;
841 struct file_id tmp;
842 TDB_DATA key = locking_key(&id, &tmp);
843 TDB_DATA data;
844
845 if (!(lck = TALLOC_P(mem_ctx, struct share_mode_lock))) {
846 DEBUG(0, ("talloc failed\n"));
847 return NULL;
848 }
849
850 if (lock_db->fetch(lock_db, lck, key, &data) == -1) {
851 DEBUG(3, ("Could not fetch share entry\n"));
852 TALLOC_FREE(lck);
853 return NULL;
854 }
855
856 if (!fill_share_mode_lock(lck, id, servicepath, fname, data, NULL)) {
857 DEBUG(3, ("fill_share_mode_lock failed\n"));
858 TALLOC_FREE(lck);
859 return NULL;
860 }
861
862 return lck;
863}
864
865/*******************************************************************
866 Sets the service name and filename for rename.
867 At this point we emit "file renamed" messages to all
868 process id's that have this file open.
869 Based on an initial code idea from SATOH Fumiyasu <fumiya@samba.gr.jp>
870********************************************************************/
871
872bool rename_share_filename(struct messaging_context *msg_ctx,
873 struct share_mode_lock *lck,
874 const char *servicepath,
875 const char *newname)
876{
877 size_t sp_len;
878 size_t fn_len;
879 size_t msg_len;
880 char *frm = NULL;
881 int i;
882
883 DEBUG(10, ("rename_share_filename: servicepath %s newname %s\n",
884 servicepath, newname));
885
886 /*
887 * rename_internal_fsp() and rename_internals() add './' to
888 * head of newname if newname does not contain a '/'.
889 */
890 while (newname[0] && newname[1] && newname[0] == '.' && newname[1] == '/') {
891 newname += 2;
892 }
893
894 lck->servicepath = talloc_strdup(lck, servicepath);
895 lck->filename = talloc_strdup(lck, newname);
896 if (lck->filename == NULL || lck->servicepath == NULL) {
897 DEBUG(0, ("rename_share_filename: talloc failed\n"));
898 return False;
899 }
900 lck->modified = True;
901
902 sp_len = strlen(lck->servicepath);
903 fn_len = strlen(lck->filename);
904
905 msg_len = MSG_FILE_RENAMED_MIN_SIZE + sp_len + 1 + fn_len + 1;
906
907 /* Set up the name changed message. */
908 frm = TALLOC_ARRAY(lck, char, msg_len);
909 if (!frm) {
910 return False;
911 }
912
913 push_file_id_16(frm, &lck->id);
914
915 DEBUG(10,("rename_share_filename: msg_len = %u\n", (unsigned int)msg_len ));
916
917 safe_strcpy(&frm[16], lck->servicepath, sp_len);
918 safe_strcpy(&frm[16 + sp_len + 1], lck->filename, fn_len);
919
920 /* Send the messages. */
921 for (i=0; i<lck->num_share_modes; i++) {
922 struct share_mode_entry *se = &lck->share_modes[i];
923 if (!is_valid_share_mode_entry(se)) {
924 continue;
925 }
926 /* But not to ourselves... */
927 if (procid_is_me(&se->pid)) {
928 continue;
929 }
930
931 DEBUG(10,("rename_share_filename: sending rename message to pid %s "
932 "file_id %s sharepath %s newname %s\n",
933 procid_str_static(&se->pid),
934 file_id_string_tos(&lck->id),
935 lck->servicepath, lck->filename ));
936
937 messaging_send_buf(msg_ctx, se->pid, MSG_SMB_FILE_RENAME,
938 (uint8 *)frm, msg_len);
939 }
940
941 return True;
942}
943
944void get_file_infos(struct file_id id,
945 bool *delete_on_close,
946 struct timespec *write_time)
947{
948 struct share_mode_lock *lck;
949
950 if (delete_on_close) {
951 *delete_on_close = false;
952 }
953
954 if (write_time) {
955 ZERO_STRUCTP(write_time);
956 }
957
958 if (!(lck = fetch_share_mode_unlocked(talloc_tos(), id, NULL, NULL))) {
959 return;
960 }
961
962 if (delete_on_close) {
963 *delete_on_close = lck->delete_on_close;
964 }
965
966 if (write_time) {
967 struct timespec wt;
968
969 wt = lck->changed_write_time;
970 if (null_timespec(wt)) {
971 wt = lck->old_write_time;
972 }
973
974 *write_time = wt;
975 }
976
977 TALLOC_FREE(lck);
978}
979
980bool is_valid_share_mode_entry(const struct share_mode_entry *e)
981{
982 int num_props = 0;
983
984 if (e->op_type == UNUSED_SHARE_MODE_ENTRY) {
985 /* cope with dead entries from the process not
986 existing. These should not be considered valid,
987 otherwise we end up doing zero timeout sharing
988 violation */
989 return False;
990 }
991
992 num_props += ((e->op_type == NO_OPLOCK) ? 1 : 0);
993 num_props += (EXCLUSIVE_OPLOCK_TYPE(e->op_type) ? 1 : 0);
994 num_props += (LEVEL_II_OPLOCK_TYPE(e->op_type) ? 1 : 0);
995
996 SMB_ASSERT(num_props <= 1);
997 return (num_props != 0);
998}
999
1000bool is_deferred_open_entry(const struct share_mode_entry *e)
1001{
1002 return (e->op_type == DEFERRED_OPEN_ENTRY);
1003}
1004
1005bool is_unused_share_mode_entry(const struct share_mode_entry *e)
1006{
1007 return (e->op_type == UNUSED_SHARE_MODE_ENTRY);
1008}
1009
1010/*******************************************************************
1011 Fill a share mode entry.
1012********************************************************************/
1013
1014static void fill_share_mode_entry(struct share_mode_entry *e,
1015 files_struct *fsp,
1016 uid_t uid, uint16 mid, uint16 op_type)
1017{
1018 ZERO_STRUCTP(e);
1019 e->pid = procid_self();
1020 e->share_access = fsp->share_access;
1021 e->private_options = fsp->fh->private_options;
1022 e->access_mask = fsp->access_mask;
1023 e->op_mid = mid;
1024 e->op_type = op_type;
1025 e->time.tv_sec = fsp->open_time.tv_sec;
1026 e->time.tv_usec = fsp->open_time.tv_usec;
1027 e->id = fsp->file_id;
1028 e->share_file_id = fsp->fh->gen_id;
1029 e->uid = (uint32)uid;
1030 e->flags = fsp->posix_open ? SHARE_MODE_FLAG_POSIX_OPEN : 0;
1031}
1032
1033static void fill_deferred_open_entry(struct share_mode_entry *e,
1034 const struct timeval request_time,
1035 struct file_id id, uint16 mid)
1036{
1037 ZERO_STRUCTP(e);
1038 e->pid = procid_self();
1039 e->op_mid = mid;
1040 e->op_type = DEFERRED_OPEN_ENTRY;
1041 e->time.tv_sec = request_time.tv_sec;
1042 e->time.tv_usec = request_time.tv_usec;
1043 e->id = id;
1044 e->uid = (uint32)-1;
1045 e->flags = 0;
1046}
1047
1048static void add_share_mode_entry(struct share_mode_lock *lck,
1049 const struct share_mode_entry *entry)
1050{
1051 int i;
1052
1053 for (i=0; i<lck->num_share_modes; i++) {
1054 struct share_mode_entry *e = &lck->share_modes[i];
1055 if (is_unused_share_mode_entry(e)) {
1056 *e = *entry;
1057 break;
1058 }
1059 }
1060
1061 if (i == lck->num_share_modes) {
1062 /* No unused entry found */
1063 ADD_TO_ARRAY(lck, struct share_mode_entry, *entry,
1064 &lck->share_modes, &lck->num_share_modes);
1065 }
1066 lck->modified = True;
1067}
1068
1069void set_share_mode(struct share_mode_lock *lck, files_struct *fsp,
1070 uid_t uid, uint16 mid, uint16 op_type, bool initial_delete_on_close_allowed)
1071{
1072 struct share_mode_entry entry;
1073 fill_share_mode_entry(&entry, fsp, uid, mid, op_type);
1074 if (initial_delete_on_close_allowed) {
1075 entry.flags |= SHARE_MODE_ALLOW_INITIAL_DELETE_ON_CLOSE;
1076 }
1077 add_share_mode_entry(lck, &entry);
1078}
1079
1080void add_deferred_open(struct share_mode_lock *lck, uint16 mid,
1081 struct timeval request_time,
1082 struct file_id id)
1083{
1084 struct share_mode_entry entry;
1085 fill_deferred_open_entry(&entry, request_time, id, mid);
1086 add_share_mode_entry(lck, &entry);
1087}
1088
1089/*******************************************************************
1090 Check if two share mode entries are identical, ignoring oplock
1091 and mid info and desired_access. (Removed paranoia test - it's
1092 not automatically a logic error if they are identical. JRA.)
1093********************************************************************/
1094
1095static bool share_modes_identical(struct share_mode_entry *e1,
1096 struct share_mode_entry *e2)
1097{
1098 /* We used to check for e1->share_access == e2->share_access here
1099 as well as the other fields but 2 different DOS or FCB opens
1100 sharing the same share mode entry may validly differ in
1101 fsp->share_access field. */
1102
1103 return (procid_equal(&e1->pid, &e2->pid) &&
1104 file_id_equal(&e1->id, &e2->id) &&
1105 e1->share_file_id == e2->share_file_id );
1106}
1107
1108static bool deferred_open_identical(struct share_mode_entry *e1,
1109 struct share_mode_entry *e2)
1110{
1111 return (procid_equal(&e1->pid, &e2->pid) &&
1112 (e1->op_mid == e2->op_mid) &&
1113 file_id_equal(&e1->id, &e2->id));
1114}
1115
1116static struct share_mode_entry *find_share_mode_entry(struct share_mode_lock *lck,
1117 struct share_mode_entry *entry)
1118{
1119 int i;
1120
1121 for (i=0; i<lck->num_share_modes; i++) {
1122 struct share_mode_entry *e = &lck->share_modes[i];
1123 if (is_valid_share_mode_entry(entry) &&
1124 is_valid_share_mode_entry(e) &&
1125 share_modes_identical(e, entry)) {
1126 return e;
1127 }
1128 if (is_deferred_open_entry(entry) &&
1129 is_deferred_open_entry(e) &&
1130 deferred_open_identical(e, entry)) {
1131 return e;
1132 }
1133 }
1134 return NULL;
1135}
1136
1137/*******************************************************************
1138 Del the share mode of a file for this process. Return the number of
1139 entries left.
1140********************************************************************/
1141
1142bool del_share_mode(struct share_mode_lock *lck, files_struct *fsp)
1143{
1144 struct share_mode_entry entry, *e;
1145
1146 /* Don't care about the pid owner being correct here - just a search. */
1147 fill_share_mode_entry(&entry, fsp, (uid_t)-1, 0, NO_OPLOCK);
1148
1149 e = find_share_mode_entry(lck, &entry);
1150 if (e == NULL) {
1151 return False;
1152 }
1153
1154 e->op_type = UNUSED_SHARE_MODE_ENTRY;
1155 lck->modified = True;
1156 return True;
1157}
1158
1159void del_deferred_open_entry(struct share_mode_lock *lck, uint16 mid)
1160{
1161 struct share_mode_entry entry, *e;
1162
1163 fill_deferred_open_entry(&entry, timeval_zero(),
1164 lck->id, mid);
1165
1166 e = find_share_mode_entry(lck, &entry);
1167 if (e == NULL) {
1168 return;
1169 }
1170
1171 e->op_type = UNUSED_SHARE_MODE_ENTRY;
1172 lck->modified = True;
1173}
1174
1175/*******************************************************************
1176 Remove an oplock mid and mode entry from a share mode.
1177********************************************************************/
1178
1179bool remove_share_oplock(struct share_mode_lock *lck, files_struct *fsp)
1180{
1181 struct share_mode_entry entry, *e;
1182
1183 /* Don't care about the pid owner being correct here - just a search. */
1184 fill_share_mode_entry(&entry, fsp, (uid_t)-1, 0, NO_OPLOCK);
1185
1186 e = find_share_mode_entry(lck, &entry);
1187 if (e == NULL) {
1188 return False;
1189 }
1190
1191 e->op_mid = 0;
1192 e->op_type = NO_OPLOCK;
1193 lck->modified = True;
1194 return True;
1195}
1196
1197/*******************************************************************
1198 Downgrade a oplock type from exclusive to level II.
1199********************************************************************/
1200
1201bool downgrade_share_oplock(struct share_mode_lock *lck, files_struct *fsp)
1202{
1203 struct share_mode_entry entry, *e;
1204
1205 /* Don't care about the pid owner being correct here - just a search. */
1206 fill_share_mode_entry(&entry, fsp, (uid_t)-1, 0, NO_OPLOCK);
1207
1208 e = find_share_mode_entry(lck, &entry);
1209 if (e == NULL) {
1210 return False;
1211 }
1212
1213 e->op_type = LEVEL_II_OPLOCK;
1214 lck->modified = True;
1215 return True;
1216}
1217
1218/****************************************************************************
1219 Deal with the internal needs of setting the delete on close flag. Note that
1220 as the tdb locking is recursive, it is safe to call this from within
1221 open_file_ntcreate. JRA.
1222****************************************************************************/
1223
1224NTSTATUS can_set_delete_on_close(files_struct *fsp, bool delete_on_close,
1225 uint32 dosmode)
1226{
1227 if (!delete_on_close) {
1228 return NT_STATUS_OK;
1229 }
1230
1231 /*
1232 * Only allow delete on close for writable files.
1233 */
1234
1235 if ((dosmode & aRONLY) &&
1236 !lp_delete_readonly(SNUM(fsp->conn))) {
1237 DEBUG(10,("can_set_delete_on_close: file %s delete on close "
1238 "flag set but file attribute is readonly.\n",
1239 fsp->fsp_name ));
1240 return NT_STATUS_CANNOT_DELETE;
1241 }
1242
1243 /*
1244 * Only allow delete on close for writable shares.
1245 */
1246
1247 if (!CAN_WRITE(fsp->conn)) {
1248 DEBUG(10,("can_set_delete_on_close: file %s delete on "
1249 "close flag set but write access denied on share.\n",
1250 fsp->fsp_name ));
1251 return NT_STATUS_ACCESS_DENIED;
1252 }
1253
1254 /*
1255 * Only allow delete on close for files/directories opened with delete
1256 * intent.
1257 */
1258
1259 if (!(fsp->access_mask & DELETE_ACCESS)) {
1260 DEBUG(10,("can_set_delete_on_close: file %s delete on "
1261 "close flag set but delete access denied.\n",
1262 fsp->fsp_name ));
1263 return NT_STATUS_ACCESS_DENIED;
1264 }
1265
1266 /* Don't allow delete on close for non-empty directories. */
1267 if (fsp->is_directory) {
1268 return can_delete_directory(fsp->conn, fsp->fsp_name);
1269 }
1270
1271 return NT_STATUS_OK;
1272}
1273
1274/****************************************************************************
1275 Do we have an open file handle that created this entry ?
1276****************************************************************************/
1277
1278bool can_set_initial_delete_on_close(const struct share_mode_lock *lck)
1279{
1280 int i;
1281
1282 for (i=0; i<lck->num_share_modes; i++) {
1283 if (lck->share_modes[i].flags & SHARE_MODE_ALLOW_INITIAL_DELETE_ON_CLOSE) {
1284 return True;
1285 }
1286 }
1287 return False;
1288}
1289
1290/*************************************************************************
1291 Return a talloced copy of a UNIX_USER_TOKEN. NULL on fail.
1292 (Should this be in locking.c.... ?).
1293*************************************************************************/
1294
1295static UNIX_USER_TOKEN *copy_unix_token(TALLOC_CTX *ctx, UNIX_USER_TOKEN *tok)
1296{
1297 UNIX_USER_TOKEN *cpy;
1298
1299 if (tok == NULL) {
1300 return NULL;
1301 }
1302
1303 cpy = TALLOC_P(ctx, UNIX_USER_TOKEN);
1304 if (!cpy) {
1305 return NULL;
1306 }
1307
1308 cpy->uid = tok->uid;
1309 cpy->gid = tok->gid;
1310 cpy->ngroups = tok->ngroups;
1311 if (tok->ngroups) {
1312 /* Make this a talloc child of cpy. */
1313 cpy->groups = TALLOC_ARRAY(cpy, gid_t, tok->ngroups);
1314 if (!cpy->groups) {
1315 return NULL;
1316 }
1317 memcpy(cpy->groups, tok->groups, tok->ngroups * sizeof(gid_t));
1318 }
1319 return cpy;
1320}
1321
1322/****************************************************************************
1323 Replace the delete on close token.
1324****************************************************************************/
1325
1326void set_delete_on_close_token(struct share_mode_lock *lck, UNIX_USER_TOKEN *tok)
1327{
1328 TALLOC_FREE(lck->delete_token); /* Also deletes groups... */
1329
1330 /* Copy the new token (can be NULL). */
1331 lck->delete_token = copy_unix_token(lck, tok);
1332 lck->modified = True;
1333}
1334
1335/****************************************************************************
1336 Sets the delete on close flag over all share modes on this file.
1337 Modify the share mode entry for all files open
1338 on this device and inode to tell other smbds we have
1339 changed the delete on close flag. This will be noticed
1340 in the close code, the last closer will delete the file
1341 if flag is set.
1342 This makes a copy of any UNIX_USER_TOKEN into the
1343 lck entry. This function is used when the lock is already granted.
1344****************************************************************************/
1345
1346void set_delete_on_close_lck(struct share_mode_lock *lck, bool delete_on_close, UNIX_USER_TOKEN *tok)
1347{
1348 if (lck->delete_on_close != delete_on_close) {
1349 set_delete_on_close_token(lck, tok);
1350 lck->delete_on_close = delete_on_close;
1351 if (delete_on_close) {
1352 SMB_ASSERT(lck->delete_token != NULL);
1353 }
1354 lck->modified = True;
1355 }
1356}
1357
1358bool set_delete_on_close(files_struct *fsp, bool delete_on_close, UNIX_USER_TOKEN *tok)
1359{
1360 struct share_mode_lock *lck;
1361
1362 DEBUG(10,("set_delete_on_close: %s delete on close flag for "
1363 "fnum = %d, file %s\n",
1364 delete_on_close ? "Adding" : "Removing", fsp->fnum,
1365 fsp->fsp_name ));
1366
1367 if (fsp->is_stat) {
1368 return True;
1369 }
1370
1371 lck = get_share_mode_lock(talloc_tos(), fsp->file_id, NULL, NULL,
1372 NULL);
1373 if (lck == NULL) {
1374 return False;
1375 }
1376
1377 set_delete_on_close_lck(lck, delete_on_close, tok);
1378
1379 if (fsp->is_directory) {
1380 send_stat_cache_delete_message(fsp->fsp_name);
1381 }
1382
1383 TALLOC_FREE(lck);
1384 return True;
1385}
1386
1387/****************************************************************************
1388 Sets the allow initial delete on close flag for this share mode.
1389****************************************************************************/
1390
1391bool set_allow_initial_delete_on_close(struct share_mode_lock *lck, files_struct *fsp, bool delete_on_close)
1392{
1393 struct share_mode_entry entry, *e;
1394
1395 /* Don't care about the pid owner being correct here - just a search. */
1396 fill_share_mode_entry(&entry, fsp, (uid_t)-1, 0, NO_OPLOCK);
1397
1398 e = find_share_mode_entry(lck, &entry);
1399 if (e == NULL) {
1400 return False;
1401 }
1402
1403 if (delete_on_close) {
1404 e->flags |= SHARE_MODE_ALLOW_INITIAL_DELETE_ON_CLOSE;
1405 } else {
1406 e->flags &= ~SHARE_MODE_ALLOW_INITIAL_DELETE_ON_CLOSE;
1407 }
1408 lck->modified = True;
1409 return True;
1410}
1411
1412bool set_sticky_write_time(struct file_id fileid, struct timespec write_time)
1413{
1414 struct share_mode_lock *lck;
1415
1416 DEBUG(5,("set_sticky_write_time: %s id=%s\n",
1417 timestring(debug_ctx(),
1418 convert_timespec_to_time_t(write_time)),
1419 file_id_string_tos(&fileid)));
1420
1421 lck = get_share_mode_lock(NULL, fileid, NULL, NULL, NULL);
1422 if (lck == NULL) {
1423 return False;
1424 }
1425
1426 if (timespec_compare(&lck->changed_write_time, &write_time) != 0) {
1427 lck->modified = True;
1428 lck->changed_write_time = write_time;
1429 }
1430
1431 TALLOC_FREE(lck);
1432 return True;
1433}
1434
1435bool set_write_time(struct file_id fileid, struct timespec write_time)
1436{
1437 struct share_mode_lock *lck;
1438
1439 DEBUG(5,("set_write_time: %s id=%s\n",
1440 timestring(debug_ctx(),
1441 convert_timespec_to_time_t(write_time)),
1442 file_id_string_tos(&fileid)));
1443
1444 lck = get_share_mode_lock(NULL, fileid, NULL, NULL, NULL);
1445 if (lck == NULL) {
1446 return False;
1447 }
1448
1449 if (timespec_compare(&lck->old_write_time, &write_time) != 0) {
1450 lck->modified = True;
1451 lck->old_write_time = write_time;
1452 }
1453
1454 TALLOC_FREE(lck);
1455 return True;
1456}
1457
1458
1459struct forall_state {
1460 void (*fn)(const struct share_mode_entry *entry,
1461 const char *sharepath,
1462 const char *fname,
1463 void *private_data);
1464 void *private_data;
1465};
1466
1467static int traverse_fn(struct db_record *rec, void *_state)
1468{
1469 struct forall_state *state = (struct forall_state *)_state;
1470 struct locking_data *data;
1471 struct share_mode_entry *shares;
1472 const char *sharepath;
1473 const char *fname;
1474 int i;
1475
1476 /* Ensure this is a locking_key record. */
1477 if (rec->key.dsize != sizeof(struct file_id))
1478 return 0;
1479
1480 data = (struct locking_data *)rec->value.dptr;
1481 shares = (struct share_mode_entry *)(rec->value.dptr + sizeof(*data));
1482 sharepath = (const char *)rec->value.dptr + sizeof(*data) +
1483 data->u.s.num_share_mode_entries*sizeof(*shares) +
1484 data->u.s.delete_token_size;
1485 fname = (const char *)rec->value.dptr + sizeof(*data) +
1486 data->u.s.num_share_mode_entries*sizeof(*shares) +
1487 data->u.s.delete_token_size +
1488 strlen(sharepath) + 1;
1489
1490 for (i=0;i<data->u.s.num_share_mode_entries;i++) {
1491 state->fn(&shares[i], sharepath, fname,
1492 state->private_data);
1493 }
1494 return 0;
1495}
1496
1497/*******************************************************************
1498 Call the specified function on each entry under management by the
1499 share mode system.
1500********************************************************************/
1501
1502int share_mode_forall(void (*fn)(const struct share_mode_entry *, const char *,
1503 const char *, void *),
1504 void *private_data)
1505{
1506 struct forall_state state;
1507
1508 if (lock_db == NULL)
1509 return 0;
1510
1511 state.fn = fn;
1512 state.private_data = private_data;
1513
1514 return lock_db->traverse_read(lock_db, traverse_fn, (void *)&state);
1515}
Note: See TracBrowser for help on using the repository browser.