LCOV - code coverage report
Current view: top level - source3/modules - vfs_shadow_copy.c (source / functions) Hit Total Coverage
Test: coverage report for v4-17-test 1498b464 Lines: 7 114 6.1 %
Date: 2024-06-13 04:01:37 Functions: 1 9 11.1 %

          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             : 
      24             : /*
      25             :     Please read the VFS module Samba-HowTo-Collection.
      26             :     there's a chapter about this module
      27             : 
      28             :     For this share
      29             :     Z:\
      30             : 
      31             :     the ShadowCopies are in this directories
      32             : 
      33             :     Z:\@GMT-2003.08.05-12.00.00\
      34             :     Z:\@GMT-2003.08.05-12.01.00\
      35             :     Z:\@GMT-2003.08.05-12.02.00\
      36             : 
      37             :     e.g.
      38             :     
      39             :     Z:\testfile.txt
      40             :     Z:\@GMT-2003.08.05-12.02.00\testfile.txt
      41             : 
      42             :     or:
      43             : 
      44             :     Z:\testdir\testfile.txt
      45             :     Z:\@GMT-2003.08.05-12.02.00\testdir\testfile.txt
      46             : 
      47             : 
      48             :     Note: Files must differ to be displayed via Windows Explorer!
      49             :           Directories are always displayed...    
      50             : */
      51             : 
      52             : static int vfs_shadow_copy_debug_level = DBGC_VFS;
      53             : 
      54             : #undef DBGC_CLASS
      55             : #define DBGC_CLASS vfs_shadow_copy_debug_level
      56             : 
      57             : #define SHADOW_COPY_PREFIX "@GMT-"
      58             : #define SHADOW_COPY_SAMPLE "@GMT-2004.02.18-15.44.00"
      59             : 
      60             : typedef struct {
      61             :         int pos;
      62             :         int num;
      63             :         struct dirent *dirs;
      64             : } shadow_copy_Dir;
      65             : 
      66           0 : static bool shadow_copy_match_name(const char *name)
      67             : {
      68           0 :         if (strncmp(SHADOW_COPY_PREFIX,name, sizeof(SHADOW_COPY_PREFIX)-1)==0 &&
      69           0 :                 (strlen(SHADOW_COPY_SAMPLE) == strlen(name))) {
      70           0 :                 return True;
      71             :         }
      72             : 
      73           0 :         return False;
      74             : }
      75             : 
      76           0 : static DIR *shadow_copy_fdopendir(vfs_handle_struct *handle, files_struct *fsp, const char *mask, uint32_t attr)
      77             : {
      78             :         shadow_copy_Dir *dirp;
      79           0 :         DIR *p = SMB_VFS_NEXT_FDOPENDIR(handle,fsp,mask,attr);
      80             : 
      81           0 :         if (!p) {
      82           0 :                 DEBUG(10,("shadow_copy_opendir: SMB_VFS_NEXT_FDOPENDIR() failed for [%s]\n",
      83             :                         smb_fname_str_dbg(fsp->fsp_name)));
      84           0 :                 return NULL;
      85             :         }
      86             : 
      87           0 :         dirp = SMB_MALLOC_P(shadow_copy_Dir);
      88           0 :         if (!dirp) {
      89           0 :                 DEBUG(0,("shadow_copy_fdopendir: Out of memory\n"));
      90           0 :                 SMB_VFS_NEXT_CLOSEDIR(handle,p);
      91             :                 /* We have now closed the fd in fsp. */
      92           0 :                 fsp_set_fd(fsp, -1);
      93           0 :                 return NULL;
      94             :         }
      95             : 
      96           0 :         ZERO_STRUCTP(dirp);
      97             : 
      98           0 :         while (True) {
      99             :                 struct dirent *d;
     100             : 
     101           0 :                 d = SMB_VFS_NEXT_READDIR(handle, fsp, p, NULL);
     102           0 :                 if (d == NULL) {
     103           0 :                         break;
     104             :                 }
     105             : 
     106           0 :                 if (shadow_copy_match_name(d->d_name)) {
     107           0 :                         DEBUG(8,("shadow_copy_fdopendir: hide [%s]\n",d->d_name));
     108           0 :                         continue;
     109             :                 }
     110             : 
     111           0 :                 DEBUG(10,("shadow_copy_fdopendir: not hide [%s]\n",d->d_name));
     112             : 
     113           0 :                 dirp->dirs = SMB_REALLOC_ARRAY(dirp->dirs,struct dirent, dirp->num+1);
     114           0 :                 if (!dirp->dirs) {
     115           0 :                         DEBUG(0,("shadow_copy_fdopendir: Out of memory\n"));
     116           0 :                         break;
     117             :                 }
     118             : 
     119           0 :                 dirp->dirs[dirp->num++] = *d;
     120             :         }
     121             : 
     122           0 :         SMB_VFS_NEXT_CLOSEDIR(handle,p);
     123             :         /* We have now closed the fd in fsp. */
     124           0 :         fsp_set_fd(fsp, -1);
     125           0 :         return((DIR *)dirp);
     126             : }
     127             : 
     128           0 : static struct dirent *shadow_copy_readdir(vfs_handle_struct *handle,
     129             :                                           struct files_struct *dirfsp,
     130             :                                           DIR *_dirp,
     131             :                                           SMB_STRUCT_STAT *sbuf)
     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_seekdir(struct vfs_handle_struct *handle, DIR *_dirp, long offset)
     143             : {
     144           0 :         shadow_copy_Dir *dirp = (shadow_copy_Dir *)_dirp;
     145             : 
     146           0 :         if (offset < dirp->num) {
     147           0 :                 dirp->pos = offset ;
     148             :         }
     149           0 : }
     150             : 
     151           0 : static long shadow_copy_telldir(struct vfs_handle_struct *handle, DIR *_dirp)
     152             : {
     153           0 :         shadow_copy_Dir *dirp = (shadow_copy_Dir *)_dirp;
     154           0 :         return( dirp->pos ) ;
     155             : }
     156             : 
     157           0 : static void shadow_copy_rewinddir(struct vfs_handle_struct *handle, DIR *_dirp)
     158             : {
     159           0 :         shadow_copy_Dir *dirp = (shadow_copy_Dir *)_dirp;
     160           0 :         dirp->pos = 0 ;
     161           0 : }
     162             : 
     163           0 : static int shadow_copy_closedir(vfs_handle_struct *handle, DIR *_dirp)
     164             : {
     165           0 :         shadow_copy_Dir *dirp = (shadow_copy_Dir *)_dirp;
     166             : 
     167           0 :         SAFE_FREE(dirp->dirs);
     168           0 :         SAFE_FREE(dirp);
     169             :  
     170           0 :         return 0;       
     171             : }
     172             : 
     173           0 : static int shadow_copy_get_shadow_copy_data(vfs_handle_struct *handle,
     174             :                                             files_struct *fsp,
     175             :                                             struct shadow_copy_data *shadow_copy_data,
     176             :                                             bool labels)
     177             : {
     178           0 :         struct smb_Dir *dir_hnd = NULL;
     179           0 :         const char *dname = NULL;
     180           0 :         char *talloced = NULL;
     181           0 :         long offset = 0;
     182             :         NTSTATUS status;
     183           0 :         struct smb_filename *smb_fname = synthetic_smb_fname(talloc_tos(),
     184           0 :                                                 fsp->conn->connectpath,
     185             :                                                 NULL,
     186             :                                                 NULL,
     187             :                                                 0,
     188             :                                                 0);
     189           0 :         if (smb_fname == NULL) {
     190           0 :                 errno = ENOMEM;
     191           0 :                 return -1;
     192             :         }
     193             : 
     194           0 :         status = OpenDir(talloc_tos(),
     195           0 :                          handle->conn,
     196             :                          smb_fname,
     197             :                          NULL,
     198             :                          0,
     199             :                          &dir_hnd);
     200           0 :         TALLOC_FREE(smb_fname);
     201           0 :         if (!NT_STATUS_IS_OK(status)) {
     202           0 :                 DBG_ERR("OpenDir() failed for [%s]\n", fsp->conn->connectpath);
     203           0 :                 errno = map_errno_from_nt_status(status);
     204           0 :                 return -1;
     205             :         }
     206             : 
     207           0 :         shadow_copy_data->num_volumes = 0;
     208           0 :         shadow_copy_data->labels = NULL;
     209             : 
     210           0 :         while (True) {
     211             :                 SHADOW_COPY_LABEL *tlabels;
     212             :                 int ret;
     213             : 
     214           0 :                 dname = ReadDirName(dir_hnd, &offset, NULL, &talloced);
     215           0 :                 if (dname == NULL) {
     216           0 :                         break;
     217             :                 }
     218             : 
     219             :                 /* */
     220           0 :                 if (!shadow_copy_match_name(dname)) {
     221           0 :                         DBG_DEBUG("ignore [%s]\n", dname);
     222           0 :                         TALLOC_FREE(talloced);
     223           0 :                         continue;
     224             :                 }
     225             : 
     226           0 :                 DBG_DEBUG("not ignore [%s]\n", dname);
     227             : 
     228           0 :                 if (!labels) {
     229           0 :                         shadow_copy_data->num_volumes++;
     230           0 :                         TALLOC_FREE(talloced);
     231           0 :                         continue;
     232             :                 }
     233             : 
     234           0 :                 tlabels = (SHADOW_COPY_LABEL *)TALLOC_REALLOC(shadow_copy_data,
     235             :                                                                         shadow_copy_data->labels,
     236             :                                                                         (shadow_copy_data->num_volumes+1)*sizeof(SHADOW_COPY_LABEL));
     237           0 :                 if (tlabels == NULL) {
     238           0 :                         DEBUG(0,("shadow_copy_get_shadow_copy_data: Out of memory\n"));
     239           0 :                         TALLOC_FREE(talloced);
     240           0 :                         TALLOC_FREE(dir_hnd);
     241           0 :                         return -1;
     242             :                 }
     243             : 
     244           0 :                 ret = strlcpy(tlabels[shadow_copy_data->num_volumes], dname,
     245             :                               sizeof(tlabels[shadow_copy_data->num_volumes]));
     246           0 :                 if (ret != sizeof(tlabels[shadow_copy_data->num_volumes]) - 1) {
     247           0 :                         DBG_ERR("malformed label %s\n", dname);
     248           0 :                         TALLOC_FREE(talloced);
     249           0 :                         TALLOC_FREE(dir_hnd);
     250           0 :                         return -1;
     251             :                 }
     252           0 :                 shadow_copy_data->num_volumes++;
     253             : 
     254           0 :                 shadow_copy_data->labels = tlabels;
     255           0 :                 TALLOC_FREE(talloced);
     256             :         }
     257             : 
     258           0 :         TALLOC_FREE(dir_hnd);
     259           0 :         return 0;
     260             : }
     261             : 
     262             : static struct vfs_fn_pointers vfs_shadow_copy_fns = {
     263             :         .fdopendir_fn = shadow_copy_fdopendir,
     264             :         .readdir_fn = shadow_copy_readdir,
     265             :         .seekdir_fn = shadow_copy_seekdir,
     266             :         .telldir_fn = shadow_copy_telldir,
     267             :         .rewind_dir_fn = shadow_copy_rewinddir,
     268             :         .closedir_fn = shadow_copy_closedir,
     269             :         .get_shadow_copy_data_fn = shadow_copy_get_shadow_copy_data,
     270             : };
     271             : 
     272             : static_decl_vfs;
     273          26 : NTSTATUS vfs_shadow_copy_init(TALLOC_CTX *ctx)
     274             : {
     275          26 :         NTSTATUS ret = smb_register_vfs(SMB_VFS_INTERFACE_VERSION,
     276             :                                         "shadow_copy", &vfs_shadow_copy_fns);
     277             : 
     278          26 :         if (!NT_STATUS_IS_OK(ret))
     279           0 :                 return ret;
     280             : 
     281          26 :         vfs_shadow_copy_debug_level = debug_add_class("shadow_copy");
     282          26 :         if (vfs_shadow_copy_debug_level == -1) {
     283           0 :                 vfs_shadow_copy_debug_level = DBGC_VFS;
     284           0 :                 DEBUG(0, ("%s: Couldn't register custom debugging class!\n",
     285             :                         "vfs_shadow_copy_init"));
     286             :         } else {
     287          26 :                 DEBUG(10, ("%s: Debug class number of '%s': %d\n", 
     288             :                         "vfs_shadow_copy_init","shadow_copy",vfs_shadow_copy_debug_level));
     289             :         }
     290             : 
     291          26 :         return ret;
     292             : }

Generated by: LCOV version 1.13