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.
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
,
32 const char *attr_name
,
35 size_t estimated_size
,
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
;
59 push a xattr as a blob
61 static NTSTATUS
push_xattr_blob(struct pvfs_state
*pvfs
,
62 const char *attr_name
,
65 const DATA_BLOB
*blob
)
68 return push_xattr_blob_tdb(pvfs
, attr_name
, fname
, fd
, blob
);
70 return push_xattr_blob_system(pvfs
, attr_name
, fname
, fd
, blob
);
77 static NTSTATUS
delete_xattr(struct pvfs_state
*pvfs
, const char *attr_name
,
78 const char *fname
, int fd
)
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
)
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
,
103 const char *fname
, int fd
, const char *attr_name
,
104 void *p
, ndr_pull_flags_fn_t pull_fn
)
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
)) {
116 status
= ndr_pull_struct_blob(&blob
, mem_ctx
, p
, pull_fn
);
118 data_blob_free(&blob
);
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
);
134 status
= ndr_push_struct_blob(&blob
, mem_ctx
, p
, push_fn
);
135 if (!NT_STATUS_IS_OK(status
)) {
136 talloc_free(mem_ctx
);
140 status
= push_xattr_blob(pvfs
, attr_name
, fname
, fd
, &blob
);
141 talloc_free(mem_ctx
);
148 fill in file attributes from extended attributes
150 NTSTATUS
pvfs_dosattrib_load(struct pvfs_state
*pvfs
, struct pvfs_filename
*name
, int fd
)
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
;
161 name
->stream_exists
= True
;
164 if (!(pvfs
->flags
& PVFS_FLAG_XATTR_ENABLE
)) {
168 status
= pvfs_xattr_ndr_load(pvfs
, mem_ctx
, name
->full_name
,
169 fd
, XATTR_DOSATTRIB_NAME
,
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
);
184 switch (attrib
.version
) {
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
;
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
;
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
);
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
)) {
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
;
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
)
277 if (!(pvfs
->flags
& PVFS_FLAG_XATTR_ENABLE
)) {
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
)) {
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
)) {
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
)
309 ZERO_STRUCTP(streams
);
310 if (!(pvfs
->flags
& PVFS_FLAG_XATTR_ENABLE
)) {
313 status
= pvfs_xattr_ndr_load(pvfs
, streams
, name
->full_name
, fd
,
314 XATTR_DOSSTREAMS_NAME
,
316 (ndr_pull_flags_fn_t
)ndr_pull_xattr_DosStreams
);
317 if (NT_STATUS_EQUAL(status
, NT_STATUS_NOT_FOUND
)) {
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
)) {
332 return pvfs_xattr_ndr_save(pvfs
, name
->full_name
, fd
,
333 XATTR_DOSSTREAMS_NAME
,
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
)
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
,
353 (ndr_pull_flags_fn_t
)ndr_pull_xattr_NTACL
);
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
)
366 if (!(pvfs
->flags
& PVFS_FLAG_XATTR_ENABLE
)) {
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
,
376 (ndr_push_flags_fn_t
)ndr_push_xattr_NTACL
);
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
)
390 DATA_BLOB blob
= data_blob(NULL
, 0);
391 char *aname
= talloc_asprintf(NULL
, "%s%s", attr_prefix
, attr_name
);
393 return NT_STATUS_NO_MEMORY
;
395 status
= push_xattr_blob(pvfs
, aname
, fname
, fd
, &blob
);
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
)
410 char *aname
= talloc_asprintf(NULL
, "%s%s", attr_prefix
, attr_name
);
412 return NT_STATUS_NO_MEMORY
;
414 status
= delete_xattr(pvfs
, aname
, fname
, fd
);
420 load a xattr with the given name
422 NTSTATUS
pvfs_xattr_load(struct pvfs_state
*pvfs
,
424 const char *fname
, int fd
,
425 const char *attr_prefix
,
426 const char *attr_name
,
427 size_t estimated_size
,
431 char *aname
= talloc_asprintf(mem_ctx
, "%s%s", attr_prefix
, attr_name
);
433 return NT_STATUS_NO_MEMORY
;
435 status
= pull_xattr_blob(pvfs
, mem_ctx
, aname
, fname
, fd
, estimated_size
, blob
);
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
)
450 char *aname
= talloc_asprintf(NULL
, "%s%s", attr_prefix
, attr_name
);
452 return NT_STATUS_NO_MEMORY
;
454 status
= push_xattr_blob(pvfs
, aname
, fname
, fd
, blob
);