LCOV - code coverage report
Current view: top level - source3/modules - vfs_crossrename.c (source / functions) Hit Total Coverage
Test: coverage report for abartlet/fix-coverage dd10fb34 Lines: 2 61 3.3 %
Date: 2021-09-23 10:06:22 Functions: 1 4 25.0 %

          Line data    Source code
       1             : /*
       2             :  * Copyright (c) Björn Jacke 2010
       3             :  *
       4             :  * This program is free software; you can redistribute it and/or modify
       5             :  * it under the terms of the GNU General Public License as published by
       6             :  * the Free Software Foundation; either version 3 of the License, or
       7             :  * (at your option) any later version.
       8             :  *
       9             :  * This program is distributed in the hope that it will be useful,
      10             :  * but WITHOUT ANY WARRANTY; without even the implied warranty of
      11             :  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      12             :  * GNU General Public License for more details.
      13             :  *
      14             :  * You should have received a copy of the GNU General Public License
      15             :  * along with this program; if not, see <http://www.gnu.org/licenses/>.
      16             :  */
      17             : 
      18             : #include "includes.h"
      19             : #include "smbd/smbd.h"
      20             : #include "system/filesys.h"
      21             : #include "transfer_file.h"
      22             : #include "smbprofile.h"
      23             : 
      24             : #define MODULE "crossrename"
      25             : static off_t module_sizelimit;
      26             : 
      27           0 : static int crossrename_connect(
      28             :                 struct vfs_handle_struct *  handle,
      29             :                 const char *                service,
      30             :                 const char *                user)
      31             : {
      32           0 :         int ret = SMB_VFS_NEXT_CONNECT(handle, service, user);
      33             : 
      34           0 :         if (ret < 0) {
      35           0 :                 return ret;
      36             :         }
      37             : 
      38           0 :         module_sizelimit = (off_t) lp_parm_int(SNUM(handle->conn),
      39             :                                         MODULE, "sizelimit", 20);
      40             :         /* convert from MiB to byte: */
      41           0 :         module_sizelimit *= 1048576;
      42             : 
      43           0 :         return 0;
      44             : }
      45             : 
      46             : /*********************************************************
      47             :  For rename across filesystems initial Patch from Warren Birnbaum
      48             :  <warrenb@hpcvscdp.cv.hp.com>
      49             : **********************************************************/
      50             : 
      51           0 : static NTSTATUS copy_reg(vfs_handle_struct *handle,
      52             :                          struct files_struct *srcfsp,
      53             :                          const struct smb_filename *source,
      54             :                          struct files_struct *dstfsp,
      55             :                          const struct smb_filename *dest)
      56             : {
      57             :         NTSTATUS status;
      58           0 :         struct smb_filename *full_fname_src = NULL;
      59           0 :         struct smb_filename *full_fname_dst = NULL;
      60             :         int ret;
      61             : 
      62           0 :         if (!VALID_STAT(source->st)) {
      63           0 :                 status = NT_STATUS_OBJECT_PATH_NOT_FOUND;
      64           0 :                 goto out;
      65             :         }
      66           0 :         if (!S_ISREG(source->st.st_ex_mode)) {
      67           0 :                 status = NT_STATUS_OBJECT_PATH_NOT_FOUND;
      68           0 :                 goto out;
      69             :         }
      70             : 
      71           0 :         if (source->st.st_ex_size > module_sizelimit) {
      72           0 :                 DBG_INFO("%s: size of %s larger than sizelimit (%lld > %lld), "
      73             :                          "rename prohibited\n",
      74             :                         MODULE,
      75             :                         source->base_name,
      76             :                         (long long)source->st.st_ex_size,
      77             :                         (long long)module_sizelimit);
      78           0 :                 status = NT_STATUS_INVALID_PARAMETER;
      79           0 :                 goto out;
      80             :         }
      81             : 
      82           0 :         full_fname_src = full_path_from_dirfsp_atname(talloc_tos(),
      83             :                                                       srcfsp,
      84             :                                                       source);
      85           0 :         if (full_fname_dst == NULL) {
      86           0 :                 status = NT_STATUS_NO_MEMORY;
      87           0 :                 goto out;
      88             :         }
      89           0 :         full_fname_dst = full_path_from_dirfsp_atname(talloc_tos(),
      90             :                                                       dstfsp,
      91             :                                                       dest);
      92           0 :         if (full_fname_dst == NULL) {
      93           0 :                 status = NT_STATUS_NO_MEMORY;
      94           0 :                 goto out;
      95             :         }
      96             : 
      97           0 :         ret = SMB_VFS_NEXT_UNLINKAT(handle,
      98             :                                     dstfsp,
      99             :                                     dest,
     100             :                                     0);
     101           0 :         if (ret == -1) {
     102           0 :                 status = map_nt_error_from_unix(errno);
     103           0 :                 goto out;
     104             :         }
     105             : 
     106             :         /*
     107             :          * copy_internals() takes attribute values from the NTrename call.
     108             :          *
     109             :          * From MS-CIFS:
     110             :          *
     111             :          * "If the attribute is 0x0000, then only normal files are renamed.
     112             :          * If the system file or hidden attributes are specified, then the
     113             :          * rename is inclusive of both special types."
     114             :          */
     115           0 :         status = copy_internals(talloc_tos(),
     116           0 :                                 handle->conn,
     117             :                                 NULL,
     118             :                                 full_fname_src,
     119             :                                 full_fname_dst,
     120             :                                 FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_SYSTEM);
     121           0 :         if (!NT_STATUS_IS_OK(status)) {
     122           0 :                 goto out;
     123             :         }
     124             : 
     125           0 :         ret = SMB_VFS_NEXT_UNLINKAT(handle,
     126             :                                     srcfsp,
     127             :                                     source,
     128             :                                     0);
     129           0 :         if (ret == -1) {
     130           0 :                 status = map_nt_error_from_unix(errno);
     131           0 :                 goto out;
     132             :         }
     133             : 
     134           0 :   out:
     135             : 
     136           0 :         TALLOC_FREE(full_fname_src);
     137           0 :         TALLOC_FREE(full_fname_dst);
     138           0 :         return status;
     139             : }
     140             : 
     141           0 : static int crossrename_renameat(vfs_handle_struct *handle,
     142             :                         files_struct *srcfsp,
     143             :                         const struct smb_filename *smb_fname_src,
     144             :                         files_struct *dstfsp,
     145             :                         const struct smb_filename *smb_fname_dst)
     146             : {
     147           0 :         int result = -1;
     148             : 
     149           0 :         START_PROFILE(syscall_renameat);
     150             : 
     151           0 :         if (smb_fname_src->stream_name || smb_fname_dst->stream_name) {
     152           0 :                 errno = ENOENT;
     153           0 :                 goto out;
     154             :         }
     155             : 
     156           0 :         result = SMB_VFS_NEXT_RENAMEAT(handle,
     157             :                                        srcfsp,
     158             :                                        smb_fname_src,
     159             :                                        dstfsp,
     160             :                                        smb_fname_dst);
     161             : 
     162           0 :         if ((result == -1) && (errno == EXDEV)) {
     163             :                 /* Rename across filesystems needed. */
     164           0 :                 NTSTATUS status = copy_reg(handle,
     165             :                                            srcfsp,
     166             :                                            smb_fname_src,
     167             :                                            dstfsp,
     168             :                                            smb_fname_dst);
     169           0 :                 if (!NT_STATUS_IS_OK(status)) {
     170           0 :                         errno = map_errno_from_nt_status(status);
     171           0 :                         result = -1;
     172             :                 }
     173             :         }
     174             : 
     175           0 :  out:
     176           0 :         END_PROFILE(syscall_renameat);
     177           0 :         return result;
     178             : }
     179             : 
     180             : 
     181             : static struct vfs_fn_pointers vfs_crossrename_fns = {
     182             :         .connect_fn = crossrename_connect,
     183             :         .renameat_fn = crossrename_renameat
     184             : };
     185             : 
     186             : static_decl_vfs;
     187          20 : NTSTATUS vfs_crossrename_init(TALLOC_CTX *ctx)
     188             : {
     189          20 :         return smb_register_vfs(SMB_VFS_INTERFACE_VERSION, MODULE,
     190             :                                 &vfs_crossrename_fns);
     191             : }
     192             : 

Generated by: LCOV version 1.13