Main Page   Alphabetical List   Data Structures   File List   Data Fields   Globals   Related Pages  

hlink.c

Go to the documentation of this file.
00001 /* 
00002    Copyright (C) Andrew Tridgell 1996
00003    Copyright (C) Paul Mackerras 1996
00004    Copyright (C) 2002 by Martin Pool <mbp@samba.org>
00005    
00006    This program is free software; you can redistribute it and/or modify
00007    it under the terms of the GNU General Public License as published by
00008    the Free Software Foundation; either version 2 of the License, or
00009    (at your option) any later version.
00010    
00011    This program is distributed in the hope that it will be useful,
00012    but WITHOUT ANY WARRANTY; without even the implied warranty of
00013    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00014    GNU General Public License for more details.
00015    
00016    You should have received a copy of the GNU General Public License
00017    along with this program; if not, write to the Free Software
00018    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
00019 */
00020 
00021 #include "rsync.h"
00022 
00023 extern int dry_run;
00024 extern int verbose;
00025 
00026 #if SUPPORT_HARD_LINKS
00027 static int hlink_compare(struct file_struct *f1, struct file_struct *f2)
00028 {
00029         if (!S_ISREG(f1->mode) && !S_ISREG(f2->mode))
00030                 return 0;
00031         if (!S_ISREG(f1->mode))
00032                 return -1;
00033         if (!S_ISREG(f2->mode))
00034                 return 1;
00035 
00036         if (f1->dev != f2->dev)
00037                 return (int) (f1->dev > f2->dev ? 1 : -1);
00038 
00039         if (f1->inode != f2->inode)
00040                 return (int) (f1->inode > f2->inode ? 1 : -1);
00041 
00042         return file_compare(&f1, &f2);
00043 }
00044 
00045 
00046 static struct file_struct *hlink_list;
00047 static int hlink_count;
00048 #endif
00049 
00050 void init_hard_links(struct file_list *flist)
00051 {
00052 #if SUPPORT_HARD_LINKS
00053         int i;
00054         if (flist->count < 2)
00055                 return;
00056 
00057         if (hlink_list)
00058                 free(hlink_list);
00059 
00060         if (!(hlink_list =
00061               (struct file_struct *) malloc(sizeof(hlink_list[0]) *
00062                                             flist->count)))
00063                 out_of_memory("init_hard_links");
00064 
00065         for (i = 0; i < flist->count; i++)
00066                 memcpy(&hlink_list[i], flist->files[i],
00067                        sizeof(hlink_list[0]));
00068 
00069         qsort(hlink_list, flist->count,
00070               sizeof(hlink_list[0]), (int (*)()) hlink_compare);
00071 
00072         hlink_count = flist->count;
00073 #endif
00074 }
00075 
00076 /* check if a file should be skipped because it is the same as an
00077    earlier hard link */
00078 int check_hard_link(struct file_struct *file)
00079 {
00080 #if SUPPORT_HARD_LINKS
00081         int low = 0, high = hlink_count - 1;
00082         int ret = 0;
00083 
00084         if (!hlink_list || !S_ISREG(file->mode))
00085                 return 0;
00086 
00087         while (low != high) {
00088                 int mid = (low + high) / 2;
00089                 ret = hlink_compare(&hlink_list[mid], file);
00090                 if (ret == 0) {
00091                         low = mid;
00092                         break;
00093                 }
00094                 if (ret > 0)
00095                         high = mid;
00096                 else
00097                         low = mid + 1;
00098         }
00099 
00100         /* XXX: To me this looks kind of dodgy -- why do we use [low]
00101          * here and [low-1] below? -- mbp */
00102         if (hlink_compare(&hlink_list[low], file) != 0)
00103                 return 0;
00104 
00105         if (low > 0 &&
00106             S_ISREG(hlink_list[low - 1].mode) &&
00107             file->dev == hlink_list[low - 1].dev &&
00108             file->inode == hlink_list[low - 1].inode) {
00109                 if (verbose >= 2) {
00110                         rprintf(FINFO, "check_hard_link: \"%s\" is a hard link to file %d, \"%s\"\n",
00111                                 f_name(file), low-1, f_name(&hlink_list[low-1]));
00112                 }
00113                 return 1;
00114         }
00115 #endif
00116 
00117         return 0;
00118 }
00119 
00120 
00121 #if SUPPORT_HARD_LINKS
00122 static void hard_link_one(int i)
00123 {
00124         STRUCT_STAT st1, st2;
00125 
00126         if (link_stat(f_name(&hlink_list[i - 1]), &st1) != 0)
00127                 return;
00128 
00129         if (link_stat(f_name(&hlink_list[i]), &st2) != 0) {
00130                 if (do_link
00131                     (f_name(&hlink_list[i - 1]),
00132                      f_name(&hlink_list[i])) != 0) {
00133                         if (verbose > 0)
00134                                 rprintf(FINFO, "link %s => %s : %s\n",
00135                                         f_name(&hlink_list[i]),
00136                                         f_name(&hlink_list[i - 1]),
00137                                         strerror(errno));
00138                         return;
00139                 }
00140         } else {
00141                 if (st2.st_dev == st1.st_dev && st2.st_ino == st1.st_ino)
00142                         return;
00143 
00144                 if (robust_unlink(f_name(&hlink_list[i])) != 0 ||
00145                     do_link(f_name(&hlink_list[i - 1]),
00146                             f_name(&hlink_list[i])) != 0) {
00147                         if (verbose > 0)
00148                                 rprintf(FINFO, "link %s => %s : %s\n",
00149                                         f_name(&hlink_list[i]),
00150                                         f_name(&hlink_list[i - 1]),
00151                                         strerror(errno));
00152                         return;
00153                 }
00154         }
00155         if (verbose > 0)
00156                 rprintf(FINFO, "%s => %s\n",
00157                         f_name(&hlink_list[i]),
00158                         f_name(&hlink_list[i - 1]));
00159 }
00160 #endif
00161 
00162 
00163 
00164 /**
00165  * Create any hard links in the global hlink_list.  They were put
00166  * there by running init_hard_links on the filelist.
00167  **/
00168 void do_hard_links(void)
00169 {
00170 #if SUPPORT_HARD_LINKS
00171         int i;
00172 
00173         if (!hlink_list)
00174                 return;
00175 
00176         for (i = 1; i < hlink_count; i++) {
00177                 if (S_ISREG(hlink_list[i].mode) &&
00178                     S_ISREG(hlink_list[i - 1].mode) &&
00179                     hlink_list[i].basename && hlink_list[i - 1].basename &&
00180                     hlink_list[i].dev == hlink_list[i - 1].dev &&
00181                     hlink_list[i].inode == hlink_list[i - 1].inode) {
00182                         hard_link_one(i);
00183                 }
00184         }
00185 #endif
00186 }

Generated on Tue Apr 16 12:37:36 2002 for rsync by doxygen1.2.15