Upgrading to GitLab 11.10.0. Expect errors and see debian-infrastructure-announce@lists.debian.org for further information.

Imported Upstream version 1.6.2

parent f90ccd93
jdupes 1.6.2
- Fix: version number shown in jdupes -v wasn't updated in 1.6.1
- Prevent BTRFS dedupe of more files than the kernel can handle
- Track directories to avoid scanning the same directory twice
jdupes 1.6.1
- Show backslash instead of forward slash as path separator on Windows
- Make BTRFS dedupe error messages more informative and less confusing
- Minor code tweaks, typo and help text fixes
- Split some functions into separate files (jdupes.c was getting large)
jdupes 1.6
- Add the -l/--linksoft option to create symbolic links from duplicates
......
......@@ -98,7 +98,7 @@ INSTALL_DATA = $(INSTALL) -c -m 0644
# to support features not supplied by their vendor. Eg: GNU getopt()
#ADDITIONAL_OBJECTS += getopt.o
OBJECT_FILES += jdupes.o jody_hash.o string_malloc.o $(ADDITIONAL_OBJECTS)
OBJECT_FILES += jdupes.o jody_hash.o jody_paths.o jody_sort.o string_malloc.o $(ADDITIONAL_OBJECTS)
all: jdupes
......
......@@ -23,7 +23,7 @@ and even if they do, they don't support Unicode and other Windows-specific
quirks and features.
jdupes is generally stable. All releases of jdupes are compared against a
known working reference version of fdupes or jdupes to be certain that
known working reference versions of fdupes or jdupes to be certain that
output does not change. You get the benefits of an aggressive development
process without putting your data at increased risk.
......@@ -31,7 +31,7 @@ Code in jdupes is written with data loss avoidance as the highest priority.
If a choice must be made between being aggressive or careful, the careful
way is always chosen.
jdupes includes features that are not found in fdupes. Examples of
jdupes includes features that are not always found elsewhere. Examples of
such features include btrfs block-level deduplication and control over
which file is kept when a match set is automatically deleted. jdupes is
not afraid of dropping features of low value; a prime example is the -1
......@@ -44,7 +44,10 @@ be held responsible. If you notice a bug, please report it.
While jdupes maintains some degree of compatibility with fdupes from which
it was originally derived, there is no guarantee that it will continue to
maintain such compatibility in the future.
maintain such compatibility in the future. However, compatibility will be
retained between minor versions, i.e. jdupes-1.6 and jdupes-1.6.1 should
not have any significant differences in results with identical command
lines.
What jdupes is not: a similar (but not identical) file finding tool
......@@ -80,7 +83,7 @@ Usage: jdupes [options] DIRECTORY...
hard links are treated as non-duplicates for safety
-i --reverse reverse (invert) the match sort order
-I --isolate files in the same specified directory won't match
-l --linksoft symbolically link all duplicate files without prompting
-l --linksoft make relative symlinks for duplicates w/o prompting
-L --linkhard hard link all duplicate files without prompting
Windows allows a maximum of 1023 hard links per file
-m --summarize summarize dupe information
......@@ -167,7 +170,7 @@ file. If more than 1023 links are created for a file, an error results."
(The number is actually 1024, but they're ignoring the first file.)
The Current jdupes Algorithm's "Triangle Problem"
The current jdupes algorithm's "triangle problem"
--------------------------------------------------------------------------
Pairs of files are excluded individually based on how the two files compare.
For example, if --hardlinks is not specified then two files which are hard
......@@ -216,7 +219,10 @@ Legal Information and Software License
--------------------------------------------------------------------------
jdupes is Copyright (C) 2015-2016 by Jody Bruchon <jody@jodybruchon.com>
Derived from the original 'fdupes' (C) 1999-2016 by Adrian Lopez
Includes jody_hash and string_malloc, (C) 2015-2016 Jody Bruchon
Includes jody_hash, jody_paths, jody_sort, and string_malloc, all of
which are (C) 2015-2016 Jody Bruchon
The MIT License
Permission is hereby granted, free of charge, to any person
obtaining a copy of this software and associated documentation files
......
This diff is collapsed.
/* Jody Bruchon's path manipulation code library
* *
* * Copyright (C) 2014-2016 by Jody Bruchon <jody@jodybruchon.com>
* * Released under The MIT License or GNU GPL v2 (your choice)
* */
#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include "jody_paths.h"
/* Collapse dot-dot and single dot path components
* This code MUST be passed a full file pathname (starting with '/') */
extern int collapse_dotdot(char * const path)
{
char *p; /* string copy input */
char *out; /* string copy output */
unsigned int i = 0;
/* Fail if not passed an absolute path */
if (*path != '/') return -1;
p = path; out = path;
while (*p != '\0') {
/* Abort if we're too close to the end of the buffer */
if (i >= (PATHBUF_SIZE - 3)) return -2;
/* Skip repeated slashes */
while (*p == '/' && *(p + 1) == '/') {
p++; i++;
}
/* Scan for '/./', '/..', '/.\0' combinations */
if (*p == '/' && *(p + 1) == '.'
&& (*(p + 2) == '.' || *(p + 2) == '/' || *(p + 2) == '\0')) {
/* Check for '../' or terminal '..' */
if (*(p + 2) == '.' && (*(p + 3) == '/' || *(p + 3) == '\0')) {
/* Found a dot-dot; pull everything back to the previous directory */
p += 3; i += 3;
/* If already at root, skip over the dot-dot */
if (i == 0) continue;
/* Don't seek back past the first character */
if ((uintptr_t)out == (uintptr_t)path) continue;
out--;
while (*out != '/') out--;
if (*p == '\0') break;
continue;
} else if (*(p + 2) == '/' || *(p + 2) == '\0') {
/* Found a single dot; seek input ptr past it */
p += 2; i += 2;
if (*p == '\0') break;
continue;
}
/* Fall through: not a dot or dot-dot, just a slash */
}
/* Copy all remaining text */
*out = *p;
p++; out++; i++;
}
/* If only a root slash remains, be sure to keep it */
if ((uintptr_t)out == (uintptr_t)path) {
*out = '/';
out++;
}
/* Output must always be terminated properly */
*out = '\0';
return 0;
}
/* Create a relative symbolic link path for a destination file */
extern int make_relative_link_name(const char * const src,
const char * const dest, char * rel_path)
{
static char p1[PATHBUF_SIZE * 2], p2[PATHBUF_SIZE * 2];
static char *sp, *dp, *ss;
if (!src || !dest) goto error_null_param;
/* Get working directory path and prefix to pathnames if needed */
if (*src != '/' || *dest != '/') {
if (!getcwd(p1, PATHBUF_SIZE * 2)) goto error_getcwd;
*(p1 + (PATHBUF_SIZE * 2) - 1) = '\0';
strncat(p1, "/", PATHBUF_SIZE * 2);
strncpy(p2, p1, PATHBUF_SIZE * 2);
}
/* If an absolute path is provided, use it as-is */
if (*src == '/') *p1 = '\0';
if (*dest == '/') *p2 = '\0';
/* Concatenate working directory to relative paths */
strncat(p1, src, PATHBUF_SIZE);
strncat(p2, dest, PATHBUF_SIZE);
/* Collapse . and .. path components */
if (collapse_dotdot(p1) != 0) goto error_cdd;
if (collapse_dotdot(p2) != 0) goto error_cdd;
/* Find where paths differ, remembering each slash along the way */
sp = p1; dp = p2; ss = p1;
while (*sp == *dp && *sp != '\0' && *dp != '\0') {
if (*sp == '/') ss = sp;
sp++; dp++;
}
/* If paths are 100% identical then the files are the same file */
if (*sp == '\0' && *dp == '\0') return 1;
/* Replace dirs in destination path with dot-dot */
while (*dp != '\0') {
if (*dp == '/') {
*rel_path++ = '.'; *rel_path++ = '.'; *rel_path++ = '/';
}
dp++;
}
/* Copy the file name into rel_path and return */
ss++;
while (*ss != '\0') *rel_path++ = *ss++;
/* . and .. dirs at end are invalid */
if (*(rel_path - 1) == '.')
if (*(rel_path - 2) == '/' ||
(*(rel_path - 2) == '.' && *(rel_path - 3) == '/'))
goto error_dir_end;
if (*(rel_path - 1) == '/') goto error_dir_end;
*rel_path = '\0';
return 0;
error_null_param:
fprintf(stderr, "Internal error: get_relative_name has NULL parameter\n");
fprintf(stderr, "Report this as a serious bug to the author\n");
exit(EXIT_FAILURE);
error_getcwd:
fprintf(stderr, "error: couldn't get the current directory\n");
return -1;
error_cdd:
fprintf(stderr, "internal error: collapse_dotdot() call failed\n");
return -2;
error_dir_end:
fprintf(stderr, "internal error: get_relative_name() result has directory at end\n");
return -3;
}
/* Jody Bruchon's path manipulation code library
*
* Copyright (C) 2014-2016 by Jody Bruchon <jody@jodybruchon.com>
* Released under The MIT License or GNU GPL v2 (your choice)
*/
#ifndef JODY_PATHS_H
#define JODY_PATHS_H
#ifdef __cplusplus
extern "C" {
#endif
#ifndef PATHBUF_SIZE
#define PATHBUF_SIZE 4096
#endif
extern int collapse_dotdot(char * const path);
extern int make_relative_link_name(const char * const src,
const char * const dest, char * rel_path);
#ifdef __cplusplus
}
#endif
#endif /* JODY_PATHS_H */
/* Jody Bruchon's sorting code library
*
* Copyright (C) 2014-2016 by Jody Bruchon <jody@jodybruchon.com>
* Released under The MIT License or GNU GPL v2 (your choice)
*/
#include "jody_sort.h"
#define IS_NUM(a) (((a >= '0') && (a <= '9')) ? 1 : 0)
extern int numeric_sort(const char * restrict c1,
const char * restrict c2, int sort_direction)
{
int len1 = 0, len2 = 0;
int precompare = 0;
/* Numerically correct sort */
while (*c1 != '\0' && *c2 != '\0') {
/* Reset string length counters */
len1 = 0; len2 = 0;
/* Skip all sequences of zeroes */
while (*c1 == '0') {
len1++;
c1++;
}
while (*c2 == '0') {
len2++;
c2++;
}
/* If both chars are numeric, do a numeric comparison */
if (IS_NUM(*c1) && IS_NUM(*c2)) {
precompare = 0;
/* Scan numbers and get preliminary results */
while (IS_NUM(*c1) && IS_NUM(*c2)) {
if (*c1 < *c2) precompare = -sort_direction;
if (*c1 > *c2) precompare = sort_direction;
len1++; len2++;
c1++; c2++;
/* Skip remaining digit pairs after any
* difference is found */
if (precompare != 0) {
while (IS_NUM(*c1) && IS_NUM(*c2)) {
len1++; len2++;
c1++; c2++;
}
break;
}
}
/* One numeric and one non-numeric means the
* numeric one is larger and sorts later */
if (IS_NUM(*c1) ^ IS_NUM(*c2)) {
if (IS_NUM(*c1)) return sort_direction;
else return -sort_direction;
}
/* If the last test fell through, numbers are
* of equal length. Use the precompare result
* as the result for this number comparison. */
if (precompare != 0) return precompare;
}
/* Do normal comparison */
if (*c1 == *c2) {
c1++; c2++;
len1++; len2++;
/* Put symbols and spaces after everything else */
} else if (*c2 < '.' && *c1 >= '.') return -sort_direction;
else if (*c1 < '.' && *c2 >= '.') return sort_direction;
/* Normal strcmp() style compare */
else if (*c1 > *c2) return sort_direction;
else return -sort_direction;
}
/* Longer strings generally sort later */
if (len1 < len2) return -sort_direction;
if (len1 > len2) return sort_direction;
/* Normal strcmp() style comparison */
if (*c1 == '\0' && *c2 != '\0') return -sort_direction;
if (*c1 != '\0' && *c2 == '\0') return sort_direction;
/* Fall through: the strings are equal */
return 0;
}
/* Jody Bruchon's sorting code library
*
* Copyright (C) 2014-2016 by Jody Bruchon <jody@jodybruchon.com>
* Released under The MIT License or GNU GPL v2 (your choice)
*/
#ifndef JODY_SORT_H
#define JODY_SORT_H
#ifdef __cplusplus
extern "C" {
#endif
extern int numeric_sort(const char * restrict c1,
const char * restrict c2, int sort_direction);
#ifdef __cplusplus
}
#endif
#endif /* JODY_SORT_H */
......@@ -3,7 +3,7 @@
#ifndef JDUPES_VERSION_H
#define JDUPES_VERSION_H
#define VER "1.6"
#define VERDATE "2016-11-27"
#define VER "1.6.2"
#define VERDATE "2016-12-03"
#endif /* JDUPES_VERSION_H */
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment