Merge branch 'v4-0-test' of ssh://git.samba.org/data/git/samba into v4-0-test
[jelmer/samba4-debian.git] / source / 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 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
28 _PUBLIC_ struct 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->statistics.request_time    = request_time;
46
47         async = talloc(req, struct ntvfs_async_state);
48         if (!async) goto failed;
49
50         async->state            = state;
51         async->private_data     = private_data;
52         async->send_fn          = send_fn;
53         async->status           = NT_STATUS_INTERNAL_ERROR;
54         async->ntvfs            = NULL;
55
56         DLIST_ADD(req->async_states, async);
57
58         return req;
59 failed:
60         talloc_free(req);
61         return NULL;
62 }
63
64 _PUBLIC_ NTSTATUS ntvfs_async_state_push(struct ntvfs_module_context *ntvfs,
65                                          struct ntvfs_request *req,
66                                          void *private_data,
67                                          void (*send_fn)(struct ntvfs_request *))
68 {
69         struct ntvfs_async_state *async;
70
71         async = talloc(req, struct ntvfs_async_state);
72         NT_STATUS_HAVE_NO_MEMORY(async);
73
74         async->state            = req->async_states->state;
75         async->private_data     = private_data;
76         async->send_fn          = send_fn;
77         async->status           = NT_STATUS_INTERNAL_ERROR;
78
79         async->ntvfs            = ntvfs;
80
81         DLIST_ADD(req->async_states, async);
82
83         return NT_STATUS_OK;
84 }
85
86 _PUBLIC_ void ntvfs_async_state_pop(struct ntvfs_request *req)
87 {
88         struct ntvfs_async_state *async;
89
90         async = req->async_states;
91
92         DLIST_REMOVE(req->async_states, async);
93
94         req->async_states->state        = async->state;
95         req->async_states->status       = async->status;
96
97         talloc_free(async);
98 }
99
100 _PUBLIC_ NTSTATUS ntvfs_handle_new(struct ntvfs_module_context *ntvfs,
101                                    struct ntvfs_request *req,
102                                    struct ntvfs_handle **h)
103 {
104         if (!ntvfs->ctx->handles.create_new) {
105                 return NT_STATUS_NOT_IMPLEMENTED;
106         }
107         return ntvfs->ctx->handles.create_new(ntvfs->ctx->handles.private_data, req, h);
108 }
109
110 _PUBLIC_ NTSTATUS ntvfs_handle_set_backend_data(struct ntvfs_handle *h,
111                                                 struct ntvfs_module_context *ntvfs,
112                                                 TALLOC_CTX *private_data)
113 {
114         struct ntvfs_handle_data *d;
115         bool first_time = h->backend_data?false:true;
116
117         for (d=h->backend_data; d; d = d->next) {
118                 if (d->owner != ntvfs) continue;
119                 d->private_data = talloc_steal(d, private_data);
120                 return NT_STATUS_OK;
121         }
122
123         d = talloc(h, struct ntvfs_handle_data);
124         NT_STATUS_HAVE_NO_MEMORY(d);
125         d->owner = ntvfs;
126         d->private_data = talloc_steal(d, private_data);
127
128         DLIST_ADD(h->backend_data, d);
129
130         if (first_time) {
131                 NTSTATUS status;
132                 status = h->ctx->handles.make_valid(h->ctx->handles.private_data, h);
133                 NT_STATUS_NOT_OK_RETURN(status);
134         }
135
136         return NT_STATUS_OK;
137 }
138
139 _PUBLIC_ void *ntvfs_handle_get_backend_data(struct ntvfs_handle *h,
140                                              struct ntvfs_module_context *ntvfs)
141 {
142         struct ntvfs_handle_data *d;
143
144         for (d=h->backend_data; d; d = d->next) {
145                 if (d->owner != ntvfs) continue;
146                 return d->private_data;
147         }
148
149         return NULL;
150 }
151
152 _PUBLIC_ void ntvfs_handle_remove_backend_data(struct ntvfs_handle *h,
153                                                struct ntvfs_module_context *ntvfs)
154 {
155         struct ntvfs_handle_data *d,*n;
156
157         for (d=h->backend_data; d; d = n) {
158                 n = d->next;
159                 if (d->owner != ntvfs) continue;
160                 DLIST_REMOVE(h->backend_data, d);
161                 talloc_free(d);
162                 d = NULL;
163         }
164
165         if (h->backend_data) return;
166
167         /* if there's no backend_data anymore, destroy the handle */
168         h->ctx->handles.destroy(h->ctx->handles.private_data, h);
169 }
170
171 _PUBLIC_ struct ntvfs_handle *ntvfs_handle_search_by_wire_key(struct ntvfs_module_context *ntvfs,
172                                                               struct ntvfs_request *req,
173                                                               const DATA_BLOB *key)
174 {
175         if (!ntvfs->ctx->handles.search_by_wire_key) {
176                 return NULL;
177         }
178         return ntvfs->ctx->handles.search_by_wire_key(ntvfs->ctx->handles.private_data, req, key);
179 }
180
181 _PUBLIC_ DATA_BLOB ntvfs_handle_get_wire_key(struct ntvfs_handle *h, TALLOC_CTX *mem_ctx)
182 {
183         return h->ctx->handles.get_wire_key(h->ctx->handles.private_data, h, mem_ctx);
184 }
185
186 _PUBLIC_ NTSTATUS ntvfs_set_handle_callbacks(struct ntvfs_context *ntvfs,
187                                              NTSTATUS (*create_new)(void *private_data, struct ntvfs_request *req, struct ntvfs_handle **h),
188                                              NTSTATUS (*make_valid)(void *private_data, struct ntvfs_handle *h),
189                                              void (*destroy)(void *private_data, struct ntvfs_handle *h),
190                                              struct ntvfs_handle *(*search_by_wire_key)(void *private_data, struct ntvfs_request *req, const DATA_BLOB *key),
191                                              DATA_BLOB (*get_wire_key)(void *private_data, struct ntvfs_handle *handle, TALLOC_CTX *mem_ctx),
192                                              void *private_data)
193 {
194         ntvfs->handles.create_new               = create_new;
195         ntvfs->handles.make_valid               = make_valid;
196         ntvfs->handles.destroy                  = destroy;
197         ntvfs->handles.search_by_wire_key       = search_by_wire_key;
198         ntvfs->handles.get_wire_key             = get_wire_key;
199         ntvfs->handles.private_data             = private_data;
200         return NT_STATUS_OK;
201 }