示例#1
0
文件: vfs_posix.c 项目: sprymak/samba
/*
  connect to a share - used when a tree_connect operation comes
  in. For a disk based backend we needs to ensure that the base
  directory exists (tho it doesn't need to be accessible by the user,
  that comes later)
*/
static NTSTATUS pvfs_connect(struct ntvfs_module_context *ntvfs,
			     struct ntvfs_request *req,
			     union smb_tcon* tcon)
{
	struct pvfs_state *pvfs;
	struct stat st;
	char *base_directory;
	NTSTATUS status;
	const char *sharename;

	switch (tcon->generic.level) {
	case RAW_TCON_TCON:
		sharename = tcon->tcon.in.service;
		break;
	case RAW_TCON_TCONX:
		sharename = tcon->tconx.in.path;
		break;
	case RAW_TCON_SMB2:
		sharename = tcon->smb2.in.path;
		break;
	default:
		return NT_STATUS_INVALID_LEVEL;
	}

	if (strncmp(sharename, "\\\\", 2) == 0) {
		char *p = strchr(sharename+2, '\\');
		if (p) {
			sharename = p + 1;
		}
	}

	/*
	 * TODO: call this from ntvfs_posix_init()
	 *       but currently we don't have a lp_ctx there
	 */
	status = pvfs_acl_init();
	NT_STATUS_NOT_OK_RETURN(status);

	pvfs = talloc_zero(ntvfs, struct pvfs_state);
	NT_STATUS_HAVE_NO_MEMORY(pvfs);

	/* for simplicity of path construction, remove any trailing slash now */
	base_directory = talloc_strdup(pvfs, share_string_option(ntvfs->ctx->config, SHARE_PATH, ""));
	NT_STATUS_HAVE_NO_MEMORY(base_directory);
	if (strcmp(base_directory, "/") != 0) {
		trim_string(base_directory, NULL, "/");
	}

	pvfs->ntvfs = ntvfs;
	pvfs->base_directory = base_directory;

	/* the directory must exist. Note that we deliberately don't
	   check that it is readable */
	if (stat(pvfs->base_directory, &st) != 0 || !S_ISDIR(st.st_mode)) {
		DEBUG(0,("pvfs_connect: '%s' is not a directory, when connecting to [%s]\n", 
			 pvfs->base_directory, sharename));
		return NT_STATUS_BAD_NETWORK_NAME;
	}

	ntvfs->ctx->fs_type = talloc_strdup(ntvfs->ctx, "NTFS");
	NT_STATUS_HAVE_NO_MEMORY(ntvfs->ctx->fs_type);

	ntvfs->ctx->dev_type = talloc_strdup(ntvfs->ctx, "A:");
	NT_STATUS_HAVE_NO_MEMORY(ntvfs->ctx->dev_type);

	if (tcon->generic.level == RAW_TCON_TCONX) {
		tcon->tconx.out.fs_type = ntvfs->ctx->fs_type;
		tcon->tconx.out.dev_type = ntvfs->ctx->dev_type;
	}

	ntvfs->private_data = pvfs;

	pvfs->brl_context = brlock_init(pvfs, 
				     pvfs->ntvfs->ctx->server_id,
				     pvfs->ntvfs->ctx->lp_ctx,
				     pvfs->ntvfs->ctx->msg_ctx);
	if (pvfs->brl_context == NULL) {
		return NT_STATUS_INTERNAL_DB_CORRUPTION;
	}

	pvfs->odb_context = odb_init(pvfs, pvfs->ntvfs->ctx);
	if (pvfs->odb_context == NULL) {
		return NT_STATUS_INTERNAL_DB_CORRUPTION;
	}

	/* allow this to be NULL - we just disable change notify */
	pvfs->notify_context = notify_init(pvfs, 
					   pvfs->ntvfs->ctx->server_id,  
					   pvfs->ntvfs->ctx->msg_ctx, 
					   pvfs->ntvfs->ctx->lp_ctx,
					   pvfs->ntvfs->ctx->event_ctx,
					   pvfs->ntvfs->ctx->config);

	pvfs->wbc_ctx = wbc_init(pvfs,
				 pvfs->ntvfs->ctx->msg_ctx,
				 pvfs->ntvfs->ctx->event_ctx);
	if (pvfs->wbc_ctx == NULL) {
		return NT_STATUS_INTERNAL_DB_CORRUPTION;
	}

	/* allocate the search handle -> ptr tree */
	pvfs->search.idtree = idr_init(pvfs);
	NT_STATUS_HAVE_NO_MEMORY(pvfs->search.idtree);

	status = pvfs_mangle_init(pvfs);
	NT_STATUS_NOT_OK_RETURN(status);

	pvfs_setup_options(pvfs);

	talloc_set_destructor(pvfs, pvfs_state_destructor);

#ifdef SIGXFSZ
	/* who had the stupid idea to generate a signal on a large
	   file write instead of just failing it!? */
	BlockSignals(true, SIGXFSZ);
#endif

	return NT_STATUS_OK;
}
示例#2
0
/*
  connect to a share - used when a tree_connect operation comes
  in. For a disk based backend we needs to ensure that the base
  directory exists (tho it doesn't need to be accessible by the user,
  that comes later)
*/
static NTSTATUS pvfs_connect(struct ntvfs_module_context *ntvfs,
			     struct ntvfs_request *req, const char *sharename)
{
	struct pvfs_state *pvfs;
	struct stat st;
	char *base_directory;
	NTSTATUS status;

	pvfs = talloc_zero(ntvfs, struct pvfs_state);
	NT_STATUS_HAVE_NO_MEMORY(pvfs);

	/* for simplicity of path construction, remove any trailing slash now */
	base_directory = talloc_strdup(pvfs, share_string_option(ntvfs->ctx->config, SHARE_PATH, ""));
	NT_STATUS_HAVE_NO_MEMORY(base_directory);
	if (strcmp(base_directory, "/") != 0) {
		trim_string(base_directory, NULL, "/");
	}

	pvfs->ntvfs = ntvfs;
	pvfs->base_directory = base_directory;

	/* the directory must exist. Note that we deliberately don't
	   check that it is readable */
	if (stat(pvfs->base_directory, &st) != 0 || !S_ISDIR(st.st_mode)) {
		DEBUG(0,("pvfs_connect: '%s' is not a directory, when connecting to [%s]\n", 
			 pvfs->base_directory, sharename));
		return NT_STATUS_BAD_NETWORK_NAME;
	}

	ntvfs->ctx->fs_type = talloc_strdup(ntvfs->ctx, "NTFS");
	NT_STATUS_HAVE_NO_MEMORY(ntvfs->ctx->fs_type);

	ntvfs->ctx->dev_type = talloc_strdup(ntvfs->ctx, "A:");
	NT_STATUS_HAVE_NO_MEMORY(ntvfs->ctx->dev_type);

	ntvfs->private_data = pvfs;

	pvfs->brl_context = brl_init(pvfs, 
				     pvfs->ntvfs->ctx->server_id,
				     pvfs->ntvfs->ctx->msg_ctx);
	if (pvfs->brl_context == NULL) {
		return NT_STATUS_INTERNAL_DB_CORRUPTION;
	}

	pvfs->odb_context = odb_init(pvfs, pvfs->ntvfs->ctx);
	if (pvfs->odb_context == NULL) {
		return NT_STATUS_INTERNAL_DB_CORRUPTION;
	}

	/* allow this to be NULL - we just disable change notify */
	pvfs->notify_context = notify_init(pvfs, 
					   pvfs->ntvfs->ctx->server_id,  
					   pvfs->ntvfs->ctx->msg_ctx, 
					   event_context_find(pvfs),
					   pvfs->ntvfs->ctx->config);

	pvfs->sidmap = sidmap_open(pvfs);
	if (pvfs->sidmap == NULL) {
		return NT_STATUS_INTERNAL_DB_CORRUPTION;
	}

	/* allocate the search handle -> ptr tree */
	pvfs->search.idtree = idr_init(pvfs);
	NT_STATUS_HAVE_NO_MEMORY(pvfs->search.idtree);

	status = pvfs_mangle_init(pvfs);
	NT_STATUS_NOT_OK_RETURN(status);

	pvfs_setup_options(pvfs);

	talloc_set_destructor(pvfs, pvfs_state_destructor);

#ifdef SIGXFSZ
	/* who had the stupid idea to generate a signal on a large
	   file write instead of just failing it!? */
	BlockSignals(True, SIGXFSZ);
#endif

	return NT_STATUS_OK;
}