LCOV - code coverage report
Current view: top level - source3/modules - vfs_fileid.c (source / functions) Hit Total Coverage
Test: coverage report for master 2f515e9b Lines: 7 334 2.1 %
Date: 2024-04-21 15:09:00 Functions: 1 19 5.3 %

          Line data    Source code
       1             : /*
       2             :  * VFS module to alter the algorithm to calculate
       3             :  * the struct file_id used as key for the share mode
       4             :  * and byte range locking db's.
       5             :  *
       6             :  * Copyright (C) 2007, Stefan Metzmacher
       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 "smbd/smbd.h"
      24             : #include "system/filesys.h"
      25             : 
      26             : static int vfs_fileid_debug_level = DBGC_VFS;
      27             : 
      28             : #undef DBGC_CLASS
      29             : #define DBGC_CLASS vfs_fileid_debug_level
      30             : 
      31             : struct fileid_mount_entry {
      32             :         SMB_DEV_T device;
      33             :         const char *mnt_fsname;
      34             :         fsid_t fsid;
      35             :         uint64_t devid;
      36             : };
      37             : 
      38             : struct fileid_nolock_inode {
      39             :         dev_t dev;
      40             :         ino_t ino;
      41             : };
      42             : 
      43             : struct fileid_handle_data {
      44             :         struct vfs_handle_struct *handle;
      45             :         struct file_id (*mapping_fn)(struct fileid_handle_data *data,
      46             :                                      const SMB_STRUCT_STAT *sbuf);
      47             :         char **fstype_deny_list;
      48             :         char **fstype_allow_list;
      49             :         char **mntdir_deny_list;
      50             :         char **mntdir_allow_list;
      51             :         unsigned num_mount_entries;
      52             :         struct fileid_mount_entry *mount_entries;
      53             :         struct {
      54             :                 bool force_all_inodes;
      55             :                 bool force_all_dirs;
      56             :                 uint64_t extid;
      57             :                 size_t num_inodes;
      58             :                 struct fileid_nolock_inode *inodes;
      59             :         } nolock;
      60             : };
      61             : 
      62             : /* check if a mount entry is allowed based on fstype and mount directory */
      63           0 : static bool fileid_mount_entry_allowed(struct fileid_handle_data *data,
      64             :                                        struct mntent *m)
      65             : {
      66             :         int i;
      67           0 :         char **fstype_deny = data->fstype_deny_list;
      68           0 :         char **fstype_allow = data->fstype_allow_list;
      69           0 :         char **mntdir_deny = data->mntdir_deny_list;
      70           0 :         char **mntdir_allow = data->mntdir_allow_list;
      71             : 
      72           0 :         if (fstype_deny != NULL) {
      73           0 :                 for (i = 0; fstype_deny[i] != NULL; i++) {
      74           0 :                         if (strcmp(m->mnt_type, fstype_deny[i]) == 0) {
      75           0 :                                 return false;
      76             :                         }
      77             :                 }
      78             :         }
      79           0 :         if (fstype_allow != NULL) {
      80           0 :                 for (i = 0; fstype_allow[i] != NULL; i++) {
      81           0 :                         if (strcmp(m->mnt_type, fstype_allow[i]) == 0) {
      82           0 :                                 break;
      83             :                         }
      84             :                 }
      85           0 :                 if (fstype_allow[i] == NULL) {
      86           0 :                         return false;
      87             :                 }
      88             :         }
      89           0 :         if (mntdir_deny != NULL) {
      90           0 :                 for (i=0; mntdir_deny[i] != NULL; i++) {
      91           0 :                         if (strcmp(m->mnt_dir, mntdir_deny[i]) == 0) {
      92           0 :                                 return false;
      93             :                         }
      94             :                 }
      95             :         }
      96           0 :         if (mntdir_allow != NULL) {
      97           0 :                 for (i=0; mntdir_allow[i] != NULL; i++) {
      98           0 :                         if (strcmp(m->mnt_dir, mntdir_allow[i]) == 0) {
      99           0 :                                 break;
     100             :                         }
     101             :                 }
     102           0 :                 if (mntdir_allow[i] == NULL) {
     103           0 :                         return false;
     104             :                 }
     105             :         }
     106           0 :         return true;
     107             : }
     108             : 
     109             : 
     110             : /* load all the mount entries from the mtab */
     111           0 : static void fileid_load_mount_entries(struct fileid_handle_data *data)
     112             : {
     113             :         FILE *f;
     114             :         struct mntent *m;
     115             : 
     116           0 :         data->num_mount_entries = 0;
     117           0 :         TALLOC_FREE(data->mount_entries);
     118             : 
     119           0 :         f = setmntent("/etc/mtab", "r");
     120           0 :         if (!f) return;
     121             : 
     122           0 :         while ((m = getmntent(f))) {
     123             :                 struct stat st;
     124             :                 struct statfs sfs;
     125             :                 struct fileid_mount_entry *cur;
     126             :                 bool allowed;
     127             : 
     128           0 :                 allowed = fileid_mount_entry_allowed(data, m);
     129           0 :                 if (!allowed) {
     130           0 :                         DBG_DEBUG("skipping mount entry %s\n", m->mnt_dir);
     131           0 :                         continue;
     132             :                 }
     133           0 :                 if (stat(m->mnt_dir, &st) != 0) continue;
     134           0 :                 if (statfs(m->mnt_dir, &sfs) != 0) continue;
     135             : 
     136           0 :                 if (strncmp(m->mnt_fsname, "/dev/", 5) == 0) {
     137           0 :                         m->mnt_fsname += 5;
     138             :                 }
     139             : 
     140           0 :                 data->mount_entries = talloc_realloc(data,
     141             :                                                            data->mount_entries,
     142             :                                                            struct fileid_mount_entry,
     143             :                                                            data->num_mount_entries+1);
     144           0 :                 if (data->mount_entries == NULL) {
     145           0 :                         goto nomem;
     146             :                 }
     147             : 
     148           0 :                 cur = &data->mount_entries[data->num_mount_entries];
     149           0 :                 cur->device  = st.st_dev;
     150           0 :                 cur->mnt_fsname = talloc_strdup(data->mount_entries,
     151           0 :                                                 m->mnt_fsname);
     152           0 :                 if (!cur->mnt_fsname) goto nomem;
     153           0 :                 cur->fsid    = sfs.f_fsid;
     154           0 :                 cur->devid   = (uint64_t)-1;
     155             : 
     156           0 :                 data->num_mount_entries++;
     157             :         }
     158           0 :         endmntent(f);
     159           0 :         return;
     160             :         
     161           0 : nomem:
     162           0 :         if (f) endmntent(f);
     163             : 
     164           0 :         data->num_mount_entries = 0;
     165           0 :         TALLOC_FREE(data->mount_entries);
     166             : 
     167           0 :         return;
     168             : }
     169             : 
     170             : /* find a mount entry given a dev_t */
     171           0 : static struct fileid_mount_entry *fileid_find_mount_entry(struct fileid_handle_data *data,
     172             :                                                           SMB_DEV_T dev)
     173             : {
     174             :         unsigned i;
     175             : 
     176           0 :         if (data->num_mount_entries == 0) {
     177           0 :                 fileid_load_mount_entries(data);
     178             :         }
     179           0 :         for (i=0;i<data->num_mount_entries;i++) {
     180           0 :                 if (data->mount_entries[i].device == dev) {
     181           0 :                         return &data->mount_entries[i];
     182             :                 }
     183             :         }
     184             :         /* 2nd pass after reloading */
     185           0 :         fileid_load_mount_entries(data);
     186           0 :         for (i=0;i<data->num_mount_entries;i++) {
     187           0 :                 if (data->mount_entries[i].device == dev) {
     188           0 :                         return &data->mount_entries[i];
     189             :                 }
     190             :         }       
     191           0 :         return NULL;
     192             : }
     193             : 
     194             : 
     195             : /* a 64 bit hash, based on the one in tdb */
     196           0 : static uint64_t fileid_uint64_hash(const uint8_t *s, size_t len)
     197             : {
     198             :         uint64_t value; /* Used to compute the hash value.  */
     199             :         uint32_t i;     /* Used to cycle through random values. */
     200             : 
     201             :         /* Set the initial value from the key size. */
     202           0 :         for (value = 0x238F13AFLL * len, i=0; i < len; i++)
     203           0 :                 value = (value + (((uint64_t)s[i]) << (i*5 % 24)));
     204             : 
     205           0 :         return (1103515243LL * value + 12345LL);
     206             : }
     207             : 
     208             : /* a device mapping using a fsname */
     209           0 : static uint64_t fileid_device_mapping_fsname(struct fileid_handle_data *data,
     210             :                                              const SMB_STRUCT_STAT *sbuf)
     211             : {
     212             :         struct fileid_mount_entry *m;
     213             : 
     214           0 :         m = fileid_find_mount_entry(data, sbuf->st_ex_dev);
     215           0 :         if (!m) return sbuf->st_ex_dev;
     216             : 
     217           0 :         if (m->devid == (uint64_t)-1) {
     218           0 :                 m->devid = fileid_uint64_hash((const uint8_t *)m->mnt_fsname,
     219             :                                               strlen(m->mnt_fsname));
     220             :         }
     221             : 
     222           0 :         return m->devid;
     223             : }
     224             : 
     225           0 : static struct file_id fileid_mapping_fsname(struct fileid_handle_data *data,
     226             :                                             const SMB_STRUCT_STAT *sbuf)
     227             : {
     228           0 :         struct file_id id = { .inode = sbuf->st_ex_ino, };
     229             : 
     230           0 :         id.devid = fileid_device_mapping_fsname(data, sbuf);
     231             : 
     232           0 :         return id;
     233             : }
     234             : 
     235             : /* a device mapping using a hostname */
     236           0 : static uint64_t fileid_device_mapping_hostname(struct fileid_handle_data *data,
     237             :                                                const SMB_STRUCT_STAT *sbuf)
     238             : {
     239             :         char hostname[HOST_NAME_MAX+1];
     240           0 :         char *devname = NULL;
     241             :         uint64_t id;
     242             :         size_t devname_len;
     243             :         int rc;
     244             : 
     245           0 :         rc = gethostname(hostname, HOST_NAME_MAX+1);
     246           0 :         if (rc != 0) {
     247           0 :                 DBG_ERR("gethostname failed\n");
     248           0 :                 return UINT64_MAX;
     249             :         }
     250             : 
     251           0 :         devname = talloc_asprintf(talloc_tos(), "%s%ju",
     252           0 :                                   hostname, (uintmax_t)sbuf->st_ex_dev);
     253           0 :         if (devname == NULL) {
     254           0 :                 DBG_ERR("talloc_asprintf failed\n");
     255           0 :                 return UINT64_MAX;
     256             :         }
     257           0 :         devname_len = talloc_array_length(devname) - 1;
     258             : 
     259           0 :         id = fileid_uint64_hash((uint8_t *)devname, devname_len);
     260             : 
     261           0 :         TALLOC_FREE(devname);
     262             : 
     263           0 :         return id;
     264             : }
     265             : 
     266           0 : static struct file_id fileid_mapping_hostname(struct fileid_handle_data *data,
     267             :                                               const SMB_STRUCT_STAT *sbuf)
     268             : {
     269           0 :         struct file_id id = { .inode = sbuf->st_ex_ino, };
     270             : 
     271           0 :         id.devid = fileid_device_mapping_hostname(data, sbuf);
     272             : 
     273           0 :         return id;
     274             : }
     275             : 
     276           0 : static bool fileid_is_nolock_inode(struct fileid_handle_data *data,
     277             :                                    const SMB_STRUCT_STAT *sbuf)
     278             : {
     279             :         size_t i;
     280             : 
     281           0 :         if (data->nolock.force_all_inodes) {
     282           0 :                 return true;
     283             :         }
     284             : 
     285           0 :         if (S_ISDIR(sbuf->st_ex_mode) && data->nolock.force_all_dirs) {
     286           0 :                 return true;
     287             :         }
     288             : 
     289             :         /*
     290             :          * We could make this a binary search over an sorted array,
     291             :          * but for now we keep things simple.
     292             :          */
     293             : 
     294           0 :         for (i=0; i < data->nolock.num_inodes; i++) {
     295           0 :                 if (data->nolock.inodes[i].ino != sbuf->st_ex_ino) {
     296           0 :                         continue;
     297             :                 }
     298             : 
     299           0 :                 if (data->nolock.inodes[i].dev == 0) {
     300             :                         /*
     301             :                          * legacy "fileid:nolockinode"
     302             :                          * handling ignoring dev
     303             :                          */
     304           0 :                         return true;
     305             :                 }
     306             : 
     307           0 :                 if (data->nolock.inodes[i].dev != sbuf->st_ex_dev) {
     308           0 :                         continue;
     309             :                 }
     310             : 
     311           0 :                 return true;
     312             :         }
     313             : 
     314           0 :         return false;
     315             : }
     316             : 
     317           0 : static int fileid_add_nolock_inode(struct fileid_handle_data *data,
     318             :                                    const SMB_STRUCT_STAT *sbuf)
     319             : {
     320           0 :         bool exists = fileid_is_nolock_inode(data, sbuf);
     321           0 :         struct fileid_nolock_inode *inodes = NULL;
     322             : 
     323           0 :         if (exists) {
     324           0 :                 return 0;
     325             :         }
     326             : 
     327           0 :         inodes = talloc_realloc(data, data->nolock.inodes,
     328             :                                 struct fileid_nolock_inode,
     329             :                                 data->nolock.num_inodes + 1);
     330           0 :         if (inodes == NULL) {
     331           0 :                 return -1;
     332             :         }
     333             : 
     334           0 :         inodes[data->nolock.num_inodes] = (struct fileid_nolock_inode) {
     335           0 :                 .dev = sbuf->st_ex_dev,
     336           0 :                 .ino = sbuf->st_ex_ino,
     337             :         };
     338           0 :         data->nolock.inodes = inodes;
     339           0 :         data->nolock.num_inodes += 1;
     340             : 
     341           0 :         return 0;
     342             : }
     343             : 
     344           0 : static uint64_t fileid_mapping_nolock_extid(uint64_t max_slots)
     345             : {
     346           0 :         char buf[8+4+HOST_NAME_MAX+1] = { 0, };
     347           0 :         uint64_t slot = 0;
     348             :         uint64_t id;
     349             :         int rc;
     350             : 
     351           0 :         if (max_slots > 1) {
     352           0 :                 slot = getpid() % max_slots;
     353             :         }
     354             : 
     355           0 :         PUSH_LE_U64(buf, 0, slot);
     356           0 :         PUSH_LE_U32(buf, 8, get_my_vnn());
     357             : 
     358           0 :         rc = gethostname(&buf[12], HOST_NAME_MAX+1);
     359           0 :         if (rc != 0) {
     360           0 :                 DBG_ERR("gethostname failed\n");
     361           0 :                 return UINT64_MAX;
     362             :         }
     363             : 
     364           0 :         id = fileid_uint64_hash((uint8_t *)buf, ARRAY_SIZE(buf));
     365             : 
     366           0 :         return id;
     367             : }
     368             : 
     369             : /* device mapping functions using a fsid */
     370           0 : static uint64_t fileid_device_mapping_fsid(struct fileid_handle_data *data,
     371             :                                            const SMB_STRUCT_STAT *sbuf)
     372             : {
     373             :         struct fileid_mount_entry *m;
     374             : 
     375           0 :         m = fileid_find_mount_entry(data, sbuf->st_ex_dev);
     376           0 :         if (!m) return sbuf->st_ex_dev;
     377             : 
     378           0 :         if (m->devid == (uint64_t)-1) {
     379             :                 if (sizeof(fsid_t) > sizeof(uint64_t)) {
     380             :                         m->devid = fileid_uint64_hash((uint8_t *)&m->fsid,
     381             :                                                       sizeof(m->fsid));
     382             :                 } else {
     383             :                         union {
     384             :                                 uint64_t ret;
     385             :                                 fsid_t fsid;
     386             :                         } u;
     387           0 :                         ZERO_STRUCT(u);
     388           0 :                         u.fsid = m->fsid;
     389           0 :                         m->devid = u.ret;
     390             :                 }
     391             :         }
     392             : 
     393           0 :         return m->devid;
     394             : }
     395             : 
     396           0 : static struct file_id fileid_mapping_fsid(struct fileid_handle_data *data,
     397             :                                           const SMB_STRUCT_STAT *sbuf)
     398             : {
     399           0 :         struct file_id id = { .inode = sbuf->st_ex_ino, };
     400             : 
     401           0 :         id.devid = fileid_device_mapping_fsid(data, sbuf);
     402             : 
     403           0 :         return id;
     404             : }
     405             : 
     406           0 : static struct file_id fileid_mapping_next_module(struct fileid_handle_data *data,
     407             :                                                  const SMB_STRUCT_STAT *sbuf)
     408             : {
     409           0 :         return SMB_VFS_NEXT_FILE_ID_CREATE(data->handle, sbuf);
     410             : }
     411             : 
     412           0 : static int get_connectpath_ino(struct vfs_handle_struct *handle,
     413             :                                const char *path,
     414             :                                SMB_STRUCT_STAT *psbuf)
     415             : {
     416           0 :         TALLOC_CTX *frame = talloc_stackframe();
     417           0 :         struct smb_filename *fname = NULL;
     418           0 :         const char *fullpath = NULL;
     419             :         int ret;
     420             : 
     421           0 :         if (path[0] == '/') {
     422           0 :                 fullpath = path;
     423             :         } else {
     424           0 :                 fullpath = talloc_asprintf(frame,
     425             :                                            "%s/%s",
     426           0 :                                            handle->conn->connectpath,
     427             :                                            path);
     428           0 :                 if (fullpath == NULL) {
     429           0 :                         DBG_ERR("talloc_asprintf() failed\n");
     430           0 :                         TALLOC_FREE(frame);
     431           0 :                         return -1;
     432             :                 }
     433             :         }
     434             : 
     435           0 :         fname = synthetic_smb_fname(frame,
     436             :                                     fullpath,
     437             :                                     NULL,
     438             :                                     NULL,
     439             :                                     0,
     440             :                                     0);
     441           0 :         if (fname == NULL) {
     442           0 :                 DBG_ERR("synthetic_smb_fname(%s) failed - %s\n",
     443             :                         fullpath, strerror(errno));
     444           0 :                 TALLOC_FREE(frame);
     445           0 :                 return -1;
     446             :         }
     447             : 
     448           0 :         ret = SMB_VFS_NEXT_STAT(handle, fname);
     449           0 :         if (ret != 0) {
     450           0 :                 DBG_ERR("stat failed for %s with %s\n",
     451             :                         fullpath, strerror(errno));
     452           0 :                 TALLOC_FREE(frame);
     453           0 :                 return -1;
     454             :         }
     455           0 :         *psbuf = fname->st;
     456             : 
     457           0 :         TALLOC_FREE(frame);
     458             : 
     459           0 :         return 0;
     460             : }
     461             : 
     462           0 : static int fileid_connect(struct vfs_handle_struct *handle,
     463             :                           const char *service, const char *user)
     464             : {
     465             :         struct fileid_handle_data *data;
     466             :         const char *algorithm;
     467           0 :         const char **fstype_deny_list = NULL;
     468           0 :         const char **fstype_allow_list = NULL;
     469           0 :         const char **mntdir_deny_list = NULL;
     470           0 :         const char **mntdir_allow_list = NULL;
     471             :         ino_t nolockinode;
     472           0 :         uint64_t max_slots = 0;
     473           0 :         bool rootdir_nolock = false;
     474           0 :         const char **nolock_paths = NULL;
     475             :         size_t i;
     476             :         int saved_errno;
     477           0 :         int ret = SMB_VFS_NEXT_CONNECT(handle, service, user);
     478             : 
     479           0 :         if (ret < 0) {
     480           0 :                 return ret;
     481             :         }
     482             : 
     483           0 :         data = talloc_zero(handle, struct fileid_handle_data);
     484           0 :         if (!data) {
     485           0 :                 saved_errno = errno;
     486           0 :                 SMB_VFS_NEXT_DISCONNECT(handle);
     487           0 :                 DEBUG(0, ("talloc_zero() failed\n"));
     488           0 :                 errno = saved_errno;
     489           0 :                 return -1;
     490             :         }
     491           0 :         data->handle = handle;
     492             : 
     493             :         /*
     494             :          * "fileid:mapping" is only here as fallback for old setups
     495             :          * "fileid:algorithm" is the option new setups should use
     496             :          */
     497           0 :         algorithm = lp_parm_const_string(SNUM(handle->conn),
     498             :                                          "fileid", "mapping",
     499             :                                          "fsname");
     500           0 :         algorithm = lp_parm_const_string(SNUM(handle->conn),
     501             :                                          "fileid", "algorithm",
     502             :                                          algorithm);
     503           0 :         if (strcmp("fsname", algorithm) == 0) {
     504           0 :                 data->mapping_fn = fileid_mapping_fsname;
     505           0 :         } else if (strcmp("fsname_nodirs", algorithm) == 0) {
     506           0 :                 data->mapping_fn = fileid_mapping_fsname;
     507           0 :                 data->nolock.force_all_dirs = true;
     508           0 :         } else if (strcmp("fsid", algorithm) == 0) {
     509           0 :                 data->mapping_fn = fileid_mapping_fsid;
     510           0 :         } else if (strcmp("hostname", algorithm) == 0) {
     511           0 :                 data->mapping_fn = fileid_mapping_hostname;
     512           0 :                 data->nolock.force_all_inodes = true;
     513           0 :         } else if (strcmp("fsname_norootdir", algorithm) == 0) {
     514           0 :                 data->mapping_fn = fileid_mapping_fsname;
     515           0 :                 rootdir_nolock = true;
     516           0 :         } else if (strcmp("fsname_norootdir_ext", algorithm) == 0) {
     517           0 :                 data->mapping_fn = fileid_mapping_fsname;
     518           0 :                 rootdir_nolock = true;
     519           0 :                 max_slots = UINT64_MAX;
     520           0 :         } else if (strcmp("next_module", algorithm) == 0) {
     521           0 :                 data->mapping_fn     = fileid_mapping_next_module;
     522             :         } else {
     523           0 :                 SMB_VFS_NEXT_DISCONNECT(handle);
     524           0 :                 DEBUG(0,("fileid_connect(): unknown algorithm[%s]\n", algorithm));
     525           0 :                 return -1;
     526             :         }
     527             : 
     528           0 :         fstype_deny_list = lp_parm_string_list(SNUM(handle->conn), "fileid",
     529             :                                                "fstype deny", NULL);
     530           0 :         if (fstype_deny_list != NULL) {
     531           0 :                 data->fstype_deny_list = str_list_copy(data, fstype_deny_list);
     532           0 :                 if (data->fstype_deny_list == NULL) {
     533           0 :                         saved_errno = errno;
     534           0 :                         DBG_ERR("str_list_copy failed\n");
     535           0 :                         SMB_VFS_NEXT_DISCONNECT(handle);
     536           0 :                         errno = saved_errno;
     537           0 :                         return -1;
     538             :                 }
     539             :         }
     540             : 
     541           0 :         fstype_allow_list = lp_parm_string_list(SNUM(handle->conn), "fileid",
     542             :                                                 "fstype allow", NULL);
     543           0 :         if (fstype_allow_list != NULL) {
     544           0 :                 data->fstype_allow_list = str_list_copy(data, fstype_allow_list);
     545           0 :                 if (data->fstype_allow_list == NULL) {
     546           0 :                         saved_errno = errno;
     547           0 :                         DBG_ERR("str_list_copy failed\n");
     548           0 :                         SMB_VFS_NEXT_DISCONNECT(handle);
     549           0 :                         errno = saved_errno;
     550           0 :                         return -1;
     551             :                 }
     552             :         }
     553             : 
     554           0 :         mntdir_deny_list = lp_parm_string_list(SNUM(handle->conn), "fileid",
     555             :                                                "mntdir deny", NULL);
     556           0 :         if (mntdir_deny_list != NULL) {
     557           0 :                 data->mntdir_deny_list = str_list_copy(data, mntdir_deny_list);
     558           0 :                 if (data->mntdir_deny_list == NULL) {
     559           0 :                         saved_errno = errno;
     560           0 :                         DBG_ERR("str_list_copy failed\n");
     561           0 :                         SMB_VFS_NEXT_DISCONNECT(handle);
     562           0 :                         errno = saved_errno;
     563           0 :                         return -1;
     564             :                 }
     565             :         }
     566             : 
     567           0 :         mntdir_allow_list = lp_parm_string_list(SNUM(handle->conn), "fileid",
     568             :                                                 "mntdir allow", NULL);
     569           0 :         if (mntdir_allow_list != NULL) {
     570           0 :                 data->mntdir_allow_list = str_list_copy(data, mntdir_allow_list);
     571           0 :                 if (data->mntdir_allow_list == NULL) {
     572           0 :                         saved_errno = errno;
     573           0 :                         DBG_ERR("str_list_copy failed\n");
     574           0 :                         SMB_VFS_NEXT_DISCONNECT(handle);
     575           0 :                         errno = saved_errno;
     576           0 :                         return -1;
     577             :                 }
     578             :         }
     579             : 
     580           0 :         data->nolock.force_all_inodes = lp_parm_bool(SNUM(handle->conn),
     581             :                                                      "fileid", "nolock_all_inodes",
     582           0 :                                                      data->nolock.force_all_inodes);
     583           0 :         data->nolock.force_all_dirs = lp_parm_bool(SNUM(handle->conn),
     584             :                                                    "fileid", "nolock_all_dirs",
     585           0 :                                                    data->nolock.force_all_dirs);
     586             : 
     587           0 :         max_slots = lp_parm_ulonglong(SNUM(handle->conn),
     588             :                                       "fileid", "nolock_max_slots",
     589             :                                       max_slots);
     590           0 :         max_slots = MAX(max_slots, 1);
     591             : 
     592           0 :         data->nolock.extid = fileid_mapping_nolock_extid(max_slots);
     593             : 
     594           0 :         nolockinode = lp_parm_ulong(SNUM(handle->conn), "fileid", "nolockinode", 0);
     595           0 :         if (nolockinode != 0) {
     596           0 :                 SMB_STRUCT_STAT tmpsbuf = { .st_ex_ino = nolockinode, };
     597             : 
     598           0 :                 ret = fileid_add_nolock_inode(data, &tmpsbuf);
     599           0 :                 if (ret != 0) {
     600           0 :                         saved_errno = errno;
     601           0 :                         SMB_VFS_NEXT_DISCONNECT(handle);
     602           0 :                         errno = saved_errno;
     603           0 :                         return -1;
     604             :                 }
     605             :         }
     606             : 
     607           0 :         if (rootdir_nolock) {
     608             :                 SMB_STRUCT_STAT rootdirsbuf;
     609             : 
     610           0 :                 ret = get_connectpath_ino(handle, ".", &rootdirsbuf);
     611           0 :                 if (ret != 0) {
     612           0 :                         saved_errno = errno;
     613           0 :                         SMB_VFS_NEXT_DISCONNECT(handle);
     614           0 :                         errno = saved_errno;
     615           0 :                         return -1;
     616             :                 }
     617             : 
     618           0 :                 ret = fileid_add_nolock_inode(data, &rootdirsbuf);
     619           0 :                 if (ret != 0) {
     620           0 :                         saved_errno = errno;
     621           0 :                         SMB_VFS_NEXT_DISCONNECT(handle);
     622           0 :                         errno = saved_errno;
     623           0 :                         return -1;
     624             :                 }
     625             :         }
     626             : 
     627           0 :         nolock_paths = lp_parm_string_list(SNUM(handle->conn), "fileid", "nolock_paths", NULL);
     628           0 :         for (i = 0; nolock_paths != NULL && nolock_paths[i] != NULL; i++) {
     629             :                 SMB_STRUCT_STAT tmpsbuf;
     630             : 
     631           0 :                 ret = get_connectpath_ino(handle, nolock_paths[i], &tmpsbuf);
     632           0 :                 if (ret == -1 && errno == ENOENT) {
     633           0 :                         DBG_ERR("ignoring non existing nolock_paths[%zu]='%s'\n",
     634             :                                 i, nolock_paths[i]);
     635           0 :                         continue;
     636             :                 }
     637           0 :                 if (ret != 0) {
     638           0 :                         saved_errno = errno;
     639           0 :                         SMB_VFS_NEXT_DISCONNECT(handle);
     640           0 :                         errno = saved_errno;
     641           0 :                         return -1;
     642             :                 }
     643             : 
     644           0 :                 ret = fileid_add_nolock_inode(data, &tmpsbuf);
     645           0 :                 if (ret != 0) {
     646           0 :                         saved_errno = errno;
     647           0 :                         SMB_VFS_NEXT_DISCONNECT(handle);
     648           0 :                         errno = saved_errno;
     649           0 :                         return -1;
     650             :                 }
     651           0 :                 DBG_DEBUG("Adding nolock_paths[%zu]='%s'\n",
     652             :                           i, nolock_paths[i]);
     653             :         }
     654             : 
     655           0 :         SMB_VFS_HANDLE_SET_DATA(handle, data, NULL,
     656             :                                 struct fileid_handle_data,
     657             :                                 return -1);
     658             : 
     659           0 :         DBG_DEBUG("connect to service[%s] with algorithm[%s] nolock.inodes %zu\n",
     660             :                   service, algorithm, data->nolock.num_inodes);
     661             : 
     662           0 :         return 0;
     663             : }
     664             : 
     665           0 : static void fileid_disconnect(struct vfs_handle_struct *handle)
     666             : {
     667             :         const struct loadparm_substitution *lp_sub =
     668           0 :                 loadparm_s3_global_substitution();
     669             : 
     670           0 :         DEBUG(10,("fileid_disconnect() connect to service[%s].\n",
     671             :                   lp_servicename(talloc_tos(), lp_sub, SNUM(handle->conn))));
     672             : 
     673           0 :         SMB_VFS_NEXT_DISCONNECT(handle);
     674           0 : }
     675             : 
     676           0 : static struct file_id fileid_file_id_create(struct vfs_handle_struct *handle,
     677             :                                             const SMB_STRUCT_STAT *sbuf)
     678             : {
     679             :         struct fileid_handle_data *data;
     680           0 :         struct file_id id = { .inode = 0, };
     681             : 
     682           0 :         SMB_VFS_HANDLE_GET_DATA(handle, data,
     683             :                                 struct fileid_handle_data,
     684             :                                 return id);
     685             : 
     686           0 :         id = data->mapping_fn(data, sbuf);
     687           0 :         if (id.extid == 0 && fileid_is_nolock_inode(data, sbuf)) {
     688           0 :                 id.extid = data->nolock.extid;
     689             :         }
     690             : 
     691           0 :         DBG_DEBUG("Returning dev [%jx] inode [%jx] extid [%jx]\n",
     692             :                   (uintmax_t)id.devid, (uintmax_t)id.inode, (uintmax_t)id.extid);
     693             : 
     694           0 :         return id;
     695             : }
     696             : 
     697             : static struct vfs_fn_pointers vfs_fileid_fns = {
     698             :         .connect_fn = fileid_connect,
     699             :         .disconnect_fn = fileid_disconnect,
     700             :         .file_id_create_fn = fileid_file_id_create
     701             : };
     702             : 
     703             : static_decl_vfs;
     704          27 : NTSTATUS vfs_fileid_init(TALLOC_CTX *ctx)
     705             : {
     706             :         NTSTATUS ret;
     707             : 
     708          27 :         ret = smb_register_vfs(SMB_VFS_INTERFACE_VERSION, "fileid",
     709             :                                &vfs_fileid_fns);
     710          27 :         if (!NT_STATUS_IS_OK(ret)) {
     711           0 :                 return ret;
     712             :         }
     713             : 
     714          27 :         vfs_fileid_debug_level = debug_add_class("fileid");
     715          27 :         if (vfs_fileid_debug_level == -1) {
     716           0 :                 vfs_fileid_debug_level = DBGC_VFS;
     717           0 :                 DEBUG(0, ("vfs_fileid: Couldn't register custom debugging class!\n"));
     718             :         } else {
     719          27 :                 DEBUG(10, ("vfs_fileid: Debug class number of 'fileid': %d\n", vfs_fileid_debug_level));
     720             :         }
     721             : 
     722          27 :         return ret;
     723             : }

Generated by: LCOV version 1.14