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"
26 #include "posix_eadb.h"
28 #define XATTR_LIST_ATTR ".xattr_list"
31 we need to maintain a list of attributes on each file, so that unlink
32 can automatically clean them up
34 static NTSTATUS
posix_eadb_add_list(struct tdb_wrap
*ea_tdb
, TALLOC_CTX
*ctx
, const char *attr_name
,
35 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
)) {
52 blob
= data_blob(NULL
, 0);
55 for (s
=(const char *)blob
.data
; s
< (const char *)(blob
.data
+blob
.length
); s
+= strlen(s
) + 1) {
56 if (strcmp(attr_name
, s
) == 0) {
62 len
= strlen(attr_name
) + 1;
64 blob
.data
= talloc_realloc(mem_ctx
, blob
.data
, uint8_t, blob
.length
+ len
);
65 if (blob
.data
== NULL
) {
67 return NT_STATUS_NO_MEMORY
;
69 memcpy(blob
.data
+ blob
.length
, attr_name
, len
);
72 status
= push_xattr_blob_tdb_raw(ea_tdb
, XATTR_LIST_ATTR
, fname
, fd
, &blob
);
79 form a key for using in the ea_tdb
81 static NTSTATUS
get_ea_tdb_key(TALLOC_CTX
*mem_ctx
,
82 const char *attr_name
,
83 const char *fname
, int fd
,
87 size_t len
= strlen(attr_name
);
90 if (stat(fname
, &st
) == -1) {
91 return NT_STATUS_NOT_FOUND
;
94 if (fstat(fd
, &st
) == -1) {
95 return NT_STATUS_NOT_FOUND
;
99 key
->dptr
= talloc_array(mem_ctx
, uint8_t, 16 + len
);
100 if (key
->dptr
== NULL
) {
101 return NT_STATUS_NO_MEMORY
;
103 key
->dsize
= 16 + len
;
105 SBVAL(key
->dptr
, 0, st
.st_dev
);
106 SBVAL(key
->dptr
, 8, st
.st_ino
);
107 memcpy(key
->dptr
+16, attr_name
, len
);
115 pull a xattr as a blob, using the ea_tdb_context tdb
117 NTSTATUS
pull_xattr_blob_tdb_raw(struct tdb_wrap
*ea_tdb
,
119 const char *attr_name
,
122 size_t estimated_size
,
125 TDB_DATA tkey
, tdata
;
128 status
= get_ea_tdb_key(mem_ctx
, attr_name
, fname
, fd
, &tkey
);
129 if (!NT_STATUS_IS_OK(status
)) {
133 tdata
= tdb_fetch_compat(ea_tdb
->tdb
, tkey
);
134 if (tdata
.dptr
== NULL
) {
135 return NT_STATUS_NOT_FOUND
;
138 *blob
= data_blob_talloc(mem_ctx
, tdata
.dptr
, tdata
.dsize
);
140 if (blob
->data
== NULL
) {
141 return NT_STATUS_NO_MEMORY
;
147 NTSTATUS
pull_xattr_blob_tdb(struct pvfs_state
*pvfs_state
,
149 const char *attr_name
,
152 size_t estimated_size
,
155 return pull_xattr_blob_tdb_raw(pvfs_state
->ea_db
,mem_ctx
,attr_name
,fname
,fd
,estimated_size
,blob
);
159 push a xattr as a blob, using ea_tdb
161 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
;
169 TALLOC_CTX
*mem_ctx
= talloc_new(ea_tdb
);
171 return NT_STATUS_NO_MEMORY
;
174 status
= get_ea_tdb_key(mem_ctx
, attr_name
, fname
, fd
, &tkey
);
175 if (!NT_STATUS_IS_OK(status
)) {
176 talloc_free(mem_ctx
);
180 tdata
.dptr
= blob
->data
;
181 tdata
.dsize
= blob
->length
;
183 if (tdb_chainlock(ea_tdb
->tdb
, tkey
) != 0) {
184 talloc_free(mem_ctx
);
185 return NT_STATUS_INTERNAL_DB_CORRUPTION
;
188 status
= posix_eadb_add_list(ea_tdb
,mem_ctx
, attr_name
, fname
, fd
);
189 if (!NT_STATUS_IS_OK(status
)) {
190 talloc_free(mem_ctx
);
194 if (tdb_store(ea_tdb
->tdb
, tkey
, tdata
, TDB_REPLACE
) != 0) {
195 status
= NT_STATUS_INTERNAL_DB_CORRUPTION
;
199 tdb_chainunlock(ea_tdb
->tdb
, tkey
);
200 talloc_free(mem_ctx
);
203 NTSTATUS
push_xattr_blob_tdb(struct pvfs_state
*pvfs_state
,
204 const char *attr_name
,
207 const DATA_BLOB
*blob
)
209 return push_xattr_blob_tdb_raw(pvfs_state
->ea_db
, attr_name
, fname
, fd
, blob
);
216 NTSTATUS
delete_posix_eadb_raw(struct tdb_wrap
*ea_tdb
, const char *attr_name
,
217 const char *fname
, int fd
)
222 status
= get_ea_tdb_key(NULL
, attr_name
, fname
, fd
, &tkey
);
223 if (!NT_STATUS_IS_OK(status
)) {
227 if (tdb_delete(ea_tdb
->tdb
, tkey
) != 0) {
228 talloc_free(tkey
.dptr
);
229 return NT_STATUS_INTERNAL_DB_CORRUPTION
;
232 talloc_free(tkey
.dptr
);
240 NTSTATUS
delete_posix_eadb(struct pvfs_state
*pvfs_state
, const char *attr_name
,
241 const char *fname
, int fd
)
243 return delete_posix_eadb_raw(pvfs_state
->ea_db
,
244 attr_name
, fname
, fd
);
249 delete all xattrs for a file
251 NTSTATUS
unlink_posix_eadb_raw(struct tdb_wrap
*ea_tdb
, const char *fname
, int fd
)
253 TALLOC_CTX
*mem_ctx
= talloc_new(ea_tdb
);
258 status
= pull_xattr_blob_tdb_raw(ea_tdb
, mem_ctx
, XATTR_LIST_ATTR
,
259 fname
, fd
, 100, &blob
);
260 if (!NT_STATUS_IS_OK(status
)) {
261 talloc_free(mem_ctx
);
265 for (s
=(const char *)blob
.data
; s
< (const char *)(blob
.data
+blob
.length
); s
+= strlen(s
) + 1) {
266 delete_posix_eadb_raw(ea_tdb
, s
, fname
, -1);
269 status
= delete_posix_eadb_raw(ea_tdb
, XATTR_LIST_ATTR
, fname
, fd
);
270 talloc_free(mem_ctx
);
275 delete all xattrs for a file
277 NTSTATUS
unlink_posix_eadb(struct pvfs_state
*pvfs_state
, const char *fname
)
279 return unlink_posix_eadb_raw(pvfs_state
->ea_db
, fname
, -1);
283 list all xattrs for a file
285 NTSTATUS
list_posix_eadb_raw(struct tdb_wrap
*ea_tdb
, TALLOC_CTX
*mem_ctx
,
286 const char *fname
, int fd
,
289 return pull_xattr_blob_tdb_raw(ea_tdb
, mem_ctx
, XATTR_LIST_ATTR
,
290 fname
, fd
, 100, list
);