LCOV - code coverage report
Current view: top level - source4/ntvfs/posix - posix_eadb.c (source / functions) Hit Total Coverage
Test: coverage report for master 2f515e9b Lines: 95 118 80.5 %
Date: 2024-04-21 15:09:00 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      200212 : 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         503 :         DATA_BLOB blob;
      39         503 :         TALLOC_CTX *mem_ctx;
      40         503 :         NTSTATUS status;
      41         503 :         size_t len;
      42             : 
      43      200212 :         if (strcmp(attr_name, XATTR_LIST_ATTR) == 0) {
      44       98405 :                 return NT_STATUS_OK;
      45             :         }
      46             : 
      47      101807 :         mem_ctx = talloc_new(ctx);
      48             : 
      49      101807 :         status = pull_xattr_blob_tdb_raw(ea_tdb, mem_ctx, XATTR_LIST_ATTR,
      50             :                                      fname, fd, 100, &blob);
      51      101807 :         if (NT_STATUS_IS_OK(status)) {
      52         135 :                 const char *s;
      53             : 
      54        3991 :                 for (s = (const char *)blob.data;
      55        4874 :                      s < (const char *)(blob.data + blob.length);
      56         883 :                      s += strlen(s) + 1) {
      57        4285 :                         if (strcmp(attr_name, s) == 0) {
      58        3402 :                                 talloc_free(mem_ctx);
      59        3402 :                                 return NT_STATUS_OK;
      60             :                         }
      61             :                 }
      62             :         } else {
      63       97816 :                 blob = data_blob(NULL, 0);
      64             :                 /* No need to parse an empty blob */
      65             :         }
      66             : 
      67       98405 :         len = strlen(attr_name) + 1;
      68             : 
      69       98405 :         blob.data = talloc_realloc(mem_ctx, blob.data, uint8_t, blob.length + len);
      70       98405 :         if (blob.data == NULL) {
      71           0 :                 talloc_free(mem_ctx);
      72           0 :                 return NT_STATUS_NO_MEMORY;
      73             :         }
      74       98405 :         memcpy(blob.data + blob.length, attr_name, len);
      75       98405 :         blob.length += len;
      76             : 
      77       98405 :         status = push_xattr_blob_tdb_raw(ea_tdb, XATTR_LIST_ATTR, fname, fd, &blob);
      78       98405 :         talloc_free(mem_ctx);
      79             : 
      80       98405 :         return status;
      81             : }
      82             : 
      83             : /*
      84             :   form a key for using in the ea_tdb
      85             : */
      86     1994151 : 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         824 :         struct stat st;
      92     1994151 :         size_t len = strlen(attr_name);
      93             : 
      94     1994151 :         if (fd == -1) {
      95     1500072 :                 if (stat(fname, &st) == -1) {
      96           0 :                         return NT_STATUS_NOT_FOUND;
      97             :                 }
      98             :         } else {
      99      494079 :                 if (fstat(fd, &st) == -1) {
     100           0 :                         return NT_STATUS_NOT_FOUND;
     101             :                 }
     102             :         }
     103             : 
     104     1994151 :         key->dptr = talloc_array(mem_ctx, uint8_t, 16 + len);
     105     1994151 :         if (key->dptr == NULL) {
     106           0 :                 return NT_STATUS_NO_MEMORY;
     107             :         }
     108     1994151 :         key->dsize = 16 + len;
     109             : 
     110     1994151 :         SBVAL(key->dptr, 0, st.st_dev);
     111     1994151 :         SBVAL(key->dptr, 8, st.st_ino);
     112     1994151 :         memcpy(key->dptr+16, attr_name, len);
     113             : 
     114     1994151 :         return NT_STATUS_OK;
     115             : }
     116             : 
     117             : 
     118             : 
     119             : /*
     120             :   pull a xattr as a blob, using the ea_tdb_context tdb
     121             : */
     122     1598894 : 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         321 :         TDB_DATA tkey, tdata;
     131         321 :         NTSTATUS status;
     132             : 
     133     1598894 :         status = get_ea_tdb_key(mem_ctx, attr_name, fname, fd, &tkey);
     134     1598894 :         if (!NT_STATUS_IS_OK(status)) {
     135           0 :                 return status;
     136             :         }
     137             : 
     138     1598894 :         tdata = tdb_fetch(ea_tdb->tdb, tkey);
     139     1598894 :         if (tdata.dptr == NULL) {
     140     1150589 :                 return NT_STATUS_NOT_FOUND;
     141             :         }
     142             : 
     143      448305 :         *blob = data_blob_talloc(mem_ctx, tdata.dptr, tdata.dsize);
     144      448305 :         free(tdata.dptr);
     145      448305 :         if (blob->data == NULL) {
     146           0 :                 return NT_STATUS_NO_MEMORY;
     147             :         }
     148             : 
     149      448305 :         return NT_STATUS_OK;
     150             : }
     151             : 
     152             : /*
     153             :   push a xattr as a blob, using ea_tdb
     154             : */
     155      200212 : 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         503 :         TDB_DATA tkey, tdata;
     162         503 :         NTSTATUS status;
     163      200212 :         TALLOC_CTX *mem_ctx = talloc_new(ea_tdb);
     164      200212 :         if (!mem_ctx) {
     165           0 :                 return NT_STATUS_NO_MEMORY;
     166             :         }
     167             : 
     168      200212 :         status = get_ea_tdb_key(mem_ctx, attr_name, fname, fd, &tkey);
     169      200212 :         if (!NT_STATUS_IS_OK(status)) {
     170           0 :                 talloc_free(mem_ctx);
     171           0 :                 return status;
     172             :         }
     173             : 
     174      200212 :         tdata.dptr = blob->data;
     175      200212 :         tdata.dsize = blob->length;
     176             : 
     177      200212 :         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      200212 :         status = posix_eadb_add_list(ea_tdb,mem_ctx, attr_name, fname, fd);
     183      200212 :         if (!NT_STATUS_IS_OK(status)) {
     184           0 :                 talloc_free(mem_ctx);
     185           0 :                 goto done;
     186             :         }
     187             : 
     188      200212 :         if (tdb_store(ea_tdb->tdb, tkey, tdata, TDB_REPLACE) != 0) {
     189           0 :                 status = NT_STATUS_INTERNAL_DB_CORRUPTION;
     190             :         }
     191             : 
     192      200212 : done:
     193      200212 :         tdb_chainunlock(ea_tdb->tdb, tkey);
     194      200212 :         talloc_free(mem_ctx);
     195      200212 :         return status;
     196             : }
     197             : 
     198             : 
     199             : /*
     200             :   delete a xattr
     201             : */
     202      195045 : 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      195045 :         status = get_ea_tdb_key(NULL, attr_name, fname, fd, &tkey);
     209      195045 :         if (!NT_STATUS_IS_OK(status)) {
     210           0 :                 return status;
     211             :         }
     212             : 
     213      195045 :         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      195040 :         talloc_free(tkey.dptr);
     219      195040 :         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      111302 :                 talloc_free(mem_ctx);
     237      111302 :                 return NT_STATUS_OK;
     238             :         }
     239             : 
     240      195038 :         for (s=(const char *)blob.data; s < (const char *)(blob.data+blob.length); s += strlen(s) + 1) {
     241       97809 :                 delete_posix_eadb_raw(ea_tdb, s, fname, -1);
     242             :         }
     243             : 
     244       97229 :         status = delete_posix_eadb_raw(ea_tdb, XATTR_LIST_ATTR, fname, fd);
     245       97229 :         talloc_free(mem_ctx);
     246       97229 :         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     1288554 : 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     1288554 :         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