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 199450 : 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 199450 : if (strcmp(attr_name, XATTR_LIST_ATTR) == 0) {
45 98143 : return NT_STATUS_OK;
46 : }
47 :
48 101307 : mem_ctx = talloc_new(ctx);
49 :
50 101307 : status = pull_xattr_blob_tdb_raw(ea_tdb, mem_ctx, XATTR_LIST_ATTR,
51 : fname, fd, 100, &blob);
52 101307 : if (!NT_STATUS_IS_OK(status)) {
53 97562 : blob = data_blob(NULL, 0);
54 : }
55 :
56 102153 : for (s=(const char *)blob.data; s < (const char *)(blob.data+blob.length); s += strlen(s) + 1) {
57 4010 : if (strcmp(attr_name, s) == 0) {
58 3164 : talloc_free(mem_ctx);
59 3164 : return NT_STATUS_OK;
60 : }
61 : }
62 :
63 98143 : len = strlen(attr_name) + 1;
64 :
65 98143 : blob.data = talloc_realloc(mem_ctx, blob.data, uint8_t, blob.length + len);
66 98143 : if (blob.data == NULL) {
67 0 : talloc_free(mem_ctx);
68 0 : return NT_STATUS_NO_MEMORY;
69 : }
70 98143 : memcpy(blob.data + blob.length, attr_name, len);
71 98143 : blob.length += len;
72 :
73 98143 : status = push_xattr_blob_tdb_raw(ea_tdb, XATTR_LIST_ATTR, fname, fd, &blob);
74 98143 : talloc_free(mem_ctx);
75 :
76 98143 : return status;
77 : }
78 :
79 : /*
80 : form a key for using in the ea_tdb
81 : */
82 1992775 : 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 1992775 : size_t len = strlen(attr_name);
89 :
90 1992775 : if (fd == -1) {
91 1499127 : if (stat(fname, &st) == -1) {
92 0 : return NT_STATUS_NOT_FOUND;
93 : }
94 : } else {
95 493648 : if (fstat(fd, &st) == -1) {
96 0 : return NT_STATUS_NOT_FOUND;
97 : }
98 : }
99 :
100 1992775 : key->dptr = talloc_array(mem_ctx, uint8_t, 16 + len);
101 1992775 : if (key->dptr == NULL) {
102 0 : return NT_STATUS_NO_MEMORY;
103 : }
104 1992775 : key->dsize = 16 + len;
105 :
106 1992775 : SBVAL(key->dptr, 0, st.st_dev);
107 1992775 : SBVAL(key->dptr, 8, st.st_ino);
108 1992775 : memcpy(key->dptr+16, attr_name, len);
109 :
110 1992775 : return NT_STATUS_OK;
111 : }
112 :
113 :
114 :
115 : /*
116 : pull a xattr as a blob, using the ea_tdb_context tdb
117 : */
118 1598308 : 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 1598308 : status = get_ea_tdb_key(mem_ctx, attr_name, fname, fd, &tkey);
130 1598308 : if (!NT_STATUS_IS_OK(status)) {
131 0 : return status;
132 : }
133 :
134 1598308 : tdata = tdb_fetch(ea_tdb->tdb, tkey);
135 1598308 : if (tdata.dptr == NULL) {
136 1150151 : return NT_STATUS_NOT_FOUND;
137 : }
138 :
139 448157 : *blob = data_blob_talloc(mem_ctx, tdata.dptr, tdata.dsize);
140 448157 : free(tdata.dptr);
141 448157 : if (blob->data == NULL) {
142 0 : return NT_STATUS_NO_MEMORY;
143 : }
144 :
145 448157 : return NT_STATUS_OK;
146 : }
147 :
148 : /*
149 : push a xattr as a blob, using ea_tdb
150 : */
151 199450 : 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 199450 : TALLOC_CTX *mem_ctx = talloc_new(ea_tdb);
160 199450 : if (!mem_ctx) {
161 0 : return NT_STATUS_NO_MEMORY;
162 : }
163 :
164 199450 : status = get_ea_tdb_key(mem_ctx, attr_name, fname, fd, &tkey);
165 199450 : if (!NT_STATUS_IS_OK(status)) {
166 0 : talloc_free(mem_ctx);
167 0 : return status;
168 : }
169 :
170 199450 : tdata.dptr = blob->data;
171 199450 : tdata.dsize = blob->length;
172 :
173 199450 : 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 199450 : status = posix_eadb_add_list(ea_tdb,mem_ctx, attr_name, fname, fd);
179 199450 : if (!NT_STATUS_IS_OK(status)) {
180 0 : talloc_free(mem_ctx);
181 0 : goto done;
182 : }
183 :
184 199450 : if (tdb_store(ea_tdb->tdb, tkey, tdata, TDB_REPLACE) != 0) {
185 0 : status = NT_STATUS_INTERNAL_DB_CORRUPTION;
186 : }
187 :
188 199450 : done:
189 199450 : tdb_chainunlock(ea_tdb->tdb, tkey);
190 199450 : talloc_free(mem_ctx);
191 199450 : return status;
192 : }
193 :
194 :
195 : /*
196 : delete a xattr
197 : */
198 195017 : 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 195017 : status = get_ea_tdb_key(NULL, attr_name, fname, fd, &tkey);
205 195017 : if (!NT_STATUS_IS_OK(status)) {
206 0 : return status;
207 : }
208 :
209 195017 : 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 195012 : talloc_free(tkey.dptr);
215 195012 : return NT_STATUS_OK;
216 : }
217 :
218 :
219 : /*
220 : delete all xattrs for a file
221 : */
222 208509 : NTSTATUS unlink_posix_eadb_raw(struct tdb_wrap *ea_tdb, const char *fname, int fd)
223 : {
224 208509 : TALLOC_CTX *mem_ctx = talloc_new(ea_tdb);
225 : DATA_BLOB blob;
226 : const char *s;
227 : NTSTATUS status;
228 :
229 208509 : status = pull_xattr_blob_tdb_raw(ea_tdb, mem_ctx, XATTR_LIST_ATTR,
230 : fname, fd, 100, &blob);
231 208509 : if (!NT_STATUS_IS_OK(status)) {
232 111292 : talloc_free(mem_ctx);
233 111292 : return NT_STATUS_OK;
234 : }
235 :
236 195010 : for (s=(const char *)blob.data; s < (const char *)(blob.data+blob.length); s += strlen(s) + 1) {
237 97793 : delete_posix_eadb_raw(ea_tdb, s, fname, -1);
238 : }
239 :
240 97217 : status = delete_posix_eadb_raw(ea_tdb, XATTR_LIST_ATTR, fname, fd);
241 97217 : talloc_free(mem_ctx);
242 97217 : 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 1288492 : 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 1288492 : return pull_xattr_blob_tdb_raw(pvfs_state->ea_db,mem_ctx,attr_name,fname,fd,estimated_size,blob);
266 : }
267 :
268 100761 : 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 100761 : 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 208509 : NTSTATUS unlink_posix_eadb(struct pvfs_state *pvfs_state, const char *fname)
291 : {
292 208509 : return unlink_posix_eadb_raw(pvfs_state->ea_db, fname, -1);
293 : }
294 :
295 : #endif
|