示例#1
0
static int				/* O - 0 = success, non-0 = failure */
smb_print(struct smbcli_state *cli,	/* I - SMB connection */
          char             *title,	/* I - Title/job name */
          FILE             *fp)		/* I - File to print */
{
  int	fnum;		/* File number */
  int	nbytes,		/* Number of bytes read */
	tbytes;		/* Total bytes read */
  char	buffer[8192],	/* Buffer for copy */
	*ptr;		/* Pointer into tile */


 /*
  * Sanitize the title...
  */

  for (ptr = title; *ptr; ptr ++)
    if (!isalnum((int)*ptr) && !isspace((int)*ptr))
      *ptr = '_';

 /*
  * Open the printer device...
  */

  if ((fnum = smbcli_open(cli, title, O_RDWR | O_CREAT | O_TRUNC, DENY_NONE)) == -1)
  {
    fprintf(stderr, "ERROR: %s opening remote file %s\n",
            smbcli_errstr(cli), title);
    return (1);
  }

 /*
  * Copy the file to the printer...
  */

  if (fp != stdin)
    rewind(fp);

  tbytes = 0;

  while ((nbytes = fread(buffer, 1, sizeof(buffer), fp)) > 0)
  {
    if (smbcli_write(cli, fnum, 0, buffer, tbytes, nbytes) != nbytes)
    {
      fprintf(stderr, "ERROR: Error writing file: %s\n", smbcli_errstr(cli));
      break;
    }

    tbytes += nbytes;
  } 

  if (!smbcli_close(cli, fnum))
  {
    fprintf(stderr, "ERROR: %s closing remote file %s\n",
            smbcli_errstr(cli), title);
    return (1);
  }
  else
    return (0);
}
示例#2
0
文件: scanner.c 项目: AIdrifter/samba
bool torture_trans2_scan(struct torture_context *torture,
						 struct smbcli_state *cli)
{
	int op, level;
	const char *fname = "\\scanner.dat";
	int fnum, dnum, qfnum;

	fnum = smbcli_open(cli->tree, fname, O_RDWR | O_CREAT | O_TRUNC, DENY_NONE);
	if (fnum == -1) {
		printf("file open failed - %s\n", smbcli_errstr(cli->tree));
	}
	dnum = smbcli_nt_create_full(cli->tree, "\\", 
				     0, 
				     SEC_RIGHTS_FILE_READ, 
				     FILE_ATTRIBUTE_NORMAL,
				     NTCREATEX_SHARE_ACCESS_READ | NTCREATEX_SHARE_ACCESS_WRITE, 
				     NTCREATEX_DISP_OPEN, 
				     NTCREATEX_OPTIONS_DIRECTORY, 0);
	if (dnum == -1) {
		printf("directory open failed - %s\n", smbcli_errstr(cli->tree));
	}
	qfnum = smbcli_nt_create_full(cli->tree, "\\$Extend\\$Quota:$Q:$INDEX_ALLOCATION", 
				   NTCREATEX_FLAGS_EXTENDED, 
				   SEC_FLAG_MAXIMUM_ALLOWED, 
				   0,
				   NTCREATEX_SHARE_ACCESS_READ|NTCREATEX_SHARE_ACCESS_WRITE, 
				   NTCREATEX_DISP_OPEN, 
				   0, 0);
	if (qfnum == -1) {
		printf("quota open failed - %s\n", smbcli_errstr(cli->tree));
	}

	for (op=OP_MIN; op<=OP_MAX; op++) {

		if (!trans2_op_exists(cli, op)) {
			continue;
		}

		for (level = 0; level <= 50; level++) {
			scan_trans2(cli, op, level, fnum, dnum, qfnum, fname);
		}

		for (level = 0x100; level <= 0x130; level++) {
			scan_trans2(cli, op, level, fnum, dnum, qfnum, fname);
		}

		for (level = 1000; level < 1050; level++) {
			scan_trans2(cli, op, level, fnum, dnum, qfnum, fname);
		}
	}

	return true;
}
示例#3
0
文件: mux.c 项目: AIdrifter/samba
/*
  test a write that hits a byte range lock and send the close after the write
*/
static bool test_mux_write(struct smbcli_state *cli, TALLOC_CTX *mem_ctx)
{
	union smb_write io;
	NTSTATUS status;
	int fnum;
	bool ret = true;
	struct smbcli_request *req;

	printf("Testing multiplexed lock/write/close\n");

	fnum = smbcli_open(cli->tree, BASEDIR "\\write.dat", O_RDWR | O_CREAT, DENY_NONE);
	if (fnum == -1) {
		printf("open failed in mux_write - %s\n", smbcli_errstr(cli->tree));
		ret = false;
		goto done;
	}

	cli->session->pid = 1;

	/* lock a range */
	if (NT_STATUS_IS_ERR(smbcli_lock(cli->tree, fnum, 0, 4, 0, WRITE_LOCK))) {
		printf("lock failed in mux_write - %s\n", smbcli_errstr(cli->tree));
		ret = false;
		goto done;
	}

	cli->session->pid = 2;

	/* send an async write */
	io.generic.level = RAW_WRITE_WRITEX;
	io.writex.in.file.fnum = fnum;
	io.writex.in.offset = 0;
	io.writex.in.wmode = 0;
	io.writex.in.remaining = 0;
	io.writex.in.count = 4;
	io.writex.in.data = (const uint8_t *)&fnum;	
	req = smb_raw_write_send(cli->tree, &io);

	/* unlock the range */
	cli->session->pid = 1;
	smbcli_unlock(cli->tree, fnum, 0, 4);

	/* and recv the async write reply */
	status = smb_raw_write_recv(req, &io);
	CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);

	smbcli_close(cli->tree, fnum);

done:
	return ret;
}
示例#4
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_raw_qfileinfo(struct torture_context *torture)
{
	struct smbcli_state *cli;
	BOOL ret = True;
	TALLOC_CTX *mem_ctx;
	int fnum;
	const char *fname = "\\torture_qfileinfo.txt";

	if (!torture_open_connection(&cli, 0)) {
		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, smbcli_errstr(cli->tree));
		ret = False;
		goto done;
	}

	ret = torture_raw_qfileinfo_internals(torture, mem_ctx, cli->tree, fnum, fname, False /* is_ipc */);
	
	smbcli_close(cli->tree, fnum);
	smbcli_unlink(cli->tree, fname);

done:
	torture_close_connection(cli);
	talloc_free(mem_ctx);
	return ret;
}
示例#5
0
static bool find_single_info2(void *mem_ctx,
			struct torture_context *torture,
			struct smbcli_state *cli,
			const char *fname,
			struct unix_info2 *info2)
{
	union smb_search_first search;
	NTSTATUS status;

	/* Set up a new search for a single item, not using resume keys. */
	ZERO_STRUCT(search);
	search.t2ffirst.level = RAW_SEARCH_TRANS2;
	search.t2ffirst.data_level = SMB_FIND_UNIX_INFO2;
	search.t2ffirst.in.max_count = 1;
	search.t2ffirst.in.flags = FLAG_TRANS2_FIND_CLOSE;
	search.t2ffirst.in.pattern = fname;

	status = smb_raw_search_first(cli->tree, mem_ctx,
				      &search, info2, search_callback);
	torture_assert_ntstatus_equal(torture, status, NT_STATUS_OK,
			smbcli_errstr(cli->tree));

	torture_assert_int_equal(torture, search.t2ffirst.out.count, 1,
			"expected exactly one result");
	torture_assert_int_equal(torture, search.t2ffirst.out.end_of_search, 1,
			"expected end_of_search to be true");

	return check_unix_info2(torture, info2);
}
示例#6
0
文件: misc.c 项目: endisd/samba
/*
  see how many RPC pipes we can open at once
*/
bool run_pipe_number(struct torture_context *tctx, 
					 struct smbcli_state *cli1)
{
	const char *pipe_name = "\\WKSSVC";
	int fnum;
	int num_pipes = 0;

	while(1) {
		fnum = smbcli_nt_create_full(cli1->tree, pipe_name, 0, SEC_FILE_READ_DATA, FILE_ATTRIBUTE_NORMAL,
				   NTCREATEX_SHARE_ACCESS_READ|NTCREATEX_SHARE_ACCESS_WRITE, NTCREATEX_DISP_OPEN_IF, 0, 0);

		if (fnum == -1) {
			torture_comment(tctx, "Open of pipe %s failed with error (%s)\n", pipe_name, smbcli_errstr(cli1->tree));
			break;
		}
		num_pipes++;
		if (torture_setting_bool(tctx, "progress", true)) {
			torture_comment(tctx, "%d\r", num_pipes);
			fflush(stdout);
		}
	}

	torture_comment(tctx, "pipe_number test - we can open %d %s pipes.\n", num_pipes, pipe_name );
	return true;
}
示例#7
0
bool torture_samba3_caseinsensitive(struct torture_context *torture)
{
	struct smbcli_state *cli;
	TALLOC_CTX *mem_ctx;
	NTSTATUS status;
	const char *dirname = "insensitive";
	const char *ucase_dirname = "InSeNsItIvE";
	const char *fname = "foo";
	char *fpath;
	int fnum;
	int counter = 0;
	bool ret = true;

	if (!(mem_ctx = talloc_init("torture_samba3_caseinsensitive"))) {
		d_printf("talloc_init failed\n");
		return false;
	}

	if (!torture_open_connection(&cli, torture, 0)) {
		goto done;
	}

	smbcli_deltree(cli->tree, dirname);

	status = smbcli_mkdir(cli->tree, dirname);
	if (!NT_STATUS_IS_OK(status)) {
		d_printf("smbcli_mkdir failed: %s\n", nt_errstr(status));
		goto done;
	}

	if (!(fpath = talloc_asprintf(mem_ctx, "%s\\%s", dirname, fname))) {
		goto done;
	}
	fnum = smbcli_open(cli->tree, fpath, O_RDWR | O_CREAT, DENY_NONE);
	if (fnum == -1) {
		d_printf("Could not create file %s: %s\n", fpath,
			 smbcli_errstr(cli->tree));
		goto done;
	}
	smbcli_close(cli->tree, fnum);

	smbcli_list(cli->tree, talloc_asprintf(
			    mem_ctx, "%s\\*", ucase_dirname),
		    FILE_ATTRIBUTE_DIRECTORY|FILE_ATTRIBUTE_HIDDEN
		    |FILE_ATTRIBUTE_SYSTEM,
		    count_fn, (void *)&counter);

	if (counter == 3) {
		ret = true;
	}
	else {
		d_fprintf(stderr, "expected 3 entries, got %d\n", counter);
		ret = false;
	}

 done:
	talloc_free(mem_ctx);
	return ret;
}
示例#8
0
文件: misc.c 项目: endisd/samba
/*
  open a file N times on the server and just hold them open
  used for testing performance when there are N file handles
  alopenn
 */
bool torture_holdopen(struct torture_context *tctx,
		      struct smbcli_state *cli)
{
	int i, fnum;
	const char *fname = "\\holdopen.dat";
	NTSTATUS status;

	smbcli_unlink(cli->tree, fname);

	fnum = smbcli_open(cli->tree, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE);
	if (fnum == -1) {
		torture_comment(tctx, "open of %s failed (%s)\n", fname, smbcli_errstr(cli->tree));
		return false;
	}

	smbcli_close(cli->tree, fnum);

	for (i=0;i<torture_numops;i++) {
		union smb_open op;

		op.generic.level = RAW_OPEN_NTCREATEX;
		op.ntcreatex.in.root_fid.fnum = 0;
		op.ntcreatex.in.flags = 0;
		op.ntcreatex.in.access_mask = SEC_FILE_WRITE_DATA;
		op.ntcreatex.in.create_options = 0;
		op.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
		op.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_MASK;
		op.ntcreatex.in.alloc_size = 0;
		op.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN;
		op.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
		op.ntcreatex.in.security_flags = 0;
		op.ntcreatex.in.fname = fname;
		status = smb_raw_open(cli->tree, tctx, &op);
		if (!NT_STATUS_IS_OK(status)) {
			torture_warning(tctx, "open %d failed\n", i);
			continue;
		}

		if (torture_setting_bool(tctx, "progress", true)) {
			torture_comment(tctx, "opened %d file\r", i);
			fflush(stdout);
		}
	}

	torture_comment(tctx, "\nStarting pings\n");

	while (1) {
		struct smb_echo ec;

		status = smb_raw_echo(cli->transport, &ec);
		torture_comment(tctx, ".");
		fflush(stdout);
		sleep(15);
	}

	return true;
}
示例#9
0
/* 
   callback function for torture_deltree() 
*/
static void delete_fn(struct clilist_file_info *finfo, const char *name, void *state)
{
	struct delete_state *dstate = (struct delete_state *)state;
	char *s, *n;
	if (ISDOT(finfo->name) || ISDOTDOT(finfo->name)) {
		return;
	}

	n = strdup(name);
	n[strlen(n)-1] = 0;
	asprintf(&s, "%s%s", n, finfo->name);

	if (finfo->attrib & FILE_ATTRIBUTE_READONLY) {
		if (NT_STATUS_IS_ERR(smbcli_setatr(dstate->tree, s, 0, 0))) {
			DEBUG(2,("Failed to remove READONLY on %s - %s\n",
				 s, smbcli_errstr(dstate->tree)));			
		}
	}

	if (finfo->attrib & FILE_ATTRIBUTE_DIRECTORY) {
		char *s2;
		asprintf(&s2, "%s\\*", s);
		smbcli_unlink(dstate->tree, s2);
		smbcli_list(dstate->tree, s2, 
			 FILE_ATTRIBUTE_DIRECTORY|FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_SYSTEM, 
			 delete_fn, state);
		free(s2);
		if (NT_STATUS_IS_ERR(smbcli_rmdir(dstate->tree, s))) {
			DEBUG(2,("Failed to delete %s - %s\n", 
				 s, smbcli_errstr(dstate->tree)));
			dstate->failed = true;
		}
		dstate->total_deleted++;
	} else {
		if (NT_STATUS_IS_ERR(smbcli_unlink(dstate->tree, s))) {
			DEBUG(2,("Failed to delete %s - %s\n", 
				 s, smbcli_errstr(dstate->tree)));
			dstate->failed = true;
		}
		dstate->total_deleted++;
	}
	free(s);
	free(n);
}
示例#10
0
文件: util_smb.c 项目: srimalik/samba
/**
  setup a directory ready for a test
*/
_PUBLIC_ bool torture_setup_dir(struct smbcli_state *cli, const char *dname)
{
	smb_raw_exit(cli->session);
	if (smbcli_deltree(cli->tree, dname) == -1 ||
	    NT_STATUS_IS_ERR(smbcli_mkdir(cli->tree, dname))) {
		printf("Unable to setup %s - %s\n", dname, smbcli_errstr(cli->tree));
		return false;
	}
	return true;
}
示例#11
0
/* 
   recursively descend a tree deleting all files
   returns the number of files deleted, or -1 on error
*/
int smbcli_deltree(struct smbcli_tree *tree, const char *dname)
{
	char *mask;
	struct delete_state dstate;
	NTSTATUS status;

	dstate.tree = tree;
	dstate.total_deleted = 0;
	dstate.failed = false;

	/* it might be a file */
	status = smbcli_unlink(tree, dname);
	if (NT_STATUS_IS_OK(smbcli_unlink(tree, dname))) {
		return 1;
	}
	if (NT_STATUS_EQUAL(smbcli_nt_error(tree), NT_STATUS_OBJECT_NAME_NOT_FOUND) ||
	    NT_STATUS_EQUAL(smbcli_nt_error(tree), NT_STATUS_OBJECT_PATH_NOT_FOUND) ||
	    NT_STATUS_EQUAL(smbcli_nt_error(tree), NT_STATUS_NO_SUCH_FILE) ||
	    NT_STATUS_EQUAL(smbcli_nt_error(tree), NT_STATUS_DOS(ERRDOS, ERRbadfile))) {
		return 0;
	}
	if (NT_STATUS_EQUAL(status, NT_STATUS_CANNOT_DELETE)) {
		/* it could be read-only */
		status = smbcli_setatr(tree, dname, FILE_ATTRIBUTE_NORMAL, 0);
		if (NT_STATUS_IS_OK(smbcli_unlink(tree, dname))) {
			return 1;
		}
	}

	asprintf(&mask, "%s\\*", dname);
	smbcli_unlink(dstate.tree, mask);
	smbcli_list(dstate.tree, mask, 
		 FILE_ATTRIBUTE_DIRECTORY|FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_SYSTEM, 
		 delete_fn, &dstate);
	free(mask);

	status = smbcli_rmdir(dstate.tree, dname);
	if (NT_STATUS_EQUAL(status, NT_STATUS_CANNOT_DELETE)) {
		/* it could be read-only */
		status = smbcli_setatr(dstate.tree, dname, FILE_ATTRIBUTE_NORMAL, 0);
		status = smbcli_rmdir(dstate.tree, dname);
	}
	if (NT_STATUS_IS_ERR(status)) {
		DEBUG(2,("Failed to delete %s - %s\n", 
			 dname, smbcli_errstr(dstate.tree)));
		return -1;
	}
	dstate.total_deleted++;

	if (dstate.failed) {
		return -1;
	}

	return dstate.total_deleted;
}
示例#12
0
文件: misc.c 项目: endisd/samba
/*
  sees what IOCTLs are supported
 */
bool torture_ioctl_test(struct torture_context *tctx, 
						struct smbcli_state *cli)
{
	uint16_t device, function;
	int fnum;
	const char *fname = "\\ioctl.dat";
	NTSTATUS status;
	union smb_ioctl parms;
	TALLOC_CTX *mem_ctx;

	mem_ctx = talloc_named_const(tctx, 0, "ioctl_test");

	smbcli_unlink(cli->tree, fname);

	fnum = smbcli_open(cli->tree, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE);
	if (fnum == -1) {
		torture_comment(tctx, "open of %s failed (%s)\n", fname, smbcli_errstr(cli->tree));
		return false;
	}

	parms.ioctl.level = RAW_IOCTL_IOCTL;
	parms.ioctl.in.file.fnum = fnum;
	parms.ioctl.in.request = IOCTL_QUERY_JOB_INFO;
	status = smb_raw_ioctl(cli->tree, mem_ctx, &parms);
	torture_comment(tctx, "ioctl job info: %s\n", smbcli_errstr(cli->tree));

	for (device=0;device<0x100;device++) {
		torture_comment(tctx, "testing device=0x%x\n", device);
		for (function=0;function<0x100;function++) {
			parms.ioctl.in.request = (device << 16) | function;
			status = smb_raw_ioctl(cli->tree, mem_ctx, &parms);

			if (NT_STATUS_IS_OK(status)) {
				torture_comment(tctx, "ioctl device=0x%x function=0x%x OK : %d bytes\n", 
					device, function, (int)parms.ioctl.out.blob.length);
			}
		}
	}

	return true;
}
示例#13
0
文件: dfs.c 项目: AllardJ/Tomato
static bool test_DeleteDir(struct smbcli_state *cli,
			   const char *dir)
{
	printf("Deleting directory %s\n", dir);

	if (smbcli_deltree(cli->tree, dir) == -1) {
		printf("Unable to delete dir %s - %s\n", dir,
			smbcli_errstr(cli->tree));
		return false;
	}

	return true;
}
示例#14
0
bool torture_samba3_caseinsensitive(struct torture_context *torture, struct smbcli_state *cli)
{
	TALLOC_CTX *mem_ctx;
	const char *dirname = "insensitive";
	const char *ucase_dirname = "InSeNsItIvE";
	const char *fname = "foo";
	char *fpath;
	int fnum;
	int counter = 0;
	bool ret = false;

	if (!(mem_ctx = talloc_init("torture_samba3_caseinsensitive"))) {
		torture_result(torture, TORTURE_FAIL, "talloc_init failed\n");
		return false;
	}

	torture_assert(torture, torture_setup_dir(cli, dirname), "creating test directory");

	if (!(fpath = talloc_asprintf(mem_ctx, "%s\\%s", dirname, fname))) {
		goto done;
	}
	fnum = smbcli_open(cli->tree, fpath, O_RDWR | O_CREAT, DENY_NONE);
	if (fnum == -1) {
		torture_result(torture, TORTURE_FAIL,
			"Could not create file %s: %s", fpath,
			 smbcli_errstr(cli->tree));
		goto done;
	}
	smbcli_close(cli->tree, fnum);

	smbcli_list(cli->tree, talloc_asprintf(
			    mem_ctx, "%s\\*", ucase_dirname),
		    FILE_ATTRIBUTE_DIRECTORY|FILE_ATTRIBUTE_HIDDEN
		    |FILE_ATTRIBUTE_SYSTEM,
		    count_fn, (void *)&counter);

	if (counter == 3) {
		ret = true;
	}
	else {
		torture_result(torture, TORTURE_FAIL,
			"expected 3 entries, got %d", counter);
		ret = false;
	}

 done:
	talloc_free(mem_ctx);
	return ret;
}
示例#15
0
static bool gpo_sync_files(struct sync_context *ctx)
{
	DEBUG(3,("calling cli_list with mask: %s\n", ctx->mask));

	if (smbcli_list(ctx->cli->tree,
		     ctx->mask,
		     ctx->attribute,
		     gpo_sync_func,
		     ctx) == -1) {
		DEBUG(1,("listing [%s] failed with error: %s\n",
			ctx->mask, smbcli_errstr(ctx->cli->tree)));
		return false;
	}

	return true;
}
示例#16
0
/*
  test disconnect with timed lock
*/
static bool test_disconnect_lock(struct smbcli_state *cli, TALLOC_CTX *mem_ctx)
{
	union smb_lock io;
	NTSTATUS status;
	int fnum;
	struct smbcli_request *req;
	struct smb_lock_entry lock[1];

	printf("trying disconnect with async lock\n");

	fnum = smbcli_open(cli->tree, BASEDIR "\\write.dat", 
			   O_RDWR | O_CREAT, DENY_NONE);
	if (fnum == -1) {
		printf("open failed in mux_write - %s\n", smbcli_errstr(cli->tree));
		return false;
	}

	io.lockx.level = RAW_LOCK_LOCKX;
	io.lockx.in.file.fnum = fnum;
	io.lockx.in.mode = 0;
	io.lockx.in.timeout = 0;
	io.lockx.in.lock_cnt = 1;
	io.lockx.in.ulock_cnt = 0;
	lock[0].pid = 1;
	lock[0].offset = 0;
	lock[0].count = 4;
	io.lockx.in.locks = &lock[0];

	status = smb_raw_lock(cli->tree, &io);
	CHECK_STATUS(status, NT_STATUS_OK);

	lock[0].pid = 2;
	io.lockx.in.timeout = 3000;
	req = smb_raw_lock_send(cli->tree, &io);
	if (!req) {
		printf("test_disconnect_lock: smb_raw_lock_send() "
			"returned NULL\n");
		return false;
	}

	status = smbcli_chkpath(cli->tree, "\\");
	CHECK_STATUS(status, NT_STATUS_OK);

	talloc_free(cli);

	return true;
}
示例#17
0
static bool query_file_path_info2(void *mem_ctx,
			struct torture_context *torture,
			struct smbcli_state *cli,
			int fnum,
			const char *fname,
			struct unix_info2 *info2)
{
	NTSTATUS result;
	union smb_fileinfo finfo;

	finfo.generic.level = RAW_FILEINFO_UNIX_INFO2;

	if (fname) {
		finfo.generic.in.file.path = fname;
		result = smb_raw_pathinfo(cli->tree, mem_ctx, &finfo);
	} else {
		finfo.generic.in.file.fnum = fnum;
		result = smb_raw_fileinfo(cli->tree, mem_ctx, &finfo);
	}

	torture_assert_ntstatus_equal(torture, result, NT_STATUS_OK,
			smbcli_errstr(cli->tree));

	info2->end_of_file = finfo.unix_info2.out.end_of_file;
	info2->num_bytes = finfo.unix_info2.out.num_bytes;
	info2->status_change_time = finfo.unix_info2.out.status_change_time;
	info2->access_time = finfo.unix_info2.out.access_time;
	info2->change_time = finfo.unix_info2.out.change_time;
	info2->uid = finfo.unix_info2.out.uid;
	info2->gid = finfo.unix_info2.out.gid;
	info2->file_type = finfo.unix_info2.out.file_type;
	info2->dev_major = finfo.unix_info2.out.dev_major;
	info2->dev_minor = finfo.unix_info2.out.dev_minor;
	info2->unique_id = finfo.unix_info2.out.unique_id;
	info2->permissions = finfo.unix_info2.out.permissions;
	info2->nlink = finfo.unix_info2.out.nlink;
	info2->create_time = finfo.unix_info2.out.create_time;
	info2->file_flags = finfo.unix_info2.out.file_flags;
	info2->flags_mask = finfo.unix_info2.out.flags_mask;

	if (!check_unix_info2(torture, info2)) {
		return false;
	}

	return true;
}
示例#18
0
/*
  check that a stream has the right contents
*/
static BOOL check_stream(struct smbcli_state *cli, TALLOC_CTX *mem_ctx,
			 const char *fname, const char *sname, 
			 const char *value)
{
	int fnum;
	const char *full_name;
	uint8_t *buf;
	ssize_t ret;

	full_name = talloc_asprintf(mem_ctx, "%s:%s", fname, sname);

	fnum = smbcli_open(cli->tree, full_name, O_RDONLY, DENY_NONE);

	if (value == NULL) {
		if (fnum != -1) {
			printf("should have failed stream open of %s\n", full_name);
			return False;
		}
		return True;
	}
	    
	if (fnum == -1) {
		printf("Failed to open stream '%s' - %s\n", 
		       full_name, smbcli_errstr(cli->tree));
		return False;
	}

	buf = talloc_size(mem_ctx, strlen(value)+11);
	
	ret = smbcli_read(cli->tree, fnum, buf, 0, strlen(value)+11);
	if (ret != strlen(value)) {
		printf("Failed to read %lu bytes from stream '%s' - got %d\n",
		       (long)strlen(value), full_name, (int)ret);
		return False;
	}

	if (memcmp(buf, value, strlen(value)) != 0) {
		printf("Bad data in stream\n");
		return False;
	}

	smbcli_close(cli->tree, fnum);
	return True;
}
示例#19
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_raw_qfileinfo(struct torture_context *torture, 
						   struct smbcli_state *cli)
{
	int fnum;
	bool ret;
	const char *fname = "\\torture_qfileinfo.txt";

	fnum = create_complex_file(cli, torture, fname);
	if (fnum == -1) {
		printf("ERROR: open of %s failed (%s)\n", fname, smbcli_errstr(cli->tree));
		return false;
	}

	ret = torture_raw_qfileinfo_internals(torture, torture, cli->tree, fnum, fname, false /* is_ipc */);
	
	smbcli_close(cli->tree, fnum);
	smbcli_unlink(cli->tree, fname);

	return ret;
}
示例#20
0
bool torture_samba3_badpath(struct torture_context *torture)
{
	struct smbcli_state *cli_nt = NULL;
	struct smbcli_state *cli_dos = NULL;
	const char *fname = "test.txt";
	const char *fname1 = "test1.txt";
	const char *dirname = "testdir";
	char *fpath;
	char *fpath1;
	int fnum;
	NTSTATUS status;
	bool ret = true;
	TALLOC_CTX *mem_ctx;
	bool nt_status_support;

	torture_assert(torture, mem_ctx = talloc_init("torture_samba3_badpath"), "talloc_init failed");

	nt_status_support = lpcfg_nt_status_support(torture->lp_ctx);

	torture_assert_goto(torture, lpcfg_set_cmdline(torture->lp_ctx, "nt status support", "yes"), ret, fail, "Could not set 'nt status support = yes'\n");

	torture_assert_goto(torture, torture_open_connection(&cli_nt, torture, 0), ret, fail, "Could not open NTSTATUS connection\n");

	torture_assert_goto(torture, lpcfg_set_cmdline(torture->lp_ctx, "nt status support", "no"), ret, fail, "Could not set 'nt status support = no'\n");

	torture_assert_goto(torture, torture_open_connection(&cli_dos, torture, 1), ret, fail, "Could not open DOS connection\n");

	torture_assert_goto(torture, lpcfg_set_cmdline(torture->lp_ctx, "nt status support",
						       nt_status_support ? "yes":"no"), 
			    ret, fail, "Could not set 'nt status support' back to where it was\n");

	torture_assert(torture, torture_setup_dir(cli_nt, dirname), "creating test directory");

	status = smbcli_chkpath(cli_nt->tree, dirname);
	CHECK_STATUS(torture, status, NT_STATUS_OK);

	status = smbcli_chkpath(cli_nt->tree,
				talloc_asprintf(mem_ctx, "%s\\bla", dirname));
	CHECK_STATUS(torture, status, NT_STATUS_OBJECT_NAME_NOT_FOUND);

	status = smbcli_chkpath(cli_dos->tree,
				talloc_asprintf(mem_ctx, "%s\\bla", dirname));
	CHECK_STATUS(torture, status, NT_STATUS_DOS(ERRDOS, ERRbadpath));

	status = smbcli_chkpath(cli_nt->tree,
				talloc_asprintf(mem_ctx, "%s\\bla\\blub",
						dirname));
	CHECK_STATUS(torture, status, NT_STATUS_OBJECT_PATH_NOT_FOUND);
	status = smbcli_chkpath(cli_dos->tree,
				talloc_asprintf(mem_ctx, "%s\\bla\\blub",
						dirname));
	CHECK_STATUS(torture, status, NT_STATUS_DOS(ERRDOS, ERRbadpath));

	torture_assert_goto(torture, fpath = talloc_asprintf(mem_ctx, "%s\\%s", dirname, fname), 
			    ret, fail, "Could not allocate fpath\n");

	fnum = smbcli_open(cli_nt->tree, fpath, O_RDWR | O_CREAT, DENY_NONE);
	if (fnum == -1) {
		torture_result(torture, TORTURE_FAIL, "Could not create file %s: %s\n", fpath,
			 smbcli_errstr(cli_nt->tree));
		goto fail;
	}
	smbcli_close(cli_nt->tree, fnum);

	if (!(fpath1 = talloc_asprintf(mem_ctx, "%s\\%s", dirname, fname1))) {
		goto fail;
	}
	fnum = smbcli_open(cli_nt->tree, fpath1, O_RDWR | O_CREAT, DENY_NONE);
	if (fnum == -1) {
		torture_result(torture, TORTURE_FAIL, "Could not create file %s: %s\n", fpath1,
			 smbcli_errstr(cli_nt->tree));
		goto fail;
	}
	smbcli_close(cli_nt->tree, fnum);

	/*
	 * Do a whole bunch of error code checks on chkpath
	 */

	status = smbcli_chkpath(cli_nt->tree, fpath);
	CHECK_STATUS(torture, status, NT_STATUS_NOT_A_DIRECTORY);
	status = smbcli_chkpath(cli_dos->tree, fpath);
	CHECK_STATUS(torture, status, NT_STATUS_DOS(ERRDOS, ERRbadpath));

	status = smbcli_chkpath(cli_nt->tree, "..");
	CHECK_STATUS(torture, status, NT_STATUS_OBJECT_PATH_SYNTAX_BAD);
	status = smbcli_chkpath(cli_dos->tree, "..");
	CHECK_STATUS(torture, status, NT_STATUS_DOS(ERRDOS, ERRinvalidpath));

	status = smbcli_chkpath(cli_nt->tree, ".");
	CHECK_STATUS(torture, status, NT_STATUS_OBJECT_NAME_INVALID);
	status = smbcli_chkpath(cli_dos->tree, ".");
	CHECK_STATUS(torture, status, NT_STATUS_DOS(ERRDOS, ERRbadpath));

	status = smbcli_chkpath(cli_nt->tree, "\t");
	CHECK_STATUS(torture, status, NT_STATUS_OBJECT_NAME_INVALID);
	status = smbcli_chkpath(cli_dos->tree, "\t");
	CHECK_STATUS(torture, status, NT_STATUS_DOS(ERRDOS, ERRbadpath));

	status = smbcli_chkpath(cli_nt->tree, "\t\\bla");
	CHECK_STATUS(torture, status, NT_STATUS_OBJECT_NAME_INVALID);
	status = smbcli_chkpath(cli_dos->tree, "\t\\bla");
	CHECK_STATUS(torture, status, NT_STATUS_DOS(ERRDOS, ERRbadpath));

	status = smbcli_chkpath(cli_nt->tree, "<");
	CHECK_STATUS(torture, status, NT_STATUS_OBJECT_NAME_INVALID);
	status = smbcli_chkpath(cli_dos->tree, "<");
	CHECK_STATUS(torture, status, NT_STATUS_DOS(ERRDOS, ERRbadpath));

	status = smbcli_chkpath(cli_nt->tree, "<\\bla");
	CHECK_STATUS(torture, status, NT_STATUS_OBJECT_NAME_INVALID);
	status = smbcli_chkpath(cli_dos->tree, "<\\bla");
	CHECK_STATUS(torture, status, NT_STATUS_DOS(ERRDOS, ERRbadpath));

	/*
	 * .... And the same gang against getatr. Note that the DOS error codes
	 * differ....
	 */

	status = smbcli_getatr(cli_nt->tree, fpath, NULL, NULL, NULL);
	CHECK_STATUS(torture, status, NT_STATUS_OK);
	status = smbcli_getatr(cli_dos->tree, fpath, NULL, NULL, NULL);
	CHECK_STATUS(torture, status, NT_STATUS_OK);

	status = smbcli_getatr(cli_nt->tree, "..", NULL, NULL, NULL);
	CHECK_STATUS(torture, status, NT_STATUS_OBJECT_PATH_SYNTAX_BAD);
	status = smbcli_getatr(cli_dos->tree, "..", NULL, NULL, NULL);
	CHECK_STATUS(torture, status, NT_STATUS_DOS(ERRDOS, ERRinvalidpath));

	status = smbcli_getatr(cli_nt->tree, ".", NULL, NULL, NULL);
	CHECK_STATUS(torture, status, NT_STATUS_OBJECT_NAME_INVALID);
	status = smbcli_getatr(cli_dos->tree, ".", NULL, NULL, NULL);
	CHECK_STATUS(torture, status, NT_STATUS_DOS(ERRDOS, ERRinvalidname));

	status = smbcli_getatr(cli_nt->tree, "\t", NULL, NULL, NULL);
	CHECK_STATUS(torture, status, NT_STATUS_OBJECT_NAME_INVALID);
	status = smbcli_getatr(cli_dos->tree, "\t", NULL, NULL, NULL);
	CHECK_STATUS(torture, status, NT_STATUS_DOS(ERRDOS, ERRinvalidname));

	status = smbcli_getatr(cli_nt->tree, "\t\\bla", NULL, NULL, NULL);
	CHECK_STATUS(torture, status, NT_STATUS_OBJECT_NAME_INVALID);
	status = smbcli_getatr(cli_dos->tree, "\t\\bla", NULL, NULL, NULL);
	CHECK_STATUS(torture, status, NT_STATUS_DOS(ERRDOS, ERRinvalidname));

	status = smbcli_getatr(cli_nt->tree, "<", NULL, NULL, NULL);
	CHECK_STATUS(torture, status, NT_STATUS_OBJECT_NAME_INVALID);
	status = smbcli_getatr(cli_dos->tree, "<", NULL, NULL, NULL);
	CHECK_STATUS(torture, status, NT_STATUS_DOS(ERRDOS, ERRinvalidname));

	status = smbcli_getatr(cli_nt->tree, "<\\bla", NULL, NULL, NULL);
	CHECK_STATUS(torture, status, NT_STATUS_OBJECT_NAME_INVALID);
	status = smbcli_getatr(cli_dos->tree, "<\\bla", NULL, NULL, NULL);
	CHECK_STATUS(torture, status, NT_STATUS_DOS(ERRDOS, ERRinvalidname));

	/* Try the same set with openX. */

	status = raw_smbcli_open(cli_nt->tree, "..", O_RDONLY, DENY_NONE, NULL);
	CHECK_STATUS(torture, status, NT_STATUS_OBJECT_PATH_SYNTAX_BAD);
	status = raw_smbcli_open(cli_dos->tree, "..", O_RDONLY, DENY_NONE, NULL);
	CHECK_STATUS(torture, status, NT_STATUS_DOS(ERRDOS, ERRinvalidpath));

	status = raw_smbcli_open(cli_nt->tree, ".", O_RDONLY, DENY_NONE, NULL);
	CHECK_STATUS(torture, status, NT_STATUS_OBJECT_NAME_INVALID);
	status = raw_smbcli_open(cli_dos->tree, ".", O_RDONLY, DENY_NONE, NULL);
	CHECK_STATUS(torture, status, NT_STATUS_DOS(ERRDOS, ERRinvalidname));

	status = raw_smbcli_open(cli_nt->tree, "\t", O_RDONLY, DENY_NONE, NULL);
	CHECK_STATUS(torture, status, NT_STATUS_OBJECT_NAME_INVALID);
	status = raw_smbcli_open(cli_dos->tree, "\t", O_RDONLY, DENY_NONE, NULL);
	CHECK_STATUS(torture, status, NT_STATUS_DOS(ERRDOS, ERRinvalidname));

	status = raw_smbcli_open(cli_nt->tree, "\t\\bla", O_RDONLY, DENY_NONE, NULL);
	CHECK_STATUS(torture, status, NT_STATUS_OBJECT_NAME_INVALID);
	status = raw_smbcli_open(cli_dos->tree, "\t\\bla", O_RDONLY, DENY_NONE, NULL);
	CHECK_STATUS(torture, status, NT_STATUS_DOS(ERRDOS, ERRinvalidname));

	status = raw_smbcli_open(cli_nt->tree, "<", O_RDONLY, DENY_NONE, NULL);
	CHECK_STATUS(torture, status, NT_STATUS_OBJECT_NAME_INVALID);
	status = raw_smbcli_open(cli_dos->tree, "<", O_RDONLY, DENY_NONE, NULL);
	CHECK_STATUS(torture, status, NT_STATUS_DOS(ERRDOS, ERRinvalidname));

	status = raw_smbcli_open(cli_nt->tree, "<\\bla", O_RDONLY, DENY_NONE, NULL);
	CHECK_STATUS(torture, status, NT_STATUS_OBJECT_NAME_INVALID);
	status = raw_smbcli_open(cli_dos->tree, "<\\bla", O_RDONLY, DENY_NONE, NULL);
	CHECK_STATUS(torture, status, NT_STATUS_DOS(ERRDOS, ERRinvalidname));

	/* Let's test EEXIST error code mapping. */
	status = raw_smbcli_open(cli_nt->tree, fpath, O_RDONLY | O_CREAT| O_EXCL, DENY_NONE, NULL);
	CHECK_STATUS(torture, status, NT_STATUS_OBJECT_NAME_COLLISION);
	status = raw_smbcli_open(cli_dos->tree, fpath, O_RDONLY | O_CREAT| O_EXCL, DENY_NONE, NULL);
	CHECK_STATUS(torture, status, NT_STATUS_DOS(ERRDOS,ERRfilexists));

	status = raw_smbcli_t2open(cli_nt->tree, fpath, O_RDONLY | O_CREAT| O_EXCL, DENY_NONE, NULL);
	if (!NT_STATUS_EQUAL(status, NT_STATUS_EAS_NOT_SUPPORTED)
	    || !torture_setting_bool(torture, "samba3", false)) {
		/* Against samba3, treat EAS_NOT_SUPPORTED as acceptable */
		CHECK_STATUS(torture, status, NT_STATUS_OBJECT_NAME_COLLISION);
	}
	status = raw_smbcli_t2open(cli_dos->tree, fpath, O_RDONLY | O_CREAT| O_EXCL, DENY_NONE, NULL);
	if (!NT_STATUS_EQUAL(status, NT_STATUS_DOS(ERRDOS,ERReasnotsupported))
	    || !torture_setting_bool(torture, "samba3", false)) {
		/* Against samba3, treat EAS_NOT_SUPPORTED as acceptable */
		CHECK_STATUS(torture, status, NT_STATUS_DOS(ERRDOS,ERRfilexists));
	}

	status = raw_smbcli_ntcreate(cli_nt->tree, fpath, NULL);
	CHECK_STATUS(torture, status, NT_STATUS_OBJECT_NAME_COLLISION);
	status = raw_smbcli_ntcreate(cli_dos->tree, fpath, NULL);
	CHECK_STATUS(torture, status, NT_STATUS_DOS(ERRDOS,ERRfilexists));

	/* Try the rename test. */
	{
		union smb_rename io;
		memset(&io, '\0', sizeof(io));
		io.rename.in.pattern1 = fpath1;
		io.rename.in.pattern2 = fpath;

		/* Try with SMBmv rename. */
		status = smb_raw_rename(cli_nt->tree, &io);
		CHECK_STATUS(torture, status, NT_STATUS_OBJECT_NAME_COLLISION);
		status = smb_raw_rename(cli_dos->tree, &io);
		CHECK_STATUS(torture, status, NT_STATUS_DOS(ERRDOS,ERRrename));

		/* Try with NT rename. */
		io.generic.level = RAW_RENAME_NTRENAME;
		io.ntrename.in.old_name = fpath1;
		io.ntrename.in.new_name = fpath;
		io.ntrename.in.attrib = 0;
		io.ntrename.in.cluster_size = 0;
		io.ntrename.in.flags = RENAME_FLAG_RENAME;

		status = smb_raw_rename(cli_nt->tree, &io);
		CHECK_STATUS(torture, status, NT_STATUS_OBJECT_NAME_COLLISION);
		status = smb_raw_rename(cli_dos->tree, &io);
		CHECK_STATUS(torture, status, NT_STATUS_DOS(ERRDOS,ERRrename));
	}

	goto done;

 fail:
	ret = false;

 done:
	if (cli_nt != NULL) {
		smbcli_deltree(cli_nt->tree, dirname);
		torture_close_connection(cli_nt);
	}
	if (cli_dos != NULL) {
		torture_close_connection(cli_dos);
	}
	talloc_free(mem_ctx);

	return ret;
}
示例#21
0
bool torture_samba3_checkfsp(struct torture_context *torture, struct smbcli_state *cli)
{
	const char *fname = "test.txt";
	const char *dirname = "testdir";
	int fnum;
	NTSTATUS status;
	bool ret = true;
	TALLOC_CTX *mem_ctx;
	ssize_t nread;
	char buf[16];
	struct smbcli_tree *tree2;

	torture_assert(torture, mem_ctx = talloc_init("torture_samba3_checkfsp"), "talloc_init failed\n");

	torture_assert_ntstatus_equal(torture, torture_second_tcon(torture, cli->session,
								   torture_setting_string(torture, "share", NULL),
								   &tree2), 
				      NT_STATUS_OK,
				      "creating second tcon");

	/* Try a read on an invalid FID */

	nread = smbcli_read(cli->tree, 4711, buf, 0, sizeof(buf));
	CHECK_STATUS(torture, smbcli_nt_error(cli->tree), NT_STATUS_INVALID_HANDLE);

	/* Try a read on a directory handle */

	torture_assert(torture, torture_setup_dir(cli, dirname), "creating test directory");

	/* Open the directory */
	{
		union smb_open io;
		io.generic.level = RAW_OPEN_NTCREATEX;
		io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED;
		io.ntcreatex.in.root_fid.fnum = 0;
		io.ntcreatex.in.security_flags = 0;
		io.ntcreatex.in.open_disposition = NTCREATEX_DISP_CREATE;
		io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
		io.ntcreatex.in.alloc_size = 0;
		io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_DIRECTORY;
		io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
		io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN;
		io.ntcreatex.in.create_options = 0;
		io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
		io.ntcreatex.in.fname = dirname;
		status = smb_raw_open(cli->tree, mem_ctx, &io);
		if (!NT_STATUS_IS_OK(status)) {
			torture_result(torture, TORTURE_FAIL, "smb_open on the directory failed: %s\n",
				 nt_errstr(status));
			ret = false;
			goto done;
		}
		fnum = io.ntcreatex.out.file.fnum;
	}

	/* Try a read on the directory */

	nread = smbcli_read(cli->tree, fnum, buf, 0, sizeof(buf));
	if (nread >= 0) {
		torture_result(torture, TORTURE_FAIL, "smbcli_read on a directory succeeded, expected "
			 "failure\n");
		ret = false;
	}

	CHECK_STATUS(torture, smbcli_nt_error(cli->tree),
		     NT_STATUS_INVALID_DEVICE_REQUEST);

	/* Same test on the second tcon */

	nread = smbcli_read(tree2, fnum, buf, 0, sizeof(buf));
	if (nread >= 0) {
		torture_result(torture, TORTURE_FAIL, "smbcli_read on a directory succeeded, expected "
			 "failure\n");
		ret = false;
	}

	CHECK_STATUS(torture, smbcli_nt_error(tree2), NT_STATUS_INVALID_HANDLE);

	smbcli_close(cli->tree, fnum);

	/* Try a normal file read on a second tcon */

	fnum = smbcli_open(cli->tree, fname, O_RDWR|O_CREAT, DENY_NONE);
	if (fnum == -1) {
		torture_result(torture, TORTURE_FAIL, "Failed to create %s - %s\n", fname,
			 smbcli_errstr(cli->tree));
		ret = false;
		goto done;
	}

	nread = smbcli_read(tree2, fnum, buf, 0, sizeof(buf));
	CHECK_STATUS(torture, smbcli_nt_error(tree2), NT_STATUS_INVALID_HANDLE);

	smbcli_close(cli->tree, fnum);

 done:
	smbcli_deltree(cli->tree, dirname);
	talloc_free(mem_ctx);

	return ret;
}
示例#22
0
文件: rename.c 项目: 0x24bin/winexe-1
/*
  Test rename on files open with share delete and no share delete.
 */
bool torture_test_rename(struct torture_context *tctx, 
			 struct smbcli_state *cli1)
{
	const char *fname = "\\test.txt";
	const char *fname1 = "\\test1.txt";
	int fnum1;

	smbcli_unlink(cli1->tree, fname);
	smbcli_unlink(cli1->tree, fname1);
	fnum1 = smbcli_nt_create_full(cli1->tree, fname, 0, 
				      SEC_RIGHTS_FILE_READ, 
				      FILE_ATTRIBUTE_NORMAL,
				      NTCREATEX_SHARE_ACCESS_READ, 
				      NTCREATEX_DISP_OVERWRITE_IF, 0, 0);

	torture_assert(tctx, fnum1 != -1, talloc_asprintf(tctx, "First open failed - %s", 
		       smbcli_errstr(cli1->tree)));

	torture_assert(tctx, NT_STATUS_IS_ERR(smbcli_rename(cli1->tree, fname, fname1)), 
					"First rename succeeded - this should have failed !");

	torture_assert_ntstatus_ok(tctx, smbcli_close(cli1->tree, fnum1),
		talloc_asprintf(tctx, "close - 1 failed (%s)", smbcli_errstr(cli1->tree)));

	smbcli_unlink(cli1->tree, fname);
	smbcli_unlink(cli1->tree, fname1);
	fnum1 = smbcli_nt_create_full(cli1->tree, fname, 0, 
				      SEC_RIGHTS_FILE_READ, 
				      FILE_ATTRIBUTE_NORMAL,
				      NTCREATEX_SHARE_ACCESS_DELETE|NTCREATEX_SHARE_ACCESS_READ, 
				      NTCREATEX_DISP_OVERWRITE_IF, 0, 0);

	torture_assert(tctx, fnum1 != -1, talloc_asprintf(tctx, 
				   "Second open failed - %s", smbcli_errstr(cli1->tree)));

	torture_assert_ntstatus_ok(tctx, smbcli_rename(cli1->tree, fname, fname1),
		talloc_asprintf(tctx, 
				"Second rename failed - this should have succeeded - %s", 
		       smbcli_errstr(cli1->tree)));

	torture_assert_ntstatus_ok(tctx, smbcli_close(cli1->tree, fnum1),
		talloc_asprintf(tctx, 
		"close - 2 failed (%s)", smbcli_errstr(cli1->tree)));

	smbcli_unlink(cli1->tree, fname);
	smbcli_unlink(cli1->tree, fname1);

	fnum1 = smbcli_nt_create_full(cli1->tree, fname, 0, 
				      SEC_STD_READ_CONTROL, 
				      FILE_ATTRIBUTE_NORMAL,
				      NTCREATEX_SHARE_ACCESS_NONE, 
				      NTCREATEX_DISP_OVERWRITE_IF, 0, 0);

	torture_assert(tctx, fnum1 != -1, talloc_asprintf(tctx, "Third open failed - %s", 
			smbcli_errstr(cli1->tree)));

	torture_assert_ntstatus_ok(tctx, smbcli_rename(cli1->tree, fname, fname1),
		talloc_asprintf(tctx, "Third rename failed - this should have succeeded - %s", 
		       smbcli_errstr(cli1->tree)));

	torture_assert_ntstatus_ok(tctx, smbcli_close(cli1->tree, fnum1), 
		talloc_asprintf(tctx, "close - 3 failed (%s)", smbcli_errstr(cli1->tree)));

	smbcli_unlink(cli1->tree, fname);
	smbcli_unlink(cli1->tree, fname1);

	return true;
}
示例#23
0
bool unix_torture_unix_info2(struct torture_context *torture)
{
	void *mem_ctx;
	struct smbcli_state *cli;
	int fnum;

	struct unix_info2 pinfo, finfo;

	mem_ctx = talloc_init("smb_query_unix_info2");
	torture_assert(torture, mem_ctx != NULL, "out of memory");

	if (!(cli = connect_to_server(torture))) {
		talloc_free(mem_ctx);
		return false;
	}

	smbcli_unlink(cli->tree, FILENAME);

	fnum = create_file(cli, FILENAME);
	torture_assert(torture, fnum != -1, smbcli_errstr(cli->tree));

	printf("checking SMB_QFILEINFO_UNIX_INFO2 for QueryFileInfo\n");
	if (!query_file_info2(mem_ctx, torture, cli, fnum, &finfo)) {
		goto fail;
	}

	printf("checking SMB_QFILEINFO_UNIX_INFO2 for QueryPathInfo\n");
	if (!query_path_info2(mem_ctx, torture, cli, FILENAME, &pinfo)) {
		goto fail;
	}

	if (!match_info2(torture, &pinfo, &finfo)) {
		goto fail;
	}

	printf("checking SMB_FIND_UNIX_INFO2 for FindFirst\n");
	if (!find_single_info2(mem_ctx, torture, cli, FILENAME, &pinfo)) {
		goto fail;
	}

	if (!match_info2(torture, &pinfo, &finfo)) {
		goto fail;
	}

	/* XXX: should repeat this test with SetFileInfo. */
	printf("checking SMB_SFILEINFO_UNIX_INFO2 for SetPathInfo\n");
	if (!verify_setinfo_flags(mem_ctx, torture, cli, FILENAME)) {
		goto fail;
	}

	smbcli_close(cli->tree, fnum);
	smbcli_unlink(cli->tree, FILENAME);
	torture_close_connection(cli);
	talloc_free(mem_ctx);
	return true;

fail:

	smbcli_close(cli->tree, fnum);
	smbcli_unlink(cli->tree, FILENAME);
	torture_close_connection(cli);
	talloc_free(mem_ctx);
	return false;

}
示例#24
0
文件: misc.c 项目: endisd/samba
/*
test how many open files this server supports on the one socket
*/
bool run_maxfidtest(struct torture_context *tctx, struct smbcli_state *cli, int dummy)
{
#define MAXFID_TEMPLATE "\\maxfid\\fid%d\\maxfid.%d.%d"
	char *fname;
	int fnums[0x11000], i;
	int retries=4, maxfid;
	bool correct = true;

	if (retries <= 0) {
		torture_comment(tctx, "failed to connect\n");
		return false;
	}

	if (smbcli_deltree(cli->tree, "\\maxfid") == -1) {
		torture_comment(tctx, "Failed to deltree \\maxfid - %s\n",
		       smbcli_errstr(cli->tree));
		return false;
	}
	if (NT_STATUS_IS_ERR(smbcli_mkdir(cli->tree, "\\maxfid"))) {
		torture_comment(tctx, "Failed to mkdir \\maxfid, error=%s\n", 
		       smbcli_errstr(cli->tree));
		return false;
	}

	torture_comment(tctx, "Testing maximum number of open files\n");

	for (i=0; i<0x11000; i++) {
		if (i % 1000 == 0) {
			asprintf(&fname, "\\maxfid\\fid%d", i/1000);
			if (NT_STATUS_IS_ERR(smbcli_mkdir(cli->tree, fname))) {
				torture_comment(tctx, "Failed to mkdir %s, error=%s\n", 
				       fname, smbcli_errstr(cli->tree));
				return false;
			}
			free(fname);
		}
		asprintf(&fname, MAXFID_TEMPLATE, i/1000, i,(int)getpid());
		if ((fnums[i] = smbcli_open(cli->tree, fname, 
					O_RDWR|O_CREAT|O_TRUNC, DENY_NONE)) ==
		    -1) {
			torture_comment(tctx, "open of %s failed (%s)\n", 
			       fname, smbcli_errstr(cli->tree));
			torture_comment(tctx, "maximum fnum is %d\n", i);
			break;
		}
		free(fname);
		if (torture_setting_bool(tctx, "progress", true)) {
			torture_comment(tctx, "%6d\r", i);
			fflush(stdout);
		}
	}
	torture_comment(tctx, "%6d\n", i);
	i--;

	maxfid = i;

	torture_comment(tctx, "cleaning up\n");
	for (i=0;i<maxfid/2;i++) {
		asprintf(&fname, MAXFID_TEMPLATE, i/1000, i,(int)getpid());
		if (NT_STATUS_IS_ERR(smbcli_close(cli->tree, fnums[i]))) {
			torture_comment(tctx, "Close of fnum %d failed - %s\n", fnums[i], smbcli_errstr(cli->tree));
		}
		if (NT_STATUS_IS_ERR(smbcli_unlink(cli->tree, fname))) {
			torture_comment(tctx, "unlink of %s failed (%s)\n", 
			       fname, smbcli_errstr(cli->tree));
			correct = false;
		}
		free(fname);

		asprintf(&fname, MAXFID_TEMPLATE, (maxfid-i)/1000, maxfid-i,(int)getpid());
		if (NT_STATUS_IS_ERR(smbcli_close(cli->tree, fnums[maxfid-i]))) {
			torture_comment(tctx, "Close of fnum %d failed - %s\n", fnums[maxfid-i], smbcli_errstr(cli->tree));
		}
		if (NT_STATUS_IS_ERR(smbcli_unlink(cli->tree, fname))) {
			torture_comment(tctx, "unlink of %s failed (%s)\n", 
			       fname, smbcli_errstr(cli->tree));
			correct = false;
		}
		free(fname);

		if (torture_setting_bool(tctx, "progress", true)) {
			torture_comment(tctx, "%6d %6d\r", i, maxfid-i);
			fflush(stdout);
		}
	}
	torture_comment(tctx, "%6d\n", 0);

	if (smbcli_deltree(cli->tree, "\\maxfid") == -1) {
		torture_comment(tctx, "Failed to deltree \\maxfid - %s\n",
		       smbcli_errstr(cli->tree));
		return false;
	}

	torture_comment(tctx, "maxfid test finished\n");
	if (!torture_close_connection(cli)) {
		correct = false;
	}
	return correct;
#undef MAXFID_TEMPLATE
}
示例#25
0
文件: misc.c 项目: endisd/samba
static bool rw_torture(struct torture_context *tctx, struct smbcli_state *c)
{
	const char *lockfname = "\\torture.lck";
	char *fname;
	int fnum;
	int fnum2;
	pid_t pid2, pid = getpid();
	int i, j;
	uint8_t buf[1024];
	bool correct = true;

	fnum2 = smbcli_open(c->tree, lockfname, O_RDWR | O_CREAT | O_EXCL, 
			 DENY_NONE);
	if (fnum2 == -1)
		fnum2 = smbcli_open(c->tree, lockfname, O_RDWR, DENY_NONE);
	if (fnum2 == -1) {
		torture_comment(tctx, "open of %s failed (%s)\n", lockfname, smbcli_errstr(c->tree));
		return false;
	}

	generate_random_buffer(buf, sizeof(buf));

	for (i=0;i<torture_numops;i++) {
		uint_t n = (uint_t)random()%10;
		if (i % 10 == 0) {
			if (torture_setting_bool(tctx, "progress", true)) {
				torture_comment(tctx, "%d\r", i);
				fflush(stdout);
			}
		}
		asprintf(&fname, "\\torture.%u", n);

		if (!wait_lock(c, fnum2, n*sizeof(int), sizeof(int))) {
			return false;
		}

		fnum = smbcli_open(c->tree, fname, O_RDWR | O_CREAT | O_TRUNC, DENY_ALL);
		if (fnum == -1) {
			torture_comment(tctx, "open failed (%s)\n", smbcli_errstr(c->tree));
			correct = false;
			break;
		}

		if (smbcli_write(c->tree, fnum, 0, &pid, 0, sizeof(pid)) != sizeof(pid)) {
			torture_comment(tctx, "write failed (%s)\n", smbcli_errstr(c->tree));
			correct = false;
		}

		for (j=0;j<50;j++) {
			if (smbcli_write(c->tree, fnum, 0, buf, 
				      sizeof(pid)+(j*sizeof(buf)), 
				      sizeof(buf)) != sizeof(buf)) {
				torture_comment(tctx, "write failed (%s)\n", smbcli_errstr(c->tree));
				correct = false;
			}
		}

		pid2 = 0;

		if (smbcli_read(c->tree, fnum, &pid2, 0, sizeof(pid)) != sizeof(pid)) {
			torture_comment(tctx, "read failed (%s)\n", smbcli_errstr(c->tree));
			correct = false;
		}

		if (pid2 != pid) {
			torture_comment(tctx, "data corruption!\n");
			correct = false;
		}

		if (NT_STATUS_IS_ERR(smbcli_close(c->tree, fnum))) {
			torture_comment(tctx, "close failed (%s)\n", smbcli_errstr(c->tree));
			correct = false;
		}

		if (NT_STATUS_IS_ERR(smbcli_unlink(c->tree, fname))) {
			torture_comment(tctx, "unlink failed (%s)\n", smbcli_errstr(c->tree));
			correct = false;
		}

		if (NT_STATUS_IS_ERR(smbcli_unlock(c->tree, fnum2, n*sizeof(int), sizeof(int)))) {
			torture_comment(tctx, "unlock failed (%s)\n", smbcli_errstr(c->tree));
			correct = false;
		}
		free(fname);
	}

	smbcli_close(c->tree, fnum2);
	smbcli_unlink(c->tree, lockfname);

	torture_comment(tctx, "%d\n", i);

	return correct;
}
示例#26
0
bool torture_samba3_posixtimedlock(struct torture_context *tctx, struct smbcli_state *cli)
{
	NTSTATUS status;
	bool ret = true;
	const char *dirname = "posixlock";
	const char *fname = "locked";
	const char *fpath;
	const char *localdir;
	const char *localname;
	int fnum = -1;

	int fd = -1;
	struct flock posix_lock;

	union smb_lock io;
	struct smb_lock_entry lock_entry;
	struct smbcli_request *req;
	struct lock_result_state lock_result;

	struct tevent_timer *te;

	torture_assert(tctx, torture_setup_dir(cli, dirname), "creating test directory");

	if (!(fpath = talloc_asprintf(tctx, "%s\\%s", dirname, fname))) {
		torture_warning(tctx, "talloc failed\n");
		ret = false;
		goto done;
	}
	fnum = smbcli_open(cli->tree, fpath, O_RDWR | O_CREAT, DENY_NONE);
	if (fnum == -1) {
		torture_warning(tctx, "Could not create file %s: %s\n", fpath,
				smbcli_errstr(cli->tree));
		ret = false;
		goto done;
	}

	if (!(localdir = torture_setting_string(tctx, "localdir", NULL))) {
		torture_warning(tctx, "Need 'localdir' setting\n");
		ret = false;
		goto done;
	}

	if (!(localname = talloc_asprintf(tctx, "%s/%s/%s", localdir, dirname,
					  fname))) {
		torture_warning(tctx, "talloc failed\n");
		ret = false;
		goto done;
	}

	/*
	 * Lock a byte range from posix
	 */

	fd = open(localname, O_RDWR);
	if (fd == -1) {
		torture_warning(tctx, "open(%s) failed: %s\n",
				localname, strerror(errno));
		goto done;
	}

	posix_lock.l_type = F_WRLCK;
	posix_lock.l_whence = SEEK_SET;
	posix_lock.l_start = 0;
	posix_lock.l_len = 1;

	if (fcntl(fd, F_SETLK, &posix_lock) == -1) {
		torture_warning(tctx, "fcntl failed: %s\n", strerror(errno));
		ret = false;
		goto done;
	}

	/*
	 * Try a cifs brlock without timeout to see if posix locking = yes
	 */

	io.lockx.in.ulock_cnt = 0;
	io.lockx.in.lock_cnt = 1;

	lock_entry.count = 1;
	lock_entry.offset = 0;
	lock_entry.pid = cli->tree->session->pid;

	io.lockx.level = RAW_LOCK_LOCKX;
	io.lockx.in.mode = LOCKING_ANDX_LARGE_FILES;
	io.lockx.in.timeout = 0;
	io.lockx.in.locks = &lock_entry;
	io.lockx.in.file.fnum = fnum;

	status = smb_raw_lock(cli->tree, &io);

	ret = true;
	CHECK_STATUS(tctx, status, NT_STATUS_FILE_LOCK_CONFLICT);

	if (!ret) {
		goto done;
	}

	/*
	 * Now fire off a timed brlock, unlock the posix lock and see if the
	 * timed lock gets through.
	 */

	io.lockx.in.timeout = 5000;

	req = smb_raw_lock_send(cli->tree, &io);
	if (req == NULL) {
		torture_warning(tctx, "smb_raw_lock_send failed\n");
		ret = false;
		goto done;
	}

	lock_result.done = false;
	req->async.fn = receive_lock_result;
	req->async.private_data = &lock_result;

	te = tevent_add_timer(tctx->ev,
			      tctx, timeval_current_ofs(1, 0),
			      close_locked_file, &fd);
	if (te == NULL) {
		torture_warning(tctx, "tevent_add_timer failed\n");
		ret = false;
		goto done;
	}

	while ((fd != -1) || (!lock_result.done)) {
		if (tevent_loop_once(tctx->ev) == -1) {
			torture_warning(tctx, "tevent_loop_once failed: %s\n",
					strerror(errno));
			ret = false;
			goto done;
		}
	}

	CHECK_STATUS(tctx, lock_result.status, NT_STATUS_OK);

 done:
	if (fnum != -1) {
		smbcli_close(cli->tree, fnum);
	}
	if (fd != -1) {
		close(fd);
	}
	smbcli_deltree(cli->tree, dirname);
	return ret;
}
示例#27
0
/*
  test seek ops
*/
static BOOL test_seek(struct smbcli_state *cli, TALLOC_CTX *mem_ctx)
{
	union smb_seek io;
	union smb_fileinfo finfo;
	union smb_setfileinfo sfinfo;
	NTSTATUS status;
	BOOL ret = True;
	int fnum, fnum2;
	const char *fname = BASEDIR "\\test.txt";
	uint8_t c[2];

	if (!torture_setup_dir(cli, BASEDIR)) {
		return False;
	}

	fnum = smbcli_open(cli->tree, fname, O_RDWR|O_CREAT|O_TRUNC, DENY_NONE);
	if (fnum == -1) {
		printf("Failed to open test.txt - %s\n", smbcli_errstr(cli->tree));
		ret = False;
		goto done;
	}

	finfo.generic.level = RAW_FILEINFO_POSITION_INFORMATION;
	finfo.position_information.in.file.fnum = fnum;
	
	printf("Trying bad handle\n");
	io.lseek.in.file.fnum = fnum+1;
	io.lseek.in.mode = SEEK_MODE_START;
	io.lseek.in.offset = 0;
	status = smb_raw_seek(cli->tree, &io);
	CHECK_STATUS(status, NT_STATUS_INVALID_HANDLE);

	printf("Trying simple seek\n");
	io.lseek.in.file.fnum = fnum;
	io.lseek.in.mode = SEEK_MODE_START;
	io.lseek.in.offset = 17;
	status = smb_raw_seek(cli->tree, &io);
	CHECK_STATUS(status, NT_STATUS_OK);
	CHECK_VALUE(io.lseek.out.offset, 17);
	status = smb_raw_fileinfo(cli->tree, mem_ctx, &finfo);
	CHECK_STATUS(status, NT_STATUS_OK);
	CHECK_VALUE(finfo.position_information.out.position, 0);
	
	printf("Trying relative seek\n");
	io.lseek.in.file.fnum = fnum;
	io.lseek.in.mode = SEEK_MODE_CURRENT;
	io.lseek.in.offset = -3;
	status = smb_raw_seek(cli->tree, &io);
	CHECK_STATUS(status, NT_STATUS_OK);
	CHECK_VALUE(io.lseek.out.offset, 14);

	printf("Trying end seek\n");
	io.lseek.in.file.fnum = fnum;
	io.lseek.in.mode = SEEK_MODE_END;
	io.lseek.in.offset = 0;
	status = smb_raw_seek(cli->tree, &io);
	CHECK_STATUS(status, NT_STATUS_OK);
	finfo.generic.level = RAW_FILEINFO_ALL_INFO;
	finfo.all_info.in.file.fnum = fnum;
	status = smb_raw_fileinfo(cli->tree, mem_ctx, &finfo);
	CHECK_STATUS(status, NT_STATUS_OK);
	CHECK_VALUE(io.lseek.out.offset, finfo.all_info.out.size);

	printf("Trying max seek\n");
	io.lseek.in.file.fnum = fnum;
	io.lseek.in.mode = SEEK_MODE_START;
	io.lseek.in.offset = -1;
	status = smb_raw_seek(cli->tree, &io);
	CHECK_STATUS(status, NT_STATUS_OK);
	CHECK_VALUE(io.lseek.out.offset, 0xffffffff);

	printf("Testing position information change\n");
	finfo.generic.level = RAW_FILEINFO_POSITION_INFORMATION;
	finfo.position_information.in.file.fnum = fnum;
	status = smb_raw_fileinfo(cli->tree, mem_ctx, &finfo);
	CHECK_STATUS(status, NT_STATUS_OK);
	CHECK_VALUE(finfo.position_information.out.position, 0);

	printf("Trying max overflow\n");
	io.lseek.in.file.fnum = fnum;
	io.lseek.in.mode = SEEK_MODE_CURRENT;
	io.lseek.in.offset = 1000;
	status = smb_raw_seek(cli->tree, &io);
	CHECK_STATUS(status, NT_STATUS_OK);
	CHECK_VALUE(io.lseek.out.offset, 999);

	printf("Testing position information change\n");
	finfo.generic.level = RAW_FILEINFO_POSITION_INFORMATION;
	finfo.position_information.in.file.fnum = fnum;
	status = smb_raw_fileinfo(cli->tree, mem_ctx, &finfo);
	CHECK_STATUS(status, NT_STATUS_OK);
	CHECK_VALUE(finfo.position_information.out.position, 0);

	printf("trying write to update offset\n");
	ZERO_STRUCT(c);
	if (smbcli_write(cli->tree, fnum, 0, c, 0, 2) != 2) {
		printf("Write failed - %s\n", smbcli_errstr(cli->tree));
		ret = False;
		goto done;		
	}

	printf("Testing position information change\n");
	finfo.generic.level = RAW_FILEINFO_POSITION_INFORMATION;
	finfo.position_information.in.file.fnum = fnum;
	status = smb_raw_fileinfo(cli->tree, mem_ctx, &finfo);
	CHECK_STATUS(status, NT_STATUS_OK);
	CHECK_VALUE(finfo.position_information.out.position, 0);

	io.lseek.in.file.fnum = fnum;
	io.lseek.in.mode = SEEK_MODE_CURRENT;
	io.lseek.in.offset = 0;
	status = smb_raw_seek(cli->tree, &io);
	CHECK_STATUS(status, NT_STATUS_OK);
	CHECK_VALUE(io.lseek.out.offset, 2);
	
	if (smbcli_read(cli->tree, fnum, c, 0, 1) != 1) {
		printf("Read failed - %s\n", smbcli_errstr(cli->tree));
		ret = False;
		goto done;		
	}

	printf("Testing position information change\n");
	finfo.generic.level = RAW_FILEINFO_POSITION_INFORMATION;
	finfo.position_information.in.file.fnum = fnum;
	status = smb_raw_fileinfo(cli->tree, mem_ctx, &finfo);
	CHECK_STATUS(status, NT_STATUS_OK);
	CHECK_VALUE(finfo.position_information.out.position, 1);

	status = smb_raw_seek(cli->tree, &io);
	CHECK_STATUS(status, NT_STATUS_OK);
	CHECK_VALUE(io.lseek.out.offset, 1);

	printf("Testing position information\n");
	fnum2 = smbcli_open(cli->tree, fname, O_RDWR, DENY_NONE);
	if (fnum2 == -1) {
		printf("2nd open failed - %s\n", smbcli_errstr(cli->tree));
		ret = False;
		goto done;
	}
	sfinfo.generic.level = RAW_SFILEINFO_POSITION_INFORMATION;
	sfinfo.position_information.in.file.fnum = fnum2;
	sfinfo.position_information.in.position = 25;
	status = smb_raw_setfileinfo(cli->tree, &sfinfo);
	CHECK_STATUS(status, NT_STATUS_OK);

	finfo.generic.level = RAW_FILEINFO_POSITION_INFORMATION;
	finfo.position_information.in.file.fnum = fnum2;
	status = smb_raw_fileinfo(cli->tree, mem_ctx, &finfo);
	CHECK_STATUS(status, NT_STATUS_OK);
	CHECK_VALUE(finfo.position_information.out.position, 25);

	finfo.generic.level = RAW_FILEINFO_POSITION_INFORMATION;
	finfo.position_information.in.file.fnum = fnum;
	status = smb_raw_fileinfo(cli->tree, mem_ctx, &finfo);
	CHECK_STATUS(status, NT_STATUS_OK);
	CHECK_VALUE(finfo.position_information.out.position, 1);

	printf("position_information via paths\n");

	sfinfo.generic.level = RAW_SFILEINFO_POSITION_INFORMATION;
	sfinfo.position_information.in.file.path = fname;
	sfinfo.position_information.in.position = 32;
	status = smb_raw_setpathinfo(cli->tree, &sfinfo);
	CHECK_STATUS(status, NT_STATUS_OK);

	finfo.generic.level = RAW_FILEINFO_POSITION_INFORMATION;
	finfo.position_information.in.file.fnum = fnum2;
	status = smb_raw_fileinfo(cli->tree, mem_ctx, &finfo);
	CHECK_STATUS(status, NT_STATUS_OK);
	CHECK_VALUE(finfo.position_information.out.position, 25);

	finfo.generic.level = RAW_FILEINFO_POSITION_INFORMATION;
	finfo.position_information.in.file.path = fname;
	status = smb_raw_pathinfo(cli->tree, mem_ctx, &finfo);
	CHECK_STATUS(status, NT_STATUS_OK);
	CHECK_VALUE(finfo.position_information.out.position, 0);
	

done:
	smb_raw_exit(cli->session);
	smbcli_deltree(cli->tree, BASEDIR);
	return ret;
}
示例#28
0
/* basic testing of all RAW_SFILEINFO_* calls
   for each call we test that it succeeds, and where possible test
   for consistency between the calls.
*/
static bool
torture_raw_sfileinfo_base(struct torture_context *torture, struct smbcli_state *cli)
{
    bool ret = true;
    int fnum = -1;
    char *fnum_fname;
    char *fnum_fname_new;
    char *path_fname;
    char *path_fname_new;
    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;
    int n = time(NULL) % 100;

    asprintf(&path_fname, BASEDIR "\\fname_test_%d.txt", n);
    asprintf(&path_fname_new, BASEDIR "\\fname_test_new_%d.txt", n);
    asprintf(&fnum_fname, BASEDIR "\\fnum_test_%d.txt", n);
    asprintf(&fnum_fname_new, BASEDIR "\\fnum_test_new_%d.txt", n);

    if (!torture_setup_dir(cli, BASEDIR)) {
        return false;
    }

#define RECREATE_FILE(fname) do { \
	if (fnum != -1) smbcli_close(cli->tree, fnum); \
	fnum = create_complex_file(cli, torture, fname); \
	if (fnum == -1) { \
		printf("(%s) ERROR: open of %s failed (%s)\n", \
		       __location__, fname, smbcli_errstr(cli->tree)); \
		ret = false; \
		goto done; \
	}} while (0)

#define RECREATE_BOTH do { \
		RECREATE_FILE(path_fname); \
		smbcli_close(cli->tree, 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.in.file.fnum = fnum; \
	status = smb_raw_setfileinfo(cli->tree, &sfinfo); \
	if (NT_STATUS_EQUAL(status, NT_STATUS_NOT_SUPPORTED)) { \
                torture_warning(torture, \
			"(%s) %s - %s", __location__, #call, \
                        nt_errstr(status)); \
        } else if (!NT_STATUS_EQUAL(status, rightstatus)) { \
		printf("(%s) %s - %s (should be %s)\n", __location__, #call, \
			nt_errstr(status), nt_errstr(rightstatus)); \
		ret = false; \
	} \
	finfo1.generic.level = RAW_FILEINFO_ALL_INFO; \
	finfo1.generic.in.file.fnum = fnum; \
	status2 = smb_raw_fileinfo(cli->tree, torture, &finfo1); \
	if (NT_STATUS_EQUAL(status, NT_STATUS_NOT_SUPPORTED)) { \
                torture_warning(torture, \
			"(%s) %s - %s", __location__, #call, \
                        nt_errstr(status)); \
        } else if (!NT_STATUS_IS_OK(status2)) { \
		printf("(%s) %s pathinfo - %s\n", __location__, #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.in.file.path = path_fname; \
	status = smb_raw_setpathinfo(cli->tree, &sfinfo); \
	if (NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) { \
		sfinfo.generic.in.file.path = path_fname_new; \
		status = smb_raw_setpathinfo(cli->tree, &sfinfo); \
	} \
	if (NT_STATUS_EQUAL(status, NT_STATUS_NOT_SUPPORTED)) { \
                torture_warning(torture, \
			"(%s) %s - %s", __location__, #call, \
                        nt_errstr(status)); \
        } else if (!NT_STATUS_EQUAL(status, rightstatus)) { \
		printf("(%s) %s - %s (should be %s)\n", __location__, #call, \
			nt_errstr(status), nt_errstr(rightstatus)); \
		ret = false; \
	} \
	finfo1.generic.level = RAW_FILEINFO_ALL_INFO; \
	finfo1.generic.in.file.path = path_fname; \
	status2 = smb_raw_pathinfo(cli->tree, torture, &finfo1); \
	if (NT_STATUS_EQUAL(status2, NT_STATUS_OBJECT_NAME_NOT_FOUND)) { \
		finfo1.generic.in.file.path = path_fname_new; \
		status2 = smb_raw_pathinfo(cli->tree, torture, &finfo1); \
	} \
	if (NT_STATUS_EQUAL(status, NT_STATUS_NOT_SUPPORTED)) { \
                torture_warning(torture, \
			"(%s) %s - %s", __location__, #call, \
                        nt_errstr(status)); \
        } else if (!NT_STATUS_IS_OK(status2)) { \
		printf("(%s) %s pathinfo - %s\n", __location__, #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.file.fnum = fnum; \
			status2 = smb_raw_fileinfo(cli->tree, torture, &finfo2); \
		} else { \
			finfo2.generic.in.file.path = path_fname; \
			status2 = smb_raw_pathinfo(cli->tree, torture, &finfo2); \
			if (NT_STATUS_EQUAL(status2, NT_STATUS_OBJECT_NAME_NOT_FOUND)) { \
				finfo2.generic.in.file.path = path_fname_new; \
				status2 = smb_raw_pathinfo(cli->tree, torture, &finfo2); \
			} \
		} \
		if (!NT_STATUS_IS_OK(status2)) { \
			printf("%s - %s\n", #call, nt_errstr(status2)); \
			ret = false; \
		} \
	}} while (0)

#define CHECK_VALUE(call, stype, field, value) do { \
 	CHECK1(call); \
	if (NT_STATUS_IS_OK(status) && NT_STATUS_IS_OK(status2) && finfo2.stype.out.field != value) { \
		printf("(%s) %s - %s/%s should be 0x%x - 0x%x\n", __location__, \
		       call_name, #stype, #field, \
		       (unsigned int)value, (unsigned int)finfo2.stype.out.field); \
		dump_all_info(torture, &finfo1); \
		ret = false; \
	}} while (0)

#define CHECK_TIME(call, stype, field, value) do { \
 	CHECK1(call); \
	if (NT_STATUS_IS_OK(status) && NT_STATUS_IS_OK(status2) && nt_time_to_unix(finfo2.stype.out.field) != value) { \
		printf("(%s) %s - %s/%s should be 0x%x - 0x%x\n", __location__, \
		        call_name, #stype, #field, \
		        (unsigned int)value, \
			(unsigned int)nt_time_to_unix(finfo2.stype.out.field)); \
		printf("\t%s", timestring(torture, value)); \
		printf("\t%s\n", nt_time_string(torture, finfo2.stype.out.field)); \
		dump_all_info(torture, &finfo1); \
		ret = false; \
	}} while (0)

#define CHECK_STR(call, stype, field, value) do { \
 	CHECK1(call); \
	if (NT_STATUS_IS_OK(status) && NT_STATUS_IS_OK(status2) && strcmp(finfo2.stype.out.field, value) != 0) { \
		printf("(%s) %s - %s/%s should be '%s' - '%s'\n", __location__, \
		        call_name, #stype, #field, \
		        value, \
			finfo2.stype.out.field); \
		dump_all_info(torture, &finfo1); \
		ret = false; \
	}} while (0)

#define CHECK_STATUS(status, correct) do { \
	if (!NT_STATUS_EQUAL(status, correct)) { \
		printf("(%s) Incorrect status %s - should be %s\n", \
		       __location__, nt_errstr(status), nt_errstr(correct)); \
		ret = false; \
		goto done; \
	}} while (0)


    printf("Test setattr\n");
    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);

    printf("setting to NORMAL doesn't do anything\n");
    sfinfo.setattr.in.attrib = FILE_ATTRIBUTE_NORMAL;
    sfinfo.setattr.in.write_time = 0;
    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);

    printf("a zero write_time means don't change\n");
    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);

    printf("Test setattre\n");
    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);

    printf("Test standard level\n");
    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);

    printf("Test basic_info level\n");
    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);

    printf("a zero time means don't change\n");
    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 = 0;
    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);

    printf("Test basic_information level\n");
    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_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);
    CHECK_TIME(ALL_INFO, all_info, change_time, basetime + 400);
    CHECK_VALUE(ALL_INFO, all_info, attrib,     FILE_ATTRIBUTE_NORMAL);

    torture_comment(torture, "try to change a file to a directory\n");
    sfinfo.basic_info.in.attrib = FILE_ATTRIBUTE_DIRECTORY;
    CHECK_CALL_FNUM(BASIC_INFO, NT_STATUS_INVALID_PARAMETER);

    printf("a zero time means don't change\n");
    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);

    printf("Test disposition_info level\n");
    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);

    printf("Test disposition_information level\n");
    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);

    printf("Test allocation_info level\n");
    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);

    printf("Test end_of_file_info level\n");
    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);

    printf("Test position_information level\n");
    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);

    printf("Test mode_information level\n");
    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);

#if 0
    printf("Test unix_basic level\n");
    CHECK_CALL_FNUM(UNIX_BASIC, NT_STATUS_OK);
    CHECK_CALL_PATH(UNIX_BASIC, NT_STATUS_OK);

    printf("Test unix_link level\n");
    CHECK_CALL_FNUM(UNIX_LINK, NT_STATUS_OK);
    CHECK_CALL_PATH(UNIX_LINK, NT_STATUS_OK);
#endif

done:
    smb_raw_exit(cli->session);
    smbcli_close(cli->tree, fnum);
    if (NT_STATUS_IS_ERR(smbcli_unlink(cli->tree, fnum_fname))) {
        printf("Failed to delete %s - %s\n", fnum_fname, smbcli_errstr(cli->tree));
    }
    if (NT_STATUS_IS_ERR(smbcli_unlink(cli->tree, path_fname))) {
        printf("Failed to delete %s - %s\n", path_fname, smbcli_errstr(cli->tree));
    }

    return ret;
}
示例#29
0
文件: mux.c 项目: AIdrifter/samba
/*
  test a lock that conflicts with an existing lock
*/
static bool test_mux_lock(struct smbcli_state *cli, TALLOC_CTX *mem_ctx)
{
	union smb_lock io;
	NTSTATUS status;
	int fnum;
	bool ret = true;
	struct smbcli_request *req;
	struct smb_lock_entry lock[1];
	struct timeval t;

	printf("TESTING MULTIPLEXED LOCK/LOCK/UNLOCK\n");

	fnum = smbcli_open(cli->tree, BASEDIR "\\write.dat", O_RDWR | O_CREAT, DENY_NONE);
	if (fnum == -1) {
		printf("open failed in mux_write - %s\n", smbcli_errstr(cli->tree));
		ret = false;
		goto done;
	}

	printf("establishing a lock\n");
	io.lockx.level = RAW_LOCK_LOCKX;
	io.lockx.in.file.fnum = fnum;
	io.lockx.in.mode = 0;
	io.lockx.in.timeout = 0;
	io.lockx.in.lock_cnt = 1;
	io.lockx.in.ulock_cnt = 0;
	lock[0].pid = 1;
	lock[0].offset = 0;
	lock[0].count = 4;
	io.lockx.in.locks = &lock[0];

	status = smb_raw_lock(cli->tree, &io);
	CHECK_STATUS(status, NT_STATUS_OK);

	printf("the second lock will conflict with the first\n");
	lock[0].pid = 2;
	io.lockx.in.timeout = 1000;
	status = smb_raw_lock(cli->tree, &io);
	CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);

	printf("this will too, but we'll unlock while waiting\n");
	t = timeval_current();
	req = smb_raw_lock_send(cli->tree, &io);

	printf("unlock the first range\n");
	lock[0].pid = 1;
	io.lockx.in.ulock_cnt = 1;
	io.lockx.in.lock_cnt = 0;
	io.lockx.in.timeout = 0;
	status = smb_raw_lock(cli->tree, &io);
	CHECK_STATUS(status, NT_STATUS_OK);

	printf("recv the async reply\n");
	status = smbcli_request_simple_recv(req);
	CHECK_STATUS(status, NT_STATUS_OK);	

	printf("async lock took %.2f msec\n", timeval_elapsed(&t) * 1000);
	if (timeval_elapsed(&t) > 0.1) {
		printf("failed to trigger early lock retry\n");
		return false;		
	}

	printf("reopening with an exit\n");
	smb_raw_exit(cli->session);
	fnum = smbcli_open(cli->tree, BASEDIR "\\write.dat", O_RDWR | O_CREAT, DENY_NONE);

	printf("Now trying with a cancel\n");

	io.lockx.level = RAW_LOCK_LOCKX;
	io.lockx.in.file.fnum = fnum;
	io.lockx.in.mode = 0;
	io.lockx.in.timeout = 0;
	io.lockx.in.lock_cnt = 1;
	io.lockx.in.ulock_cnt = 0;
	lock[0].pid = 1;
	lock[0].offset = 0;
	lock[0].count = 4;
	io.lockx.in.locks = &lock[0];

	status = smb_raw_lock(cli->tree, &io);
	CHECK_STATUS(status, NT_STATUS_OK);

	lock[0].pid = 2;
	io.lockx.in.timeout = 1000;
	status = smb_raw_lock(cli->tree, &io);
	CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);

	req = smb_raw_lock_send(cli->tree, &io);

	/* cancel the blocking lock */
	smb_raw_ntcancel(req);

	printf("sending 2nd cancel\n");
	/* the 2nd cancel is totally harmless, but tests the server trying to 
	   cancel an already cancelled request */
	smb_raw_ntcancel(req);

	printf("sent 2nd cancel\n");

	lock[0].pid = 1;
	io.lockx.in.ulock_cnt = 1;
	io.lockx.in.lock_cnt = 0;
	io.lockx.in.timeout = 0;
	status = smb_raw_lock(cli->tree, &io);
	CHECK_STATUS(status, NT_STATUS_OK);

	status = smbcli_request_simple_recv(req);
	CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);	

	printf("cancel a lock using exit to close file\n");
	lock[0].pid = 1;
	io.lockx.in.ulock_cnt = 0;
	io.lockx.in.lock_cnt = 1;
	io.lockx.in.timeout = 1000;

	status = smb_raw_lock(cli->tree, &io);
	CHECK_STATUS(status, NT_STATUS_OK);

	t = timeval_current();
	lock[0].pid = 2;
	req = smb_raw_lock_send(cli->tree, &io);

	smb_raw_exit(cli->session);
	smb_raw_exit(cli->session);
	smb_raw_exit(cli->session);
	smb_raw_exit(cli->session);

	printf("recv the async reply\n");
	status = smbcli_request_simple_recv(req);
	CHECK_STATUS(status, NT_STATUS_RANGE_NOT_LOCKED);
	printf("async lock exit took %.2f msec\n", timeval_elapsed(&t) * 1000);
	if (timeval_elapsed(&t) > 0.1) {
		printf("failed to trigger early lock failure\n");
		return false;		
	}

done:
	return ret;
}
示例#30
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. 
*/
static bool torture_raw_qfileinfo_internals(struct torture_context *torture, 
					    TALLOC_CTX *mem_ctx, 	
					    struct smbcli_tree *tree, 
					    int fnum, const char *fname,
					    bool is_ipc)
{
	int i;
	bool ret = true;
	int count;
	union smb_fileinfo *s1, *s2;	
	NTTIME correct_time;
	uint64_t correct_size;
	uint32_t correct_attrib;
	const char *correct_name;
	bool skip_streams = false;

	/* 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.file.fnum = fnum;
			levels[i].fnum_status = smb_raw_fileinfo(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.file.path = talloc_strdup(mem_ctx, fname);
			levels[i].fname_status = smb_raw_pathinfo(tree, mem_ctx, 
								  &levels[i].fname_finfo);
		}
	}

	/* check for completely broken levels */
	for (count=i=0; levels[i].name; i++) {
		uint32_t cap = tree->session->transport->negotiate.capabilities;
		/* see if this server claims to support this level */
		if ((cap & levels[i].capability_mask) != levels[i].capability_mask) {
			continue;
		}

		if (is_ipc) {
			if (levels[i].expected_ipc_access_denied && NT_STATUS_EQUAL(NT_STATUS_ACCESS_DENIED, levels[i].fname_status)) {
			} else if (!levels[i].only_handles &&
				   NT_STATUS_EQUAL(levels[i].fname_status,
				   NT_STATUS_NOT_SUPPORTED)) {
				torture_warning(torture, "fname level %s %s",
					levels[i].name,
					nt_errstr(levels[i].fname_status));
				continue;
			} else if (!levels[i].only_handles && !NT_STATUS_EQUAL(NT_STATUS_INVALID_DEVICE_REQUEST, levels[i].fname_status)) {
				printf("ERROR: fname level %s failed, expected NT_STATUS_INVALID_DEVICE_REQUEST - %s\n", 
				       levels[i].name, nt_errstr(levels[i].fname_status));
				count++;
			}
			if (!levels[i].only_paths &&
			   (NT_STATUS_EQUAL(levels[i].fnum_status,
			    NT_STATUS_NOT_SUPPORTED) ||
			    NT_STATUS_EQUAL(levels[i].fnum_status,
			    NT_STATUS_NOT_IMPLEMENTED))) {
				torture_warning(torture, "fnum level %s %s",
					levels[i].name,
					nt_errstr(levels[i].fnum_status));
				continue;
			}
			if (!levels[i].only_paths && !NT_STATUS_EQUAL(levels[i].expected_ipc_fnum_status, levels[i].fnum_status)) {
				printf("ERROR: fnum level %s failed, expected %s - %s\n", 
				       levels[i].name, nt_errstr(levels[i].expected_ipc_fnum_status), 
				       nt_errstr(levels[i].fnum_status));
				count++;
			}
		} else {
			if (!levels[i].only_paths &&
			   (NT_STATUS_EQUAL(levels[i].fnum_status,
			    NT_STATUS_NOT_SUPPORTED) ||
			    NT_STATUS_EQUAL(levels[i].fnum_status,
			    NT_STATUS_NOT_IMPLEMENTED))) {
				torture_warning(torture, "fnum level %s %s",
					levels[i].name,
					nt_errstr(levels[i].fnum_status));
				continue;
			}

			if (!levels[i].only_handles &&
			   (NT_STATUS_EQUAL(levels[i].fname_status,
			    NT_STATUS_NOT_SUPPORTED) ||
			    NT_STATUS_EQUAL(levels[i].fname_status,
			    NT_STATUS_NOT_IMPLEMENTED))) {
                                torture_warning(torture, "fname level %s %s",
					levels[i].name,
					nt_errstr(levels[i].fname_status));
				continue;
			}

			if (!levels[i].only_paths && !NT_STATUS_IS_OK(levels[i].fnum_status)) {
				printf("ERROR: fnum 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: fname 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 > 35) {
			torture_fail(torture, "too many level failures - giving up");
		}
	}

	/* see if we can do streams */
	s1 = fnum_find("STREAM_INFO");
	if (!s1 || s1->stream_info.out.num_streams == 0) {
		if (!is_ipc) {
			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(is_ipc, sname1); s2 = fname_find(is_ipc, sname2); \
		if (s1 && s2) { INFO_CHECK } \
		s1 = fnum_find(sname1);	 s2 = fname_find(is_ipc, 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 \
		VAL_EQUAL(compression_info, compressed_size,compression_info, compressed_size); \
		VAL_EQUAL(compression_info, format,         compression_info, format); \
		VAL_EQUAL(compression_info, unit_shift,     compression_info, unit_shift); \
		VAL_EQUAL(compression_info, chunk_shift,    compression_info, chunk_shift); \
		VAL_EQUAL(compression_info, cluster_shift,  compression_info, cluster_shift);

	ALIAS_CHECK("COMPRESSION_INFO", "COMPRESSION_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(is_ipc, 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,  \
		       timestring(mem_ctx, s1->stype.out.tfield), \
		       nt_time_string(mem_ctx, correct_time)); \
		ret = false; \
	} \
	s1 = fname_find(is_ipc, 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,  \
		       timestring(mem_ctx, s1->stype.out.tfield), \
		       nt_time_string(mem_ctx, correct_time)); \
		ret = false; \
	}} while (0)

#if 0 /* unused */
#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,  \
		       timestring(mem_ctx, s1->stype.out.tfield), \
		       nt_time_string(mem_ctx, correct_time)); \
		ret = false; \
	} \
	s1 = fname_find(is_ipc, 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,  \
		       timestring(mem_ctx, s1->stype.out.tfield), \
		       nt_time_string(mem_ctx, correct_time)); \
		ret = false; \
	}} while (0)
#endif

	/* 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;
	torture_comment(torture, "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;
	torture_comment(torture, "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;
	torture_comment(torture, "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("GETATTR",                  getattr,    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;
	torture_comment(torture, "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 int)s1->stype.out.tfield, \
		       (unsigned int)correct_size); \
		ret = false; \
	} \
	s1 = fname_find(is_ipc, sname); \
	if (s1 && s1->stype.out.tfield != correct_size) { \
		printf("(%d) path %s/%s incorrect - %u should be %u\n", __LINE__, #stype, #tfield,  \
		       (unsigned int)s1->stype.out.tfield, \
		       (unsigned int)correct_size); \
		ret = false; \
	}} while (0)

	s1 = fnum_find("STANDARD_INFO");
	correct_size = s1->standard_info.out.size;
	torture_comment(torture, "size: %u\n", (unsigned int)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;
	torture_comment(torture, "alloc_size: %u\n", (unsigned int)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 int)s1->stype.out.tfield, \
		       (unsigned int)correct_attrib); \
		ret = false; \
	} \
	s1 = fname_find(is_ipc, 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 int)s1->stype.out.tfield, \
		       (unsigned int)correct_attrib); \
		ret = false; \
	}} while (0)

	s1 = fnum_find("BASIC_INFO");
	correct_attrib = s1->basic_info.out.attrib;
	torture_comment(torture, "attrib: 0x%x\n", (unsigned int)correct_attrib);
	
	ATTRIB_CHECK("GETATTR",                   getattr,                   attrib);
	if (!is_ipc) {
		ATTRIB_CHECK("GETATTRE",                  getattre,                  attrib);
		ATTRIB_CHECK("STANDARD",                  standard,                  attrib);
		ATTRIB_CHECK("EA_SIZE",                   ea_size,                   attrib);
	}
	ATTRIB_CHECK("BASIC_INFO",                basic_info,                attrib);
	ATTRIB_CHECK("BASIC_INFORMATION",         basic_info,                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;
	torture_comment(torture, "name: %s\n", correct_name);

#define NAME_CHECK(sname, stype, tfield, flags) do { \
	s1 = fnum_find(sname); \
	if (s1 && (strcmp_safe(s1->stype.out.tfield.s, correct_name) != 0 || \
	    		wire_bad_flags(&s1->stype.out.tfield, flags, tree->session->transport))) { \
		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(is_ipc, sname); \
	if (s1 && (strcmp_safe(s1->stype.out.tfield.s, correct_name) != 0 || \
	    		wire_bad_flags(&s1->stype.out.tfield, flags, tree->session->transport))) { \
		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) {
		torture_fail(torture, "ALL_INFO didn't give a filename");
	}
	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_safe(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, tree->session->transport)) {
			printf("Should not null terminate all_info/fname\n");
			ret = false;
		}
	}

	s1 = fnum_find("ALT_NAME_INFO");
	if (s1) {
		correct_name = s1->alt_name_info.out.fname.s;
	}

	if (!correct_name) {
		torture_comment(torture, "no alternate name information\n");
	} else {
		torture_comment(torture, "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 */
		smbcli_close(tree, fnum);
		fnum = smbcli_nt_create_full(tree, correct_name, 0, 
					     SEC_RIGHTS_FILE_ALL,
					     FILE_ATTRIBUTE_NORMAL,
					     NTCREATEX_SHARE_ACCESS_DELETE|
					     NTCREATEX_SHARE_ACCESS_READ|
					     NTCREATEX_SHARE_ACCESS_WRITE, 
					     NTCREATEX_DISP_OVERWRITE_IF, 
					     0, 0);
		if (fnum == -1) {
			printf("Unable to open by alt_name - %s\n", smbcli_errstr(tree));
			ret = false;
		}
		
		if (!skip_streams) {
			correct_name = "::$DATA";
			torture_comment(torture, "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");
	s2 = fnum_find("ALL_INFO");
	if (s1) {
		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,
			       (int)s1->all_eas.out.eas[i].value.length,
			       (int)s1->all_eas.out.eas[i].value.length,
			       s1->all_eas.out.eas[i].value.data);
		}
	}
	if (s1 && s2) {
		if (s1->all_eas.out.num_eas == 0) {
			if (s2->all_info.out.ea_size != 0) {
				printf("ERROR: num_eas==0 but fnum all_info.out.ea_size == %d\n",
				       s2->all_info.out.ea_size);
			}
		} else {
			if (s2->all_info.out.ea_size != 
			    ea_list_size(s1->all_eas.out.num_eas, s1->all_eas.out.eas)) {
				printf("ERROR: ea_list_size=%d != fnum all_info.out.ea_size=%d\n",
				       (int)ea_list_size(s1->all_eas.out.num_eas, s1->all_eas.out.eas),
				       (int)s2->all_info.out.ea_size);
			}
		}
	}
	s2 = fname_find(is_ipc, "ALL_EAS");
	if (s2) {
		VAL_EQUAL(all_eas, num_eas, all_eas, num_eas);
		for (i=0;i<s1->all_eas.out.num_eas;i++) {
			VAL_EQUAL(all_eas, eas[i].flags, all_eas, eas[i].flags);
			STR_EQUAL(all_eas, eas[i].name, all_eas, eas[i].name);
			VAL_EQUAL(all_eas, eas[i].value.length, all_eas, eas[i].value.length);
		}
	}

#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(is_ipc, sname1); s2 = fname_find(is_ipc, 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(is_ipc, 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(is_ipc, 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);
	s1 = fnum_find("BASIC_INFO");
	if (s1 && is_ipc) {
		if (s1->basic_info.out.attrib != FILE_ATTRIBUTE_NORMAL) {
			printf("(%d) attrib basic_info/nlink incorrect - %d should be %d\n", __LINE__, s1->basic_info.out.attrib, (int)FILE_ATTRIBUTE_NORMAL);
			ret = false;
		}
	}
	s1 = fnum_find("STANDARD_INFO");
	if (s1 && is_ipc) {
		if (s1->standard_info.out.nlink != 1) {
			printf("(%d) nlinks standard_info/nlink incorrect - %d should be 1\n", __LINE__, s1->standard_info.out.nlink);
			ret = false;
		}
		if (s1->standard_info.out.delete_pending != 1) {
			printf("(%d) nlinks standard_info/delete_pending incorrect - %d should be 1\n", __LINE__, s1->standard_info.out.delete_pending);
			ret = false;
		}
	}
	VAL_CHECK("EA_INFO",       ea_info,       ea_size, 
		  "ALL_INFO",      all_info,      ea_size);
	if (!is_ipc) {
		VAL_CHECK("EA_SIZE",       ea_size,       ea_size, 
			  "ALL_INFO",      all_info,      ea_size);
	}

#define NAME_PATH_CHECK(sname, stype, field) do { \
	s1 = fname_find(is_ipc, sname); s2 = fnum_find(sname); \
        if (s1 && s2) { \
		VAL_EQUAL(stype, field, stype, field); \
	} \
} while (0)


	s1 = fnum_find("INTERNAL_INFORMATION");
	if (s1) {
		torture_comment(torture, "file_id=%.0f\n", (double)s1->internal_information.out.file_id);
	}

	NAME_PATH_CHECK("INTERNAL_INFORMATION", internal_information, file_id);
	NAME_PATH_CHECK("POSITION_INFORMATION", position_information, position);
	if (s1 && s2) {
		printf("fnum pos = %.0f, fname pos = %.0f\n",
		       (double)s2->position_information.out.position,
		       (double)s1->position_information.out.position );
	}
	NAME_PATH_CHECK("MODE_INFORMATION", mode_information, mode);
	NAME_PATH_CHECK("ALIGNMENT_INFORMATION", alignment_information, alignment_requirement);
	NAME_PATH_CHECK("ATTRIBUTE_TAG_INFORMATION", attribute_tag_information, attrib);
	NAME_PATH_CHECK("ATTRIBUTE_TAG_INFORMATION", attribute_tag_information, reparse_tag);

#if 0
	/* these are expected to differ */
	NAME_PATH_CHECK("ACCESS_INFORMATION", access_information, access_flags);
#endif

#if 0 /* unused */
#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 int)s1->stype.out.tfield); \
	} \
	s1 = fname_find(is_ipc, sname); \
	if (s1 && s1->stype.out.tfield != 0) { \
		printf("(%d) path %s/%s unknown != 0 (0x%x)\n", __LINE__, \
                       #stype, #tfield, \
		       (unsigned int)s1->stype.out.tfield); \
	}} while (0)
#endif
	/* 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 */
	
	return ret;
}