Script 'mail_helper' called by obssrc Hello community, here is the log from the commit of package jdupes for openSUSE:Factory checked in at 2022-12-07 17:35:21 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/jdupes (Old) and /work/SRC/openSUSE:Factory/.jdupes.new.1835 (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "jdupes" Wed Dec 7 17:35:21 2022 rev:3 rq:1040814 version:1.21.1 Changes: -------- --- /work/SRC/openSUSE:Factory/jdupes/jdupes.changes 2022-03-22 19:39:51.799068706 +0100 +++ /work/SRC/openSUSE:Factory/.jdupes.new.1835/jdupes.changes 2022-12-07 17:36:41.669107316 +0100 @@ -1,0 +2,16 @@ +Tue Dec 6 21:35:51 UTC 2022 - Dirk Müller <dmuel...@suse.com> + +- update to 1.21.1: + * Reinstate '-I/--isolate' by popular demand; use at your own risk! + * Expect to lose data if you use this feature. It is strongly susceptible + to the documented "triangle problem" and absolutely does not protect + files in each directory from matching with one another. Don't get mad at + me if you use it and see a cloud of smoke come out of your disk array. + * Remove '-I/--isolate' which has never worked correctly + * Fix compiling when NO_HARDLINKS and NO_SYMLINKS are both defined + * Increased stack size limits to enable deeper recursion without crashing + * Fixes to make compilation under Cygwin (instead of MSYS2 MinGW) work + * Remove the temporary '-X help' warning about changes in functionality + * Some minor under-the-hood changes for future enhancements + +------------------------------------------------------------------- Old: ---- v1.20.2.tar.gz New: ---- v1.21.1.tar.gz ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ jdupes.spec ++++++ --- /var/tmp/diff_new_pack.c2mZNx/_old 2022-12-07 17:36:42.125109813 +0100 +++ /var/tmp/diff_new_pack.c2mZNx/_new 2022-12-07 17:36:42.129109835 +0100 @@ -18,7 +18,7 @@ Name: jdupes -Version: 1.20.2 +Version: 1.21.1 Release: 0 Summary: A powerful duplicate file finder and an enhanced fork of 'fdupes' License: MIT ++++++ v1.20.2.tar.gz -> v1.21.1.tar.gz ++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/jdupes-1.20.2/.dockerignore new/jdupes-1.21.1/.dockerignore --- old/jdupes-1.20.2/.dockerignore 1970-01-01 01:00:00.000000000 +0100 +++ new/jdupes-1.21.1/.dockerignore 2022-12-01 18:46:17.000000000 +0100 @@ -0,0 +1,3 @@ +.* +example_scripts +testdir diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/jdupes-1.20.2/.github/ISSUE_TEMPLATE/template-for-all-issue-submissions.md new/jdupes-1.21.1/.github/ISSUE_TEMPLATE/template-for-all-issue-submissions.md --- old/jdupes-1.20.2/.github/ISSUE_TEMPLATE/template-for-all-issue-submissions.md 1970-01-01 01:00:00.000000000 +0100 +++ new/jdupes-1.21.1/.github/ISSUE_TEMPLATE/template-for-all-issue-submissions.md 2022-12-01 18:46:17.000000000 +0100 @@ -0,0 +1,43 @@ +--- +name: Template for all Issue submissions +about: Use this template for all submissions, including bug reports and feature requests +title: '' +labels: '' +assignees: '' + +--- + +<!-- Run `jdupes -v` to get your version information, i.e. "jdupes 1.20.2 (2021-11-02) 64-bit i32" --> +**What jdupes version are you using?** + +`paste version within these backquotes` + + +<!-- Change the box to [x] with your answer --> +**Where did you get your copy of the jdupes binary?** + +[ ] Official binary from jdupes releases +[ ] OS distribution repository (Linux, Homebrew, etc. - put distro's name/version in text block below) +[ ] I personally compiled it from source code (paste your build commands in the text block below) +[ ] Other (please explain below) + +``` +No additional information provided (replace this line with info requested above as needed) +``` + + +<!-- Certify that you've searched through Issues before adding yours. Failure to do this will result in immediate closure or deletion of your issue. --> +**Have you searched in Issues?** + +[ ] I have searched for my problem in Issues and I am confident that this is not a duplicate of a previous reported issue or feature request. + + +<!--Certify that you're not posting about common non-issues. We see a lot of submissions that wouldn't exist if people read the documentation and code before making them. --> +**I have done my due diligence** + +[ ] I am not suggesting changing the hash algorithm, storing files in a database, comparing file data blocks differently, suggesting that file sizes should be used before comparison, or other common suggestions that indicate I haven't read the documentation, code, or examined the issue tracker entries to discover that all of these things have already been implemented or won't make a difference if they were implemented. I have done my due diligence before asking for help or making a suggestion. + +<!-- Describe the issue you're having or feature you're requesting. Be as clear and detailed as possible. --> +**Issue or feature request details** + +blah blah blah, I didn't fill this out, please close my request diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/jdupes-1.20.2/.github/workflows/main.yml new/jdupes-1.21.1/.github/workflows/main.yml --- old/jdupes-1.20.2/.github/workflows/main.yml 1970-01-01 01:00:00.000000000 +0100 +++ new/jdupes-1.21.1/.github/workflows/main.yml 2022-12-01 18:46:17.000000000 +0100 @@ -0,0 +1,56 @@ +name: ci + +on: + push: + branches: + - 'master' + - 'github-action' + +jobs: + docker: + runs-on: ubuntu-latest + + steps: + - name: set lower case owner name + run: | + echo "OWNER_LC=${OWNER,,}" >>${GITHUB_ENV} + env: + OWNER: '${{ github.repository_owner }}' + - + name: Checkout + uses: actions/checkout@v2 + - + name: Set up QEMU + uses: docker/setup-qemu-action@v1 + - + name: Set up Docker Buildx + uses: docker/setup-buildx-action@v1 + - + name: Login to GitHub Container Registry + uses: docker/login-action@v1 + with: + registry: ghcr.io + username: ${{ env.OWNER_LC }} + password: ${{ secrets.PERSONAL_ACCESS_TOKEN }} + - + name: Build and push slim + uses: docker/build-push-action@v2 + with: + context: . + file: docker/slim.Dockerfile + platforms: linux/amd64 + push: true + tags: | + ghcr.io/${{ env.OWNER_LC }}/jdupes:latest + ghcr.io/${{ env.OWNER_LC }}/jdupes:${{ github.ref_name }} + - + name: Build and push alpine + uses: docker/build-push-action@v2 + with: + context: . + file: docker/alpine.Dockerfile + platforms: linux/amd64 + push: true + tags: | + ghcr.io/${{ env.OWNER_LC }}/jdupes:alpine + ghcr.io/${{ env.OWNER_LC }}/jdupes:${{ github.ref_name }}-alpine diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/jdupes-1.20.2/CHANGES new/jdupes-1.21.1/CHANGES --- old/jdupes-1.20.2/CHANGES 2021-11-03 03:54:09.000000000 +0100 +++ new/jdupes-1.21.1/CHANGES 2022-12-01 18:46:17.000000000 +0100 @@ -1,3 +1,16 @@ +jdupes 1.21.1 + +- Reinstate '-I/--isolate' by popular demand; use at your own risk! + +jdupes 1.21.0 + +- Remove '-I/--isolate' which has never worked correctly +- Fix compiling when NO_HARDLINKS and NO_SYMLINKS are both defined +- Increased stack size limits to enable deeper recursion without crashing +- Fixes to make compilation under Cygwin (instead of MSYS2 MinGW) work +- Remove the temporary '-X help' warning about changes in functionality +- Some minor under-the-hood changes for future enhancements + jdupes 1.20.2 - Interactive deletion now offers "link set" options too diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/jdupes-1.20.2/INSTALL new/jdupes-1.21.1/INSTALL --- old/jdupes-1.20.2/INSTALL 2021-11-03 03:54:09.000000000 +0100 +++ new/jdupes-1.21.1/INSTALL 2022-12-01 18:46:17.000000000 +0100 @@ -11,6 +11,15 @@ to a different location by editing the Makefile or specifying a PREFIX on the command line: make PREFIX=/usr install +On Windows, you need to use MSYS2 with MinGW-w64 installed. Use this guide to +install the build environment: + +https://stackoverflow.com/a/30071634/1906641 + +Running "make" as usual under the MSYS2 mingw32/mingw64 terminal will build a +Windows binary for the bitness of the terminal you're using. The Makefile will +detect a Windows environment and automatically make the needed build changes. + Various build options are available and can be turned on at compile time by setting CFLAGS_EXTRA or by passing it to 'make': @@ -21,19 +30,22 @@ OMIT_GETOPT_LONG Do not use getopt_long() C library call ON_WINDOWS Modify code to compile with MinGW on Windows +NO_WINDOWS Disable Windows MinGW special cases (mainly for Cygwin) +NO_PERMS Disable permission options and code +NO_HARDLINKS Disable hard linking options and code +NO_SYMLINKS Disable symbolic linking options and code +NO_USER_ORDER Disable -I/-O options and code +NO_MTIME Disable all modify time features and code +NO_ATIME Disable all access time features and code -Certain options need to be turned on by setting a variable passed to make -instead of using CFLAGS_EXTRA, i.e. 'make DEBUG=1': +Certain options can be turned on by setting a variable passed to make instead +of using CFLAGS_EXTRA, i.e. 'make DEBUG=1': DEBUG Turn on algorithm statistic reporting with '-D' LOUD '-@' for low-level debugging; enables DEBUG ENABLE_DEDUPE Enable '-B/--dedupe' deduplication features STATIC_DEDUPE_H Build dedupe support with included minimal header file LOW_MEMORY Build for extremely low-RAM environments (CAUTION!) -NO_PERMS Disable permission options and code -NO_HARDLINKS Disable hard linking options and code -NO_SYMLINKS Disable symbolic linking options and code -NO_USER_ORDER Disable -I/-O options and code NO_UNICODE [Windows only] disable all Unicode support The LOW_MEMORY option tweaks various knobs in the program to lower total @@ -61,3 +73,14 @@ chrootpackage Uses chroots under /chroot to build Linux packages package Makes auto-detected macOS/Linux/Windows packages + +Windows builds do not support dedupe or symbolic links. Dedupe would only work +in ReFS which was removed from all non-enterprise Windows 10 editions, so it +will likely never be supported for Windows builds of jdupes. Symbolic linking +is supported on Windows, but on all versions of Windows before Windows 10 1703 +(the "Creators Update"), creating symlinks required administrative escalation. +Symlinks can be dangerous on Windows because most Windows software is symlink- +unaware. Support can be added in the future, but it is not a priority. If you +are interested in seeing symlink support added, leave a +1 comment here: + +https://github.com/jbruchon/jdupes/issues/194 diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/jdupes-1.20.2/LICENSE new/jdupes-1.21.1/LICENSE --- old/jdupes-1.20.2/LICENSE 2021-11-03 03:54:09.000000000 +0100 +++ new/jdupes-1.21.1/LICENSE 2022-12-01 18:46:17.000000000 +0100 @@ -1,6 +1,6 @@ The MIT License (MIT) -Copyright (C) 2015-2021 Jody Lee Bruchon and contributors +Copyright (C) 2015-2022 Jody Lee Bruchon and contributors Forked from fdupes 1.51, Copyright (C) 1999-2014 Adrian Lopez and contributors Permission is hereby granted, free of charge, to any person obtaining a copy of diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/jdupes-1.20.2/Makefile new/jdupes-1.21.1/Makefile --- old/jdupes-1.20.2/Makefile 2021-11-03 03:54:09.000000000 +0100 +++ new/jdupes-1.21.1/Makefile 2022-12-01 18:46:17.000000000 +0100 @@ -55,18 +55,25 @@ COMPILER_OPTIONS = -Wall -Wwrite-strings -Wcast-align -Wstrict-aliasing -Wstrict-prototypes -Wpointer-arith -Wundef COMPILER_OPTIONS += -Wshadow -Wfloat-equal -Waggregate-return -Wcast-qual -Wswitch-default -Wswitch-enum -Wconversion -Wunreachable-code -Wformat=2 COMPILER_OPTIONS += -std=gnu99 -O2 -g -D_FILE_OFFSET_BITS=64 -fstrict-aliasing -pipe -COMPILER_OPTIONS += -DSMA_MAX_FREE=11 +COMPILER_OPTIONS += -DSMA_MAX_FREE=11 -DNO_ATIME ##################################################################### # no need to modify anything beyond this point # ##################################################################### # Don't use unsupported compiler options on gcc 3/4 (OS X 10.5.8 Xcode) -GCCVERSION = $(shell expr `gcc -v 2>&1 | grep 'gcc version ' | cut -d\ -f3 | cut -d. -f1` \>= 5) +GCCVERSION = $(shell expr `LC_ALL=C gcc -v 2>&1 | grep 'gcc version ' | cut -d\ -f3 | cut -d. -f1` \>= 5) ifeq "$(GCCVERSION)" "1" COMPILER_OPTIONS += -Wextra -Wstrict-overflow=5 -Winit-self endif +# Are we running on a Windows OS? +ifeq ($(OS), Windows_NT) + ifndef NO_WINDOWS + ON_WINDOWS=1 + endif +endif + # Debugging code inclusion ifdef LOUD DEBUG=1 @@ -92,7 +99,7 @@ UNAME_S=$(shell uname -s) # MinGW needs this for printf() conversions to work -ifeq ($(OS), Windows_NT) +ifdef ON_WINDOWS ifndef NO_UNICODE UNICODE=1 COMPILER_OPTIONS += -municode @@ -108,6 +115,16 @@ override undefine ENABLE_DEDUPE endif +# Stack size limit can be too small for deep directory trees, so set to 16 MiB +# The ld syntax for Windows is the same for both Cygwin and MinGW +ifeq ($(OS), Windows_NT) +COMPILER_OPTIONS += -Wl,--stack=16777216 +else ifeq ($(UNAME_S), Darwin) +COMPILER_OPTIONS += -Wl,-stack_size -Wl,0x1000000 +else +COMPILER_OPTIONS += -Wl,-z,stack-size=16777216 +endif + # Don't do clonefile on Mac OS X < 10.13 (High Sierra) ifeq ($(UNAME_S), Darwin) DARWINVER := $(shell expr `uname -r | cut -d. -f1` \< 17) @@ -137,7 +154,7 @@ # Low memory mode ifdef LOW_MEMORY -COMPILER_OPTIONS += -DLOW_MEMORY -DSMA_PAGE_SIZE=32768 -DCHUNK_SIZE=16384 -DNO_HARDLINKS -DNO_SYMLINKS -DNO_USER_ORDER -DNO_PERMS +COMPILER_OPTIONS += -DLOW_MEMORY -DSMA_PAGE_SIZE=32768 -DCHUNK_SIZE=16384 -DNO_HARDLINKS -DNO_SYMLINKS -DNO_USER_ORDER -DNO_PERMS -DNO_ATIME endif CFLAGS += $(COMPILER_OPTIONS) $(CFLAGS_EXTRA) @@ -198,7 +215,7 @@ strip $(PROGRAM_NAME)$(PROGRAM_SUFFIX) clean: - $(RM) $(OBJS) $(OBJS_CLEAN) build_date.h $(PROGRAM_NAME) $(PROGRAM_NAME).exe *~ *.gcno *.gcda *.gcov + $(RM) $(OBJS) $(OBJS_CLEAN) build_date.h $(PROGRAM_NAME) $(PROGRAM_NAME).exe *~ .*.un~ *.gcno *.gcda *.gcov distclean: clean $(RM) *.pkg.tar.* diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/jdupes-1.20.2/README.md new/jdupes-1.21.1/README.md --- old/jdupes-1.20.2/README.md 2021-11-03 03:54:09.000000000 +0100 +++ new/jdupes-1.21.1/README.md 2022-12-01 18:46:17.000000000 +0100 @@ -142,6 +142,10 @@ ``` Usage: jdupes [options] DIRECTORY... ``` +### Or with Docker +``` +docker run -it --init -v /path/to/dir:/data ghcr.io/jbruchon/jdupes:latest [options] /data +``` Duplicate file sets will be printed by default unless a different action option is specified (delete, summarize, link, dedupe, etc.) @@ -387,6 +391,8 @@ `-@@->` File was symlinked to the first file in the chain +`-##->` File was cloned from the first file in the chain + `-==->` Already a hard link to the first file in the chain `-//->` File linking failed due to an error during the linking process @@ -533,9 +539,9 @@ Legal information and software license ------------------------------------------------------------------------------- -jdupes is Copyright (C) 2015-2021 by Jody Bruchon <j...@jodybruchon.com> +jdupes is Copyright (C) 2015-2022 by Jody Bruchon <j...@jodybruchon.com> Derived from the original 'fdupes' 1.51 (C) 1999-2014 by Adrian Lopez -Includes other code libraries which are (C) 2015-2021 by Jody Bruchon +Includes other code libraries which are (C) 2015-2022 by Jody Bruchon The MIT License diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/jdupes-1.20.2/README.stupid_dupes new/jdupes-1.21.1/README.stupid_dupes --- old/jdupes-1.20.2/README.stupid_dupes 2021-11-03 03:54:09.000000000 +0100 +++ new/jdupes-1.21.1/README.stupid_dupes 2022-12-01 18:46:17.000000000 +0100 @@ -35,7 +35,7 @@ Legal information and software license ------------------------------------------------------------------------------- -Copyright (C) 2020-2021 by Jody Bruchon <j...@jodybruchon.com> and contributors +Copyright (C) 2020-2022 by Jody Bruchon <j...@jodybruchon.com> and contributors and for some reason Jody is willing to admit to writing it. The MIT License diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/jdupes-1.20.2/act_deletefiles.c new/jdupes-1.21.1/act_deletefiles.c --- old/jdupes-1.20.2/act_deletefiles.c 2021-11-03 03:54:09.000000000 +0100 +++ new/jdupes-1.21.1/act_deletefiles.c 2022-12-01 18:46:17.000000000 +0100 @@ -113,7 +113,11 @@ token = strtok(preservestr, " ,\n"); if (token != NULL) { +#if defined NO_HARDLINKS && defined NO_SYMLINKS + /* no linktype needed */ +#else int linktype = -1; +#endif /* defined NO_HARDLINKS && defined NO_SYMLINKS */ /* "Delete none" = stop parsing string */ if (*token == 'n' || *token == 'N') goto stop_scanning; /* If requested, link this set instead */ @@ -123,10 +127,14 @@ #ifndef NO_SYMLINKS if (*token == 's' || *token == 'S') linktype = 0; /* symlink */ #endif +#if defined NO_HARDLINKS && defined NO_SYMLINKS + /* no linking calls */ +#else if (linktype != -1) { linkfiles(files, linktype, 1); goto skip_deletion; } +#endif /* defined NO_HARDLINKS && defined NO_SYMLINKS */ } while (token != NULL) { @@ -172,7 +180,11 @@ } } } +#if defined NO_HARDLINKS && defined NO_SYMLINKS + /* label not needed */ +#else skip_deletion: +#endif /* defined NO_HARDLINKS && defined NO_SYMLINKS */ printf("\n"); } } diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/jdupes-1.20.2/act_linkfiles.c new/jdupes-1.21.1/act_linkfiles.c --- old/jdupes-1.20.2/act_linkfiles.c 2021-11-03 03:54:09.000000000 +0100 +++ new/jdupes-1.21.1/act_linkfiles.c 2022-12-01 18:46:17.000000000 +0100 @@ -53,6 +53,12 @@ static unsigned int symsrc; static char rel_path[PATHBUF_SIZE]; #endif +#ifdef ENABLE_CLONEFILE_LINK + static unsigned int srcfile_preserved_flags = 0; + static unsigned int dupfile_preserved_flags = 0; + static unsigned int dupfile_original_flags = 0; + static struct timeval dupfile_original_tval[2]; +#endif LOUD(fprintf(stderr, "linkfiles(%d): %p\n", linktype, files);) curfile = files; @@ -121,6 +127,20 @@ if (!ISFLAG(flags, F_HIDEPROGRESS)) { printf("[SRC] "); fwprint(stdout, srcfile->d_name, 1); } +#ifdef ENABLE_CLONEFILE_LINK + if (linktype == 2) { + if (STAT(srcfile->d_name, &s) != 0) { + fprintf(stderr, "warning: stat() on source file failed, skipping:\n[SRC] "); + fwprint(stderr, srcfile->d_name, 1); + continue; + } + + /* macOS unexpectedly copies the compressed flag when copying metadata + * (which can result in files being unreadable), so we want to retain + * the compression flag of srcfile */ + srcfile_preserved_flags = s.st_flags & UF_COMPRESSED; + } +#endif for (; x <= counter; x++) { if (linktype == 1 || linktype == 2) { /* Can't hard link files on different devices */ @@ -203,6 +223,25 @@ continue; } #endif +#ifdef ENABLE_CLONEFILE_LINK + if (linktype == 2) { + if (STAT(dupelist[x]->d_name, &s) != 0) { + fprintf(stderr, "warning: stat() on destination file failed, skipping:\n-##-> "); + fwprint(stderr, dupelist[x]->d_name, 1); + continue; + } + + /* macOS unexpectedly copies the compressed flag when copying metadata + * (which can result in files being unreadable), so we want to ignore + * the compression flag on dstfile in favor of the one from srcfile */ + dupfile_preserved_flags = s.st_flags & ~(unsigned int)UF_COMPRESSED; + dupfile_original_flags = s.st_flags; + dupfile_original_tval[0].tv_sec = s.st_atime; + dupfile_original_tval[1].tv_sec = s.st_mtime; + dupfile_original_tval[0].tv_usec = 0; + dupfile_original_tval[1].tv_usec = 0; + } +#endif /* Make sure the name will fit in the buffer before trying */ name_len = strlen(dupelist[x]->d_name) + 14; @@ -210,7 +249,7 @@ /* Assemble a temporary file name */ strcpy(tempname, dupelist[x]->d_name); strcat(tempname, ".__jdupes__.tmp"); - /* Rename the source file to the temporary name */ + /* Rename the destination file to the temporary name */ #ifdef UNICODE if (!M2W(tempname, wname2)) { fprintf(stderr, "error: MultiByteToWideChar failed: "); fwprint(stderr, srcfile->d_name, 1); @@ -248,12 +287,35 @@ #else /* ON_WINDOWS */ if (linktype == 1) { if (link(srcfile->d_name, dupelist[x]->d_name) == 0) success = 1; -#ifdef ENABLE_CLONEFILE_LINK + #ifdef ENABLE_CLONEFILE_LINK } else if (linktype == 2) { - if (clonefile(srcfile->d_name, dupelist[x]->d_name, 0) == 0) success = 1; - /* Preserve all file metadata on macOS */ - copyfile(tempname, dupelist[x]->d_name, NULL, COPYFILE_METADATA); -#endif /* ENABLE_CLONEFILE_LINK */ + if (clonefile(srcfile->d_name, dupelist[x]->d_name, 0) == 0) { + if (copyfile(tempname, dupelist[x]->d_name, NULL, COPYFILE_METADATA) == 0) { + /* If the preserved flags match what we just copied from the original dupfile, we're done. + * Otherwise, we need to update the flags to avoid data loss due to differing compression flags */ + if (dupfile_original_flags == (srcfile_preserved_flags | dupfile_preserved_flags)) { + success = 1; + } else if (chflags(dupelist[x]->d_name, srcfile_preserved_flags | dupfile_preserved_flags) == 0) { + /* chflags overrides the timestamps that were restored by copyfile, so we need to reapply those as well */ + if (utimes(dupelist[x]->d_name, dupfile_original_tval) == 0) { + success = 1; + } else { + fprintf(stderr, "warning: utimes() failed for destination file, reverting:\n-##-> "); + fwprint(stderr, dupelist[x]->d_name, 1); + } + } else { + fprintf(stderr, "warning: chflags() failed for destination file, reverting:\n-##-> "); + fwprint(stderr, dupelist[x]->d_name, 1); + } + } else { + fprintf(stderr, "warning: copyfile() failed for destination file, reverting:\n-##-> "); + fwprint(stderr, dupelist[x]->d_name, 1); + } + } else { + fprintf(stderr, "warning: clonefile() failed for destination file, reverting:\n-##-> "); + fwprint(stderr, dupelist[x]->d_name, 1); + } + #endif /* ENABLE_CLONEFILE_LINK */ } #ifndef NO_SYMLINKS else { diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/jdupes-1.20.2/chroot_build.sh new/jdupes-1.21.1/chroot_build.sh --- old/jdupes-1.20.2/chroot_build.sh 2021-11-03 03:54:09.000000000 +0100 +++ new/jdupes-1.21.1/chroot_build.sh 2022-12-01 18:46:17.000000000 +0100 @@ -24,20 +24,24 @@ do_build () { test -z "$WD" && echo "WD not set, aborting" && exit 1 test -z "$PKG" && echo "PKG not set, aborting" && exit 1 - make clean - PN="${NAME}_$VER-$ARCH.pkg.tar.xz" - if ! make -j$JOBS all - then echo "Build failed"; exit 1 + if [ -e ./generate_packages.sh ] + then ./generate_packages.sh else - echo "WD/PKG: $WD/$PKG" - test -d $WD/$PKG && rm -rf $WD/$PKG - mkdir $WD/$PKG - make DESTDIR=$WD/$PKG install && \ - tar -C pkg -c usr | xz -e > "$PN" - # Set ownership to current directory ownership - chown "$(stat -c '%u:%g' .)" "$PN" - echo "Built $PN" make clean + PN="${NAME}_$VER-$ARCH.pkg.tar.xz" + if ! make -j$JOBS all + then echo "Build failed"; exit 1 + else + echo "WD/PKG: $WD/$PKG" + test -d $WD/$PKG && rm -rf $WD/$PKG + mkdir $WD/$PKG + make DESTDIR=$WD/$PKG install && \ + tar -C pkg -c usr | xz -e > "$PN" + # Set ownership to current directory ownership + chown "$(stat -c '%u:%g' .)" "$PN" + echo "Built $PN" + make clean + fi fi } diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/jdupes-1.20.2/docker/alpine.Dockerfile new/jdupes-1.21.1/docker/alpine.Dockerfile --- old/jdupes-1.20.2/docker/alpine.Dockerfile 1970-01-01 01:00:00.000000000 +0100 +++ new/jdupes-1.21.1/docker/alpine.Dockerfile 2022-12-01 18:46:17.000000000 +0100 @@ -0,0 +1,11 @@ +FROM alpine:latest as builder +RUN apk update && apk add --no-cache gcc make musl-dev + +COPY . . +RUN make && make install + +FROM alpine:latest as runner + +COPY --from=builder /usr/local/bin/jdupes /usr/local/bin/jdupes + +ENTRYPOINT [ "/usr/local/bin/jdupes" ] diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/jdupes-1.20.2/docker/slim.Dockerfile new/jdupes-1.21.1/docker/slim.Dockerfile --- old/jdupes-1.20.2/docker/slim.Dockerfile 1970-01-01 01:00:00.000000000 +0100 +++ new/jdupes-1.21.1/docker/slim.Dockerfile 2022-12-01 18:46:17.000000000 +0100 @@ -0,0 +1,10 @@ +FROM gcc:bullseye as builder + +COPY . . +RUN make && make install + +FROM debian:bullseye-slim as runner + +COPY --from=builder /usr/local/bin/jdupes /usr/local/bin/jdupes + +ENTRYPOINT [ "/usr/local/bin/jdupes" ] diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/jdupes-1.20.2/generate_packages.sh new/jdupes-1.21.1/generate_packages.sh --- old/jdupes-1.20.2/generate_packages.sh 2021-11-03 03:54:09.000000000 +0100 +++ new/jdupes-1.21.1/generate_packages.sh 2022-12-01 18:46:17.000000000 +0100 @@ -35,7 +35,9 @@ # Detect Linux if [ "$UNAME_S" = "linux" ] - then TA="linux-$UNAME_M" + then + TA="linux-$UNAME_M" + [ ! -z "$ARCH" ] && TA="linux-$ARCH" PKGTYPE=xz fi diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/jdupes-1.20.2/jdupes.1 new/jdupes-1.21.1/jdupes.1 --- old/jdupes-1.20.2/jdupes.1 2021-11-03 03:54:09.000000000 +0100 +++ new/jdupes-1.21.1/jdupes.1 2022-12-01 18:46:17.000000000 +0100 @@ -207,6 +207,9 @@ .B -@@-> This file was successfully symlinked to the first file in the chain .TP +.B -##-> +This file was successfully cloned from the first file in the chain +.TP .B -==-> This file was already a hard link to the first file in the chain .TP @@ -342,7 +345,7 @@ The MIT License (MIT) -Copyright (C) 2015-2021 Jody Lee Bruchon and contributors +Copyright (C) 2015-2022 Jody Lee Bruchon and contributors Forked from fdupes 1.51, Copyright (C) 1999-2014 Adrian Lopez and contributors Permission is hereby granted, free of charge, to any person obtaining a copy of diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/jdupes-1.20.2/jdupes.c new/jdupes-1.21.1/jdupes.c --- old/jdupes-1.20.2/jdupes.c 2021-11-03 03:54:09.000000000 +0100 +++ new/jdupes-1.21.1/jdupes.c 2022-12-01 18:46:17.000000000 +0100 @@ -1,4 +1,4 @@ -/* jdupes (C) 2015-2021 Jody Bruchon <j...@jodybruchon.com> +/* jdupes (C) 2015-2022 Jody Bruchon <j...@jodybruchon.com> Forked from fdupes 1.51 (C) 1999-2014 Adrian Lopez Permission is hereby granted, free of charge, to any person @@ -65,7 +65,7 @@ #include "act_summarize.h" /* Detect Windows and modify as needed */ -#if defined _WIN32 || defined __CYGWIN__ +#if defined _WIN32 || defined __MINGW32__ const char dir_sep = '\\'; #ifdef UNICODE const wchar_t *FILE_MODE_RO = L"rbS"; @@ -80,7 +80,7 @@ #error Do not define UNICODE on non-Windows platforms. #undef UNICODE #endif -#endif /* _WIN32 || __CYGWIN__ */ +#endif /* _WIN32 || __MINGW32__ */ /* Windows + Unicode compilation */ #ifdef UNICODE @@ -493,8 +493,10 @@ if (file->inode != s.st_ino) return 1; if (file->size != s.st_size) return 1; if (file->device != s.st_dev) return 1; - if (file->mtime != s.st_mtime) return 1; if (file->mode != s.st_mode) return 1; +#ifndef NO_MTIME + if (file->mtime != s.st_mtime) return 1; +#endif #ifndef NO_PERMS if (file->uid != s.st_uid) return 1; if (file->gid != s.st_gid) return 1; @@ -508,7 +510,7 @@ } -extern inline int getfilestats(file_t * const restrict file) +int getfilestats(file_t * const restrict file) { if (file == NULL || file->d_name == NULL) nullptr("getfilestats()"); LOUD(fprintf(stderr, "getfilestats('%s')\n", file->d_name);) @@ -518,10 +520,15 @@ SETFLAG(file->flags, FF_VALID_STAT); if (STAT(file->d_name, &s) != 0) return -1; - file->inode = s.st_ino; file->size = s.st_size; + file->inode = s.st_ino; file->device = s.st_dev; +#ifndef NO_MTIME file->mtime = s.st_mtime; +#endif +#ifndef NO_ATIME + file->atime = s.st_atime; +#endif file->mode = s.st_mode; #ifndef NO_HARDLINKS file->nlink = s.st_nlink; @@ -771,17 +778,19 @@ LOUD(fprintf(stderr, "check_singlefile: extfilter check: %08x %ld %ld %s\n", sflag, newfile->size, extf->size, newfile->d_name);) if ( /* Any line that passes will result in file exclusion */ - ((sflag == XF_SIZE_EQ) && (newfile->size != extf->size)) || - ((sflag == XF_SIZE_LTEQ) && (newfile->size > extf->size)) || - ((sflag == XF_SIZE_GTEQ) && (newfile->size < extf->size)) || - ((sflag == XF_SIZE_GT) && (newfile->size <= extf->size)) || - ((sflag == XF_SIZE_LT) && (newfile->size >= extf->size)) || - ((sflag == XF_EXCL_EXT) && match_extensions(newfile->d_name, extf->param)) || - ((sflag == XF_ONLY_EXT) && !match_extensions(newfile->d_name, extf->param)) || - ((sflag == XF_EXCL_STR) && strstr(newfile->d_name, extf->param)) || - ((sflag == XF_ONLY_STR) && !strstr(newfile->d_name, extf->param)) || - ((sflag == XF_DATE_NEWER) && (newfile->mtime < extf->size)) || - ((sflag == XF_DATE_OLDER) && (newfile->mtime >= extf->size)) + ((sflag == XF_SIZE_EQ) && (newfile->size != extf->size)) + || ((sflag == XF_SIZE_LTEQ) && (newfile->size > extf->size)) + || ((sflag == XF_SIZE_GTEQ) && (newfile->size < extf->size)) + || ((sflag == XF_SIZE_GT) && (newfile->size <= extf->size)) + || ((sflag == XF_SIZE_LT) && (newfile->size >= extf->size)) + || ((sflag == XF_EXCL_EXT) && match_extensions(newfile->d_name, extf->param)) + || ((sflag == XF_ONLY_EXT) && !match_extensions(newfile->d_name, extf->param)) + || ((sflag == XF_EXCL_STR) && strstr(newfile->d_name, extf->param)) + || ((sflag == XF_ONLY_STR) && !strstr(newfile->d_name, extf->param)) +#ifndef NO_MTIME + || ((sflag == XF_DATE_NEWER) && (newfile->mtime < extf->size)) + || ((sflag == XF_DATE_OLDER) && (newfile->mtime >= extf->size)) +#endif ) excluded = 1; } if (excluded) { @@ -1556,6 +1565,7 @@ #endif +#ifndef NO_MTIME static int sort_pairs_by_mtime(file_t *f1, file_t *f2) { if (f1 == NULL || f2 == NULL) nullptr("sort_pairs_by_mtime()"); @@ -1571,6 +1581,7 @@ /* If the mtimes match, use the names to break the tie */ return numeric_sort(f1->d_name, f2->d_name, sort_direction); } +#endif static int sort_pairs_by_filename(file_t *f1, file_t *f2) @@ -1685,8 +1696,10 @@ printf(" -N --no-prompt \ttogether with --delete, preserve the first file in\n"); printf(" \teach set of duplicates and delete the rest without\n"); printf(" \tprompting the user\n"); +#ifndef NO_MTIME printf(" -o --order=BY \tselect sort order for output, linking and deleting; by\n"); printf(" \tmtime (BY=time) or filename (BY=name, the default)\n"); +#endif #ifndef NO_USER_ORDER printf(" -O --param-order \tParameter order is more important than selected -o sort\n"); #endif @@ -1732,9 +1745,6 @@ printf("Detailed help for jdupes -X/--ext-filter options\n"); printf("General format: jdupes -X filter[:value][size_suffix]\n\n"); - /* FIXME: Remove after v1.19.0 */ - printf("****** WARNING: THE MEANINGS HAVE CHANGED IN v1.19.0 - READ CAREFULLY ******\n\n"); - printf("noext:ext1[,ext2,...] \tExclude files with certain extension(s)\n\n"); printf("onlyext:ext1[,ext2,...] \tOnly include files with certain extension(s)\n\n"); printf("size[+-=]:size[suffix] \tOnly Include files matching size criteria\n"); @@ -1778,7 +1788,9 @@ static int opt; static int pm = 1; static int partialonly_spec = 0; +#ifndef NO_MTIME /* Remove if new order types are added! */ static ordertype_t ordertype = ORDER_NAME; +#endif static long manual_chunk_size = 0; #ifdef __linux__ static struct proc_cacheinfo pci; @@ -2095,7 +2107,7 @@ c++; } } else printf(" none"); - printf("\nCopyright (C) 2015-2021 by Jody Bruchon and contributors\n"); + printf("\nCopyright (C) 2015-2022 by Jody Bruchon and contributors\n"); printf("Forked from fdupes 1.51, (C) 1999-2014 Adrian Lopez and contributors\n\n"); printf("Permission is hereby granted, free of charge, to any person obtaining a copy of\n"); printf("this software and associated documentation files (the \"Software\"), to deal in\n"); @@ -2118,6 +2130,7 @@ printf("\nReport bugs and get the latest releases: https://github.com/jbruchon/jdupes\n"); exit(EXIT_SUCCESS); case 'o': +#ifndef NO_MTIME /* Remove if new order types are added! */ if (!strncasecmp("name", optarg, 5)) { ordertype = ORDER_NAME; } else if (!strncasecmp("time", optarg, 5)) { @@ -2126,6 +2139,7 @@ fprintf(stderr, "invalid value for --order: '%s'\n", optarg); exit(EXIT_FAILURE); } +#endif /* NO_MTIME */ break; case 'B': #ifdef ENABLE_DEDUPE @@ -2295,8 +2309,11 @@ (curfile->device == (*match)->device)) ) { LOUD(fprintf(stderr, "MAIN: notice: hard linked, quick, or partial-only match (-H/-Q/-T)\n")); - registerpair(match, curfile, - (ordertype == ORDER_TIME) ? sort_pairs_by_mtime : sort_pairs_by_filename); +#ifndef NO_MTIME + registerpair(match, curfile, (ordertype == ORDER_TIME) ? sort_pairs_by_mtime : sort_pairs_by_filename); +#else + registerpair(match, curfile, sort_pairs_by_filename); +#endif dupecount++; goto skip_full_check; } @@ -2328,8 +2345,11 @@ if (confirmmatch(file1, file2, curfile->size)) { LOUD(fprintf(stderr, "MAIN: registering matched file pair\n")); - registerpair(match, curfile, - (ordertype == ORDER_TIME) ? sort_pairs_by_mtime : sort_pairs_by_filename); +#ifndef NO_MTIME + registerpair(match, curfile, (ordertype == ORDER_TIME) ? sort_pairs_by_mtime : sort_pairs_by_filename); +#else + registerpair(match, curfile, sort_pairs_by_filename); +#endif dupecount++; } DBG(else hash_fail++;) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/jdupes-1.20.2/jdupes.h new/jdupes-1.21.1/jdupes.h --- old/jdupes-1.20.2/jdupes.h 2021-11-03 03:54:09.000000000 +0100 +++ new/jdupes-1.21.1/jdupes.h 2022-12-01 18:46:17.000000000 +0100 @@ -9,7 +9,7 @@ #endif /* Detect Windows and modify as needed */ -#if defined _WIN32 || defined __CYGWIN__ +#if defined _WIN32 || defined __MINGW32__ #ifndef ON_WINDOWS #define ON_WINDOWS 1 #endif @@ -58,7 +58,7 @@ #error Do not define UNICODE on non-Windows platforms. #undef UNICODE #endif -#endif /* _WIN32 || __CYGWIN__ */ +#endif /* _WIN32 || __MINGW32__ */ /* Windows + Unicode compilation */ #ifdef UNICODE @@ -182,14 +182,19 @@ struct _file *duplicates; struct _file *next; char *d_name; - dev_t device; + uint32_t flags; /* Status flags */ jdupes_mode_t mode; off_t size; + dev_t device; jdupes_ino_t inode; jdupes_hash_t filehash_partial; jdupes_hash_t filehash; +#ifndef NO_MTIME time_t mtime; - uint32_t flags; /* Status flags */ +#endif +#ifndef NO_ATIME + time_t atime; +#endif #ifndef NO_USER_ORDER unsigned int user_order; /* Order of the originating command-line parameter */ #endif @@ -274,7 +279,6 @@ extern void nullptr(const char * restrict func); extern int file_has_changed(file_t * const restrict file); -extern int getfilestats(file_t * const restrict file); extern int getdirstats(const char * const restrict name, jdupes_ino_t * const restrict inode, dev_t * const restrict dev, jdupes_mode_t * const restrict mode); diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/jdupes-1.20.2/jody_cacheinfo.c new/jdupes-1.21.1/jody_cacheinfo.c --- old/jdupes-1.20.2/jody_cacheinfo.c 2021-11-03 03:54:09.000000000 +0100 +++ new/jdupes-1.21.1/jody_cacheinfo.c 2022-12-01 18:46:17.000000000 +0100 @@ -1,6 +1,6 @@ /* Detect and report size of CPU caches * - * Copyright (C) 2017-2021 by Jody Bruchon <j...@jodybruchon.com> + * Copyright (C) 2017-2022 by Jody Bruchon <j...@jodybruchon.com> * Distributed under The MIT License * * If an error occurs or a cache is missing, zeroes are returned diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/jdupes-1.20.2/jody_paths.c new/jdupes-1.21.1/jody_paths.c --- old/jdupes-1.20.2/jody_paths.c 2021-11-03 03:54:09.000000000 +0100 +++ new/jdupes-1.21.1/jody_paths.c 2022-12-01 18:46:17.000000000 +0100 @@ -1,6 +1,6 @@ /* Jody Bruchon's path manipulation code library * - * Copyright (C) 2014-2021 by Jody Bruchon <j...@jodybruchon.com> + * Copyright (C) 2014-2022 by Jody Bruchon <j...@jodybruchon.com> * Released under The MIT License */ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/jdupes-1.20.2/jody_sort.c new/jdupes-1.21.1/jody_sort.c --- old/jdupes-1.20.2/jody_sort.c 2021-11-03 03:54:09.000000000 +0100 +++ new/jdupes-1.21.1/jody_sort.c 2022-12-01 18:46:17.000000000 +0100 @@ -1,6 +1,6 @@ /* Jody Bruchon's sorting code library * - * Copyright (C) 2014-2021 by Jody Bruchon <j...@jodybruchon.com> + * Copyright (C) 2014-2022 by Jody Bruchon <j...@jodybruchon.com> * Released under The MIT License */ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/jdupes-1.20.2/jody_strtoepoch.c new/jdupes-1.21.1/jody_strtoepoch.c --- old/jdupes-1.20.2/jody_strtoepoch.c 2021-11-03 03:54:09.000000000 +0100 +++ new/jdupes-1.21.1/jody_strtoepoch.c 2022-12-01 18:46:17.000000000 +0100 @@ -1,6 +1,6 @@ /* Jody Bruchon's datetime-to-epoch conversion function * - * Copyright (C) 2020-2021 by Jody Bruchon <j...@jodybruchon.com> + * Copyright (C) 2020-2022 by Jody Bruchon <j...@jodybruchon.com> * Released under The MIT License */ @@ -11,8 +11,13 @@ #define REQ_NUM(a) { if (a < '0' || a > '9') return -1; } #define ATONUM(a,b) (a = b - '0') /* Fast multiplies by 100 (*64 + *32 + *4) and 10 (*8 + *2) */ -#define MUL100(a) ((a << 6) + (a << 5) + (a << 2)) -#define MUL10(a) ((a << 3) + a + a) +#ifndef STRTOEPOCH_USE_REAL_MULTIPLY + #define MUL100(a) ((a << 6) + (a << 5) + (a << 2)) + #define MUL10(a) ((a << 3) + a + a) +#else + #define MUL100(a) (a * 100) + #define MUL10(a) (a * 10) +#endif /* STRTOEPOCH_USE_REAL_MULTIPLY */ /* Accepts date[time] strings "YYYY-MM-DD" or "YYYY-MM-DD HH:MM:SS" * and returns the number of seconds since the Unix Epoch a la mktime() diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/jdupes-1.20.2/jody_strtoepoch.h new/jdupes-1.21.1/jody_strtoepoch.h --- old/jdupes-1.20.2/jody_strtoepoch.h 2021-11-03 03:54:09.000000000 +0100 +++ new/jdupes-1.21.1/jody_strtoepoch.h 2022-12-01 18:46:17.000000000 +0100 @@ -1,6 +1,6 @@ /* Jody Bruchon's datetime-to-epoch conversion function * - * Copyright (C) 2020-2021 by Jody Bruchon <j...@jodybruchon.com> + * Copyright (C) 2020-2022 by Jody Bruchon <j...@jodybruchon.com> * Released under The MIT License */ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/jdupes-1.20.2/jody_win_unicode.c new/jdupes-1.21.1/jody_win_unicode.c --- old/jdupes-1.20.2/jody_win_unicode.c 2021-11-03 03:54:09.000000000 +0100 +++ new/jdupes-1.21.1/jody_win_unicode.c 2022-12-01 18:46:17.000000000 +0100 @@ -1,6 +1,6 @@ /* Jody Bruchon's Windows Unicode helper routines * - * Copyright (C) 2014-2021 by Jody Bruchon <j...@jodybruchon.com> + * Copyright (C) 2014-2022 by Jody Bruchon <j...@jodybruchon.com> * Released under The MIT License */ #include "jody_win_unicode.h" diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/jdupes-1.20.2/linux-dedupe-static.h new/jdupes-1.21.1/linux-dedupe-static.h --- old/jdupes-1.20.2/linux-dedupe-static.h 2021-11-03 03:54:09.000000000 +0100 +++ new/jdupes-1.21.1/linux-dedupe-static.h 2022-12-01 18:46:17.000000000 +0100 @@ -1,58 +1,24 @@ -/* - * Copyright (C) 2007 Oracle. All rights reserved. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public - * License v2 as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public - * License along with this program; if not, write to the - * Free Software Foundation, Inc., 59 Temple Place - Suite 330, - * Boston, MA 021110-1307, USA. - */ - -#ifndef JDUPES_BTRFS_H -#define JDUPES_BTRFS_H +/* Bare header for Linux dedupe API */ +#ifndef JDUPES_DEDUPESTATIC_H +#define JDUPES_DEDUPESTATIC_H #include <linux/types.h> #include <linux/ioctl.h> - -#define BTRFS_IOCTL_MAGIC 0x94 - -#define BTRFS_DEVICE_PATH_NAME_MAX 1024 - #define FILE_DEDUPE_RANGE_SAME 0 #define FILE_DEDUPE_RANGE_DIFFERS 1 - -/* For extent-same ioctl */ struct file_dedupe_range_info { - __s64 dest_fd; /* in - destination file */ - __u64 dest_offset; /* in - start of extent in destination */ - __u64 bytes_deduped; /* out - total # of bytes we were able - * to dedupe from this file */ - /* status of this dedupe operation: - * 0 if dedup succeeds - * < 0 for error - * == FILE_DEDUPE_RANGE_DIFFERS if data differs - */ - __s32 status; /* out - see above description */ + __s64 dest_fd; + __u64 dest_offset; + __u64 bytes_deduped; + __s32 status; __u32 reserved; }; - struct file_dedupe_range { - __u64 src_offset; /* in - start of extent in source */ - __u64 src_length; /* in - length of extent */ - __u16 dest_count; /* in - total elements in info array */ + __u64 src_offset; + __u64 src_length; + __u16 dest_count; __u16 reserved1; __u32 reserved2; struct file_dedupe_range_info info[0]; }; - -#define FIDEDUPERANGE _IOWR(BTRFS_IOCTL_MAGIC, 54, \ - struct file_dedupe_range) - -#endif /* JDUPES_BTRFS_H */ +#define FIDEDUPERANGE _IOWR(0x94, 54, struct file_dedupe_range) +#endif /* JDUPES_DEDUPESTATIC_H */ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/jdupes-1.20.2/string_malloc.c new/jdupes-1.21.1/string_malloc.c --- old/jdupes-1.20.2/string_malloc.c 2021-11-03 03:54:09.000000000 +0100 +++ new/jdupes-1.21.1/string_malloc.c 2022-12-01 18:46:17.000000000 +0100 @@ -2,7 +2,7 @@ * String table allocator * A replacement for malloc() for tables of fixed strings * - * Copyright (C) 2015-2021 by Jody Bruchon <j...@jodybruchon.com> + * Copyright (C) 2015-2022 by Jody Bruchon <j...@jodybruchon.com> * Released under The MIT License */ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/jdupes-1.20.2/stupid_dupes.sh new/jdupes-1.21.1/stupid_dupes.sh --- old/jdupes-1.20.2/stupid_dupes.sh 2021-11-03 03:54:09.000000000 +0100 +++ new/jdupes-1.21.1/stupid_dupes.sh 2022-12-01 18:46:17.000000000 +0100 @@ -1,7 +1,7 @@ #!/bin/bash # stupid_dupes: find duplicates like jdupes but more slowly with a shell script -# Copyright (C) 2020-2021 by Jody Bruchon <j...@jodybruchon.com> +# Copyright (C) 2020-2022 by Jody Bruchon <j...@jodybruchon.com> # # The MIT License (MIT) # @@ -245,7 +245,7 @@ } show_help () { - COPYTEXT="Copyright (C) 2020-2021 by Jody Bruchon <j...@jodybruchon.com> and contributors\n" + COPYTEXT="Copyright (C) 2020-2022 by Jody Bruchon <j...@jodybruchon.com> and contributors\n" echo "$PROGNAME $VER ($VERDATE)" if [ "$2" = "full" ] then diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/jdupes-1.20.2/version.h new/jdupes-1.21.1/version.h --- old/jdupes-1.20.2/version.h 2021-11-03 03:54:09.000000000 +0100 +++ new/jdupes-1.21.1/version.h 2022-12-01 18:46:17.000000000 +0100 @@ -4,7 +4,7 @@ #ifndef JDUPES_VERSION_H #define JDUPES_VERSION_H -#define VER "1.20.2" -#define VERDATE "2021-11-02" +#define VER "1.21.1" +#define VERDATE "2022-12-01" #endif /* JDUPES_VERSION_H */ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/jdupes-1.20.2/win_stat.c new/jdupes-1.21.1/win_stat.c --- old/jdupes-1.20.2/win_stat.c 2021-11-03 03:54:09.000000000 +0100 +++ new/jdupes-1.21.1/win_stat.c 2022-12-01 18:46:17.000000000 +0100 @@ -1,7 +1,7 @@ /* * Windows-native code for getting stat()-like information * - * Copyright (C) 2016-2021 by Jody Bruchon <j...@jodybruchon.com> + * Copyright (C) 2016-2022 by Jody Bruchon <j...@jodybruchon.com> * Released under The MIT License */ @@ -14,7 +14,7 @@ #include <stdint.h> /* Convert NT epoch to UNIX epoch */ -static time_t nttime_to_unixtime(const uint64_t * const restrict timestamp) +time_t nttime_to_unixtime(const uint64_t * const restrict timestamp) { uint64_t newstamp; @@ -25,6 +25,18 @@ return (time_t)newstamp; } +/* Convert UNIX epoch to NT epoch */ +time_t unixtime_to_nttime(const uint64_t * const restrict timestamp) +{ + uint64_t newstamp; + + memcpy(&newstamp, timestamp, sizeof(uint64_t)); + newstamp += 11644473600LL; + newstamp *= 10000000LL; + if (newstamp <= 11644473600LL) return 0; + return (time_t)newstamp; +} + /* Get stat()-like extra information for a file on Windows */ int win_stat(const char * const filename, struct winstat * const restrict buf) { diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/jdupes-1.20.2/win_stat.h new/jdupes-1.21.1/win_stat.h --- old/jdupes-1.20.2/win_stat.h 2021-11-03 03:54:09.000000000 +0100 +++ new/jdupes-1.21.1/win_stat.h 2022-12-01 18:46:17.000000000 +0100 @@ -45,6 +45,8 @@ #define M2W(a,b) MultiByteToWideChar(CP_UTF8, 0, a, -1, (LPWSTR)b, WPATH_MAX) #endif +extern time_t nttime_to_unixtime(const uint64_t * const restrict timestamp); +extern time_t unixtime_to_nttime(const uint64_t * const restrict timestamp); extern int win_stat(const char * const filename, struct winstat * const restrict buf); #ifdef __cplusplus diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/jdupes-1.20.2/winres.manifest.xml new/jdupes-1.21.1/winres.manifest.xml --- old/jdupes-1.20.2/winres.manifest.xml 2021-11-03 03:54:09.000000000 +0100 +++ new/jdupes-1.21.1/winres.manifest.xml 2022-12-01 18:46:17.000000000 +0100 @@ -1,6 +1,6 @@ <?xml version="1.0" encoding="UTF-8" standalone="yes"?> <assembly xmlns="urn:schemas-microsoft-com:asm.v3" manifestVersion="1.0"> - <assemblyIdentity type="win32" name="jdupes" version="1.20.2.0"/> + <assemblyIdentity type="win32" name="jdupes" version="1.21.1.0"/> <application xmlns="urn:schemas-microsoft-com:asm.v3"> <windowsSettings xmlns:ws2="http://schemas.microsoft.com/SMI/2016/WindowsSettings"> <ws2:longPathAware>true</ws2:longPathAware> diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/jdupes-1.20.2/winres.rc new/jdupes-1.21.1/winres.rc --- old/jdupes-1.20.2/winres.rc 2021-11-03 03:54:09.000000000 +0100 +++ new/jdupes-1.21.1/winres.rc 2022-12-01 18:46:17.000000000 +0100 @@ -3,8 +3,8 @@ 1 24 winres.manifest.xml VS_VERSION_INFO VERSIONINFO - FILEVERSION 1,20,2,0 - PRODUCTVERSION 1,20,2,0 + FILEVERSION 1,21,1,0 + PRODUCTVERSION 1,21,1,0 FILEFLAGSMASK 0x3fL FILEFLAGS 0x0L FILEOS 0x40004L @@ -15,15 +15,15 @@ BEGIN BLOCK "040904b0" BEGIN - VALUE "Comments", "(C) 2015-2021 Jody Bruchon and contributors, published under The MIT License" + VALUE "Comments", "(C) 2015-2022 Jody Bruchon and contributors, published under The MIT License" VALUE "CompanyName", "Jody Bruchon" VALUE "FileDescription", "jdupes Duplicate File Finder Tool" - VALUE "FileVersion", "1,20,2,0" + VALUE "FileVersion", "1,21,1,0" VALUE "InternalName", "jdupes" - VALUE "LegalCopyright", "(C) 2015-2021 Jody Bruchon and contributors" + VALUE "LegalCopyright", "(C) 2015-2022 Jody Bruchon and contributors" VALUE "OriginalFilename", "jdupes.exe" VALUE "ProductName", "jdupes" - VALUE "ProductVersion", "1,20,2,0" + VALUE "ProductVersion", "1,21,1,0" END END BLOCK "VarFileInfo" diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/jdupes-1.20.2/winres_xp.rc new/jdupes-1.21.1/winres_xp.rc --- old/jdupes-1.20.2/winres_xp.rc 2021-11-03 03:54:09.000000000 +0100 +++ new/jdupes-1.21.1/winres_xp.rc 2022-12-01 18:46:17.000000000 +0100 @@ -1,8 +1,8 @@ #include "winver.h" VS_VERSION_INFO VERSIONINFO - FILEVERSION 1,20,2,0 - PRODUCTVERSION 1,20,2,0 + FILEVERSION 1,21,1,0 + PRODUCTVERSION 1,21,1,0 FILEFLAGSMASK 0x3fL FILEFLAGS 0x0L FILEOS 0x40004L @@ -13,15 +13,15 @@ BEGIN BLOCK "040904b0" BEGIN - VALUE "Comments", "(C) 2015-2021 Jody Bruchon and contributors, published under The MIT License" + VALUE "Comments", "(C) 2015-2022 Jody Bruchon and contributors, published under The MIT License" VALUE "CompanyName", "Jody Bruchon" VALUE "FileDescription", "jdupes Duplicate File Finder Tool" - VALUE "FileVersion", "1,20,2,0" + VALUE "FileVersion", "1,21,1,0" VALUE "InternalName", "jdupes" - VALUE "LegalCopyright", "(C) 2015-2021 Jody Bruchon and contributors" + VALUE "LegalCopyright", "(C) 2015-2022 Jody Bruchon and contributors" VALUE "OriginalFilename", "jdupes.exe" VALUE "ProductName", "jdupes" - VALUE "ProductVersion", "1,20,2,0" + VALUE "ProductVersion", "1,21,1,0" END END BLOCK "VarFileInfo"