root/source3/modules/vfs_xattr_tdb.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. xattr_tdb_pull_attrs
  2. xattr_tdb_push_attrs
  3. xattr_tdb_load_attrs
  4. xattr_tdb_lock_attrs
  5. xattr_tdb_save_attrs
  6. xattr_tdb_getattr
  7. xattr_tdb_getxattr
  8. xattr_tdb_fgetxattr
  9. xattr_tdb_setattr
  10. xattr_tdb_setxattr
  11. xattr_tdb_fsetxattr
  12. xattr_tdb_listattr
  13. xattr_tdb_listxattr
  14. xattr_tdb_flistxattr
  15. xattr_tdb_removeattr
  16. xattr_tdb_removexattr
  17. xattr_tdb_fremovexattr
  18. xattr_tdb_init
  19. xattr_tdb_unlink
  20. xattr_tdb_rmdir
  21. close_xattr_db
  22. xattr_tdb_connect
  23. vfs_xattr_tdb_init

   1 /*
   2  * Store posix-level xattrs in a tdb
   3  *
   4  * Copyright (C) Volker Lendecke, 2007
   5  *
   6  * This program is free software; you can redistribute it and/or modify
   7  * it under the terms of the GNU General Public License as published by
   8  * the Free Software Foundation; either version 3 of the License, or
   9  * (at your option) any later version.
  10  *
  11  * This program is distributed in the hope that it will be useful,
  12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  14  * GNU General Public License for more details.
  15  *
  16  * You should have received a copy of the GNU General Public License
  17  * along with this program; if not, see <http://www.gnu.org/licenses/>.
  18  */
  19 
  20 #include "includes.h"
  21 #include "librpc/gen_ndr/xattr.h"
  22 #include "librpc/gen_ndr/ndr_xattr.h"
  23 
  24 #undef DBGC_CLASS
  25 #define DBGC_CLASS DBGC_VFS
  26 
  27 /*
  28  * unmarshall tdb_xattrs
  29  */
  30 
  31 static NTSTATUS xattr_tdb_pull_attrs(TALLOC_CTX *mem_ctx,
     /* [<][>][^][v][top][bottom][index][help] */
  32                                      const TDB_DATA *data,
  33                                      struct tdb_xattrs **presult)
  34 {
  35         DATA_BLOB blob;
  36         enum ndr_err_code ndr_err;
  37         struct tdb_xattrs *result;
  38 
  39         if (!(result = TALLOC_ZERO_P(mem_ctx, struct tdb_xattrs))) {
  40                 return NT_STATUS_NO_MEMORY;
  41         }
  42 
  43         if (data->dsize == 0) {
  44                 *presult = result;
  45                 return NT_STATUS_OK;
  46         }
  47 
  48         blob = data_blob_const(data->dptr, data->dsize);
  49 
  50         ndr_err = ndr_pull_struct_blob(
  51                 &blob, result, NULL, result,
  52                 (ndr_pull_flags_fn_t)ndr_pull_tdb_xattrs);
  53 
  54         if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
  55                 DEBUG(0, ("ndr_pull_tdb_xattrs failed: %s\n",
  56                           ndr_errstr(ndr_err)));
  57                 TALLOC_FREE(result);
  58                 return ndr_map_error2ntstatus(ndr_err);;
  59         }
  60 
  61         *presult = result;
  62         return NT_STATUS_OK;
  63 }
  64 
  65 /*
  66  * marshall tdb_xattrs
  67  */
  68 
  69 static NTSTATUS xattr_tdb_push_attrs(TALLOC_CTX *mem_ctx,
     /* [<][>][^][v][top][bottom][index][help] */
  70                                      const struct tdb_xattrs *attribs,
  71                                      TDB_DATA *data)
  72 {
  73         DATA_BLOB blob;
  74         enum ndr_err_code ndr_err;
  75 
  76         ndr_err = ndr_push_struct_blob(
  77                 &blob, mem_ctx, NULL, attribs,
  78                 (ndr_push_flags_fn_t)ndr_push_tdb_xattrs);
  79 
  80         if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
  81                 DEBUG(0, ("ndr_push_tdb_xattrs failed: %s\n",
  82                           ndr_errstr(ndr_err)));
  83                 return ndr_map_error2ntstatus(ndr_err);;
  84         }
  85 
  86         *data = make_tdb_data(blob.data, blob.length);
  87         return NT_STATUS_OK;
  88 }
  89 
  90 /*
  91  * Load tdb_xattrs for a file from the tdb
  92  */
  93 
  94 static NTSTATUS xattr_tdb_load_attrs(TALLOC_CTX *mem_ctx,
     /* [<][>][^][v][top][bottom][index][help] */
  95                                      struct db_context *db_ctx,
  96                                      const struct file_id *id,
  97                                      struct tdb_xattrs **presult)
  98 {
  99         uint8 id_buf[16];
 100         NTSTATUS status;
 101         TDB_DATA data;
 102 
 103         /* For backwards compatibility only store the dev/inode. */
 104         push_file_id_16((char *)id_buf, id);
 105 
 106         if (db_ctx->fetch(db_ctx, mem_ctx,
 107                           make_tdb_data(id_buf, sizeof(id_buf)),
 108                           &data) == -1) {
 109                 return NT_STATUS_INTERNAL_DB_CORRUPTION;
 110         }
 111 
 112         status = xattr_tdb_pull_attrs(mem_ctx, &data, presult);
 113         TALLOC_FREE(data.dptr);
 114         return status;
 115 }
 116 
 117 /*
 118  * fetch_lock the tdb_ea record for a file
 119  */
 120 
 121 static struct db_record *xattr_tdb_lock_attrs(TALLOC_CTX *mem_ctx,
     /* [<][>][^][v][top][bottom][index][help] */
 122                                               struct db_context *db_ctx,
 123                                               const struct file_id *id)
 124 {
 125         uint8 id_buf[16];
 126 
 127         /* For backwards compatibility only store the dev/inode. */
 128         push_file_id_16((char *)id_buf, id);
 129         return db_ctx->fetch_locked(db_ctx, mem_ctx,
 130                                     make_tdb_data(id_buf, sizeof(id_buf)));
 131 }
 132 
 133 /*
 134  * Save tdb_xattrs to a previously fetch_locked record
 135  */
 136 
 137 static NTSTATUS xattr_tdb_save_attrs(struct db_record *rec,
     /* [<][>][^][v][top][bottom][index][help] */
 138                                      const struct tdb_xattrs *attribs)
 139 {
 140         TDB_DATA data = tdb_null;
 141         NTSTATUS status;
 142 
 143         status = xattr_tdb_push_attrs(talloc_tos(), attribs, &data);
 144 
 145         if (!NT_STATUS_IS_OK(status)) {
 146                 DEBUG(0, ("xattr_tdb_push_attrs failed: %s\n",
 147                           nt_errstr(status)));
 148                 return status;
 149         }
 150 
 151         status = rec->store(rec, data, 0);
 152 
 153         TALLOC_FREE(data.dptr);
 154 
 155         return status;
 156 }
 157 
 158 /*
 159  * Worker routine for getxattr and fgetxattr
 160  */
 161 
 162 static ssize_t xattr_tdb_getattr(struct db_context *db_ctx,
     /* [<][>][^][v][top][bottom][index][help] */
 163                                  const struct file_id *id,
 164                                  const char *name, void *value, size_t size)
 165 {
 166         struct tdb_xattrs *attribs;
 167         uint32_t i;
 168         ssize_t result = -1;
 169         NTSTATUS status;
 170 
 171         DEBUG(10, ("xattr_tdb_getattr called for file %s, name %s\n",
 172                    file_id_string_tos(id), name));
 173 
 174         status = xattr_tdb_load_attrs(talloc_tos(), db_ctx, id, &attribs);
 175 
 176         if (!NT_STATUS_IS_OK(status)) {
 177                 DEBUG(10, ("xattr_tdb_fetch_attrs failed: %s\n",
 178                            nt_errstr(status)));
 179                 errno = EINVAL;
 180                 return -1;
 181         }
 182 
 183         for (i=0; i<attribs->num_eas; i++) {
 184                 if (strcmp(attribs->eas[i].name, name) == 0) {
 185                         break;
 186                 }
 187         }
 188 
 189         if (i == attribs->num_eas) {
 190                 errno = ENOATTR;
 191                 goto fail;
 192         }
 193 
 194         if (attribs->eas[i].value.length > size) {
 195                 errno = ERANGE;
 196                 goto fail;
 197         }
 198 
 199         memcpy(value, attribs->eas[i].value.data,
 200                attribs->eas[i].value.length);
 201         result = attribs->eas[i].value.length;
 202 
 203  fail:
 204         TALLOC_FREE(attribs);
 205         return result;
 206 }
 207 
 208 static ssize_t xattr_tdb_getxattr(struct vfs_handle_struct *handle,
     /* [<][>][^][v][top][bottom][index][help] */
 209                                   const char *path, const char *name,
 210                                   void *value, size_t size)
 211 {
 212         SMB_STRUCT_STAT sbuf;
 213         struct file_id id;
 214         struct db_context *db;
 215         int ret;
 216 
 217         SMB_VFS_HANDLE_GET_DATA(handle, db, struct db_context, return -1);
 218 
 219         if (lp_posix_pathnames()) {
 220                 ret = SMB_VFS_LSTAT(handle->conn, path, &sbuf);
 221         } else {
 222                 ret = SMB_VFS_STAT(handle->conn, path, &sbuf);
 223         }
 224 
 225         if (ret == -1) {
 226                 return -1;
 227         }
 228 
 229         id = SMB_VFS_FILE_ID_CREATE(handle->conn, &sbuf);
 230 
 231         return xattr_tdb_getattr(db, &id, name, value, size);
 232 }
 233 
 234 static ssize_t xattr_tdb_fgetxattr(struct vfs_handle_struct *handle,
     /* [<][>][^][v][top][bottom][index][help] */
 235                                    struct files_struct *fsp,
 236                                    const char *name, void *value, size_t size)
 237 {
 238         SMB_STRUCT_STAT sbuf;
 239         struct file_id id;
 240         struct db_context *db;
 241 
 242         SMB_VFS_HANDLE_GET_DATA(handle, db, struct db_context, return -1);
 243 
 244         if (SMB_VFS_FSTAT(fsp, &sbuf) == -1) {
 245                 return -1;
 246         }
 247 
 248         id = SMB_VFS_FILE_ID_CREATE(handle->conn, &sbuf);
 249 
 250         return xattr_tdb_getattr(db, &id, name, value, size);
 251 }
 252 
 253 /*
 254  * Worker routine for setxattr and fsetxattr
 255  */
 256 
 257 static int xattr_tdb_setattr(struct db_context *db_ctx,
     /* [<][>][^][v][top][bottom][index][help] */
 258                              const struct file_id *id, const char *name,
 259                              const void *value, size_t size, int flags)
 260 {
 261         NTSTATUS status;
 262         struct db_record *rec;
 263         struct tdb_xattrs *attribs;
 264         uint32_t i;
 265 
 266         DEBUG(10, ("xattr_tdb_setattr called for file %s, name %s\n",
 267                    file_id_string_tos(id), name));
 268 
 269         rec = xattr_tdb_lock_attrs(talloc_tos(), db_ctx, id);
 270 
 271         if (rec == NULL) {
 272                 DEBUG(0, ("xattr_tdb_lock_attrs failed\n"));
 273                 errno = EINVAL;
 274                 return -1;
 275         }
 276 
 277         status = xattr_tdb_pull_attrs(rec, &rec->value, &attribs);
 278 
 279         if (!NT_STATUS_IS_OK(status)) {
 280                 DEBUG(10, ("xattr_tdb_fetch_attrs failed: %s\n",
 281                            nt_errstr(status)));
 282                 TALLOC_FREE(rec);
 283                 return -1;
 284         }
 285 
 286         for (i=0; i<attribs->num_eas; i++) {
 287                 if (strcmp(attribs->eas[i].name, name) == 0) {
 288                         if (flags & XATTR_CREATE) {
 289                                 TALLOC_FREE(rec);
 290                                 errno = EEXIST;
 291                                 return -1;
 292                         }
 293                         break;
 294                 }
 295         }
 296 
 297         if (i == attribs->num_eas) {
 298                 struct xattr_EA *tmp;
 299 
 300                 if (flags & XATTR_REPLACE) {
 301                         TALLOC_FREE(rec);
 302                         errno = ENOATTR;
 303                         return -1;
 304                 }
 305 
 306                 tmp = TALLOC_REALLOC_ARRAY(
 307                         attribs, attribs->eas, struct xattr_EA,
 308                         attribs->num_eas+ 1);
 309 
 310                 if (tmp == NULL) {
 311                         DEBUG(0, ("TALLOC_REALLOC_ARRAY failed\n"));
 312                         TALLOC_FREE(rec);
 313                         errno = ENOMEM;
 314                         return -1;
 315                 }
 316 
 317                 attribs->eas = tmp;
 318                 attribs->num_eas += 1;
 319         }
 320 
 321         attribs->eas[i].name = name;
 322         attribs->eas[i].value.data = CONST_DISCARD(uint8 *, value);
 323         attribs->eas[i].value.length = size;
 324 
 325         status = xattr_tdb_save_attrs(rec, attribs);
 326 
 327         TALLOC_FREE(rec);
 328 
 329         if (!NT_STATUS_IS_OK(status)) {
 330                 DEBUG(1, ("save failed: %s\n", nt_errstr(status)));
 331                 return -1;
 332         }
 333 
 334         return 0;
 335 }
 336 
 337 static int xattr_tdb_setxattr(struct vfs_handle_struct *handle,
     /* [<][>][^][v][top][bottom][index][help] */
 338                               const char *path, const char *name,
 339                               const void *value, size_t size, int flags)
 340 {
 341         SMB_STRUCT_STAT sbuf;
 342         struct file_id id;
 343         struct db_context *db;
 344         int ret;
 345 
 346         SMB_VFS_HANDLE_GET_DATA(handle, db, struct db_context, return -1);
 347 
 348         if (lp_posix_pathnames()) {
 349                 ret = SMB_VFS_LSTAT(handle->conn, path, &sbuf);
 350         } else {
 351                 ret = SMB_VFS_STAT(handle->conn, path, &sbuf);
 352         }
 353 
 354         if (ret == -1) {
 355                 return -1;
 356         }
 357 
 358         id = SMB_VFS_FILE_ID_CREATE(handle->conn, &sbuf);
 359 
 360         return xattr_tdb_setattr(db, &id, name, value, size, flags);
 361 }
 362 
 363 static int xattr_tdb_fsetxattr(struct vfs_handle_struct *handle,
     /* [<][>][^][v][top][bottom][index][help] */
 364                                struct files_struct *fsp,
 365                                const char *name, const void *value,
 366                                size_t size, int flags)
 367 {
 368         SMB_STRUCT_STAT sbuf;
 369         struct file_id id;
 370         struct db_context *db;
 371 
 372         SMB_VFS_HANDLE_GET_DATA(handle, db, struct db_context, return -1);
 373 
 374         if (SMB_VFS_FSTAT(fsp, &sbuf) == -1) {
 375                 return -1;
 376         }
 377 
 378         id = SMB_VFS_FILE_ID_CREATE(handle->conn, &sbuf);
 379 
 380         return xattr_tdb_setattr(db, &id, name, value, size, flags);
 381 }
 382 
 383 /*
 384  * Worker routine for listxattr and flistxattr
 385  */
 386 
 387 static ssize_t xattr_tdb_listattr(struct db_context *db_ctx,
     /* [<][>][^][v][top][bottom][index][help] */
 388                                   const struct file_id *id, char *list,
 389                                   size_t size)
 390 {
 391         NTSTATUS status;
 392         struct tdb_xattrs *attribs;
 393         uint32_t i;
 394         size_t len = 0;
 395 
 396         status = xattr_tdb_load_attrs(talloc_tos(), db_ctx, id, &attribs);
 397 
 398         if (!NT_STATUS_IS_OK(status)) {
 399                 DEBUG(10, ("xattr_tdb_fetch_attrs failed: %s\n",
 400                            nt_errstr(status)));
 401                 errno = EINVAL;
 402                 return -1;
 403         }
 404 
 405         DEBUG(10, ("xattr_tdb_listattr: Found %d xattrs\n",
 406                    attribs->num_eas));
 407 
 408         for (i=0; i<attribs->num_eas; i++) {
 409                 size_t tmp;
 410 
 411                 DEBUG(10, ("xattr_tdb_listattr: xattrs[i].name: %s\n",
 412                            attribs->eas[i].name));
 413 
 414                 tmp = strlen(attribs->eas[i].name);
 415 
 416                 /*
 417                  * Try to protect against overflow
 418                  */
 419 
 420                 if (len + (tmp+1) < len) {
 421                         TALLOC_FREE(attribs);
 422                         errno = EINVAL;
 423                         return -1;
 424                 }
 425 
 426                 /*
 427                  * Take care of the terminating NULL
 428                  */
 429                 len += (tmp + 1);
 430         }
 431 
 432         if (len > size) {
 433                 TALLOC_FREE(attribs);
 434                 errno = ERANGE;
 435                 return -1;
 436         }
 437 
 438         len = 0;
 439 
 440         for (i=0; i<attribs->num_eas; i++) {
 441                 strlcpy(list+len, attribs->eas[i].name,
 442                         size-len);
 443                 len += (strlen(attribs->eas[i].name) + 1);
 444         }
 445 
 446         TALLOC_FREE(attribs);
 447         return len;
 448 }
 449 
 450 static ssize_t xattr_tdb_listxattr(struct vfs_handle_struct *handle,
     /* [<][>][^][v][top][bottom][index][help] */
 451                                    const char *path, char *list, size_t size)
 452 {
 453         SMB_STRUCT_STAT sbuf;
 454         struct file_id id;
 455         struct db_context *db;
 456         int ret;
 457 
 458         SMB_VFS_HANDLE_GET_DATA(handle, db, struct db_context, return -1);
 459 
 460         if (lp_posix_pathnames()) {
 461                 ret = SMB_VFS_LSTAT(handle->conn, path, &sbuf);
 462         } else {
 463                 ret = SMB_VFS_STAT(handle->conn, path, &sbuf);
 464         }
 465 
 466         if (ret == -1) {
 467                 return -1;
 468         }
 469 
 470         id = SMB_VFS_FILE_ID_CREATE(handle->conn, &sbuf);
 471 
 472         return xattr_tdb_listattr(db, &id, list, size);
 473 }
 474 
 475 static ssize_t xattr_tdb_flistxattr(struct vfs_handle_struct *handle,
     /* [<][>][^][v][top][bottom][index][help] */
 476                                     struct files_struct *fsp, char *list,
 477                                     size_t size)
 478 {
 479         SMB_STRUCT_STAT sbuf;
 480         struct file_id id;
 481         struct db_context *db;
 482 
 483         SMB_VFS_HANDLE_GET_DATA(handle, db, struct db_context, return -1);
 484 
 485         if (SMB_VFS_FSTAT(fsp, &sbuf) == -1) {
 486                 return -1;
 487         }
 488 
 489         id = SMB_VFS_FILE_ID_CREATE(handle->conn, &sbuf);
 490 
 491         return xattr_tdb_listattr(db, &id, list, size);
 492 }
 493 
 494 /*
 495  * Worker routine for removexattr and fremovexattr
 496  */
 497 
 498 static int xattr_tdb_removeattr(struct db_context *db_ctx,
     /* [<][>][^][v][top][bottom][index][help] */
 499                                 const struct file_id *id, const char *name)
 500 {
 501         NTSTATUS status;
 502         struct db_record *rec;
 503         struct tdb_xattrs *attribs;
 504         uint32_t i;
 505 
 506         rec = xattr_tdb_lock_attrs(talloc_tos(), db_ctx, id);
 507 
 508         if (rec == NULL) {
 509                 DEBUG(0, ("xattr_tdb_lock_attrs failed\n"));
 510                 errno = EINVAL;
 511                 return -1;
 512         }
 513 
 514         status = xattr_tdb_pull_attrs(rec, &rec->value, &attribs);
 515 
 516         if (!NT_STATUS_IS_OK(status)) {
 517                 DEBUG(10, ("xattr_tdb_fetch_attrs failed: %s\n",
 518                            nt_errstr(status)));
 519                 TALLOC_FREE(rec);
 520                 return -1;
 521         }
 522 
 523         for (i=0; i<attribs->num_eas; i++) {
 524                 if (strcmp(attribs->eas[i].name, name) == 0) {
 525                         break;
 526                 }
 527         }
 528 
 529         if (i == attribs->num_eas) {
 530                 TALLOC_FREE(rec);
 531                 errno = ENOATTR;
 532                 return -1;
 533         }
 534 
 535         attribs->eas[i] =
 536                 attribs->eas[attribs->num_eas-1];
 537         attribs->num_eas -= 1;
 538 
 539         if (attribs->num_eas == 0) {
 540                 rec->delete_rec(rec);
 541                 TALLOC_FREE(rec);
 542                 return 0;
 543         }
 544 
 545         status = xattr_tdb_save_attrs(rec, attribs);
 546 
 547         TALLOC_FREE(rec);
 548 
 549         if (!NT_STATUS_IS_OK(status)) {
 550                 DEBUG(1, ("save failed: %s\n", nt_errstr(status)));
 551                 return -1;
 552         }
 553 
 554         return 0;
 555 }
 556 
 557 static int xattr_tdb_removexattr(struct vfs_handle_struct *handle,
     /* [<][>][^][v][top][bottom][index][help] */
 558                                  const char *path, const char *name)
 559 {
 560         SMB_STRUCT_STAT sbuf;
 561         struct file_id id;
 562         struct db_context *db;
 563         int ret;
 564 
 565         SMB_VFS_HANDLE_GET_DATA(handle, db, struct db_context, return -1);
 566 
 567         if (lp_posix_pathnames()) {
 568                 ret = SMB_VFS_LSTAT(handle->conn, path, &sbuf);
 569         } else {
 570                 ret = SMB_VFS_STAT(handle->conn, path, &sbuf);
 571         }
 572 
 573         if (ret == -1) {
 574                 return -1;
 575         }
 576 
 577         id = SMB_VFS_FILE_ID_CREATE(handle->conn, &sbuf);
 578 
 579         return xattr_tdb_removeattr(db, &id, name);
 580 }
 581 
 582 static int xattr_tdb_fremovexattr(struct vfs_handle_struct *handle,
     /* [<][>][^][v][top][bottom][index][help] */
 583                                   struct files_struct *fsp, const char *name)
 584 {
 585         SMB_STRUCT_STAT sbuf;
 586         struct file_id id;
 587         struct db_context *db;
 588 
 589         SMB_VFS_HANDLE_GET_DATA(handle, db, struct db_context, return -1);
 590 
 591         if (SMB_VFS_FSTAT(fsp, &sbuf) == -1) {
 592                 return -1;
 593         }
 594 
 595         id = SMB_VFS_FILE_ID_CREATE(handle->conn, &sbuf);
 596 
 597         return xattr_tdb_removeattr(db, &id, name);
 598 }
 599 
 600 /*
 601  * Open the tdb file upon VFS_CONNECT
 602  */
 603 
 604 static bool xattr_tdb_init(int snum, struct db_context **p_db)
     /* [<][>][^][v][top][bottom][index][help] */
 605 {
 606         struct db_context *db;
 607         const char *dbname;
 608         char *def_dbname;
 609 
 610         def_dbname = state_path("xattr.tdb");
 611         if (def_dbname == NULL) {
 612                 errno = ENOSYS;
 613                 return false;
 614         }
 615 
 616         dbname = lp_parm_const_string(snum, "xattr_tdb", "file", def_dbname);
 617 
 618         /* now we know dbname is not NULL */
 619 
 620         become_root();
 621         db = db_open(NULL, dbname, 0, TDB_DEFAULT, O_RDWR|O_CREAT, 0600);
 622         unbecome_root();
 623 
 624         if (db == NULL) {
 625 #if defined(ENOTSUP)
 626                 errno = ENOTSUP;
 627 #else
 628                 errno = ENOSYS;
 629 #endif
 630                 TALLOC_FREE(def_dbname);
 631                 return false;
 632         }
 633 
 634         *p_db = db;
 635         TALLOC_FREE(def_dbname);
 636         return true;
 637 }
 638 
 639 /*
 640  * On unlink we need to delete the tdb record
 641  */
 642 static int xattr_tdb_unlink(vfs_handle_struct *handle, const char *path)
     /* [<][>][^][v][top][bottom][index][help] */
 643 {
 644         SMB_STRUCT_STAT sbuf;
 645         struct file_id id;
 646         struct db_context *db;
 647         struct db_record *rec;
 648         int ret;
 649 
 650         SMB_VFS_HANDLE_GET_DATA(handle, db, struct db_context, return -1);
 651 
 652         if (lp_posix_pathnames()) {
 653                 ret = SMB_VFS_LSTAT(handle->conn, path, &sbuf);
 654         } else {
 655                 ret = SMB_VFS_STAT(handle->conn, path, &sbuf);
 656         }
 657 
 658         if (ret == -1) {
 659                 return -1;
 660         }
 661 
 662         ret = SMB_VFS_NEXT_UNLINK(handle, path);
 663 
 664         if (ret == -1) {
 665                 return -1;
 666         }
 667 
 668         id = SMB_VFS_FILE_ID_CREATE(handle->conn, &sbuf);
 669 
 670         rec = xattr_tdb_lock_attrs(talloc_tos(), db, &id);
 671 
 672         /*
 673          * If rec == NULL there's not much we can do about it
 674          */
 675 
 676         if (rec != NULL) {
 677                 rec->delete_rec(rec);
 678                 TALLOC_FREE(rec);
 679         }
 680 
 681         return 0;
 682 }
 683 
 684 /*
 685  * On rmdir we need to delete the tdb record
 686  */
 687 static int xattr_tdb_rmdir(vfs_handle_struct *handle, const char *path)
     /* [<][>][^][v][top][bottom][index][help] */
 688 {
 689         SMB_STRUCT_STAT sbuf;
 690         struct file_id id;
 691         struct db_context *db;
 692         struct db_record *rec;
 693         int ret;
 694 
 695         SMB_VFS_HANDLE_GET_DATA(handle, db, struct db_context, return -1);
 696 
 697         if (lp_posix_pathnames()) {
 698                 ret = SMB_VFS_LSTAT(handle->conn, path, &sbuf);
 699         } else {
 700                 ret = SMB_VFS_STAT(handle->conn, path, &sbuf);
 701         }
 702 
 703         if (ret == -1) {
 704                 return -1;
 705         }
 706 
 707         ret = SMB_VFS_NEXT_RMDIR(handle, path);
 708 
 709         if (ret == -1) {
 710                 return -1;
 711         }
 712 
 713         id = SMB_VFS_FILE_ID_CREATE(handle->conn, &sbuf);
 714 
 715         rec = xattr_tdb_lock_attrs(talloc_tos(), db, &id);
 716 
 717         /*
 718          * If rec == NULL there's not much we can do about it
 719          */
 720 
 721         if (rec != NULL) {
 722                 rec->delete_rec(rec);
 723                 TALLOC_FREE(rec);
 724         }
 725 
 726         return 0;
 727 }
 728 
 729 /*
 730  * Destructor for the VFS private data
 731  */
 732 
 733 static void close_xattr_db(void **data)
     /* [<][>][^][v][top][bottom][index][help] */
 734 {
 735         struct db_context **p_db = (struct db_context **)data;
 736         TALLOC_FREE(*p_db);
 737 }
 738 
 739 static int xattr_tdb_connect(vfs_handle_struct *handle, const char *service,
     /* [<][>][^][v][top][bottom][index][help] */
 740                           const char *user)
 741 {
 742         fstring sname;
 743         int res, snum;
 744         struct db_context *db;
 745 
 746         res = SMB_VFS_NEXT_CONNECT(handle, service, user);
 747         if (res < 0) {
 748                 return res;
 749         }
 750 
 751         fstrcpy(sname, service);
 752         snum = find_service(sname);
 753         if (snum == -1) {
 754                 /*
 755                  * Should not happen, but we should not fail just *here*.
 756                  */
 757                 return 0;
 758         }
 759 
 760         if (!xattr_tdb_init(snum, &db)) {
 761                 DEBUG(5, ("Could not init xattr tdb\n"));
 762                 lp_do_parameter(snum, "ea support", "False");
 763                 return 0;
 764         }
 765 
 766         lp_do_parameter(snum, "ea support", "True");
 767 
 768         SMB_VFS_HANDLE_SET_DATA(handle, db, close_xattr_db,
 769                                 struct db_context, return -1);
 770 
 771         return 0;
 772 }
 773 
 774 /* VFS operations structure */
 775 
 776 static const vfs_op_tuple xattr_tdb_ops[] = {
 777         {SMB_VFS_OP(xattr_tdb_getxattr), SMB_VFS_OP_GETXATTR,
 778          SMB_VFS_LAYER_TRANSPARENT},
 779         {SMB_VFS_OP(xattr_tdb_fgetxattr), SMB_VFS_OP_FGETXATTR,
 780          SMB_VFS_LAYER_TRANSPARENT},
 781         {SMB_VFS_OP(xattr_tdb_setxattr), SMB_VFS_OP_SETXATTR,
 782          SMB_VFS_LAYER_TRANSPARENT},
 783         {SMB_VFS_OP(xattr_tdb_fsetxattr), SMB_VFS_OP_FSETXATTR,
 784          SMB_VFS_LAYER_TRANSPARENT},
 785         {SMB_VFS_OP(xattr_tdb_listxattr), SMB_VFS_OP_LISTXATTR,
 786          SMB_VFS_LAYER_TRANSPARENT},
 787         {SMB_VFS_OP(xattr_tdb_flistxattr), SMB_VFS_OP_FLISTXATTR,
 788          SMB_VFS_LAYER_TRANSPARENT},
 789         {SMB_VFS_OP(xattr_tdb_removexattr), SMB_VFS_OP_REMOVEXATTR,
 790          SMB_VFS_LAYER_TRANSPARENT},
 791         {SMB_VFS_OP(xattr_tdb_fremovexattr), SMB_VFS_OP_FREMOVEXATTR,
 792          SMB_VFS_LAYER_TRANSPARENT},
 793         {SMB_VFS_OP(xattr_tdb_unlink), SMB_VFS_OP_UNLINK,
 794          SMB_VFS_LAYER_TRANSPARENT},
 795         {SMB_VFS_OP(xattr_tdb_rmdir), SMB_VFS_OP_RMDIR,
 796          SMB_VFS_LAYER_TRANSPARENT},
 797         {SMB_VFS_OP(xattr_tdb_connect), SMB_VFS_OP_CONNECT,
 798          SMB_VFS_LAYER_TRANSPARENT},
 799         {SMB_VFS_OP(NULL), SMB_VFS_OP_NOOP, SMB_VFS_LAYER_NOOP}
 800 };
 801 
 802 NTSTATUS vfs_xattr_tdb_init(void);
 803 NTSTATUS vfs_xattr_tdb_init(void)
     /* [<][>][^][v][top][bottom][index][help] */
 804 {
 805         return smb_register_vfs(SMB_VFS_INTERFACE_VERSION, "xattr_tdb",
 806                                 xattr_tdb_ops);
 807 }

/* [<][>][^][v][top][bottom][index][help] */