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

          Line data    Source code
       1             : /* 
       2             :  * implementation of an Shadow Copy module
       3             :  *
       4             :  * Copyright (C) Stefan Metzmacher      2003-2004
       5             :  *
       6             :  * This program is free software; you can redistribute it and/or modify
       7             :  * it under the terms of the GNU General Public License as published by
       8             :  * the Free Software Foundation; either version 3 of the License, or
       9             :  * (at your option) any later version.
      10             :  *  
      11             :  * This program is distributed in the hope that it will be useful,
      12             :  * but WITHOUT ANY WARRANTY; without even the implied warranty of
      13             :  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      14             :  * GNU General Public License for more details.
      15             :  *  
      16             :  * You should have received a copy of the GNU General Public License
      17             :  * along with this program; if not, see <http://www.gnu.org/licenses/>.
      18             :  */
      19             : 
      20             : #include "includes.h"
      21             : #include "smbd/smbd.h"
      22             : #include "ntioctl.h"
      23             : #include "source3/smbd/dir.h"
      24             : 
      25             : /*
      26             :     Please read the VFS module Samba-HowTo-Collection.
      27             :     there's a chapter about this module
      28             : 
      29             :     For this share
      30             :     Z:\
      31             : 
      32             :     the ShadowCopies are in this directories
      33             : 
      34             :     Z:\@GMT-2003.08.05-12.00.00\
      35             :     Z:\@GMT-2003.08.05-12.01.00\
      36             :     Z:\@GMT-2003.08.05-12.02.00\
      37             : 
      38             :     e.g.
      39             :     
      40             :     Z:\testfile.txt
      41             :     Z:\@GMT-2003.08.05-12.02.00\testfile.txt
      42             : 
      43             :     or:
      44             : 
      45             :     Z:\testdir\testfile.txt
      46             :     Z:\@GMT-2003.08.05-12.02.00\testdir\testfile.txt
      47             : 
      48             : 
      49             :     Note: Files must differ to be displayed via Windows Explorer!
      50             :           Directories are always displayed...    
      51             : */
      52             : 
      53             : static int vfs_shadow_copy_debug_level = DBGC_VFS;
      54             : 
      55             : #undef DBGC_CLASS
      56             : #define DBGC_CLASS vfs_shadow_copy_debug_level
      57             : 
      58             : #define SHADOW_COPY_PREFIX "@GMT-"
      59             : #define SHADOW_COPY_SAMPLE "@GMT-2004.02.18-15.44.00"
      60             : 
      61             : typedef struct {
      62             :         int pos;
      63             :         int num;
      64             :         struct dirent *dirs;
      65             : } shadow_copy_Dir;
      66             : 
      67           0 : static bool shadow_copy_match_name(const char *name)
      68             : {
      69           0 :         if (strncmp(SHADOW_COPY_PREFIX,name, sizeof(SHADOW_COPY_PREFIX)-1)==0 &&
      70           0 :                 (strlen(SHADOW_COPY_SAMPLE) == strlen(name))) {
      71           0 :                 return True;
      72             :         }
      73             : 
      74           0 :         return False;
      75             : }
      76             : 
      77           0 : static DIR *shadow_copy_fdopendir(vfs_handle_struct *handle, files_struct *fsp, const char *mask, uint32_t attr)
      78             : {
      79             :         shadow_copy_Dir *dirp;
      80           0 :         DIR *p = SMB_VFS_NEXT_FDOPENDIR(handle,fsp,mask,attr);
      81             : 
      82           0 :         if (!p) {
      83           0 :                 DEBUG(10,("shadow_copy_opendir: SMB_VFS_NEXT_FDOPENDIR() failed for [%s]\n",
      84             :                         smb_fname_str_dbg(fsp->fsp_name)));
      85           0 :                 return NULL;
      86             :         }
      87             : 
      88           0 :         dirp = SMB_MALLOC_P(shadow_copy_Dir);
      89           0 :         if (!dirp) {
      90           0 :                 DEBUG(0,("shadow_copy_fdopendir: Out of memory\n"));
      91           0 :                 SMB_VFS_NEXT_CLOSEDIR(handle,p);
      92             :                 /* We have now closed the fd in fsp. */
      93           0 :                 fsp_set_fd(fsp, -1);
      94           0 :                 return NULL;
      95             :         }
      96             : 
      97           0 :         ZERO_STRUCTP(dirp);
      98             : 
      99           0 :         while (True) {
     100             :                 struct dirent *d;
     101             : 
     102           0 :                 d = SMB_VFS_NEXT_READDIR(handle, fsp, p);
     103           0 :                 if (d == NULL) {
     104           0 :                         break;
     105             :                 }
     106             : 
     107           0 :                 if (shadow_copy_match_name(d->d_name)) {
     108           0 :                         DEBUG(8,("shadow_copy_fdopendir: hide [%s]\n",d->d_name));
     109           0 :                         continue;
     110             :                 }
     111             : 
     112           0 :                 DEBUG(10,("shadow_copy_fdopendir: not hide [%s]\n",d->d_name));
     113             : 
     114           0 :                 dirp->dirs = SMB_REALLOC_ARRAY(dirp->dirs,struct dirent, dirp->num+1);
     115           0 :                 if (!dirp->dirs) {
     116           0 :                         DEBUG(0,("shadow_copy_fdopendir: Out of memory\n"));
     117           0 :                         break;
     118             :                 }
     119             : 
     120           0 :                 dirp->dirs[dirp->num++] = *d;
     121             :         }
     122             : 
     123           0 :         SMB_VFS_NEXT_CLOSEDIR(handle,p);
     124             :         /* We have now closed the fd in fsp. */
     125           0 :         fsp_set_fd(fsp, -1);
     126           0 :         return((DIR *)dirp);
     127             : }
     128             : 
     129           0 : static struct dirent *shadow_copy_readdir(vfs_handle_struct *handle,
     130             :                                           struct files_struct *dirfsp,
     131             :                                           DIR *_dirp)
     132             : {
     133           0 :         shadow_copy_Dir *dirp = (shadow_copy_Dir *)_dirp;
     134             : 
     135           0 :         if (dirp->pos < dirp->num) {
     136           0 :                 return &(dirp->dirs[dirp->pos++]);
     137             :         }
     138             : 
     139           0 :         return NULL;
     140             : }
     141             : 
     142           0 : static void shadow_copy_rewinddir(struct vfs_handle_struct *handle, DIR *_dirp)
     143             : {
     144           0 :         shadow_copy_Dir *dirp = (shadow_copy_Dir *)_dirp;
     145           0 :         dirp->pos = 0 ;
     146           0 : }
     147             : 
     148           0 : static int shadow_copy_closedir(vfs_handle_struct *handle, DIR *_dirp)
     149             : {
     150           0 :         shadow_copy_Dir *dirp = (shadow_copy_Dir *)_dirp;
     151             : 
     152           0 :         SAFE_FREE(dirp->dirs);
     153           0 :         SAFE_FREE(dirp);
     154             :  
     155           0 :         return 0;       
     156             : }
     157             : 
     158           0 : static int shadow_copy_get_shadow_copy_data(vfs_handle_struct *handle,
     159             :                                             files_struct *fsp,
     160             :                                             struct shadow_copy_data *shadow_copy_data,
     161             :                                             bool labels)
     162             : {
     163           0 :         struct smb_Dir *dir_hnd = NULL;
     164           0 :         const char *dname = NULL;
     165           0 :         char *talloced = NULL;
     166             :         NTSTATUS status;
     167           0 :         struct smb_filename *smb_fname = synthetic_smb_fname(talloc_tos(),
     168           0 :                                                 fsp->conn->connectpath,
     169             :                                                 NULL,
     170             :                                                 NULL,
     171             :                                                 0,
     172             :                                                 0);
     173           0 :         if (smb_fname == NULL) {
     174           0 :                 errno = ENOMEM;
     175           0 :                 return -1;
     176             :         }
     177             : 
     178           0 :         status = OpenDir(talloc_tos(),
     179           0 :                          handle->conn,
     180             :                          smb_fname,
     181             :                          NULL,
     182             :                          0,
     183             :                          &dir_hnd);
     184           0 :         TALLOC_FREE(smb_fname);
     185           0 :         if (!NT_STATUS_IS_OK(status)) {
     186           0 :                 DBG_ERR("OpenDir() failed for [%s]\n", fsp->conn->connectpath);
     187           0 :                 errno = map_errno_from_nt_status(status);
     188           0 :                 return -1;
     189             :         }
     190             : 
     191           0 :         shadow_copy_data->num_volumes = 0;
     192           0 :         shadow_copy_data->labels = NULL;
     193             : 
     194           0 :         while (True) {
     195             :                 SHADOW_COPY_LABEL *tlabels;
     196             :                 int ret;
     197             : 
     198           0 :                 dname = ReadDirName(dir_hnd, &talloced);
     199           0 :                 if (dname == NULL) {
     200           0 :                         break;
     201             :                 }
     202             : 
     203             :                 /* */
     204           0 :                 if (!shadow_copy_match_name(dname)) {
     205           0 :                         DBG_DEBUG("ignore [%s]\n", dname);
     206           0 :                         TALLOC_FREE(talloced);
     207           0 :                         continue;
     208             :                 }
     209             : 
     210           0 :                 DBG_DEBUG("not ignore [%s]\n", dname);
     211             : 
     212           0 :                 if (!labels) {
     213           0 :                         shadow_copy_data->num_volumes++;
     214           0 :                         TALLOC_FREE(talloced);
     215           0 :                         continue;
     216             :                 }
     217             : 
     218           0 :                 tlabels = (SHADOW_COPY_LABEL *)TALLOC_REALLOC(shadow_copy_data,
     219             :                                                                         shadow_copy_data->labels,
     220             :                                                                         (shadow_copy_data->num_volumes+1)*sizeof(SHADOW_COPY_LABEL));
     221           0 :                 if (tlabels == NULL) {
     222           0 :                         DEBUG(0,("shadow_copy_get_shadow_copy_data: Out of memory\n"));
     223           0 :                         TALLOC_FREE(talloced);
     224           0 :                         TALLOC_FREE(dir_hnd);
     225           0 :                         return -1;
     226             :                 }
     227             : 
     228           0 :                 ret = strlcpy(tlabels[shadow_copy_data->num_volumes], dname,
     229             :                               sizeof(tlabels[shadow_copy_data->num_volumes]));
     230           0 :                 if (ret != sizeof(tlabels[shadow_copy_data->num_volumes]) - 1) {
     231           0 :                         DBG_ERR("malformed label %s\n", dname);
     232           0 :                         TALLOC_FREE(talloced);
     233           0 :                         TALLOC_FREE(dir_hnd);
     234           0 :                         return -1;
     235             :                 }
     236           0 :                 shadow_copy_data->num_volumes++;
     237             : 
     238           0 :                 shadow_copy_data->labels = tlabels;
     239           0 :                 TALLOC_FREE(talloced);
     240             :         }
     241             : 
     242           0 :         TALLOC_FREE(dir_hnd);
     243           0 :         return 0;
     244             : }
     245             : 
     246             : static struct vfs_fn_pointers vfs_shadow_copy_fns = {
     247             :         .fdopendir_fn = shadow_copy_fdopendir,
     248             :         .readdir_fn = shadow_copy_readdir,
     249             :         .rewind_dir_fn = shadow_copy_rewinddir,
     250             :         .closedir_fn = shadow_copy_closedir,
     251             :         .get_shadow_copy_data_fn = shadow_copy_get_shadow_copy_data,
     252             : };
     253             : 
     254             : static_decl_vfs;
     255          27 : NTSTATUS vfs_shadow_copy_init(TALLOC_CTX *ctx)
     256             : {
     257          27 :         NTSTATUS ret = smb_register_vfs(SMB_VFS_INTERFACE_VERSION,
     258             :                                         "shadow_copy", &vfs_shadow_copy_fns);
     259             : 
     260          27 :         if (!NT_STATUS_IS_OK(ret))
     261           0 :                 return ret;
     262             : 
     263          27 :         vfs_shadow_copy_debug_level = debug_add_class("shadow_copy");
     264          27 :         if (vfs_shadow_copy_debug_level == -1) {
     265           0 :                 vfs_shadow_copy_debug_level = DBGC_VFS;
     266           0 :                 DEBUG(0, ("%s: Couldn't register custom debugging class!\n",
     267             :                         "vfs_shadow_copy_init"));
     268             :         } else {
     269          27 :                 DEBUG(10, ("%s: Debug class number of '%s': %d\n", 
     270             :                         "vfs_shadow_copy_init","shadow_copy",vfs_shadow_copy_debug_level));
     271             :         }
     272             : 
     273          27 :         return ret;
     274             : }

Generated by: LCOV version 1.14