LCOV - code coverage report
Current view: top level - source3/modules - vfs_crossrename.c (source / functions) Hit Total Coverage
Test: coverage report for master 2f515e9b Lines: 2 61 3.3 %
Date: 2024-04-21 15:09:00 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_src == 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             :                                 srcfsp, /* src_dirfsp */
     119             :                                 full_fname_src,
     120             :                                 dstfsp, /* dst_dirfsp */
     121             :                                 full_fname_dst,
     122             :                                 FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_SYSTEM);
     123           0 :         if (!NT_STATUS_IS_OK(status)) {
     124           0 :                 goto out;
     125             :         }
     126             : 
     127           0 :         ret = SMB_VFS_NEXT_UNLINKAT(handle,
     128             :                                     srcfsp,
     129             :                                     source,
     130             :                                     0);
     131           0 :         if (ret == -1) {
     132           0 :                 status = map_nt_error_from_unix(errno);
     133           0 :                 goto out;
     134             :         }
     135             : 
     136           0 :   out:
     137             : 
     138           0 :         TALLOC_FREE(full_fname_src);
     139           0 :         TALLOC_FREE(full_fname_dst);
     140           0 :         return status;
     141             : }
     142             : 
     143           0 : static int crossrename_renameat(vfs_handle_struct *handle,
     144             :                         files_struct *srcfsp,
     145             :                         const struct smb_filename *smb_fname_src,
     146             :                         files_struct *dstfsp,
     147             :                         const struct smb_filename *smb_fname_dst)
     148             : {
     149           0 :         int result = -1;
     150             : 
     151           0 :         START_PROFILE(syscall_renameat);
     152             : 
     153           0 :         if (smb_fname_src->stream_name || smb_fname_dst->stream_name) {
     154           0 :                 errno = ENOENT;
     155           0 :                 goto out;
     156             :         }
     157             : 
     158           0 :         result = SMB_VFS_NEXT_RENAMEAT(handle,
     159             :                                        srcfsp,
     160             :                                        smb_fname_src,
     161             :                                        dstfsp,
     162             :                                        smb_fname_dst);
     163             : 
     164           0 :         if ((result == -1) && (errno == EXDEV)) {
     165             :                 /* Rename across filesystems needed. */
     166           0 :                 NTSTATUS status = copy_reg(handle,
     167             :                                            srcfsp,
     168             :                                            smb_fname_src,
     169             :                                            dstfsp,
     170             :                                            smb_fname_dst);
     171           0 :                 if (!NT_STATUS_IS_OK(status)) {
     172           0 :                         errno = map_errno_from_nt_status(status);
     173           0 :                         result = -1;
     174             :                 }
     175             :         }
     176             : 
     177           0 :  out:
     178           0 :         END_PROFILE(syscall_renameat);
     179           0 :         return result;
     180             : }
     181             : 
     182             : 
     183             : static struct vfs_fn_pointers vfs_crossrename_fns = {
     184             :         .connect_fn = crossrename_connect,
     185             :         .renameat_fn = crossrename_renameat
     186             : };
     187             : 
     188             : static_decl_vfs;
     189          27 : NTSTATUS vfs_crossrename_init(TALLOC_CTX *ctx)
     190             : {
     191          27 :         return smb_register_vfs(SMB_VFS_INTERFACE_VERSION, MODULE,
     192             :                                 &vfs_crossrename_fns);
     193             : }
     194             : 

Generated by: LCOV version 1.14