bool (*write_data_cb)(void *private_data),
void *private_data)
{
- union smb_fileinfo finfo0, finfo1, finfoT;
+ union smb_fileinfo finfo0, finfo1, finfo2, finfo3, finfoT;
struct timeval before_write;
struct timeval after_write;
+ struct timeval before_last_write;
+ struct timeval after_last_write;
struct timeval start;
struct timeval end;
double sec = used_delay / normal_delay;
ok = write_data_cb(private_data);
after_write = timeval_current();
torture_assert(tctx, ok, "write_data_cb");
- (void)(&before_write == &after_write);
start = timeval_current();
end = timeval_add(&start, max_delay * 2, 0);
ok = get_basic_info_cb(private_data, &finfoT);
after_get = timeval_current();
torture_assert(tctx, ok, "get_basic_info_cb: finfoT");
- (void)(&before_get == &after_get);
if (finfoT.basic_info.out.write_time > finfo0.basic_info.out.write_time) {
double delayS = timeval_elapsed2(&after_write, &before_get);
ok = get_basic_info_cb(private_data, &finfoT);
torture_assert(tctx, ok, "get_basic_info_cb: finfoT");
COMPARE_ALL_TIMES_EQUAL(finfoT, finfo1);
-#if 0
+
+ torture_comment(tctx, "Do a write on the file handle\n");
+ before_write = timeval_current();
+ ok = write_data_cb(private_data);
+ after_write = timeval_current();
+ torture_assert(tctx, ok, "write_data_cb");
+
+ ZERO_STRUCT(finfo2);
+ before_last_write = before_write;
+ after_last_write = after_write;
start = timeval_current();
- end = timeval_add(&start, 7 * sec, 0);
+ end = timeval_add(&start, max_delay * 2, 0);
while (!timeval_expired(&end)) {
- union smb_fileinfo finfoT0;
- union smb_fileinfo finfoT1;
+ struct timeval before_get;
+ struct timeval after_get;
- ok = get_basic_info_cb(private_data, &finfoT0);
- torture_assert(tctx, ok, "get_basic_info_cb: finfoT0");
+ smb_msleep(0.01 * msec);
- torture_comment(tctx, "Do a write on the file handle\n");
- ok = write_data_cb(private_data);
- torture_assert_ntstatus_ok(tctx, status);
-
- ok = get_basic_info_cb(private_data, &finfoT1);
- torture_assert(tctx, ok, "get_basic_info_cb: finfoT1");
- COMPARE_WRITE_TIME_EQUAL(finfoT1, finfoT0);
-
- if (finfo.basic_info.out.write_time > finfo0.basic_info.out.write_time) {
- double diff = timeval_elapsed(&start);
- if (diff < (used_delay / (double)1000000)) {
- torture_result(tctx, TORTURE_FAIL, __location__": Server updated write_time after %.2f seconds "
- "(write time update delay == %.2f) (wrong!)\n",
- diff, used_delay / (double)1000000);
- ret = false;
- break;
- }
-
- torture_comment(tctx, "Server updated write_time after %.2f seconds "
- "(correct)\n",
- diff);
- changed = true;
+ torture_comment(tctx, "Wait for change\n");
+ before_get = timeval_current();
+ ok = get_basic_info_cb(private_data, &finfoT);
+ after_get = timeval_current();
+ torture_assert(tctx, ok, "get_basic_info_cb: finfoT");
+
+ if (finfoT.basic_info.out.write_time > finfo1.basic_info.out.write_time) {
+ double delayS = timeval_elapsed2(&after_write, &before_get);
+ double delayL = timeval_elapsed2(&before_write, &after_get);
+
+ torture_comment(tctx, "Server updated write_time after %.2f/%.2f seconds "
+ "(min delay == %.2f, max delay == %.2f)\n",
+ delayS, delayL, min_delay, max_delay);
+ torture_assert(tctx, (delayL >= min_delay),
+ "Server updated write_time to early!");
+ torture_assert(tctx, (delayS <= max_delay),
+ "Server didn't update write_time!");
+
+ COMPARE_TIMES_AFTER_WRITE(finfoT, finfo1);
+ before_write = before_last_write;
+ after_write = after_last_write;
+ finfo2 = finfoT;
break;
}
- ok = get_basic_info_cb(private_data, &finfo1);
- torture_assert_ntstatus_ok(tctx, status);
- COMPARE_WRITE_TIME_EQUAL(finfo1, finfoT);
- smb_msleep(0.5 * msec);
+ COMPARE_ALL_TIMES_EQUAL(finfoT, finfo1);
+
+ torture_comment(tctx, "Write while waiting\n");
+ before_last_write = timeval_current();
+ ok = write_data_cb(private_data);
+ after_last_write = timeval_current();
+ torture_assert(tctx, ok, "write_data_cb");
+ }
+
+ // We may get one additional change...
+
+ ok = get_basic_info_cb(private_data, &finfo3);
+ torture_assert(tctx, ok, "get_basic_info_cb: finfo3");
+ COMPARE_ALL_TIMES_EQUAL(finfo3, finfo2);
+
+ /*
+ * Make sure the time doesn't change during the next 5 seconds
+ */
+ start = timeval_current();
+ end = timeval_add(&start, max_delay * 1.25, 0);
+ while (!timeval_expired(&end)) {
+ smb_msleep(1 * msec);
+ torture_comment(tctx, "Check for no additional change\n");
+ ok = get_basic_info_cb(private_data, &finfoT);
+ torture_assert(tctx, ok, "get_basic_info_cb: finfoT");
+ COMPARE_ALL_TIMES_EQUAL(finfoT, finfo3);
}
- changed = false;
- GET_INFO_BOTH(finfo1, c2finfo1);
- COMPARE_WRITE_TIME_GREATER(finfo1, finfo0);
-#endif
+
+ ok = get_basic_info_cb(private_data, &finfoT);
+ torture_assert(tctx, ok, "get_basic_info_cb: finfoT");
+ COMPARE_ALL_TIMES_EQUAL(finfoT, finfo3);
+
done:
return ret;
}
GET_INFO_FILE(state->tree2, t2finfo);
GET_INFO_FILE(state->tree1, t1finfo);
+ if (t1finfo.basic_info.out.write_time != t2finfo.basic_info.out.write_time) {
+ /*
+ * There was a race, get it again on handle 2,
+ * but then they have to match.
+ */
+ GET_INFO_FILE(state->tree2, t2finfo);
+ }
COMPARE_ALL_TIMES_EQUAL(t1finfo, t2finfo);
finfo->basic_info.out = t1finfo.basic_info.out;
NTSTATUS status;
TALLOC_CTX *mem_ctx = talloc_new(tctx);
char fname[256];
- struct smb2_handle _h;
- struct smb2_handle *h = NULL;
+ struct smb2_handle _h1;
+ struct smb2_handle *h1 = NULL;
struct smb2_handle _h2;
struct smb2_handle *h2 = NULL;
- struct smb2_create cr;
+ struct smb2_create cr1;
struct smb2_create cr2;
- union smb_fileinfo finfoCR, finfo0, finfo1, finfo2, finfo3, finfo4, finfoT, finfoCL;
- union smb_fileinfo c2finfoCR, c2finfo0, c2finfo1, c2finfo2, c2finfo3, c2finfo4, c2finfoT, c2finfoCL;
- struct smb2_close cl;
+ union smb_fileinfo c1finfoCR, c1finfo0, c1finfo1, c1finfo2, c1finfoCL;
+ union smb_fileinfo c2finfoCR, c2finfo0, c2finfo1, c2finfo2, c2finfo3, c2finfoCL;
+ struct smb2_close cl1;
struct smb2_close cl2;
- struct smb2_write wr;
- ssize_t written;
- struct timeval start;
- struct timeval end;
//double used_delay = torture_setting_int(tctx, "writetimeupdatedelay", 2000000);
//double used_delay = torture_setting_int(tctx, "writetimeupdatedelay", 1000000);
double normal_delay = 1000000;
double sec = ((double)used_delay) / ((double)normal_delay);
int msec = 1000 * sec;
bool ret = true;
- bool changed = false;
bool ok;
/* Choose a random name in case the state is left a little funky. */
smb2_util_unlink(tree1, fname);
- smb2_oplock_create_share(&cr, fname,
+ smb2_oplock_create_share(&cr1, fname,
smb2_util_share_access(""),
smb2_util_oplock_level("b"));
- cr.in.durable_open = true;
+ cr1.in.durable_open = true;
- status = smb2_create(tree1, mem_ctx, &cr);
+ status = smb2_create(tree1, mem_ctx, &cr1);
CHECK_STATUS(status, NT_STATUS_OK);
- _h = cr.out.file.handle;
- h = &_h;
- CHECK_CREATED(&cr, CREATED, FILE_ATTRIBUTE_ARCHIVE);
- CHECK_VAL(cr.out.oplock_level, smb2_util_oplock_level("b"));
- CHECK_VAL(cr.out.durable_open, true);
- CHECK_VAL(cr.out.durable_open_v2, false);
- CHECK_VAL(cr.out.persistent_open, false);
- //CHECK_VAL(io.out.timeout, io.in.timeout);
-
- // struct {
- // NTTIME create_time;
- // NTTIME access_time;
- // NTTIME write_time;
- // NTTIME change_time;
- // uint32_t attrib;
- // } out;
- //} basic_info;
- ZERO_STRUCT(finfoCR);
- finfoCR.basic_info.out.create_time = cr.out.create_time;
- finfoCR.basic_info.out.access_time = cr.out.access_time;
- finfoCR.basic_info.out.write_time = cr.out.write_time;
- finfoCR.basic_info.out.change_time = cr.out.change_time;
- finfoCR.basic_info.out.attrib = cr.out.file_attr;
-
- ZERO_STRUCT(finfo0);
- finfo0.basic_info.level = RAW_FILEINFO_BASIC_INFORMATION;
- finfo0.basic_info.in.file.handle = *h;
- finfo1 = finfo0;
- finfo2 = finfo0;
- finfo3 = finfo0;
- finfo4 = finfo0;
- finfoT = finfo0;
+ _h1 = cr1.out.file.handle;
+ h1 = &_h1;
+ CHECK_CREATED(&cr1, CREATED, FILE_ATTRIBUTE_ARCHIVE);
+ CHECK_VAL(cr1.out.oplock_level, smb2_util_oplock_level("b"));
+ CHECK_VAL(cr1.out.durable_open, true);
+ CHECK_VAL(cr1.out.durable_open_v2, false);
+ CHECK_VAL(cr1.out.persistent_open, false);
- /* get the initial times */
- GET_INFO_FILE(tree1, finfo0);
- COMPARE_WRITE_TIME_EQUAL(finfoCR, finfo0);
-
- ///* static body buffer 56 (0x38) bytes */
- //uint8_t security_flags; /* SMB2_SECURITY_* */
- //uint8_t oplock_level; /* SMB2_OPLOCK_LEVEL_* */
- //uint32_t impersonation_level; /* SMB2_IMPERSONATION_* */
- //uint64_t create_flags;
- //uint64_t reserved;
- //uint32_t desired_access;
- //uint32_t file_attributes;
- //uint32_t share_access; /* NTCREATEX_SHARE_ACCESS_* */
- //uint32_t create_disposition; /* NTCREATEX_DISP_* */
- //uint32_t create_options; /* NTCREATEX_OPTIONS_* */
-
- ///* uint16_t fname_ofs */
- ///* uint16_t fname_size */
- ///* uint32_t blob_ofs; */
- ///* uint32_t blob_size; */
-
- ///* dynamic body */
- //const char *fname;
-
- ///* now some optional parameters - encoded as tagged blobs */
- //struct smb_ea_list eas;
- //uint64_t alloc_size;
- //struct security_descriptor *sec_desc;
- //bool durable_open;
- //struct smb2_handle *durable_handle;
-
- ///* data for durable handle v2 */
- //bool durable_open_v2;
- //struct GUID create_guid;
- //bool persistent_open;
- //uint32_t timeout;
- //struct smb2_handle *durable_handle_v2;
-
- //bool query_maximal_access;
- //NTTIME timewarp;
- //bool query_on_disk_id;
- //struct smb2_lease *lease_request;
- //struct smb2_lease *lease_request_v2;
-
- //struct GUID *app_instance_id;
-
- ///* and any additional blobs the caller wants */
- //struct smb2_create_blobs blobs;
- //} in;
- //struct {//
- //union smb_handle file;
-
- ///* static body buffer 88 (0x58) bytes */
- ///* uint16_t buffer_code; 0x59 = 0x58 + 1 */
- //uint8_t oplock_level;
- //uint8_t reserved;
- //uint32_t create_action;
- //NTTIME create_time;
- //NTTIME access_time;
- //NTTIME write_time;
- //NTTIME change_time;
- //uint64_t alloc_size;
- //uint64_t size;
- //uint32_t file_attr;
- //uint32_t reserved2;
- ///* struct smb2_handle handle;*/
- ///* uint32_t blob_ofs; */
- ///* uint32_t blob_size; */
-
- ///* optional return values matching tagged values in the call */
- //uint32_t maximal_access;
- //uint8_t on_disk_id[32];
- //struct smb2_lease lease_response;
- //struct smb2_lease lease_response_v2;
- //bool durable_open;
-
- ///* durable handle v2 */
- //bool durable_open_v2;
- //bool persistent_open;
- //uint32_t timeout;
-
- ///* tagged blobs in the reply */
- //struct smb2_create_blobs blobs;
- //} out;
- cr2 = cr;
- cr2.in.desired_access = SEC_FILE_READ_ATTRIBUTE;//FILE_READ_ATTRIBUTES;
+ cr2 = cr1;
+ cr2.in.desired_access = SEC_FILE_READ_ATTRIBUTE;
cr2.in.durable_open = false;
cr2.in.oplock_level = 0;
cr2.in.create_disposition = NTCREATEX_DISP_OPEN;
CHECK_VAL(cr2.out.durable_open_v2, false);
CHECK_VAL(cr2.out.persistent_open, false);
+ ZERO_STRUCT(c1finfoCR);
+ c1finfoCR.basic_info.out.create_time = cr1.out.create_time;
+ c1finfoCR.basic_info.out.access_time = cr1.out.access_time;
+ c1finfoCR.basic_info.out.write_time = cr1.out.write_time;
+ c1finfoCR.basic_info.out.change_time = cr1.out.change_time;
+ c1finfoCR.basic_info.out.attrib = cr1.out.file_attr;
+
ZERO_STRUCT(c2finfoCR);
c2finfoCR.basic_info.out.create_time = cr2.out.create_time;
c2finfoCR.basic_info.out.access_time = cr2.out.access_time;
c2finfoCR.basic_info.out.change_time = cr2.out.change_time;
c2finfoCR.basic_info.out.attrib = cr2.out.file_attr;
+ COMPARE_ALL_TIMES_EQUAL(c1finfoCR, c2finfoCR);
+
+ ZERO_STRUCT(c1finfo0);
+ c1finfo0.basic_info.level = RAW_FILEINFO_BASIC_INFORMATION;
+ c1finfo0.basic_info.in.file.handle = *h1;
+ c1finfo1 = c1finfo0;
+ c1finfo2 = c1finfo0;
+
ZERO_STRUCT(c2finfo0);
c2finfo0.basic_info.level = RAW_FILEINFO_BASIC_INFORMATION;
c2finfo0.basic_info.in.file.handle = *h2;
c2finfo1 = c2finfo0;
c2finfo2 = c2finfo0;
c2finfo3 = c2finfo0;
- c2finfo4 = c2finfo0;
- c2finfoT = c2finfo0;
- /* get the initial times */
- GET_INFO_FILE(tree2, c2finfo0);
- COMPARE_WRITE_TIME_EQUAL(c2finfoCR, c2finfo0);
+ GET_INFO_BOTH(c1finfo0, c2finfo0);
+ COMPARE_ALL_TIMES_EQUAL(c1finfo0, c1finfoCR);
- state.h1 = h;
+ state.h1 = h1;
state.h2 = h2;
ok = test_delay_writetime(tctx, used_delay, normal_delay,
- "some description",
+ "run1",
test_durable_open_delaywrite1_get_info,
test_durable_open_delaywrite1_write_data,
&state);
- torture_assert(tctx, ok, "test_delay_writetime");
-goto close_handles;
-goto done;
- /*
- * make sure the write time is updated 2 seconds later
- * calcuated from the first write
- * (but expect upto 5 seconds extra time for a busy server)
- */
- start = timeval_current();
- end = timeval_add(&start, 7 * sec, 0);
- while (!timeval_expired(&end)) {
- /* do a write */
- torture_comment(tctx, "Do a write on the file handle\n");
- GET_INFO_BOTH(finfoT, c2finfoT);
- ZERO_STRUCT(wr);
- wr.in.file.handle = *h;
- wr.in.offset = 0;
- wr.in.data = data_blob_const("x", 1);
- status = smb2_write(tree1, &wr);
- CHECK_STATUS(status, NT_STATUS_OK);
- written = wr.out.nwritten;
- if (written != 1) {
- torture_result(tctx, TORTURE_FAIL, __location__": written gave %d - should have been 1", (int)written);
- ret = false;
- goto done;
- }
- /* get the times after the write */
- GET_INFO_BOTH(finfo1, c2finfo1);
- if (changed) {
- COMPARE_WRITE_TIME_GREATER(finfo1, finfoT);
- }
-
- if (finfo1.basic_info.out.write_time > finfo0.basic_info.out.write_time) {
- double diff = timeval_elapsed(&start);
- if (diff < (used_delay / (double)1000000)) {
- torture_result(tctx, TORTURE_FAIL, __location__": Server updated write_time after %.2f seconds "
- "(write time update delay == %.2f) (wrong!)\n",
- diff, used_delay / (double)1000000);
- ret = false;
- break;
- }
-
- torture_comment(tctx, "Server updated write_time after %.2f seconds "
- "(correct)\n",
- diff);
- changed = true;
- break;
- }
- COMPARE_WRITE_TIME_EQUAL(finfo1, finfoT);
- smb_msleep(0.5 * msec);
- }
-
- changed = false;
- GET_INFO_BOTH(finfo1, c2finfo1);
- COMPARE_WRITE_TIME_GREATER(finfo1, finfo0);
-
- /* sure any further write doesn't update the write time */
- start = timeval_current();
- end = timeval_add(&start, 15 * sec, 0);
- while (!timeval_expired(&end)) {
- /* do a write */
- torture_comment(tctx, "Do a write on the file handle\n");
- ZERO_STRUCT(wr);
- wr.in.file.handle = *h;
- wr.in.offset = 0;
- wr.in.data = data_blob_const("x", 1);
- status = smb2_write(tree1, &wr);
- CHECK_STATUS(status, NT_STATUS_OK);
- written = wr.out.nwritten;
- if (written != 1) {
- torture_result(tctx, TORTURE_FAIL, __location__": written gave %d - should have been 1", (int)written);
- ret = false;
- goto done;
- }
- /* get the times after the write */
- GET_INFO_BOTH(finfo2, c2finfo2);
-
- if (finfo2.basic_info.out.write_time > finfo1.basic_info.out.write_time) {
- double diff = timeval_elapsed(&start);
- torture_result(tctx, TORTURE_FAIL, __location__": Server updated write_time after %.2f seconds "
- "(wrong!)\n",
- diff);
- ret = false;
- //break;
- }
- smb_msleep(0.1 * msec);
- //smb_msleep(1 * msec);
- }
-
- GET_INFO_BOTH(finfo2, c2finfo2);
- //COMPARE_WRITE_TIME_EQUAL(finfo2, finfo1);
- COMPARE_WRITE_TIME_GREATER(finfo2, finfo1);
- if (finfo2.basic_info.out.write_time == finfo1.basic_info.out.write_time) {
- torture_comment(tctx, "Server did not update write_time (correct)\n");
- }
+ torture_assert(tctx, ok, "test_delay_writetime(1)");
+ ok = test_delay_writetime(tctx, used_delay, normal_delay,
+ "run2",
+ test_durable_open_delaywrite1_get_info,
+ test_durable_open_delaywrite1_write_data,
+ &state);
+ torture_assert(tctx, ok, "test_delay_writetime(2)");
- /* sure any further write doesn't update the write time */
- start = timeval_current();
- end = timeval_add(&start, 15 * sec, 0);
- while (!timeval_expired(&end)) {
- /* do a write */
- torture_comment(tctx, "Check on both file handles\n");
- GET_INFO_BOTH(finfo3, c2finfo3);
-
- if (finfo3.basic_info.out.write_time > finfo2.basic_info.out.write_time) {
- double diff = timeval_elapsed(&start);
- torture_result(tctx, TORTURE_FAIL, __location__": Server updated write_time after %.2f seconds "
- "(wrong!)\n",
- diff);
- ret = false;
- break;
- }
- smb_msleep(0.1 * msec);
- //smb_msleep(1 * msec);
- }
-close_handles:
- GET_INFO_BOTH(finfo3, c2finfo3);
- //COMPARE_WRITE_TIME_EQUAL(finfo3, finfo2);
+ GET_INFO_BOTH(c1finfo1, c2finfo1);
+ COMPARE_TIMES_AFTER_WRITE(c1finfo1, c1finfo0);
/* sleep */
torture_comment(tctx, "Sleep ...\n");
smb_msleep(5 * msec);
torture_comment(tctx, "... continue\n");
- GET_INFO_BOTH(finfo4, c2finfo4);
- COMPARE_WRITE_TIME_EQUAL(finfo4, finfo3);
+ GET_INFO_BOTH(c1finfo2, c2finfo2);
+ COMPARE_ALL_TIMES_EQUAL(c1finfo2, c1finfo1);
/*
* the close updates the write time to the time of the close
*/
torture_comment(tctx, "Close the file handle\n");
- ZERO_STRUCT(cl);
- cl.in.file.handle = *h;
- cl.in.flags = SMB2_CLOSE_FLAGS_FULL_INFORMATION;
- status = smb2_close(tree1, &cl);
+ ZERO_STRUCT(cl1);
+ cl1.in.file.handle = *h1;
+ cl1.in.flags = SMB2_CLOSE_FLAGS_FULL_INFORMATION;
+ status = smb2_close(tree1, &cl1);
CHECK_STATUS(status, NT_STATUS_OK);
- h = NULL;
- ZERO_STRUCT(finfoCL);
- finfoCL.basic_info.out.create_time = cl.out.create_time;
- finfoCL.basic_info.out.access_time = cl.out.access_time;
- finfoCL.basic_info.out.write_time = cl.out.write_time;
- finfoCL.basic_info.out.change_time = cl.out.change_time;
- finfoCL.basic_info.out.attrib = cl.out.file_attr;
- //COMPARE_WRITE_TIME_GREATER(finfoCL, finfo3);
- //COMPARE_TIMES_AFTER_CLOSE(finfoCL, finfo3);
+ h1 = NULL;
+ ZERO_STRUCT(c1finfoCL);
+ c1finfoCL.basic_info.out.create_time = cl1.out.create_time;
+ c1finfoCL.basic_info.out.access_time = cl1.out.access_time;
+ c1finfoCL.basic_info.out.write_time = cl1.out.write_time;
+ c1finfoCL.basic_info.out.change_time = cl1.out.change_time;
+ c1finfoCL.basic_info.out.attrib = cl1.out.file_attr;
+ COMPARE_ALL_TIMES_EQUAL(c1finfoCL, c1finfo2);
GET_INFO_FILE(tree2, c2finfo3);
- COMPARE_ALL_TIMES_EQUAL(c2finfo3, finfoCL);
+ COMPARE_ALL_TIMES_EQUAL(c2finfo3, c1finfoCL);
ZERO_STRUCT(cl2);
cl2.in.file.handle = *h2;
c2finfoCL.basic_info.out.write_time = cl2.out.write_time;
c2finfoCL.basic_info.out.change_time = cl2.out.change_time;
c2finfoCL.basic_info.out.attrib = cl2.out.file_attr;
- COMPARE_ALL_TIMES_EQUAL(c2finfoCL, finfoCL);
- //struct {
- // /* static body buffer 60 (0x3C) bytes */
- // /* uint16_t buffer_code; 0x3C */
- // uint16_t flags;
- // uint32_t _pad;
- // NTTIME create_time;
- // NTTIME access_time;
- // NTTIME write_time;
- // NTTIME change_time;
- // uint64_t alloc_size;
- // uint64_t size;
- // uint32_t file_attr;
- //} out;
-
- //if (pinfo4.basic_info.out.write_time > pinfo3.basic_info.out.write_time) {
- // torture_comment(tctx, "Server updated the write_time on close (correct)\n");
- //}
- ///* try a durable reconnect while the file is still open */
- //ZERO_STRUCT(io);
- //io.in.fname = "";
- //io.in.durable_handle_v2 = h;
- //io.in.create_guid = create_guid;
- //status = smb2_create(tree1, mem_ctx, &io);
- //CHECK_STATUS(status, NT_STATUS_OBJECT_NAME_NOT_FOUND);
+ COMPARE_ALL_TIMES_EQUAL(c2finfoCL, c1finfoCL);
done:
- if (h != NULL) {
- smb2_util_close(tree1, *h);
+ if (h1 != NULL) {
+ smb2_util_close(tree1, *h1);
+ }
+ if (h2 != NULL) {
+ smb2_util_close(tree2, *h2);
}
smb2_util_unlink(tree1, fname);