1
0
mirror of https://github.com/samba-team/samba.git synced 2025-01-22 22:04:08 +03:00

s3/4: libsmbclient test. Test using smbc_telldir/smbc_lseekdir with smbc_readdir/smbc_readdirplus/smbc_getdents.

Ensure that for file access you can mix any of these
three access methods for directory entries and the
returned names/structs stay in sync across telldir/seekdir
changes.

BUG: https://bugzilla.samba.org/show_bug.cgi?id=14094

Back-ported from master 3355601fe8541994cc41f5ed800aab9b6a2294f4.

Signed-off-by: Jeremy Allison <jra@samba.org>
Reviewed-by: Ralph Böhme <slow@samba.org>

Autobuild-User(v4-9-test): Karolin Seeger <kseeger@samba.org>
Autobuild-Date(v4-9-test): Thu Sep 19 10:40:56 UTC 2019 on sn-devel-144
This commit is contained in:
Jeremy Allison 2019-08-26 11:22:35 -07:00 committed by Karolin Seeger
parent 5cd57eb58b
commit c50486c09a

View File

@ -18,6 +18,7 @@
*/
#include "includes.h"
#include "system/dir.h"
#include "torture/smbtorture.h"
#include "auth/credentials/credentials.h"
#include "lib/cmdline/popt_common.h"
@ -316,6 +317,343 @@ static bool torture_libsmbclient_readdirplus(struct torture_context *tctx)
return true;
}
static bool torture_libsmbclient_readdirplus_seek(struct torture_context *tctx)
{
SMBCCTX *ctx;
int ret = -1;
int dhandle = -1;
int fhandle = -1;
const char *dname = NULL;
const char *full_filename[100] = {0};
const char *filename[100] = {0};
const struct libsmb_file_info *direntries[102] = {0};
unsigned int i = 0;
const char *smburl = torture_setting_string(tctx, "smburl", NULL);
bool success = false;
off_t telldir_50 = (off_t)-1;
off_t telldir_20 = (off_t)-1;
size_t getdentries_size = 0;
struct smbc_dirent *getdentries = NULL;
struct smbc_dirent *dirent_20 = NULL;
const struct libsmb_file_info *direntries_20 = NULL;
if (smburl == NULL) {
torture_fail(tctx,
"option --option=torture:smburl="
"smb://user:password@server/share missing\n");
}
DEBUG(0,("torture_libsmbclient_readdirplus_seek start\n"));
torture_assert(tctx, torture_libsmbclient_init_context(tctx, &ctx), "");
smbc_set_context(ctx);
dname = talloc_asprintf(tctx,
"%s/rd_seek",
smburl);
if (dname == NULL) {
torture_fail_goto(tctx,
done,
"talloc fail\n");
}
/* Ensure the files don't exist. */
for (i = 0; i < 100; i++) {
filename[i] = talloc_asprintf(tctx,
"test_readdirplus_%u.txt",
i);
if (filename[i] == NULL) {
torture_fail_goto(tctx,
done,
"talloc fail\n");
}
full_filename[i] = talloc_asprintf(tctx,
"%s/%s",
dname,
filename[i]);
if (full_filename[i] == NULL) {
torture_fail_goto(tctx,
done,
"talloc fail\n");
}
(void)smbc_unlink(full_filename[i]);
}
/* Ensure the directory doesn't exist. */
(void)smbc_rmdir(dname);
/* Create containing directory. */
ret = smbc_mkdir(dname, 0777);
if (ret != 0) {
torture_fail_goto(tctx,
done,
talloc_asprintf(tctx,
"failed to create directory '%s': %s",
dname,
strerror(errno)));
}
DEBUG(0,("torture_libsmbclient_readdirplus_seek create\n"));
/* Create them. */
for (i = 0; i < 100; i++) {
fhandle = smbc_creat(full_filename[i], 0666);
if (fhandle < 0) {
torture_fail_goto(tctx,
done,
talloc_asprintf(tctx,
"failed to create file '%s': %s",
full_filename[i],
strerror(errno)));
}
ret = smbc_close(fhandle);
torture_assert_int_equal_goto(tctx,
ret,
0,
success,
done,
talloc_asprintf(tctx,
"failed to close handle for '%s'",
full_filename[i]));
}
DEBUG(0,("torture_libsmbclient_readdirplus_seek enum\n"));
/* Now enumerate the directory. */
dhandle = smbc_opendir(dname);
if (dhandle < 0) {
torture_fail_goto(tctx,
done,
talloc_asprintf(tctx,
"failed to obtain "
"directory handle for '%s' : %s",
dname,
strerror(errno)));
}
/* Read all the files. 100 we created plus . and .. */
for (i = 0; i < 102; i++) {
bool found = false;
unsigned int j;
direntries[i] = smbc_readdirplus(dhandle);
if (direntries[i] == NULL) {
break;
}
/* Store at offset 50. */
if (i == 50) {
telldir_50 = smbc_telldir(dhandle);
if (telldir_50 == (off_t)-1) {
torture_fail_goto(tctx,
done,
talloc_asprintf(tctx,
"telldir failed file %s\n",
direntries[i]->name));
}
}
if (ISDOT(direntries[i]->name)) {
continue;
}
if (ISDOTDOT(direntries[i]->name)) {
continue;
}
/* Ensure all our files exist. */
for (j = 0; j < 100; j++) {
if (strcmp(direntries[i]->name,
filename[j]) == 0) {
found = true;
}
}
if (!found) {
torture_fail_goto(tctx,
done,
talloc_asprintf(tctx,
"failed to find file %s\n",
direntries[i]->name));
}
}
/*
* We're seeking on in-memory lists here, so
* whilst the handle is open we really should
* get the same files back in the same order.
*/
ret = smbc_lseekdir(dhandle, telldir_50);
torture_assert_int_equal_goto(tctx,
ret,
0,
success,
done,
talloc_asprintf(tctx,
"failed to seek (50) directory handle for '%s'",
dname));
DEBUG(0,("torture_libsmbclient_readdirplus_seek seek\n"));
for (i = 51; i < 102; i++) {
const struct libsmb_file_info *entry =
smbc_readdirplus(dhandle);
if (entry != direntries[i]) {
torture_fail_goto(tctx,
done,
talloc_asprintf(tctx,
"after seek - failed to find "
"file %s - got %s\n",
direntries[i]->name,
entry->name));
}
}
/* Seek back to the start. */
ret = smbc_lseekdir(dhandle, 0);
torture_assert_int_equal_goto(tctx,
ret,
0,
success,
done,
talloc_asprintf(tctx,
"failed to seek directory handle to start for '%s'",
dname));
/*
* Mix getdents/readdir/readdirplus with lseek to ensure
* we get the same result.
*/
/* Allocate the space for 20 entries.
* Tricky as we need to allocate 20 struct smbc_dirent's + space
* for the name lengths.
*/
getdentries_size = 20 * (sizeof(struct smbc_dirent) +
strlen("test_readdirplus_1000.txt") + 1);
getdentries = (struct smbc_dirent *)talloc_array_size(tctx,
getdentries_size,
1);
ret = smbc_getdents(dhandle, getdentries, getdentries_size);
torture_assert_goto(tctx,
(ret != -1),
success,
done,
talloc_asprintf(tctx,
"smbd_getdents(1) for '%s' failed\n",
dname));
telldir_20 = smbc_telldir(dhandle);
if (telldir_20 == (off_t)-1) {
torture_fail_goto(tctx,
done,
talloc_asprintf(tctx,
"telldir (20) failed\n"));
}
/* Read another 20. */
ret = smbc_getdents(dhandle, getdentries, getdentries_size);
torture_assert_goto(tctx,
(ret != -1),
success,
done,
talloc_asprintf(tctx,
"smbd_getdents(2) for '%s' failed\n",
dname));
/* Seek back to 20. */
ret = smbc_lseekdir(dhandle, telldir_20);
torture_assert_int_equal_goto(tctx,
ret,
0,
success,
done,
talloc_asprintf(tctx,
"failed to seek (20) directory handle for '%s'",
dname));
/* Read with readdir. */
dirent_20 = smbc_readdir(dhandle);
if (dirent_20 == NULL) {
torture_fail_goto(tctx,
done,
talloc_asprintf(tctx,
"smbc_readdir (20) failed\n"));
}
/* Ensure the getdents and readdir names are the same. */
ret = strcmp(dirent_20->name, getdentries[0].name);
if (ret != 0) {
torture_fail_goto(tctx,
done,
talloc_asprintf(tctx,
"after seek (20) readdir name missmatch "
"file %s - got %s\n",
dirent_20->name,
getdentries[0].name));
}
/* Seek back to 20. */
ret = smbc_lseekdir(dhandle, telldir_20);
torture_assert_int_equal_goto(tctx,
ret,
0,
success,
done,
talloc_asprintf(tctx,
"failed to seek (20) directory handle for '%s'",
dname));
/* Read with readdirplus. */
direntries_20 = smbc_readdirplus(dhandle);
if (direntries_20 == NULL) {
torture_fail_goto(tctx,
done,
talloc_asprintf(tctx,
"smbc_readdirplus (20) failed\n"));
}
/* Ensure the readdirplus and readdir names are the same. */
ret = strcmp(dirent_20->name, direntries_20->name);
if (ret != 0) {
torture_fail_goto(tctx,
done,
talloc_asprintf(tctx,
"after seek (20) readdirplus name missmatch "
"file %s - got %s\n",
dirent_20->name,
direntries_20->name));
}
ret = smbc_closedir(dhandle);
torture_assert_int_equal(tctx,
ret,
0,
talloc_asprintf(tctx,
"failed to close directory handle for '%s'",
dname));
dhandle = -1;
success = true;
done:
/* Clean up. */
if (dhandle != -1) {
smbc_closedir(dhandle);
}
for (i = 0; i < 100; i++) {
if (full_filename[i] != NULL) {
smbc_unlink(full_filename[i]);
}
}
if (dname != NULL) {
smbc_rmdir(dname);
}
smbc_free_context(ctx, 1);
return success;
}
bool torture_libsmbclient_configuration(struct torture_context *tctx)
{
SMBCCTX *ctx;
@ -519,6 +857,8 @@ NTSTATUS torture_libsmbclient_init(TALLOC_CTX *ctx)
torture_suite_add_simple_test(suite, "opendir", torture_libsmbclient_opendir);
torture_suite_add_simple_test(suite, "readdirplus",
torture_libsmbclient_readdirplus);
torture_suite_add_simple_test(suite, "readdirplus_seek",
torture_libsmbclient_readdirplus_seek);
suite->description = talloc_strdup(suite, "libsmbclient interface tests");