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 #include "tdb_compat.h"
25 #include "vfs_posix.h"
27 #define XATTR_LIST_ATTR ".xattr_list"
30 we need to maintain a list of attributes on each file, so that unlink
31 can automatically clean them up
33 static NTSTATUS
xattr_tdb_add_list(struct tdb_wrap
*ea_tdb
, TALLOC_CTX
*ctx
, const char *attr_name
,
34 const char *fname
, int fd
)
42 if (strcmp(attr_name
, XATTR_LIST_ATTR
) == 0) {
46 mem_ctx
= talloc_new(ctx
);
48 status
= pull_xattr_blob_tdb_raw(ea_tdb
, mem_ctx
, XATTR_LIST_ATTR
,
49 fname
, fd
, 100, &blob
);
50 if (!NT_STATUS_IS_OK(status
)) {
51 blob
= data_blob(NULL
, 0);
54 for (s
=(const char *)blob
.data
; s
< (const char *)(blob
.data
+blob
.length
); s
+= strlen(s
) + 1) {
55 if (strcmp(attr_name
, s
) == 0) {
61 len
= strlen(attr_name
) + 1;
63 blob
.data
= talloc_realloc(mem_ctx
, blob
.data
, uint8_t, blob
.length
+ len
);
64 if (blob
.data
== NULL
) {
66 return NT_STATUS_NO_MEMORY
;
68 memcpy(blob
.data
+ blob
.length
, attr_name
, len
);
71 status
= push_xattr_blob_tdb_raw(ea_tdb
,ctx
, XATTR_LIST_ATTR
, fname
, fd
, &blob
);
78 form a key for using in the ea_tdb
80 static NTSTATUS
get_ea_tdb_key(TALLOC_CTX
*mem_ctx
,
81 const char *attr_name
,
82 const char *fname
, int fd
,
86 size_t len
= strlen(attr_name
);
89 if (stat(fname
, &st
) == -1) {
90 return NT_STATUS_NOT_FOUND
;
93 if (fstat(fd
, &st
) == -1) {
94 return NT_STATUS_NOT_FOUND
;
98 key
->dptr
= talloc_array(mem_ctx
, uint8_t, 16 + len
);
99 if (key
->dptr
== NULL
) {
100 return NT_STATUS_NO_MEMORY
;
102 key
->dsize
= 16 + len
;
104 SBVAL(key
->dptr
, 0, st
.st_dev
);
105 SBVAL(key
->dptr
, 8, st
.st_ino
);
106 memcpy(key
->dptr
+16, attr_name
, len
);
114 pull a xattr as a blob, using the ea_tdb_context tdb
116 NTSTATUS
pull_xattr_blob_tdb_raw(struct tdb_wrap
*ea_tdb
,
118 const char *attr_name
,
121 size_t estimated_size
,
124 TDB_DATA tkey
, tdata
;
127 status
= get_ea_tdb_key(mem_ctx
, attr_name
, fname
, fd
, &tkey
);
128 if (!NT_STATUS_IS_OK(status
)) {
132 tdata
= tdb_fetch_compat(ea_tdb
->tdb
, tkey
);
133 if (tdata
.dptr
== NULL
) {
134 return NT_STATUS_NOT_FOUND
;
137 *blob
= data_blob_talloc(mem_ctx
, tdata
.dptr
, tdata
.dsize
);
139 if (blob
->data
== NULL
) {
140 return NT_STATUS_NO_MEMORY
;
146 NTSTATUS
pull_xattr_blob_tdb(struct pvfs_state
*pvfs
,
148 const char *attr_name
,
151 size_t estimated_size
,
154 return pull_xattr_blob_tdb_raw(pvfs
->ea_db
,mem_ctx
,attr_name
,fname
,fd
,estimated_size
,blob
);
158 push a xattr as a blob, using ea_tdb
160 NTSTATUS
push_xattr_blob_tdb_raw(struct tdb_wrap
*ea_tdb
,
162 const char *attr_name
,
165 const DATA_BLOB
*blob
)
167 TDB_DATA tkey
, tdata
;
170 status
= get_ea_tdb_key(mem_ctx
, attr_name
, fname
, fd
, &tkey
);
171 if (!NT_STATUS_IS_OK(status
)) {
175 tdata
.dptr
= blob
->data
;
176 tdata
.dsize
= blob
->length
;
178 if (tdb_chainlock(ea_tdb
->tdb
, tkey
) != 0) {
179 talloc_free(tkey
.dptr
);
180 return NT_STATUS_INTERNAL_DB_CORRUPTION
;
183 status
= xattr_tdb_add_list(ea_tdb
,mem_ctx
, attr_name
, fname
, fd
);
184 if (!NT_STATUS_IS_OK(status
)) {
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(tkey
.dptr
);
197 NTSTATUS
push_xattr_blob_tdb(struct pvfs_state
*pvfs
,
198 const char *attr_name
,
201 const DATA_BLOB
*blob
)
203 return push_xattr_blob_tdb_raw(pvfs
->ea_db
,pvfs
,attr_name
,fname
,fd
,blob
);
210 NTSTATUS
delete_xattr_tdb(struct pvfs_state
*pvfs
, const char *attr_name
,
211 const char *fname
, int fd
)
216 status
= get_ea_tdb_key(NULL
, attr_name
, fname
, fd
, &tkey
);
217 if (!NT_STATUS_IS_OK(status
)) {
221 if (tdb_delete(pvfs
->ea_db
->tdb
, tkey
) != 0) {
222 talloc_free(tkey
.dptr
);
223 return NT_STATUS_INTERNAL_DB_CORRUPTION
;
226 talloc_free(tkey
.dptr
);
233 delete all xattrs for a file
235 NTSTATUS
unlink_xattr_tdb(struct pvfs_state
*pvfs
, const char *fname
)
237 TALLOC_CTX
*mem_ctx
= talloc_new(pvfs
);
242 status
= pull_xattr_blob_tdb(pvfs
, mem_ctx
, XATTR_LIST_ATTR
,
243 fname
, -1, 100, &blob
);
244 if (!NT_STATUS_IS_OK(status
)) {
245 talloc_free(mem_ctx
);
249 for (s
=(const char *)blob
.data
; s
< (const char *)(blob
.data
+blob
.length
); s
+= strlen(s
) + 1) {
250 delete_xattr_tdb(pvfs
, s
, fname
, -1);
253 status
= delete_xattr_tdb(pvfs
, XATTR_LIST_ATTR
, fname
, -1);
254 talloc_free(mem_ctx
);