The branch, master has been updated via 0bf6ec8 s3:selftest: run smbtorture3 CLEANUP3 in the s3dc:local environment via 68d03f2 s3: Test whether get_share_mode_lock cleans up stale processes via 58dff07 s3: Do not check the PIDs is parse_share_modes via 50fdb32 Ensure we only return NT_STATUS_DELETE_PENDING if the share modes are valid. via 89cf7ea s3: Check for serverid_exists in close_directory via bdc4404 s3: Check for serverid_exists in close_remove_share_mode via bc3b7d7 s3: Be less picky on stale share mode entries via 1b15d8b s3: Check for serverid_exists in find_oplock_types via 6666de1 s3: Check for serverid_exists in rename_share_filename via e2818d4 s3: Check for serverid_exists in smb_posix_unlink via fdcca54 s3: Check for serverid_exists in open_mode_check via 19b6671 s3: Check for serverid_exists in notify_deferred_opens via 65264326 Fix an invalid state only reachable on server crash/abort. via 5842d4e s3: Add "share_mode_stale_pid" via 035342c Fix bug #8373 - Can't join XP Pro workstations to 3.6.1 DC. from e17fa58 s3:smbd: move global smbd_msg_state to smbXsrv_connection
http://gitweb.samba.org/?p=samba.git;a=shortlog;h=master - Log ----------------------------------------------------------------- commit 0bf6ec88eddc8e3267deeaa8f48b79f76a184834 Author: Stefan Metzmacher <me...@samba.org> Date: Wed May 16 09:11:40 2012 +0200 s3:selftest: run smbtorture3 CLEANUP3 in the s3dc:local environment metze Signed-off-by: Jeremy Allison <j...@samba.org> Autobuild-User: Jeremy Allison <j...@samba.org> Autobuild-Date: Fri May 25 20:09:15 CEST 2012 on sn-devel-104 commit 68d03f2ef587d32e1c80e51716b032c8c307ad1e Author: Volker Lendecke <v...@samba.org> Date: Fri May 11 14:39:42 2012 +0200 s3: Test whether get_share_mode_lock cleans up stale processes Signed-off-by: Jeremy Allison <j...@samba.org> Signed-off-by: Stefan Metzmacher <me...@samba.org> commit 58dff077d994b66591f5c208112027959336b178 Author: Volker Lendecke <v...@samba.org> Date: Mon May 7 16:34:11 2012 +0200 s3: Do not check the PIDs is parse_share_modes We do that when conflicts arise Signed-off-by: Jeremy Allison <j...@samba.org> Signed-off-by: Stefan Metzmacher <me...@samba.org> commit 50fdb32a4d30128d3e23d98833b31b84fc3f8215 Author: Jeremy Allison <j...@samba.org> Date: Tue May 22 12:28:04 2012 -0700 Ensure we only return NT_STATUS_DELETE_PENDING if the share modes are valid. Ensure we only return *file_existed = true if there were valid share modes. Signed-off-by: Stefan Metzmacher <me...@samba.org> commit 89cf7ea944b8947d5b64b5e2819936ea8af1e661 Author: Volker Lendecke <v...@samba.org> Date: Mon May 7 15:23:29 2012 +0200 s3: Check for serverid_exists in close_directory Signed-off-by: Jeremy Allison <j...@samba.org> Signed-off-by: Stefan Metzmacher <me...@samba.org> commit bdc4404ef950e3cb4d026dd49a247b5ab8ecdbd4 Author: Volker Lendecke <v...@samba.org> Date: Mon May 7 15:23:29 2012 +0200 s3: Check for serverid_exists in close_remove_share_mode Signed-off-by: Jeremy Allison <j...@samba.org> Signed-off-by: Stefan Metzmacher <me...@samba.org> commit bc3b7d76a8ea1b96668163af9379ba4be3771466 Author: Volker Lendecke <v...@samba.org> Date: Mon May 14 14:57:34 2012 +0200 s3: Be less picky on stale share mode entries If a process died, the share mode entry might be bogus. Ignore those entries. Signed-off-by: Jeremy Allison <j...@samba.org> Signed-off-by: Stefan Metzmacher <me...@samba.org> commit 1b15d8b3da19c2f43f41632cd3e1fe20f5088bbb Author: Volker Lendecke <v...@samba.org> Date: Mon May 7 15:23:29 2012 +0200 s3: Check for serverid_exists in find_oplock_types Signed-off-by: Jeremy Allison <j...@samba.org> Signed-off-by: Stefan Metzmacher <me...@samba.org> commit 6666de1975e596990cc7b031a89ce67000093987 Author: Volker Lendecke <v...@samba.org> Date: Mon May 7 15:23:10 2012 +0200 s3: Check for serverid_exists in rename_share_filename Signed-off-by: Jeremy Allison <j...@samba.org> Signed-off-by: Stefan Metzmacher <me...@samba.org> commit e2818d4a0b87bf9ff8b2dc14698fa14c7e695c23 Author: Volker Lendecke <v...@samba.org> Date: Mon May 7 15:23:29 2012 +0200 s3: Check for serverid_exists in smb_posix_unlink Signed-off-by: Jeremy Allison <j...@samba.org> Signed-off-by: Stefan Metzmacher <me...@samba.org> commit fdcca54ca302e9b92bdf72823f6a7c9b63886728 Author: Volker Lendecke <v...@samba.org> Date: Mon May 7 15:23:10 2012 +0200 s3: Check for serverid_exists in open_mode_check Signed-off-by: Jeremy Allison <j...@samba.org> Signed-off-by: Stefan Metzmacher <me...@samba.org> commit 19b6671c07be2419398a07f202e22abefe562176 Author: Volker Lendecke <v...@samba.org> Date: Mon May 7 12:22:50 2012 +0200 s3: Check for serverid_exists in notify_deferred_opens We will remove the check in parse_share_modes soon Signed-off-by: Jeremy Allison <j...@samba.org> Signed-off-by: Stefan Metzmacher <me...@samba.org> commit 6526432682760f182fdd9152b923fa3468c042ff Author: Jeremy Allison <j...@samba.org> Date: Tue May 22 12:27:06 2012 -0700 Fix an invalid state only reachable on server crash/abort. Remove any delete-on-close tokens and clear the count if there are no valid share modes. Signed-off-by: Stefan Metzmacher <me...@samba.org> commit 5842d4e025e4c042829a585fe6c58b71b219386f Author: Volker Lendecke <v...@samba.org> Date: Mon May 7 12:57:07 2012 +0200 s3: Add "share_mode_stale_pid" This is a helper routine that prunes a dead share mode entry on demand. This prepares for removing the serverids_exist call in parse_share_modes. Signed-off-by: Jeremy Allison <j...@samba.org> Signed-off-by: Stefan Metzmacher <me...@samba.org> commit 035342c11719d1daa647c0b2ae7cec27a969f83a Author: Jeremy Allison <j...@samba.org> Date: Fri May 25 09:16:50 2012 -0700 Fix bug #8373 - Can't join XP Pro workstations to 3.6.1 DC. Treat LIBNDR_FLAG_NOALIGN and LIBNDR_FLAG_REMAINING the same as the other align flags - make them mutually exclusive. Combined work from Metze, Günther and Jeremy. ----------------------------------------------------------------------- Summary of changes: librpc/ndr/libndr.h | 8 ++- librpc/ndr/ndr.c | 8 +- source3/Makefile.in | 3 +- source3/locking/locking.c | 51 +++++++++++- source3/locking/proto.h | 1 + source3/locking/share_mode_lock.c | 42 --------- source3/selftest/tests.py | 4 + source3/smbd/close.c | 16 +++- source3/smbd/open.c | 46 +++++++++- source3/smbd/trans2.c | 3 + source3/torture/proto.h | 1 + source3/torture/test_cleanup.c | 175 +++++++++++++++++++++++++++++++++++++ source3/torture/torture.c | 1 + source3/wscript_build | 3 +- 14 files changed, 307 insertions(+), 55 deletions(-) Changeset truncated at 500 lines: diff --git a/librpc/ndr/libndr.h b/librpc/ndr/libndr.h index 37a3145..1bd284f 100644 --- a/librpc/ndr/libndr.h +++ b/librpc/ndr/libndr.h @@ -135,7 +135,13 @@ struct ndr_print { #define LIBNDR_FLAG_ALIGN4 (1<<23) #define LIBNDR_FLAG_ALIGN8 (1<<24) -#define LIBNDR_ALIGN_FLAGS (LIBNDR_FLAG_ALIGN2|LIBNDR_FLAG_ALIGN4|LIBNDR_FLAG_ALIGN8) +#define LIBNDR_ALIGN_FLAGS ( 0 | \ + LIBNDR_FLAG_NOALIGN | \ + LIBNDR_FLAG_REMAINING | \ + LIBNDR_FLAG_ALIGN2 | \ + LIBNDR_FLAG_ALIGN4 | \ + LIBNDR_FLAG_ALIGN8 | \ + 0) #define LIBNDR_PRINT_ARRAY_HEX (1<<25) #define LIBNDR_PRINT_SET_VALUES (1<<26) diff --git a/librpc/ndr/ndr.c b/librpc/ndr/ndr.c index 2279d1c..b77bfae 100644 --- a/librpc/ndr/ndr.c +++ b/librpc/ndr/ndr.c @@ -378,11 +378,11 @@ _PUBLIC_ void ndr_set_flags(uint32_t *pflags, uint32_t new_flags) (*pflags) &= ~LIBNDR_FLAG_LITTLE_ENDIAN; (*pflags) &= ~LIBNDR_FLAG_NDR64; } - if (new_flags & LIBNDR_FLAG_REMAINING) { - (*pflags) &= ~LIBNDR_ALIGN_FLAGS; - } if (new_flags & LIBNDR_ALIGN_FLAGS) { - (*pflags) &= ~LIBNDR_FLAG_REMAINING; + /* Ensure we only have the passed-in + align flag set in the new_flags, + remove any old align flag. */ + (*pflags) &= ~LIBNDR_ALIGN_FLAGS; } if (new_flags & LIBNDR_FLAG_NO_RELATIVE_REVERSE) { (*pflags) &= ~LIBNDR_FLAG_RELATIVE_REVERSE; diff --git a/source3/Makefile.in b/source3/Makefile.in index e289252..9bd4f90 100644 --- a/source3/Makefile.in +++ b/source3/Makefile.in @@ -1283,11 +1283,12 @@ SMBTORTURE_OBJ1 = torture/torture.o torture/nbio.o torture/scanner.o torture/uta torture/t_strappend.o SMBTORTURE_OBJ = $(SMBTORTURE_OBJ1) $(PARAM_OBJ) $(TLDAP_OBJ) \ - $(LIBSMB_OBJ) $(KRBCLIENT_OBJ) $(LIB_NONSMBD_OBJ) \ + $(LIBSMB_OBJ) $(KRBCLIENT_OBJ) $(LIB_NONSMBD_OBJ) $(LOCKING_OBJ) \ @LIBWBCLIENT_STATIC@ \ torture/wbc_async.o \ ../nsswitch/wb_reqtrans.o \ ../libcli/lsarpc/util_lsarpc.o \ + lib/filename_util.o \ $(LIBMSRPC_OBJ) $(LIBMSRPC_GEN_OBJ) $(LIBCLI_ECHO_OBJ) MASKTEST_OBJ = torture/masktest.o $(PARAM_OBJ) $(LIBSMB_OBJ) $(KRBCLIENT_OBJ) \ diff --git a/source3/locking/locking.c b/source3/locking/locking.c index b9afd23..00a46fa 100644 --- a/source3/locking/locking.c +++ b/source3/locking/locking.c @@ -556,6 +556,10 @@ bool rename_share_filename(struct messaging_context *msg_ctx, continue; } + if (share_mode_stale_pid(d, i)) { + continue; + } + DEBUG(10,("rename_share_filename: sending rename message to " "pid %s file_id %s sharepath %s base_name %s " "stream_name %s\n", @@ -616,7 +620,9 @@ bool is_valid_share_mode_entry(const struct share_mode_entry *e) num_props += (EXCLUSIVE_OPLOCK_TYPE(e->op_type) ? 1 : 0); num_props += (LEVEL_II_OPLOCK_TYPE(e->op_type) ? 1 : 0); - SMB_ASSERT(num_props <= 1); + if (serverid_exists(&e->pid) && (num_props > 1)) { + smb_panic("Invalid share mode entry"); + } return (num_props != 0); } @@ -625,6 +631,49 @@ bool is_deferred_open_entry(const struct share_mode_entry *e) return (e->op_type == DEFERRED_OPEN_ENTRY); } +/* + * In case d->share_modes[i] conflicts with something or otherwise is + * being used, we need to make sure the corresponding process still + * exists. This routine checks it and potentially removes the entry + * from d->share_modes. Modifies d->num_share_modes, watch out in + * routines iterating over that array. + */ +bool share_mode_stale_pid(struct share_mode_data *d, unsigned i) +{ + struct share_mode_entry *e; + + if (i > d->num_share_modes) { + DEBUG(1, ("Asking for index %u, only %u around\n", + i, (unsigned)d->num_share_modes)); + return false; + } + e = &d->share_modes[i]; + if (serverid_exists(&e->pid)) { + DEBUG(10, ("PID %s (index %u out of %u) still exists\n", + procid_str_static(&e->pid), i, + (unsigned)d->num_share_modes)); + return false; + } + DEBUG(10, ("PID %s (index %u out of %u) does not exist anymore\n", + procid_str_static(&e->pid), i, + (unsigned)d->num_share_modes)); + *e = d->share_modes[d->num_share_modes-1]; + d->num_share_modes -= 1; + + if (d->num_share_modes == 0 && + d->num_delete_tokens) { + /* + * We cannot have any delete tokens + * if there are no valid share modes. + */ + TALLOC_FREE(d->delete_tokens); + d->num_delete_tokens = 0; + } + + d->modified = true; + return true; +} + /******************************************************************* Fill a share mode entry. ********************************************************************/ diff --git a/source3/locking/proto.h b/source3/locking/proto.h index 54badd9..f6a6f2e 100644 --- a/source3/locking/proto.h +++ b/source3/locking/proto.h @@ -168,6 +168,7 @@ void get_file_infos(struct file_id id, struct timespec *write_time); bool is_valid_share_mode_entry(const struct share_mode_entry *e); bool is_deferred_open_entry(const struct share_mode_entry *e); +bool share_mode_stale_pid(struct share_mode_data *d, unsigned i); void set_share_mode(struct share_mode_lock *lck, files_struct *fsp, uid_t uid, uint64_t mid, uint16 op_type); void add_deferred_open(struct share_mode_lock *lck, uint64_t mid, diff --git a/source3/locking/share_mode_lock.c b/source3/locking/share_mode_lock.c index 493bc15..171c72f 100644 --- a/source3/locking/share_mode_lock.c +++ b/source3/locking/share_mode_lock.c @@ -118,9 +118,6 @@ static struct share_mode_data *parse_share_modes(TALLOC_CTX *mem_ctx, const TDB_DATA dbuf) { struct share_mode_data *d; - int i; - struct server_id *pids; - bool *pid_exists; enum ndr_err_code ndr_err; DATA_BLOB blob; @@ -148,45 +145,6 @@ static struct share_mode_data *parse_share_modes(TALLOC_CTX *mem_ctx, NDR_PRINT_DEBUG(share_mode_data, d); } - /* - * Ensure that each entry has a real process attached. - */ - - pids = talloc_array(talloc_tos(), struct server_id, - d->num_share_modes); - if (pids == NULL) { - DEBUG(0, ("talloc failed\n")); - goto fail; - } - pid_exists = talloc_array(talloc_tos(), bool, d->num_share_modes); - if (pid_exists == NULL) { - DEBUG(0, ("talloc failed\n")); - goto fail; - } - - for (i=0; i<d->num_share_modes; i++) { - pids[i] = d->share_modes[i].pid; - } - if (!serverids_exist(pids, d->num_share_modes, pid_exists)) { - DEBUG(0, ("serverid_exists failed\n")); - goto fail; - } - - i = 0; - while (i < d->num_share_modes) { - struct share_mode_entry *e = &d->share_modes[i]; - if (!pid_exists[i]) { - DEBUG(10, ("wipe non-existent pid %s\n", - procid_str_static(&e->pid))); - *e = d->share_modes[d->num_share_modes-1]; - d->num_share_modes -= 1; - d->modified = True; - continue; - } - i += 1; - } - TALLOC_FREE(pid_exists); - TALLOC_FREE(pids); return d; fail: TALLOC_FREE(d); diff --git a/source3/selftest/tests.py b/source3/selftest/tests.py index fa1f5e5..ce80274 100755 --- a/source3/selftest/tests.py +++ b/source3/selftest/tests.py @@ -90,6 +90,10 @@ for t in tests: plantestsuite("samba3.smbtorture_s3.crypt(s3dc).%s" % t, "s3dc", [os.path.join(samba3srcdir, "script/tests/test_smbtorture_s3.sh"), t, '//$SERVER_IP/tmp', '$USERNAME', '$PASSWORD', binpath('smbtorture3'), "-e", "-l $LOCAL_PATH"]) plantestsuite("samba3.smbtorture_s3.plain(dc).%s" % t, "dc", [os.path.join(samba3srcdir, "script/tests/test_smbtorture_s3.sh"), t, '//$SERVER_IP/tmp', '$USERNAME', '$PASSWORD', binpath('smbtorture3'), "", "-l $LOCAL_PATH"]) +env = "s3dc:local" +t = "CLEANUP3" +plantestsuite("samba3.smbtorture_s3.plain(%s).%s" % (env, t), env, [os.path.join(samba3srcdir, "script/tests/test_smbtorture_s3.sh"), t, '//$SERVER_IP/tmp', '$USERNAME', '$PASSWORD', binpath('smbtorture3'), "", "-l $LOCAL_PATH"]) + local_tests=[ "LOCAL-SUBSTITUTE", "LOCAL-GENCACHE", diff --git a/source3/smbd/close.c b/source3/smbd/close.c index 22d756c..4b7f694 100644 --- a/source3/smbd/close.c +++ b/source3/smbd/close.c @@ -179,9 +179,15 @@ static void notify_deferred_opens(struct smbd_server_connection *sconn, num_deferred = 0; for (i=0; i<lck->data->num_share_modes; i++) { - if (is_deferred_open_entry(&lck->data->share_modes[i])) { - num_deferred += 1; + struct share_mode_entry *e = &lck->data->share_modes[i]; + + if (!is_deferred_open_entry(e)) { + continue; + } + if (share_mode_stale_pid(lck->data, i)) { + continue; } + num_deferred += 1; } if (num_deferred == 0) { return; @@ -419,6 +425,9 @@ static NTSTATUS close_remove_share_mode(files_struct *fsp, if (fsp->posix_open && (e->flags & SHARE_MODE_FLAG_POSIX_OPEN)) { continue; } + if (share_mode_stale_pid(lck->data, i)) { + continue; + } delete_file = False; break; } @@ -1081,6 +1090,9 @@ static NTSTATUS close_directory(struct smb_request *req, files_struct *fsp, if (fsp->posix_open && (e->flags & SHARE_MODE_FLAG_POSIX_OPEN)) { continue; } + if (share_mode_stale_pid(lck->data, i)) { + continue; + } delete_dir = False; break; } diff --git a/source3/smbd/open.c b/source3/smbd/open.c index 543a661..9042e90 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -984,12 +984,23 @@ static NTSTATUS open_mode_check(connection_struct *conn, return NT_STATUS_OK; } - *file_existed = True; - /* A delete on close prohibits everything */ if (is_delete_on_close_set(lck, name_hash)) { - return NT_STATUS_DELETE_PENDING; + /* + * Check the delete on close token + * is valid. It could have been left + * after a server crash. + */ + for(i = 0; i < lck->data->num_share_modes; i++) { + if (!share_mode_stale_pid(lck->data, i)) { + + *file_existed = true; + + return NT_STATUS_DELETE_PENDING; + } + } + return NT_STATUS_OK; } if (is_stat_open(access_mask)) { @@ -1024,10 +1035,21 @@ static NTSTATUS open_mode_check(connection_struct *conn, * too */ if (share_conflict(&lck->data->share_modes[i], access_mask, share_access)) { + + if (share_mode_stale_pid(lck->data, i)) { + continue; + } + + *file_existed = true; + return NT_STATUS_SHARING_VIOLATION; } } + if (lck->data->num_share_modes != 0) { + *file_existed = true; + } + return NT_STATUS_OK; } @@ -1123,6 +1145,10 @@ static void find_oplock_types(files_struct *fsp, if (BATCH_OPLOCK_TYPE(lck->data->share_modes[i].op_type)) { /* batch - can only be one. */ + if (share_mode_stale_pid(lck->data, i)) { + DEBUG(10, ("Found stale batch oplock\n")); + continue; + } if (*pp_ex_or_batch || *pp_batch || *got_level2 || *got_no_oplock) { smb_panic("Bad batch oplock entry."); } @@ -1130,6 +1156,10 @@ static void find_oplock_types(files_struct *fsp, } if (EXCLUSIVE_OPLOCK_TYPE(lck->data->share_modes[i].op_type)) { + if (share_mode_stale_pid(lck->data, i)) { + DEBUG(10, ("Found stale duplicate oplock\n")); + continue; + } /* Exclusive or batch - can only be one. */ if (*pp_ex_or_batch || *got_level2 || *got_no_oplock) { smb_panic("Bad exclusive or batch oplock entry."); @@ -1139,6 +1169,11 @@ static void find_oplock_types(files_struct *fsp, if (LEVEL_II_OPLOCK_TYPE(lck->data->share_modes[i].op_type)) { if (*pp_batch || *pp_ex_or_batch) { + if (share_mode_stale_pid(lck->data, i)) { + DEBUG(10, ("Found stale LevelII " + "oplock\n")); + continue; + } smb_panic("Bad levelII oplock entry."); } *got_level2 = true; @@ -1146,6 +1181,11 @@ static void find_oplock_types(files_struct *fsp, if (lck->data->share_modes[i].op_type == NO_OPLOCK) { if (*pp_batch || *pp_ex_or_batch) { + if (share_mode_stale_pid(lck->data, i)) { + DEBUG(10, ("Found stale NO_OPLOCK " + "entry\n")); + continue; + } smb_panic("Bad no oplock entry."); } *got_no_oplock = true; diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index d4b32ce..af2a21f 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -7596,6 +7596,9 @@ static NTSTATUS smb_posix_unlink(connection_struct *conn, if (e->flags & SHARE_MODE_FLAG_POSIX_OPEN) { continue; } + if (share_mode_stale_pid(lck->data, i)) { + continue; + } /* Fail with sharing violation. */ close_file(req, fsp, NORMAL_CLOSE); TALLOC_FREE(lck); diff --git a/source3/torture/proto.h b/source3/torture/proto.h index 80618ce..4104fbc 100644 --- a/source3/torture/proto.h +++ b/source3/torture/proto.h @@ -104,6 +104,7 @@ bool run_local_conv_auth_info(int dummy); bool run_local_sprintf_append(int dummy); bool run_cleanup1(int dummy); bool run_cleanup2(int dummy); +bool run_cleanup3(int dummy); bool run_ctdb_conn(int dummy); bool run_msg_test(int dummy); bool run_notify_bench2(int dummy); diff --git a/source3/torture/test_cleanup.c b/source3/torture/test_cleanup.c index 39f579a..d9dce40 100644 --- a/source3/torture/test_cleanup.c +++ b/source3/torture/test_cleanup.c @@ -18,11 +18,14 @@ */ #include "includes.h" +#include "locking/proto.h" #include "torture/proto.h" #include "system/filesys.h" +#include "system/select.h" #include "libsmb/libsmb.h" #include "libcli/smb/smbXcli_base.h" #include "libcli/security/security.h" +#include "librpc/gen_ndr/open_files.h" bool run_cleanup1(int dummy) { @@ -154,3 +157,175 @@ bool run_cleanup2(int dummy) } return true; } + +static bool create_stale_share_mode_entry(const char *fname, + struct file_id *p_id) +{ + struct cli_state *cli; + uint16_t fnum; + NTSTATUS status; + SMB_STRUCT_STAT sbuf; + struct file_id id; + + if (!torture_open_connection(&cli, 0)) { + return false; + } + + status = torture_setup_unix_extensions(cli); + if (!NT_STATUS_IS_OK(status)) { + printf("torture_setup_unix_extensions failed: %s\n", + nt_errstr(status)); + return false; + } + status = cli_openx(cli, fname, O_RDWR|O_CREAT, DENY_ALL, &fnum); + if (!NT_STATUS_IS_OK(status)) { + printf("open of %s failed (%s)\n", fname, nt_errstr(status)); + return false; + } + status = cli_posix_stat(cli, fname, &sbuf); + if (!NT_STATUS_IS_OK(status)) { + printf("cli_posix_stat failed: %s\n", nt_errstr(status)); + return false; + } + status = smbXcli_conn_samba_suicide(cli->conn, 1); + if (!NT_STATUS_IS_OK(status)) { + printf("smbXcli_conn_samba_suicide failed: %s\n", + nt_errstr(status)); + return false; + } + + id.devid = sbuf.st_ex_rdev; + id.inode = sbuf.st_ex_ino; + id.extid = 0; + + poll(NULL, 0, 1000); + + *p_id = id; + return true; +} + +static bool corrupt_dummy(struct share_mode_data *d) +{ + return true; +} + +static bool invalidate_sharemode(struct share_mode_data *d) +{ + d->share_modes[0].op_type = + OPLOCK_EXCLUSIVE|OPLOCK_BATCH|OPLOCK_LEVEL_II; + d->modified = true; + return true; +} + +static bool duplicate_entry(struct share_mode_data *d, int i) +{ + struct share_mode_entry *tmp; + + if (i >= d->num_share_modes) { + return false; + } + + tmp = talloc_realloc(d, d->share_modes, struct share_mode_entry, + d->num_share_modes + 1); + if (tmp == NULL) { + return false; + } + d->share_modes = tmp; + d->num_share_modes += 1; + d->share_modes[d->num_share_modes-1] = d->share_modes[i]; + d->modified = true; + return true; +} + +static bool create_duplicate_batch(struct share_mode_data *d) +{ + if (d->num_share_modes != 1) { + return false; + } + d->share_modes[0].op_type = OPLOCK_BATCH; + if (!duplicate_entry(d, 0)) { + return false; + } + return true; -- Samba Shared Repository