LCOV - code coverage report
Current view: top level - source3/modules - vfs_xattr_tdb.c (source / functions) Hit Total Coverage
Test: coverage report for master 2b515b7d Lines: 239 315 75.9 %
Date: 2024-02-28 12:06:22 Functions: 16 17 94.1 %

          Line data    Source code
       1             : /*
       2             :  * Store posix-level xattrs in a tdb
       3             :  *
       4             :  * Copyright (C) Volker Lendecke, 2007
       5             :  * Copyright (C) Andrew Bartlett, 2012
       6             :  *
       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.
      11             :  *
      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.
      16             :  *
      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/>.
      19             :  */
      20             : 
      21             : #include "includes.h"
      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"
      27             : #include "lib/util/tevent_unix.h"
      28             : 
      29             : #undef DBGC_CLASS
      30             : #define DBGC_CLASS DBGC_VFS
      31             : 
      32             : struct xattr_tdb_config {
      33             :         struct db_context *db;
      34             :         bool ignore_user_xattr;
      35             : };
      36             : 
      37             : static bool xattr_tdb_init(struct vfs_handle_struct *handle,
      38             :                            struct xattr_tdb_config **_config);
      39             : 
      40        1535 : static bool is_user_xattr(const char *xattr_name)
      41             : {
      42           0 :         int match;
      43             : 
      44        1535 :         match = strncmp(xattr_name, "user.", strlen("user."));
      45        1535 :         return (match == 0);
      46             : }
      47             : 
      48       10068 : static int xattr_tdb_get_file_id(struct vfs_handle_struct *handle,
      49             :                                 const char *path, struct file_id *id)
      50             : {
      51           0 :         int ret;
      52       10068 :         TALLOC_CTX *frame = talloc_stackframe();
      53           0 :         struct smb_filename *smb_fname;
      54             : 
      55       10068 :         smb_fname = synthetic_smb_fname(frame,
      56             :                                         path,
      57             :                                         NULL,
      58             :                                         NULL,
      59             :                                         0,
      60             :                                         0);
      61       10068 :         if (smb_fname == NULL) {
      62           0 :                 TALLOC_FREE(frame);
      63           0 :                 errno = ENOMEM;
      64           0 :                 return -1;
      65             :         }
      66             : 
      67       10068 :         ret = SMB_VFS_NEXT_STAT(handle, smb_fname);
      68             : 
      69       10068 :         if (ret == -1) {
      70           0 :                 TALLOC_FREE(frame); 
      71           0 :                 return -1;
      72             :         }
      73             : 
      74       10068 :         *id = SMB_VFS_NEXT_FILE_ID_CREATE(handle, &smb_fname->st);
      75       10068 :         TALLOC_FREE(frame);
      76       10068 :         return 0;
      77             : }
      78             : 
      79             : struct xattr_tdb_getxattrat_state {
      80             :         struct vfs_aio_state vfs_aio_state;
      81             :         ssize_t xattr_size;
      82             :         uint8_t *xattr_value;
      83             : };
      84             : 
      85             : static void xattr_tdb_getxattrat_done(struct tevent_req *subreq);
      86             : 
      87       10068 : static struct tevent_req *xattr_tdb_getxattrat_send(
      88             :                         TALLOC_CTX *mem_ctx,
      89             :                         struct tevent_context *ev,
      90             :                         struct vfs_handle_struct *handle,
      91             :                         files_struct *dir_fsp,
      92             :                         const struct smb_filename *smb_fname,
      93             :                         const char *xattr_name,
      94             :                         size_t alloc_hint)
      95             : {
      96       10068 :         struct xattr_tdb_config *config = NULL;
      97       10068 :         struct tevent_req *req = NULL;
      98       10068 :         struct tevent_req *subreq = NULL;
      99       10068 :         struct xattr_tdb_getxattrat_state *state = NULL;
     100       10068 :         struct smb_filename *cwd = NULL;
     101           0 :         struct file_id id;
     102           0 :         int ret;
     103           0 :         int error;
     104           0 :         int cwd_ret;
     105           0 :         DATA_BLOB xattr_blob;
     106             : 
     107       10068 :         if (!xattr_tdb_init(handle, &config)) {
     108           0 :                 return NULL;
     109             :         }
     110             : 
     111       10068 :         req = tevent_req_create(mem_ctx, &state,
     112             :                                 struct xattr_tdb_getxattrat_state);
     113       10068 :         if (req == NULL) {
     114           0 :                 return NULL;
     115             :         }
     116       10068 :         state->xattr_size = -1;
     117             : 
     118       10068 :         if (config->ignore_user_xattr && is_user_xattr(xattr_name)) {
     119           0 :                 subreq = SMB_VFS_NEXT_GETXATTRAT_SEND(state,
     120             :                                                       ev,
     121             :                                                       handle,
     122             :                                                       dir_fsp,
     123             :                                                       smb_fname,
     124             :                                                       xattr_name,
     125             :                                                       alloc_hint);
     126           0 :                 if (tevent_req_nomem(subreq, req)) {
     127           0 :                         return tevent_req_post(req, ev);
     128             :                 }
     129           0 :                 tevent_req_set_callback(subreq, xattr_tdb_getxattrat_done, req);
     130           0 :                 return req;
     131             :         }
     132             : 
     133       10068 :         cwd = SMB_VFS_GETWD(dir_fsp->conn, state);
     134       10068 :         if (tevent_req_nomem(cwd, req)) {
     135           0 :                 return tevent_req_post(req, ev);
     136             :         }
     137             : 
     138       10068 :         ret = SMB_VFS_CHDIR(dir_fsp->conn, dir_fsp->fsp_name);
     139       10068 :         if (ret != 0) {
     140           0 :                 tevent_req_error(req, errno);
     141           0 :                 return tevent_req_post(req, ev);
     142             :         }
     143             : 
     144       10068 :         ret = xattr_tdb_get_file_id(handle, smb_fname->base_name, &id);
     145       10068 :         error = errno;
     146             : 
     147       10068 :         cwd_ret = SMB_VFS_CHDIR(dir_fsp->conn, cwd);
     148       10068 :         SMB_ASSERT(cwd_ret == 0);
     149             : 
     150       10068 :         if (ret == -1) {
     151           0 :                 tevent_req_error(req, error);
     152           0 :                 return tevent_req_post(req, ev);
     153             :         }
     154             : 
     155       10068 :         state->xattr_size = xattr_tdb_getattr(config->db,
     156             :                                               state,
     157             :                                               &id,
     158             :                                               xattr_name,
     159             :                                               &xattr_blob);
     160       10068 :         if (state->xattr_size == -1) {
     161          60 :                 tevent_req_error(req, errno);
     162          60 :                 return tevent_req_post(req, ev);
     163             :         }
     164             : 
     165       10008 :         if (alloc_hint == 0) {
     166             :                 /*
     167             :                  * The caller only wants to know the size.
     168             :                  */
     169           0 :                 tevent_req_done(req);
     170           0 :                 return tevent_req_post(req, ev);
     171             :         }
     172             : 
     173       10008 :         if (state->xattr_size == 0) {
     174             :                 /*
     175             :                  * There's no data.
     176             :                  */
     177           0 :                 tevent_req_done(req);
     178           0 :                 return tevent_req_post(req, ev);
     179             :         }
     180             : 
     181       10008 :         if (xattr_blob.length > alloc_hint) {
     182             :                 /*
     183             :                  * The data doesn't fit.
     184             :                  */
     185           0 :                 state->xattr_size = -1;
     186           0 :                 tevent_req_error(req, ERANGE);
     187           0 :                 return tevent_req_post(req, ev);
     188             :         }
     189             : 
     190             :         /*
     191             :          * take the whole blob.
     192             :          */
     193       10008 :         state->xattr_value = xattr_blob.data;
     194             : 
     195       10008 :         tevent_req_done(req);
     196       10008 :         return tevent_req_post(req, ev);
     197             : }
     198             : 
     199           0 : static void xattr_tdb_getxattrat_done(struct tevent_req *subreq)
     200             : {
     201           0 :         struct tevent_req *req = tevent_req_callback_data(
     202             :                 subreq, struct tevent_req);
     203           0 :         struct xattr_tdb_getxattrat_state *state = tevent_req_data(
     204             :                 req, struct xattr_tdb_getxattrat_state);
     205             : 
     206           0 :         state->xattr_size = SMB_VFS_NEXT_GETXATTRAT_RECV(subreq,
     207             :                                                          &state->vfs_aio_state,
     208             :                                                          state,
     209             :                                                          &state->xattr_value);
     210           0 :         TALLOC_FREE(subreq);
     211           0 :         if (state->xattr_size == -1) {
     212           0 :                 tevent_req_error(req, state->vfs_aio_state.error);
     213           0 :                 return;
     214             :         }
     215             : 
     216           0 :         tevent_req_done(req);
     217             : }
     218             : 
     219             : 
     220       10068 : static ssize_t xattr_tdb_getxattrat_recv(struct tevent_req *req,
     221             :                                          struct vfs_aio_state *aio_state,
     222             :                                          TALLOC_CTX *mem_ctx,
     223             :                                          uint8_t **xattr_value)
     224             : {
     225       10068 :         struct xattr_tdb_getxattrat_state *state = tevent_req_data(
     226             :                 req, struct xattr_tdb_getxattrat_state);
     227           0 :         ssize_t xattr_size;
     228             : 
     229       10068 :         if (tevent_req_is_unix_error(req, &aio_state->error)) {
     230          60 :                 tevent_req_received(req);
     231          60 :                 return -1;
     232             :         }
     233             : 
     234       10008 :         *aio_state = state->vfs_aio_state;
     235       10008 :         xattr_size = state->xattr_size;
     236       10008 :         if (xattr_value != NULL) {
     237       10008 :                 *xattr_value = talloc_move(mem_ctx, &state->xattr_value);
     238             :         }
     239             : 
     240       10008 :         tevent_req_received(req);
     241       10008 :         return xattr_size;
     242             : }
     243             : 
     244    25006084 : static ssize_t xattr_tdb_fgetxattr(struct vfs_handle_struct *handle,
     245             :                                    struct files_struct *fsp,
     246             :                                    const char *name, void *value, size_t size)
     247             : {
     248    25006084 :         struct xattr_tdb_config *config = NULL;
     249       86577 :         SMB_STRUCT_STAT sbuf;
     250       86577 :         struct file_id id;
     251       86577 :         ssize_t xattr_size;
     252       86577 :         DATA_BLOB blob;
     253    25006084 :         TALLOC_CTX *frame = NULL;
     254             : 
     255    25006084 :         if (!xattr_tdb_init(handle, &config)) {
     256           0 :                 return -1;
     257             :         }
     258             : 
     259    25006084 :         if (config->ignore_user_xattr && is_user_xattr(name)) {
     260         216 :                 return SMB_VFS_NEXT_FGETXATTR(
     261             :                         handle, fsp, name, value, size);
     262             :         }
     263             : 
     264    25005868 :         if (SMB_VFS_NEXT_FSTAT(handle, fsp, &sbuf) == -1) {
     265         186 :                 return -1;
     266             :         }
     267             : 
     268    25005682 :         frame = talloc_stackframe();
     269             : 
     270    25005682 :         id = SMB_VFS_NEXT_FILE_ID_CREATE(handle, &sbuf);
     271             : 
     272    25005682 :         xattr_size = xattr_tdb_getattr(config->db, frame, &id, name, &blob);
     273    25005682 :         if (xattr_size < 0) {
     274     7825730 :                 errno = ENOATTR;
     275     7825730 :                 TALLOC_FREE(frame);
     276     7825730 :                 return -1;
     277             :         }
     278             : 
     279    17179952 :         if (size == 0) {
     280          18 :                 TALLOC_FREE(frame);
     281          18 :                 return xattr_size;
     282             :         }
     283             : 
     284    17179934 :         if (blob.length > size) {
     285         132 :                 TALLOC_FREE(frame);
     286         132 :                 errno = ERANGE;
     287         132 :                 return -1;
     288             :         }
     289    17179802 :         memcpy(value, blob.data, xattr_size);
     290    17179802 :         TALLOC_FREE(frame);
     291    17123328 :         return xattr_size;
     292             : }
     293             : 
     294      847321 : static int xattr_tdb_fsetxattr(struct vfs_handle_struct *handle,
     295             :                                struct files_struct *fsp,
     296             :                                const char *name, const void *value,
     297             :                                size_t size, int flags)
     298             : {
     299      847321 :         struct xattr_tdb_config *config = NULL;
     300        2620 :         SMB_STRUCT_STAT sbuf;
     301        2620 :         struct file_id id;
     302        2620 :         int ret;
     303             : 
     304      847321 :         if (!xattr_tdb_init(handle, &config)) {
     305           0 :                 return -1;
     306             :         }
     307             : 
     308      847321 :         if (config->ignore_user_xattr && is_user_xattr(name)) {
     309          30 :                 return SMB_VFS_NEXT_FSETXATTR(
     310             :                         handle, fsp, name, value, size, flags);
     311             :         }
     312             : 
     313      847291 :         if (SMB_VFS_NEXT_FSTAT(handle, fsp, &sbuf) == -1) {
     314           0 :                 return -1;
     315             :         }
     316             : 
     317      847291 :         id = SMB_VFS_NEXT_FILE_ID_CREATE(handle, &sbuf);
     318             : 
     319      847291 :         ret = xattr_tdb_setattr(config->db, &id, name, value, size, flags);
     320      847291 :         return ret;
     321             : 
     322             : }
     323             : 
     324      749640 : static ssize_t xattr_tdb_flistxattr(struct vfs_handle_struct *handle,
     325             :                                     struct files_struct *fsp, char *list,
     326             :                                     size_t size)
     327             : {
     328      749640 :         struct xattr_tdb_config *config = NULL;
     329        1071 :         SMB_STRUCT_STAT sbuf;
     330        1071 :         struct file_id id;
     331        1071 :         ssize_t backend_size;
     332        1071 :         ssize_t ret;
     333             : 
     334      749640 :         if (!xattr_tdb_init(handle, &config)) {
     335           0 :                 return -1;
     336             :         }
     337             : 
     338      749640 :         if (SMB_VFS_NEXT_FSTAT(handle, fsp, &sbuf) == -1) {
     339           0 :                 return -1;
     340             :         }
     341             : 
     342      749640 :         id = SMB_VFS_NEXT_FILE_ID_CREATE(handle, &sbuf);
     343             : 
     344      749640 :         ret = xattr_tdb_listattr(config->db, &id, list, size);
     345      749640 :         if (ret == -1) {
     346           0 :                 return -1;
     347             :         }
     348      749640 :         if (ret == size) {
     349           4 :                 return ret;
     350             :         }
     351      749636 :         if (!config->ignore_user_xattr) {
     352      748547 :                 return ret;
     353             :         }
     354          18 :         SMB_ASSERT(ret < size);
     355             : 
     356          18 :         backend_size = SMB_VFS_NEXT_FLISTXATTR(
     357             :                 handle, fsp, list + ret, size - ret);
     358          18 :         if (backend_size == -1) {
     359           0 :                 return -1;
     360             :         }
     361             : 
     362          18 :         return ret + backend_size;
     363             : }
     364             : 
     365        2092 : static int xattr_tdb_fremovexattr(struct vfs_handle_struct *handle,
     366             :                                   struct files_struct *fsp, const char *name)
     367             : {
     368        2092 :         struct xattr_tdb_config *config = NULL;
     369         216 :         SMB_STRUCT_STAT sbuf;
     370         216 :         struct file_id id;
     371             : 
     372        2092 :         if (!xattr_tdb_init(handle, &config)) {
     373           0 :                 return -1;
     374             :         }
     375             : 
     376        2092 :         if (config->ignore_user_xattr && is_user_xattr(name)) {
     377           3 :                 return SMB_VFS_NEXT_FREMOVEXATTR(handle, fsp, name);
     378             :         }
     379             : 
     380        2089 :         if (SMB_VFS_NEXT_FSTAT(handle, fsp, &sbuf) == -1) {
     381           0 :                 return -1;
     382             :         }
     383             : 
     384        2089 :         id = SMB_VFS_NEXT_FILE_ID_CREATE(handle, &sbuf);
     385             : 
     386        2089 :         return xattr_tdb_removeattr(config->db, &id, name);
     387             : }
     388             : 
     389             : /*
     390             :  * Destructor for the VFS private data
     391             :  */
     392             : 
     393       63642 : static void config_destructor(void **data)
     394             : {
     395       63642 :         struct xattr_tdb_config **config = (struct xattr_tdb_config **)data;
     396       63642 :         TALLOC_FREE((*config)->db);
     397       63642 : }
     398             : 
     399             : /*
     400             :  * Open the tdb file upon VFS_CONNECT
     401             :  */
     402             : 
     403    33126930 : static bool xattr_tdb_init(struct vfs_handle_struct *handle,
     404             :                            struct xattr_tdb_config **_config)
     405             : {
     406    33126930 :         struct xattr_tdb_config *config = NULL;
     407      121973 :         const char *dbname;
     408      121973 :         char *def_dbname;
     409             : 
     410    33126930 :         if (SMB_VFS_HANDLE_TEST_DATA(handle)) {
     411    33063266 :                 SMB_VFS_HANDLE_GET_DATA(handle, config, struct xattr_tdb_config,
     412      121099 :                                         return false);
     413    33063266 :                 if (_config != NULL) {
     414    33063266 :                         *_config = config;
     415             :                 }
     416    33063266 :                 return true;
     417             :         }
     418             : 
     419       63664 :         config = talloc_zero(handle->conn, struct xattr_tdb_config);
     420       63664 :         if (config == NULL) {
     421           0 :                 errno = ENOMEM;
     422           0 :                 goto error;
     423             :         }
     424             : 
     425       63664 :         def_dbname = state_path(talloc_tos(), "xattr.tdb");
     426       63664 :         if (def_dbname == NULL) {
     427           0 :                 errno = ENOSYS;
     428           0 :                 goto error;
     429             :         }
     430             : 
     431       63664 :         dbname = lp_parm_const_string(SNUM(handle->conn),
     432             :                                       "xattr_tdb",
     433             :                                       "file",
     434             :                                       def_dbname);
     435             : 
     436             :         /* now we know dbname is not NULL */
     437             : 
     438       63664 :         become_root();
     439       63664 :         config->db = db_open(handle, dbname, 0, TDB_DEFAULT, O_RDWR|O_CREAT, 0600,
     440             :                              DBWRAP_LOCK_ORDER_2, DBWRAP_FLAG_NONE);
     441       63664 :         unbecome_root();
     442             : 
     443       63664 :         if (config->db == NULL) {
     444             : #if defined(ENOTSUP)
     445           0 :                 errno = ENOTSUP;
     446             : #else
     447             :                 errno = ENOSYS;
     448             : #endif
     449           0 :                 TALLOC_FREE(def_dbname);
     450           0 :                 goto error;
     451             :         }
     452       63664 :         TALLOC_FREE(def_dbname);
     453             : 
     454       63664 :         config->ignore_user_xattr = lp_parm_bool(
     455       63664 :                 SNUM(handle->conn), "xattr_tdb", "ignore_user_xattr", false);
     456             : 
     457       63664 :         SMB_VFS_HANDLE_SET_DATA(handle, config, config_destructor,
     458         874 :                                 struct xattr_tdb_config, return false);
     459             : 
     460       63664 :         if (_config != NULL) {
     461        1320 :                 *_config = config;
     462             :         }
     463       62790 :         return true;
     464             : 
     465           0 : error:
     466           0 :         DBG_WARNING("Failed to initialize config: %s\n", strerror(errno));
     467           0 :         lp_do_parameter(SNUM(handle->conn), "ea support", "False");
     468           0 :         return false;
     469             : }
     470             : 
     471     6265941 : static int xattr_tdb_openat(struct vfs_handle_struct *handle,
     472             :                             const struct files_struct *dirfsp,
     473             :                             const struct smb_filename *smb_fname,
     474             :                             struct files_struct *fsp,
     475             :                             const struct vfs_open_how *how)
     476             : {
     477     6265941 :         struct xattr_tdb_config *config = NULL;
     478       30220 :         SMB_STRUCT_STAT sbuf;
     479       30220 :         int fd;
     480       30220 :         int ret;
     481             : 
     482     6265941 :         if (!xattr_tdb_init(handle, &config)) {
     483           0 :                 return -1;
     484             :         }
     485             : 
     486     6265941 :         fd = SMB_VFS_NEXT_OPENAT(handle,
     487             :                                  dirfsp,
     488             :                                  smb_fname,
     489             :                                  fsp,
     490             :                                  how);
     491     6265941 :         if (fd == -1) {
     492     1808472 :                 return -1;
     493             :         }
     494             : 
     495     4453293 :         if ((how->flags & (O_CREAT|O_EXCL)) != (O_CREAT|O_EXCL)) {
     496     4268116 :                 return fd;
     497             :         }
     498             : 
     499             :         /*
     500             :          * We know we used O_CREAT|O_EXCL and it worked.
     501             :          * We must have created the file.
     502             :          */
     503             : 
     504      159411 :         fsp_set_fd(fsp, fd);
     505      159411 :         ret = SMB_VFS_FSTAT(fsp, &sbuf);
     506      159411 :         fsp_set_fd(fsp, -1);
     507      159411 :         if (ret == -1) {
     508             :                 /* Can't happen... */
     509           0 :                 DBG_WARNING("SMB_VFS_FSTAT failed on file %s (%s)\n",
     510             :                             smb_fname_str_dbg(smb_fname),
     511             :                             strerror(errno));
     512           0 :                 return -1;
     513             :         }
     514             : 
     515      159411 :         fsp->file_id = SMB_VFS_FILE_ID_CREATE(fsp->conn, &sbuf);
     516             : 
     517      159411 :         xattr_tdb_remove_all_attrs(config->db, &fsp->file_id);
     518             : 
     519      159411 :         return fd;
     520             : }
     521             : 
     522       12016 : static int xattr_tdb_mkdirat(vfs_handle_struct *handle,
     523             :                 struct files_struct *dirfsp,
     524             :                 const struct smb_filename *smb_fname,
     525             :                 mode_t mode)
     526             : {
     527       12016 :         struct xattr_tdb_config *config = NULL;
     528          68 :         struct file_id fileid;
     529       12016 :         struct stat_ex sbuf = { .st_ex_nlink = 0, };
     530          68 :         int ret;
     531             : 
     532       12016 :         if (!xattr_tdb_init(handle, &config)) {
     533           0 :                 return -1;
     534             :         }
     535             : 
     536       12016 :         ret = SMB_VFS_NEXT_MKDIRAT(handle,
     537             :                                 dirfsp,
     538             :                                 smb_fname,
     539             :                                 mode);
     540       12016 :         if (ret < 0) {
     541         277 :                 return ret;
     542             :         }
     543             : 
     544       11739 :         ret = SMB_VFS_NEXT_FSTATAT(
     545             :                 handle, dirfsp, smb_fname, &sbuf, AT_SYMLINK_NOFOLLOW);
     546             : 
     547       11739 :         if (ret == -1) {
     548             :                 /* Rename race. Let upper level take care of it. */
     549           0 :                 return -1;
     550             :         }
     551       11739 :         if (!S_ISDIR(sbuf.st_ex_mode)) {
     552             :                 /* Rename race. Let upper level take care of it. */
     553           0 :                 return -1;
     554             :         }
     555             : 
     556       11739 :         fileid = SMB_VFS_FILE_ID_CREATE(handle->conn, &sbuf);
     557             : 
     558       11739 :         xattr_tdb_remove_all_attrs(config->db, &fileid);
     559       11739 :         return 0;
     560             : }
     561             : 
     562             : /*
     563             :  * On unlink we need to delete the tdb record
     564             :  */
     565      171424 : static int xattr_tdb_unlinkat(vfs_handle_struct *handle,
     566             :                         struct files_struct *dirfsp,
     567             :                         const struct smb_filename *smb_fname,
     568             :                         int flags)
     569             : {
     570      171424 :         struct xattr_tdb_config *config = NULL;
     571      171424 :         struct smb_filename *smb_fname_tmp = NULL;
     572      171424 :         struct smb_filename *full_fname = NULL;
     573         337 :         struct file_id id;
     574      171424 :         int ret = -1;
     575      171424 :         bool remove_record = false;
     576      171424 :         TALLOC_CTX *frame = NULL;
     577             : 
     578      171424 :         if (!xattr_tdb_init(handle, &config)) {
     579           0 :                 return -1;
     580             :         }
     581             : 
     582      171424 :         frame = talloc_stackframe();
     583             : 
     584      171424 :         smb_fname_tmp = cp_smb_filename(frame, smb_fname);
     585      171424 :         if (smb_fname_tmp == NULL) {
     586           0 :                 TALLOC_FREE(frame);
     587           0 :                 errno = ENOMEM;
     588           0 :                 return -1;
     589             :         }
     590             : 
     591             :         /*
     592             :          * TODO: use SMB_VFS_STATX() once we have that
     593             :          */
     594             : 
     595      171424 :         full_fname = full_path_from_dirfsp_atname(frame,
     596             :                                                   dirfsp,
     597             :                                                   smb_fname);
     598      171424 :         if (full_fname == NULL) {
     599           0 :                 goto out;
     600             :         }
     601             : 
     602      171424 :         if (full_fname->flags & SMB_FILENAME_POSIX_PATH) {
     603        1345 :                 ret = SMB_VFS_NEXT_LSTAT(handle, full_fname);
     604             :         } else {
     605      170079 :                 ret = SMB_VFS_NEXT_STAT(handle, full_fname);
     606      170079 :                 if (ret == -1 && (errno == ENOENT || errno == ELOOP)) {
     607         295 :                         if (VALID_STAT(smb_fname->st) &&
     608           3 :                                         S_ISLNK(smb_fname->st.st_ex_mode)) {
     609             :                                 /*
     610             :                                  * Original name was a link - Could be
     611             :                                  * trying to remove a dangling symlink.
     612             :                                  */
     613           3 :                                 ret = SMB_VFS_NEXT_LSTAT(handle, full_fname);
     614             :                         }
     615             :                 }
     616             :         }
     617      171424 :         if (ret == -1) {
     618         292 :                 goto out;
     619             :         }
     620      171132 :         smb_fname_tmp->st = full_fname->st;
     621             : 
     622      171132 :         if (flags & AT_REMOVEDIR) {
     623             :                 /* Always remove record when removing a directory succeeds. */
     624       11172 :                 remove_record = true;
     625             :         } else {
     626      159896 :                 if (smb_fname_tmp->st.st_ex_nlink == 1) {
     627             :                         /* Only remove record on last link to file. */
     628      159852 :                         remove_record = true;
     629             :                 }
     630             :         }
     631             : 
     632      171132 :         ret = SMB_VFS_NEXT_UNLINKAT(handle,
     633             :                                 dirfsp,
     634             :                                 smb_fname_tmp,
     635             :                                 flags);
     636             : 
     637      171132 :         if (ret == -1) {
     638          20 :                 goto out;
     639             :         }
     640             : 
     641      171112 :         if (!remove_record) {
     642          44 :                 goto out;
     643             :         }
     644             : 
     645      171068 :         id = SMB_VFS_NEXT_FILE_ID_CREATE(handle, &smb_fname_tmp->st);
     646             : 
     647      171068 :         xattr_tdb_remove_all_attrs(config->db, &id);
     648             : 
     649      171424 :  out:
     650      171424 :         TALLOC_FREE(frame);
     651      171087 :         return ret;
     652             : }
     653             : 
     654       63690 : static int xattr_tdb_connect(vfs_handle_struct *handle, const char *service,
     655             :                           const char *user)
     656             : {
     657       63690 :         char *sname = NULL;
     658         874 :         int res, snum;
     659             : 
     660       63690 :         res = SMB_VFS_NEXT_CONNECT(handle, service, user);
     661       63690 :         if (res < 0) {
     662          18 :                 return res;
     663             :         }
     664             : 
     665       63672 :         snum = find_service(talloc_tos(), service, &sname);
     666       63672 :         if (snum == -1 || sname == NULL) {
     667             :                 /*
     668             :                  * Should not happen, but we should not fail just *here*.
     669             :                  */
     670        1318 :                 return 0;
     671             :         }
     672             : 
     673       62344 :         if (!xattr_tdb_init(handle, NULL)) {
     674           0 :                 DEBUG(5, ("Could not init xattr tdb\n"));
     675           0 :                 lp_do_parameter(snum, "ea support", "False");
     676           0 :                 return 0;
     677             :         }
     678             : 
     679       62344 :         lp_do_parameter(snum, "ea support", "True");
     680             : 
     681       62344 :         return 0;
     682             : }
     683             : 
     684             : static struct vfs_fn_pointers vfs_xattr_tdb_fns = {
     685             :         .getxattrat_send_fn = xattr_tdb_getxattrat_send,
     686             :         .getxattrat_recv_fn = xattr_tdb_getxattrat_recv,
     687             :         .fgetxattr_fn = xattr_tdb_fgetxattr,
     688             :         .fsetxattr_fn = xattr_tdb_fsetxattr,
     689             :         .flistxattr_fn = xattr_tdb_flistxattr,
     690             :         .fremovexattr_fn = xattr_tdb_fremovexattr,
     691             :         .openat_fn = xattr_tdb_openat,
     692             :         .mkdirat_fn = xattr_tdb_mkdirat,
     693             :         .unlinkat_fn = xattr_tdb_unlinkat,
     694             :         .connect_fn = xattr_tdb_connect,
     695             : };
     696             : 
     697             : static_decl_vfs;
     698       32780 : NTSTATUS vfs_xattr_tdb_init(TALLOC_CTX *ctx)
     699             : {
     700       32780 :         return smb_register_vfs(SMB_VFS_INTERFACE_VERSION, "xattr_tdb",
     701             :                                 &vfs_xattr_tdb_fns);
     702             : }

Generated by: LCOV version 1.14