The branch, v4-2-test has been updated via e7a90aa s3:locking: remove dead code from brl_get_locks_readonly() via 38b8e09 s3:locking: Change from ndr_pull_struct_blob() to ndr_pull_struct_blob_all() so we fail if not all bytes are consumed. via 1fd4868 s4:torture/smb2: test rename dir deny with open files via b5cc961 s3:smbd: Don't rename a dir with files open underneath via beb05a1b selftest:Samba3: use "strict rename = yes" via 4ff4c58 s3:param: Add new option "strict rename". via b527525 s3:locking: allow early return for share_entry_forall() via cfa74dc s3:locking: Introduce share_mode_forall via ac37fae s3:locking: Rename share_mode_forall->share_entry_forall via e430584 s3: smbd: Preparation for leases code merge. Ensure VFS is ready for 4.2.0. via fd4cc75 samba-tool group add: Add option --nis-domain and --gid from 703957e s3: libsmbclient - smb2. MacOSX 10 SMB2 server doesn't set STATUS_NO_MORE_FILES when handed a non-wildcard path.
https://git.samba.org/?p=samba.git;a=shortlog;h=v4-2-test - Log ----------------------------------------------------------------- commit e7a90aaa200d95afe0d6e90a1149d0c9f09aed8f Author: Stefan Metzmacher <me...@samba.org> Date: Wed Oct 29 17:29:06 2014 +0100 s3:locking: remove dead code from brl_get_locks_readonly() struct byte_range_lock *rw = NULL; will never change... commit 105724073300af03eb0835b3c93d9b2e2bfacb07 removed the possible assigment of 'rw'. So we can remove all code under if (rw != NULL) { ... Signed-off-by: Stefan Metzmacher <me...@samba.org> Reviewed-by: Michael Adam <ob...@samba.org> Autobuild-User(master): Jeremy Allison <j...@samba.org> Autobuild-Date(master): Fri Oct 31 06:07:43 CET 2014 on sn-devel-104 (cherry picked from commit a3b333a1a2ab23ba0c59be1fc65c730e2b53e8c5) The last 10 patches address bug #10911 - SMB2 leases are not yet supported. Autobuild-User(v4-2-test): Karolin Seeger <ksee...@samba.org> Autobuild-Date(v4-2-test): Tue Nov 4 23:38:34 CET 2014 on sn-devel-104 commit 38b8e0975c0ad51af722556e27d7c5f7402daf94 Author: Volker Lendecke <v...@samba.org> Date: Tue Oct 28 15:20:26 2014 -0700 s3:locking: Change from ndr_pull_struct_blob() to ndr_pull_struct_blob_all() so we fail if not all bytes are consumed. Signed-off-by: Volker Lendecke <v...@samba.org> Reviewed-by: Jeremy Allison <j...@samba.org> Reviewed-by: Stefan Metzmacher <me...@samba.org> (cherry picked from commit 151b9caeef7dc4fa4816035a406acb9f1c5812c3) commit 1fd48687fe5bf5fd3dcd918422a4fe4fc34d38b9 Author: Volker Lendecke <v...@samba.org> Date: Thu Sep 25 01:32:00 2014 +0200 s4:torture/smb2: test rename dir deny with open files Signed-off-by: Volker Lendecke <v...@samba.org> Reviewed-by: Jeremy Allison <j...@samba.org> Reviewed-by: Stefan Metzmacher <me...@samba.org> (cherry picked from commit 8334428666b8282d2cfbcfd411acab0c338ae390) commit b5cc9614fc6d5296fb5b3482a56888a3aa03461b Author: Volker Lendecke <v...@samba.org> Date: Thu Sep 25 01:30:33 2014 +0200 s3:smbd: Don't rename a dir with files open underneath This is an EXPENSIVE check. We'll have to guard this with an option Signed-off-by: Volker Lendecke <v...@samba.org> Reviewed-by: Jeremy Allison <j...@samba.org> Reviewed-by: Stefan Metzmacher <me...@samba.org> (cherry picked from commit 035fd7200d8a025cdb8bfae30c264757aa3cb193) commit beb05a1b891fd51463def0b6f3b43394e4451414 Author: Jeremy Allison <j...@samba.org> Date: Fri Oct 24 13:57:04 2014 -0700 selftest:Samba3: use "strict rename = yes" Signed-off-by: Jeremy Allison <j...@samba.org> Reviewed-by: Stefan Metzmacher <me...@samba.org> (cherry picked from commit 5f60dcc38ca275aedeb1d67611b5acf9b26361d5) commit 4ff4c58ee75887b8e5e4ea3752eb0d82e13e903a Author: Jeremy Allison <j...@samba.org> Date: Fri Oct 24 13:57:04 2014 -0700 s3:param: Add new option "strict rename". Control whether smbd can rename directories containing open files. Defaults to "no" (meaning we *can* do such renames). Signed-off-by: Jeremy Allison <j...@samba.org> Reviewed-by: Stefan Metzmacher <me...@samba.org> (cherry picked from commit b0a434386dc2f77df89811bc3f56c4cc7fb7b16c) commit b5275259290ae468c9047ef5a1e27b7f113c9718 Author: Volker Lendecke <v...@samba.org> Date: Wed Sep 24 20:46:15 2014 +0200 s3:locking: allow early return for share_entry_forall() Signed-off-by: Volker Lendecke <v...@samba.org> Reviewed-by: Jeremy Allison <j...@samba.org> Reviewed-by: Stefan Metzmacher <me...@samba.org> (cherry picked from commit 9010bbeb00264f4476c3be7d2e8c8420c695cfbb) commit cfa74dcf2617b2c03de1458e35cbb0533d2bfffb Author: Volker Lendecke <v...@samba.org> Date: Tue Sep 23 05:45:49 2014 +0200 s3:locking: Introduce share_mode_forall Signed-off-by: Volker Lendecke <v...@samba.org> Reviewed-by: Jeremy Allison <j...@samba.org> Reviewed-by: Stefan Metzmacher <me...@samba.org> (cherry picked from commit 48926b761975a7d9cb6daf30d64d6a4f0a34f38a) commit ac37fae12b5023a2680df73fe230825be069b515 Author: Volker Lendecke <v...@samba.org> Date: Tue Sep 23 05:18:54 2014 +0200 s3:locking: Rename share_mode_forall->share_entry_forall Signed-off-by: Volker Lendecke <v...@samba.org> Reviewed-by: Jeremy Allison <j...@samba.org> Reviewed-by: Stefan Metzmacher <me...@samba.org> (cherry picked from commit 0d4f7bfdb995a239508457cd433bc8001c0e8279) commit e4305846e7fb3963336189f30839811424151c84 Author: Jeremy Allison <j...@samba.org> Date: Wed Oct 8 09:06:06 2014 -0700 s3: smbd: Preparation for leases code merge. Ensure VFS is ready for 4.2.0. Signed-off-by: Jeremy Allison <j...@samba.org> Reviewed-by: Volker Lendecke <v...@samba.org> Autobuild-User(master): Jeremy Allison <j...@samba.org> Autobuild-Date(master): Fri Oct 10 02:55:53 CEST 2014 on sn-devel-104 (cherry picked from commit aa2a6c7b18e2e2bd3979ffb53208564764b8b9cf) commit fd4cc75b3b19e6dce1f5fdb9e09fe539bb8d026b Author: Marc Muehlfeld <mmuehlf...@samba.org> Date: Sat Oct 18 00:34:35 2014 +0200 samba-tool group add: Add option --nis-domain and --gid This allows creating RFC2307 enabled groups via samba-tool Signed-off-by: Marc Muehlfeld <mmuehlf...@samba.org> Reviewed-by: Michael Adam <ob...@samba.org> Autobuild-User(master): Michael Adam <ob...@samba.org> Autobuild-Date(master): Thu Oct 23 18:19:35 CEST 2014 on sn-devel-104 (cherry picked from commit 4bec1867987845fc40e9a17a283d2affc36e0dc5) Bug: https://bugzilla.samba.org/show_bug.cgi?id=10895 samba-tool can't treat RCF2307 enabled groups ----------------------------------------------------------------------- Summary of changes: docs-xml/smbdotconf/tuning/strictrename.xml | 25 ++++++ lib/param/param_table.c | 9 +++ python/samba/netcmd/group.py | 15 +++- python/samba/samdb.py | 13 ++- selftest/knownfail | 1 + selftest/target/Samba3.pm | 1 + source3/include/vfs.h | 7 ++ source3/locking/brlock.c | 78 +++++++----------- source3/locking/proto.h | 6 +- source3/locking/share_mode_lock.c | 105 ++++++++++++++++-------- source3/param/loadparm.c | 1 + source3/rpc_server/srvsvc/srv_srvsvc_nt.c | 54 +++++++------ source3/smbd/dir.c | 121 +++++++++++++++++++++++++++- source3/utils/status.c | 14 ++-- source4/torture/smb2/rename.c | 97 ++++++++++++++++++++++ 15 files changed, 430 insertions(+), 117 deletions(-) create mode 100644 docs-xml/smbdotconf/tuning/strictrename.xml Changeset truncated at 500 lines: diff --git a/docs-xml/smbdotconf/tuning/strictrename.xml b/docs-xml/smbdotconf/tuning/strictrename.xml new file mode 100644 index 0000000..5478863 --- /dev/null +++ b/docs-xml/smbdotconf/tuning/strictrename.xml @@ -0,0 +1,25 @@ +<samba:parameter name="strict rename" + context="S" + type="boolean" + xmlns:samba="http://www.samba.org/samba/DTD/samba-doc"> +<description> + <para>By default a Windows SMB server prevents directory + renames when there are open file or directory handles below + it in the filesystem hierarchy. Historically Samba has always + allowed this as POSIX filesystem semantics require it.</para> + + <para>This boolean parameter allows Samba to match the Windows + behavior. Setting this to "yes" is a very expensive change, + as it forces Samba to travers the entire open file handle + database on every directory rename request. In a clustered + Samba system the cost is even greater than the non-clustered + case.</para> + + <para>For this reason the default is "no", and it is recommended + to be left that way unless a specific Windows application requires + it to be changed.</para> + +</description> + +<value type="default">no</value> +</samba:parameter> diff --git a/lib/param/param_table.c b/lib/param/param_table.c index d3f60c3..4d0e6a9 100644 --- a/lib/param/param_table.c +++ b/lib/param/param_table.c @@ -1882,6 +1882,15 @@ struct parm_struct parm_table[] = { .flags = FLAG_ADVANCED | FLAG_SHARE, }, { + .label = "strict rename", + .type = P_BOOL, + .p_class = P_LOCAL, + .offset = LOCAL_VAR(strict_rename), + .special = NULL, + .enum_list = NULL, + .flags = FLAG_ADVANCED | FLAG_SHARE, + }, + { .label = "strict sync", .type = P_BOOL, .p_class = P_LOCAL, diff --git a/python/samba/netcmd/group.py b/python/samba/netcmd/group.py index 1a24e5f..4b5fd27 100644 --- a/python/samba/netcmd/group.py +++ b/python/samba/netcmd/group.py @@ -70,6 +70,11 @@ Example2: sudo samba-tool group add Group2 --group-type=Distribution Example2 adds a new distribution group to the local server. The command is run under root using the sudo command. + +Example3: +samba-tool group add Group3 --nis-domain=samdom --gid=12345 + +Example3 adds a new RFC2307 enabled group for NIS domain samdom and GID 12345 (both options are required to enable this feature). """ synopsis = "%prog <groupname> [options]" @@ -93,19 +98,24 @@ Example2 adds a new distribution group to the local server. The command is run Option("--description", help="Group's description", type=str), Option("--mail-address", help="Group's email address", type=str), Option("--notes", help="Groups's notes", type=str), + Option("--gid-number", help="Group's Unix/RFC2307 GID number", type=int), + Option("--nis-domain", help="SFU30 NIS Domain", type=str), ] takes_args = ["groupname"] def run(self, groupname, credopts=None, sambaopts=None, versionopts=None, H=None, groupou=None, group_scope=None, - group_type=None, description=None, mail_address=None, notes=None): + group_type=None, description=None, mail_address=None, notes=None, gid_number=None, nis_domain=None): if (group_type or "Security") == "Security": gtype = security_group.get(group_scope, GTYPE_SECURITY_GLOBAL_GROUP) else: gtype = distribution_group.get(group_scope, GTYPE_DISTRIBUTION_GLOBAL_GROUP) + if (gid_number is None and nis_domain is not None) or (gid_number is not None and nis_domain is None): + raise CommandError('Both --gid-number and --nis-domain have to be set for a RFC2307-enabled group. Operation cancelled.') + lp = sambaopts.get_loadparm() creds = credopts.get_credentials(lp, fallback_machine=True) @@ -113,7 +123,8 @@ Example2 adds a new distribution group to the local server. The command is run samdb = SamDB(url=H, session_info=system_session(), credentials=creds, lp=lp) samdb.newgroup(groupname, groupou=groupou, grouptype = gtype, - description=description, mailaddress=mail_address, notes=notes) + description=description, mailaddress=mail_address, notes=notes, + gidnumber=gid_number, nisdomain=nis_domain) except Exception, e: # FIXME: catch more specific exception raise CommandError('Failed to create group "%s"' % groupname, e) diff --git a/python/samba/samdb.py b/python/samba/samdb.py index 2dfc839..e68519f 100644 --- a/python/samba/samdb.py +++ b/python/samba/samdb.py @@ -169,7 +169,8 @@ pwdLastSet: 0 self.modify_ldif(mod) def newgroup(self, groupname, groupou=None, grouptype=None, - description=None, mailaddress=None, notes=None, sd=None): + description=None, mailaddress=None, notes=None, sd=None, + gidnumber=None, nisdomain=None): """Adds a new group with additional parameters :param groupname: Name of the new group @@ -177,6 +178,8 @@ pwdLastSet: 0 :param description: Description of the new group :param mailaddress: Email address of the new group :param notes: Notes of the new group + :param gidnumber: GID Number of the new group + :param nisdomain: NIS Domain Name of the new group :param sd: security descriptor of the object """ @@ -188,6 +191,8 @@ pwdLastSet: 0 "sAMAccountName": groupname, "objectClass": "group"} + ldbmessage["msSFU30Name"] = groupname + if grouptype is not None: ldbmessage["groupType"] = normalise_int32(grouptype) @@ -200,6 +205,12 @@ pwdLastSet: 0 if notes is not None: ldbmessage["info"] = notes + if gidnumber is not None: + ldbmessage["gidNumber"] = normalise_int32(gidnumber) + + if nisdomain is not None: + ldbmessage["msSFU30NisDomain"] = nisdomain + if sd is not None: ldbmessage["nTSecurityDescriptor"] = ndr_pack(sd) diff --git a/selftest/knownfail b/selftest/knownfail index 3d73495..6cca3dd 100644 --- a/selftest/knownfail +++ b/selftest/knownfail @@ -112,6 +112,7 @@ ^samba4.smb2.rename.no_share_delete_no_delete_access\(.*\)$ ^samba4.smb2.rename.msword ^samba4.smb2.rename.rename_dir_bench\(dc\) +^samba4.smb2.rename.rename_dir_openfile\(.*\)$ ^samba4.smb2.oplock.doc ^samba4.smb2.compound.related3 ^samba4.smb2.compound.compound-break diff --git a/selftest/target/Samba3.pm b/selftest/target/Samba3.pm index de40ced..ebe2c09 100755 --- a/selftest/target/Samba3.pm +++ b/selftest/target/Samba3.pm @@ -1073,6 +1073,7 @@ sub provision($$$$$$) store dos attributes = yes create mask = 755 dos filemode = yes + strict rename = yes vfs objects = acl_xattr fake_acls xattr_tdb streams_depot printing = vlp diff --git a/source3/include/vfs.h b/source3/include/vfs.h index 3702b75..b0f00e8 100644 --- a/source3/include/vfs.h +++ b/source3/include/vfs.h @@ -158,6 +158,7 @@ /* Bump to version 32 - Samba 4.2 will ship with that. */ /* Version 32 - Add "lease" to CREATE_FILE operation */ +/* Version 32 - Add "lease" to struct files_struct */ #define SMB_VFS_INTERFACE_VERSION 32 @@ -202,6 +203,11 @@ struct fd_handle { unsigned long gen_id; }; +struct fsp_lease { + size_t ref_count; + struct smb2_lease lease; +}; + typedef struct files_struct { struct files_struct *next, *prev; uint64_t fnum; @@ -225,6 +231,7 @@ typedef struct files_struct { bool write_time_forced; int oplock_type; + struct fsp_lease *lease; /* Not yet used. Placeholder for leases. */ int sent_oplock_break; struct tevent_timer *oplock_timeout; struct lock_struct last_lock_failure; diff --git a/source3/locking/brlock.c b/source3/locking/brlock.c index 295e147..1c4c4d0 100644 --- a/source3/locking/brlock.c +++ b/source3/locking/brlock.c @@ -2026,7 +2026,8 @@ static void brl_get_locks_readonly_parser(TDB_DATA key, TDB_DATA data, struct byte_range_lock *brl_get_locks_readonly(files_struct *fsp) { struct byte_range_lock *br_lock = NULL; - struct byte_range_lock *rw = NULL; + struct brl_get_locks_readonly_state state; + NTSTATUS status; DEBUG(10, ("seqnum=%d, fsp->brlock_seqnum=%d\n", dbwrap_get_seqnum(brlock_db), fsp->brlock_seqnum)); @@ -2040,60 +2041,39 @@ struct byte_range_lock *brl_get_locks_readonly(files_struct *fsp) return fsp->brlock_rec; } - if (rw != NULL) { - size_t lock_data_size; + /* + * Parse the record fresh from the database + */ + + state.mem_ctx = fsp; + state.br_lock = &br_lock; + status = dbwrap_parse_record( + brlock_db, + make_tdb_data((uint8_t *)&fsp->file_id, + sizeof(fsp->file_id)), + brl_get_locks_readonly_parser, &state); + + if (NT_STATUS_EQUAL(status,NT_STATUS_NOT_FOUND)) { /* - * Make a copy of the already retrieved and sanitized rw record + * No locks on this file. Return an empty br_lock. */ - lock_data_size = rw->num_locks * sizeof(struct lock_struct); - br_lock = talloc_pooled_object( - fsp, struct byte_range_lock, 1, lock_data_size); + br_lock = talloc(fsp, struct byte_range_lock); if (br_lock == NULL) { - goto fail; + return NULL; } - br_lock->have_read_oplocks = rw->have_read_oplocks; - br_lock->num_locks = rw->num_locks; - br_lock->lock_data = (struct lock_struct *)talloc_memdup( - br_lock, rw->lock_data, lock_data_size); - } else { - struct brl_get_locks_readonly_state state; - NTSTATUS status; - - /* - * Parse the record fresh from the database - */ - state.mem_ctx = fsp; - state.br_lock = &br_lock; - - status = dbwrap_parse_record( - brlock_db, - make_tdb_data((uint8_t *)&fsp->file_id, - sizeof(fsp->file_id)), - brl_get_locks_readonly_parser, &state); - - if (NT_STATUS_EQUAL(status,NT_STATUS_NOT_FOUND)) { - /* - * No locks on this file. Return an empty br_lock. - */ - br_lock = talloc(fsp, struct byte_range_lock); - if (br_lock == NULL) { - goto fail; - } - - br_lock->have_read_oplocks = false; - br_lock->num_locks = 0; - br_lock->lock_data = NULL; + br_lock->have_read_oplocks = false; + br_lock->num_locks = 0; + br_lock->lock_data = NULL; - } else if (!NT_STATUS_IS_OK(status)) { - DEBUG(3, ("Could not parse byte range lock record: " - "%s\n", nt_errstr(status))); - goto fail; - } - if (br_lock == NULL) { - goto fail; - } + } else if (!NT_STATUS_IS_OK(status)) { + DEBUG(3, ("Could not parse byte range lock record: " + "%s\n", nt_errstr(status))); + return NULL; + } + if (br_lock == NULL) { + return NULL; } br_lock->fsp = fsp; @@ -2117,8 +2097,6 @@ struct byte_range_lock *brl_get_locks_readonly(files_struct *fsp) fsp->brlock_seqnum = dbwrap_get_seqnum(brlock_db); } -fail: - TALLOC_FREE(rw); return br_lock; } diff --git a/source3/locking/proto.h b/source3/locking/proto.h index 46eec2a..44f3ba1 100644 --- a/source3/locking/proto.h +++ b/source3/locking/proto.h @@ -190,7 +190,11 @@ bool is_delete_on_close_set(struct share_mode_lock *lck, uint32_t name_hash); bool set_sticky_write_time(struct file_id fileid, struct timespec write_time); bool set_write_time(struct file_id fileid, struct timespec write_time); struct timespec get_share_mode_write_time(struct share_mode_lock *lck); -int share_mode_forall(void (*fn)(const struct share_mode_entry *, const char *, +int share_mode_forall(int (*fn)(struct file_id fid, + const struct share_mode_data *data, + void *private_data), + void *private_data); +int share_entry_forall(int (*fn)(const struct share_mode_entry *, const char *, const char *, void *), void *private_data); bool share_mode_cleanup_disconnected(struct file_id id, diff --git a/source3/locking/share_mode_lock.c b/source3/locking/share_mode_lock.c index 12f499b..65409ac 100644 --- a/source3/locking/share_mode_lock.c +++ b/source3/locking/share_mode_lock.c @@ -133,7 +133,7 @@ static struct share_mode_data *parse_share_modes(TALLOC_CTX *mem_ctx, blob.data = dbuf.dptr; blob.length = dbuf.dsize; - ndr_err = ndr_pull_struct_blob( + ndr_err = ndr_pull_struct_blob_all( &blob, d, d, (ndr_pull_flags_fn_t)ndr_pull_share_mode_data); if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { DEBUG(1, ("ndr_pull_share_mode_lock failed: %s\n", @@ -440,30 +440,33 @@ struct share_mode_lock *fetch_share_mode_unlocked(TALLOC_CTX *mem_ctx, return lck; } -struct forall_state { - void (*fn)(const struct share_mode_entry *entry, - const char *sharepath, - const char *fname, - void *private_data); +struct share_mode_forall_state { + int (*fn)(struct file_id fid, const struct share_mode_data *data, + void *private_data); void *private_data; }; -static int traverse_fn(struct db_record *rec, void *_state) +static int share_mode_traverse_fn(struct db_record *rec, void *_state) { - struct forall_state *state = (struct forall_state *)_state; + struct share_mode_forall_state *state = + (struct share_mode_forall_state *)_state; uint32_t i; TDB_DATA key; TDB_DATA value; DATA_BLOB blob; enum ndr_err_code ndr_err; struct share_mode_data *d; + struct file_id fid; + int ret; key = dbwrap_record_get_key(rec); value = dbwrap_record_get_value(rec); /* Ensure this is a locking_key record. */ - if (key.dsize != sizeof(struct file_id)) + if (key.dsize != sizeof(fid)) { return 0; + } + memcpy(&fid, key.dptr, sizeof(fid)); d = talloc(talloc_tos(), struct share_mode_data); if (d == NULL) { @@ -473,7 +476,7 @@ static int traverse_fn(struct db_record *rec, void *_state) blob.data = value.dptr; blob.length = value.dsize; - ndr_err = ndr_pull_struct_blob( + ndr_err = ndr_pull_struct_blob_all( &blob, d, d, (ndr_pull_flags_fn_t)ndr_pull_share_mode_data); if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { DEBUG(1, ("ndr_pull_share_mode_lock failed\n")); @@ -485,42 +488,80 @@ static int traverse_fn(struct db_record *rec, void *_state) } for (i=0; i<d->num_share_modes; i++) { d->share_modes[i].stale = false; /* [skip] in idl */ - state->fn(&d->share_modes[i], - d->servicepath, d->base_name, - state->private_data); } - TALLOC_FREE(d); - return 0; -} + ret = state->fn(fid, d, state->private_data); -/******************************************************************* - Call the specified function on each entry under management by the - share mode system. -********************************************************************/ + TALLOC_FREE(d); + return ret; +} -int share_mode_forall(void (*fn)(const struct share_mode_entry *, const char *, - const char *, void *), +int share_mode_forall(int (*fn)(struct file_id fid, + const struct share_mode_data *data, + void *private_data), void *private_data) { - struct forall_state state; + struct share_mode_forall_state state = { + .fn = fn, + .private_data = private_data + }; NTSTATUS status; int count; - if (lock_db == NULL) + if (lock_db == NULL) { return 0; + } - state.fn = fn; - state.private_data = private_data; - - status = dbwrap_traverse_read(lock_db, traverse_fn, (void *)&state, - &count); - + status = dbwrap_traverse_read(lock_db, share_mode_traverse_fn, + &state, &count); if (!NT_STATUS_IS_OK(status)) { return -1; - } else { - return count; } + + return count; +} + +struct share_entry_forall_state { + int (*fn)(const struct share_mode_entry *e, + const char *service_path, const char *base_name, + void *private_data); + void *private_data; +}; + +static int share_entry_traverse_fn(struct file_id fid, + const struct share_mode_data *data, + void *private_data) +{ + struct share_entry_forall_state *state = private_data; + uint32_t i; + + for (i=0; i<data->num_share_modes; i++) { + int ret; + + ret = state->fn(&data->share_modes[i], + data->servicepath, data->base_name, + state->private_data); + if (ret != 0) { + return ret; + } + } + + return 0; +} + +/******************************************************************* + Call the specified function on each entry under management by the + share mode system. +********************************************************************/ + +int share_entry_forall(int (*fn)(const struct share_mode_entry *, + const char *, const char *, void *), + void *private_data) +{ + struct share_entry_forall_state state = { + .fn = fn, .private_data = private_data }; + + return share_mode_forall(share_entry_traverse_fn, &state); } bool share_mode_cleanup_disconnected(struct file_id fid, diff --git a/source3/param/loadparm.c b/source3/param/loadparm.c index 5ab0de7..884cc45 100644 -- Samba Shared Repository