예제 #1
0
파일: vfs_acl_tdb.c 프로젝트: encukou/samba
static int unlink_acl_tdb(vfs_handle_struct *handle,
			  const struct smb_filename *smb_fname)
{
	struct smb_filename *smb_fname_tmp = NULL;
	struct db_context *db = acl_db;
	int ret = -1;

	smb_fname_tmp = cp_smb_filename(talloc_tos(), smb_fname);
	if (smb_fname_tmp == NULL) {
		errno = ENOMEM;
		goto out;
	}

	if (smb_fname_tmp->flags & SMB_FILENAME_POSIX_PATH) {
		ret = SMB_VFS_LSTAT(handle->conn, smb_fname_tmp);
	} else {
		ret = SMB_VFS_STAT(handle->conn, smb_fname_tmp);
	}

	if (ret == -1) {
		goto out;
	}

	ret = unlink_acl_common(handle, smb_fname_tmp);

	if (ret == -1) {
		goto out;
	}

	acl_tdb_delete(handle, db, &smb_fname_tmp->st);
 out:
	return ret;
}
예제 #2
0
/*
 * On unlink we need to delete the tdb record
 */
static int posix_eadb_unlink(vfs_handle_struct *handle,
			    const struct smb_filename *smb_fname)
{
	struct smb_filename *smb_fname_tmp = NULL;
	int ret = -1;

	struct tdb_wrap *ea_tdb;

	SMB_VFS_HANDLE_GET_DATA(handle, ea_tdb, struct tdb_wrap, return -1);

	smb_fname_tmp = cp_smb_filename(talloc_tos(), smb_fname);
	if (smb_fname_tmp == NULL) {
		errno = ENOMEM;
		return -1;
	}

	if (lp_posix_pathnames()) {
		ret = SMB_VFS_NEXT_LSTAT(handle, smb_fname_tmp);
	} else {
		ret = SMB_VFS_NEXT_STAT(handle, smb_fname_tmp);
	}
	if (ret == -1) {
		goto out;
	}

	if (smb_fname_tmp->st.st_ex_nlink == 1) {
		NTSTATUS status;

		/* Only remove record on last link to file. */

		if (tdb_transaction_start(ea_tdb->tdb) != 0) {
			ret = -1;
			goto out;
		}

		status = unlink_posix_eadb_raw(ea_tdb, smb_fname->base_name, -1);
		if (!NT_STATUS_IS_OK(status)) {
			tdb_transaction_cancel(ea_tdb->tdb);
			ret = -1;
			goto out;
		}
	}

	ret = SMB_VFS_NEXT_UNLINK(handle, smb_fname_tmp);

	if (ret == -1) {
		tdb_transaction_cancel(ea_tdb->tdb);
		goto out;
	} else {
		if (tdb_transaction_commit(ea_tdb->tdb) != 0) {
			ret = -1;
			goto out;
		}
	}

out:
	TALLOC_FREE(smb_fname_tmp);
	return ret;
}
예제 #3
0
파일: files.c 프로젝트: Distrotech/samba
NTSTATUS file_name_hash(connection_struct *conn,
			const char *name, uint32_t *p_name_hash)
{
	char tmpbuf[PATH_MAX];
	char *fullpath, *to_free;
	ssize_t len;
	TDB_DATA key;

	/* Set the hash of the full pathname. */

	len = full_path_tos(conn->connectpath, name, tmpbuf, sizeof(tmpbuf),
			    &fullpath, &to_free);
	if (len == -1) {
		return NT_STATUS_NO_MEMORY;
	}
	key = (TDB_DATA) { .dptr = (uint8_t *)fullpath, .dsize = len+1 };
	*p_name_hash = tdb_jenkins_hash(&key);

	DEBUG(10,("file_name_hash: %s hash 0x%x\n",
		  fullpath,
		(unsigned int)*p_name_hash ));

	TALLOC_FREE(to_free);
	return NT_STATUS_OK;
}

/**
 * The only way that the fsp->fsp_name field should ever be set.
 */
NTSTATUS fsp_set_smb_fname(struct files_struct *fsp,
			   const struct smb_filename *smb_fname_in)
{
	struct smb_filename *smb_fname_new;

	smb_fname_new = cp_smb_filename(fsp, smb_fname_in);
	if (smb_fname_new == NULL) {
		return NT_STATUS_NO_MEMORY;
	}

	TALLOC_FREE(fsp->fsp_name);
	fsp->fsp_name = smb_fname_new;

	return file_name_hash(fsp->conn,
			smb_fname_str_dbg(fsp->fsp_name),
			&fsp->name_hash);
}

const struct GUID *fsp_client_guid(const files_struct *fsp)
{
	return &fsp->conn->sconn->client->connections->smb2.client.guid;
}

uint32_t fsp_lease_type(struct files_struct *fsp)
{
	if (fsp->oplock_type == LEASE_OPLOCK) {
		return fsp->lease->lease.lease_state;
	}
	return map_oplock_to_lease_type(fsp->oplock_type);
}
예제 #4
0
static int streams_xattr_unlink(vfs_handle_struct *handle,
				const struct smb_filename *smb_fname)
{
	NTSTATUS status;
	int ret = -1;
	char *xattr_name = NULL;

	if (!is_ntfs_stream_smb_fname(smb_fname)) {
		return SMB_VFS_NEXT_UNLINK(handle, smb_fname);
	}

	/* If the default stream is requested, just open the base file. */
	if (is_ntfs_default_stream_smb_fname(smb_fname)) {
		struct smb_filename *smb_fname_base = NULL;

		smb_fname_base = cp_smb_filename(talloc_tos(), smb_fname);
		if (smb_fname_base == NULL) {
			errno = ENOMEM;
			return -1;
		}

		ret = SMB_VFS_NEXT_UNLINK(handle, smb_fname_base);

		TALLOC_FREE(smb_fname_base);
		return ret;
	}

	status = streams_xattr_get_name(handle, talloc_tos(),
					smb_fname->stream_name, &xattr_name);
	if (!NT_STATUS_IS_OK(status)) {
		errno = map_errno_from_nt_status(status);
		goto fail;
	}

	ret = SMB_VFS_REMOVEXATTR(handle->conn, smb_fname, xattr_name);

	if ((ret == -1) && (errno == ENOATTR)) {
		errno = ENOENT;
		goto fail;
	}

	ret = 0;

 fail:
	TALLOC_FREE(xattr_name);
	return ret;
}
예제 #5
0
파일: files.c 프로젝트: rchicoli/samba
/**
 * The only way that the fsp->fsp_name field should ever be set.
 */
NTSTATUS fsp_set_smb_fname(struct files_struct *fsp,
			   const struct smb_filename *smb_fname_in)
{
	struct smb_filename *smb_fname_new;

	smb_fname_new = cp_smb_filename(fsp, smb_fname_in);
	if (smb_fname_new == NULL) {
		return NT_STATUS_NO_MEMORY;
	}

	TALLOC_FREE(fsp->fsp_name);
	fsp->fsp_name = smb_fname_new;

	return file_name_hash(fsp->conn,
			smb_fname_str_dbg(fsp->fsp_name),
			&fsp->name_hash);
}
/**
 * There are actually legitimate callers of this such as functions that
 * enumerate streams using the vfs_streaminfo interface and then want to
 * operate on each stream.
 */
struct smb_filename *synthetic_smb_fname(TALLOC_CTX *mem_ctx,
					 const char *base_name,
					 const char *stream_name,
					 const SMB_STRUCT_STAT *psbuf)
{
	struct smb_filename smb_fname_loc = { 0, };

	/* Setup the base_name/stream_name. */
	smb_fname_loc.base_name = discard_const_p(char, base_name);
	smb_fname_loc.stream_name = discard_const_p(char, stream_name);

	/* Copy the psbuf if one was given. */
	if (psbuf)
		smb_fname_loc.st = *psbuf;

	/* Let cp_smb_filename() do the heavy lifting. */
	return cp_smb_filename(mem_ctx, &smb_fname_loc);
}
예제 #7
0
static NTSTATUS smbd_smb2_close(struct smbd_smb2_request *req,
				struct files_struct *fsp,
				uint16_t in_flags,
				uint16_t *out_flags,
				struct timespec *out_creation_ts,
				struct timespec *out_last_access_ts,
				struct timespec *out_last_write_ts,
				struct timespec *out_change_ts,
				uint64_t *out_allocation_size,
				uint64_t *out_end_of_file,
				uint32_t *out_file_attributes)
{
	NTSTATUS status;
	struct smb_request *smbreq;
	connection_struct *conn = req->tcon->compat;
	struct smb_filename *smb_fname = NULL;
	uint64_t allocation_size = 0;
	uint64_t file_size = 0;
	uint32_t dos_attrs = 0;
	uint16_t flags = 0;
	bool posix_open = false;

	ZERO_STRUCTP(out_creation_ts);
	ZERO_STRUCTP(out_last_access_ts);
	ZERO_STRUCTP(out_last_write_ts);
	ZERO_STRUCTP(out_change_ts);

	*out_flags = 0;
	*out_allocation_size = 0;
	*out_end_of_file = 0;
	*out_file_attributes = 0;

	DEBUG(10,("smbd_smb2_close: %s - %s\n",
		  fsp_str_dbg(fsp), fsp_fnum_dbg(fsp)));

	smbreq = smbd_smb2_fake_smb_request(req);
	if (smbreq == NULL) {
		return NT_STATUS_NO_MEMORY;
	}

	posix_open = (fsp->posix_flags & FSP_POSIX_FLAGS_OPEN);
	smb_fname = cp_smb_filename(talloc_tos(), fsp->fsp_name);
	if (smb_fname == NULL) {
		return NT_STATUS_NO_MEMORY;
	}

	if ((in_flags & SMB2_CLOSE_FLAGS_FULL_INFORMATION) &&
	    (fsp->initial_delete_on_close || fsp->delete_on_close)) {
		/*
		 * We might be deleting the file. Ensure we
		 * return valid data from before the file got
		 * removed.
		 */
		setup_close_full_information(conn,
				smb_fname,
				posix_open,
				out_creation_ts,
				out_last_access_ts,
				out_last_write_ts,
				out_change_ts,
				&flags,
				&allocation_size,
				&file_size,
				&dos_attrs);
	}

	status = close_file(smbreq, fsp, NORMAL_CLOSE);
	if (!NT_STATUS_IS_OK(status)) {
		DEBUG(5,("smbd_smb2_close: close_file[%s]: %s\n",
			 fsp_str_dbg(fsp), nt_errstr(status)));
		return status;
	}

	if (in_flags & SMB2_CLOSE_FLAGS_FULL_INFORMATION) {
		setup_close_full_information(conn,
				smb_fname,
				posix_open,
				out_creation_ts,
				out_last_access_ts,
				out_last_write_ts,
				out_change_ts,
				&flags,
				&allocation_size,
				&file_size,
				&dos_attrs);
	}

	*out_flags = flags;
	*out_allocation_size = allocation_size;
	*out_end_of_file = file_size;
	*out_file_attributes = dos_attrs;

	return NT_STATUS_OK;
}
예제 #8
0
파일: smb2_close.c 프로젝트: hef/samba
static NTSTATUS smbd_smb2_close(struct smbd_smb2_request *req,
				struct files_struct *fsp,
				uint16_t in_flags,
				uint16_t *out_flags,
				struct timespec *out_creation_ts,
				struct timespec *out_last_access_ts,
				struct timespec *out_last_write_ts,
				struct timespec *out_change_ts,
				uint64_t *out_allocation_size,
				uint64_t *out_end_of_file,
				uint32_t *out_file_attributes)
{
	NTSTATUS status;
	struct smb_request *smbreq;
	connection_struct *conn = req->tcon->compat;
	struct smb_filename *smb_fname = NULL;
	uint64_t allocation_size = 0;
	uint64_t file_size = 0;
	uint32_t dos_attrs = 0;
	uint16_t flags = 0;
	bool posix_open = false;

	ZERO_STRUCTP(out_creation_ts);
	ZERO_STRUCTP(out_last_access_ts);
	ZERO_STRUCTP(out_last_write_ts);
	ZERO_STRUCTP(out_change_ts);

	*out_flags = 0;
	*out_allocation_size = 0;
	*out_end_of_file = 0;
	*out_file_attributes = 0;

	DEBUG(10,("smbd_smb2_close: %s - %s\n",
		  fsp_str_dbg(fsp), fsp_fnum_dbg(fsp)));

	smbreq = smbd_smb2_fake_smb_request(req);
	if (smbreq == NULL) {
		return NT_STATUS_NO_MEMORY;
	}

	posix_open = fsp->posix_open;
	smb_fname = cp_smb_filename(talloc_tos(), fsp->fsp_name);
	if (smb_fname == NULL) {
		return NT_STATUS_NO_MEMORY;
	}

	status = close_file(smbreq, fsp, NORMAL_CLOSE);
	if (!NT_STATUS_IS_OK(status)) {
		DEBUG(5,("smbd_smb2_close: close_file[%s]: %s\n",
			 fsp_str_dbg(fsp), nt_errstr(status)));
		return status;
	}

	if (in_flags & SMB2_CLOSE_FLAGS_FULL_INFORMATION) {
		int ret;
		if (posix_open) {
			ret = SMB_VFS_LSTAT(conn, smb_fname);
		} else {
			ret = SMB_VFS_STAT(conn, smb_fname);
		}
		if (ret == 0) {
			flags = SMB2_CLOSE_FLAGS_FULL_INFORMATION;
			dos_attrs = dos_mode(conn, smb_fname);
			*out_last_write_ts = smb_fname->st.st_ex_mtime;
			*out_last_access_ts = smb_fname->st.st_ex_atime;
			*out_creation_ts = get_create_timespec(conn, NULL, smb_fname);
			*out_change_ts = get_change_timespec(conn, NULL, smb_fname);

			if (lp_dos_filetime_resolution(SNUM(conn))) {
				dos_filetime_timespec(out_creation_ts);
				dos_filetime_timespec(out_last_write_ts);
				dos_filetime_timespec(out_last_access_ts);
				dos_filetime_timespec(out_change_ts);
			}
			if (!(dos_attrs & FILE_ATTRIBUTE_DIRECTORY)) {
				file_size = get_file_size_stat(&smb_fname->st);
			}

			allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn, NULL, &smb_fname->st);
		}
	}

	*out_flags = flags;
	*out_allocation_size = allocation_size;
	*out_end_of_file = file_size;
	*out_file_attributes = dos_attrs;

	return NT_STATUS_OK;
}