r15768: make it possible that the caller of the ntvfs_subsystem doesn't
[sharpe/samba-autobuild/.git] / source4 / ntvfs / ntvfs_util.c
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 2 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, write to the Free Software
18    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
19 */
20 /*
21   this implements common utility functions that many NTVFS backends may wish to use
22 */
23
24 #include "includes.h"
25 #include "dlinklist.h"
26 #include "ntvfs/ntvfs.h"
27
28
29 _PUBLIC_ struct ntvfs_request *ntvfs_request_create(struct ntvfs_context *ctx, TALLOC_CTX *mem_ctx,
30                                                     struct auth_session_info *session_info,
31                                                     uint16_t smbpid, uint16_t smbmid,
32                                                     struct timeval request_time,
33                                                     void *private_data,
34                                                     void (*send_fn)(struct ntvfs_request *),
35                                                     uint32_t state)
36 {
37         struct ntvfs_request *req;
38         struct ntvfs_async_state *async;
39
40         req = talloc(mem_ctx, struct ntvfs_request);
41         if (!req) return NULL;
42         req->ctx                        = ctx;
43         req->async_states               = NULL;
44         req->session_info               = session_info;
45         req->smbpid                     = smbpid;
46         req->smbmid                     = smbmid;
47         req->statistics.request_time    = request_time;
48
49         async = talloc(req, struct ntvfs_async_state);
50         if (!async) goto failed;
51
52         async->state            = state;
53         async->private_data     = private_data;
54         async->send_fn          = send_fn;
55         async->status           = NT_STATUS_INTERNAL_ERROR;
56         async->ntvfs            = NULL;
57
58         DLIST_ADD(req->async_states, async);
59
60         return req;
61 failed:
62         talloc_free(req);
63         return NULL;
64 }
65
66 _PUBLIC_ NTSTATUS ntvfs_async_state_push(struct ntvfs_module_context *ntvfs,
67                                          struct ntvfs_request *req,
68                                          void *private_data,
69                                          void (*send_fn)(struct ntvfs_request *))
70 {
71         struct ntvfs_async_state *async;
72
73         async = talloc(req, struct ntvfs_async_state);
74         NT_STATUS_HAVE_NO_MEMORY(async);
75
76         async->state            = req->async_states->state;
77         async->private_data     = private_data;
78         async->send_fn          = send_fn;
79         async->status           = NT_STATUS_INTERNAL_ERROR;
80
81         async->ntvfs            = ntvfs;
82
83         DLIST_ADD(req->async_states, async);
84
85         return NT_STATUS_OK;
86 }
87
88 _PUBLIC_ void ntvfs_async_state_pop(struct ntvfs_request *req)
89 {
90         struct ntvfs_async_state *async;
91
92         async = req->async_states;
93
94         DLIST_REMOVE(req->async_states, async);
95
96         req->async_states->state        = async->state;
97         req->async_states->status       = async->status;
98
99         talloc_free(async);
100 }
101
102 _PUBLIC_ NTSTATUS ntvfs_handle_new(struct ntvfs_module_context *ntvfs,
103                                    struct ntvfs_request *req,
104                                    struct ntvfs_handle **h)
105 {
106         if (!ntvfs->ctx->handles.create_new) {
107                 return NT_STATUS_NOT_IMPLEMENTED;
108         }
109         return ntvfs->ctx->handles.create_new(ntvfs->ctx->handles.private_data, req, h);
110 }
111
112 _PUBLIC_ NTSTATUS ntvfs_handle_set_backend_data(struct ntvfs_handle *h,
113                                                 struct ntvfs_module_context *ntvfs,
114                                                 TALLOC_CTX *private_data)
115 {
116         struct ntvfs_handle_data *d;
117         BOOL first_time = h->backend_data?False:True;
118
119         for (d=h->backend_data; d; d = d->next) {
120                 if (d->owner != ntvfs) continue;
121                 d->private_data = talloc_steal(d, private_data);
122                 return NT_STATUS_OK;
123         }
124
125         d = talloc(h, struct ntvfs_handle_data);
126         NT_STATUS_HAVE_NO_MEMORY(d);
127         d->owner = ntvfs;
128         d->private_data = talloc_steal(d, private_data);
129
130         DLIST_ADD(h->backend_data, d);
131
132         if (first_time) {
133                 NTSTATUS status;
134                 status = h->ctx->handles.make_valid(h->ctx->handles.private_data, h);
135                 NT_STATUS_NOT_OK_RETURN(status);
136         }
137
138         return NT_STATUS_OK;
139 }
140
141 _PUBLIC_ void *ntvfs_handle_get_backend_data(struct ntvfs_handle *h,
142                                              struct ntvfs_module_context *ntvfs)
143 {
144         struct ntvfs_handle_data *d;
145
146         for (d=h->backend_data; d; d = d->next) {
147                 if (d->owner != ntvfs) continue;
148                 return d->private_data;
149         }
150
151         return NULL;
152 }
153
154 _PUBLIC_ void ntvfs_handle_remove_backend_data(struct ntvfs_handle *h,
155                                                struct ntvfs_module_context *ntvfs)
156 {
157         struct ntvfs_handle_data *d,*n;
158
159         for (d=h->backend_data; d; d = n) {
160                 n = d->next;
161                 if (d->owner != ntvfs) continue;
162                 DLIST_REMOVE(h->backend_data, d);
163                 talloc_free(d);
164                 d = NULL;
165         }
166
167         if (h->backend_data) return;
168
169         /* if there's no backend_data anymore, destroy the handle */
170         h->ctx->handles.destroy(h->ctx->handles.private_data, h);
171 }
172
173 _PUBLIC_ struct ntvfs_handle *ntvfs_handle_search_by_wire_key(struct ntvfs_module_context *ntvfs,
174                                                               struct ntvfs_request *req,
175                                                               const DATA_BLOB *key)
176 {
177         if (!ntvfs->ctx->handles.search_by_wire_key) {
178                 return NULL;
179         }
180         return ntvfs->ctx->handles.search_by_wire_key(ntvfs->ctx->handles.private_data, req, key);
181 }
182
183 _PUBLIC_ DATA_BLOB ntvfs_handle_get_wire_key(struct ntvfs_handle *h, TALLOC_CTX *mem_ctx)
184 {
185         return h->ctx->handles.get_wire_key(h->ctx->handles.private_data, h, mem_ctx);
186 }
187
188 _PUBLIC_ NTSTATUS ntvfs_set_handle_callbacks(struct ntvfs_context *ntvfs,
189                                              NTSTATUS (*create_new)(void *private_data, struct ntvfs_request *req, struct ntvfs_handle **h),
190                                              NTSTATUS (*make_valid)(void *private_data, struct ntvfs_handle *h),
191                                              void (*destroy)(void *private_data, struct ntvfs_handle *h),
192                                              struct ntvfs_handle *(*search_by_wire_key)(void *private_data, struct ntvfs_request *req, const DATA_BLOB *key),
193                                              DATA_BLOB (*get_wire_key)(void *private_data, struct ntvfs_handle *handle, TALLOC_CTX *mem_ctx),
194                                              void *private_data)
195 {
196         ntvfs->handles.create_new               = create_new;
197         ntvfs->handles.make_valid               = make_valid;
198         ntvfs->handles.destroy                  = destroy;
199         ntvfs->handles.search_by_wire_key       = search_by_wire_key;
200         ntvfs->handles.get_wire_key             = get_wire_key;
201         ntvfs->handles.private_data             = private_data;
202         return NT_STATUS_OK;
203 }