Ejemplo n.º 1
0
static void unlock_byte(struct smbcli_state *cli, int fd, int offset)
{
	union smb_lock io;
	struct smb_lock_entry lock;
	NTSTATUS status;

	ZERO_STRUCT(lock);
	io.lockx.in.ulock_cnt = 1;
	io.lockx.in.lock_cnt = 0;

	lock.count = 1;
	lock.offset = offset;
	lock.pid = cli->tree->session->pid;
	io.lockx.level = RAW_LOCK_LOCKX;
	io.lockx.in.mode = LOCKING_ANDX_LARGE_FILES;
	io.lockx.in.timeout = 100000;
	io.lockx.in.locks = &lock;
	io.lockx.in.file.fnum = fd;

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

	if (!NT_STATUS_IS_OK(status)) {
		DEBUG(0,("Unlock failed\n"));
		exit(1);
	}
}
Ejemplo n.º 2
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;
}
Ejemplo n.º 3
0
/*
  lock a byte range
*/
static NTSTATUS cvfs_lock(struct ntvfs_module_context *ntvfs, 
			  struct ntvfs_request *req, union smb_lock *io)
{
	struct cvfs_private *p = ntvfs->private_data;
	struct smbcli_request *c_req;

	SETUP_PID;

	if (io->generic.level != RAW_LOCK_GENERIC &&
	    p->map_generic) {
		return ntvfs_map_lock(ntvfs, req, io);
	}
	SETUP_FILE;

	if (!(req->async_states->state & NTVFS_ASYNC_STATE_MAY_ASYNC)) {
		return smb_raw_lock(p->tree, io);
	}

	c_req = smb_raw_lock_send(p->tree, io);
	SIMPLE_ASYNC_TAIL;
}
Ejemplo n.º 4
0
static void lock_byte(struct smbcli_state *cli, int fd, int offset, int lock_timeout)
{
	union smb_lock io;
	struct smb_lock_entry lock;
	NTSTATUS status;

try_again:
	ZERO_STRUCT(lock);
	io.lockx.in.ulock_cnt = 0;
	io.lockx.in.lock_cnt = 1;

	lock.count = 1;
	lock.offset = offset;
	lock.pid = cli->tree->session->pid;
	io.lockx.level = RAW_LOCK_LOCKX;
	io.lockx.in.mode = LOCKING_ANDX_LARGE_FILES;
	io.lockx.in.timeout = lock_timeout;
	io.lockx.in.locks = &lock;
	io.lockx.in.file.fnum = fd;

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

	/* If we dont use timeouts and we got file lock conflict
	   just try the lock again.
	*/
	if (lock_timeout==0) {
		if ( (NT_STATUS_EQUAL(NT_STATUS_FILE_LOCK_CONFLICT, status))
		   ||(NT_STATUS_EQUAL(NT_STATUS_LOCK_NOT_GRANTED, status)) ) {
			goto try_again;
		}
	}

	if (!NT_STATUS_IS_OK(status)) {
		DEBUG(0,("Lock failed\n"));
		exit(1);
	}
}
Ejemplo n.º 5
0
/*
  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;
}
Ejemplo n.º 6
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;
}
Ejemplo n.º 7
0
static bool test_one(struct smbcli_state *cli[NSERVERS][NCONNECTIONS], 
		     int fnum[NSERVERS][NCONNECTIONS][NFILES],
		     struct record *rec)
{
	unsigned int conn = rec->conn;
	unsigned int f = rec->f;
	uint64_t start = rec->start;
	uint64_t len = rec->len;
	enum brl_type op = rec->lock_type;
	int server;
	bool ret[NSERVERS];
	NTSTATUS status[NSERVERS];

	switch (rec->lock_op) {
	case OP_LOCK:
		/* set a lock */
		for (server=0;server<NSERVERS;server++) {
			NTSTATUS res;
			struct smbcli_tree *tree=cli[server][conn]->tree;
			int fn=fnum[server][conn][f];

			if (!(tree->session->transport->negotiate.capabilities & CAP_LARGE_FILES)) {
				res=smbcli_lock(tree, fn, start, len, LOCK_TIMEOUT, rec->lock_op);
			} else {
				union smb_lock parms;
				int ltype;
				struct smb_lock_entry lock[1];

				parms.lockx.level = RAW_LOCK_LOCKX;
				parms.lockx.in.file.fnum = fn;
	
				ltype = (rec->lock_op == READ_LOCK? 1 : 0);
				ltype |= LOCKING_ANDX_LARGE_FILES;
				parms.lockx.in.mode = ltype;
				parms.lockx.in.timeout = LOCK_TIMEOUT;
				parms.lockx.in.ulock_cnt = 0;
				parms.lockx.in.lock_cnt = 1;
				lock[0].pid = rec->pid;
				lock[0].offset = start;
				lock[0].count = len;
				parms.lockx.in.locks = &lock[0];

				res = smb_raw_lock(tree, &parms);
			}

			ret[server] = NT_STATUS_IS_OK(res); 
			status[server] = smbcli_nt_error(cli[server][conn]->tree);
			if (!exact_error_codes && 
			    NT_STATUS_EQUAL(status[server], 
					    NT_STATUS_FILE_LOCK_CONFLICT)) {
				status[server] = NT_STATUS_LOCK_NOT_GRANTED;
			}
		}
		if (showall || !NT_STATUS_EQUAL(status[0],status[1])) {
			printf("lock   conn=%u f=%u range=%.0f(%.0f) op=%s -> %s:%s\n",
			       conn, f, 
			       (double)start, (double)len,
			       op==READ_LOCK?"READ_LOCK":"WRITE_LOCK",
			       nt_errstr(status[0]), nt_errstr(status[1]));
		}
		if (!NT_STATUS_EQUAL(status[0],status[1])) return false;
		break;
		
	case OP_UNLOCK:
		/* unset a lock */
		for (server=0;server<NSERVERS;server++) {
			NTSTATUS res;
			struct smbcli_tree *tree=cli[server][conn]->tree;
			int fn=fnum[server][conn][f];


			if (!(tree->session->transport->negotiate.capabilities & CAP_LARGE_FILES)) {
				res=smbcli_unlock(tree, fn, start, len);
			} else {
				union smb_lock parms;
				struct smb_lock_entry lock[1];

				parms.lockx.level = RAW_LOCK_LOCKX;
				parms.lockx.in.file.fnum = fn;
				parms.lockx.in.mode = LOCKING_ANDX_LARGE_FILES;
				parms.lockx.in.timeout = 0;
				parms.lockx.in.ulock_cnt = 1;
				parms.lockx.in.lock_cnt = 0;
				lock[0].pid = rec->pid;
				lock[0].count = len;
				lock[0].offset = start;
				parms.lockx.in.locks = &lock[0];

				res = smb_raw_lock(tree, &parms);
			}

			ret[server] = NT_STATUS_IS_OK(res);
			status[server] = smbcli_nt_error(cli[server][conn]->tree);
		}
		if (showall || 
		    (!hide_unlock_fails && !NT_STATUS_EQUAL(status[0],status[1]))) {
			printf("unlock conn=%u f=%u range=%.0f(%.0f)       -> %s:%s\n",
			       conn, f, 
			       (double)start, (double)len,
			       nt_errstr(status[0]), nt_errstr(status[1]));
		}
		if (!hide_unlock_fails && !NT_STATUS_EQUAL(status[0],status[1])) 
			return false;
		break;

	case OP_REOPEN:
		/* reopen the file */
		for (server=0;server<NSERVERS;server++) {
			smbcli_close(cli[server][conn]->tree, fnum[server][conn][f]);
			fnum[server][conn][f] = -1;
		}
		for (server=0;server<NSERVERS;server++) {
			fnum[server][conn][f] = smbcli_open(cli[server][conn]->tree, FILENAME,
							 O_RDWR|O_CREAT,
							 DENY_NONE);
			if (fnum[server][conn][f] == -1) {
				printf("failed to reopen on share%d\n", server);
				return false;
			}
		}
		if (showall) {
			printf("reopen conn=%u f=%u\n",
			       conn, f);
		}
		break;
	}

	return true;
}