1/* 2 Unix SMB/CIFS implementation. 3 NTVFS utility code 4 Copyright (C) Stefan Metzmacher 2004 5 6 This program is free software; you can redistribute it and/or modify 7 it under the terms of the GNU General Public License as published by 8 the Free Software Foundation; either version 3 of the License, or 9 (at your option) any later version. 10 11 This program is distributed in the hope that it will be useful, 12 but WITHOUT ANY WARRANTY; without even the implied warranty of 13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 GNU General Public License for more details. 15 16 You should have received a copy of the GNU General Public License 17 along with this program. If not, see <http://www.gnu.org/licenses/>. 18*/ 19/* 20 this implements common utility functions that many NTVFS backends may wish to use 21*/ 22 23#include "includes.h" 24#include "../lib/util/dlinklist.h" 25#include "ntvfs/ntvfs.h" 26 27 28struct ntvfs_request *ntvfs_request_create(struct ntvfs_context *ctx, TALLOC_CTX *mem_ctx, 29 struct auth_session_info *session_info, 30 uint16_t smbpid, 31 struct timeval request_time, 32 void *private_data, 33 void (*send_fn)(struct ntvfs_request *), 34 uint32_t state) 35{ 36 struct ntvfs_request *req; 37 struct ntvfs_async_state *async; 38 39 req = talloc(mem_ctx, struct ntvfs_request); 40 if (!req) return NULL; 41 req->ctx = ctx; 42 req->async_states = NULL; 43 req->session_info = session_info; 44 req->smbpid = smbpid; 45 req->client_caps = ctx->client_caps; 46 req->statistics.request_time = request_time; 47 48 async = talloc(req, struct ntvfs_async_state); 49 if (!async) goto failed; 50 51 async->state = state; 52 async->private_data = private_data; 53 async->send_fn = send_fn; 54 async->status = NT_STATUS_INTERNAL_ERROR; 55 async->ntvfs = NULL; 56 57 DLIST_ADD(req->async_states, async); 58 59 return req; 60failed: 61 talloc_free(req); 62 return NULL; 63} 64 65NTSTATUS ntvfs_async_state_push(struct ntvfs_module_context *ntvfs, 66 struct ntvfs_request *req, 67 void *private_data, 68 void (*send_fn)(struct ntvfs_request *)) 69{ 70 struct ntvfs_async_state *async; 71 72 async = talloc(req, struct ntvfs_async_state); 73 NT_STATUS_HAVE_NO_MEMORY(async); 74 75 async->state = req->async_states->state; 76 async->private_data = private_data; 77 async->send_fn = send_fn; 78 async->status = NT_STATUS_INTERNAL_ERROR; 79 80 async->ntvfs = ntvfs; 81 82 DLIST_ADD(req->async_states, async); 83 84 return NT_STATUS_OK; 85} 86 87void ntvfs_async_state_pop(struct ntvfs_request *req) 88{ 89 struct ntvfs_async_state *async; 90 91 async = req->async_states; 92 93 DLIST_REMOVE(req->async_states, async); 94 95 req->async_states->state = async->state; 96 req->async_states->status = async->status; 97 98 talloc_free(async); 99} 100 101NTSTATUS ntvfs_handle_new(struct ntvfs_module_context *ntvfs, 102 struct ntvfs_request *req, 103 struct ntvfs_handle **h) 104{ 105 if (!ntvfs->ctx->handles.create_new) { 106 return NT_STATUS_NOT_IMPLEMENTED; 107 } 108 return ntvfs->ctx->handles.create_new(ntvfs->ctx->handles.private_data, req, h); 109} 110 111NTSTATUS ntvfs_handle_set_backend_data(struct ntvfs_handle *h, 112 struct ntvfs_module_context *ntvfs, 113 TALLOC_CTX *private_data) 114{ 115 struct ntvfs_handle_data *d; 116 bool first_time = h->backend_data?false:true; 117 118 for (d=h->backend_data; d; d = d->next) { 119 if (d->owner != ntvfs) continue; 120 d->private_data = talloc_steal(d, private_data); 121 return NT_STATUS_OK; 122 } 123 124 d = talloc(h, struct ntvfs_handle_data); 125 NT_STATUS_HAVE_NO_MEMORY(d); 126 d->owner = ntvfs; 127 d->private_data = talloc_steal(d, private_data); 128 129 DLIST_ADD(h->backend_data, d); 130 131 if (first_time) { 132 NTSTATUS status; 133 status = h->ctx->handles.make_valid(h->ctx->handles.private_data, h); 134 NT_STATUS_NOT_OK_RETURN(status); 135 } 136 137 return NT_STATUS_OK; 138} 139 140void *ntvfs_handle_get_backend_data(struct ntvfs_handle *h, 141 struct ntvfs_module_context *ntvfs) 142{ 143 struct ntvfs_handle_data *d; 144 145 for (d=h->backend_data; d; d = d->next) { 146 if (d->owner != ntvfs) continue; 147 return d->private_data; 148 } 149 150 return NULL; 151} 152 153void ntvfs_handle_remove_backend_data(struct ntvfs_handle *h, 154 struct ntvfs_module_context *ntvfs) 155{ 156 struct ntvfs_handle_data *d,*n; 157 158 for (d=h->backend_data; d; d = n) { 159 n = d->next; 160 if (d->owner != ntvfs) continue; 161 DLIST_REMOVE(h->backend_data, d); 162 talloc_free(d); 163 d = NULL; 164 } 165 166 if (h->backend_data) return; 167 168 /* if there's no backend_data anymore, destroy the handle */ 169 h->ctx->handles.destroy(h->ctx->handles.private_data, h); 170} 171 172struct ntvfs_handle *ntvfs_handle_search_by_wire_key(struct ntvfs_module_context *ntvfs, 173 struct ntvfs_request *req, 174 const DATA_BLOB *key) 175{ 176 if (!ntvfs->ctx->handles.search_by_wire_key) { 177 return NULL; 178 } 179 return ntvfs->ctx->handles.search_by_wire_key(ntvfs->ctx->handles.private_data, req, key); 180} 181 182DATA_BLOB ntvfs_handle_get_wire_key(struct ntvfs_handle *h, TALLOC_CTX *mem_ctx) 183{ 184 return h->ctx->handles.get_wire_key(h->ctx->handles.private_data, h, mem_ctx); 185} 186 187NTSTATUS ntvfs_set_handle_callbacks(struct ntvfs_context *ntvfs, 188 NTSTATUS (*create_new)(void *private_data, struct ntvfs_request *req, struct ntvfs_handle **h), 189 NTSTATUS (*make_valid)(void *private_data, struct ntvfs_handle *h), 190 void (*destroy)(void *private_data, struct ntvfs_handle *h), 191 struct ntvfs_handle *(*search_by_wire_key)(void *private_data, struct ntvfs_request *req, const DATA_BLOB *key), 192 DATA_BLOB (*get_wire_key)(void *private_data, struct ntvfs_handle *handle, TALLOC_CTX *mem_ctx), 193 void *private_data) 194{ 195 ntvfs->handles.create_new = create_new; 196 ntvfs->handles.make_valid = make_valid; 197 ntvfs->handles.destroy = destroy; 198 ntvfs->handles.search_by_wire_key = search_by_wire_key; 199 ntvfs->handles.get_wire_key = get_wire_key; 200 ntvfs->handles.private_data = private_data; 201 return NT_STATUS_OK; 202} 203