LCOV - code coverage report
Current view: top level - src/server/protocol1 - link.c (source / functions) Hit Total Coverage
Test: burp-coverage-clean.info Lines: 4 69 5.8 %
Date: 2016-02-29 Functions: 1 3 33.3 %

          Line data    Source code
       1             : #include "../../burp.h"
       2             : #include "../../alloc.h"
       3             : #include "../../cntr.h"
       4             : #include "../../conf.h"
       5             : #include "../../fsops.h"
       6             : #include "../../fzp.h"
       7             : #include "../../log.h"
       8             : #include "../../prepend.h"
       9             : #include "../child.h"
      10             : #include "link.h"
      11             : 
      12           0 : int recursive_hardlink(const char *src, const char *dst, struct conf **confs)
      13             : {
      14           0 :         int n=-1;
      15           0 :         int ret=0;
      16             :         struct dirent **dir;
      17           0 :         char *tmp=NULL;
      18           0 :         char *fullpatha=NULL;
      19           0 :         char *fullpathb=NULL;
      20             :         //logp("in rec hl: %s %s\n", src, dst);
      21           0 :         if(!(tmp=prepend_s(dst, "dummy"))) return -1;
      22           0 :         if(mkpath(&tmp, dst))
      23             :         {
      24           0 :                 logp("could not mkpath for %s\n", tmp);
      25           0 :                 free_w(&tmp);
      26           0 :                 return -1;
      27             :         }
      28           0 :         free_w(&tmp);
      29             : 
      30           0 :         if((n=scandir(src, &dir, 0, 0))<0)
      31             :         {
      32             :                 logp("recursive_hardlink scandir %s: %s\n",
      33           0 :                         src, strerror(errno));
      34           0 :                 return -1;
      35             :         }
      36           0 :         while(n--)
      37             :         {
      38             :                 struct stat statp;
      39           0 :                 if(dir[n]->d_ino==0
      40           0 :                   || !strcmp(dir[n]->d_name, ".")
      41           0 :                   || !strcmp(dir[n]->d_name, ".."))
      42           0 :                         { free(dir[n]); continue; }
      43           0 :                 free_w(&fullpatha);
      44           0 :                 free_w(&fullpathb);
      45           0 :                 if(!(fullpatha=prepend_s(src, dir[n]->d_name))
      46           0 :                   || !(fullpathb=prepend_s(dst, dir[n]->d_name)))
      47             :                         break;
      48             : 
      49             : #ifdef _DIRENT_HAVE_D_TYPE
      50             : // Faster evaluation on most systems.
      51           0 :                 if(dir[n]->d_type==DT_DIR)
      52             :                 {
      53           0 :                         if(recursive_hardlink(fullpatha, fullpathb, confs))
      54             :                                 break;
      55             :                 }
      56             :                 else
      57             : #endif
      58             :                 // Otherwise, we have to do an lstat() anyway, because we
      59             :                 // will need to check the number of hardlinks in do_link().
      60           0 :                 if(lstat(fullpatha, &statp))
      61             :                 {
      62           0 :                         logp("could not lstat %s\n", fullpatha);
      63             :                 }
      64           0 :                 else if(S_ISDIR(statp.st_mode))
      65             :                 {
      66           0 :                         if(recursive_hardlink(fullpatha, fullpathb, confs))
      67             :                                 break;
      68             :                 }
      69             :                 else
      70             :                 {
      71             :                         //logp("hardlinking %s to %s\n", fullpathb, fullpatha);
      72           0 :                         if(write_status(CNTR_STATUS_SHUFFLING, fullpathb,
      73           0 :                                 get_cntr(confs))
      74           0 :                           || do_link(fullpatha, fullpathb, &statp, confs,
      75           0 :                                 0 /* do not overwrite target */))
      76             :                                 break;
      77             :                 }
      78           0 :                 free(dir[n]);
      79             :         }
      80           0 :         if(n>0)
      81             :         {
      82             :                 ret=-1;
      83           0 :                 for(; n>0; n--) free(dir[n]);
      84             :         }
      85           0 :         free(dir);
      86             : 
      87           0 :         free_w(&fullpatha);
      88           0 :         free_w(&fullpathb);
      89             : 
      90           0 :         return ret;
      91             : }
      92             : 
      93             : #define DUP_CHUNK       4096
      94           0 : static int duplicate_file(const char *oldpath, const char *newpath)
      95             : {
      96           0 :         int ret=-1;
      97           0 :         size_t s=0;
      98           0 :         size_t t=0;
      99           0 :         struct fzp *op=NULL;
     100           0 :         struct fzp *np=NULL;
     101           0 :         char buf[DUP_CHUNK]="";
     102           0 :         if(!(op=fzp_open(oldpath, "rb"))
     103           0 :           || !(np=fzp_open(newpath, "wb")))
     104             :                 goto end;
     105             : 
     106           0 :         while((s=fzp_read(op, buf, DUP_CHUNK))>0)
     107             :         {
     108           0 :                 t=fzp_write(np, buf, s);
     109           0 :                 if(t!=s)
     110             :                 {
     111             :                         logp("could not write all bytes: %lu!=%lu\n",
     112           0 :                                 (unsigned long)s, (unsigned long)t);
     113           0 :                         goto end;
     114             :                 }
     115             :         }
     116             : 
     117             :         ret=0;
     118             : end:
     119           0 :         fzp_close(&np);
     120           0 :         fzp_close(&op);
     121           0 :         if(ret) logp("could not duplicate %s to %s\n", oldpath, newpath);
     122           0 :         return ret;
     123             : }
     124             : 
     125           3 : int do_link(const char *oldpath, const char *newpath, struct stat *statp,
     126             :         struct conf **confs, uint8_t overwrite)
     127             : {
     128             :         /* Avoid creating too many hardlinks */
     129           3 :         if(confs
     130           3 :           && statp->st_nlink >= (unsigned int)get_int(confs[OPT_MAX_HARDLINKS]))
     131             :         {
     132           0 :                 return duplicate_file(oldpath, newpath);
     133             :         }
     134           3 :         else if(link(oldpath, newpath))
     135             :         {
     136           0 :                 if(overwrite && errno==EEXIST)
     137             :                 {
     138           0 :                         unlink(newpath);
     139           0 :                         if(!link(oldpath, newpath))
     140             :                         {
     141             :                                 //logp("Successful hard link of '%s' to '%s' after unlinking the former\n", newpath, oldpath);
     142             :                                 return 0;
     143             :                         }
     144             :                 }
     145             :                 logp("could not hard link '%s' to '%s': %s\n",
     146           0 :                         newpath, oldpath, strerror(errno));
     147           0 :                 return -1;
     148             :         }
     149             :         return 0;
     150             : }

Generated by: LCOV version 1.10