r5871: Remove file with unused function (that uses fstring)
[Samba/gebeck_regimport.git] / source4 / ntvfs / posix / pvfs_xattr.c
blobc2af2e10bdea261f123a478d43a6dd934901d58a
1 /*
2 Unix SMB/CIFS implementation.
4 POSIX NTVFS backend - xattr support
6 Copyright (C) Andrew Tridgell 2004
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 2 of the License, or
11 (at your option) any later version.
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.
18 You should have received a copy of the GNU General Public License
19 along with this program; if not, write to the Free Software
20 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
23 #include "includes.h"
24 #include "vfs_posix.h"
25 #include "librpc/gen_ndr/ndr_xattr.h"
28 pull a xattr as a blob
30 static NTSTATUS pull_xattr_blob(struct pvfs_state *pvfs,
31 TALLOC_CTX *mem_ctx,
32 const char *attr_name,
33 const char *fname,
34 int fd,
35 size_t estimated_size,
36 DATA_BLOB *blob)
38 NTSTATUS status;
40 if (pvfs->ea_db) {
41 return pull_xattr_blob_tdb(pvfs, mem_ctx, attr_name, fname,
42 fd, estimated_size, blob);
45 status = pull_xattr_blob_system(pvfs, mem_ctx, attr_name, fname,
46 fd, estimated_size, blob);
48 /* if the filesystem doesn't support them, then tell pvfs not to try again */
49 if (NT_STATUS_EQUAL(status, NT_STATUS_NOT_SUPPORTED)) {
50 DEBUG(5,("pvfs_xattr: xattr not supported in filesystem\n"));
51 pvfs->flags &= ~PVFS_FLAG_XATTR_ENABLE;
52 status = NT_STATUS_NOT_FOUND;
55 return status;
59 push a xattr as a blob
61 static NTSTATUS push_xattr_blob(struct pvfs_state *pvfs,
62 const char *attr_name,
63 const char *fname,
64 int fd,
65 const DATA_BLOB *blob)
67 if (pvfs->ea_db) {
68 return push_xattr_blob_tdb(pvfs, attr_name, fname, fd, blob);
70 return push_xattr_blob_system(pvfs, attr_name, fname, fd, blob);
75 delete a xattr
77 static NTSTATUS delete_xattr(struct pvfs_state *pvfs, const char *attr_name,
78 const char *fname, int fd)
80 if (pvfs->ea_db) {
81 return delete_xattr_tdb(pvfs, attr_name, fname, fd);
83 return delete_xattr_system(pvfs, attr_name, fname, fd);
87 a hook called on unlink - allows the tdb xattr backend to cleanup
89 NTSTATUS pvfs_xattr_unlink_hook(struct pvfs_state *pvfs, const char *fname)
91 if (pvfs->ea_db) {
92 return unlink_xattr_tdb(pvfs, fname);
94 return unlink_xattr_system(pvfs, fname);
99 load a NDR structure from a xattr
101 static NTSTATUS pvfs_xattr_ndr_load(struct pvfs_state *pvfs,
102 TALLOC_CTX *mem_ctx,
103 const char *fname, int fd, const char *attr_name,
104 void *p, ndr_pull_flags_fn_t pull_fn)
106 NTSTATUS status;
107 DATA_BLOB blob;
109 status = pull_xattr_blob(pvfs, mem_ctx, attr_name, fname,
110 fd, XATTR_DOSATTRIB_ESTIMATED_SIZE, &blob);
111 if (!NT_STATUS_IS_OK(status)) {
112 return status;
115 /* pull the blob */
116 status = ndr_pull_struct_blob(&blob, mem_ctx, p, pull_fn);
118 data_blob_free(&blob);
120 return status;
124 save a NDR structure into a xattr
126 static NTSTATUS pvfs_xattr_ndr_save(struct pvfs_state *pvfs,
127 const char *fname, int fd, const char *attr_name,
128 void *p, ndr_push_flags_fn_t push_fn)
130 TALLOC_CTX *mem_ctx = talloc_new(NULL);
131 DATA_BLOB blob;
132 NTSTATUS status;
134 status = ndr_push_struct_blob(&blob, mem_ctx, p, push_fn);
135 if (!NT_STATUS_IS_OK(status)) {
136 talloc_free(mem_ctx);
137 return status;
140 status = push_xattr_blob(pvfs, attr_name, fname, fd, &blob);
141 talloc_free(mem_ctx);
143 return status;
148 fill in file attributes from extended attributes
150 NTSTATUS pvfs_dosattrib_load(struct pvfs_state *pvfs, struct pvfs_filename *name, int fd)
152 NTSTATUS status;
153 struct xattr_DosAttrib attrib;
154 TALLOC_CTX *mem_ctx = talloc_new(name);
155 struct xattr_DosInfo1 *info1;
156 struct xattr_DosInfo2 *info2;
158 if (name->stream_name != NULL) {
159 name->stream_exists = False;
160 } else {
161 name->stream_exists = True;
164 if (!(pvfs->flags & PVFS_FLAG_XATTR_ENABLE)) {
165 return NT_STATUS_OK;
168 status = pvfs_xattr_ndr_load(pvfs, mem_ctx, name->full_name,
169 fd, XATTR_DOSATTRIB_NAME,
170 &attrib,
171 (ndr_pull_flags_fn_t)ndr_pull_xattr_DosAttrib);
173 /* not having a DosAttrib is not an error */
174 if (NT_STATUS_EQUAL(status, NT_STATUS_NOT_FOUND)) {
175 talloc_free(mem_ctx);
176 return pvfs_stream_info(pvfs, name, fd);
179 if (!NT_STATUS_IS_OK(status)) {
180 talloc_free(mem_ctx);
181 return status;
184 switch (attrib.version) {
185 case 1:
186 info1 = &attrib.info.info1;
187 name->dos.attrib = pvfs_attrib_normalise(info1->attrib);
188 name->dos.ea_size = info1->ea_size;
189 if (name->st.st_size == info1->size) {
190 name->dos.alloc_size =
191 pvfs_round_alloc_size(pvfs, info1->alloc_size);
193 if (!null_nttime(info1->create_time)) {
194 name->dos.create_time = info1->create_time;
196 if (!null_nttime(info1->change_time)) {
197 name->dos.change_time = info1->change_time;
199 name->dos.flags = 0;
200 break;
202 case 2:
203 info2 = &attrib.info.info2;
204 name->dos.attrib = pvfs_attrib_normalise(info2->attrib);
205 name->dos.ea_size = info2->ea_size;
206 if (name->st.st_size == info2->size) {
207 name->dos.alloc_size =
208 pvfs_round_alloc_size(pvfs, info2->alloc_size);
210 if (!null_nttime(info2->create_time)) {
211 name->dos.create_time = info2->create_time;
213 if (!null_nttime(info2->change_time)) {
214 name->dos.change_time = info2->change_time;
216 name->dos.flags = info2->flags;
217 if (name->dos.flags & XATTR_ATTRIB_FLAG_STICKY_WRITE_TIME) {
218 name->dos.write_time = info2->write_time;
220 break;
222 default:
223 DEBUG(0,("ERROR: Unsupported xattr DosAttrib version %d on '%s'\n",
224 attrib.version, name->full_name));
225 talloc_free(mem_ctx);
226 return NT_STATUS_INVALID_LEVEL;
228 talloc_free(mem_ctx);
230 status = pvfs_stream_info(pvfs, name, fd);
232 return status;
237 save the file attribute into the xattr
239 NTSTATUS pvfs_dosattrib_save(struct pvfs_state *pvfs, struct pvfs_filename *name, int fd)
241 struct xattr_DosAttrib attrib;
242 struct xattr_DosInfo2 *info2;
244 if (!(pvfs->flags & PVFS_FLAG_XATTR_ENABLE)) {
245 return NT_STATUS_OK;
248 attrib.version = 2;
249 info2 = &attrib.info.info2;
251 name->dos.attrib = pvfs_attrib_normalise(name->dos.attrib);
253 info2->attrib = name->dos.attrib;
254 info2->ea_size = name->dos.ea_size;
255 info2->size = name->st.st_size;
256 info2->alloc_size = name->dos.alloc_size;
257 info2->create_time = name->dos.create_time;
258 info2->change_time = name->dos.change_time;
259 info2->write_time = name->dos.write_time;
260 info2->flags = name->dos.flags;
261 info2->name = "";
263 return pvfs_xattr_ndr_save(pvfs, name->full_name, fd,
264 XATTR_DOSATTRIB_NAME, &attrib,
265 (ndr_push_flags_fn_t)ndr_push_xattr_DosAttrib);
270 load the set of DOS EAs
272 NTSTATUS pvfs_doseas_load(struct pvfs_state *pvfs, struct pvfs_filename *name, int fd,
273 struct xattr_DosEAs *eas)
275 NTSTATUS status;
276 ZERO_STRUCTP(eas);
277 if (!(pvfs->flags & PVFS_FLAG_XATTR_ENABLE)) {
278 return NT_STATUS_OK;
280 status = pvfs_xattr_ndr_load(pvfs, eas, name->full_name, fd, XATTR_DOSEAS_NAME,
281 eas, (ndr_pull_flags_fn_t)ndr_pull_xattr_DosEAs);
282 if (NT_STATUS_EQUAL(status, NT_STATUS_NOT_FOUND)) {
283 return NT_STATUS_OK;
285 return status;
289 save the set of DOS EAs
291 NTSTATUS pvfs_doseas_save(struct pvfs_state *pvfs, struct pvfs_filename *name, int fd,
292 struct xattr_DosEAs *eas)
294 if (!(pvfs->flags & PVFS_FLAG_XATTR_ENABLE)) {
295 return NT_STATUS_OK;
297 return pvfs_xattr_ndr_save(pvfs, name->full_name, fd, XATTR_DOSEAS_NAME, eas,
298 (ndr_push_flags_fn_t)ndr_push_xattr_DosEAs);
303 load the set of streams from extended attributes
305 NTSTATUS pvfs_streams_load(struct pvfs_state *pvfs, struct pvfs_filename *name, int fd,
306 struct xattr_DosStreams *streams)
308 NTSTATUS status;
309 ZERO_STRUCTP(streams);
310 if (!(pvfs->flags & PVFS_FLAG_XATTR_ENABLE)) {
311 return NT_STATUS_OK;
313 status = pvfs_xattr_ndr_load(pvfs, streams, name->full_name, fd,
314 XATTR_DOSSTREAMS_NAME,
315 streams,
316 (ndr_pull_flags_fn_t)ndr_pull_xattr_DosStreams);
317 if (NT_STATUS_EQUAL(status, NT_STATUS_NOT_FOUND)) {
318 return NT_STATUS_OK;
320 return status;
324 save the set of streams into filesystem xattr
326 NTSTATUS pvfs_streams_save(struct pvfs_state *pvfs, struct pvfs_filename *name, int fd,
327 struct xattr_DosStreams *streams)
329 if (!(pvfs->flags & PVFS_FLAG_XATTR_ENABLE)) {
330 return NT_STATUS_OK;
332 return pvfs_xattr_ndr_save(pvfs, name->full_name, fd,
333 XATTR_DOSSTREAMS_NAME,
334 streams,
335 (ndr_push_flags_fn_t)ndr_push_xattr_DosStreams);
340 load the current ACL from extended attributes
342 NTSTATUS pvfs_acl_load(struct pvfs_state *pvfs, struct pvfs_filename *name, int fd,
343 struct xattr_NTACL *acl)
345 NTSTATUS status;
346 ZERO_STRUCTP(acl);
347 if (!(pvfs->flags & PVFS_FLAG_XATTR_ENABLE)) {
348 return NT_STATUS_NOT_FOUND;
350 status = pvfs_xattr_ndr_load(pvfs, acl, name->full_name, fd,
351 XATTR_NTACL_NAME,
352 acl,
353 (ndr_pull_flags_fn_t)ndr_pull_xattr_NTACL);
354 return status;
358 save the acl for a file into filesystem xattr
360 NTSTATUS pvfs_acl_save(struct pvfs_state *pvfs, struct pvfs_filename *name, int fd,
361 struct xattr_NTACL *acl)
363 NTSTATUS status;
364 void *privs;
366 if (!(pvfs->flags & PVFS_FLAG_XATTR_ENABLE)) {
367 return NT_STATUS_OK;
370 /* this xattr is in the "system" namespace, so we need
371 admin privileges to set it */
372 privs = root_privileges();
373 status = pvfs_xattr_ndr_save(pvfs, name->full_name, fd,
374 XATTR_NTACL_NAME,
375 acl,
376 (ndr_push_flags_fn_t)ndr_push_xattr_NTACL);
377 talloc_free(privs);
378 return status;
382 create a zero length xattr with the given name
384 NTSTATUS pvfs_xattr_create(struct pvfs_state *pvfs,
385 const char *fname, int fd,
386 const char *attr_prefix,
387 const char *attr_name)
389 NTSTATUS status;
390 DATA_BLOB blob = data_blob(NULL, 0);
391 char *aname = talloc_asprintf(NULL, "%s%s", attr_prefix, attr_name);
392 if (aname == NULL) {
393 return NT_STATUS_NO_MEMORY;
395 status = push_xattr_blob(pvfs, aname, fname, fd, &blob);
396 talloc_free(aname);
397 return status;
402 delete a xattr with the given name
404 NTSTATUS pvfs_xattr_delete(struct pvfs_state *pvfs,
405 const char *fname, int fd,
406 const char *attr_prefix,
407 const char *attr_name)
409 NTSTATUS status;
410 char *aname = talloc_asprintf(NULL, "%s%s", attr_prefix, attr_name);
411 if (aname == NULL) {
412 return NT_STATUS_NO_MEMORY;
414 status = delete_xattr(pvfs, aname, fname, fd);
415 talloc_free(aname);
416 return status;
420 load a xattr with the given name
422 NTSTATUS pvfs_xattr_load(struct pvfs_state *pvfs,
423 TALLOC_CTX *mem_ctx,
424 const char *fname, int fd,
425 const char *attr_prefix,
426 const char *attr_name,
427 size_t estimated_size,
428 DATA_BLOB *blob)
430 NTSTATUS status;
431 char *aname = talloc_asprintf(mem_ctx, "%s%s", attr_prefix, attr_name);
432 if (aname == NULL) {
433 return NT_STATUS_NO_MEMORY;
435 status = pull_xattr_blob(pvfs, mem_ctx, aname, fname, fd, estimated_size, blob);
436 talloc_free(aname);
437 return status;
441 save a xattr with the given name
443 NTSTATUS pvfs_xattr_save(struct pvfs_state *pvfs,
444 const char *fname, int fd,
445 const char *attr_prefix,
446 const char *attr_name,
447 const DATA_BLOB *blob)
449 NTSTATUS status;
450 char *aname = talloc_asprintf(NULL, "%s%s", attr_prefix, attr_name);
451 if (aname == NULL) {
452 return NT_STATUS_NO_MEMORY;
454 status = push_xattr_blob(pvfs, aname, fname, fd, blob);
455 talloc_free(aname);
456 return status;