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 "vfs_posix.h"
24 #include "../tdb/include/tdb.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 pvfs_state
*pvfs
, const char *attr_name
,
34 const char *fname
, int fd
)
42 if (strcmp(attr_name
, XATTR_LIST_ATTR
) == 0) {
46 mem_ctx
= talloc_new(pvfs
);
48 status
= pull_xattr_blob_tdb(pvfs
, 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(pvfs
, XATTR_LIST_ATTR
, fname
, fd
, &blob
);
78 form a key for using in the ea_db
80 static NTSTATUS
get_ea_db_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
);
112 pull a xattr as a blob, using the ea_db tdb
114 NTSTATUS
pull_xattr_blob_tdb(struct pvfs_state
*pvfs
,
116 const char *attr_name
,
119 size_t estimated_size
,
122 TDB_DATA tkey
, tdata
;
125 status
= get_ea_db_key(mem_ctx
, attr_name
, fname
, fd
, &tkey
);
126 if (!NT_STATUS_IS_OK(status
)) {
130 tdata
= tdb_fetch(pvfs
->ea_db
->tdb
, tkey
);
131 if (tdata
.dptr
== NULL
) {
132 return NT_STATUS_NOT_FOUND
;
135 *blob
= data_blob_talloc(mem_ctx
, tdata
.dptr
, tdata
.dsize
);
137 if (blob
->data
== NULL
) {
138 return NT_STATUS_NO_MEMORY
;
145 push a xattr as a blob, using ea_db
147 NTSTATUS
push_xattr_blob_tdb(struct pvfs_state
*pvfs
,
148 const char *attr_name
,
151 const DATA_BLOB
*blob
)
153 TDB_DATA tkey
, tdata
;
156 status
= get_ea_db_key(pvfs
, attr_name
, fname
, fd
, &tkey
);
157 if (!NT_STATUS_IS_OK(status
)) {
161 tdata
.dptr
= blob
->data
;
162 tdata
.dsize
= blob
->length
;
164 if (tdb_chainlock(pvfs
->ea_db
->tdb
, tkey
) != 0) {
165 talloc_free(tkey
.dptr
);
166 return NT_STATUS_INTERNAL_DB_CORRUPTION
;
169 status
= xattr_tdb_add_list(pvfs
, attr_name
, fname
, fd
);
170 if (!NT_STATUS_IS_OK(status
)) {
174 if (tdb_store(pvfs
->ea_db
->tdb
, tkey
, tdata
, TDB_REPLACE
) == -1) {
175 status
= NT_STATUS_INTERNAL_DB_CORRUPTION
;
179 tdb_chainunlock(pvfs
->ea_db
->tdb
, tkey
);
180 talloc_free(tkey
.dptr
);
188 NTSTATUS
delete_xattr_tdb(struct pvfs_state
*pvfs
, const char *attr_name
,
189 const char *fname
, int fd
)
194 status
= get_ea_db_key(NULL
, attr_name
, fname
, fd
, &tkey
);
195 if (!NT_STATUS_IS_OK(status
)) {
199 if (tdb_delete(pvfs
->ea_db
->tdb
, tkey
) == -1) {
200 talloc_free(tkey
.dptr
);
201 return NT_STATUS_INTERNAL_DB_CORRUPTION
;
204 talloc_free(tkey
.dptr
);
211 delete all xattrs for a file
213 NTSTATUS
unlink_xattr_tdb(struct pvfs_state
*pvfs
, const char *fname
)
215 TALLOC_CTX
*mem_ctx
= talloc_new(pvfs
);
220 status
= pull_xattr_blob_tdb(pvfs
, mem_ctx
, XATTR_LIST_ATTR
,
221 fname
, -1, 100, &blob
);
222 if (!NT_STATUS_IS_OK(status
)) {
223 talloc_free(mem_ctx
);
227 for (s
=(const char *)blob
.data
; s
< (const char *)(blob
.data
+blob
.length
); s
+= strlen(s
) + 1) {
228 delete_xattr_tdb(pvfs
, s
, fname
, -1);
231 status
= delete_xattr_tdb(pvfs
, XATTR_LIST_ATTR
, fname
, -1);
232 talloc_free(mem_ctx
);