mirror of
https://github.com/samba-team/samba.git
synced 2024-12-31 17:18:04 +03:00
remove some unused files
This commit is contained in:
parent
564e505e92
commit
a6f43de7f8
@ -1,514 +0,0 @@
|
||||
/*
|
||||
Unix SMB/CIFS implementation.
|
||||
SAM module functions
|
||||
|
||||
Copyright (C) Jelmer Vernooij 2002
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
|
||||
#include "includes.h"
|
||||
#include "samtest.h"
|
||||
|
||||
static void print_account(SAM_ACCOUNT_HANDLE *a)
|
||||
{
|
||||
/* FIXME */
|
||||
}
|
||||
|
||||
static NTSTATUS cmd_context(struct samtest_state *st, TALLOC_CTX *mem_ctx, int argc, char **argv)
|
||||
{
|
||||
NTSTATUS status;
|
||||
char **plugins;
|
||||
int i;
|
||||
|
||||
plugins = malloc(argc * sizeof(char *));
|
||||
|
||||
for(i = 1; i < argc; i++)
|
||||
plugins[i-1] = argv[i];
|
||||
|
||||
plugins[argc-1] = NULL;
|
||||
|
||||
if(!NT_STATUS_IS_OK(status = make_sam_context_list(&st->context, plugins))) {
|
||||
printf("make_sam_context_list failed: %s\n", nt_errstr(status));
|
||||
SAFE_FREE(plugins);
|
||||
return status;
|
||||
}
|
||||
|
||||
SAFE_FREE(plugins);
|
||||
|
||||
return NT_STATUS_OK;
|
||||
}
|
||||
|
||||
static NTSTATUS cmd_load_module(struct samtest_state *st, TALLOC_CTX *mem_ctx, int argc, char **argv)
|
||||
{
|
||||
char *plugin_arg[2];
|
||||
NTSTATUS status;
|
||||
if (argc != 2 && argc != 3) {
|
||||
printf("Usage: load <module path> [domain-name]\n");
|
||||
return NT_STATUS_OK;
|
||||
}
|
||||
|
||||
if (argc == 3)
|
||||
asprintf(&plugin_arg[0], "plugin:%s|%s", argv[1], argv[2]);
|
||||
else
|
||||
asprintf(&plugin_arg[0], "plugin:%s", argv[1]);
|
||||
|
||||
plugin_arg[1] = NULL;
|
||||
|
||||
if(!NT_STATUS_IS_OK(status = make_sam_context_list(&st->context, plugin_arg))) {
|
||||
free(plugin_arg[0]);
|
||||
return status;
|
||||
}
|
||||
|
||||
free(plugin_arg[0]);
|
||||
|
||||
printf("load: ok\n");
|
||||
return NT_STATUS_OK;
|
||||
}
|
||||
|
||||
static NTSTATUS cmd_get_sec_desc(struct samtest_state *st, TALLOC_CTX *mem_ctx, int argc, char **argv)
|
||||
{
|
||||
return NT_STATUS_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
static NTSTATUS cmd_set_sec_desc(struct samtest_state *st, TALLOC_CTX *mem_ctx, int argc, char **argv)
|
||||
{
|
||||
return NT_STATUS_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
static NTSTATUS cmd_lookup_sid(struct samtest_state *st, TALLOC_CTX *mem_ctx, int argc, char **argv)
|
||||
{
|
||||
char *name;
|
||||
uint32 type;
|
||||
NTSTATUS status;
|
||||
DOM_SID sid;
|
||||
if (argc != 2) {
|
||||
printf("Usage: lookup_sid <sid>\n");
|
||||
return NT_STATUS_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
if (!string_to_sid(&sid, argv[1])){
|
||||
printf("Unparseable SID specified!\n");
|
||||
return NT_STATUS_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
if (!NT_STATUS_IS_OK(status = sam_lookup_sid(st->context, st->token, mem_ctx, &sid, &name, &type))) {
|
||||
printf("sam_lookup_sid failed!\n");
|
||||
return status;
|
||||
}
|
||||
|
||||
printf("Name: %s\n", name);
|
||||
printf("Type: %d\n", type); /* FIXME: What kind of an integer is type ? */
|
||||
|
||||
return NT_STATUS_OK;
|
||||
}
|
||||
|
||||
static NTSTATUS cmd_lookup_name(struct samtest_state *st, TALLOC_CTX *mem_ctx, int argc, char **argv)
|
||||
{
|
||||
DOM_SID sid;
|
||||
uint32 type;
|
||||
NTSTATUS status;
|
||||
if (argc != 3) {
|
||||
printf("Usage: lookup_name <domain> <name>\n");
|
||||
return NT_STATUS_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
if (!NT_STATUS_IS_OK(status = sam_lookup_name(st->context, st->token, argv[1], argv[2], &sid, &type))) {
|
||||
printf("sam_lookup_name failed!\n");
|
||||
return status;
|
||||
}
|
||||
|
||||
printf("SID: %s\n", sid_string_static(&sid));
|
||||
printf("Type: %d\n", type);
|
||||
|
||||
return NT_STATUS_OK;
|
||||
}
|
||||
|
||||
static NTSTATUS cmd_lookup_account(struct samtest_state *st, TALLOC_CTX *mem_ctx, int argc, char **argv)
|
||||
{
|
||||
return NT_STATUS_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
static NTSTATUS cmd_lookup_group(struct samtest_state *st, TALLOC_CTX *mem_ctx, int argc, char **argv)
|
||||
{
|
||||
return NT_STATUS_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
static NTSTATUS cmd_lookup_domain(struct samtest_state *st, TALLOC_CTX *mem_ctx, int argc, char **argv)
|
||||
{
|
||||
DOM_SID *sid;
|
||||
NTSTATUS status;
|
||||
if (argc != 2) {
|
||||
printf("Usage: lookup_domain <domain>\n");
|
||||
return NT_STATUS_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
if (!NT_STATUS_IS_OK(status = sam_lookup_domain(st->context, st->token, argv[1], &sid))) {
|
||||
printf("sam_lookup_name failed!\n");
|
||||
return status;
|
||||
}
|
||||
|
||||
printf("SID: %s\n", sid_string_static(sid));
|
||||
|
||||
return NT_STATUS_OK;
|
||||
}
|
||||
|
||||
static NTSTATUS cmd_enum_domains(struct samtest_state *st, TALLOC_CTX *mem_ctx, int argc, char **argv)
|
||||
{
|
||||
int32 domain_count, i;
|
||||
DOM_SID *domain_sids;
|
||||
char **domain_names;
|
||||
NTSTATUS status;
|
||||
|
||||
if (!NT_STATUS_IS_OK(status = sam_enum_domains(st->context, st->token, &domain_count, &domain_sids, &domain_names))) {
|
||||
printf("sam_enum_domains failed!\n");
|
||||
return status;
|
||||
}
|
||||
|
||||
if (domain_count == 0) {
|
||||
printf("No domains found!\n");
|
||||
return NT_STATUS_OK;
|
||||
}
|
||||
|
||||
for (i = 0; i < domain_count; i++) {
|
||||
printf("%s %s\n", domain_names[i], sid_string_static(&domain_sids[i]));
|
||||
}
|
||||
|
||||
SAFE_FREE(domain_sids);
|
||||
SAFE_FREE(domain_names);
|
||||
|
||||
return NT_STATUS_OK;
|
||||
}
|
||||
|
||||
static NTSTATUS cmd_update_domain(struct samtest_state *st, TALLOC_CTX *mem_ctx, int argc, char **argv)
|
||||
{
|
||||
return NT_STATUS_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
static NTSTATUS cmd_show_domain(struct samtest_state *st, TALLOC_CTX *mem_ctx, int argc, char **argv)
|
||||
{
|
||||
NTSTATUS status;
|
||||
DOM_SID sid;
|
||||
SAM_DOMAIN_HANDLE *domain;
|
||||
uint32 tmp_uint32;
|
||||
uint16 tmp_uint16;
|
||||
NTTIME tmp_nttime;
|
||||
BOOL tmp_bool;
|
||||
const char *tmp_string;
|
||||
|
||||
if (argc != 2) {
|
||||
printf("Usage: show_domain <sid>\n");
|
||||
return status;
|
||||
}
|
||||
|
||||
if (!string_to_sid(&sid, argv[1])){
|
||||
printf("Unparseable SID specified!\n");
|
||||
return NT_STATUS_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
if (!NT_STATUS_IS_OK(status = sam_get_domain_by_sid(st->context, st->token, GENERIC_RIGHTS_DOMAIN_ALL_ACCESS, &sid, &domain))) {
|
||||
printf("sam_get_domain_by_sid failed\n");
|
||||
return status;
|
||||
}
|
||||
|
||||
if (!NT_STATUS_IS_OK(status = sam_get_domain_num_accounts(domain, &tmp_uint32))) {
|
||||
printf("sam_get_domain_num_accounts failed: %s\n", nt_errstr(status));
|
||||
} else {
|
||||
printf("Number of accounts: %d\n", tmp_uint32);
|
||||
}
|
||||
|
||||
if (!NT_STATUS_IS_OK(status = sam_get_domain_num_groups(domain, &tmp_uint32))) {
|
||||
printf("sam_get_domain_num_groups failed: %s\n", nt_errstr(status));
|
||||
} else {
|
||||
printf("Number of groups: %u\n", tmp_uint32);
|
||||
}
|
||||
|
||||
if (!NT_STATUS_IS_OK(status = sam_get_domain_num_aliases(domain, &tmp_uint32))) {
|
||||
printf("sam_get_domain_num_aliases failed: %s\n", nt_errstr(status));
|
||||
} else {
|
||||
printf("Number of aliases: %u\n", tmp_uint32);
|
||||
}
|
||||
|
||||
if (!NT_STATUS_IS_OK(status = sam_get_domain_name(domain, &tmp_string))) {
|
||||
printf("sam_get_domain_name failed: %s\n", nt_errstr(status));
|
||||
} else {
|
||||
printf("Domain Name: %s\n", tmp_string);
|
||||
}
|
||||
|
||||
if (!NT_STATUS_IS_OK(status = sam_get_domain_lockout_count(domain, &tmp_uint16))) {
|
||||
printf("sam_get_domain_lockout_count failed: %s\n", nt_errstr(status));
|
||||
} else {
|
||||
printf("Lockout Count: %u\n", tmp_uint16);
|
||||
}
|
||||
|
||||
if (!NT_STATUS_IS_OK(status = sam_get_domain_force_logoff(domain, &tmp_bool))) {
|
||||
printf("sam_get_domain_force_logoff failed: %s\n", nt_errstr(status));
|
||||
} else {
|
||||
printf("Force Logoff: %s\n", (tmp_bool?"Yes":"No"));
|
||||
}
|
||||
|
||||
if (!NT_STATUS_IS_OK(status = sam_get_domain_lockout_duration(domain, &tmp_nttime))) {
|
||||
printf("sam_get_domain_lockout_duration failed: %s\n", nt_errstr(status));
|
||||
} else {
|
||||
printf("Lockout duration: %u\n", tmp_nttime.low);
|
||||
}
|
||||
|
||||
if (!NT_STATUS_IS_OK(status = sam_get_domain_login_pwdchange(domain, &tmp_bool))) {
|
||||
printf("sam_get_domain_login_pwdchange failed: %s\n", nt_errstr(status));
|
||||
} else {
|
||||
printf("Password changing allowed: %s\n", (tmp_bool?"Yes":"No"));
|
||||
}
|
||||
|
||||
if (!NT_STATUS_IS_OK(status = sam_get_domain_max_pwdage(domain, &tmp_nttime))) {
|
||||
printf("sam_get_domain_max_pwdage failed: %s\n", nt_errstr(status));
|
||||
} else {
|
||||
printf("Maximum password age: %u\n", tmp_nttime.low);
|
||||
}
|
||||
|
||||
if (!NT_STATUS_IS_OK(status = sam_get_domain_min_pwdage(domain, &tmp_nttime))) {
|
||||
printf("sam_get_domain_min_pwdage failed: %s\n", nt_errstr(status));
|
||||
} else {
|
||||
printf("Minimal password age: %u\n", tmp_nttime.low);
|
||||
}
|
||||
|
||||
if (!NT_STATUS_IS_OK(status = sam_get_domain_min_pwdlength(domain, &tmp_uint16))) {
|
||||
printf("sam_get_domain_min_pwdlength: %s\n", nt_errstr(status));
|
||||
} else {
|
||||
printf("Minimal Password Length: %u\n", tmp_uint16);
|
||||
}
|
||||
|
||||
if (!NT_STATUS_IS_OK(status = sam_get_domain_pwd_history(domain, &tmp_uint16))) {
|
||||
printf("sam_get_domain_pwd_history failed: %s\n", nt_errstr(status));
|
||||
} else {
|
||||
printf("Password history: %u\n", tmp_uint16);
|
||||
}
|
||||
|
||||
if (!NT_STATUS_IS_OK(status = sam_get_domain_reset_count(domain, &tmp_nttime))) {
|
||||
printf("sam_get_domain_reset_count failed: %s\n", nt_errstr(status));
|
||||
} else {
|
||||
printf("Reset count: %u\n", tmp_nttime.low);
|
||||
}
|
||||
|
||||
if (!NT_STATUS_IS_OK(status = sam_get_domain_server(domain, &tmp_string))) {
|
||||
printf("sam_get_domain_server failed: %s\n", nt_errstr(status));
|
||||
} else {
|
||||
printf("Server: %s\n", tmp_string);
|
||||
}
|
||||
|
||||
return NT_STATUS_OK;
|
||||
}
|
||||
|
||||
static NTSTATUS cmd_create_account(struct samtest_state *st, TALLOC_CTX *mem_ctx, int argc, char **argv)
|
||||
{
|
||||
return NT_STATUS_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
static NTSTATUS cmd_update_account(struct samtest_state *st, TALLOC_CTX *mem_ctx, int argc, char **argv)
|
||||
{
|
||||
return NT_STATUS_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
static NTSTATUS cmd_delete_account(struct samtest_state *st, TALLOC_CTX *mem_ctx, int argc, char **argv)
|
||||
{
|
||||
return NT_STATUS_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
static NTSTATUS cmd_enum_accounts(struct samtest_state *st, TALLOC_CTX *mem_ctx, int argc, char **argv)
|
||||
{
|
||||
NTSTATUS status;
|
||||
DOM_SID sid;
|
||||
int32 account_count, i;
|
||||
SAM_ACCOUNT_ENUM *accounts;
|
||||
|
||||
if (argc != 2) {
|
||||
printf("Usage: enum_accounts <domain-sid>\n");
|
||||
return NT_STATUS_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
if (!string_to_sid(&sid, argv[1])){
|
||||
printf("Unparseable SID specified!\n");
|
||||
return NT_STATUS_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
if (!NT_STATUS_IS_OK(status = sam_enum_accounts(st->context, st->token, &sid, 0, &account_count, &accounts))) {
|
||||
printf("sam_enum_accounts failed: %s\n", nt_errstr(status));
|
||||
return status;
|
||||
}
|
||||
|
||||
if (account_count == 0) {
|
||||
printf("No accounts found!\n");
|
||||
return NT_STATUS_OK;
|
||||
}
|
||||
|
||||
for (i = 0; i < account_count; i++)
|
||||
printf("SID: %s\nName: %s\nFullname: %s\nDescription: %s\nACB_BITS: %08X\n\n",
|
||||
sid_string_static(&accounts[i].sid), accounts[i].account_name,
|
||||
accounts[i].full_name, accounts[i].account_desc,
|
||||
accounts[i].acct_ctrl);
|
||||
|
||||
SAFE_FREE(accounts);
|
||||
|
||||
return NT_STATUS_OK;
|
||||
}
|
||||
|
||||
static NTSTATUS cmd_lookup_account_sid(struct samtest_state *st, TALLOC_CTX *mem_ctx, int argc, char **argv)
|
||||
{
|
||||
NTSTATUS status;
|
||||
DOM_SID sid;
|
||||
SAM_ACCOUNT_HANDLE *account;
|
||||
|
||||
if (argc != 2) {
|
||||
printf("Usage: lookup_account_sid <account-sid>\n");
|
||||
return NT_STATUS_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
if (!string_to_sid(&sid, argv[1])){
|
||||
printf("Unparseable SID specified!\n");
|
||||
return NT_STATUS_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
if (!NT_STATUS_IS_OK(status = sam_get_account_by_sid(st->context, st->token, GENERIC_RIGHTS_USER_ALL_ACCESS, &sid, &account))) {
|
||||
printf("context_sam_get_account_by_sid failed: %s\n", nt_errstr(status));
|
||||
return status;
|
||||
}
|
||||
|
||||
print_account(account);
|
||||
|
||||
return NT_STATUS_OK;
|
||||
}
|
||||
|
||||
static NTSTATUS cmd_lookup_account_name(struct samtest_state *st, TALLOC_CTX *mem_ctx, int argc, char **argv)
|
||||
{
|
||||
NTSTATUS status;
|
||||
SAM_ACCOUNT_HANDLE *account;
|
||||
|
||||
if (argc != 3) {
|
||||
printf("Usage: lookup_account_name <domain-name> <account-name>\n");
|
||||
return NT_STATUS_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
|
||||
if (!NT_STATUS_IS_OK(status = sam_get_account_by_name(st->context, st->token, GENERIC_RIGHTS_USER_ALL_ACCESS, argv[1], argv[2], &account))) {
|
||||
printf("context_sam_get_account_by_sid failed: %s\n", nt_errstr(status));
|
||||
return status;
|
||||
}
|
||||
|
||||
print_account(account);
|
||||
|
||||
return NT_STATUS_OK;
|
||||
}
|
||||
|
||||
static NTSTATUS cmd_create_group(struct samtest_state *st, TALLOC_CTX *mem_ctx, int argc, char **argv)
|
||||
{
|
||||
return NT_STATUS_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
static NTSTATUS cmd_update_group(struct samtest_state *st, TALLOC_CTX *mem_ctx, int argc, char **argv)
|
||||
{
|
||||
return NT_STATUS_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
static NTSTATUS cmd_delete_group(struct samtest_state *st, TALLOC_CTX *mem_ctx, int argc, char **argv)
|
||||
{
|
||||
return NT_STATUS_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
static NTSTATUS cmd_enum_groups(struct samtest_state *st, TALLOC_CTX *mem_ctx, int argc, char **argv)
|
||||
{
|
||||
return NT_STATUS_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
static NTSTATUS cmd_lookup_group_sid(struct samtest_state *st, TALLOC_CTX *mem_ctx, int argc, char **argv)
|
||||
{
|
||||
return NT_STATUS_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
static NTSTATUS cmd_lookup_group_name(struct samtest_state *st, TALLOC_CTX *mem_ctx, int argc, char **argv)
|
||||
{
|
||||
return NT_STATUS_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
static NTSTATUS cmd_group_add_member(struct samtest_state *st, TALLOC_CTX *mem_ctx, int argc, char **argv)
|
||||
{
|
||||
return NT_STATUS_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
static NTSTATUS cmd_group_del_member(struct samtest_state *st, TALLOC_CTX *mem_ctx, int argc, char **argv)
|
||||
{
|
||||
return NT_STATUS_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
|
||||
static NTSTATUS cmd_group_enum(struct samtest_state *st, TALLOC_CTX *mem_ctx, int argc, char **argv)
|
||||
{
|
||||
return NT_STATUS_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
|
||||
static NTSTATUS cmd_get_sid_groups(struct samtest_state *st, TALLOC_CTX *mem_ctx, int argc, char **argv)
|
||||
{
|
||||
return NT_STATUS_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
struct cmd_set sam_general_commands[] = {
|
||||
|
||||
{ "General SAM Commands" },
|
||||
|
||||
{ "load", cmd_load_module, "Load a module", "load <module.so> [domain-sid]" },
|
||||
{ "context", cmd_context, "Load specified context", "context [DOMAIN|]backend1[:options] [DOMAIN|]backend2[:options]" },
|
||||
{ "get_sec_desc", cmd_get_sec_desc, "Get security descriptor info", "get_sec_desc <access-token> <sid>" },
|
||||
{ "set_sec_desc", cmd_set_sec_desc, "Set security descriptor info", "set_sec_desc <access-token> <sid>" },
|
||||
{ "lookup_sid", cmd_lookup_sid, "Lookup type of specified SID", "lookup_sid <sid>" },
|
||||
{ "lookup_name", cmd_lookup_name, "Lookup type of specified name", "lookup_name <sid>" },
|
||||
{ NULL }
|
||||
};
|
||||
|
||||
struct cmd_set sam_domain_commands[] = {
|
||||
{ "Domain Commands" },
|
||||
{ "update_domain", cmd_update_domain, "Update domain information", "update_domain [domain-options] domain-name | domain-sid" },
|
||||
{ "show_domain", cmd_show_domain, "Show domain information", "show_domain domain-sid | domain-name" },
|
||||
{ "enum_domains", cmd_enum_domains, "Enumerate all domains", "enum_domains <token> <acct-ctrl>" },
|
||||
{ "lookup_domain", cmd_lookup_domain, "Lookup a domain by name", "lookup_domain domain-name" },
|
||||
{ NULL }
|
||||
};
|
||||
|
||||
struct cmd_set sam_account_commands[] = {
|
||||
{ "Account Commands" },
|
||||
{ "create_account", cmd_create_account, "Create a new account with specified properties", "create_account [account-options]" },
|
||||
{ "update_account", cmd_update_account, "Update an existing account", "update_account [account-options] account-sid | account-name" },
|
||||
{ "delete_account", cmd_delete_account, "Delete an account", "delete_account account-sid | account-name" },
|
||||
{ "enum_accounts", cmd_enum_accounts, "Enumerate all accounts", "enum_accounts <token> <acct-ctrl>" },
|
||||
{ "lookup_account", cmd_lookup_account, "Lookup an account by either sid or name", "lookup_account account-sid | account-name" },
|
||||
{ "lookup_account_sid", cmd_lookup_account_sid, "Lookup an account by sid", "lookup_account_sid account-sid" },
|
||||
{ "lookup_account_name", cmd_lookup_account_name, "Lookup an account by name", "lookup_account_name account-name" },
|
||||
{ NULL }
|
||||
};
|
||||
|
||||
struct cmd_set sam_group_commands[] = {
|
||||
{ "Group Commands" },
|
||||
{ "create_group", cmd_create_group, "Create a new group", "create_group [group-opts]" },
|
||||
{ "update_group", cmd_update_group, "Update an existing group", "update_group [group-opts] group-name | group-sid" },
|
||||
{ "delete_group", cmd_delete_group, "Delete an existing group", "delete_group group-name | group-sid" },
|
||||
{ "enum_groups", cmd_enum_groups, "Enumerate all groups", "enum_groups <token> <group-ctrl>" },
|
||||
{ "lookup_group", cmd_lookup_group, "Lookup a group by SID or name", "lookup_group group-sid | group-name" },
|
||||
{ "lookup_group_sid", cmd_lookup_group_sid, "Lookup a group by SID", "lookup_group_sid <sid>" },
|
||||
{ "lookup_group_name", cmd_lookup_group_name, "Lookup a group by name", "lookup_group_name <name>" },
|
||||
{ "group_add_member", cmd_group_add_member, "Add group member to group", "group_add_member <group-name | group-sid> <member-name | member-sid>" },
|
||||
{ "group_del_member", cmd_group_del_member, "Delete group member from group", "group_del_member <group-name | group-sid> <member-name | member-sid>" },
|
||||
{ "group_enum", cmd_group_enum, "Enumerate all members of specified group", "group_enum group-sid | group-name" },
|
||||
|
||||
{ "get_sid_groups", cmd_get_sid_groups, "Get a list of groups specified sid is a member of", "group_enum <group-sid | group-name>" },
|
||||
{ NULL }
|
||||
};
|
File diff suppressed because it is too large
Load Diff
@ -1,83 +0,0 @@
|
||||
/*
|
||||
Unix SMB/CIFS implementation.
|
||||
Gentest test definitions
|
||||
|
||||
Copyright (C) James Myers 2003
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
|
||||
get_field_function test_field_get_file_attr;
|
||||
get_field_function test_field_get_fid;
|
||||
get_field_function test_field_get_filename;
|
||||
get_field_function test_field_get_mtime;
|
||||
get_field_function test_field_get_trans2;
|
||||
get_field_function test_field_get_fsinfo_level;
|
||||
|
||||
static struct unlink_test_parms_t gen_unlink_test_parms;
|
||||
static struct close_test_parms_t gen_close_test_parms;
|
||||
static struct qfsi_test_parms_t gen_qfsi_test_parms;
|
||||
|
||||
static struct trans2_parms trans2_qfsi_parms = {
|
||||
testFieldTypeTrans2, 1, 2, 0, 0, TRANSACT2_QFSINFO
|
||||
};
|
||||
|
||||
static struct field_test_spec gen_unlink_test_spec[] = {
|
||||
{"FATTR", testFieldTypeFileAttr, NULL,
|
||||
1, test_field_get_file_attr},
|
||||
{"FNAME", testFieldTypeFilename, NULL,
|
||||
-1, test_field_get_filename},
|
||||
{"", -1, NULL, -1, NULL}
|
||||
};
|
||||
|
||||
static struct field_test_spec gen_close_test_spec[] = {
|
||||
{"FID", testFieldTypeFid, NULL, 1,
|
||||
test_field_get_fid},
|
||||
{"MTIME", testFieldTypeMtime, NULL, 2,
|
||||
test_field_get_mtime},
|
||||
{"", -1, NULL, -1, NULL}
|
||||
};
|
||||
|
||||
static struct field_test_spec gen_qfsi_test_spec[] = {
|
||||
{"TRANS2", testFieldTypeTrans2,
|
||||
(void*)&trans2_qfsi_parms, 15,
|
||||
test_field_get_trans2},
|
||||
{"INFO_LEVEL", 0, NULL, 1, test_field_get_fsinfo_level},
|
||||
{"", -1, NULL, -1, NULL}
|
||||
};
|
||||
|
||||
static struct enum_test gen_enum_tests[] = {
|
||||
{SMBunlink, "UNLINK", TEST_COND_TCON,
|
||||
testTypeFilename,
|
||||
TEST_OPTION_FILE_EXISTS |
|
||||
TEST_OPTION_FILE_SYSTEM |
|
||||
TEST_OPTION_FILE_HIDDEN |
|
||||
TEST_OPTION_FILE_INVISIBLE |
|
||||
TEST_OPTION_FILE_WILDCARD |
|
||||
TEST_OPTION_FILE_NOT_EXIST,
|
||||
1, gen_unlink_test_spec, (void*)&gen_unlink_test_parms,
|
||||
gen_execute_unlink, gen_verify_unlink},
|
||||
{SMBclose, "CLOSE", TEST_COND_TCON,
|
||||
testTypeFid,
|
||||
TEST_OPTION_FID_VALID | TEST_OPTION_FID_INVALID,
|
||||
3, gen_close_test_spec, (void*)&gen_close_test_parms,
|
||||
gen_execute_close, gen_verify_close},
|
||||
{SMBtrans2, "QUERY_FS_INFO", TEST_COND_TCON,
|
||||
testTypeConnected,
|
||||
1,
|
||||
16, gen_qfsi_test_spec, (void*)&gen_qfsi_test_parms,
|
||||
gen_execute_qfsi, gen_verify_qfsi},
|
||||
{-1, NULL, 0, 0, 0, -1, NULL, NULL, NULL}
|
||||
};
|
@ -1,83 +0,0 @@
|
||||
/*
|
||||
Unix SMB/CIFS implementation.
|
||||
Gentest test definitions
|
||||
|
||||
Copyright (C) James Myers 2003
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
|
||||
get_field_function test_field_get_file_attr;
|
||||
get_field_function test_field_get_fid;
|
||||
get_field_function test_field_get_filename;
|
||||
get_field_function test_field_get_mtime;
|
||||
get_field_function test_field_get_trans2;
|
||||
get_field_function test_field_get_fsinfo_level;
|
||||
|
||||
static struct unlink_test_parms_t gen_unlink_test_parms;
|
||||
static struct close_test_parms_t gen_close_test_parms;
|
||||
static struct qfsi_test_parms_t gen_qfsi_test_parms;
|
||||
|
||||
static struct trans2_parms trans2_qfsi_parms = {
|
||||
testFieldTypeTrans2, 1, 2, 0, 0, TRANSACT2_QFSINFO
|
||||
};
|
||||
|
||||
static struct field_test_spec gen_unlink_test_spec[] = {
|
||||
{"FATTR", testFieldTypeFileAttr, NULL,
|
||||
1, test_field_get_file_attr},
|
||||
{"FNAME", testFieldTypeFilename, NULL,
|
||||
-1, test_field_get_filename},
|
||||
{"", -1, NULL, -1, NULL}
|
||||
};
|
||||
|
||||
static struct field_test_spec gen_close_test_spec[] = {
|
||||
{"FID", testFieldTypeFid, NULL, 1,
|
||||
test_field_get_fid},
|
||||
{"MTIME", testFieldTypeMtime, NULL, 2,
|
||||
test_field_get_mtime},
|
||||
{"", -1, NULL, -1, NULL}
|
||||
};
|
||||
|
||||
static struct field_test_spec gen_qfsi_test_spec[] = {
|
||||
{"TRANS2", testFieldTypeTrans2,
|
||||
(void*)&trans2_qfsi_parms, 15,
|
||||
test_field_get_trans2},
|
||||
{"INFO_LEVEL", 0, NULL, 1, test_field_get_fsinfo_level},
|
||||
{"", -1, NULL, -1, NULL}
|
||||
};
|
||||
|
||||
static struct enum_test gen_enum_tests[] = {
|
||||
{SMBunlink, "UNLINK", TEST_COND_TCON,
|
||||
testTypeFilename,
|
||||
TEST_OPTION_FILE_EXISTS |
|
||||
TEST_OPTION_FILE_SYSTEM |
|
||||
TEST_OPTION_FILE_HIDDEN |
|
||||
TEST_OPTION_FILE_INVISIBLE |
|
||||
TEST_OPTION_FILE_WILDCARD |
|
||||
TEST_OPTION_FILE_NOT_EXIST,
|
||||
1, gen_unlink_test_spec, (void*)&gen_unlink_test_parms,
|
||||
gen_execute_unlink, gen_verify_unlink},
|
||||
{SMBclose, "CLOSE", TEST_COND_TCON,
|
||||
testTypeFid,
|
||||
TEST_OPTION_FID_VALID | TEST_OPTION_FID_INVALID,
|
||||
3, gen_close_test_spec, (void*)&gen_close_test_parms,
|
||||
gen_execute_close, gen_verify_close},
|
||||
{SMBtrans2, "QUERY_FS_INFO", TEST_COND_TCON,
|
||||
testTypeConnected,
|
||||
1,
|
||||
16, gen_qfsi_test_spec, (void*)&gen_qfsi_test_parms,
|
||||
gen_execute_qfsi, gen_verify_qfsi},
|
||||
{-1, NULL, 0, 0, 0, -1, NULL, NULL, NULL}
|
||||
};
|
@ -1,732 +0,0 @@
|
||||
/*
|
||||
Unix SMB/CIFS implementation.
|
||||
SMB test generator - load and parse test config
|
||||
Copyright (C) James Myers 2003
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
|
||||
#include "includes.h"
|
||||
#include "gentest.h"
|
||||
|
||||
static struct gentest_context_t *contextP;
|
||||
|
||||
#define NUMPARAMETERS (sizeof(parm_table) / sizeof(struct parm_struct))
|
||||
|
||||
static BOOL do_parameter(const char *pszParmName, const char *pszParmValue);
|
||||
static BOOL do_section(const char *pszSectionName);
|
||||
|
||||
/* prototypes for the special type handlers */
|
||||
static BOOL handle_tests(const char *pszParmValue, char **ptr);
|
||||
|
||||
static BOOL handle_options(const char *pszParmValue, char **ptr);
|
||||
static BOOL handle_fields(const char *pszParmValue, char **ptr);
|
||||
|
||||
static struct enum_list enum_command[] = {
|
||||
{
|
||||
SMBunlink, "SMBunlink"
|
||||
},
|
||||
{SMBclose, "SMBclosex"},
|
||||
{-1, NULL}
|
||||
};
|
||||
static struct enum_list enum_condition[] = {
|
||||
{
|
||||
TEST_COND_NEGPROT, "TEST_COND_NEGPROT"
|
||||
},
|
||||
{TEST_COND_SESSION, "TEST_COND_SESSION"},
|
||||
{TEST_COND_TCON, "TEST_COND_TCON"},
|
||||
{TEST_COND_FID, "TEST_COND_FID"},
|
||||
{-1, NULL}
|
||||
};
|
||||
static struct enum_list enum_test_type[] = {
|
||||
{
|
||||
testTypeConnected, "Connected"
|
||||
},
|
||||
{testTypeFilename, "Filename"},
|
||||
{testTypeFid, "FID"},
|
||||
{-1, NULL}
|
||||
};
|
||||
static struct enum_list enum_options[] = {
|
||||
{TEST_OPTION_FILE_EXISTS, "FILE_EXISTS"},
|
||||
{TEST_OPTION_FILE_NOT_EXIST, "FILE_NOT_EXIST"},
|
||||
{TEST_OPTION_FILE_HIDDEN, "FILE_HIDDEN"},
|
||||
{TEST_OPTION_FILE_SYSTEM, "FILE_SYSTEM"},
|
||||
{TEST_OPTION_FILE_INVISIBLE, "FILE_INVISIBLE"},
|
||||
{TEST_OPTION_FILE_WILDCARD, "FILE_WILDCARD"},
|
||||
{TEST_OPTION_FID_INVALID, "FID_INVALID"},
|
||||
{TEST_OPTION_FID_VALID, "FID_VALID"},
|
||||
{-1, NULL}
|
||||
};
|
||||
static struct enum_list enum_execute[] = {
|
||||
{(int)gen_execute_unlink, "gen_execute_unlink"},
|
||||
{(int)gen_execute_close, "gen_execute_close"},
|
||||
{-1, NULL}
|
||||
};
|
||||
static struct enum_list enum_verify[] = {
|
||||
{
|
||||
(int)gen_verify_unlink, "gen_verify_unlink"
|
||||
},
|
||||
{(int)gen_verify_close, "gen_verify_close"},
|
||||
{-1, NULL}
|
||||
};
|
||||
static struct enum_list enum_field_type[] = {
|
||||
{
|
||||
testFieldTypeFilename, "Filename"
|
||||
},
|
||||
{testFieldTypeFileAttr, "FileAttr"},
|
||||
{testFieldTypeFid, "FID"},
|
||||
{testFieldTypeMtime, "Mtime"},
|
||||
{testFieldTypeTrans2, "Trans2"},
|
||||
{-1, NULL}
|
||||
};
|
||||
static struct enum_list enum_function[] = {
|
||||
{
|
||||
(int)test_field_get_filename, "test_field_get_filename"
|
||||
},
|
||||
{(int)test_field_get_file_attr, "test_field_get_file_attr"},
|
||||
{-1, NULL}
|
||||
};
|
||||
|
||||
/* Note: We do not initialise the defaults union - it is not allowed in ANSI C
|
||||
*/
|
||||
#define GEN_FLAG_GLOBAL 0x0001 /* fundamental options */
|
||||
#define GEN_FLAG_TEST 0x0002 /* test options */
|
||||
#define GEN_FLAG_FIELD 0x0004 /* field options */
|
||||
|
||||
static struct {
|
||||
int command;
|
||||
char *name;
|
||||
int debug;
|
||||
int condition;
|
||||
int type;
|
||||
int options;
|
||||
int words;
|
||||
struct field_test_spec* fields;
|
||||
int field_count;
|
||||
void* execute;
|
||||
void* verify;
|
||||
}
|
||||
test_section;
|
||||
|
||||
static struct {
|
||||
char *name;
|
||||
int type;
|
||||
BOOL random;
|
||||
int words;
|
||||
void * function;
|
||||
}
|
||||
field_section;
|
||||
|
||||
static struct parm_struct parm_table[] = {
|
||||
{"Base Options", P_SEP, P_SEPARATOR
|
||||
},
|
||||
/* global section parameters */
|
||||
{"tests", P_LIST, P_GLOBAL, NULL, handle_tests, NULL, GEN_FLAG_GLOBAL},
|
||||
|
||||
/* test section parameters */
|
||||
{"Test section", P_SEP, P_SEPARATOR},
|
||||
{"command", P_ENUM, P_LOCAL, &test_section.command, NULL, enum_command, GEN_FLAG_TEST},
|
||||
{"name", P_STRING, P_LOCAL, &test_section.name, NULL, NULL, GEN_FLAG_TEST},
|
||||
{"debug", P_INTEGER, P_LOCAL, &test_section.debug, NULL, NULL, GEN_FLAG_TEST},
|
||||
{"condition", P_ENUM, P_LOCAL, &test_section.condition, NULL, enum_condition, GEN_FLAG_TEST},
|
||||
{"type", P_ENUM, P_LOCAL, &test_section.type, NULL, enum_test_type, GEN_FLAG_TEST},
|
||||
{"options", P_LIST, P_LOCAL, &test_section.options, handle_options, NULL, GEN_FLAG_TEST},
|
||||
{"word count", P_INTEGER, P_LOCAL, &test_section.words, NULL, NULL, GEN_FLAG_TEST},
|
||||
{"fields", P_LIST, P_LOCAL, NULL, handle_fields, NULL, GEN_FLAG_TEST},
|
||||
{"execute", P_ENUM, P_LOCAL, &test_section.execute, NULL, enum_execute, GEN_FLAG_TEST},
|
||||
{"verify", P_ENUM, P_LOCAL, &test_section.verify, NULL, enum_verify, GEN_FLAG_TEST},
|
||||
|
||||
/* field section parameters */
|
||||
{"Field section", P_SEP, P_SEPARATOR},
|
||||
{"type", P_ENUM, P_LOCAL, &field_section.type, NULL, enum_field_type, GEN_FLAG_FIELD},
|
||||
{"random", P_BOOL, P_LOCAL, &field_section.random, NULL, NULL, GEN_FLAG_FIELD},
|
||||
{"word count", P_INTEGER, P_LOCAL, &field_section.words, NULL, NULL, GEN_FLAG_FIELD},
|
||||
{"function", P_ENUM, P_LOCAL, &field_section.function, NULL, enum_function, GEN_FLAG_FIELD},
|
||||
|
||||
{NULL, P_BOOL, P_NONE, NULL, NULL, NULL, 0}
|
||||
};
|
||||
|
||||
static BOOL handle_tests(const char *pszParmValue, char **ptr) {
|
||||
contextP->testNames = str_list_make(pszParmValue, NULL);
|
||||
return True;
|
||||
}
|
||||
static BOOL handle_options(const char *pszParmValue, char **ptr) {
|
||||
/* convert option names (in enum_options) to flags */
|
||||
char **str_array;
|
||||
|
||||
str_array = str_list_make(pszParmValue, NULL);
|
||||
|
||||
if (str_array) {
|
||||
size_t i, j;
|
||||
for ( j = 0; str_array[j] != NULL; j++) {
|
||||
BOOL optionValid = False;
|
||||
for (i = 0; enum_options[i].name; i++) {
|
||||
if (strequal(str_array[j],
|
||||
enum_options[i].name)) {
|
||||
*(int *)ptr |= enum_options[i].value;
|
||||
optionValid = True;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!optionValid)
|
||||
DEBUG(0,("handle_options: '%s' invalid option\n",
|
||||
str_array[j]));
|
||||
}
|
||||
}
|
||||
DEBUG(9,("handle_options: %s -> %p\n", pszParmValue, *ptr));
|
||||
|
||||
return True;
|
||||
}
|
||||
|
||||
static BOOL handle_fields(const char *pszParmValue, char **ptr) {
|
||||
/* create initialized field structures for each name */
|
||||
char **str_array;
|
||||
|
||||
str_array = str_list_make(pszParmValue, NULL);
|
||||
|
||||
if (str_array) {
|
||||
size_t i;
|
||||
for ( i = 0; str_array[i] != NULL; i++)
|
||||
test_section.field_count++;
|
||||
/* allocate new field array */
|
||||
test_section.fields = talloc(contextP->mem_ctx,
|
||||
test_section.field_count * sizeof(struct field_test_spec));
|
||||
for ( i = 0; str_array[i] != NULL; i++)
|
||||
test_section.fields[i].name = str_array[i];
|
||||
}
|
||||
return True;
|
||||
}
|
||||
|
||||
/***************************************************************************
|
||||
Map a parameter's string representation to something we can use.
|
||||
Returns False if the parameter string is not recognised, else TRUE.
|
||||
***************************************************************************/
|
||||
|
||||
static int map_parameter(const char *pszParmName, int section) {
|
||||
int iIndex;
|
||||
unsigned validFlags = 0;
|
||||
|
||||
if (*pszParmName == '-')
|
||||
return (-1);
|
||||
|
||||
/* Check for section-specific parameters.
|
||||
* This allows the same parameter name to be used in
|
||||
* different sections with different meanings.
|
||||
*/
|
||||
if (section == GEN_SECTION_GLOBAL)
|
||||
validFlags |= GEN_FLAG_GLOBAL;
|
||||
if (section == GEN_SECTION_TEST)
|
||||
validFlags |= GEN_FLAG_TEST;
|
||||
if (section == GEN_SECTION_FIELD)
|
||||
validFlags |= GEN_FLAG_FIELD;
|
||||
for (iIndex = 0; parm_table[iIndex].label; iIndex++)
|
||||
if ((parm_table[iIndex].flags & validFlags) &&
|
||||
strwicmp(parm_table[iIndex].label, pszParmName) == 0)
|
||||
return (iIndex);
|
||||
|
||||
/* Warn only if it isn't parametric option */
|
||||
if (strchr(pszParmName, ':') == NULL)
|
||||
DEBUG(0, ("Unknown parameter encountered: \"%s\"\n", pszParmName));
|
||||
/* We do return 'fail' for parametric options as well because they are
|
||||
stored in different storage
|
||||
*/
|
||||
return (-1);
|
||||
}
|
||||
|
||||
/***************************************************************************
|
||||
Set a boolean variable from the text value stored in the passed string.
|
||||
Returns True in success, False if the passed string does not correctly
|
||||
represent a boolean.
|
||||
***************************************************************************/
|
||||
|
||||
static BOOL set_boolean(BOOL *pb, const char *pszParmValue) {
|
||||
BOOL bRetval;
|
||||
|
||||
bRetval = True;
|
||||
if (strwicmp(pszParmValue, "yes") == 0 ||
|
||||
strwicmp(pszParmValue, "true") == 0 ||
|
||||
strwicmp(pszParmValue, "1") == 0) {
|
||||
*pb = True;
|
||||
} else if (strwicmp(pszParmValue, "no") == 0 ||
|
||||
strwicmp(pszParmValue, "False") == 0 ||
|
||||
strwicmp(pszParmValue, "0") == 0) {
|
||||
*pb = False;
|
||||
} else {
|
||||
DEBUG(0,
|
||||
("ERROR: Badly formed boolean in configuration file: \"%s\".\n",
|
||||
pszParmValue));
|
||||
bRetval = False;
|
||||
}
|
||||
return (bRetval);
|
||||
}
|
||||
|
||||
/***************************************************************************
|
||||
Process a parameter
|
||||
***************************************************************************/
|
||||
|
||||
static BOOL gen_do_parm(struct gentest_context_t *context,
|
||||
const char *pszParmName, const char *pszParmValue) {
|
||||
int parmnum, i;
|
||||
void *parm_ptr = NULL; /* where we are going to store the result */
|
||||
void *def_ptr = NULL;
|
||||
|
||||
parmnum = map_parameter(pszParmName, context->iCurrentSectionType);
|
||||
|
||||
if (parmnum < 0) {
|
||||
DEBUG(0, ("Ignoring unknown parameter \"%s\"\n", pszParmName));
|
||||
return (True);
|
||||
}
|
||||
DEBUG(19,("gen_do_parm: parm %s is valid\n", pszParmName));
|
||||
def_ptr = parm_table[parmnum].ptr;
|
||||
|
||||
/* we might point at a test, a field or a global */
|
||||
if (context->iCurrentSectionType == GEN_SECTION_GLOBAL) {
|
||||
parm_ptr = def_ptr;
|
||||
} else {
|
||||
if (parm_table[parmnum].class == P_GLOBAL) {
|
||||
DEBUG(0,
|
||||
("Global parameter %s found in service section!\n",
|
||||
pszParmName));
|
||||
return (True);
|
||||
}
|
||||
parm_ptr = def_ptr;
|
||||
}
|
||||
|
||||
/* if it is a special case then go ahead */
|
||||
if (parm_table[parmnum].special) {
|
||||
parm_table[parmnum].special(pszParmValue, (char **)parm_ptr);
|
||||
return (True);
|
||||
}
|
||||
DEBUG(19,("gen_do_parm: parm %s type=%d\n", pszParmName,
|
||||
parm_table[parmnum].type));
|
||||
|
||||
/* now switch on the type of variable it is */
|
||||
switch (parm_table[parmnum].type) {
|
||||
case P_BOOL:
|
||||
set_boolean(parm_ptr, pszParmValue);
|
||||
break;
|
||||
|
||||
case P_INTEGER:
|
||||
*(int *)parm_ptr = atoi(pszParmValue);
|
||||
break;
|
||||
|
||||
case P_LIST:
|
||||
*(char ***)parm_ptr = str_list_make(pszParmValue, NULL);
|
||||
break;
|
||||
|
||||
case P_STRING:
|
||||
parm_ptr = talloc_strdup(context->mem_ctx, pszParmValue);
|
||||
break;
|
||||
|
||||
case P_ENUM:
|
||||
for (i = 0; parm_table[parmnum].enum_list[i].name; i++) {
|
||||
if (strequal
|
||||
(pszParmValue,
|
||||
parm_table[parmnum].enum_list[i].name)) {
|
||||
*(int *)parm_ptr =
|
||||
parm_table[parmnum].
|
||||
enum_list[i].value;
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case P_SEP:
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return (True);
|
||||
}
|
||||
/***************************************************************************
|
||||
Process a parameter.
|
||||
***************************************************************************/
|
||||
|
||||
static BOOL do_parameter(const char *pszParmName, const char *pszParmValue) {
|
||||
BOOL bRetval;
|
||||
|
||||
DEBUG(4, ("doing parameter %s = %s\n", pszParmName, pszParmValue));
|
||||
bRetval = gen_do_parm(contextP, pszParmName, pszParmValue);
|
||||
|
||||
return bRetval;
|
||||
}
|
||||
|
||||
/***************************************************************************
|
||||
Check a test for consistency. Return False if the test is in any way
|
||||
incomplete or faulty, else True.
|
||||
***************************************************************************/
|
||||
|
||||
static BOOL test_ok(struct gentest_context_t *context,int iTest) {
|
||||
BOOL bRetval = True;
|
||||
|
||||
DEBUG(9,("test_ok: index=%d, tests@%p\n", iTest,
|
||||
context->tests));
|
||||
/* initialize new test section */
|
||||
DEBUG(9,("test_ok: name=%s\n", test_section.name));
|
||||
context->tests[iTest].name = test_section.name;
|
||||
context->tests[iTest].debug = test_section.debug;
|
||||
context->tests[iTest].type = test_section.type;
|
||||
context->tests[iTest].command = test_section.command;
|
||||
context->tests[iTest].initial_conditions = test_section.condition;
|
||||
context->tests[iTest].options = test_section.options;
|
||||
context->tests[iTest].word_count = test_section.words;
|
||||
context->tests[iTest].fields = test_section.fields;
|
||||
context->tests[iTest].field_count = test_section.field_count;
|
||||
context->tests[iTest].execute = test_section.execute;
|
||||
context->tests[iTest].verify = test_section.verify;
|
||||
|
||||
/* validate test entry */
|
||||
DEBUG(9,("test_ok: validate name=%s\n", test_section.name));
|
||||
if (context->tests[iTest].name[0] == '\0') {
|
||||
DEBUG(0, ("The following message indicates an internal error:\n"));
|
||||
DEBUG(0, ("No test name in test entry.\n"));
|
||||
bRetval = False;
|
||||
}
|
||||
if (bRetval) {
|
||||
context->tests[iTest].valid = True;
|
||||
DEBUG(9,("added valid test %s\n",test_section.name));
|
||||
}
|
||||
|
||||
return (bRetval);
|
||||
}
|
||||
/***************************************************************************
|
||||
Check a field for consistency. Return False if the field is in any way
|
||||
incomplete or faulty, else True.
|
||||
***************************************************************************/
|
||||
|
||||
static BOOL field_ok(struct gentest_context_t *context,int iField) {
|
||||
BOOL bRetval = True;
|
||||
|
||||
/* setup new field entry */
|
||||
DEBUG(9,("field_ok: index=%d, fields@%p\n", iField,
|
||||
context->fields));
|
||||
context->fields[iField].name = field_section.name;
|
||||
context->fields[iField].type = field_section.type;
|
||||
context->fields[iField].random = field_section.random;
|
||||
context->fields[iField].word_count = field_section.words;
|
||||
context->fields[iField].function = field_section.function;
|
||||
|
||||
/* validate field */
|
||||
if (context->fields[iField].name[0] == '\0') {
|
||||
DEBUG(0, ("The following message indicates an internal error:\n"));
|
||||
DEBUG(0, ("No field name in field entry.\n"));
|
||||
bRetval = False;
|
||||
}
|
||||
if (bRetval) {
|
||||
context->fields[iField].valid = True;
|
||||
DEBUG(9,("added valid field %s\n",field_section.name));
|
||||
}
|
||||
|
||||
return (bRetval);
|
||||
}
|
||||
/***************************************************************************
|
||||
Find a test by name. Otherwise works like get_test.
|
||||
***************************************************************************/
|
||||
|
||||
static int gettestbyname(struct gentest_context_t *context,
|
||||
const char *pszTestName) {
|
||||
int iTest;
|
||||
|
||||
for (iTest = context->iNumTests - 1; iTest >= 0; iTest--)
|
||||
if (context->tests[iTest].valid &&
|
||||
strwicmp(context->tests[iTest].name, pszTestName) == 0) {
|
||||
break;
|
||||
}
|
||||
|
||||
return (iTest);
|
||||
}
|
||||
/***************************************************************************
|
||||
Find a field by name. Otherwise works like get_field.
|
||||
***************************************************************************/
|
||||
|
||||
static int getfieldbyname(struct gentest_context_t *context,
|
||||
const char *pszFieldName) {
|
||||
int iField;
|
||||
|
||||
for (iField = context->iNumFields - 1; iField >= 0; iField--)
|
||||
if (context->fields[iField].valid &&
|
||||
strwicmp(context->fields[iField].name, pszFieldName) == 0) {
|
||||
break;
|
||||
}
|
||||
|
||||
return (iField);
|
||||
}
|
||||
/***************************************************************************
|
||||
Add a new test to the tests array initialising it with the given
|
||||
test.
|
||||
***************************************************************************/
|
||||
|
||||
static int add_a_test(struct gentest_context_t *context,
|
||||
const char *name) {
|
||||
int i;
|
||||
int num_to_alloc = context->iNumTests + 1;
|
||||
|
||||
DEBUG(3, ("add_a_test: %s at index %d\n", name, num_to_alloc-1));
|
||||
/* it might already exist */
|
||||
if (name) {
|
||||
i = gettestbyname(context, name);
|
||||
if (i >= 0)
|
||||
return (i);
|
||||
}
|
||||
|
||||
/* find an invalid one */
|
||||
for (i = 0; i < context->iNumTests; i++)
|
||||
if (!context->tests[i].valid)
|
||||
break;
|
||||
|
||||
/* if not, then create one */
|
||||
DEBUG(3, ("add_a_test: add %s at index %d\n", name, i));
|
||||
if (i == context->iNumTests) {
|
||||
struct enum_test *tsp;
|
||||
|
||||
tsp = talloc_realloc(context->mem_ctx, context->tests,
|
||||
sizeof(struct enum_test) *
|
||||
num_to_alloc);
|
||||
|
||||
if (!tsp) {
|
||||
DEBUG(0,("add_a_test: failed to enlarge TestPtrs!\n"));
|
||||
return (-1);
|
||||
} else {
|
||||
context->tests = tsp;
|
||||
}
|
||||
|
||||
context->iNumTests++;
|
||||
DEBUG(3, ("add_a_test: tests@%p\n", tsp));
|
||||
} //else
|
||||
//free_test(context->tests[i]);
|
||||
/* reinitialize test section fields */
|
||||
test_section.command = 0;
|
||||
test_section.name = talloc_strdup(context->mem_ctx, name);
|
||||
test_section.debug = 0;
|
||||
test_section.condition = 0;
|
||||
test_section.type = 0;
|
||||
test_section.options = 0;
|
||||
test_section.words = 0;
|
||||
test_section.fields = NULL;
|
||||
test_section.field_count = 0;
|
||||
test_section.execute = NULL;
|
||||
test_section.verify = NULL;
|
||||
context->tests[i].valid = False;
|
||||
|
||||
if (name)
|
||||
context->tests[i].name = test_section.name;
|
||||
DEBUG(3, ("add_a_test: added %s at index %d\n", name, i));
|
||||
return (i);
|
||||
}
|
||||
/***************************************************************************
|
||||
Add a new field to the fields array initialising it with the given
|
||||
field.
|
||||
***************************************************************************/
|
||||
|
||||
static int add_a_field(struct gentest_context_t *context,
|
||||
const char *name) {
|
||||
int i;
|
||||
int num_to_alloc = context->iNumFields + 1;
|
||||
|
||||
DEBUG(3, ("add_a_field: %s at index %d\n", name, num_to_alloc-1));
|
||||
/* it might already exist */
|
||||
if (name) {
|
||||
i = getfieldbyname(context, name);
|
||||
if (i >= 0)
|
||||
return (i);
|
||||
}
|
||||
|
||||
/* find an invalid one */
|
||||
for (i = 0; i < context->iNumFields; i++)
|
||||
if (!context->fields[i].valid)
|
||||
break;
|
||||
|
||||
/* if not, then create one */
|
||||
DEBUG(3, ("add_a_field: add %s at index %d\n", name, i));
|
||||
if (i == context->iNumFields) {
|
||||
field_test_spec *tsp;
|
||||
|
||||
tsp = talloc_realloc(context->mem_ctx, context->fields,
|
||||
sizeof(field_test_spec) *
|
||||
num_to_alloc);
|
||||
|
||||
if (!tsp) {
|
||||
DEBUG(0,("add_a_field: failed to enlarge FieldPtrs!\n"));
|
||||
return (-1);
|
||||
} else {
|
||||
context->fields = tsp;
|
||||
}
|
||||
|
||||
context->iNumFields++;
|
||||
DEBUG(3, ("add_a_field: fields@%p\n", tsp));
|
||||
}
|
||||
|
||||
/* reinitialize field section fields */
|
||||
field_section.name = NULL;
|
||||
field_section.type = 0;
|
||||
field_section.random = False;
|
||||
field_section.words = 0;
|
||||
field_section.function = NULL;
|
||||
context->fields[i].valid = False;
|
||||
|
||||
if (name)
|
||||
field_section.name = talloc_strdup(context->mem_ctx, name);
|
||||
DEBUG(3, ("add_a_field: added %s at index %d\n", name, i));
|
||||
return (i);
|
||||
}
|
||||
/***************************************************************************
|
||||
Process a new section (test or field).
|
||||
Returns True on success, False on failure.
|
||||
***************************************************************************/
|
||||
|
||||
static BOOL do_section(const char *pszSectionName) {
|
||||
BOOL bRetval;
|
||||
BOOL isglobal = (strwicmp(pszSectionName, GLOBAL_NAME) == 0);
|
||||
char *sectionType, *sectionName, *p;
|
||||
|
||||
bRetval = False;
|
||||
DEBUG(4, ("doing section %s\n", pszSectionName));
|
||||
/* if we've just struck a global section, note the fact. */
|
||||
contextP->bInGlobalSection = isglobal;
|
||||
|
||||
/* check for multiple global sections */
|
||||
if (contextP->bInGlobalSection) {
|
||||
DEBUG(3, ("Processing section \"[%s]\"\n", pszSectionName));
|
||||
contextP->iCurrentSectionType = GEN_SECTION_GLOBAL;
|
||||
return (True);
|
||||
} else if (contextP->iCurrentSectionType == GEN_SECTION_GLOBAL) {
|
||||
/* just finished global section */
|
||||
;
|
||||
}
|
||||
|
||||
/* parse section name (form <type:name> */
|
||||
sectionType = talloc_strdup(contextP->mem_ctx, pszSectionName);
|
||||
p = strchr_m(sectionType,':');
|
||||
if (p) {
|
||||
*p = 0;
|
||||
sectionName = talloc_strdup(contextP->mem_ctx, p+1);
|
||||
} else {
|
||||
DEBUG(0, ("Invalid section name %s\n", pszSectionName));
|
||||
return False;
|
||||
}
|
||||
|
||||
/* if we have a current test or field, tidy it up before moving on */
|
||||
bRetval = True;
|
||||
|
||||
if (contextP->iTestIndex >= 0 && contextP->iCurrentSectionType == GEN_SECTION_TEST)
|
||||
bRetval = test_ok(contextP, contextP->iTestIndex);
|
||||
if (contextP->iFieldIndex >= 0 && contextP->iCurrentSectionType == GEN_SECTION_FIELD)
|
||||
bRetval = field_ok(contextP, contextP->iFieldIndex);
|
||||
|
||||
/* determine type of this section */
|
||||
contextP->iCurrentSectionType = GEN_SECTION_INVALID;
|
||||
if (strequal(sectionType, "test"))
|
||||
contextP->iCurrentSectionType = GEN_SECTION_TEST;
|
||||
if (strequal(sectionType, "field"))
|
||||
contextP->iCurrentSectionType = GEN_SECTION_FIELD;
|
||||
if (contextP->iCurrentSectionType == GEN_SECTION_INVALID) {
|
||||
DEBUG(0, ("Invalid section type %s\n", sectionType));
|
||||
return False;
|
||||
}
|
||||
|
||||
/* if all is still well, move to the next record in the tests array */
|
||||
if (bRetval) {
|
||||
/* We put this here to avoid an odd message order if messages are */
|
||||
/* issued by the post-processing of a previous section. */
|
||||
DEBUG(2, ("Processing section \"[%s]\"\n", pszSectionName));
|
||||
|
||||
if (contextP->iCurrentSectionType == GEN_SECTION_TEST) {
|
||||
if ((contextP->iTestIndex = add_a_test(contextP, sectionName))
|
||||
< 0) {
|
||||
DEBUG(0, ("Failed to add a new test\n"));
|
||||
return (False);
|
||||
}
|
||||
}
|
||||
if (contextP->iCurrentSectionType == GEN_SECTION_FIELD) {
|
||||
if ((contextP->iFieldIndex = add_a_field(contextP, sectionName))
|
||||
< 0) {
|
||||
DEBUG(0, ("Failed to add a new field\n"));
|
||||
return (False);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return (bRetval);
|
||||
}
|
||||
|
||||
/***************************************************************************
|
||||
Load the test configuration from the test config file. Return True on success,
|
||||
False on failure.
|
||||
***************************************************************************/
|
||||
|
||||
BOOL gen_load_config(struct gentest_context_t *contextPTR) {
|
||||
char *n2;
|
||||
BOOL bRetval;
|
||||
|
||||
contextP = contextPTR;
|
||||
contextP->param_opt = NULL;
|
||||
|
||||
n2 = talloc_strdup(contextP->mem_ctx, contextP->config_filename);
|
||||
|
||||
/* We get sections first, so have to start 'behind' to make up */
|
||||
contextP->iTestIndex = -1;
|
||||
bRetval = pm_process(n2, do_section, do_parameter);
|
||||
|
||||
/* finish up the last section */
|
||||
DEBUG(4, ("pm_process() returned %s\n", BOOLSTR(bRetval)));
|
||||
|
||||
/* if we have a current test or field, tidy it up before moving on */
|
||||
if (contextP->iTestIndex >= 0 && contextP->iCurrentSectionType == GEN_SECTION_TEST)
|
||||
bRetval = test_ok(contextP, contextP->iTestIndex);
|
||||
if (contextP->iFieldIndex >= 0 && contextP->iCurrentSectionType == GEN_SECTION_FIELD)
|
||||
bRetval = field_ok(contextP, contextP->iFieldIndex);
|
||||
|
||||
/* OK, we've parsed the configuration, now we need to match
|
||||
* the field sections to fields required by tests */
|
||||
if (bRetval) {
|
||||
int i,j,k;
|
||||
BOOL fieldValid;
|
||||
for (i=0; i<contextP->iNumTests; i++) {
|
||||
DEBUG(19,("gen_load_config: process test %d %s\n",
|
||||
i, contextP->tests[i].name));
|
||||
for (j=0; j<contextP->tests[i].field_count; j++) {
|
||||
fieldValid = False;
|
||||
DEBUG(19,("gen_load_config: look for field %s\n",
|
||||
contextP->tests[i].fields[j].name));
|
||||
for (k=0; k<contextP->iNumFields; k++) {
|
||||
DEBUG(19,("gen_load_config: compare field %s\n",
|
||||
contextP->fields[k].name));
|
||||
if (strequal(contextP->tests[i].fields[j].name,
|
||||
contextP->fields[k].name)) {
|
||||
/* matching field found */
|
||||
fieldValid = True;
|
||||
contextP->tests[i].fields[j].type = contextP->fields[k].type;
|
||||
contextP->tests[i].fields[j].word_count = contextP->fields[k].word_count;
|
||||
contextP->tests[i].fields[j].function = contextP->fields[k].function;
|
||||
contextP->tests[i].fields[j].valid = contextP->fields[k].valid;
|
||||
contextP->tests[i].fields[j].random = contextP->fields[k].random;
|
||||
contextP->tests[i].fields[j].parms = contextP->fields[k].parms;
|
||||
break;
|
||||
}
|
||||
if (fieldValid)
|
||||
break;
|
||||
}
|
||||
if (!fieldValid) {
|
||||
contextP->tests[i].fields[j].valid = False;
|
||||
contextP->tests[i].fields[j].function = test_field_get_null;
|
||||
DEBUG(0,("missing field section: %s\n",
|
||||
contextP->tests[i].fields[j].name));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return (bRetval);
|
||||
}
|
@ -1,640 +0,0 @@
|
||||
/*
|
||||
Unix SMB/CIFS implementation.
|
||||
RAW_FILEINFO_* individual test suite
|
||||
Copyright (C) Andrew Tridgell 2003
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
|
||||
#include "includes.h"
|
||||
|
||||
static struct {
|
||||
const char *name;
|
||||
enum fileinfo_level level;
|
||||
unsigned only_paths:1;
|
||||
unsigned only_handles:1;
|
||||
NTSTATUS fnum_status, fname_status;
|
||||
union smb_fileinfo fnum_finfo, fname_finfo;
|
||||
} levels[] = {
|
||||
{ "GETATTR", RAW_FILEINFO_GETATTR, 1, 0, },
|
||||
{ "GETATTRE", RAW_FILEINFO_GETATTRE, 0, 1, },
|
||||
{ "STANDARD", RAW_FILEINFO_STANDARD, },
|
||||
{ "EA_SIZE", RAW_FILEINFO_EA_SIZE, },
|
||||
{ "ALL_EAS", RAW_FILEINFO_ALL_EAS, },
|
||||
{ "IS_NAME_VALID", RAW_FILEINFO_IS_NAME_VALID, 1, 0, },
|
||||
{ "BASIC_INFO", RAW_FILEINFO_BASIC_INFO, },
|
||||
{ "STANDARD_INFO", RAW_FILEINFO_STANDARD_INFO, },
|
||||
{ "EA_INFO", RAW_FILEINFO_EA_INFO, },
|
||||
{ "NAME_INFO", RAW_FILEINFO_NAME_INFO, },
|
||||
{ "ALL_INFO", RAW_FILEINFO_ALL_INFO, },
|
||||
{ "ALT_NAME_INFO", RAW_FILEINFO_ALT_NAME_INFO, },
|
||||
{ "STREAM_INFO", RAW_FILEINFO_STREAM_INFO, },
|
||||
{ "COMPRESSION_INFO", RAW_FILEINFO_COMPRESSION_INFO, },
|
||||
{ "BASIC_INFORMATION", RAW_FILEINFO_BASIC_INFORMATION, },
|
||||
{ "STANDARD_INFORMATION", RAW_FILEINFO_STANDARD_INFORMATION, },
|
||||
{ "INTERNAL_INFORMATION", RAW_FILEINFO_INTERNAL_INFORMATION, },
|
||||
{ "EA_INFORMATION", RAW_FILEINFO_EA_INFORMATION, },
|
||||
{ "ACCESS_INFORMATION", RAW_FILEINFO_ACCESS_INFORMATION, },
|
||||
{ "NAME_INFORMATION", RAW_FILEINFO_NAME_INFORMATION, },
|
||||
{ "POSITION_INFORMATION", RAW_FILEINFO_POSITION_INFORMATION, },
|
||||
{ "MODE_INFORMATION", RAW_FILEINFO_MODE_INFORMATION, },
|
||||
{ "ALIGNMENT_INFORMATION", RAW_FILEINFO_ALIGNMENT_INFORMATION, },
|
||||
{ "ALL_INFORMATION", RAW_FILEINFO_ALL_INFORMATION, },
|
||||
{ "ALT_NAME_INFORMATION", RAW_FILEINFO_ALT_NAME_INFORMATION, },
|
||||
{ "STREAM_INFORMATION", RAW_FILEINFO_STREAM_INFORMATION, },
|
||||
{ "COMPRESSION_INFORMATION", RAW_FILEINFO_COMPRESSION_INFORMATION, },
|
||||
{ "NETWORK_OPEN_INFORMATION", RAW_FILEINFO_NETWORK_OPEN_INFORMATION, },
|
||||
{ "ATTRIBUTE_TAG_INFORMATION", RAW_FILEINFO_ATTRIBUTE_TAG_INFORMATION, },
|
||||
{ NULL, }
|
||||
};
|
||||
|
||||
/*
|
||||
compare a dos time (2 second resolution) to a nt time
|
||||
*/
|
||||
static int dos_nt_time_cmp(time_t t, const NTTIME *nt)
|
||||
{
|
||||
time_t t2 = nt_time_to_unix(nt);
|
||||
if (ABS(t2 - t) <= 2) return 0;
|
||||
return t2 - t;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
find a level in the levels[] table
|
||||
*/
|
||||
static union smb_fileinfo *fnum_find(const char *name)
|
||||
{
|
||||
int i;
|
||||
for (i=0; levels[i].name; i++) {
|
||||
if (NT_STATUS_IS_OK(levels[i].fnum_status) &&
|
||||
strcmp(name, levels[i].name) == 0 &&
|
||||
!levels[i].only_paths) {
|
||||
return &levels[i].fnum_finfo;
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
find a level in the levels[] table
|
||||
*/
|
||||
static union smb_fileinfo *fname_find(const char *name)
|
||||
{
|
||||
int i;
|
||||
for (i=0; levels[i].name; i++) {
|
||||
if (NT_STATUS_IS_OK(levels[i].fname_status) &&
|
||||
strcmp(name, levels[i].name) == 0 &&
|
||||
!levels[i].only_handles) {
|
||||
return &levels[i].fname_finfo;
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* local macros to make the code below more readable */
|
||||
#define VAL_EQUAL(n1, v1, n2, v2) do {if (s1->n1.out.v1 != s2->n2.out.v2) { \
|
||||
printf("%s/%s [%u] != %s/%s [%u] at %s(%d)\n", \
|
||||
#n1, #v1, (uint_t)s1->n1.out.v1, \
|
||||
#n2, #v2, (uint_t)s2->n2.out.v2, \
|
||||
__FILE__, __LINE__); \
|
||||
ret = False; \
|
||||
}} while(0)
|
||||
|
||||
#define STR_EQUAL(n1, v1, n2, v2) do {if (strcmp(s1->n1.out.v1.s, s2->n2.out.v2.s) || \
|
||||
s1->n1.out.v1.private_length != s2->n2.out.v2.private_length) { \
|
||||
printf("%s/%s [%s/%d] != %s/%s [%s/%d] at %s(%d)\n", \
|
||||
#n1, #v1, s1->n1.out.v1.s, s1->n1.out.v1.private_length, \
|
||||
#n2, #v2, s2->n2.out.v2.s, s2->n2.out.v2.private_length, \
|
||||
__FILE__, __LINE__); \
|
||||
ret = False; \
|
||||
}} while(0)
|
||||
|
||||
#define STRUCT_EQUAL(n1, v1, n2, v2) do {if (memcmp(&s1->n1.out.v1,&s2->n2.out.v2,sizeof(s1->n1.out.v1))) { \
|
||||
printf("%s/%s != %s/%s at %s(%d)\n", \
|
||||
#n1, #v1, \
|
||||
#n2, #v2, \
|
||||
__FILE__, __LINE__); \
|
||||
ret = False; \
|
||||
}} while(0)
|
||||
|
||||
/* used to find hints on unknown values - and to make sure
|
||||
we zero-fill */
|
||||
#define VAL_UNKNOWN(n1, v1) do {if (s1->n1.out.v1 != 0) { \
|
||||
printf("%s/%s non-zero unknown - %u (0x%x) at %s(%d)\n", \
|
||||
#n1, #v1, \
|
||||
(uint_t)s1->n1.out.v1, \
|
||||
(uint_t)s1->n1.out.v1, \
|
||||
__FILE__, __LINE__); \
|
||||
ret = False; \
|
||||
}} while(0)
|
||||
|
||||
/* basic testing of all RAW_FILEINFO_* calls
|
||||
for each call we test that it succeeds, and where possible test
|
||||
for consistency between the calls.
|
||||
*/
|
||||
BOOL torture_qfileinfo(int dummy)
|
||||
{
|
||||
struct cli_state *cli;
|
||||
int i;
|
||||
BOOL ret = True;
|
||||
int count;
|
||||
union smb_fileinfo *s1, *s2;
|
||||
TALLOC_CTX *mem_ctx;
|
||||
int fnum;
|
||||
const char *fname = "\\torture_qfileinfo.txt";
|
||||
NTTIME correct_time;
|
||||
large_t correct_size;
|
||||
uint32 correct_attrib;
|
||||
const char *correct_name;
|
||||
BOOL skip_streams = False;
|
||||
|
||||
if (!torture_open_connection(&cli)) {
|
||||
return False;
|
||||
}
|
||||
|
||||
mem_ctx = talloc_init("torture_qfileinfo");
|
||||
|
||||
fnum = create_complex_file(cli, mem_ctx, fname);
|
||||
if (fnum == -1) {
|
||||
printf("ERROR: open of %s failed (%s)\n", fname, cli_errstr(cli));
|
||||
ret = False;
|
||||
goto done;
|
||||
}
|
||||
|
||||
|
||||
/* scan all the fileinfo and pathinfo levels */
|
||||
for (i=0; levels[i].name; i++) {
|
||||
if (!levels[i].only_paths) {
|
||||
levels[i].fnum_finfo.generic.level = levels[i].level;
|
||||
levels[i].fnum_finfo.generic.in.fnum = fnum;
|
||||
levels[i].fnum_status = smb_raw_fileinfo(cli->tree, mem_ctx,
|
||||
&levels[i].fnum_finfo);
|
||||
}
|
||||
|
||||
if (!levels[i].only_handles) {
|
||||
levels[i].fname_finfo.generic.level = levels[i].level;
|
||||
levels[i].fname_finfo.generic.in.fname = talloc_strdup(mem_ctx, fname);
|
||||
levels[i].fname_status = smb_raw_pathinfo(cli->tree, mem_ctx,
|
||||
&levels[i].fname_finfo);
|
||||
}
|
||||
}
|
||||
|
||||
/* check for completely broken levels */
|
||||
for (count=i=0; levels[i].name; i++) {
|
||||
if (!levels[i].only_paths && !NT_STATUS_IS_OK(levels[i].fnum_status)) {
|
||||
printf("ERROR: level %s failed - %s\n",
|
||||
levels[i].name, nt_errstr(levels[i].fnum_status));
|
||||
count++;
|
||||
}
|
||||
if (!levels[i].only_handles && !NT_STATUS_IS_OK(levels[i].fname_status)) {
|
||||
printf("ERROR: level %s failed - %s\n",
|
||||
levels[i].name, nt_errstr(levels[i].fname_status));
|
||||
count++;
|
||||
}
|
||||
}
|
||||
|
||||
if (count != 0) {
|
||||
ret = False;
|
||||
printf("%d levels failed\n", count);
|
||||
if (count > 32) {
|
||||
printf("too many level failures - giving up\n");
|
||||
goto done;
|
||||
}
|
||||
}
|
||||
|
||||
/* see if we can do streams */
|
||||
s1 = fnum_find("STREAM_INFO");
|
||||
if (!s1 || s1->stream_info.out.num_streams == 0) {
|
||||
printf("STREAM_INFO broken (%d) - skipping streams checks\n",
|
||||
s1 ? s1->stream_info.out.num_streams : -1);
|
||||
skip_streams = True;
|
||||
}
|
||||
|
||||
|
||||
/* this code is incredibly repititive but doesn't lend itself to loops, so
|
||||
we use lots of macros to make it less painful */
|
||||
|
||||
/* first off we check the levels that are supposed to be aliases. It will be quite rare for
|
||||
this code to fail, but we need to check it for completeness */
|
||||
|
||||
|
||||
|
||||
#define ALIAS_CHECK(sname1, sname2) \
|
||||
do { \
|
||||
s1 = fnum_find(sname1); s2 = fnum_find(sname2); \
|
||||
if (s1 && s2) { INFO_CHECK } \
|
||||
s1 = fname_find(sname1); s2 = fname_find(sname2); \
|
||||
if (s1 && s2) { INFO_CHECK } \
|
||||
s1 = fnum_find(sname1); s2 = fname_find(sname2); \
|
||||
if (s1 && s2) { INFO_CHECK } \
|
||||
} while (0)
|
||||
|
||||
#define INFO_CHECK \
|
||||
STRUCT_EQUAL(basic_info, create_time, basic_info, create_time); \
|
||||
STRUCT_EQUAL(basic_info, access_time, basic_info, access_time); \
|
||||
STRUCT_EQUAL(basic_info, write_time, basic_info, write_time); \
|
||||
STRUCT_EQUAL(basic_info, change_time, basic_info, change_time); \
|
||||
VAL_EQUAL (basic_info, attrib, basic_info, attrib);
|
||||
|
||||
ALIAS_CHECK("BASIC_INFO", "BASIC_INFORMATION");
|
||||
|
||||
#undef INFO_CHECK
|
||||
#define INFO_CHECK \
|
||||
VAL_EQUAL(standard_info, alloc_size, standard_info, alloc_size); \
|
||||
VAL_EQUAL(standard_info, size, standard_info, size); \
|
||||
VAL_EQUAL(standard_info, nlink, standard_info, nlink); \
|
||||
VAL_EQUAL(standard_info, delete_pending, standard_info, delete_pending); \
|
||||
VAL_EQUAL(standard_info, directory, standard_info, directory);
|
||||
|
||||
ALIAS_CHECK("STANDARD_INFO", "STANDARD_INFORMATION");
|
||||
|
||||
#undef INFO_CHECK
|
||||
#define INFO_CHECK \
|
||||
VAL_EQUAL(ea_info, ea_size, ea_info, ea_size);
|
||||
|
||||
ALIAS_CHECK("EA_INFO", "EA_INFORMATION");
|
||||
|
||||
#undef INFO_CHECK
|
||||
#define INFO_CHECK \
|
||||
STR_EQUAL(name_info, fname, name_info, fname);
|
||||
|
||||
ALIAS_CHECK("NAME_INFO", "NAME_INFORMATION");
|
||||
|
||||
#undef INFO_CHECK
|
||||
#define INFO_CHECK \
|
||||
STRUCT_EQUAL(all_info, create_time, all_info, create_time); \
|
||||
STRUCT_EQUAL(all_info, access_time, all_info, access_time); \
|
||||
STRUCT_EQUAL(all_info, write_time, all_info, write_time); \
|
||||
STRUCT_EQUAL(all_info, change_time, all_info, change_time); \
|
||||
VAL_EQUAL(all_info, attrib, all_info, attrib); \
|
||||
VAL_EQUAL(all_info, alloc_size, all_info, alloc_size); \
|
||||
VAL_EQUAL(all_info, size, all_info, size); \
|
||||
VAL_EQUAL(all_info, nlink, all_info, nlink); \
|
||||
VAL_EQUAL(all_info, delete_pending, all_info, delete_pending); \
|
||||
VAL_EQUAL(all_info, directory, all_info, directory); \
|
||||
VAL_EQUAL(all_info, ea_size, all_info, ea_size); \
|
||||
STR_EQUAL(all_info, fname, all_info, fname);
|
||||
|
||||
ALIAS_CHECK("ALL_INFO", "ALL_INFORMATION");
|
||||
|
||||
|
||||
#undef INFO_CHECK
|
||||
#define INFO_CHECK \
|
||||
STR_EQUAL(alt_name_info, fname, alt_name_info, fname);
|
||||
|
||||
ALIAS_CHECK("ALT_NAME_INFO", "ALT_NAME_INFORMATION");
|
||||
|
||||
#define TIME_CHECK_NT(sname, stype, tfield) do { \
|
||||
s1 = fnum_find(sname); \
|
||||
if (s1 && memcmp(&s1->stype.out.tfield, &correct_time, sizeof(correct_time)) != 0) { \
|
||||
printf("(%d) handle %s/%s incorrect - %s should be %s\n", __LINE__, #stype, #tfield, \
|
||||
nt_time_string(mem_ctx, &s1->stype.out.tfield), \
|
||||
nt_time_string(mem_ctx, &correct_time)); \
|
||||
ret = False; \
|
||||
} \
|
||||
s1 = fname_find(sname); \
|
||||
if (s1 && memcmp(&s1->stype.out.tfield, &correct_time, sizeof(correct_time)) != 0) { \
|
||||
printf("(%d) path %s/%s incorrect - %s should be %s\n", __LINE__, #stype, #tfield, \
|
||||
nt_time_string(mem_ctx, &s1->stype.out.tfield), \
|
||||
nt_time_string(mem_ctx, &correct_time)); \
|
||||
ret = False; \
|
||||
}} while (0)
|
||||
|
||||
#define TIME_CHECK_DOS(sname, stype, tfield) do { \
|
||||
s1 = fnum_find(sname); \
|
||||
if (s1 && dos_nt_time_cmp(s1->stype.out.tfield, &correct_time) != 0) { \
|
||||
printf("(%d) handle %s/%s incorrect - %s should be %s\n", __LINE__, #stype, #tfield, \
|
||||
time_string(mem_ctx, s1->stype.out.tfield), \
|
||||
nt_time_string(mem_ctx, &correct_time)); \
|
||||
ret = False; \
|
||||
} \
|
||||
s1 = fname_find(sname); \
|
||||
if (s1 && dos_nt_time_cmp(s1->stype.out.tfield, &correct_time) != 0) { \
|
||||
printf("(%d) path %s/%s incorrect - %s should be %s\n", __LINE__, #stype, #tfield, \
|
||||
time_string(mem_ctx, s1->stype.out.tfield), \
|
||||
nt_time_string(mem_ctx, &correct_time)); \
|
||||
ret = False; \
|
||||
}} while (0)
|
||||
|
||||
#define TIME_CHECK_UNX(sname, stype, tfield) do { \
|
||||
s1 = fnum_find(sname); \
|
||||
if (s1 && unx_nt_time_cmp(s1->stype.out.tfield, &correct_time) != 0) { \
|
||||
printf("(%d) handle %s/%s incorrect - %s should be %s\n", __LINE__, #stype, #tfield, \
|
||||
time_string(mem_ctx, s1->stype.out.tfield), \
|
||||
nt_time_string(mem_ctx, &correct_time)); \
|
||||
ret = False; \
|
||||
} \
|
||||
s1 = fname_find(sname); \
|
||||
if (s1 && unx_nt_time_cmp(s1->stype.out.tfield, &correct_time) != 0) { \
|
||||
printf("(%d) path %s/%s incorrect - %s should be %s\n", __LINE__, #stype, #tfield, \
|
||||
time_string(mem_ctx, s1->stype.out.tfield), \
|
||||
nt_time_string(mem_ctx, &correct_time)); \
|
||||
ret = False; \
|
||||
}} while (0)
|
||||
|
||||
/* now check that all the times that are supposed to be equal are correct */
|
||||
s1 = fnum_find("BASIC_INFO");
|
||||
correct_time = s1->basic_info.out.create_time;
|
||||
printf("create_time: %s\n", nt_time_string(mem_ctx, &correct_time));
|
||||
|
||||
TIME_CHECK_NT ("BASIC_INFO", basic_info, create_time);
|
||||
TIME_CHECK_NT ("BASIC_INFORMATION", basic_info, create_time);
|
||||
TIME_CHECK_DOS("GETATTRE", getattre, create_time);
|
||||
TIME_CHECK_DOS("STANDARD", standard, create_time);
|
||||
TIME_CHECK_DOS("EA_SIZE", ea_size, create_time);
|
||||
TIME_CHECK_NT ("ALL_INFO", all_info, create_time);
|
||||
TIME_CHECK_NT ("NETWORK_OPEN_INFORMATION", network_open_information, create_time);
|
||||
|
||||
s1 = fnum_find("BASIC_INFO");
|
||||
correct_time = s1->basic_info.out.access_time;
|
||||
printf("access_time: %s\n", nt_time_string(mem_ctx, &correct_time));
|
||||
|
||||
TIME_CHECK_NT ("BASIC_INFO", basic_info, access_time);
|
||||
TIME_CHECK_NT ("BASIC_INFORMATION", basic_info, access_time);
|
||||
TIME_CHECK_DOS("GETATTRE", getattre, access_time);
|
||||
TIME_CHECK_DOS("STANDARD", standard, access_time);
|
||||
TIME_CHECK_DOS("EA_SIZE", ea_size, access_time);
|
||||
TIME_CHECK_NT ("ALL_INFO", all_info, access_time);
|
||||
TIME_CHECK_NT ("NETWORK_OPEN_INFORMATION", network_open_information, access_time);
|
||||
|
||||
s1 = fnum_find("BASIC_INFO");
|
||||
correct_time = s1->basic_info.out.write_time;
|
||||
printf("write_time : %s\n", nt_time_string(mem_ctx, &correct_time));
|
||||
|
||||
TIME_CHECK_NT ("BASIC_INFO", basic_info, write_time);
|
||||
TIME_CHECK_NT ("BASIC_INFORMATION", basic_info, write_time);
|
||||
TIME_CHECK_DOS("GETATTRE", getattre, write_time);
|
||||
TIME_CHECK_DOS("STANDARD", standard, write_time);
|
||||
TIME_CHECK_DOS("EA_SIZE", ea_size, write_time);
|
||||
TIME_CHECK_NT ("ALL_INFO", all_info, write_time);
|
||||
TIME_CHECK_NT ("NETWORK_OPEN_INFORMATION", network_open_information, write_time);
|
||||
|
||||
s1 = fnum_find("BASIC_INFO");
|
||||
correct_time = s1->basic_info.out.change_time;
|
||||
printf("change_time: %s\n", nt_time_string(mem_ctx, &correct_time));
|
||||
|
||||
TIME_CHECK_NT ("BASIC_INFO", basic_info, change_time);
|
||||
TIME_CHECK_NT ("BASIC_INFORMATION", basic_info, change_time);
|
||||
TIME_CHECK_NT ("ALL_INFO", all_info, change_time);
|
||||
TIME_CHECK_NT ("NETWORK_OPEN_INFORMATION", network_open_information, change_time);
|
||||
|
||||
|
||||
#define SIZE_CHECK(sname, stype, tfield) do { \
|
||||
s1 = fnum_find(sname); \
|
||||
if (s1 && s1->stype.out.tfield != correct_size) { \
|
||||
printf("(%d) handle %s/%s incorrect - %u should be %u\n", __LINE__, #stype, #tfield, \
|
||||
(unsigned)s1->stype.out.tfield, \
|
||||
(unsigned)correct_size); \
|
||||
ret = False; \
|
||||
} \
|
||||
s1 = fname_find(sname); \
|
||||
if (s1 && s1->stype.out.tfield != correct_size) { \
|
||||
printf("(%d) path %s/%s incorrect - %u should be %u\n", __LINE__, #stype, #tfield, \
|
||||
(unsigned)s1->stype.out.tfield, \
|
||||
(unsigned)correct_size); \
|
||||
ret = False; \
|
||||
}} while (0)
|
||||
|
||||
s1 = fnum_find("STANDARD_INFO");
|
||||
correct_size = s1->standard_info.out.size;
|
||||
printf("size: %u\n", (unsigned)correct_size);
|
||||
|
||||
SIZE_CHECK("GETATTR", getattr, size);
|
||||
SIZE_CHECK("GETATTRE", getattre, size);
|
||||
SIZE_CHECK("STANDARD", standard, size);
|
||||
SIZE_CHECK("EA_SIZE", ea_size, size);
|
||||
SIZE_CHECK("STANDARD_INFO", standard_info, size);
|
||||
SIZE_CHECK("STANDARD_INFORMATION", standard_info, size);
|
||||
SIZE_CHECK("ALL_INFO", all_info, size);
|
||||
SIZE_CHECK("ALL_INFORMATION", all_info, size);
|
||||
SIZE_CHECK("COMPRESSION_INFO", compression_info, compressed_size);
|
||||
SIZE_CHECK("COMPRESSION_INFORMATION", compression_info, compressed_size);
|
||||
SIZE_CHECK("NETWORK_OPEN_INFORMATION", network_open_information, size);
|
||||
if (!skip_streams) {
|
||||
SIZE_CHECK("STREAM_INFO", stream_info, streams[0].size);
|
||||
SIZE_CHECK("STREAM_INFORMATION", stream_info, streams[0].size);
|
||||
}
|
||||
|
||||
|
||||
s1 = fnum_find("STANDARD_INFO");
|
||||
correct_size = s1->standard_info.out.alloc_size;
|
||||
printf("alloc_size: %u\n", (unsigned)correct_size);
|
||||
|
||||
SIZE_CHECK("GETATTRE", getattre, alloc_size);
|
||||
SIZE_CHECK("STANDARD", standard, alloc_size);
|
||||
SIZE_CHECK("EA_SIZE", ea_size, alloc_size);
|
||||
SIZE_CHECK("STANDARD_INFO", standard_info, alloc_size);
|
||||
SIZE_CHECK("STANDARD_INFORMATION", standard_info, alloc_size);
|
||||
SIZE_CHECK("ALL_INFO", all_info, alloc_size);
|
||||
SIZE_CHECK("ALL_INFORMATION", all_info, alloc_size);
|
||||
SIZE_CHECK("NETWORK_OPEN_INFORMATION", network_open_information, alloc_size);
|
||||
if (!skip_streams) {
|
||||
SIZE_CHECK("STREAM_INFO", stream_info, streams[0].alloc_size);
|
||||
SIZE_CHECK("STREAM_INFORMATION", stream_info, streams[0].alloc_size);
|
||||
}
|
||||
|
||||
#define ATTRIB_CHECK(sname, stype, tfield) do { \
|
||||
s1 = fnum_find(sname); \
|
||||
if (s1 && s1->stype.out.tfield != correct_attrib) { \
|
||||
printf("(%d) handle %s/%s incorrect - 0x%x should be 0x%x\n", __LINE__, #stype, #tfield, \
|
||||
(unsigned)s1->stype.out.tfield, \
|
||||
(unsigned)correct_attrib); \
|
||||
ret = False; \
|
||||
} \
|
||||
s1 = fname_find(sname); \
|
||||
if (s1 && s1->stype.out.tfield != correct_attrib) { \
|
||||
printf("(%d) path %s/%s incorrect - 0x%x should be 0x%x\n", __LINE__, #stype, #tfield, \
|
||||
(unsigned)s1->stype.out.tfield, \
|
||||
(unsigned)correct_attrib); \
|
||||
ret = False; \
|
||||
}} while (0)
|
||||
|
||||
s1 = fnum_find("BASIC_INFO");
|
||||
correct_attrib = s1->basic_info.out.attrib;
|
||||
printf("attrib: 0x%x\n", (unsigned)correct_attrib);
|
||||
|
||||
ATTRIB_CHECK("GETATTR", getattr, attrib);
|
||||
ATTRIB_CHECK("GETATTRE", getattre, attrib);
|
||||
ATTRIB_CHECK("STANDARD", standard, attrib);
|
||||
ATTRIB_CHECK("BASIC_INFO", basic_info, attrib);
|
||||
ATTRIB_CHECK("BASIC_INFORMATION", basic_info, attrib);
|
||||
ATTRIB_CHECK("EA_SIZE", ea_size, attrib);
|
||||
ATTRIB_CHECK("ALL_INFO", all_info, attrib);
|
||||
ATTRIB_CHECK("ALL_INFORMATION", all_info, attrib);
|
||||
ATTRIB_CHECK("NETWORK_OPEN_INFORMATION", network_open_information, attrib);
|
||||
ATTRIB_CHECK("ATTRIBUTE_TAG_INFORMATION", attribute_tag_information, attrib);
|
||||
|
||||
correct_name = fname;
|
||||
printf("name: %s\n", correct_name);
|
||||
|
||||
#define NAME_CHECK(sname, stype, tfield, flags) do { \
|
||||
s1 = fnum_find(sname); \
|
||||
if ((s1 && strcmp(s1->stype.out.tfield.s, correct_name) != 0) || \
|
||||
wire_bad_flags(&s1->stype.out.tfield, flags)) { \
|
||||
printf("(%d) handle %s/%s incorrect - '%s/%d'\n", __LINE__, #stype, #tfield, \
|
||||
s1->stype.out.tfield.s, s1->stype.out.tfield.private_length); \
|
||||
ret = False; \
|
||||
} \
|
||||
s1 = fname_find(sname); \
|
||||
if ((s1 && strcmp(s1->stype.out.tfield.s, correct_name)) != 0 || \
|
||||
wire_bad_flags(&s1->stype.out.tfield, flags)) { \
|
||||
printf("(%d) path %s/%s incorrect - '%s/%d'\n", __LINE__, #stype, #tfield, \
|
||||
s1->stype.out.tfield.s, s1->stype.out.tfield.private_length); \
|
||||
ret = False; \
|
||||
}} while (0)
|
||||
|
||||
NAME_CHECK("NAME_INFO", name_info, fname, STR_UNICODE);
|
||||
NAME_CHECK("NAME_INFORMATION", name_info, fname, STR_UNICODE);
|
||||
|
||||
/* the ALL_INFO file name is the full path on the filesystem */
|
||||
s1 = fnum_find("ALL_INFO");
|
||||
if (s1 && !s1->all_info.out.fname.s) {
|
||||
printf("ALL_INFO didn't give a filename\n");
|
||||
ret = False;
|
||||
}
|
||||
if (s1 && s1->all_info.out.fname.s) {
|
||||
char *p = strrchr(s1->all_info.out.fname.s, '\\');
|
||||
if (!p) {
|
||||
printf("Not a full path in all_info/fname? - '%s'\n",
|
||||
s1->all_info.out.fname.s);
|
||||
ret = False;
|
||||
} else {
|
||||
if (strcmp(correct_name, p) != 0) {
|
||||
printf("incorrect basename in all_info/fname - '%s'\n",
|
||||
s1->all_info.out.fname.s);
|
||||
ret = False;
|
||||
}
|
||||
}
|
||||
if (wire_bad_flags(&s1->all_info.out.fname, STR_UNICODE)) {
|
||||
printf("Should not null terminate all_info/fname\n");
|
||||
ret = False;
|
||||
}
|
||||
}
|
||||
|
||||
s1 = fnum_find("ALT_NAME_INFO");
|
||||
correct_name = s1->alt_name_info.out.fname.s;
|
||||
printf("alt_name: %s\n", correct_name);
|
||||
|
||||
NAME_CHECK("ALT_NAME_INFO", alt_name_info, fname, STR_UNICODE);
|
||||
NAME_CHECK("ALT_NAME_INFORMATION", alt_name_info, fname, STR_UNICODE);
|
||||
|
||||
/* and make sure we can open by alternate name */
|
||||
cli_close(cli, fnum);
|
||||
fnum = cli_nt_create_full(cli, correct_name, 0, NT_ACCESS_GENERIC_ALL_ACCESS,
|
||||
FILE_ATTRIBUTE_NORMAL,
|
||||
NTCREATEX_SHARE_ACCESS_DELETE|
|
||||
NTCREATEX_SHARE_ACCESS_READ|
|
||||
NTCREATEX_SHARE_ACCESS_WRITE,
|
||||
FILE_OVERWRITE_IF,
|
||||
0, 0);
|
||||
if (fnum == -1) {
|
||||
printf("Unable to open by alt_name - %s\n", cli_errstr(cli));
|
||||
ret = False;
|
||||
}
|
||||
|
||||
if (!skip_streams) {
|
||||
correct_name = "::$DATA";
|
||||
printf("stream_name: %s\n", correct_name);
|
||||
|
||||
NAME_CHECK("STREAM_INFO", stream_info, streams[0].stream_name, STR_UNICODE);
|
||||
NAME_CHECK("STREAM_INFORMATION", stream_info, streams[0].stream_name, STR_UNICODE);
|
||||
}
|
||||
|
||||
/* make sure the EAs look right */
|
||||
s1 = fnum_find("ALL_EAS");
|
||||
if (s1) {
|
||||
printf("ea_size: %d\n", s1->all_eas.out.ea_size);
|
||||
for (i=0;i<s1->all_eas.out.num_eas;i++) {
|
||||
printf(" flags=%d %s=%*.*s\n",
|
||||
s1->all_eas.out.eas[i].flags,
|
||||
s1->all_eas.out.eas[i].name.s,
|
||||
s1->all_eas.out.eas[i].value.length,
|
||||
s1->all_eas.out.eas[i].value.length,
|
||||
s1->all_eas.out.eas[i].value.data);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#define VAL_CHECK(sname1, stype1, tfield1, sname2, stype2, tfield2) do { \
|
||||
s1 = fnum_find(sname1); s2 = fnum_find(sname2); \
|
||||
if (s1 && s2 && s1->stype1.out.tfield1 != s2->stype2.out.tfield2) { \
|
||||
printf("(%d) handle %s/%s != %s/%s - 0x%x vs 0x%x\n", __LINE__, \
|
||||
#stype1, #tfield1, #stype2, #tfield2, \
|
||||
s1->stype1.out.tfield1, s2->stype2.out.tfield2); \
|
||||
ret = False; \
|
||||
} \
|
||||
s1 = fname_find(sname1); s2 = fname_find(sname2); \
|
||||
if (s1 && s2 && s1->stype1.out.tfield1 != s2->stype2.out.tfield2) { \
|
||||
printf("(%d) path %s/%s != %s/%s - 0x%x vs 0x%x\n", __LINE__, \
|
||||
#stype1, #tfield1, #stype2, #tfield2, \
|
||||
s1->stype1.out.tfield1, s2->stype2.out.tfield2); \
|
||||
ret = False; \
|
||||
} \
|
||||
s1 = fnum_find(sname1); s2 = fname_find(sname2); \
|
||||
if (s1 && s2 && s1->stype1.out.tfield1 != s2->stype2.out.tfield2) { \
|
||||
printf("(%d) handle %s/%s != path %s/%s - 0x%x vs 0x%x\n", __LINE__, \
|
||||
#stype1, #tfield1, #stype2, #tfield2, \
|
||||
s1->stype1.out.tfield1, s2->stype2.out.tfield2); \
|
||||
ret = False; \
|
||||
} \
|
||||
s1 = fname_find(sname1); s2 = fnum_find(sname2); \
|
||||
if (s1 && s2 && s1->stype1.out.tfield1 != s2->stype2.out.tfield2) { \
|
||||
printf("(%d) path %s/%s != handle %s/%s - 0x%x vs 0x%x\n", __LINE__, \
|
||||
#stype1, #tfield1, #stype2, #tfield2, \
|
||||
s1->stype1.out.tfield1, s2->stype2.out.tfield2); \
|
||||
ret = False; \
|
||||
}} while (0)
|
||||
|
||||
VAL_CHECK("STANDARD_INFO", standard_info, delete_pending,
|
||||
"ALL_INFO", all_info, delete_pending);
|
||||
VAL_CHECK("STANDARD_INFO", standard_info, directory,
|
||||
"ALL_INFO", all_info, directory);
|
||||
VAL_CHECK("STANDARD_INFO", standard_info, nlink,
|
||||
"ALL_INFO", all_info, nlink);
|
||||
VAL_CHECK("EA_INFO", ea_info, ea_size,
|
||||
"ALL_INFO", all_info, ea_size);
|
||||
VAL_CHECK("ALL_EAS", all_eas, ea_size,
|
||||
"ALL_INFO", all_info, ea_size);
|
||||
VAL_CHECK("EA_SIZE", ea_size, ea_size,
|
||||
"ALL_INFO", all_info, ea_size);
|
||||
|
||||
#define UNKNOWN_CHECK(sname, stype, tfield) do { \
|
||||
s1 = fnum_find(sname); \
|
||||
if (s1 && s1->stype.out.tfield != 0) { \
|
||||
printf("(%d) handle %s/%s unknown != 0 (0x%x)\n", __LINE__, \
|
||||
#stype, #tfield, \
|
||||
(unsigned)s1->stype.out.tfield); \
|
||||
} \
|
||||
s1 = fname_find(sname); \
|
||||
if (s1 && s1->stype.out.tfield != 0) { \
|
||||
printf("(%d) path %s/%s unknown != 0 (0x%x)\n", __LINE__, \
|
||||
#stype, #tfield, \
|
||||
(unsigned)s1->stype.out.tfield); \
|
||||
}} while (0)
|
||||
|
||||
/* now get a bit fancier .... */
|
||||
|
||||
/* when we set the delete disposition then the link count should drop
|
||||
to 0 and delete_pending should be 1 */
|
||||
|
||||
|
||||
done:
|
||||
cli_close(cli, fnum);
|
||||
cli_unlink(cli, fname);
|
||||
|
||||
torture_close_connection(cli);
|
||||
talloc_destroy(mem_ctx);
|
||||
return ret;
|
||||
}
|
@ -1,286 +0,0 @@
|
||||
/*
|
||||
Unix SMB/CIFS implementation.
|
||||
RAW_QFS_* individual test suite
|
||||
Copyright (C) Andrew Tridgell 2003
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
|
||||
#include "includes.h"
|
||||
|
||||
|
||||
static struct {
|
||||
const char *name;
|
||||
enum fsinfo_level level;
|
||||
NTSTATUS status;
|
||||
union smb_fsinfo fsinfo;
|
||||
} levels[] = {
|
||||
{"DSKATTR", RAW_QFS_DSKATTR, },
|
||||
{"ALLOCATION", RAW_QFS_ALLOCATION, },
|
||||
{"VOLUME", RAW_QFS_VOLUME, },
|
||||
{"VOLUME_INFO", RAW_QFS_VOLUME_INFO, },
|
||||
{"SIZE_INFO", RAW_QFS_SIZE_INFO, },
|
||||
{"DEVICE_INFO", RAW_QFS_DEVICE_INFO, },
|
||||
{"ATTRIBUTE_INFO", RAW_QFS_ATTRIBUTE_INFO, },
|
||||
{"VOLUME_INFORMATION", RAW_QFS_VOLUME_INFORMATION, },
|
||||
{"SIZE_INFORMATION", RAW_QFS_SIZE_INFORMATION, },
|
||||
{"DEVICE_INFORMATION", RAW_QFS_DEVICE_INFORMATION, },
|
||||
{"ATTRIBUTE_INFORMATION", RAW_QFS_ATTRIBUTE_INFORMATION, },
|
||||
{"QUOTA_INFORMATION", RAW_QFS_QUOTA_INFORMATION, },
|
||||
{"FULL_SIZE_INFORMATION", RAW_QFS_FULL_SIZE_INFORMATION, },
|
||||
{"OBJECTID_INFORMATION", RAW_QFS_OBJECTID_INFORMATION, },
|
||||
{ NULL, }
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
find a level in the levels[] table
|
||||
*/
|
||||
static union smb_fsinfo *find(const char *name)
|
||||
{
|
||||
int i;
|
||||
for (i=0; levels[i].name; i++) {
|
||||
if (strcmp(name, levels[i].name) == 0) {
|
||||
return &levels[i].fsinfo;
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* local macros to make the code below more readable */
|
||||
#define VAL_EQUAL(n1, v1, n2, v2) do {if (s1->n1.out.v1 != s2->n2.out.v2) { \
|
||||
printf("%s/%s [%u] != %s/%s [%u] at %s(%d)\n", \
|
||||
#n1, #v1, (uint_t)s1->n1.out.v1, \
|
||||
#n2, #v2, (uint_t)s2->n2.out.v2, \
|
||||
__FILE__, __LINE__); \
|
||||
ret = False; \
|
||||
}} while(0)
|
||||
|
||||
#define STR_EQUAL(n1, v1, n2, v2) do {if (!s1->n1.out.v1 && !s2->n2.out.v2) return True; \
|
||||
if (!s1->n1.out.v1 || !s2->n2.out.v2) return False; \
|
||||
if (strcmp(s1->n1.out.v1, s2->n2.out.v2)) { \
|
||||
printf("%s/%s [%s] != %s/%s [%s] at %s(%d)\n", \
|
||||
#n1, #v1, s1->n1.out.v1, \
|
||||
#n2, #v2, s2->n2.out.v2, \
|
||||
__FILE__, __LINE__); \
|
||||
ret = False; \
|
||||
}} while(0)
|
||||
|
||||
#define STRUCT_EQUAL(n1, v1, n2, v2) do {if (memcmp(&s1->n1.out.v1,&s2->n2.out.v2,sizeof(s1->n1.out.v1))) { \
|
||||
printf("%s/%s != %s/%s at %s(%d)\n", \
|
||||
#n1, #v1, \
|
||||
#n2, #v2, \
|
||||
__FILE__, __LINE__); \
|
||||
ret = False; \
|
||||
}} while(0)
|
||||
|
||||
/* used to find hints on unknown values - and to make sure
|
||||
we zero-fill */
|
||||
#define VAL_UNKNOWN(n1, v1) do {if (s1->n1.out.v1 != 0) { \
|
||||
printf("%s/%s non-zero unknown - %u (0x%x) at %s(%d)\n", \
|
||||
#n1, #v1, \
|
||||
(uint_t)s1->n1.out.v1, \
|
||||
(uint_t)s1->n1.out.v1, \
|
||||
__FILE__, __LINE__); \
|
||||
ret = False; \
|
||||
}} while(0)
|
||||
|
||||
/* basic testing of all RAW_QFS_* calls
|
||||
for each call we test that it succeeds, and where possible test
|
||||
for consistency between the calls.
|
||||
|
||||
Some of the consistency tests assume that the target filesystem is
|
||||
quiescent, which is sometimes hard to achieve
|
||||
*/
|
||||
BOOL torture_qfsinfo(int dummy)
|
||||
{
|
||||
struct cli_state *cli;
|
||||
int i;
|
||||
BOOL ret = True;
|
||||
int count;
|
||||
union smb_fsinfo *s1, *s2;
|
||||
TALLOC_CTX *mem_ctx;
|
||||
|
||||
if (!torture_open_connection(&cli)) {
|
||||
return False;
|
||||
}
|
||||
|
||||
mem_ctx = talloc_init("torture_qfsinfo");
|
||||
|
||||
/* scan all the levels, pulling the results */
|
||||
for (i=0; levels[i].name; i++) {
|
||||
levels[i].fsinfo.generic.level = levels[i].level;
|
||||
levels[i].status = smb_raw_fsinfo(cli->tree, mem_ctx, &levels[i].fsinfo);
|
||||
}
|
||||
|
||||
/* check for completely broken levels */
|
||||
for (count=i=0; levels[i].name; i++) {
|
||||
if (!NT_STATUS_IS_OK(levels[i].status)) {
|
||||
printf("ERROR: level %s failed - %s\n", levels[i].name, nt_errstr(levels[i].status));
|
||||
count++;
|
||||
}
|
||||
}
|
||||
|
||||
if (count != 0) {
|
||||
ret = False;
|
||||
printf("%d levels failed\n", count);
|
||||
if (count > 10) {
|
||||
printf("too many level failures - giving up\n");
|
||||
goto done;
|
||||
}
|
||||
}
|
||||
|
||||
/* check for correct aliases */
|
||||
s1 = find("SIZE_INFO");
|
||||
s2 = find("SIZE_INFORMATION");
|
||||
if (s1 && s2) {
|
||||
VAL_EQUAL(size_info, total_alloc_units, size_info, total_alloc_units);
|
||||
VAL_EQUAL(size_info, avail_alloc_units, size_info, avail_alloc_units);
|
||||
VAL_EQUAL(size_info, sectors_per_unit, size_info, sectors_per_unit);
|
||||
VAL_EQUAL(size_info, bytes_per_sector, size_info, bytes_per_sector);
|
||||
}
|
||||
|
||||
s1 = find("DEVICE_INFO");
|
||||
s2 = find("DEVICE_INFORMATION");
|
||||
if (s1 && s2) {
|
||||
VAL_EQUAL(device_info, device_type, device_info, device_type);
|
||||
VAL_EQUAL(device_info, characteristics, device_info, characteristics);
|
||||
}
|
||||
|
||||
s1 = find("VOLUME_INFO");
|
||||
s2 = find("VOLUME_INFORMATION");
|
||||
if (s1 && s2) {
|
||||
STRUCT_EQUAL(volume_info, create_time, volume_info, create_time);
|
||||
VAL_EQUAL (volume_info, serial_number, volume_info, serial_number);
|
||||
STR_EQUAL (volume_info, volume_name.s, volume_info, volume_name.s);
|
||||
printf("volume_info.volume_name = '%s'\n", s1->volume_info.out.volume_name.s);
|
||||
}
|
||||
|
||||
s1 = find("ATTRIBUTE_INFO");
|
||||
s2 = find("ATTRIBUTE_INFORMATION");
|
||||
if (s1 && s2) {
|
||||
VAL_EQUAL(attribute_info, fs_attr,
|
||||
attribute_info, fs_attr);
|
||||
VAL_EQUAL(attribute_info, max_file_component_length,
|
||||
attribute_info, max_file_component_length);
|
||||
STR_EQUAL(attribute_info, fs_type.s, attribute_info, fs_type.s);
|
||||
printf("attribute_info.fs_type = '%s'\n", s1->attribute_info.out.fs_type.s);
|
||||
}
|
||||
|
||||
/* check for consistent disk sizes */
|
||||
s1 = find("DSKATTR");
|
||||
s2 = find("ALLOCATION");
|
||||
if (s1 && s2) {
|
||||
double size1, size2;
|
||||
double scale = s1->dskattr.out.blocks_per_unit * s1->dskattr.out.block_size;
|
||||
size1 = 1.0 *
|
||||
s1->dskattr.out.units_total *
|
||||
s1->dskattr.out.blocks_per_unit *
|
||||
s1->dskattr.out.block_size / scale;
|
||||
size2 = 1.0 *
|
||||
s2->allocation.out.sectors_per_unit *
|
||||
s2->allocation.out.total_alloc_units *
|
||||
s2->allocation.out.bytes_per_sector / scale;
|
||||
if (ABS(size1 - size2) > 1) {
|
||||
printf("Inconsistent total size in DSKATTR and ALLOCATION - size1=%.0f size2=%.0f\n",
|
||||
size1, size2);
|
||||
ret = False;
|
||||
}
|
||||
printf("total disk = %.0f MB\n", size1*scale/1.0e6);
|
||||
}
|
||||
|
||||
/* and for consistent free disk space */
|
||||
s1 = find("DSKATTR");
|
||||
s2 = find("ALLOCATION");
|
||||
if (s1 && s2) {
|
||||
double size1, size2;
|
||||
double scale = s1->dskattr.out.blocks_per_unit * s1->dskattr.out.block_size;
|
||||
size1 = 1.0 *
|
||||
s1->dskattr.out.units_free *
|
||||
s1->dskattr.out.blocks_per_unit *
|
||||
s1->dskattr.out.block_size / scale;
|
||||
size2 = 1.0 *
|
||||
s2->allocation.out.sectors_per_unit *
|
||||
s2->allocation.out.avail_alloc_units *
|
||||
s2->allocation.out.bytes_per_sector / scale;
|
||||
if (ABS(size1 - size2) > 1) {
|
||||
printf("Inconsistent avail size in DSKATTR and ALLOCATION - size1=%.0f size2=%.0f\n",
|
||||
size1, size2);
|
||||
ret = False;
|
||||
}
|
||||
printf("free disk = %.0f MB\n", size1*scale/1.0e6);
|
||||
}
|
||||
|
||||
/* volume info consistency */
|
||||
s1 = find("VOLUME");
|
||||
s2 = find("VOLUME_INFO");
|
||||
if (s1 && s2) {
|
||||
VAL_EQUAL(volume, serial_number, volume_info, serial_number);
|
||||
STR_EQUAL(volume, volume_name.s, volume_info, volume_name.s);
|
||||
}
|
||||
|
||||
/* disk size consistency - notice that 'avail_alloc_units' maps to the caller
|
||||
available allocation units, not the total */
|
||||
s1 = find("SIZE_INFO");
|
||||
s2 = find("FULL_SIZE_INFORMATION");
|
||||
if (s1 && s2) {
|
||||
VAL_EQUAL(size_info, total_alloc_units, full_size_information, total_alloc_units);
|
||||
VAL_EQUAL(size_info, avail_alloc_units, full_size_information, call_avail_alloc_units);
|
||||
VAL_EQUAL(size_info, sectors_per_unit, full_size_information, sectors_per_unit);
|
||||
VAL_EQUAL(size_info, bytes_per_sector, full_size_information, bytes_per_sector);
|
||||
}
|
||||
|
||||
/* check for non-zero unknown fields - if we find them
|
||||
they might give us some hints */
|
||||
s1 = find("QUOTA_INFORMATION");
|
||||
if (s1) {
|
||||
VAL_UNKNOWN(quota_information, unknown[0]);
|
||||
VAL_UNKNOWN(quota_information, unknown[1]);
|
||||
VAL_UNKNOWN(quota_information, unknown[2]);
|
||||
}
|
||||
|
||||
s1 = find("OBJECTID_INFORMATION");
|
||||
if (s1) {
|
||||
VAL_UNKNOWN(objectid_information, unknown[0]);
|
||||
VAL_UNKNOWN(objectid_information, unknown[1]);
|
||||
VAL_UNKNOWN(objectid_information, unknown[2]);
|
||||
VAL_UNKNOWN(objectid_information, unknown[3]);
|
||||
VAL_UNKNOWN(objectid_information, unknown[4]);
|
||||
VAL_UNKNOWN(objectid_information, unknown[5]);
|
||||
}
|
||||
|
||||
|
||||
#define STR_CHECK(sname, stype, field, flags) do { \
|
||||
s1 = find(sname); \
|
||||
if (s1) { \
|
||||
if (wire_bad_flags(&s1->stype.out.field, flags)) { \
|
||||
printf("(%d) incorrect string termination in %s/%s\n", \
|
||||
__LINE__, #stype, #field); \
|
||||
ret = False; \
|
||||
} \
|
||||
}} while (0)
|
||||
|
||||
/* check for correct termination */
|
||||
STR_CHECK("VOLUME", volume, volume_name, 0);
|
||||
STR_CHECK("VOLUME_INFO", volume_info, volume_name, STR_UNICODE);
|
||||
STR_CHECK("VOLUME_INFORMATION", volume_info, volume_name, STR_UNICODE);
|
||||
STR_CHECK("ATTRIBUTE_INFO", attribute_info, fs_type, STR_UNICODE);
|
||||
STR_CHECK("ATTRIBUTE_INFORMATION", attribute_info, fs_type, STR_UNICODE);
|
||||
|
||||
done:
|
||||
torture_close_connection(cli);
|
||||
talloc_destroy(mem_ctx);
|
||||
return ret;
|
||||
}
|
@ -1,526 +0,0 @@
|
||||
/*
|
||||
Unix SMB/CIFS implementation.
|
||||
SMB client
|
||||
Copyright (C) Andrew Tridgell 1994-1998
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
|
||||
#include "includes.h"
|
||||
|
||||
#ifndef REGISTER
|
||||
#define REGISTER 0
|
||||
#endif
|
||||
|
||||
extern file_info def_finfo;
|
||||
|
||||
#define CNV_LANG(s) dos2unix_format(s,False)
|
||||
#define CNV_INPUT(s) unix2dos_format(s,True)
|
||||
|
||||
static struct cli_state smbcli;
|
||||
struct cli_state *smb_cli = &smbcli;
|
||||
|
||||
FILE *out_hnd;
|
||||
|
||||
static pstring password; /* local copy only, if one is entered */
|
||||
|
||||
/****************************************************************************
|
||||
initialise smb client structure
|
||||
****************************************************************************/
|
||||
void rpcclient_init(void)
|
||||
{
|
||||
memset((char *)smb_cli, '\0', sizeof(smb_cli));
|
||||
cli_initialise(smb_cli);
|
||||
smb_cli->capabilities |= CAP_NT_SMBS;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
make smb client connection
|
||||
****************************************************************************/
|
||||
static BOOL rpcclient_connect(struct client_info *info)
|
||||
{
|
||||
struct nmb_name calling;
|
||||
struct nmb_name called;
|
||||
|
||||
make_nmb_name(&called , dns_to_netbios_name(info->dest_host ), info->name_type);
|
||||
make_nmb_name(&calling, dns_to_netbios_name(info->myhostname), 0x0);
|
||||
|
||||
if (!cli_establish_connection(smb_cli,
|
||||
info->dest_host, &info->dest_ip,
|
||||
&calling, &called,
|
||||
info->share, info->svc_type,
|
||||
False, True))
|
||||
{
|
||||
DEBUG(0,("rpcclient_connect: connection failed\n"));
|
||||
cli_shutdown(smb_cli);
|
||||
return False;
|
||||
}
|
||||
|
||||
return True;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
stop the smb connection(s?)
|
||||
****************************************************************************/
|
||||
static void rpcclient_stop(void)
|
||||
{
|
||||
cli_shutdown(smb_cli);
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
log in as an nt user, log out again.
|
||||
****************************************************************************/
|
||||
void run_enums_test(int num_ops, struct client_info *cli_info, struct cli_state *cli)
|
||||
{
|
||||
pstring cmd;
|
||||
int i;
|
||||
|
||||
/* establish connections. nothing to stop these being re-established. */
|
||||
rpcclient_connect(cli_info);
|
||||
|
||||
DEBUG(5,("rpcclient_connect: cli->fd:%d\n", cli->fd));
|
||||
if (cli->fd <= 0)
|
||||
{
|
||||
fprintf(out_hnd, "warning: connection could not be established to %s<%02x>\n",
|
||||
cli_info->dest_host, cli_info->name_type);
|
||||
return;
|
||||
}
|
||||
|
||||
for (i = 0; i < num_ops; i++)
|
||||
{
|
||||
set_first_token("");
|
||||
cmd_srv_enum_sess(cli_info);
|
||||
set_first_token("");
|
||||
cmd_srv_enum_shares(cli_info);
|
||||
set_first_token("");
|
||||
cmd_srv_enum_files(cli_info);
|
||||
|
||||
if (password[0] != 0)
|
||||
{
|
||||
slprintf(cmd, sizeof(cmd)-1, "1");
|
||||
set_first_token(cmd);
|
||||
}
|
||||
else
|
||||
{
|
||||
set_first_token("");
|
||||
}
|
||||
cmd_srv_enum_conn(cli_info);
|
||||
}
|
||||
|
||||
rpcclient_stop();
|
||||
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
log in as an nt user, log out again.
|
||||
****************************************************************************/
|
||||
void run_ntlogin_test(int num_ops, struct client_info *cli_info, struct cli_state *cli)
|
||||
{
|
||||
pstring cmd;
|
||||
int i;
|
||||
|
||||
/* establish connections. nothing to stop these being re-established. */
|
||||
rpcclient_connect(cli_info);
|
||||
|
||||
DEBUG(5,("rpcclient_connect: cli->fd:%d\n", cli->fd));
|
||||
if (cli->fd <= 0)
|
||||
{
|
||||
fprintf(out_hnd, "warning: connection could not be established to %s<%02x>\n",
|
||||
cli_info->dest_host, cli_info->name_type);
|
||||
return;
|
||||
}
|
||||
|
||||
for (i = 0; i < num_ops; i++)
|
||||
{
|
||||
slprintf(cmd, sizeof(cmd)-1, "%s %s", cli->user_name, password);
|
||||
set_first_token(cmd);
|
||||
|
||||
cmd_netlogon_login_test(cli_info);
|
||||
}
|
||||
|
||||
rpcclient_stop();
|
||||
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
runs n simultaneous functions.
|
||||
****************************************************************************/
|
||||
static void create_procs(int nprocs, int numops,
|
||||
struct client_info *cli_info, struct cli_state *cli,
|
||||
void (*fn)(int, struct client_info *, struct cli_state *))
|
||||
{
|
||||
int i, status;
|
||||
|
||||
for (i=0;i<nprocs;i++)
|
||||
{
|
||||
if (fork() == 0)
|
||||
{
|
||||
pid_t mypid = getpid();
|
||||
sys_srandom(mypid ^ time(NULL));
|
||||
fn(numops, cli_info, cli);
|
||||
fflush(out_hnd);
|
||||
_exit(0);
|
||||
}
|
||||
}
|
||||
|
||||
for (i=0;i<nprocs;i++)
|
||||
{
|
||||
waitpid(0, &status, 0);
|
||||
}
|
||||
}
|
||||
/****************************************************************************
|
||||
usage on the program - OUT OF DATE!
|
||||
****************************************************************************/
|
||||
static void usage(char *pname)
|
||||
{
|
||||
fprintf(out_hnd, "Usage: %s service <password> [-d debuglevel] [-l log] ",
|
||||
pname);
|
||||
|
||||
fprintf(out_hnd, "\nVersion %s\n",VERSION);
|
||||
fprintf(out_hnd, "\t-d debuglevel set the debuglevel\n");
|
||||
fprintf(out_hnd, "\t-l log basename. Basename for log/debug files\n");
|
||||
fprintf(out_hnd, "\t-n netbios name. Use this name as my netbios name\n");
|
||||
fprintf(out_hnd, "\t-m max protocol set the max protocol level\n");
|
||||
fprintf(out_hnd, "\t-I dest IP use this IP to connect to\n");
|
||||
fprintf(out_hnd, "\t-E write messages to stderr instead of stdout\n");
|
||||
fprintf(out_hnd, "\t-U username set the network username\n");
|
||||
fprintf(out_hnd, "\t-W workgroup set the workgroup name\n");
|
||||
fprintf(out_hnd, "\t-t terminal code terminal i/o code {sjis|euc|jis7|jis8|junet|hex}\n");
|
||||
fprintf(out_hnd, "\n");
|
||||
}
|
||||
|
||||
enum client_action
|
||||
{
|
||||
CLIENT_NONE,
|
||||
CLIENT_IPC,
|
||||
CLIENT_SVC
|
||||
};
|
||||
|
||||
/****************************************************************************
|
||||
main program
|
||||
****************************************************************************/
|
||||
int main(int argc,char *argv[])
|
||||
{
|
||||
char *pname = argv[0];
|
||||
int opt;
|
||||
extern char *optarg;
|
||||
extern int optind;
|
||||
pstring term_code;
|
||||
BOOL got_pass = False;
|
||||
char *cmd_str="";
|
||||
enum client_action cli_action = CLIENT_NONE;
|
||||
int nprocs = 1;
|
||||
int numops = 100;
|
||||
pstring logfile;
|
||||
|
||||
struct client_info cli_info;
|
||||
|
||||
out_hnd = stdout;
|
||||
|
||||
rpcclient_init();
|
||||
|
||||
#ifdef KANJI
|
||||
pstrcpy(term_code, KANJI);
|
||||
#else /* KANJI */
|
||||
*term_code = 0;
|
||||
#endif /* KANJI */
|
||||
|
||||
if (!lp_load(dyn_CONFIGFILE,True, False, False))
|
||||
{
|
||||
fprintf(stderr, "Can't load %s - run testparm to debug it\n", dyn_CONFIGFILE);
|
||||
}
|
||||
|
||||
DEBUGLEVEL = 0;
|
||||
|
||||
cli_info.put_total_size = 0;
|
||||
cli_info.put_total_time_ms = 0;
|
||||
cli_info.get_total_size = 0;
|
||||
cli_info.get_total_time_ms = 0;
|
||||
|
||||
cli_info.dir_total = 0;
|
||||
cli_info.newer_than = 0;
|
||||
cli_info.archive_level = 0;
|
||||
cli_info.print_mode = 1;
|
||||
|
||||
cli_info.translation = False;
|
||||
cli_info.recurse_dir = False;
|
||||
cli_info.lowercase = False;
|
||||
cli_info.prompt = True;
|
||||
cli_info.abort_mget = True;
|
||||
|
||||
cli_info.dest_ip.s_addr = 0;
|
||||
cli_info.name_type = 0x20;
|
||||
|
||||
pstrcpy(cli_info.cur_dir , "\\");
|
||||
pstrcpy(cli_info.file_sel, "");
|
||||
pstrcpy(cli_info.base_dir, "");
|
||||
pstrcpy(smb_cli->domain, "");
|
||||
pstrcpy(smb_cli->user_name, "");
|
||||
pstrcpy(cli_info.myhostname, "");
|
||||
pstrcpy(cli_info.dest_host, "");
|
||||
|
||||
pstrcpy(cli_info.svc_type, "A:");
|
||||
pstrcpy(cli_info.share, "");
|
||||
pstrcpy(cli_info.service, "");
|
||||
|
||||
ZERO_STRUCT(cli_info.dom.level3_sid);
|
||||
pstrcpy(cli_info.dom.level3_dom, "");
|
||||
ZERO_STRUCT(cli_info.dom.level5_sid);
|
||||
pstrcpy(cli_info.dom.level5_dom, "");
|
||||
|
||||
smb_cli->nt_pipe_fnum = 0xffff;
|
||||
|
||||
setup_logging(pname, DEBUG_STDOUT);
|
||||
|
||||
password[0] = 0;
|
||||
|
||||
if (argc < 2)
|
||||
{
|
||||
usage(pname);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if (*argv[1] != '-')
|
||||
{
|
||||
pstrcpy(cli_info.service, argv[1]);
|
||||
/* Convert any '/' characters in the service name to '\' characters */
|
||||
string_replace( cli_info.service, '/','\\');
|
||||
argc--;
|
||||
argv++;
|
||||
|
||||
DEBUG(1,("service: %s\n", cli_info.service));
|
||||
|
||||
if (count_chars(cli_info.service,'\\') < 3)
|
||||
{
|
||||
usage(pname);
|
||||
printf("\n%s: Not enough '\\' characters in service\n", cli_info.service);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
/*
|
||||
if (count_chars(cli_info.service,'\\') > 3)
|
||||
{
|
||||
usage(pname);
|
||||
printf("\n%s: Too many '\\' characters in service\n", cli_info.service);
|
||||
exit(1);
|
||||
}
|
||||
*/
|
||||
|
||||
if (argc > 1 && (*argv[1] != '-'))
|
||||
{
|
||||
got_pass = True;
|
||||
pstrcpy(password,argv[1]);
|
||||
memset(argv[1],'X',strlen(argv[1]));
|
||||
argc--;
|
||||
argv++;
|
||||
}
|
||||
|
||||
cli_action = CLIENT_SVC;
|
||||
}
|
||||
|
||||
while ((opt = getopt(argc, argv,"s:O:M:S:i:N:o:n:d:l:hI:EB:U:L:t:m:W:T:D:c:")) != EOF)
|
||||
{
|
||||
switch (opt)
|
||||
{
|
||||
case 'm':
|
||||
{
|
||||
/* FIXME ... max_protocol seems to be funny here */
|
||||
|
||||
int max_protocol = 0;
|
||||
max_protocol = interpret_protocol(optarg,max_protocol);
|
||||
fprintf(stderr, "max protocol not currently supported\n");
|
||||
break;
|
||||
}
|
||||
|
||||
case 'O':
|
||||
lp_set_cmdline("socket options", optarg);
|
||||
break;
|
||||
|
||||
case 'S':
|
||||
{
|
||||
pstrcpy(cli_info.dest_host,optarg);
|
||||
strupper(cli_info.dest_host);
|
||||
cli_action = CLIENT_IPC;
|
||||
break;
|
||||
}
|
||||
|
||||
case 'i':
|
||||
{
|
||||
pstrcpy(scope, optarg);
|
||||
break;
|
||||
}
|
||||
|
||||
case 'U':
|
||||
{
|
||||
char *lp;
|
||||
pstrcpy(smb_cli->user_name,optarg);
|
||||
if ((lp=strchr_m(smb_cli->user_name,'%')))
|
||||
{
|
||||
*lp = 0;
|
||||
pstrcpy(password,lp+1);
|
||||
got_pass = True;
|
||||
memset(strchr_m(optarg,'%')+1,'X',strlen(password));
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case 'W':
|
||||
{
|
||||
pstrcpy(smb_cli->domain,optarg);
|
||||
break;
|
||||
}
|
||||
|
||||
case 'E':
|
||||
{
|
||||
dbf = x_stderr;
|
||||
break;
|
||||
}
|
||||
|
||||
case 'I':
|
||||
{
|
||||
cli_info.dest_ip = *interpret_addr2(optarg);
|
||||
if (is_zero_ip(cli_info.dest_ip))
|
||||
{
|
||||
exit(1);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case 'N':
|
||||
{
|
||||
nprocs = atoi(optarg);
|
||||
break;
|
||||
}
|
||||
|
||||
case 'o':
|
||||
{
|
||||
numops = atoi(optarg);
|
||||
break;
|
||||
}
|
||||
|
||||
case 'n':
|
||||
lp_set_cmdline("netbios name", optarg);
|
||||
break;
|
||||
|
||||
case 'd':
|
||||
{
|
||||
if (*optarg == 'A')
|
||||
DEBUGLEVEL = 10000;
|
||||
else
|
||||
DEBUGLEVEL = atoi(optarg);
|
||||
break;
|
||||
}
|
||||
|
||||
case 'l':
|
||||
{
|
||||
slprintf(logfile, sizeof(logfile)-1,
|
||||
"%s.client",optarg);
|
||||
lp_set_logfile(logfile);
|
||||
break;
|
||||
}
|
||||
|
||||
case 'c':
|
||||
{
|
||||
cmd_str = optarg;
|
||||
got_pass = True;
|
||||
break;
|
||||
}
|
||||
|
||||
case 'h':
|
||||
{
|
||||
usage(pname);
|
||||
exit(0);
|
||||
break;
|
||||
}
|
||||
|
||||
case 's':
|
||||
{
|
||||
pstrcpy(dyn_CONFIGFILE, optarg);
|
||||
break;
|
||||
}
|
||||
|
||||
case 't':
|
||||
{
|
||||
pstrcpy(term_code, optarg);
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
{
|
||||
usage(pname);
|
||||
exit(1);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (cli_action == CLIENT_NONE)
|
||||
{
|
||||
usage(pname);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
fstrcpy(cli_info.myhostname, lp_netbios_name());
|
||||
|
||||
DEBUG(3,("%s client started (version %s)\n",timestring(False),VERSION));
|
||||
|
||||
if (*smb_cli->domain == 0)
|
||||
{
|
||||
pstrcpy(smb_cli->domain,lp_workgroup());
|
||||
}
|
||||
strupper(smb_cli->domain);
|
||||
|
||||
load_interfaces();
|
||||
|
||||
if (cli_action == CLIENT_IPC)
|
||||
{
|
||||
pstrcpy(cli_info.share, "IPC$");
|
||||
pstrcpy(cli_info.svc_type, "IPC");
|
||||
}
|
||||
|
||||
fstrcpy(cli_info.mach_acct, cli_info.myhostname);
|
||||
strupper(cli_info.mach_acct);
|
||||
fstrcat(cli_info.mach_acct, "$");
|
||||
|
||||
/* set the password cache info */
|
||||
if (got_pass)
|
||||
{
|
||||
if (password[0] == 0)
|
||||
{
|
||||
pwd_set_nullpwd(&(smb_cli->pwd));
|
||||
}
|
||||
else
|
||||
{
|
||||
pwd_make_lm_nt_16(&(smb_cli->pwd), password); /* generate 16 byte hashes */
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
char *pwd = getpass("Enter Password:");
|
||||
safe_strcpy(password, pwd, sizeof(password));
|
||||
pwd_make_lm_nt_16(&(smb_cli->pwd), password); /* generate 16 byte hashes */
|
||||
}
|
||||
|
||||
create_procs(nprocs, numops, &cli_info, smb_cli, run_enums_test);
|
||||
|
||||
if (password[0] != 0)
|
||||
{
|
||||
create_procs(nprocs, numops, &cli_info, smb_cli, run_ntlogin_test);
|
||||
}
|
||||
|
||||
fflush(out_hnd);
|
||||
|
||||
return(0);
|
||||
}
|
@ -1,471 +0,0 @@
|
||||
/*
|
||||
Unix SMB/CIFS implementation.
|
||||
RAW_SFILEINFO_* individual test suite
|
||||
Copyright (C) Andrew Tridgell 2003
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
|
||||
#include "includes.h"
|
||||
|
||||
/* basic testing of all RAW_SFILEINFO_* calls
|
||||
for each call we test that it succeeds, and where possible test
|
||||
for consistency between the calls.
|
||||
*/
|
||||
BOOL torture_sfileinfo(int dummy)
|
||||
{
|
||||
struct cli_state *cli;
|
||||
BOOL ret = True;
|
||||
TALLOC_CTX *mem_ctx;
|
||||
int fnum = -1;
|
||||
const char *fnum_fname = "\\torture_sfileinfo.txt";
|
||||
const char *fnum_fname_new = "\\torture_sfileinfo-new.txt";
|
||||
const char *path_fname = "\\torture_spathinfo13.txt";
|
||||
const char *path_fname_new = "\\torture_spathinfo-new.txt";
|
||||
union smb_fileinfo finfo1, finfo2;
|
||||
union smb_setfileinfo sfinfo;
|
||||
NTSTATUS status, status2;
|
||||
const char *call_name;
|
||||
time_t basetime = (time(NULL) - 86400) & ~1;
|
||||
BOOL check_fnum;
|
||||
|
||||
if (!torture_open_connection(&cli)) {
|
||||
return False;
|
||||
}
|
||||
|
||||
mem_ctx = talloc_init("torture_sfileinfo");
|
||||
|
||||
#define RECREATE_FILE(fname) do { \
|
||||
if (fnum != -1) cli_close(cli, fnum); \
|
||||
fnum = create_complex_file(cli, mem_ctx, fname); \
|
||||
if (fnum == -1) { \
|
||||
printf("(%d) ERROR: open of %s failed (%s)\n", \
|
||||
__LINE__, fname, cli_errstr(cli)); \
|
||||
ret = False; \
|
||||
goto done; \
|
||||
}} while (0)
|
||||
|
||||
#define RECREATE_BOTH do { \
|
||||
RECREATE_FILE(path_fname); \
|
||||
cli_close(cli, fnum); \
|
||||
RECREATE_FILE(fnum_fname); \
|
||||
} while (0)
|
||||
|
||||
RECREATE_BOTH;
|
||||
|
||||
#define CHECK_CALL_FNUM(call, rightstatus) do { \
|
||||
check_fnum = True; \
|
||||
call_name = #call; \
|
||||
sfinfo.generic.level = RAW_SFILEINFO_ ## call; \
|
||||
sfinfo.generic.file.fnum = fnum; \
|
||||
status = smb_raw_setfileinfo(cli->tree, &sfinfo); \
|
||||
if (!NT_STATUS_EQUAL(status, rightstatus)) { \
|
||||
printf("(%d) %s - %s (should be %s)\n", __LINE__, #call, \
|
||||
nt_errstr(status), nt_errstr(rightstatus)); \
|
||||
ret = False; \
|
||||
} \
|
||||
finfo1.generic.level = RAW_FILEINFO_ALL_INFO; \
|
||||
finfo1.generic.in.fnum = fnum; \
|
||||
status2 = smb_raw_fileinfo(cli->tree, mem_ctx, &finfo1); \
|
||||
if (!NT_STATUS_IS_OK(status2)) { \
|
||||
printf("(%d) %s pathinfo - %s\n", __LINE__, #call, nt_errstr(status)); \
|
||||
ret = False; \
|
||||
}} while (0)
|
||||
|
||||
#define CHECK_CALL_PATH(call, rightstatus) do { \
|
||||
check_fnum = False; \
|
||||
call_name = #call; \
|
||||
sfinfo.generic.level = RAW_SFILEINFO_ ## call; \
|
||||
sfinfo.generic.file.fname = path_fname; \
|
||||
status = smb_raw_setpathinfo(cli->tree, &sfinfo); \
|
||||
if (NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) { \
|
||||
sfinfo.generic.file.fname = path_fname_new; \
|
||||
status = smb_raw_setpathinfo(cli->tree, &sfinfo); \
|
||||
} \
|
||||
if (!NT_STATUS_EQUAL(status, rightstatus)) { \
|
||||
printf("(%d) %s - %s (should be %s)\n", __LINE__, #call, \
|
||||
nt_errstr(status), nt_errstr(rightstatus)); \
|
||||
ret = False; \
|
||||
} \
|
||||
finfo1.generic.level = RAW_FILEINFO_ALL_INFO; \
|
||||
finfo1.generic.in.fname = path_fname; \
|
||||
status2 = smb_raw_pathinfo(cli->tree, mem_ctx, &finfo1); \
|
||||
if (NT_STATUS_EQUAL(status2, NT_STATUS_OBJECT_NAME_NOT_FOUND)) { \
|
||||
finfo1.generic.in.fname = path_fname_new; \
|
||||
status2 = smb_raw_pathinfo(cli->tree, mem_ctx, &finfo1); \
|
||||
} \
|
||||
if (!NT_STATUS_IS_OK(status2)) { \
|
||||
printf("(%d) %s pathinfo - %s\n", __LINE__, #call, nt_errstr(status2)); \
|
||||
ret = False; \
|
||||
}} while (0)
|
||||
|
||||
#define CHECK1(call) \
|
||||
do { if (NT_STATUS_IS_OK(status)) { \
|
||||
finfo2.generic.level = RAW_FILEINFO_ ## call; \
|
||||
if (check_fnum) { \
|
||||
finfo2.generic.in.fnum = fnum; \
|
||||
status2 = smb_raw_fileinfo(cli->tree, mem_ctx, &finfo2); \
|
||||
} else { \
|
||||
finfo2.generic.in.fname = path_fname; \
|
||||
status2 = smb_raw_pathinfo(cli->tree, mem_ctx, &finfo2); \
|
||||
if (NT_STATUS_EQUAL(status2, NT_STATUS_OBJECT_NAME_NOT_FOUND)) { \
|
||||
finfo2.generic.in.fname = path_fname_new; \
|
||||
status2 = smb_raw_pathinfo(cli->tree, mem_ctx, &finfo2); \
|
||||
} \
|
||||
} \
|
||||
if (!NT_STATUS_IS_OK(status2)) { \
|
||||
printf("%s - %s\n", #call, nt_errstr(status2)); \
|
||||
} \
|
||||
}} while (0)
|
||||
|
||||
#define CHECK_VALUE(call, stype, field, value) do { \
|
||||
CHECK1(call); \
|
||||
if (NT_STATUS_IS_OK(status) && finfo2.stype.out.field != value) { \
|
||||
printf("(%d) %s - %s/%s should be 0x%x - 0x%x\n", __LINE__, \
|
||||
call_name, #stype, #field, \
|
||||
(uint_t)value, (uint_t)finfo2.stype.out.field); \
|
||||
dump_all_info(mem_ctx, &finfo1); \
|
||||
}} while (0)
|
||||
|
||||
#define CHECK_TIME(call, stype, field, value) do { \
|
||||
CHECK1(call); \
|
||||
if (NT_STATUS_IS_OK(status) && nt_time_to_unix(&finfo2.stype.out.field) != value) { \
|
||||
printf("(%d) %s - %s/%s should be 0x%x - 0x%x\n", __LINE__, \
|
||||
call_name, #stype, #field, \
|
||||
(uint_t)value, \
|
||||
(uint_t)nt_time_to_unix(&finfo2.stype.out.field)); \
|
||||
printf("\t%s", http_timestring(value)); \
|
||||
printf("\t%s\n", nt_time_string(mem_ctx, &finfo2.stype.out.field)); \
|
||||
dump_all_info(mem_ctx, &finfo1); \
|
||||
}} while (0)
|
||||
|
||||
#define CHECK_STR(call, stype, field, value) do { \
|
||||
CHECK1(call); \
|
||||
if (NT_STATUS_IS_OK(status) && strcmp(finfo2.stype.out.field, value) != 0) { \
|
||||
printf("(%d) %s - %s/%s should be '%s' - '%s'\n", __LINE__, \
|
||||
call_name, #stype, #field, \
|
||||
value, \
|
||||
finfo2.stype.out.field); \
|
||||
dump_all_info(mem_ctx, &finfo1); \
|
||||
}} while (0)
|
||||
|
||||
/* test setattr */
|
||||
sfinfo.setattr.in.attrib = FILE_ATTRIBUTE_READONLY;
|
||||
sfinfo.setattr.in.write_time = basetime;
|
||||
CHECK_CALL_PATH(SETATTR, NT_STATUS_OK);
|
||||
CHECK_VALUE (ALL_INFO, all_info, attrib, FILE_ATTRIBUTE_READONLY);
|
||||
CHECK_TIME (ALL_INFO, all_info, write_time, basetime);
|
||||
|
||||
/* a zero write_time means don't change */
|
||||
sfinfo.setattr.in.attrib = 0;
|
||||
sfinfo.setattr.in.write_time = 0;
|
||||
CHECK_CALL_PATH(SETATTR, NT_STATUS_OK);
|
||||
CHECK_VALUE(ALL_INFO, all_info, attrib, FILE_ATTRIBUTE_NORMAL);
|
||||
CHECK_TIME (ALL_INFO, all_info, write_time, basetime);
|
||||
|
||||
/* test setattre */
|
||||
sfinfo.setattre.in.create_time = basetime + 20;
|
||||
sfinfo.setattre.in.access_time = basetime + 30;
|
||||
sfinfo.setattre.in.write_time = basetime + 40;
|
||||
CHECK_CALL_FNUM(SETATTRE, NT_STATUS_OK);
|
||||
CHECK_TIME(ALL_INFO, all_info, create_time, basetime + 20);
|
||||
CHECK_TIME(ALL_INFO, all_info, access_time, basetime + 30);
|
||||
CHECK_TIME(ALL_INFO, all_info, write_time, basetime + 40);
|
||||
|
||||
sfinfo.setattre.in.create_time = 0;
|
||||
sfinfo.setattre.in.access_time = 0;
|
||||
sfinfo.setattre.in.write_time = 0;
|
||||
CHECK_CALL_FNUM(SETATTRE, NT_STATUS_OK);
|
||||
CHECK_TIME(ALL_INFO, all_info, create_time, basetime + 20);
|
||||
CHECK_TIME(ALL_INFO, all_info, access_time, basetime + 30);
|
||||
CHECK_TIME(ALL_INFO, all_info, write_time, basetime + 40);
|
||||
|
||||
/* test standard level */
|
||||
sfinfo.standard.in.create_time = basetime + 100;
|
||||
sfinfo.standard.in.access_time = basetime + 200;
|
||||
sfinfo.standard.in.write_time = basetime + 300;
|
||||
CHECK_CALL_FNUM(STANDARD, NT_STATUS_OK);
|
||||
CHECK_TIME(ALL_INFO, all_info, create_time, basetime + 100);
|
||||
CHECK_TIME(ALL_INFO, all_info, access_time, basetime + 200);
|
||||
CHECK_TIME(ALL_INFO, all_info, write_time, basetime + 300);
|
||||
|
||||
/* test basic_info level */
|
||||
basetime += 86400;
|
||||
unix_to_nt_time(&sfinfo.basic_info.in.create_time, basetime + 100);
|
||||
unix_to_nt_time(&sfinfo.basic_info.in.access_time, basetime + 200);
|
||||
unix_to_nt_time(&sfinfo.basic_info.in.write_time, basetime + 300);
|
||||
unix_to_nt_time(&sfinfo.basic_info.in.change_time, basetime + 400);
|
||||
sfinfo.basic_info.in.attrib = FILE_ATTRIBUTE_READONLY;
|
||||
CHECK_CALL_FNUM(BASIC_INFO, NT_STATUS_OK);
|
||||
CHECK_TIME(ALL_INFO, all_info, create_time, basetime + 100);
|
||||
CHECK_TIME(ALL_INFO, all_info, access_time, basetime + 200);
|
||||
CHECK_TIME(ALL_INFO, all_info, write_time, basetime + 300);
|
||||
CHECK_TIME(ALL_INFO, all_info, change_time, basetime + 400);
|
||||
CHECK_VALUE(ALL_INFO, all_info, attrib, FILE_ATTRIBUTE_READONLY);
|
||||
|
||||
/* a zero time means don't change */
|
||||
unix_to_nt_time(&sfinfo.basic_info.in.create_time, 0);
|
||||
unix_to_nt_time(&sfinfo.basic_info.in.access_time, 0);
|
||||
unix_to_nt_time(&sfinfo.basic_info.in.write_time, 0);
|
||||
unix_to_nt_time(&sfinfo.basic_info.in.change_time, 0);
|
||||
sfinfo.basic_info.in.attrib = FILE_ATTRIBUTE_NORMAL;
|
||||
CHECK_CALL_FNUM(BASIC_INFO, NT_STATUS_OK);
|
||||
CHECK_TIME(ALL_INFO, all_info, create_time, basetime + 100);
|
||||
CHECK_TIME(ALL_INFO, all_info, access_time, basetime + 200);
|
||||
CHECK_TIME(ALL_INFO, all_info, write_time, basetime + 300);
|
||||
CHECK_TIME(ALL_INFO, all_info, change_time, basetime + 400);
|
||||
CHECK_VALUE(ALL_INFO, all_info, attrib, FILE_ATTRIBUTE_NORMAL);
|
||||
|
||||
/* test basic_information level */
|
||||
basetime += 86400;
|
||||
unix_to_nt_time(&sfinfo.basic_info.in.create_time, basetime + 100);
|
||||
unix_to_nt_time(&sfinfo.basic_info.in.access_time, basetime + 200);
|
||||
unix_to_nt_time(&sfinfo.basic_info.in.write_time, basetime + 300);
|
||||
unix_to_nt_time(&sfinfo.basic_info.in.change_time, basetime + 400);
|
||||
sfinfo.basic_info.in.attrib = FILE_ATTRIBUTE_READONLY;
|
||||
CHECK_CALL_FNUM(BASIC_INFORMATION, NT_STATUS_OK);
|
||||
CHECK_TIME(ALL_INFO, all_info, create_time, basetime + 100);
|
||||
CHECK_TIME(ALL_INFO, all_info, access_time, basetime + 200);
|
||||
CHECK_TIME(ALL_INFO, all_info, write_time, basetime + 300);
|
||||
CHECK_TIME(ALL_INFO, all_info, change_time, basetime + 400);
|
||||
CHECK_VALUE(ALL_INFO, all_info, attrib, FILE_ATTRIBUTE_READONLY);
|
||||
|
||||
CHECK_CALL_PATH(BASIC_INFORMATION, NT_STATUS_OK);
|
||||
CHECK_TIME(ALL_INFO, all_info, create_time, basetime + 100);
|
||||
CHECK_TIME(ALL_INFO, all_info, access_time, basetime + 200);
|
||||
CHECK_TIME(ALL_INFO, all_info, write_time, basetime + 300);
|
||||
CHECK_TIME(ALL_INFO, all_info, change_time, basetime + 400);
|
||||
CHECK_VALUE(ALL_INFO, all_info, attrib, FILE_ATTRIBUTE_READONLY);
|
||||
|
||||
/* a zero time means don't change */
|
||||
unix_to_nt_time(&sfinfo.basic_info.in.create_time, 0);
|
||||
unix_to_nt_time(&sfinfo.basic_info.in.access_time, 0);
|
||||
unix_to_nt_time(&sfinfo.basic_info.in.write_time, 0);
|
||||
unix_to_nt_time(&sfinfo.basic_info.in.change_time, 0);
|
||||
sfinfo.basic_info.in.attrib = FILE_ATTRIBUTE_NORMAL;
|
||||
CHECK_CALL_FNUM(BASIC_INFORMATION, NT_STATUS_OK);
|
||||
CHECK_TIME(ALL_INFO, all_info, create_time, basetime + 100);
|
||||
CHECK_TIME(ALL_INFO, all_info, access_time, basetime + 200);
|
||||
CHECK_TIME(ALL_INFO, all_info, write_time, basetime + 300);
|
||||
CHECK_TIME(ALL_INFO, all_info, change_time, basetime + 400);
|
||||
CHECK_VALUE(ALL_INFO, all_info, attrib, FILE_ATTRIBUTE_NORMAL);
|
||||
|
||||
CHECK_CALL_PATH(BASIC_INFORMATION, NT_STATUS_OK);
|
||||
CHECK_TIME(ALL_INFO, all_info, create_time, basetime + 100);
|
||||
CHECK_TIME(ALL_INFO, all_info, access_time, basetime + 200);
|
||||
CHECK_TIME(ALL_INFO, all_info, write_time, basetime + 300);
|
||||
/* interesting - w2k3 leaves change_time as current time for 0 change time
|
||||
in setpathinfo
|
||||
CHECK_TIME(ALL_INFO, all_info, change_time, basetime + 400);
|
||||
*/
|
||||
CHECK_VALUE(ALL_INFO, all_info, attrib, FILE_ATTRIBUTE_NORMAL);
|
||||
|
||||
/* test disposition_info level */
|
||||
sfinfo.disposition_info.in.delete_on_close = 1;
|
||||
CHECK_CALL_FNUM(DISPOSITION_INFO, NT_STATUS_OK);
|
||||
CHECK_VALUE(ALL_INFO, all_info, delete_pending, 1);
|
||||
CHECK_VALUE(ALL_INFO, all_info, nlink, 0);
|
||||
|
||||
sfinfo.disposition_info.in.delete_on_close = 0;
|
||||
CHECK_CALL_FNUM(DISPOSITION_INFO, NT_STATUS_OK);
|
||||
CHECK_VALUE(ALL_INFO, all_info, delete_pending, 0);
|
||||
CHECK_VALUE(ALL_INFO, all_info, nlink, 1);
|
||||
|
||||
/* test disposition_information level */
|
||||
sfinfo.disposition_info.in.delete_on_close = 1;
|
||||
CHECK_CALL_FNUM(DISPOSITION_INFORMATION, NT_STATUS_OK);
|
||||
CHECK_VALUE(ALL_INFO, all_info, delete_pending, 1);
|
||||
CHECK_VALUE(ALL_INFO, all_info, nlink, 0);
|
||||
|
||||
/* this would delete the file! */
|
||||
/*
|
||||
CHECK_CALL_PATH(DISPOSITION_INFORMATION, NT_STATUS_OK);
|
||||
CHECK_VALUE(ALL_INFO, all_info, delete_pending, 1);
|
||||
CHECK_VALUE(ALL_INFO, all_info, nlink, 0);
|
||||
*/
|
||||
|
||||
sfinfo.disposition_info.in.delete_on_close = 0;
|
||||
CHECK_CALL_FNUM(DISPOSITION_INFORMATION, NT_STATUS_OK);
|
||||
CHECK_VALUE(ALL_INFO, all_info, delete_pending, 0);
|
||||
CHECK_VALUE(ALL_INFO, all_info, nlink, 1);
|
||||
|
||||
CHECK_CALL_PATH(DISPOSITION_INFORMATION, NT_STATUS_OK);
|
||||
CHECK_VALUE(ALL_INFO, all_info, delete_pending, 0);
|
||||
CHECK_VALUE(ALL_INFO, all_info, nlink, 1);
|
||||
|
||||
/* test allocation_info level - this can truncate the file
|
||||
to the rounded up size */
|
||||
sfinfo.allocation_info.in.alloc_size = 0;
|
||||
CHECK_CALL_FNUM(ALLOCATION_INFO, NT_STATUS_OK);
|
||||
CHECK_VALUE(ALL_INFO, all_info, size, 0);
|
||||
CHECK_VALUE(ALL_INFO, all_info, alloc_size, 0);
|
||||
|
||||
sfinfo.allocation_info.in.alloc_size = 4096;
|
||||
CHECK_CALL_FNUM(ALLOCATION_INFO, NT_STATUS_OK);
|
||||
CHECK_VALUE(ALL_INFO, all_info, alloc_size, 4096);
|
||||
CHECK_VALUE(ALL_INFO, all_info, size, 0);
|
||||
|
||||
RECREATE_BOTH;
|
||||
sfinfo.allocation_info.in.alloc_size = 0;
|
||||
CHECK_CALL_FNUM(ALLOCATION_INFORMATION, NT_STATUS_OK);
|
||||
CHECK_VALUE(ALL_INFO, all_info, size, 0);
|
||||
CHECK_VALUE(ALL_INFO, all_info, alloc_size, 0);
|
||||
|
||||
CHECK_CALL_PATH(ALLOCATION_INFORMATION, NT_STATUS_OK);
|
||||
CHECK_VALUE(ALL_INFO, all_info, size, 0);
|
||||
CHECK_VALUE(ALL_INFO, all_info, alloc_size, 0);
|
||||
|
||||
sfinfo.allocation_info.in.alloc_size = 4096;
|
||||
CHECK_CALL_FNUM(ALLOCATION_INFORMATION, NT_STATUS_OK);
|
||||
CHECK_VALUE(ALL_INFO, all_info, alloc_size, 4096);
|
||||
CHECK_VALUE(ALL_INFO, all_info, size, 0);
|
||||
|
||||
/* setting the allocation size up via setpathinfo seems
|
||||
to be broken in w2k3 */
|
||||
CHECK_CALL_PATH(ALLOCATION_INFORMATION, NT_STATUS_OK);
|
||||
CHECK_VALUE(ALL_INFO, all_info, alloc_size, 0);
|
||||
CHECK_VALUE(ALL_INFO, all_info, size, 0);
|
||||
|
||||
/* test end_of_file_info level */
|
||||
sfinfo.end_of_file_info.in.size = 37;
|
||||
CHECK_CALL_FNUM(END_OF_FILE_INFO, NT_STATUS_OK);
|
||||
CHECK_VALUE(ALL_INFO, all_info, size, 37);
|
||||
|
||||
sfinfo.end_of_file_info.in.size = 7;
|
||||
CHECK_CALL_FNUM(END_OF_FILE_INFO, NT_STATUS_OK);
|
||||
CHECK_VALUE(ALL_INFO, all_info, size, 7);
|
||||
|
||||
sfinfo.end_of_file_info.in.size = 37;
|
||||
CHECK_CALL_FNUM(END_OF_FILE_INFORMATION, NT_STATUS_OK);
|
||||
CHECK_VALUE(ALL_INFO, all_info, size, 37);
|
||||
|
||||
CHECK_CALL_PATH(END_OF_FILE_INFORMATION, NT_STATUS_OK);
|
||||
CHECK_VALUE(ALL_INFO, all_info, size, 37);
|
||||
|
||||
sfinfo.end_of_file_info.in.size = 7;
|
||||
CHECK_CALL_FNUM(END_OF_FILE_INFORMATION, NT_STATUS_OK);
|
||||
CHECK_VALUE(ALL_INFO, all_info, size, 7);
|
||||
|
||||
CHECK_CALL_PATH(END_OF_FILE_INFORMATION, NT_STATUS_OK);
|
||||
CHECK_VALUE(ALL_INFO, all_info, size, 7);
|
||||
|
||||
|
||||
/* test position_information level */
|
||||
sfinfo.position_information.in.position = 123456;
|
||||
CHECK_CALL_FNUM(POSITION_INFORMATION, NT_STATUS_OK);
|
||||
CHECK_VALUE(POSITION_INFORMATION, position_information, position, 123456);
|
||||
|
||||
CHECK_CALL_PATH(POSITION_INFORMATION, NT_STATUS_OK);
|
||||
CHECK_VALUE(POSITION_INFORMATION, position_information, position, 0);
|
||||
|
||||
/* test mode_information level */
|
||||
sfinfo.mode_information.in.mode = 2;
|
||||
CHECK_CALL_FNUM(MODE_INFORMATION, NT_STATUS_OK);
|
||||
CHECK_VALUE(MODE_INFORMATION, mode_information, mode, 2);
|
||||
|
||||
CHECK_CALL_PATH(MODE_INFORMATION, NT_STATUS_OK);
|
||||
CHECK_VALUE(MODE_INFORMATION, mode_information, mode, 0);
|
||||
|
||||
sfinfo.mode_information.in.mode = 1;
|
||||
CHECK_CALL_FNUM(MODE_INFORMATION, NT_STATUS_INVALID_PARAMETER);
|
||||
CHECK_CALL_PATH(MODE_INFORMATION, NT_STATUS_INVALID_PARAMETER);
|
||||
|
||||
sfinfo.mode_information.in.mode = 0;
|
||||
CHECK_CALL_FNUM(MODE_INFORMATION, NT_STATUS_OK);
|
||||
CHECK_VALUE(MODE_INFORMATION, mode_information, mode, 0);
|
||||
|
||||
CHECK_CALL_PATH(MODE_INFORMATION, NT_STATUS_OK);
|
||||
CHECK_VALUE(MODE_INFORMATION, mode_information, mode, 0);
|
||||
|
||||
/* finally the rename_information level */
|
||||
cli_close(cli, create_complex_file(cli, mem_ctx, fnum_fname_new));
|
||||
cli_close(cli, create_complex_file(cli, mem_ctx, path_fname_new));
|
||||
|
||||
sfinfo.rename_information.in.overwrite = 0;
|
||||
sfinfo.rename_information.in.root_fid = 0;
|
||||
sfinfo.rename_information.in.new_name = fnum_fname_new+1;
|
||||
CHECK_CALL_FNUM(RENAME_INFORMATION, NT_STATUS_OBJECT_NAME_COLLISION);
|
||||
|
||||
sfinfo.rename_information.in.new_name = path_fname_new+1;
|
||||
CHECK_CALL_PATH(RENAME_INFORMATION, NT_STATUS_OBJECT_NAME_COLLISION);
|
||||
|
||||
sfinfo.rename_information.in.new_name = fnum_fname_new+1;
|
||||
sfinfo.rename_information.in.overwrite = 1;
|
||||
CHECK_CALL_FNUM(RENAME_INFORMATION, NT_STATUS_OK);
|
||||
CHECK_STR(NAME_INFO, name_info, fname.s, fnum_fname_new);
|
||||
|
||||
sfinfo.rename_information.in.new_name = path_fname_new+1;
|
||||
CHECK_CALL_PATH(RENAME_INFORMATION, NT_STATUS_OK);
|
||||
CHECK_STR(NAME_INFO, name_info, fname.s, path_fname_new);
|
||||
|
||||
sfinfo.rename_information.in.new_name = fnum_fname+1;
|
||||
CHECK_CALL_FNUM(RENAME_INFORMATION, NT_STATUS_OK);
|
||||
CHECK_STR(NAME_INFO, name_info, fname.s, fnum_fname);
|
||||
|
||||
sfinfo.rename_information.in.new_name = path_fname+1;
|
||||
CHECK_CALL_PATH(RENAME_INFORMATION, NT_STATUS_OK);
|
||||
CHECK_STR(NAME_INFO, name_info, fname.s, path_fname);
|
||||
|
||||
|
||||
done:
|
||||
cli_close(cli, fnum);
|
||||
if (!cli_unlink(cli, fnum_fname)) {
|
||||
printf("Failed to delete %s - %s\n", fnum_fname, cli_errstr(cli));
|
||||
}
|
||||
if (!cli_unlink(cli, path_fname)) {
|
||||
printf("Failed to delete %s - %s\n", path_fname, cli_errstr(cli));
|
||||
}
|
||||
|
||||
torture_close_connection(cli);
|
||||
talloc_destroy(mem_ctx);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
look for the w2k3 setpathinfo STANDARD bug
|
||||
*/
|
||||
BOOL torture_sfileinfo_bug(int dummy)
|
||||
{
|
||||
struct cli_state *cli;
|
||||
TALLOC_CTX *mem_ctx;
|
||||
const char *fname = "\\bug3.txt";
|
||||
union smb_setfileinfo sfinfo;
|
||||
NTSTATUS status;
|
||||
int fnum;
|
||||
|
||||
if (!torture_open_connection(&cli)) {
|
||||
return False;
|
||||
}
|
||||
|
||||
mem_ctx = talloc_init("torture_sfileinfo");
|
||||
|
||||
fnum = create_complex_file(cli, mem_ctx, fname);
|
||||
cli_close(cli, fnum);
|
||||
|
||||
sfinfo.generic.level = RAW_SFILEINFO_STANDARD;
|
||||
sfinfo.generic.file.fname = fname;
|
||||
|
||||
sfinfo.standard.in.create_time = 0;
|
||||
sfinfo.standard.in.access_time = 0;
|
||||
sfinfo.standard.in.write_time = 0;
|
||||
|
||||
status = smb_raw_setpathinfo(cli->tree, &sfinfo);
|
||||
printf("%s - %s\n", fname, nt_errstr(status));
|
||||
|
||||
printf("now try and delete %s\n", fname);
|
||||
|
||||
return True;
|
||||
}
|
Loading…
Reference in New Issue
Block a user