diff options
Diffstat (limited to '')
-rw-r--r-- | source4/ntvfs/ntvfs_util.c | 197 |
1 files changed, 197 insertions, 0 deletions
diff --git a/source4/ntvfs/ntvfs_util.c b/source4/ntvfs/ntvfs_util.c new file mode 100644 index 0000000..2888ef4 --- /dev/null +++ b/source4/ntvfs/ntvfs_util.c @@ -0,0 +1,197 @@ +/* + Unix SMB/CIFS implementation. + NTVFS utility code + Copyright (C) Stefan Metzmacher 2004 + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. +*/ +/* + this implements common utility functions that many NTVFS backends may wish to use +*/ + +#include "includes.h" +#include "../lib/util/dlinklist.h" +#include "ntvfs/ntvfs.h" + + +struct ntvfs_request *ntvfs_request_create(struct ntvfs_context *ctx, TALLOC_CTX *mem_ctx, + struct auth_session_info *session_info, + uint16_t smbpid, + struct timeval request_time, + void *private_data, + void (*send_fn)(struct ntvfs_request *), + uint32_t state) +{ + struct ntvfs_request *req; + struct ntvfs_async_state *async; + + req = talloc(mem_ctx, struct ntvfs_request); + if (!req) return NULL; + req->ctx = ctx; + req->async_states = NULL; + req->session_info = session_info; + req->smbpid = smbpid; + req->client_caps = ctx->client_caps; + req->statistics.request_time = request_time; + + async = talloc(req, struct ntvfs_async_state); + if (!async) goto failed; + + async->state = state; + async->private_data = private_data; + async->send_fn = send_fn; + async->status = NT_STATUS_INTERNAL_ERROR; + async->ntvfs = NULL; + + DLIST_ADD(req->async_states, async); + + return req; +failed: + talloc_free(req); + return NULL; +} + +NTSTATUS ntvfs_async_state_push(struct ntvfs_module_context *ntvfs, + struct ntvfs_request *req, + void *private_data, + void (*send_fn)(struct ntvfs_request *)) +{ + struct ntvfs_async_state *async; + + async = talloc(req, struct ntvfs_async_state); + NT_STATUS_HAVE_NO_MEMORY(async); + + async->state = req->async_states->state; + async->private_data = private_data; + async->send_fn = send_fn; + async->status = NT_STATUS_INTERNAL_ERROR; + + async->ntvfs = ntvfs; + + DLIST_ADD(req->async_states, async); + + return NT_STATUS_OK; +} + +void ntvfs_async_state_pop(struct ntvfs_request *req) +{ + struct ntvfs_async_state *async; + + async = req->async_states; + + DLIST_REMOVE(req->async_states, async); + + req->async_states->state = async->state; + req->async_states->status = async->status; + + talloc_free(async); +} + +NTSTATUS ntvfs_handle_new(struct ntvfs_module_context *ntvfs, + struct ntvfs_request *req, + struct ntvfs_handle **h) +{ + if (!ntvfs->ctx->handles.create_new) { + return NT_STATUS_NOT_IMPLEMENTED; + } + return ntvfs->ctx->handles.create_new(ntvfs->ctx->handles.private_data, req, h); +} + +NTSTATUS ntvfs_handle_set_backend_data(struct ntvfs_handle *h, + struct ntvfs_module_context *ntvfs, + TALLOC_CTX *private_data) +{ + struct ntvfs_handle_data *d; + bool first_time = h->backend_data?false:true; + + for (d=h->backend_data; d; d = d->next) { + if (d->owner != ntvfs) continue; + d->private_data = talloc_steal(d, private_data); + return NT_STATUS_OK; + } + + d = talloc(h, struct ntvfs_handle_data); + NT_STATUS_HAVE_NO_MEMORY(d); + d->owner = ntvfs; + d->private_data = talloc_steal(d, private_data); + + DLIST_ADD(h->backend_data, d); + + if (first_time) { + NTSTATUS status; + status = h->ctx->handles.make_valid(h->ctx->handles.private_data, h); + NT_STATUS_NOT_OK_RETURN(status); + } + + return NT_STATUS_OK; +} + +void *ntvfs_handle_get_backend_data(struct ntvfs_handle *h, + struct ntvfs_module_context *ntvfs) +{ + struct ntvfs_handle_data *d; + + for (d=h->backend_data; d; d = d->next) { + if (d->owner != ntvfs) continue; + return d->private_data; + } + + return NULL; +} + +void ntvfs_handle_remove_backend_data(struct ntvfs_handle *h, + struct ntvfs_module_context *ntvfs) +{ + struct ntvfs_handle_data *d,*n; + + for (d=h->backend_data; d; d = n) { + n = d->next; + if (d->owner != ntvfs) continue; + DLIST_REMOVE(h->backend_data, d); + talloc_free(d); + d = NULL; + } + + if (h->backend_data) return; + + /* if there's no backend_data anymore, destroy the handle */ + h->ctx->handles.destroy(h->ctx->handles.private_data, h); +} + +struct ntvfs_handle *ntvfs_handle_search_by_wire_key(struct ntvfs_module_context *ntvfs, + struct ntvfs_request *req, + const DATA_BLOB *key) +{ + if (!ntvfs->ctx->handles.search_by_wire_key) { + return NULL; + } + return ntvfs->ctx->handles.search_by_wire_key(ntvfs->ctx->handles.private_data, req, key); +} + +NTSTATUS ntvfs_set_handle_callbacks(struct ntvfs_context *ntvfs, + NTSTATUS (*create_new)(void *private_data, struct ntvfs_request *req, struct ntvfs_handle **h), + NTSTATUS (*make_valid)(void *private_data, struct ntvfs_handle *h), + void (*destroy)(void *private_data, struct ntvfs_handle *h), + struct ntvfs_handle *(*search_by_wire_key)(void *private_data, struct ntvfs_request *req, const DATA_BLOB *key), + DATA_BLOB (*get_wire_key)(void *private_data, struct ntvfs_handle *handle, TALLOC_CTX *mem_ctx), + void *private_data) +{ + ntvfs->handles.create_new = create_new; + ntvfs->handles.make_valid = make_valid; + ntvfs->handles.destroy = destroy; + ntvfs->handles.search_by_wire_key = search_by_wire_key; + ntvfs->handles.get_wire_key = get_wire_key; + ntvfs->handles.private_data = private_data; + return NT_STATUS_OK; +} |