Line data Source code
1 : /*
2 : Unix SMB/CIFS implementation.
3 :
4 : POSIX NTVFS backend - xattr support using a tdb
5 :
6 : Copyright (C) Andrew Tridgell 2004
7 :
8 : This program is free software; you can redistribute it and/or modify
9 : it under the terms of the GNU General Public License as published by
10 : the Free Software Foundation; either version 3 of the License, or
11 : (at your option) any later version.
12 :
13 : This program is distributed in the hope that it will be useful,
14 : but WITHOUT ANY WARRANTY; without even the implied warranty of
15 : MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 : GNU General Public License for more details.
17 :
18 : You should have received a copy of the GNU General Public License
19 : along with this program. If not, see <http://www.gnu.org/licenses/>.
20 : */
21 :
22 : #include "includes.h"
23 : #include "lib/tdb_wrap/tdb_wrap.h"
24 : #ifdef WITH_NTVFS_FILESERVER
25 : #include "vfs_posix.h"
26 : #endif
27 : #include "posix_eadb.h"
28 :
29 : #define XATTR_LIST_ATTR ".xattr_list"
30 :
31 : /*
32 : we need to maintain a list of attributes on each file, so that unlink
33 : can automatically clean them up
34 : */
35 198852 : static NTSTATUS posix_eadb_add_list(struct tdb_wrap *ea_tdb, TALLOC_CTX *ctx, const char *attr_name,
36 : const char *fname, int fd)
37 : {
38 : DATA_BLOB blob;
39 : TALLOC_CTX *mem_ctx;
40 : const char *s;
41 : NTSTATUS status;
42 : size_t len;
43 :
44 198852 : if (strcmp(attr_name, XATTR_LIST_ATTR) == 0) {
45 97927 : return NT_STATUS_OK;
46 : }
47 :
48 100925 : mem_ctx = talloc_new(ctx);
49 :
50 100925 : status = pull_xattr_blob_tdb_raw(ea_tdb, mem_ctx, XATTR_LIST_ATTR,
51 : fname, fd, 100, &blob);
52 100925 : if (!NT_STATUS_IS_OK(status)) {
53 97346 : blob = data_blob(NULL, 0);
54 : }
55 :
56 101771 : for (s=(const char *)blob.data; s < (const char *)(blob.data+blob.length); s += strlen(s) + 1) {
57 3844 : if (strcmp(attr_name, s) == 0) {
58 2998 : talloc_free(mem_ctx);
59 2998 : return NT_STATUS_OK;
60 : }
61 : }
62 :
63 97927 : len = strlen(attr_name) + 1;
64 :
65 97927 : blob.data = talloc_realloc(mem_ctx, blob.data, uint8_t, blob.length + len);
66 97927 : if (blob.data == NULL) {
67 0 : talloc_free(mem_ctx);
68 0 : return NT_STATUS_NO_MEMORY;
69 : }
70 97927 : memcpy(blob.data + blob.length, attr_name, len);
71 97927 : blob.length += len;
72 :
73 97927 : status = push_xattr_blob_tdb_raw(ea_tdb, XATTR_LIST_ATTR, fname, fd, &blob);
74 97927 : talloc_free(mem_ctx);
75 :
76 97927 : return status;
77 : }
78 :
79 : /*
80 : form a key for using in the ea_tdb
81 : */
82 1989545 : static NTSTATUS get_ea_tdb_key(TALLOC_CTX *mem_ctx,
83 : const char *attr_name,
84 : const char *fname, int fd,
85 : TDB_DATA *key)
86 : {
87 : struct stat st;
88 1989545 : size_t len = strlen(attr_name);
89 :
90 1989545 : if (fd == -1) {
91 1496050 : if (stat(fname, &st) == -1) {
92 0 : return NT_STATUS_NOT_FOUND;
93 : }
94 : } else {
95 493495 : if (fstat(fd, &st) == -1) {
96 0 : return NT_STATUS_NOT_FOUND;
97 : }
98 : }
99 :
100 1989545 : key->dptr = talloc_array(mem_ctx, uint8_t, 16 + len);
101 1989545 : if (key->dptr == NULL) {
102 0 : return NT_STATUS_NO_MEMORY;
103 : }
104 1989545 : key->dsize = 16 + len;
105 :
106 1989545 : SBVAL(key->dptr, 0, st.st_dev);
107 1989545 : SBVAL(key->dptr, 8, st.st_ino);
108 1989545 : memcpy(key->dptr+16, attr_name, len);
109 :
110 1989545 : return NT_STATUS_OK;
111 : }
112 :
113 :
114 :
115 : /*
116 : pull a xattr as a blob, using the ea_tdb_context tdb
117 : */
118 1595751 : NTSTATUS pull_xattr_blob_tdb_raw(struct tdb_wrap *ea_tdb,
119 : TALLOC_CTX *mem_ctx,
120 : const char *attr_name,
121 : const char *fname,
122 : int fd,
123 : size_t estimated_size,
124 : DATA_BLOB *blob)
125 : {
126 : TDB_DATA tkey, tdata;
127 : NTSTATUS status;
128 :
129 1595751 : status = get_ea_tdb_key(mem_ctx, attr_name, fname, fd, &tkey);
130 1595751 : if (!NT_STATUS_IS_OK(status)) {
131 0 : return status;
132 : }
133 :
134 1595751 : tdata = tdb_fetch(ea_tdb->tdb, tkey);
135 1595751 : if (tdata.dptr == NULL) {
136 1147881 : return NT_STATUS_NOT_FOUND;
137 : }
138 :
139 447870 : *blob = data_blob_talloc(mem_ctx, tdata.dptr, tdata.dsize);
140 447870 : free(tdata.dptr);
141 447870 : if (blob->data == NULL) {
142 0 : return NT_STATUS_NO_MEMORY;
143 : }
144 :
145 447870 : return NT_STATUS_OK;
146 : }
147 :
148 : /*
149 : push a xattr as a blob, using ea_tdb
150 : */
151 198852 : NTSTATUS push_xattr_blob_tdb_raw(struct tdb_wrap *ea_tdb,
152 : const char *attr_name,
153 : const char *fname,
154 : int fd,
155 : const DATA_BLOB *blob)
156 : {
157 : TDB_DATA tkey, tdata;
158 : NTSTATUS status;
159 198852 : TALLOC_CTX *mem_ctx = talloc_new(ea_tdb);
160 198852 : if (!mem_ctx) {
161 0 : return NT_STATUS_NO_MEMORY;
162 : }
163 :
164 198852 : status = get_ea_tdb_key(mem_ctx, attr_name, fname, fd, &tkey);
165 198852 : if (!NT_STATUS_IS_OK(status)) {
166 0 : talloc_free(mem_ctx);
167 0 : return status;
168 : }
169 :
170 198852 : tdata.dptr = blob->data;
171 198852 : tdata.dsize = blob->length;
172 :
173 198852 : if (tdb_chainlock(ea_tdb->tdb, tkey) != 0) {
174 0 : talloc_free(mem_ctx);
175 0 : return NT_STATUS_INTERNAL_DB_CORRUPTION;
176 : }
177 :
178 198852 : status = posix_eadb_add_list(ea_tdb,mem_ctx, attr_name, fname, fd);
179 198852 : if (!NT_STATUS_IS_OK(status)) {
180 0 : talloc_free(mem_ctx);
181 0 : goto done;
182 : }
183 :
184 198852 : if (tdb_store(ea_tdb->tdb, tkey, tdata, TDB_REPLACE) != 0) {
185 0 : status = NT_STATUS_INTERNAL_DB_CORRUPTION;
186 : }
187 :
188 397594 : done:
189 198852 : tdb_chainunlock(ea_tdb->tdb, tkey);
190 198852 : talloc_free(mem_ctx);
191 198852 : return status;
192 : }
193 :
194 :
195 : /*
196 : delete a xattr
197 : */
198 194942 : NTSTATUS delete_posix_eadb_raw(struct tdb_wrap *ea_tdb, const char *attr_name,
199 : const char *fname, int fd)
200 : {
201 : TDB_DATA tkey;
202 : NTSTATUS status;
203 :
204 194942 : status = get_ea_tdb_key(NULL, attr_name, fname, fd, &tkey);
205 194942 : if (!NT_STATUS_IS_OK(status)) {
206 0 : return status;
207 : }
208 :
209 194942 : if (tdb_delete(ea_tdb->tdb, tkey) != 0) {
210 5 : talloc_free(tkey.dptr);
211 5 : return NT_STATUS_INTERNAL_DB_CORRUPTION;
212 : }
213 :
214 194937 : talloc_free(tkey.dptr);
215 194937 : return NT_STATUS_OK;
216 : }
217 :
218 :
219 : /*
220 : delete all xattrs for a file
221 : */
222 208459 : NTSTATUS unlink_posix_eadb_raw(struct tdb_wrap *ea_tdb, const char *fname, int fd)
223 : {
224 208459 : TALLOC_CTX *mem_ctx = talloc_new(ea_tdb);
225 : DATA_BLOB blob;
226 : const char *s;
227 : NTSTATUS status;
228 :
229 208459 : status = pull_xattr_blob_tdb_raw(ea_tdb, mem_ctx, XATTR_LIST_ATTR,
230 : fname, fd, 100, &blob);
231 208459 : if (!NT_STATUS_IS_OK(status)) {
232 111276 : talloc_free(mem_ctx);
233 111276 : return NT_STATUS_OK;
234 : }
235 :
236 194935 : for (s=(const char *)blob.data; s < (const char *)(blob.data+blob.length); s += strlen(s) + 1) {
237 97752 : delete_posix_eadb_raw(ea_tdb, s, fname, -1);
238 : }
239 :
240 97183 : status = delete_posix_eadb_raw(ea_tdb, XATTR_LIST_ATTR, fname, fd);
241 97183 : talloc_free(mem_ctx);
242 97183 : return status;
243 : }
244 :
245 : /*
246 : list all xattrs for a file
247 : */
248 0 : NTSTATUS list_posix_eadb_raw(struct tdb_wrap *ea_tdb, TALLOC_CTX *mem_ctx,
249 : const char *fname, int fd,
250 : DATA_BLOB *list)
251 : {
252 0 : return pull_xattr_blob_tdb_raw(ea_tdb, mem_ctx, XATTR_LIST_ATTR,
253 : fname, fd, 100, list);
254 : }
255 :
256 : #ifdef WITH_NTVFS_FILESERVER
257 1286367 : NTSTATUS pull_xattr_blob_tdb(struct pvfs_state *pvfs_state,
258 : TALLOC_CTX *mem_ctx,
259 : const char *attr_name,
260 : const char *fname,
261 : int fd,
262 : size_t estimated_size,
263 : DATA_BLOB *blob)
264 : {
265 1286367 : return pull_xattr_blob_tdb_raw(pvfs_state->ea_db,mem_ctx,attr_name,fname,fd,estimated_size,blob);
266 : }
267 :
268 100736 : NTSTATUS push_xattr_blob_tdb(struct pvfs_state *pvfs_state,
269 : const char *attr_name,
270 : const char *fname,
271 : int fd,
272 : const DATA_BLOB *blob)
273 : {
274 100736 : return push_xattr_blob_tdb_raw(pvfs_state->ea_db, attr_name, fname, fd, blob);
275 : }
276 :
277 : /*
278 : delete a xattr
279 : */
280 7 : NTSTATUS delete_posix_eadb(struct pvfs_state *pvfs_state, const char *attr_name,
281 : const char *fname, int fd)
282 : {
283 7 : return delete_posix_eadb_raw(pvfs_state->ea_db,
284 : attr_name, fname, fd);
285 : }
286 :
287 : /*
288 : delete all xattrs for a file
289 : */
290 208459 : NTSTATUS unlink_posix_eadb(struct pvfs_state *pvfs_state, const char *fname)
291 : {
292 208459 : return unlink_posix_eadb_raw(pvfs_state->ea_db, fname, -1);
293 : }
294 :
295 : #endif
|