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 "vfs_posix.h"
25 #include "posix_eadb.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
posix_eadb_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
, 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(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_state
,
148 const char *attr_name
,
151 size_t estimated_size
,
154 return pull_xattr_blob_tdb_raw(pvfs_state
->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
,
161 const char *attr_name
,
164 const DATA_BLOB
*blob
)
166 TDB_DATA tkey
, tdata
;
168 TALLOC_CTX
*mem_ctx
= talloc_new(ea_tdb
);
170 return NT_STATUS_NO_MEMORY
;
173 status
= get_ea_tdb_key(mem_ctx
, attr_name
, fname
, fd
, &tkey
);
174 if (!NT_STATUS_IS_OK(status
)) {
175 talloc_free(mem_ctx
);
179 tdata
.dptr
= blob
->data
;
180 tdata
.dsize
= blob
->length
;
182 if (tdb_chainlock(ea_tdb
->tdb
, tkey
) != 0) {
183 talloc_free(mem_ctx
);
184 return NT_STATUS_INTERNAL_DB_CORRUPTION
;
187 status
= posix_eadb_add_list(ea_tdb
,mem_ctx
, attr_name
, fname
, fd
);
188 if (!NT_STATUS_IS_OK(status
)) {
189 talloc_free(mem_ctx
);
193 if (tdb_store(ea_tdb
->tdb
, tkey
, tdata
, TDB_REPLACE
) != 0) {
194 status
= NT_STATUS_INTERNAL_DB_CORRUPTION
;
198 tdb_chainunlock(ea_tdb
->tdb
, tkey
);
199 talloc_free(mem_ctx
);
202 NTSTATUS
push_xattr_blob_tdb(struct pvfs_state
*pvfs_state
,
203 const char *attr_name
,
206 const DATA_BLOB
*blob
)
208 return push_xattr_blob_tdb_raw(pvfs_state
->ea_db
, attr_name
, fname
, fd
, blob
);
215 NTSTATUS
delete_posix_eadb_raw(struct tdb_wrap
*ea_tdb
, const char *attr_name
,
216 const char *fname
, int fd
)
221 status
= get_ea_tdb_key(NULL
, attr_name
, fname
, fd
, &tkey
);
222 if (!NT_STATUS_IS_OK(status
)) {
226 if (tdb_delete(ea_tdb
->tdb
, tkey
) != 0) {
227 talloc_free(tkey
.dptr
);
228 return NT_STATUS_INTERNAL_DB_CORRUPTION
;
231 talloc_free(tkey
.dptr
);
239 NTSTATUS
delete_posix_eadb(struct pvfs_state
*pvfs_state
, const char *attr_name
,
240 const char *fname
, int fd
)
242 return delete_posix_eadb_raw(pvfs_state
->ea_db
,
243 attr_name
, fname
, fd
);
248 delete all xattrs for a file
250 NTSTATUS
unlink_posix_eadb_raw(struct tdb_wrap
*ea_tdb
, const char *fname
, int fd
)
252 TALLOC_CTX
*mem_ctx
= talloc_new(ea_tdb
);
257 status
= pull_xattr_blob_tdb_raw(ea_tdb
, mem_ctx
, XATTR_LIST_ATTR
,
258 fname
, fd
, 100, &blob
);
259 if (!NT_STATUS_IS_OK(status
)) {
260 talloc_free(mem_ctx
);
264 for (s
=(const char *)blob
.data
; s
< (const char *)(blob
.data
+blob
.length
); s
+= strlen(s
) + 1) {
265 delete_posix_eadb_raw(ea_tdb
, s
, fname
, -1);
268 status
= delete_posix_eadb_raw(ea_tdb
, XATTR_LIST_ATTR
, fname
, fd
);
269 talloc_free(mem_ctx
);
274 delete all xattrs for a file
276 NTSTATUS
unlink_posix_eadb(struct pvfs_state
*pvfs_state
, const char *fname
)
278 return unlink_posix_eadb_raw(pvfs_state
->ea_db
, fname
, -1);
282 list all xattrs for a file
284 NTSTATUS
list_posix_eadb_raw(struct tdb_wrap
*ea_tdb
, TALLOC_CTX
*mem_ctx
,
285 const char *fname
, int fd
,
288 return pull_xattr_blob_tdb_raw(ea_tdb
, mem_ctx
, XATTR_LIST_ATTR
,
289 fname
, fd
, 100, list
);