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 200212 : 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 503 : DATA_BLOB blob;
39 503 : TALLOC_CTX *mem_ctx;
40 503 : NTSTATUS status;
41 503 : size_t len;
42 :
43 200212 : if (strcmp(attr_name, XATTR_LIST_ATTR) == 0) {
44 98405 : return NT_STATUS_OK;
45 : }
46 :
47 101807 : mem_ctx = talloc_new(ctx);
48 :
49 101807 : status = pull_xattr_blob_tdb_raw(ea_tdb, mem_ctx, XATTR_LIST_ATTR,
50 : fname, fd, 100, &blob);
51 101807 : if (NT_STATUS_IS_OK(status)) {
52 135 : const char *s;
53 :
54 3991 : for (s = (const char *)blob.data;
55 4874 : s < (const char *)(blob.data + blob.length);
56 883 : s += strlen(s) + 1) {
57 4285 : if (strcmp(attr_name, s) == 0) {
58 3402 : talloc_free(mem_ctx);
59 3402 : return NT_STATUS_OK;
60 : }
61 : }
62 : } else {
63 97816 : blob = data_blob(NULL, 0);
64 : /* No need to parse an empty blob */
65 : }
66 :
67 98405 : len = strlen(attr_name) + 1;
68 :
69 98405 : blob.data = talloc_realloc(mem_ctx, blob.data, uint8_t, blob.length + len);
70 98405 : if (blob.data == NULL) {
71 0 : talloc_free(mem_ctx);
72 0 : return NT_STATUS_NO_MEMORY;
73 : }
74 98405 : memcpy(blob.data + blob.length, attr_name, len);
75 98405 : blob.length += len;
76 :
77 98405 : status = push_xattr_blob_tdb_raw(ea_tdb, XATTR_LIST_ATTR, fname, fd, &blob);
78 98405 : talloc_free(mem_ctx);
79 :
80 98405 : return status;
81 : }
82 :
83 : /*
84 : form a key for using in the ea_tdb
85 : */
86 1994151 : static NTSTATUS get_ea_tdb_key(TALLOC_CTX *mem_ctx,
87 : const char *attr_name,
88 : const char *fname, int fd,
89 : TDB_DATA *key)
90 : {
91 824 : struct stat st;
92 1994151 : size_t len = strlen(attr_name);
93 :
94 1994151 : if (fd == -1) {
95 1500072 : if (stat(fname, &st) == -1) {
96 0 : return NT_STATUS_NOT_FOUND;
97 : }
98 : } else {
99 494079 : if (fstat(fd, &st) == -1) {
100 0 : return NT_STATUS_NOT_FOUND;
101 : }
102 : }
103 :
104 1994151 : key->dptr = talloc_array(mem_ctx, uint8_t, 16 + len);
105 1994151 : if (key->dptr == NULL) {
106 0 : return NT_STATUS_NO_MEMORY;
107 : }
108 1994151 : key->dsize = 16 + len;
109 :
110 1994151 : SBVAL(key->dptr, 0, st.st_dev);
111 1994151 : SBVAL(key->dptr, 8, st.st_ino);
112 1994151 : memcpy(key->dptr+16, attr_name, len);
113 :
114 1994151 : return NT_STATUS_OK;
115 : }
116 :
117 :
118 :
119 : /*
120 : pull a xattr as a blob, using the ea_tdb_context tdb
121 : */
122 1598894 : NTSTATUS pull_xattr_blob_tdb_raw(struct tdb_wrap *ea_tdb,
123 : TALLOC_CTX *mem_ctx,
124 : const char *attr_name,
125 : const char *fname,
126 : int fd,
127 : size_t estimated_size,
128 : DATA_BLOB *blob)
129 : {
130 321 : TDB_DATA tkey, tdata;
131 321 : NTSTATUS status;
132 :
133 1598894 : status = get_ea_tdb_key(mem_ctx, attr_name, fname, fd, &tkey);
134 1598894 : if (!NT_STATUS_IS_OK(status)) {
135 0 : return status;
136 : }
137 :
138 1598894 : tdata = tdb_fetch(ea_tdb->tdb, tkey);
139 1598894 : if (tdata.dptr == NULL) {
140 1150589 : return NT_STATUS_NOT_FOUND;
141 : }
142 :
143 448305 : *blob = data_blob_talloc(mem_ctx, tdata.dptr, tdata.dsize);
144 448305 : free(tdata.dptr);
145 448305 : if (blob->data == NULL) {
146 0 : return NT_STATUS_NO_MEMORY;
147 : }
148 :
149 448305 : return NT_STATUS_OK;
150 : }
151 :
152 : /*
153 : push a xattr as a blob, using ea_tdb
154 : */
155 200212 : NTSTATUS push_xattr_blob_tdb_raw(struct tdb_wrap *ea_tdb,
156 : const char *attr_name,
157 : const char *fname,
158 : int fd,
159 : const DATA_BLOB *blob)
160 : {
161 503 : TDB_DATA tkey, tdata;
162 503 : NTSTATUS status;
163 200212 : TALLOC_CTX *mem_ctx = talloc_new(ea_tdb);
164 200212 : if (!mem_ctx) {
165 0 : return NT_STATUS_NO_MEMORY;
166 : }
167 :
168 200212 : status = get_ea_tdb_key(mem_ctx, attr_name, fname, fd, &tkey);
169 200212 : if (!NT_STATUS_IS_OK(status)) {
170 0 : talloc_free(mem_ctx);
171 0 : return status;
172 : }
173 :
174 200212 : tdata.dptr = blob->data;
175 200212 : tdata.dsize = blob->length;
176 :
177 200212 : if (tdb_chainlock(ea_tdb->tdb, tkey) != 0) {
178 0 : talloc_free(mem_ctx);
179 0 : return NT_STATUS_INTERNAL_DB_CORRUPTION;
180 : }
181 :
182 200212 : status = posix_eadb_add_list(ea_tdb,mem_ctx, attr_name, fname, fd);
183 200212 : if (!NT_STATUS_IS_OK(status)) {
184 0 : talloc_free(mem_ctx);
185 0 : goto done;
186 : }
187 :
188 200212 : if (tdb_store(ea_tdb->tdb, tkey, tdata, TDB_REPLACE) != 0) {
189 0 : status = NT_STATUS_INTERNAL_DB_CORRUPTION;
190 : }
191 :
192 200212 : done:
193 200212 : tdb_chainunlock(ea_tdb->tdb, tkey);
194 200212 : talloc_free(mem_ctx);
195 200212 : return status;
196 : }
197 :
198 :
199 : /*
200 : delete a xattr
201 : */
202 195045 : NTSTATUS delete_posix_eadb_raw(struct tdb_wrap *ea_tdb, const char *attr_name,
203 : const char *fname, int fd)
204 : {
205 0 : TDB_DATA tkey;
206 0 : NTSTATUS status;
207 :
208 195045 : status = get_ea_tdb_key(NULL, attr_name, fname, fd, &tkey);
209 195045 : if (!NT_STATUS_IS_OK(status)) {
210 0 : return status;
211 : }
212 :
213 195045 : if (tdb_delete(ea_tdb->tdb, tkey) != 0) {
214 5 : talloc_free(tkey.dptr);
215 5 : return NT_STATUS_INTERNAL_DB_CORRUPTION;
216 : }
217 :
218 195040 : talloc_free(tkey.dptr);
219 195040 : return NT_STATUS_OK;
220 : }
221 :
222 :
223 : /*
224 : delete all xattrs for a file
225 : */
226 208531 : NTSTATUS unlink_posix_eadb_raw(struct tdb_wrap *ea_tdb, const char *fname, int fd)
227 : {
228 208531 : TALLOC_CTX *mem_ctx = talloc_new(ea_tdb);
229 0 : DATA_BLOB blob;
230 0 : const char *s;
231 0 : NTSTATUS status;
232 :
233 208531 : status = pull_xattr_blob_tdb_raw(ea_tdb, mem_ctx, XATTR_LIST_ATTR,
234 : fname, fd, 100, &blob);
235 208531 : if (!NT_STATUS_IS_OK(status)) {
236 111302 : talloc_free(mem_ctx);
237 111302 : return NT_STATUS_OK;
238 : }
239 :
240 195038 : for (s=(const char *)blob.data; s < (const char *)(blob.data+blob.length); s += strlen(s) + 1) {
241 97809 : delete_posix_eadb_raw(ea_tdb, s, fname, -1);
242 : }
243 :
244 97229 : status = delete_posix_eadb_raw(ea_tdb, XATTR_LIST_ATTR, fname, fd);
245 97229 : talloc_free(mem_ctx);
246 97229 : return status;
247 : }
248 :
249 : /*
250 : list all xattrs for a file
251 : */
252 0 : NTSTATUS list_posix_eadb_raw(struct tdb_wrap *ea_tdb, TALLOC_CTX *mem_ctx,
253 : const char *fname, int fd,
254 : DATA_BLOB *list)
255 : {
256 0 : return pull_xattr_blob_tdb_raw(ea_tdb, mem_ctx, XATTR_LIST_ATTR,
257 : fname, fd, 100, list);
258 : }
259 :
260 : #ifdef WITH_NTVFS_FILESERVER
261 1288554 : NTSTATUS pull_xattr_blob_tdb(struct pvfs_state *pvfs_state,
262 : TALLOC_CTX *mem_ctx,
263 : const char *attr_name,
264 : const char *fname,
265 : int fd,
266 : size_t estimated_size,
267 : DATA_BLOB *blob)
268 : {
269 1288554 : return pull_xattr_blob_tdb_raw(pvfs_state->ea_db,mem_ctx,attr_name,fname,fd,estimated_size,blob);
270 : }
271 :
272 100837 : NTSTATUS push_xattr_blob_tdb(struct pvfs_state *pvfs_state,
273 : const char *attr_name,
274 : const char *fname,
275 : int fd,
276 : const DATA_BLOB *blob)
277 : {
278 100837 : return push_xattr_blob_tdb_raw(pvfs_state->ea_db, attr_name, fname, fd, blob);
279 : }
280 :
281 : /*
282 : delete a xattr
283 : */
284 7 : NTSTATUS delete_posix_eadb(struct pvfs_state *pvfs_state, const char *attr_name,
285 : const char *fname, int fd)
286 : {
287 7 : return delete_posix_eadb_raw(pvfs_state->ea_db,
288 : attr_name, fname, fd);
289 : }
290 :
291 : /*
292 : delete all xattrs for a file
293 : */
294 208531 : NTSTATUS unlink_posix_eadb(struct pvfs_state *pvfs_state, const char *fname)
295 : {
296 208531 : return unlink_posix_eadb_raw(pvfs_state->ea_db, fname, -1);
297 : }
298 :
299 : #endif
|