2 * Store posix-level xattrs in a tdb
4 * Copyright (C) Volker Lendecke, 2007
5 * Copyright (C) Andrew Bartlett, 2012
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 3 of the License, or
10 * (at your option) any later version.
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, see <http://www.gnu.org/licenses/>.
22 #include "system/filesys.h"
23 #include "smbd/smbd.h"
24 #include "dbwrap/dbwrap.h"
25 #include "dbwrap/dbwrap_open.h"
26 #include "source3/lib/xattr_tdb.h"
29 #define DBGC_CLASS DBGC_VFS
31 static bool xattr_tdb_init(int snum
, TALLOC_CTX
*mem_ctx
, struct db_context
**p_db
);
33 static int xattr_tdb_get_file_id(struct vfs_handle_struct
*handle
,
34 const char *path
, struct file_id
*id
)
37 TALLOC_CTX
*frame
= talloc_stackframe();
38 struct smb_filename
*smb_fname
;
40 smb_fname
= synthetic_smb_fname(frame
, path
, NULL
, NULL
, 0);
41 if (smb_fname
== NULL
) {
47 ret
= SMB_VFS_NEXT_STAT(handle
, smb_fname
);
54 *id
= SMB_VFS_NEXT_FILE_ID_CREATE(handle
, &smb_fname
->st
);
59 static ssize_t
xattr_tdb_getxattr(struct vfs_handle_struct
*handle
,
60 const struct smb_filename
*smb_fname
,
66 struct db_context
*db
;
70 TALLOC_CTX
*frame
= talloc_stackframe();
72 SMB_VFS_HANDLE_GET_DATA(handle
, db
, struct db_context
,
73 if (!xattr_tdb_init(-1, frame
, &db
))
75 TALLOC_FREE(frame
); return -1;
78 ret
= xattr_tdb_get_file_id(handle
, smb_fname
->base_name
, &id
);
84 xattr_size
= xattr_tdb_getattr(db
, frame
, &id
, name
, &blob
);
96 if (blob
.length
> size
) {
101 memcpy(value
, blob
.data
, xattr_size
);
106 static ssize_t
xattr_tdb_fgetxattr(struct vfs_handle_struct
*handle
,
107 struct files_struct
*fsp
,
108 const char *name
, void *value
, size_t size
)
110 SMB_STRUCT_STAT sbuf
;
112 struct db_context
*db
;
115 TALLOC_CTX
*frame
= talloc_stackframe();
117 SMB_VFS_HANDLE_GET_DATA(handle
, db
, struct db_context
,
118 if (!xattr_tdb_init(-1, frame
, &db
))
120 TALLOC_FREE(frame
); return -1;
123 if (SMB_VFS_NEXT_FSTAT(handle
, fsp
, &sbuf
) == -1) {
128 id
= SMB_VFS_NEXT_FILE_ID_CREATE(handle
, &sbuf
);
130 xattr_size
= xattr_tdb_getattr(db
, frame
, &id
, name
, &blob
);
131 if (xattr_size
< 0) {
142 if (blob
.length
> size
) {
147 memcpy(value
, blob
.data
, xattr_size
);
152 static int xattr_tdb_setxattr(struct vfs_handle_struct
*handle
,
153 const struct smb_filename
*smb_fname
,
160 struct db_context
*db
;
162 TALLOC_CTX
*frame
= talloc_stackframe();
164 SMB_VFS_HANDLE_GET_DATA(handle
, db
, struct db_context
,
165 if (!xattr_tdb_init(-1, frame
, &db
))
167 TALLOC_FREE(frame
); return -1;
170 ret
= xattr_tdb_get_file_id(handle
, smb_fname
->base_name
, &id
);
176 ret
= xattr_tdb_setattr(db
, &id
, name
, value
, size
, flags
);
181 static int xattr_tdb_fsetxattr(struct vfs_handle_struct
*handle
,
182 struct files_struct
*fsp
,
183 const char *name
, const void *value
,
184 size_t size
, int flags
)
186 SMB_STRUCT_STAT sbuf
;
188 struct db_context
*db
;
190 TALLOC_CTX
*frame
= talloc_stackframe();
192 SMB_VFS_HANDLE_GET_DATA(handle
, db
, struct db_context
,
193 if (!xattr_tdb_init(-1, frame
, &db
))
195 TALLOC_FREE(frame
); return -1;
198 if (SMB_VFS_NEXT_FSTAT(handle
, fsp
, &sbuf
) == -1) {
203 id
= SMB_VFS_NEXT_FILE_ID_CREATE(handle
, &sbuf
);
205 ret
= xattr_tdb_setattr(db
, &id
, name
, value
, size
, flags
);
211 static ssize_t
xattr_tdb_listxattr(struct vfs_handle_struct
*handle
,
212 const struct smb_filename
*smb_fname
,
217 struct db_context
*db
;
219 TALLOC_CTX
*frame
= talloc_stackframe();
221 SMB_VFS_HANDLE_GET_DATA(handle
, db
, struct db_context
,
222 if (!xattr_tdb_init(-1, frame
, &db
))
224 TALLOC_FREE(frame
); return -1;
227 ret
= xattr_tdb_get_file_id(handle
, smb_fname
->base_name
, &id
);
233 ret
= xattr_tdb_listattr(db
, &id
, list
, size
);
239 static ssize_t
xattr_tdb_flistxattr(struct vfs_handle_struct
*handle
,
240 struct files_struct
*fsp
, char *list
,
243 SMB_STRUCT_STAT sbuf
;
245 struct db_context
*db
;
247 TALLOC_CTX
*frame
= talloc_stackframe();
249 SMB_VFS_HANDLE_GET_DATA(handle
, db
, struct db_context
,
250 if (!xattr_tdb_init(-1, frame
, &db
))
252 TALLOC_FREE(frame
); return -1;
255 if (SMB_VFS_NEXT_FSTAT(handle
, fsp
, &sbuf
) == -1) {
260 id
= SMB_VFS_NEXT_FILE_ID_CREATE(handle
, &sbuf
);
262 ret
= xattr_tdb_listattr(db
, &id
, list
, size
);
267 static int xattr_tdb_removexattr(struct vfs_handle_struct
*handle
,
268 const struct smb_filename
*smb_fname
,
272 struct db_context
*db
;
274 TALLOC_CTX
*frame
= talloc_stackframe();
276 SMB_VFS_HANDLE_GET_DATA(handle
, db
, struct db_context
,
277 if (!xattr_tdb_init(-1, frame
, &db
))
279 TALLOC_FREE(frame
); return -1;
282 ret
= xattr_tdb_get_file_id(handle
, smb_fname
->base_name
, &id
);
289 ret
= xattr_tdb_removeattr(db
, &id
, name
);
294 static int xattr_tdb_fremovexattr(struct vfs_handle_struct
*handle
,
295 struct files_struct
*fsp
, const char *name
)
297 SMB_STRUCT_STAT sbuf
;
299 struct db_context
*db
;
301 TALLOC_CTX
*frame
= talloc_stackframe();
303 SMB_VFS_HANDLE_GET_DATA(handle
, db
, struct db_context
,
304 if (!xattr_tdb_init(-1, frame
, &db
))
306 TALLOC_FREE(frame
); return -1;
309 if (SMB_VFS_NEXT_FSTAT(handle
, fsp
, &sbuf
) == -1) {
314 id
= SMB_VFS_NEXT_FILE_ID_CREATE(handle
, &sbuf
);
316 ret
= xattr_tdb_removeattr(db
, &id
, name
);
322 * Open the tdb file upon VFS_CONNECT
325 static bool xattr_tdb_init(int snum
, TALLOC_CTX
*mem_ctx
, struct db_context
**p_db
)
327 struct db_context
*db
;
331 def_dbname
= state_path("xattr.tdb");
332 if (def_dbname
== NULL
) {
337 dbname
= lp_parm_const_string(snum
, "xattr_tdb", "file", def_dbname
);
339 /* now we know dbname is not NULL */
342 db
= db_open(NULL
, dbname
, 0, TDB_DEFAULT
, O_RDWR
|O_CREAT
, 0600,
343 DBWRAP_LOCK_ORDER_2
, DBWRAP_FLAG_NONE
);
352 TALLOC_FREE(def_dbname
);
357 TALLOC_FREE(def_dbname
);
361 static int xattr_tdb_open(vfs_handle_struct
*handle
,
362 struct smb_filename
*smb_fname
,
367 struct db_context
*db
= NULL
;
368 TALLOC_CTX
*frame
= NULL
;
371 fsp
->fh
->fd
= SMB_VFS_NEXT_OPEN(handle
,
376 if (fsp
->fh
->fd
< 0) {
380 if ((flags
& (O_CREAT
|O_EXCL
)) != (O_CREAT
|O_EXCL
)) {
385 * We know we used O_CREAT|O_EXCL and it worked.
386 * We must have created the file.
389 ret
= SMB_VFS_FSTAT(fsp
, &smb_fname
->st
);
391 /* Can't happen... */
392 DBG_WARNING("SMB_VFS_FSTAT failed on file %s (%s)\n",
393 smb_fname_str_dbg(smb_fname
),
397 fsp
->file_id
= SMB_VFS_FILE_ID_CREATE(fsp
->conn
, &smb_fname
->st
);
399 frame
= talloc_stackframe();
400 SMB_VFS_HANDLE_GET_DATA(handle
, db
, struct db_context
,
401 if (!xattr_tdb_init(-1, frame
, &db
))
403 TALLOC_FREE(frame
); return -1;
406 xattr_tdb_remove_all_attrs(db
, &fsp
->file_id
);
411 static int xattr_tdb_mkdir(vfs_handle_struct
*handle
,
412 const struct smb_filename
*smb_fname
,
415 struct db_context
*db
= NULL
;
416 TALLOC_CTX
*frame
= NULL
;
417 struct file_id fileid
;
419 struct smb_filename
*smb_fname_tmp
= NULL
;
421 ret
= SMB_VFS_NEXT_MKDIR(handle
, smb_fname
, mode
);
426 frame
= talloc_stackframe();
427 smb_fname_tmp
= cp_smb_filename(frame
, smb_fname
);
428 if (smb_fname_tmp
== NULL
) {
434 /* Always use LSTAT here - we just creaded the directory. */
435 ret
= SMB_VFS_LSTAT(handle
->conn
, smb_fname_tmp
);
437 /* Rename race. Let upper level take care of it. */
441 if (!S_ISDIR(smb_fname_tmp
->st
.st_ex_mode
)) {
442 /* Rename race. Let upper level take care of it. */
447 fileid
= SMB_VFS_FILE_ID_CREATE(handle
->conn
, &smb_fname_tmp
->st
);
449 SMB_VFS_HANDLE_GET_DATA(handle
, db
, struct db_context
,
450 if (!xattr_tdb_init(-1, frame
, &db
))
452 TALLOC_FREE(frame
); return -1;
455 xattr_tdb_remove_all_attrs(db
, &fileid
);
461 * On unlink we need to delete the tdb record
463 static int xattr_tdb_unlink(vfs_handle_struct
*handle
,
464 const struct smb_filename
*smb_fname
)
466 struct smb_filename
*smb_fname_tmp
= NULL
;
468 struct db_context
*db
;
470 bool remove_record
= false;
471 TALLOC_CTX
*frame
= talloc_stackframe();
473 SMB_VFS_HANDLE_GET_DATA(handle
, db
, struct db_context
,
474 if (!xattr_tdb_init(-1, frame
, &db
))
476 TALLOC_FREE(frame
); return -1;
479 smb_fname_tmp
= cp_smb_filename(frame
, smb_fname
);
480 if (smb_fname_tmp
== NULL
) {
486 if (smb_fname_tmp
->flags
& SMB_FILENAME_POSIX_PATH
) {
487 ret
= SMB_VFS_NEXT_LSTAT(handle
, smb_fname_tmp
);
489 ret
= SMB_VFS_NEXT_STAT(handle
, smb_fname_tmp
);
495 if (smb_fname_tmp
->st
.st_ex_nlink
== 1) {
496 /* Only remove record on last link to file. */
497 remove_record
= true;
500 ret
= SMB_VFS_NEXT_UNLINK(handle
, smb_fname_tmp
);
506 if (!remove_record
) {
510 id
= SMB_VFS_NEXT_FILE_ID_CREATE(handle
, &smb_fname_tmp
->st
);
512 xattr_tdb_remove_all_attrs(db
, &id
);
520 * On rmdir we need to delete the tdb record
522 static int xattr_tdb_rmdir(vfs_handle_struct
*handle
,
523 const struct smb_filename
*smb_fname
)
525 SMB_STRUCT_STAT sbuf
;
527 struct db_context
*db
;
529 TALLOC_CTX
*frame
= talloc_stackframe();
531 SMB_VFS_HANDLE_GET_DATA(handle
, db
, struct db_context
,
532 if (!xattr_tdb_init(-1, frame
, &db
))
534 TALLOC_FREE(frame
); return -1;
537 if (vfs_stat_smb_basename(handle
->conn
,
544 ret
= SMB_VFS_NEXT_RMDIR(handle
, smb_fname
);
551 id
= SMB_VFS_NEXT_FILE_ID_CREATE(handle
, &sbuf
);
553 xattr_tdb_remove_all_attrs(db
, &id
);
560 * Destructor for the VFS private data
563 static void close_xattr_db(void **data
)
565 struct db_context
**p_db
= (struct db_context
**)data
;
569 static int xattr_tdb_connect(vfs_handle_struct
*handle
, const char *service
,
574 struct db_context
*db
;
576 res
= SMB_VFS_NEXT_CONNECT(handle
, service
, user
);
581 snum
= find_service(talloc_tos(), service
, &sname
);
582 if (snum
== -1 || sname
== NULL
) {
584 * Should not happen, but we should not fail just *here*.
589 if (!xattr_tdb_init(snum
, NULL
, &db
)) {
590 DEBUG(5, ("Could not init xattr tdb\n"));
591 lp_do_parameter(snum
, "ea support", "False");
595 lp_do_parameter(snum
, "ea support", "True");
597 SMB_VFS_HANDLE_SET_DATA(handle
, db
, close_xattr_db
,
598 struct db_context
, return -1);
603 static struct vfs_fn_pointers vfs_xattr_tdb_fns
= {
604 .getxattr_fn
= xattr_tdb_getxattr
,
605 .fgetxattr_fn
= xattr_tdb_fgetxattr
,
606 .setxattr_fn
= xattr_tdb_setxattr
,
607 .fsetxattr_fn
= xattr_tdb_fsetxattr
,
608 .listxattr_fn
= xattr_tdb_listxattr
,
609 .flistxattr_fn
= xattr_tdb_flistxattr
,
610 .removexattr_fn
= xattr_tdb_removexattr
,
611 .fremovexattr_fn
= xattr_tdb_fremovexattr
,
612 .open_fn
= xattr_tdb_open
,
613 .mkdir_fn
= xattr_tdb_mkdir
,
614 .unlink_fn
= xattr_tdb_unlink
,
615 .rmdir_fn
= xattr_tdb_rmdir
,
616 .connect_fn
= xattr_tdb_connect
,
620 NTSTATUS
vfs_xattr_tdb_init(TALLOC_CTX
*ctx
)
622 return smb_register_vfs(SMB_VFS_INTERFACE_VERSION
, "xattr_tdb",