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:
parent
5cd57eb58b
commit
c50486c09a
@ -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");
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user