LCOV - code coverage report
Current view: top level - source4/ntvfs/posix - posix_eadb.c (source / functions) Hit Total Coverage
Test: coverage report for master 98b443d9 Lines: 94 118 79.7 %
Date: 2024-05-31 13:13:24 Functions: 10 11 90.9 %

          Line data    Source code
       1             : /*
       2             :    Unix SMB/CIFS implementation.
       3             : 
       4             :    POSIX NTVFS backend - xattr support using a tdb
       5             : 
       6             :    Copyright (C) Andrew Tridgell 2004
       7             : 
       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.
      12             : 
      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.
      17             : 
      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/>.
      20             : */
      21             : 
      22             : #include "includes.h"
      23             : #include "lib/tdb_wrap/tdb_wrap.h"
      24             : #ifdef WITH_NTVFS_FILESERVER
      25             : #include "vfs_posix.h"
      26             : #endif
      27             : #include "posix_eadb.h"
      28             : 
      29             : #define XATTR_LIST_ATTR ".xattr_list"
      30             : 
      31             : /*
      32             :   we need to maintain a list of attributes on each file, so that unlink
      33             :   can automatically clean them up
      34             : */
      35      199003 : static NTSTATUS posix_eadb_add_list(struct tdb_wrap *ea_tdb, TALLOC_CTX *ctx, const char *attr_name,
      36             :                                    const char *fname, int fd)
      37             : {
      38           8 :         DATA_BLOB blob;
      39           8 :         TALLOC_CTX *mem_ctx;
      40           8 :         NTSTATUS status;
      41           8 :         size_t len;
      42             : 
      43      199003 :         if (strcmp(attr_name, XATTR_LIST_ATTR) == 0) {
      44       97973 :                 return NT_STATUS_OK;
      45             :         }
      46             : 
      47      101030 :         mem_ctx = talloc_new(ctx);
      48             : 
      49      101030 :         status = pull_xattr_blob_tdb_raw(ea_tdb, mem_ctx, XATTR_LIST_ATTR,
      50             :                                      fname, fd, 100, &blob);
      51      101030 :         if (NT_STATUS_IS_OK(status)) {
      52           0 :                 const char *s;
      53             : 
      54        3646 :                 for (s = (const char *)blob.data;
      55        4529 :                      s < (const char *)(blob.data + blob.length);
      56         883 :                      s += strlen(s) + 1) {
      57        3940 :                         if (strcmp(attr_name, s) == 0) {
      58        3057 :                                 talloc_free(mem_ctx);
      59        3057 :                                 return NT_STATUS_OK;
      60             :                         }
      61             :                 }
      62             :         } else {
      63       97384 :                 blob = data_blob(NULL, 0);
      64             :                 /* No need to parse an empty blob */
      65             :         }
      66             : 
      67       97973 :         len = strlen(attr_name) + 1;
      68             : 
      69       97973 :         blob.data = talloc_realloc(mem_ctx, blob.data, uint8_t, blob.length + len);
      70       97973 :         if (blob.data == NULL) {
      71           0 :                 talloc_free(mem_ctx);
      72           0 :                 return NT_STATUS_NO_MEMORY;
      73             :         }
      74       97973 :         memcpy(blob.data + blob.length, attr_name, len);
      75       97973 :         blob.length += len;
      76             : 
      77       97973 :         status = push_xattr_blob_tdb_raw(ea_tdb, XATTR_LIST_ATTR, fname, fd, &blob);
      78       97973 :         talloc_free(mem_ctx);
      79             : 
      80       97973 :         return status;
      81             : }
      82             : 
      83             : /*
      84             :   form a key for using in the ea_tdb
      85             : */
      86     1990696 : static NTSTATUS get_ea_tdb_key(TALLOC_CTX *mem_ctx,
      87             :                               const char *attr_name,
      88             :                               const char *fname, int fd,
      89             :                               TDB_DATA *key)
      90             : {
      91          14 :         struct stat st;
      92     1990696 :         size_t len = strlen(attr_name);
      93             : 
      94     1990696 :         if (fd == -1) {
      95     1496629 :                 if (stat(fname, &st) == -1) {
      96           0 :                         return NT_STATUS_NOT_FOUND;
      97             :                 }
      98             :         } else {
      99      494067 :                 if (fstat(fd, &st) == -1) {
     100           0 :                         return NT_STATUS_NOT_FOUND;
     101             :                 }
     102             :         }
     103             : 
     104     1990696 :         key->dptr = talloc_array(mem_ctx, uint8_t, 16 + len);
     105     1990696 :         if (key->dptr == NULL) {
     106           0 :                 return NT_STATUS_NO_MEMORY;
     107             :         }
     108     1990696 :         key->dsize = 16 + len;
     109             : 
     110     1990696 :         SBVAL(key->dptr, 0, st.st_dev);
     111     1990696 :         SBVAL(key->dptr, 8, st.st_ino);
     112     1990696 :         memcpy(key->dptr+16, attr_name, len);
     113             : 
     114     1990696 :         return NT_STATUS_OK;
     115             : }
     116             : 
     117             : 
     118             : 
     119             : /*
     120             :   pull a xattr as a blob, using the ea_tdb_context tdb
     121             : */
     122     1596675 : NTSTATUS pull_xattr_blob_tdb_raw(struct tdb_wrap *ea_tdb,
     123             :                              TALLOC_CTX *mem_ctx,
     124             :                              const char *attr_name,
     125             :                              const char *fname,
     126             :                              int fd,
     127             :                              size_t estimated_size,
     128             :                              DATA_BLOB *blob)
     129             : {
     130           6 :         TDB_DATA tkey, tdata;
     131           6 :         NTSTATUS status;
     132             : 
     133     1596675 :         status = get_ea_tdb_key(mem_ctx, attr_name, fname, fd, &tkey);
     134     1596675 :         if (!NT_STATUS_IS_OK(status)) {
     135           0 :                 return status;
     136             :         }
     137             : 
     138     1596675 :         tdata = tdb_fetch(ea_tdb->tdb, tkey);
     139     1596675 :         if (tdata.dptr == NULL) {
     140     1148759 :                 return NT_STATUS_NOT_FOUND;
     141             :         }
     142             : 
     143      447916 :         *blob = data_blob_talloc(mem_ctx, tdata.dptr, tdata.dsize);
     144      447916 :         free(tdata.dptr);
     145      447916 :         if (blob->data == NULL) {
     146           0 :                 return NT_STATUS_NO_MEMORY;
     147             :         }
     148             : 
     149      447916 :         return NT_STATUS_OK;
     150             : }
     151             : 
     152             : /*
     153             :   push a xattr as a blob, using ea_tdb
     154             : */
     155      199003 : NTSTATUS push_xattr_blob_tdb_raw(struct tdb_wrap *ea_tdb,
     156             :                              const char *attr_name,
     157             :                              const char *fname,
     158             :                              int fd,
     159             :                              const DATA_BLOB *blob)
     160             : {
     161           8 :         TDB_DATA tkey, tdata;
     162           8 :         NTSTATUS status;
     163      199003 :         TALLOC_CTX *mem_ctx = talloc_new(ea_tdb);
     164      199003 :         if (!mem_ctx) {
     165           0 :                 return NT_STATUS_NO_MEMORY;
     166             :         }
     167             : 
     168      199003 :         status = get_ea_tdb_key(mem_ctx, attr_name, fname, fd, &tkey);
     169      199003 :         if (!NT_STATUS_IS_OK(status)) {
     170           0 :                 talloc_free(mem_ctx);
     171           0 :                 return status;
     172             :         }
     173             : 
     174      199003 :         tdata.dptr = blob->data;
     175      199003 :         tdata.dsize = blob->length;
     176             : 
     177      199003 :         if (tdb_chainlock(ea_tdb->tdb, tkey) != 0) {
     178           0 :                 talloc_free(mem_ctx);
     179           0 :                 return NT_STATUS_INTERNAL_DB_CORRUPTION;
     180             :         }
     181             : 
     182      199003 :         status = posix_eadb_add_list(ea_tdb,mem_ctx, attr_name, fname, fd);
     183      199003 :         if (!NT_STATUS_IS_OK(status)) {
     184           0 :                 talloc_free(mem_ctx);
     185           0 :                 goto done;
     186             :         }
     187             : 
     188      199003 :         if (tdb_store(ea_tdb->tdb, tkey, tdata, TDB_REPLACE) != 0) {
     189           0 :                 status = NT_STATUS_INTERNAL_DB_CORRUPTION;
     190             :         }
     191             : 
     192      199003 : done:
     193      199003 :         tdb_chainunlock(ea_tdb->tdb, tkey);
     194      199003 :         talloc_free(mem_ctx);
     195      199003 :         return status;
     196             : }
     197             : 
     198             : 
     199             : /*
     200             :   delete a xattr
     201             : */
     202      195018 : NTSTATUS delete_posix_eadb_raw(struct tdb_wrap *ea_tdb, const char *attr_name,
     203             :                           const char *fname, int fd)
     204             : {
     205           0 :         TDB_DATA tkey;
     206           0 :         NTSTATUS status;
     207             : 
     208      195018 :         status = get_ea_tdb_key(NULL, attr_name, fname, fd, &tkey);
     209      195018 :         if (!NT_STATUS_IS_OK(status)) {
     210           0 :                 return status;
     211             :         }
     212             : 
     213      195018 :         if (tdb_delete(ea_tdb->tdb, tkey) != 0) {
     214           5 :                 talloc_free(tkey.dptr);
     215           5 :                 return NT_STATUS_INTERNAL_DB_CORRUPTION;
     216             :         }
     217             : 
     218      195013 :         talloc_free(tkey.dptr);
     219      195013 :         return NT_STATUS_OK;
     220             : }
     221             : 
     222             : 
     223             : /*
     224             :   delete all xattrs for a file
     225             : */
     226      208531 : NTSTATUS unlink_posix_eadb_raw(struct tdb_wrap *ea_tdb, const char *fname, int fd)
     227             : {
     228      208531 :         TALLOC_CTX *mem_ctx = talloc_new(ea_tdb);
     229           0 :         DATA_BLOB blob;
     230           0 :         const char *s;
     231           0 :         NTSTATUS status;
     232             : 
     233      208531 :         status = pull_xattr_blob_tdb_raw(ea_tdb, mem_ctx, XATTR_LIST_ATTR,
     234             :                                      fname, fd, 100, &blob);
     235      208531 :         if (!NT_STATUS_IS_OK(status)) {
     236      111312 :                 talloc_free(mem_ctx);
     237      111312 :                 return NT_STATUS_OK;
     238             :         }
     239             : 
     240      195011 :         for (s=(const char *)blob.data; s < (const char *)(blob.data+blob.length); s += strlen(s) + 1) {
     241       97792 :                 delete_posix_eadb_raw(ea_tdb, s, fname, -1);
     242             :         }
     243             : 
     244       97219 :         status = delete_posix_eadb_raw(ea_tdb, XATTR_LIST_ATTR, fname, fd);
     245       97219 :         talloc_free(mem_ctx);
     246       97219 :         return status;
     247             : }
     248             : 
     249             : /*
     250             :   list all xattrs for a file
     251             : */
     252           0 : NTSTATUS list_posix_eadb_raw(struct tdb_wrap *ea_tdb, TALLOC_CTX *mem_ctx,
     253             :                             const char *fname, int fd,
     254             :                             DATA_BLOB *list)
     255             : {
     256           0 :         return pull_xattr_blob_tdb_raw(ea_tdb, mem_ctx, XATTR_LIST_ATTR,
     257             :                                      fname, fd, 100, list);
     258             : }
     259             : 
     260             : #ifdef WITH_NTVFS_FILESERVER
     261     1287112 : NTSTATUS pull_xattr_blob_tdb(struct pvfs_state *pvfs_state,
     262             :                              TALLOC_CTX *mem_ctx,
     263             :                              const char *attr_name,
     264             :                              const char *fname,
     265             :                              int fd,
     266             :                              size_t estimated_size,
     267             :                              DATA_BLOB *blob)
     268             : {
     269     1287112 :         return pull_xattr_blob_tdb_raw(pvfs_state->ea_db,mem_ctx,attr_name,fname,fd,estimated_size,blob);
     270             : }
     271             : 
     272      100837 : NTSTATUS push_xattr_blob_tdb(struct pvfs_state *pvfs_state,
     273             :                              const char *attr_name,
     274             :                              const char *fname,
     275             :                              int fd,
     276             :                              const DATA_BLOB *blob)
     277             : {
     278      100837 :         return push_xattr_blob_tdb_raw(pvfs_state->ea_db, attr_name, fname, fd, blob);
     279             : }
     280             : 
     281             : /*
     282             :   delete a xattr
     283             : */
     284           7 : NTSTATUS delete_posix_eadb(struct pvfs_state *pvfs_state, const char *attr_name,
     285             :                           const char *fname, int fd)
     286             : {
     287           7 :         return delete_posix_eadb_raw(pvfs_state->ea_db,
     288             :                                     attr_name, fname, fd);
     289             : }
     290             : 
     291             : /*
     292             :   delete all xattrs for a file
     293             : */
     294      208531 : NTSTATUS unlink_posix_eadb(struct pvfs_state *pvfs_state, const char *fname)
     295             : {
     296      208531 :         return unlink_posix_eadb_raw(pvfs_state->ea_db, fname, -1);
     297             : }
     298             : 
     299             : #endif

Generated by: LCOV version 1.14