Line data Source code
1 : /* 2 : Bacula® - The Network Backup Solution 3 : 4 : Copyright (C) 2000-2010 Free Software Foundation Europe e.V. 5 : 6 : The main author of Bacula is Kern Sibbald, with contributions from 7 : many others, a complete list can be found in the file AUTHORS. 8 : This program is Free Software; you can redistribute it and/or 9 : modify it under the terms of version three of the GNU Affero General Public 10 : License as published by the Free Software Foundation and included 11 : in the file LICENSE. 12 : 13 : This program is distributed in the hope that it will be useful, but 14 : WITHOUT ANY WARRANTY; without even the implied warranty of 15 : MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 16 : General Public License for more details. 17 : 18 : You should have received a copy of the GNU Affero General Public License 19 : along with this program; if not, write to the Free Software 20 : Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 21 : 02110-1301, USA. 22 : 23 : Bacula® is a registered trademark of Kern Sibbald. 24 : The licensor of Bacula is the Free Software Foundation Europe 25 : (FSFE), Fiduciary Program, Sumatrastrasse 25, 8006 Zürich, 26 : Switzerland, email:ftf@fsfeurope.org. 27 : */ 28 : /* 29 : Code extracted from findlib from bacula-5.0.3, and 30 : heavily modified. Therefore, I have retained the bacula copyright notice. 31 : 32 : Graham Keeling, 2015. 33 : */ 34 : 35 : #include "burp.h" 36 : #include "handy.h" 37 : #include "linkhash.h" 38 : 39 : // List of all hard linked files found. 40 : struct f_link **linkhash=NULL; 41 : 42 : #define LINK_HASHTABLE_BITS 16 43 : #define LINK_HASHTABLE_SIZE (1<<LINK_HASHTABLE_BITS) 44 : #define LINK_HASHTABLE_MASK (LINK_HASHTABLE_SIZE-1) 45 : 46 16 : int linkhash_init(void) 47 : { 48 16 : if(!(linkhash=(struct f_link **)calloc_w(1, 49 : LINK_HASHTABLE_SIZE*sizeof(*linkhash), __func__))) 50 0 : return -1; 51 : return 0; 52 : } 53 : 54 16 : void linkhash_free(void) 55 : { 56 16 : int i; 57 16 : struct f_link *lp; 58 16 : struct f_link *lc; 59 : 60 16 : if(!linkhash) return; 61 : 62 1048592 : for(i=0; i<LINK_HASHTABLE_SIZE; i++) 63 : { 64 : // Free up list of hard linked files. 65 1048576 : lp=linkhash[i]; 66 1048578 : while(lp) 67 : { 68 2 : lc=lp; 69 2 : lp=lp->next; 70 2 : if(lc) 71 : { 72 2 : free_w(&lc->name); 73 2 : free_v((void **)&lc); 74 : } 75 : } 76 1048576 : linkhash[i]=NULL; 77 : } 78 16 : free_v((void **)&linkhash); 79 : } 80 : 81 5 : static inline int get_hash(struct stat *statp) 82 : { 83 5 : int hash=statp->st_dev; 84 5 : uint64_t i=statp->st_ino; 85 5 : hash ^= i; 86 5 : i >>= 16; 87 5 : hash ^= i; 88 5 : i >>= 16; 89 5 : hash ^= i; 90 5 : i >>= 16; 91 5 : hash ^= i; 92 5 : return hash & LINK_HASHTABLE_MASK; 93 : } 94 : 95 5 : struct f_link *linkhash_search(struct stat *statp, struct f_link ***bucket) 96 : { 97 5 : struct f_link *lp; 98 5 : *bucket=&linkhash[get_hash(statp)]; 99 5 : for(lp=**bucket; lp; lp=lp->next) 100 2 : if(lp->ino==(ino_t)statp->st_ino 101 2 : && lp->dev==(dev_t)statp->st_dev) 102 2 : return lp; 103 : return NULL; 104 : } 105 : 106 2 : int linkhash_add(char *fname, struct stat *statp, struct f_link **bucket) 107 : { 108 2 : struct f_link *new_fl; 109 2 : if(!(new_fl=(struct f_link *)malloc_w(sizeof(struct f_link), __func__)) 110 2 : || !(new_fl->name=strdup_w(fname, __func__))) 111 0 : return -1; 112 2 : new_fl->ino=statp->st_ino; 113 2 : new_fl->dev=statp->st_dev; 114 2 : new_fl->next=*bucket; 115 2 : *bucket=new_fl; 116 2 : return 0; 117 : }