LCOV - code coverage report
Current view: top level - source3/modules - vfs_xattr_tdb.c (source / functions) Hit Total Coverage
Test: coverage report for v4-17-test 1498b464 Lines: 146 291 50.2 %
Date: 2024-06-13 04:01:37 Functions: 12 17 70.6 %

          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           0 : static bool is_user_xattr(const char *xattr_name)
      41             : {
      42             :         int match;
      43             : 
      44           0 :         match = strncmp(xattr_name, "user.", strlen("user."));
      45           0 :         return (match == 0);
      46             : }
      47             : 
      48           0 : static int xattr_tdb_get_file_id(struct vfs_handle_struct *handle,
      49             :                                 const char *path, struct file_id *id)
      50             : {
      51             :         int ret;
      52           0 :         TALLOC_CTX *frame = talloc_stackframe();
      53             :         struct smb_filename *smb_fname;
      54             : 
      55           0 :         smb_fname = synthetic_smb_fname(frame,
      56             :                                         path,
      57             :                                         NULL,
      58             :                                         NULL,
      59             :                                         0,
      60             :                                         0);
      61           0 :         if (smb_fname == NULL) {
      62           0 :                 TALLOC_FREE(frame);
      63           0 :                 errno = ENOMEM;
      64           0 :                 return -1;
      65             :         }
      66             : 
      67           0 :         ret = SMB_VFS_NEXT_STAT(handle, smb_fname);
      68             : 
      69           0 :         if (ret == -1) {
      70           0 :                 TALLOC_FREE(frame); 
      71           0 :                 return -1;
      72             :         }
      73             : 
      74           0 :         *id = SMB_VFS_NEXT_FILE_ID_CREATE(handle, &smb_fname->st);
      75           0 :         TALLOC_FREE(frame);
      76           0 :         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           0 : 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           0 :         struct xattr_tdb_config *config = NULL;
      97           0 :         struct tevent_req *req = NULL;
      98           0 :         struct tevent_req *subreq = NULL;
      99           0 :         struct xattr_tdb_getxattrat_state *state = NULL;
     100           0 :         struct smb_filename *cwd = NULL;
     101             :         struct file_id id;
     102             :         int ret;
     103             :         int error;
     104             :         int cwd_ret;
     105             :         DATA_BLOB xattr_blob;
     106             : 
     107           0 :         if (!xattr_tdb_init(handle, &config)) {
     108           0 :                 return NULL;
     109             :         }
     110             : 
     111           0 :         req = tevent_req_create(mem_ctx, &state,
     112             :                                 struct xattr_tdb_getxattrat_state);
     113           0 :         if (req == NULL) {
     114           0 :                 return NULL;
     115             :         }
     116           0 :         state->xattr_size = -1;
     117             : 
     118           0 :         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           0 :         cwd = SMB_VFS_GETWD(dir_fsp->conn, state);
     134           0 :         if (tevent_req_nomem(cwd, req)) {
     135           0 :                 return tevent_req_post(req, ev);
     136             :         }
     137             : 
     138           0 :         ret = SMB_VFS_CHDIR(dir_fsp->conn, dir_fsp->fsp_name);
     139           0 :         if (ret != 0) {
     140           0 :                 tevent_req_error(req, errno);
     141           0 :                 return tevent_req_post(req, ev);
     142             :         }
     143             : 
     144           0 :         ret = xattr_tdb_get_file_id(handle, smb_fname->base_name, &id);
     145           0 :         error = errno;
     146             : 
     147           0 :         cwd_ret = SMB_VFS_CHDIR(dir_fsp->conn, cwd);
     148           0 :         SMB_ASSERT(cwd_ret == 0);
     149             : 
     150           0 :         if (ret == -1) {
     151           0 :                 tevent_req_error(req, error);
     152           0 :                 return tevent_req_post(req, ev);
     153             :         }
     154             : 
     155           0 :         state->xattr_size = xattr_tdb_getattr(config->db,
     156             :                                               state,
     157             :                                               &id,
     158             :                                               xattr_name,
     159             :                                               &xattr_blob);
     160           0 :         if (state->xattr_size == -1) {
     161           0 :                 tevent_req_error(req, errno);
     162           0 :                 return tevent_req_post(req, ev);
     163             :         }
     164             : 
     165           0 :         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           0 :         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           0 :         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           0 :         state->xattr_value = xattr_blob.data;
     194             : 
     195           0 :         tevent_req_done(req);
     196           0 :         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           0 : 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           0 :         struct xattr_tdb_getxattrat_state *state = tevent_req_data(
     226             :                 req, struct xattr_tdb_getxattrat_state);
     227             :         ssize_t xattr_size;
     228             : 
     229           0 :         if (tevent_req_is_unix_error(req, &aio_state->error)) {
     230           0 :                 tevent_req_received(req);
     231           0 :                 return -1;
     232             :         }
     233             : 
     234           0 :         *aio_state = state->vfs_aio_state;
     235           0 :         xattr_size = state->xattr_size;
     236           0 :         if (xattr_value != NULL) {
     237           0 :                 *xattr_value = talloc_move(mem_ctx, &state->xattr_value);
     238             :         }
     239             : 
     240           0 :         tevent_req_received(req);
     241           0 :         return xattr_size;
     242             : }
     243             : 
     244      508472 : 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      508472 :         struct xattr_tdb_config *config = NULL;
     249             :         SMB_STRUCT_STAT sbuf;
     250             :         struct file_id id;
     251             :         ssize_t xattr_size;
     252             :         DATA_BLOB blob;
     253      508472 :         TALLOC_CTX *frame = NULL;
     254             : 
     255      508472 :         if (!xattr_tdb_init(handle, &config)) {
     256           0 :                 return -1;
     257             :         }
     258             : 
     259      508472 :         if (config->ignore_user_xattr && is_user_xattr(name)) {
     260           0 :                 return SMB_VFS_NEXT_FGETXATTR(
     261             :                         handle, fsp, name, value, size);
     262             :         }
     263             : 
     264      508472 :         if (SMB_VFS_NEXT_FSTAT(handle, fsp, &sbuf) == -1) {
     265           0 :                 return -1;
     266             :         }
     267             : 
     268      508472 :         frame = talloc_stackframe();
     269             : 
     270      508472 :         id = SMB_VFS_NEXT_FILE_ID_CREATE(handle, &sbuf);
     271             : 
     272      508472 :         xattr_size = xattr_tdb_getattr(config->db, frame, &id, name, &blob);
     273      508472 :         if (xattr_size < 0) {
     274      362665 :                 errno = ENOATTR;
     275      362665 :                 TALLOC_FREE(frame);
     276      362665 :                 return -1;
     277             :         }
     278             : 
     279      145807 :         if (size == 0) {
     280           0 :                 TALLOC_FREE(frame);
     281           0 :                 return xattr_size;
     282             :         }
     283             : 
     284      145807 :         if (blob.length > size) {
     285           0 :                 TALLOC_FREE(frame);
     286           0 :                 errno = ERANGE;
     287           0 :                 return -1;
     288             :         }
     289      145807 :         memcpy(value, blob.data, xattr_size);
     290      145807 :         TALLOC_FREE(frame);
     291      145807 :         return xattr_size;
     292             : }
     293             : 
     294       10349 : 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       10349 :         struct xattr_tdb_config *config = NULL;
     300             :         SMB_STRUCT_STAT sbuf;
     301             :         struct file_id id;
     302             :         int ret;
     303             : 
     304       10349 :         if (!xattr_tdb_init(handle, &config)) {
     305           0 :                 return -1;
     306             :         }
     307             : 
     308       10349 :         if (config->ignore_user_xattr && is_user_xattr(name)) {
     309           0 :                 return SMB_VFS_NEXT_FSETXATTR(
     310             :                         handle, fsp, name, value, size, flags);
     311             :         }
     312             : 
     313       10349 :         if (SMB_VFS_NEXT_FSTAT(handle, fsp, &sbuf) == -1) {
     314           0 :                 return -1;
     315             :         }
     316             : 
     317       10349 :         id = SMB_VFS_NEXT_FILE_ID_CREATE(handle, &sbuf);
     318             : 
     319       10349 :         ret = xattr_tdb_setattr(config->db, &id, name, value, size, flags);
     320       10349 :         return ret;
     321             : 
     322             : }
     323             : 
     324       10360 : static ssize_t xattr_tdb_flistxattr(struct vfs_handle_struct *handle,
     325             :                                     struct files_struct *fsp, char *list,
     326             :                                     size_t size)
     327             : {
     328       10360 :         struct xattr_tdb_config *config = NULL;
     329             :         SMB_STRUCT_STAT sbuf;
     330             :         struct file_id id;
     331             :         ssize_t backend_size;
     332             :         ssize_t ret;
     333             : 
     334       10360 :         if (!xattr_tdb_init(handle, &config)) {
     335           0 :                 return -1;
     336             :         }
     337             : 
     338       10360 :         if (SMB_VFS_NEXT_FSTAT(handle, fsp, &sbuf) == -1) {
     339           0 :                 return -1;
     340             :         }
     341             : 
     342       10360 :         id = SMB_VFS_NEXT_FILE_ID_CREATE(handle, &sbuf);
     343             : 
     344       10360 :         ret = xattr_tdb_listattr(config->db, &id, list, size);
     345       10360 :         if (ret == -1) {
     346           0 :                 return -1;
     347             :         }
     348       10360 :         if (ret == size) {
     349           0 :                 return ret;
     350             :         }
     351       10360 :         if (!config->ignore_user_xattr) {
     352       10360 :                 return ret;
     353             :         }
     354           0 :         SMB_ASSERT(ret < size);
     355             : 
     356           0 :         backend_size = SMB_VFS_NEXT_FLISTXATTR(
     357             :                 handle, fsp, list + ret, size - ret);
     358           0 :         if (backend_size == -1) {
     359           0 :                 return -1;
     360             :         }
     361             : 
     362           0 :         return ret + backend_size;
     363             : }
     364             : 
     365          38 : static int xattr_tdb_fremovexattr(struct vfs_handle_struct *handle,
     366             :                                   struct files_struct *fsp, const char *name)
     367             : {
     368          38 :         struct xattr_tdb_config *config = NULL;
     369             :         SMB_STRUCT_STAT sbuf;
     370             :         struct file_id id;
     371             : 
     372          38 :         if (!xattr_tdb_init(handle, &config)) {
     373           0 :                 return -1;
     374             :         }
     375             : 
     376          38 :         if (config->ignore_user_xattr && is_user_xattr(name)) {
     377           0 :                 return SMB_VFS_NEXT_FREMOVEXATTR(handle, fsp, name);
     378             :         }
     379             : 
     380          38 :         if (SMB_VFS_NEXT_FSTAT(handle, fsp, &sbuf) == -1) {
     381           0 :                 return -1;
     382             :         }
     383             : 
     384          38 :         id = SMB_VFS_NEXT_FILE_ID_CREATE(handle, &sbuf);
     385             : 
     386          38 :         return xattr_tdb_removeattr(config->db, &id, name);
     387             : }
     388             : 
     389             : /*
     390             :  * Destructor for the VFS private data
     391             :  */
     392             : 
     393        7966 : static void config_destructor(void **data)
     394             : {
     395        7966 :         struct xattr_tdb_config **config = (struct xattr_tdb_config **)data;
     396        7966 :         TALLOC_FREE((*config)->db);
     397        7966 : }
     398             : 
     399             : /*
     400             :  * Open the tdb file upon VFS_CONNECT
     401             :  */
     402             : 
     403      693455 : static bool xattr_tdb_init(struct vfs_handle_struct *handle,
     404             :                            struct xattr_tdb_config **_config)
     405             : {
     406      693455 :         struct xattr_tdb_config *config = NULL;
     407             :         const char *dbname;
     408             :         char *def_dbname;
     409             : 
     410      693455 :         if (SMB_VFS_HANDLE_TEST_DATA(handle)) {
     411      685489 :                 SMB_VFS_HANDLE_GET_DATA(handle, config, struct xattr_tdb_config,
     412             :                                         return false);
     413      685489 :                 if (_config != NULL) {
     414      685489 :                         *_config = config;
     415             :                 }
     416      685489 :                 return true;
     417             :         }
     418             : 
     419        7966 :         config = talloc_zero(handle->conn, struct xattr_tdb_config);
     420        7966 :         if (config == NULL) {
     421           0 :                 errno = ENOMEM;
     422           0 :                 goto error;
     423             :         }
     424             : 
     425        7966 :         def_dbname = state_path(talloc_tos(), "xattr.tdb");
     426        7966 :         if (def_dbname == NULL) {
     427           0 :                 errno = ENOSYS;
     428           0 :                 goto error;
     429             :         }
     430             : 
     431        7966 :         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        7966 :         become_root();
     439        7966 :         config->db = db_open(handle, dbname, 0, TDB_DEFAULT, O_RDWR|O_CREAT, 0600,
     440             :                              DBWRAP_LOCK_ORDER_2, DBWRAP_FLAG_NONE);
     441        7966 :         unbecome_root();
     442             : 
     443        7966 :         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        7966 :         TALLOC_FREE(def_dbname);
     453             : 
     454       13503 :         config->ignore_user_xattr = lp_parm_bool(
     455       13503 :                 SNUM(handle->conn), "xattr_tdb", "ignore_user_xattr", false);
     456             : 
     457        7966 :         SMB_VFS_HANDLE_SET_DATA(handle, config, config_destructor,
     458             :                                 struct xattr_tdb_config, return false);
     459             : 
     460        7966 :         if (_config != NULL) {
     461         378 :                 *_config = config;
     462             :         }
     463        7966 :         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      154177 : 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      154177 :         struct xattr_tdb_config *config = NULL;
     478             :         SMB_STRUCT_STAT sbuf;
     479             :         int fd;
     480             :         int ret;
     481             : 
     482      154177 :         if (!xattr_tdb_init(handle, &config)) {
     483           0 :                 return -1;
     484             :         }
     485             : 
     486      154177 :         fd = SMB_VFS_NEXT_OPENAT(handle,
     487             :                                  dirfsp,
     488             :                                  smb_fname,
     489             :                                  fsp,
     490             :                                  how);
     491      154177 :         if (fd == -1) {
     492       30182 :                 return -1;
     493             :         }
     494             : 
     495      123995 :         if ((how->flags & (O_CREAT|O_EXCL)) != (O_CREAT|O_EXCL)) {
     496      123313 :                 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         682 :         fsp_set_fd(fsp, fd);
     505         682 :         ret = SMB_VFS_FSTAT(fsp, &sbuf);
     506         682 :         fsp_set_fd(fsp, -1);
     507         682 :         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         682 :         fsp->file_id = SMB_VFS_FILE_ID_CREATE(fsp->conn, &sbuf);
     516             : 
     517         682 :         xattr_tdb_remove_all_attrs(config->db, &fsp->file_id);
     518             : 
     519         682 :         return fd;
     520             : }
     521             : 
     522        1090 : 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        1090 :         struct xattr_tdb_config *config = NULL;
     528        1090 :         TALLOC_CTX *frame = NULL;
     529             :         struct file_id fileid;
     530             :         int ret;
     531        1090 :         struct smb_filename *full_fname = NULL;
     532             : 
     533        1090 :         if (!xattr_tdb_init(handle, &config)) {
     534           0 :                 return -1;
     535             :         }
     536             : 
     537        1090 :         ret = SMB_VFS_NEXT_MKDIRAT(handle,
     538             :                                 dirfsp,
     539             :                                 smb_fname,
     540             :                                 mode);
     541        1090 :         if (ret < 0) {
     542           1 :                 return ret;
     543             :         }
     544             : 
     545        1089 :         frame = talloc_stackframe();
     546             : 
     547        1089 :         full_fname = full_path_from_dirfsp_atname(talloc_tos(),
     548             :                                                   dirfsp,
     549             :                                                   smb_fname);
     550        1089 :         if (full_fname == NULL) {
     551           0 :                 errno = ENOMEM;
     552           0 :                 return -1;
     553             :         }
     554             : 
     555             :         /* Always use LSTAT here - we just created the directory. */
     556        1089 :         ret = SMB_VFS_LSTAT(handle->conn, full_fname);
     557        1089 :         if (ret == -1) {
     558             :                 /* Rename race. Let upper level take care of it. */
     559           0 :                 TALLOC_FREE(frame);
     560           0 :                 return -1;
     561             :         }
     562        1089 :         if (!S_ISDIR(full_fname->st.st_ex_mode)) {
     563             :                 /* Rename race. Let upper level take care of it. */
     564           0 :                 TALLOC_FREE(frame);
     565           0 :                 return -1;
     566             :         }
     567             : 
     568        1089 :         fileid = SMB_VFS_FILE_ID_CREATE(handle->conn, &full_fname->st);
     569             : 
     570        1089 :         xattr_tdb_remove_all_attrs(config->db, &fileid);
     571        1089 :         TALLOC_FREE(frame);
     572        1089 :         return 0;
     573             : }
     574             : 
     575             : /*
     576             :  * On unlink we need to delete the tdb record
     577             :  */
     578        1381 : static int xattr_tdb_unlinkat(vfs_handle_struct *handle,
     579             :                         struct files_struct *dirfsp,
     580             :                         const struct smb_filename *smb_fname,
     581             :                         int flags)
     582             : {
     583        1381 :         struct xattr_tdb_config *config = NULL;
     584        1381 :         struct smb_filename *smb_fname_tmp = NULL;
     585        1381 :         struct smb_filename *full_fname = NULL;
     586             :         struct file_id id;
     587        1381 :         int ret = -1;
     588        1381 :         bool remove_record = false;
     589        1381 :         TALLOC_CTX *frame = NULL;
     590             : 
     591        1381 :         if (!xattr_tdb_init(handle, &config)) {
     592           0 :                 return -1;
     593             :         }
     594             : 
     595        1381 :         frame = talloc_stackframe();
     596             : 
     597        1381 :         smb_fname_tmp = cp_smb_filename(frame, smb_fname);
     598        1381 :         if (smb_fname_tmp == NULL) {
     599           0 :                 TALLOC_FREE(frame);
     600           0 :                 errno = ENOMEM;
     601           0 :                 return -1;
     602             :         }
     603             : 
     604             :         /*
     605             :          * TODO: use SMB_VFS_STATX() once we have that
     606             :          */
     607             : 
     608        1381 :         full_fname = full_path_from_dirfsp_atname(frame,
     609             :                                                   dirfsp,
     610             :                                                   smb_fname);
     611        1381 :         if (full_fname == NULL) {
     612           0 :                 goto out;
     613             :         }
     614             : 
     615        1381 :         if (full_fname->flags & SMB_FILENAME_POSIX_PATH) {
     616           0 :                 ret = SMB_VFS_NEXT_LSTAT(handle, full_fname);
     617             :         } else {
     618        1381 :                 ret = SMB_VFS_NEXT_STAT(handle, full_fname);
     619        1381 :                 if (ret == -1 && (errno == ENOENT || errno == ELOOP)) {
     620           0 :                         if (VALID_STAT(smb_fname->st) &&
     621           0 :                                         S_ISLNK(smb_fname->st.st_ex_mode)) {
     622             :                                 /*
     623             :                                  * Original name was a link - Could be
     624             :                                  * trying to remove a dangling symlink.
     625             :                                  */
     626           0 :                                 ret = SMB_VFS_NEXT_LSTAT(handle, full_fname);
     627             :                         }
     628             :                 }
     629             :         }
     630        1381 :         if (ret == -1) {
     631           0 :                 goto out;
     632             :         }
     633        1381 :         smb_fname_tmp->st = full_fname->st;
     634             : 
     635        1381 :         if (flags & AT_REMOVEDIR) {
     636             :                 /* Always remove record when removing a directory succeeds. */
     637         808 :                 remove_record = true;
     638             :         } else {
     639         573 :                 if (smb_fname_tmp->st.st_ex_nlink == 1) {
     640             :                         /* Only remove record on last link to file. */
     641         569 :                         remove_record = true;
     642             :                 }
     643             :         }
     644             : 
     645        1381 :         ret = SMB_VFS_NEXT_UNLINKAT(handle,
     646             :                                 dirfsp,
     647             :                                 smb_fname_tmp,
     648             :                                 flags);
     649             : 
     650        1381 :         if (ret == -1) {
     651           0 :                 goto out;
     652             :         }
     653             : 
     654        1381 :         if (!remove_record) {
     655           4 :                 goto out;
     656             :         }
     657             : 
     658        1377 :         id = SMB_VFS_NEXT_FILE_ID_CREATE(handle, &smb_fname_tmp->st);
     659             : 
     660        1377 :         xattr_tdb_remove_all_attrs(config->db, &id);
     661             : 
     662        1381 :  out:
     663        1381 :         TALLOC_FREE(frame);
     664        1381 :         return ret;
     665             : }
     666             : 
     667        7966 : static int xattr_tdb_connect(vfs_handle_struct *handle, const char *service,
     668             :                           const char *user)
     669             : {
     670        7966 :         char *sname = NULL;
     671             :         int res, snum;
     672             : 
     673        7966 :         res = SMB_VFS_NEXT_CONNECT(handle, service, user);
     674        7966 :         if (res < 0) {
     675           0 :                 return res;
     676             :         }
     677             : 
     678        7966 :         snum = find_service(talloc_tos(), service, &sname);
     679        7966 :         if (snum == -1 || sname == NULL) {
     680             :                 /*
     681             :                  * Should not happen, but we should not fail just *here*.
     682             :                  */
     683         378 :                 return 0;
     684             :         }
     685             : 
     686        7588 :         if (!xattr_tdb_init(handle, NULL)) {
     687           0 :                 DEBUG(5, ("Could not init xattr tdb\n"));
     688           0 :                 lp_do_parameter(snum, "ea support", "False");
     689           0 :                 return 0;
     690             :         }
     691             : 
     692        7588 :         lp_do_parameter(snum, "ea support", "True");
     693             : 
     694        7588 :         return 0;
     695             : }
     696             : 
     697             : static struct vfs_fn_pointers vfs_xattr_tdb_fns = {
     698             :         .getxattrat_send_fn = xattr_tdb_getxattrat_send,
     699             :         .getxattrat_recv_fn = xattr_tdb_getxattrat_recv,
     700             :         .fgetxattr_fn = xattr_tdb_fgetxattr,
     701             :         .fsetxattr_fn = xattr_tdb_fsetxattr,
     702             :         .flistxattr_fn = xattr_tdb_flistxattr,
     703             :         .fremovexattr_fn = xattr_tdb_fremovexattr,
     704             :         .openat_fn = xattr_tdb_openat,
     705             :         .mkdirat_fn = xattr_tdb_mkdirat,
     706             :         .unlinkat_fn = xattr_tdb_unlinkat,
     707             :         .connect_fn = xattr_tdb_connect,
     708             : };
     709             : 
     710             : static_decl_vfs;
     711        4875 : NTSTATUS vfs_xattr_tdb_init(TALLOC_CTX *ctx)
     712             : {
     713        4875 :         return smb_register_vfs(SMB_VFS_INTERFACE_VERSION, "xattr_tdb",
     714             :                                 &vfs_xattr_tdb_fns);
     715             : }

Generated by: LCOV version 1.13