tags 284274 patch
thanks

Attached is a patch to the program sources (through the use of a dpatch patch
in the Debian package) that adds a new -L / --linkhard option to fdupes. This
option will replace all duplicate files with hardlinks which is useful in
order to reduce space.

It has been tested only slightly, but the code looks (to me) about right.

Please consider this patch and include it in the Debian package.

Regards

Javier
diff -Nru fdupes-1.50-PR2/debian/changelog fdupes-1.50-PR2-2/debian/changelog
--- fdupes-1.50-PR2/debian/changelog	2009-07-31 00:47:23.000000000 +0200
+++ fdupes-1.50-PR2-2/debian/changelog	2009-07-31 00:44:27.000000000 +0200
@@ -1,3 +1,11 @@
+fdupes (1.50-PR2-2.1) unstable; urgency=low
+
+  * debian/patches/50_bts284274_hardlinkreplace.dpatch created.
+    - added -L / --linkhard to make fdupes replace files with hardlinks. Also
+      update the manual page; Closes: 284274
+
+ -- Javier Fernandez-Sanguino Pen~a <j...@debian.org>  Fri, 31 Jul 2009 00:43:11 +0200
+
 fdupes (1.50-PR2-2) unstable; urgency=low
 
   * debian/control
diff -Nru fdupes-1.50-PR2/debian/patches/00list fdupes-1.50-PR2-2/debian/patches/00list
--- fdupes-1.50-PR2/debian/patches/00list	2009-07-31 00:47:23.000000000 +0200
+++ fdupes-1.50-PR2-2/debian/patches/00list	2009-07-31 00:43:02.000000000 +0200
@@ -5,3 +5,4 @@
 20_bts447601_lfs_support
 30_bts481809_manpage_summarize
 40_bts511702_nohidden_support
+50_bts284274_hardlinkreplace
diff -Nru fdupes-1.50-PR2/debian/patches/50_bts284274_hardlinkreplace.dpatch fdupes-1.50-PR2-2/debian/patches/50_bts284274_hardlinkreplace.dpatch
--- fdupes-1.50-PR2/debian/patches/50_bts284274_hardlinkreplace.dpatch	1970-01-01 01:00:00.000000000 +0100
+++ fdupes-1.50-PR2-2/debian/patches/50_bts284274_hardlinkreplace.dpatch	2009-07-31 00:42:42.000000000 +0200
@@ -0,0 +1,228 @@
+#! /bin/sh /usr/share/dpatch/dpatch-run
+## 50_bts284274_hardlinkreplace.dpatch by  <j...@debian.org>
+##
+## All lines beginning with `## DP:' are a description of the patch.
+## DP: No description.
+
+...@dpatch@
+diff -urNad fdupes-1.50-PR2~/fdupes.1 fdupes-1.50-PR2/fdupes.1
+--- fdupes-1.50-PR2~/fdupes.1	2009-07-31 00:38:28.000000000 +0200
++++ fdupes-1.50-PR2/fdupes.1	2009-07-31 00:42:14.000000000 +0200
+@@ -58,10 +58,17 @@
+ .B CAVEATS
+ below)
+ .TP
++.B -L --hardlink
++replace all duplicate files with hardlinks to the
++first file in each set of duplicates
++.TP
+ .B -N --noprompt
+ when used together with \-\-delete, preserve the first file in each
+ set of duplicates and delete the others without prompting the user 
+ .TP
++.B -D --debug
++provide debugging information
++.TP
+ .B -v --version
+ display fdupes version
+ .TP
+diff -urNad fdupes-1.50-PR2~/fdupes.c fdupes-1.50-PR2/fdupes.c
+--- fdupes-1.50-PR2~/fdupes.c	2009-07-31 00:38:28.000000000 +0200
++++ fdupes-1.50-PR2/fdupes.c	2009-07-31 00:41:08.000000000 +0200
+@@ -53,6 +53,8 @@
+ #define F_NOPROMPT          0x0400
+ #define F_SUMMARIZEMATCHES  0x0800
+ #define F_EXCLUDEHIDDEN     0x1000
++#define F_HARDLINKFILES     0x2000
++#define F_DEBUGINFO         0x4000
+ 
+ char *program_name;
+ 
+@@ -881,6 +883,88 @@
+   free(preservestr);
+ }
+ 
++void hardlinkfiles(file_t *files, int debug)
++{
++  int counter;
++  int groups = 0;
++  int curgroup = 0;
++  file_t *tmpfile;
++  file_t *curfile;
++  file_t **dupelist;
++  int max = 0;
++  int x = 0;
++
++  curfile = files;
++  
++  while (curfile) {
++    if (curfile->hasdupes) {
++      counter = 1;
++      groups++;
++
++      tmpfile = curfile->duplicates;
++      while (tmpfile) {
++	counter++;
++	tmpfile = tmpfile->duplicates;
++      }
++      
++      if (counter > max) max = counter;
++    }
++    
++    curfile = curfile->next;
++  }
++
++  max++;
++
++  dupelist = (file_t**) malloc(sizeof(file_t*) * max);
++
++  if (!dupelist) {
++    errormsg("out of memory\n");
++    exit(1);
++  }
++
++  while (files) {
++    if (files->hasdupes) {
++      curgroup++;
++      counter = 1;
++      dupelist[counter] = files;
++
++      if (debug) printf("[%d] %s\n", counter, files->d_name);
++
++      tmpfile = files->duplicates;
++
++      while (tmpfile) {
++	dupelist[++counter] = tmpfile;
++	if (debug) printf("[%d] %s\n", counter, tmpfile->d_name);
++	tmpfile = tmpfile->duplicates;
++      }
++
++      if (debug) printf("\n");
++
++      /* preserve only the first file */
++
++      printf("   [+] %s\n", dupelist[1]->d_name);
++      for (x = 2; x <= counter; x++) { 
++	  if (unlink(dupelist[x]->d_name) == 0) {
++            if ( link(dupelist[1]->d_name, dupelist[x]->d_name) == 0 ) {
++                printf("   [h] %s\n", dupelist[x]->d_name);
++            } else {
++                printf("-- unable to create a hardlink for the file: %s\n", strerror(errno));
++                printf("   [!] %s ", dupelist[x]->d_name);
++            }
++	  } else {
++	    printf("   [!] %s ", dupelist[x]->d_name);
++	    printf("-- unable to delete the file!\n");
++	  }
++	}
++      printf("\n");
++    }
++    
++    files = files->next;
++  }
++
++  free(dupelist);
++}
++
+ int sort_pairs_by_arrival(file_t *f1, file_t *f2)
+ {
+   if (f2->duplicates != 0)
+@@ -971,10 +1055,14 @@
+   printf("                  \twith -s or --symlinks, or when specifying a\n");
+   printf("                  \tparticular directory more than once; refer to the\n");
+   printf("                  \tfdupes documentation for additional information\n");
+-  //printf(" -l --relink      \t(description)\n");
++  /* printf(" -r --dlink     \t(description)\n"); */
++  printf(" -L --linkhard    \thardlink duplicate files to the first file in\n");
++  printf("                  \teach set of duplicates without prompting the user\n");
+   printf(" -N --noprompt    \ttogether with --delete, preserve the first file in\n");
+   printf("                  \teach set of duplicates and delete the rest without\n");
+   printf("                  \twithout prompting the user\n");
++  printf(" -D --debug       \tenable debugging information\n");
++  printf("                  \teach set of duplicates without prompting the user\n");
+   printf(" -v --version     \tdisplay fdupes version\n");
+   printf(" -h --help        \tdisplay this help message\n\n");
+ #ifdef OMIT_GETOPT_LONG
+@@ -1010,12 +1098,14 @@
+     { "symlinks", 0, 0, 's' },
+     { "hardlinks", 0, 0, 'H' },
+     { "relink", 0, 0, 'l' },
++    { "linkhard", 0, 0, 'L' },
+     { "noempty", 0, 0, 'n' },
+     { "nohidden", 0, 0, 'A' },
+     { "delete", 0, 0, 'd' },
+     { "version", 0, 0, 'v' },
+     { "help", 0, 0, 'h' },
+     { "noprompt", 0, 0, 'N' },
++    { "debug", 0, 0, 'D' },
+     { "summarize", 0, 0, 'm'},
+     { "summary", 0, 0, 'm' },
+     { 0, 0, 0, 0 }
+@@ -1029,7 +1119,7 @@
+ 
+   oldargv = cloneargs(argc, argv);
+ 
+-  while ((opt = GETOPT(argc, argv, "frRq1Ss::HlnAdvhNm"
++  while ((opt = GETOPT(argc, argv, "frRq1Ss::HlLnAdDvhNm"
+ #ifndef OMIT_GETOPT_LONG
+           , long_options, NULL
+ #endif
+@@ -1068,6 +1158,12 @@
+     case 'd':
+       SETFLAG(flags, F_DELETEFILES);
+       break;
++    case 'L':
++      SETFLAG(flags, F_HARDLINKFILES);
++      break;
++    case 'D':
++      SETFLAG(flags, F_DEBUGINFO);
++      break;
+     case 'v':
+       printf("fdupes %s\n", VERSION);
+       exit(0);
+@@ -1102,6 +1198,16 @@
+     exit(1);
+   }
+ 
++  if (ISFLAG(flags, F_HARDLINKFILES) && ISFLAG(flags, F_DELETEFILES)) {
++    errormsg("options --linkhard and --delete are not compatible\n");
++    exit(1);
++  }
++
++  if (ISFLAG(flags, F_HARDLINKFILES) && ISFLAG(flags, F_CONSIDERHARDLINKS)) {
++    errormsg("options --linkhard and --hardlinks are not compatible\n");
++    exit(1);
++  }
++
+   if (ISFLAG(flags, F_RECURSEAFTER)) {
+     firstrecurse = nonoptafter("--recurse:", argc, oldargv, argv, optind);
+     
+@@ -1187,12 +1293,23 @@
+ 
+   else 
+ 
+-    if (ISFLAG(flags, F_SUMMARIZEMATCHES))
+-      summarizematches(files);
+-      
+-    else
++    if (ISFLAG(flags, F_HARDLINKFILES))
+ 
+-      printmatches(files);
++        if (ISFLAG(flags, F_DEBUGINFO))
++            hardlinkfiles(files, 1);
++        else
++            hardlinkfiles(files, 0);
++
++    else {
++    
++        if (ISFLAG(flags, F_SUMMARIZEMATCHES))
++            summarizematches(files);
++
++        else
++
++            printmatches(files);
++
++    }
+ 
+   while (files) {
+     curfile = files->next;

Attachment: signature.asc
Description: Digital signature

Reply via email to