2 Unix SMB/CIFS implementation.
4 POSIX NTVFS backend - xattr support using a tdb
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 3 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, see <http://www.gnu.org/licenses/>.
23 #include "lib/tdb_wrap/tdb_wrap.h"
24 #ifdef WITH_NTVFS_FILESERVER
25 #include "vfs_posix.h"
27 #include "posix_eadb.h"
29 #define XATTR_LIST_ATTR ".xattr_list"
32 we need to maintain a list of attributes on each file, so that unlink
33 can automatically clean them up
35 static NTSTATUS
posix_eadb_add_list(struct tdb_wrap
*ea_tdb
, TALLOC_CTX
*ctx
, const char *attr_name
,
36 const char *fname
, int fd
)
43 if (strcmp(attr_name
, XATTR_LIST_ATTR
) == 0) {
47 mem_ctx
= talloc_new(ctx
);
49 status
= pull_xattr_blob_tdb_raw(ea_tdb
, mem_ctx
, XATTR_LIST_ATTR
,
50 fname
, fd
, 100, &blob
);
51 if (NT_STATUS_IS_OK(status
)) {
54 for (s
= (const char *)blob
.data
;
55 s
< (const char *)(blob
.data
+ blob
.length
);
57 if (strcmp(attr_name
, s
) == 0) {
63 blob
= data_blob(NULL
, 0);
64 /* No need to parse an empty blob */
67 len
= strlen(attr_name
) + 1;
69 blob
.data
= talloc_realloc(mem_ctx
, blob
.data
, uint8_t, blob
.length
+ len
);
70 if (blob
.data
== NULL
) {
72 return NT_STATUS_NO_MEMORY
;
74 memcpy(blob
.data
+ blob
.length
, attr_name
, len
);
77 status
= push_xattr_blob_tdb_raw(ea_tdb
, XATTR_LIST_ATTR
, fname
, fd
, &blob
);
84 form a key for using in the ea_tdb
86 static NTSTATUS
get_ea_tdb_key(TALLOC_CTX
*mem_ctx
,
87 const char *attr_name
,
88 const char *fname
, int fd
,
92 size_t len
= strlen(attr_name
);
95 if (stat(fname
, &st
) == -1) {
96 return NT_STATUS_NOT_FOUND
;
99 if (fstat(fd
, &st
) == -1) {
100 return NT_STATUS_NOT_FOUND
;
104 key
->dptr
= talloc_array(mem_ctx
, uint8_t, 16 + len
);
105 if (key
->dptr
== NULL
) {
106 return NT_STATUS_NO_MEMORY
;
108 key
->dsize
= 16 + len
;
110 SBVAL(key
->dptr
, 0, st
.st_dev
);
111 SBVAL(key
->dptr
, 8, st
.st_ino
);
112 memcpy(key
->dptr
+16, attr_name
, len
);
120 pull a xattr as a blob, using the ea_tdb_context tdb
122 NTSTATUS
pull_xattr_blob_tdb_raw(struct tdb_wrap
*ea_tdb
,
124 const char *attr_name
,
127 size_t estimated_size
,
130 TDB_DATA tkey
, tdata
;
133 status
= get_ea_tdb_key(mem_ctx
, attr_name
, fname
, fd
, &tkey
);
134 if (!NT_STATUS_IS_OK(status
)) {
138 tdata
= tdb_fetch(ea_tdb
->tdb
, tkey
);
139 if (tdata
.dptr
== NULL
) {
140 return NT_STATUS_NOT_FOUND
;
143 *blob
= data_blob_talloc(mem_ctx
, tdata
.dptr
, tdata
.dsize
);
145 if (blob
->data
== NULL
) {
146 return NT_STATUS_NO_MEMORY
;
153 push a xattr as a blob, using ea_tdb
155 NTSTATUS
push_xattr_blob_tdb_raw(struct tdb_wrap
*ea_tdb
,
156 const char *attr_name
,
159 const DATA_BLOB
*blob
)
161 TDB_DATA tkey
, tdata
;
163 TALLOC_CTX
*mem_ctx
= talloc_new(ea_tdb
);
165 return NT_STATUS_NO_MEMORY
;
168 status
= get_ea_tdb_key(mem_ctx
, attr_name
, fname
, fd
, &tkey
);
169 if (!NT_STATUS_IS_OK(status
)) {
170 talloc_free(mem_ctx
);
174 tdata
.dptr
= blob
->data
;
175 tdata
.dsize
= blob
->length
;
177 if (tdb_chainlock(ea_tdb
->tdb
, tkey
) != 0) {
178 talloc_free(mem_ctx
);
179 return NT_STATUS_INTERNAL_DB_CORRUPTION
;
182 status
= posix_eadb_add_list(ea_tdb
,mem_ctx
, attr_name
, fname
, fd
);
183 if (!NT_STATUS_IS_OK(status
)) {
184 talloc_free(mem_ctx
);
188 if (tdb_store(ea_tdb
->tdb
, tkey
, tdata
, TDB_REPLACE
) != 0) {
189 status
= NT_STATUS_INTERNAL_DB_CORRUPTION
;
193 tdb_chainunlock(ea_tdb
->tdb
, tkey
);
194 talloc_free(mem_ctx
);
202 NTSTATUS
delete_posix_eadb_raw(struct tdb_wrap
*ea_tdb
, const char *attr_name
,
203 const char *fname
, int fd
)
208 status
= get_ea_tdb_key(NULL
, attr_name
, fname
, fd
, &tkey
);
209 if (!NT_STATUS_IS_OK(status
)) {
213 if (tdb_delete(ea_tdb
->tdb
, tkey
) != 0) {
214 talloc_free(tkey
.dptr
);
215 return NT_STATUS_INTERNAL_DB_CORRUPTION
;
218 talloc_free(tkey
.dptr
);
224 delete all xattrs for a file
226 NTSTATUS
unlink_posix_eadb_raw(struct tdb_wrap
*ea_tdb
, const char *fname
, int fd
)
228 TALLOC_CTX
*mem_ctx
= talloc_new(ea_tdb
);
233 status
= pull_xattr_blob_tdb_raw(ea_tdb
, mem_ctx
, XATTR_LIST_ATTR
,
234 fname
, fd
, 100, &blob
);
235 if (!NT_STATUS_IS_OK(status
)) {
236 talloc_free(mem_ctx
);
240 for (s
=(const char *)blob
.data
; s
< (const char *)(blob
.data
+blob
.length
); s
+= strlen(s
) + 1) {
241 delete_posix_eadb_raw(ea_tdb
, s
, fname
, -1);
244 status
= delete_posix_eadb_raw(ea_tdb
, XATTR_LIST_ATTR
, fname
, fd
);
245 talloc_free(mem_ctx
);
250 list all xattrs for a file
252 NTSTATUS
list_posix_eadb_raw(struct tdb_wrap
*ea_tdb
, TALLOC_CTX
*mem_ctx
,
253 const char *fname
, int fd
,
256 return pull_xattr_blob_tdb_raw(ea_tdb
, mem_ctx
, XATTR_LIST_ATTR
,
257 fname
, fd
, 100, list
);
260 #ifdef WITH_NTVFS_FILESERVER
261 NTSTATUS
pull_xattr_blob_tdb(struct pvfs_state
*pvfs_state
,
263 const char *attr_name
,
266 size_t estimated_size
,
269 return pull_xattr_blob_tdb_raw(pvfs_state
->ea_db
,mem_ctx
,attr_name
,fname
,fd
,estimated_size
,blob
);
272 NTSTATUS
push_xattr_blob_tdb(struct pvfs_state
*pvfs_state
,
273 const char *attr_name
,
276 const DATA_BLOB
*blob
)
278 return push_xattr_blob_tdb_raw(pvfs_state
->ea_db
, attr_name
, fname
, fd
, blob
);
284 NTSTATUS
delete_posix_eadb(struct pvfs_state
*pvfs_state
, const char *attr_name
,
285 const char *fname
, int fd
)
287 return delete_posix_eadb_raw(pvfs_state
->ea_db
,
288 attr_name
, fname
, fd
);
292 delete all xattrs for a file
294 NTSTATUS
unlink_posix_eadb(struct pvfs_state
*pvfs_state
, const char *fname
)
296 return unlink_posix_eadb_raw(pvfs_state
->ea_db
, fname
, -1);