diff -ur fdupes-2.1.2/CHANGES fdupes-2.2.1/CHANGES --- fdupes-2.1.2/CHANGES 2020-08-12 21:09:35 +++ fdupes-2.2.1/CHANGES 2022-09-09 10:04:04 @@ -6,6 +6,20 @@ those who've otherwise worked on that item. For a list of contributors names and identifiers please see the CONTRIBUTORS file. +Changes from 2.2.0 to 2.2.1: + + - Fix bug in code meant to skip over the current log file when --log + option is given. + - Updates to copyright notices in source code. + +Changes from 2.1.2 to 2.2.0: + + - Add --deferconfirmation option. + - Check that files marked as duplicates haven't changed during program + execution before deleting them. + - Update documentation to indicate units for SIZE in command-line options. + - Move some configuration settings to configure.ac file. + Changes from 2.1.1 to 2.1.2: - Do not enter ncurses mode when --immediate option given. diff -ur fdupes-2.1.2/Makefile.am fdupes-2.2.1/Makefile.am --- fdupes-2.1.2/Makefile.am 2020-08-12 21:09:35 +++ fdupes-2.2.1/Makefile.am 2022-09-09 09:52:05 @@ -1,6 +1,5 @@ bin_PROGRAMS = fdupes -if NO_NCURSES fdupes_SOURCES = fdupes.c\ fdupes.h\ errormsg.c\ @@ -15,16 +14,20 @@ sigint.h\ flags.c\ flags.h\ + confirmmatch.c\ + confirmmatch.h\ + removeifnotchanged.c\ + removeifnotchanged.h\ mbstowcs_escape_invalid.c\ mbstowcs_escape_invalid.h\ md5/md5.c\ md5/md5.h dist_man1_MANS = fdupes.1 -else -fdupes_SOURCES = fdupes.c\ - fdupes.h\ - filegroup.h\ +if WITH_NCURSES +fdupes_SOURCES += filegroup.h\ + fileaction.h\ + fileaction.c\ ncurses-commands.c\ ncurses-commands.h\ ncurses-getcommand.c\ @@ -39,27 +42,10 @@ ncurses-status.h\ commandidentifier.c\ commandidentifier.h\ - errormsg.c\ - errormsg.h\ wcs.c\ wcs.h\ - dir.c\ - dir.h\ - log.c\ - log.h\ - fmatch.c\ - fmatch.h\ - sigint.c\ - sigint.h\ - flags.c\ - flags.h\ - mbstowcs_escape_invalid.c\ - mbstowcs_escape_invalid.h\ positive_wcwidth.c\ - positive_wcwidth.h\ - md5/md5.c\ - md5/md5.h -dist_man1_MANS = fdupes.1 + positive_wcwidth.h dist_man7_MANS = fdupes-help.7 endif diff -ur fdupes-2.1.2/Makefile.in fdupes-2.2.1/Makefile.in --- fdupes-2.1.2/Makefile.in 2020-08-12 21:10:06 +++ fdupes-2.2.1/Makefile.in 2022-09-09 09:52:54 @@ -1,7 +1,7 @@ -# Makefile.in generated by automake 1.15.1 from Makefile.am. +# Makefile.in generated by automake 1.16.1 from Makefile.am. # @configure_input@ -# Copyright (C) 1994-2017 Free Software Foundation, Inc. +# Copyright (C) 1994-2018 Free Software Foundation, Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, @@ -87,6 +87,28 @@ PRE_UNINSTALL = : POST_UNINSTALL = : bin_PROGRAMS = fdupes$(EXEEXT) +@WITH_NCURSES_TRUE@am__append_1 = filegroup.h\ +@WITH_NCURSES_TRUE@ fileaction.h\ +@WITH_NCURSES_TRUE@ fileaction.c\ +@WITH_NCURSES_TRUE@ ncurses-commands.c\ +@WITH_NCURSES_TRUE@ ncurses-commands.h\ +@WITH_NCURSES_TRUE@ ncurses-getcommand.c\ +@WITH_NCURSES_TRUE@ ncurses-getcommand.h\ +@WITH_NCURSES_TRUE@ ncurses-interface.c\ +@WITH_NCURSES_TRUE@ ncurses-interface.h\ +@WITH_NCURSES_TRUE@ ncurses-print.c\ +@WITH_NCURSES_TRUE@ ncurses-print.h\ +@WITH_NCURSES_TRUE@ ncurses-prompt.c\ +@WITH_NCURSES_TRUE@ ncurses-prompt.h\ +@WITH_NCURSES_TRUE@ ncurses-status.c\ +@WITH_NCURSES_TRUE@ ncurses-status.h\ +@WITH_NCURSES_TRUE@ commandidentifier.c\ +@WITH_NCURSES_TRUE@ commandidentifier.h\ +@WITH_NCURSES_TRUE@ wcs.c\ +@WITH_NCURSES_TRUE@ wcs.h\ +@WITH_NCURSES_TRUE@ positive_wcwidth.c\ +@WITH_NCURSES_TRUE@ positive_wcwidth.h + subdir = . ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/configure.ac @@ -103,36 +125,33 @@ am__installdirs = "$(DESTDIR)$(bindir)" "$(DESTDIR)$(man1dir)" \ "$(DESTDIR)$(man7dir)" PROGRAMS = $(bin_PROGRAMS) -am__fdupes_SOURCES_DIST = fdupes.c fdupes.h filegroup.h \ +am__fdupes_SOURCES_DIST = fdupes.c fdupes.h errormsg.c errormsg.h \ + dir.c dir.h log.c log.h fmatch.c fmatch.h sigint.c sigint.h \ + flags.c flags.h confirmmatch.c confirmmatch.h \ + removeifnotchanged.c removeifnotchanged.h \ + mbstowcs_escape_invalid.c mbstowcs_escape_invalid.h md5/md5.c \ + md5/md5.h filegroup.h fileaction.h fileaction.c \ ncurses-commands.c ncurses-commands.h ncurses-getcommand.c \ ncurses-getcommand.h ncurses-interface.c ncurses-interface.h \ ncurses-print.c ncurses-print.h ncurses-prompt.c \ ncurses-prompt.h ncurses-status.c ncurses-status.h \ - commandidentifier.c commandidentifier.h errormsg.c errormsg.h \ - wcs.c wcs.h dir.c dir.h log.c log.h fmatch.c fmatch.h sigint.c \ - sigint.h flags.c flags.h mbstowcs_escape_invalid.c \ - mbstowcs_escape_invalid.h positive_wcwidth.c \ - positive_wcwidth.h md5/md5.c md5/md5.h + commandidentifier.c commandidentifier.h wcs.c wcs.h \ + positive_wcwidth.c positive_wcwidth.h am__dirstamp = $(am__leading_dot)dirstamp -@NO_NCURSES_FALSE@am_fdupes_OBJECTS = fdupes.$(OBJEXT) \ -@NO_NCURSES_FALSE@ ncurses-commands.$(OBJEXT) \ -@NO_NCURSES_FALSE@ ncurses-getcommand.$(OBJEXT) \ -@NO_NCURSES_FALSE@ ncurses-interface.$(OBJEXT) \ -@NO_NCURSES_FALSE@ ncurses-print.$(OBJEXT) \ -@NO_NCURSES_FALSE@ ncurses-prompt.$(OBJEXT) \ -@NO_NCURSES_FALSE@ ncurses-status.$(OBJEXT) \ -@NO_NCURSES_FALSE@ commandidentifier.$(OBJEXT) \ -@NO_NCURSES_FALSE@ errormsg.$(OBJEXT) wcs.$(OBJEXT) \ -@NO_NCURSES_FALSE@ dir.$(OBJEXT) log.$(OBJEXT) fmatch.$(OBJEXT) \ -@NO_NCURSES_FALSE@ sigint.$(OBJEXT) flags.$(OBJEXT) \ -@NO_NCURSES_FALSE@ mbstowcs_escape_invalid.$(OBJEXT) \ -@NO_NCURSES_FALSE@ positive_wcwidth.$(OBJEXT) md5/md5.$(OBJEXT) -@NO_NCURSES_TRUE@am_fdupes_OBJECTS = fdupes.$(OBJEXT) \ -@NO_NCURSES_TRUE@ errormsg.$(OBJEXT) dir.$(OBJEXT) \ -@NO_NCURSES_TRUE@ log.$(OBJEXT) fmatch.$(OBJEXT) \ -@NO_NCURSES_TRUE@ sigint.$(OBJEXT) flags.$(OBJEXT) \ -@NO_NCURSES_TRUE@ mbstowcs_escape_invalid.$(OBJEXT) \ -@NO_NCURSES_TRUE@ md5/md5.$(OBJEXT) +@WITH_NCURSES_TRUE@am__objects_1 = fileaction.$(OBJEXT) \ +@WITH_NCURSES_TRUE@ ncurses-commands.$(OBJEXT) \ +@WITH_NCURSES_TRUE@ ncurses-getcommand.$(OBJEXT) \ +@WITH_NCURSES_TRUE@ ncurses-interface.$(OBJEXT) \ +@WITH_NCURSES_TRUE@ ncurses-print.$(OBJEXT) \ +@WITH_NCURSES_TRUE@ ncurses-prompt.$(OBJEXT) \ +@WITH_NCURSES_TRUE@ ncurses-status.$(OBJEXT) \ +@WITH_NCURSES_TRUE@ commandidentifier.$(OBJEXT) wcs.$(OBJEXT) \ +@WITH_NCURSES_TRUE@ positive_wcwidth.$(OBJEXT) +am_fdupes_OBJECTS = fdupes.$(OBJEXT) errormsg.$(OBJEXT) dir.$(OBJEXT) \ + log.$(OBJEXT) fmatch.$(OBJEXT) sigint.$(OBJEXT) \ + flags.$(OBJEXT) confirmmatch.$(OBJEXT) \ + removeifnotchanged.$(OBJEXT) mbstowcs_escape_invalid.$(OBJEXT) \ + md5/md5.$(OBJEXT) $(am__objects_1) fdupes_OBJECTS = $(am_fdupes_OBJECTS) fdupes_LDADD = $(LDADD) AM_V_P = $(am__v_P_@AM_V@) @@ -149,7 +168,20 @@ am__v_at_1 = DEFAULT_INCLUDES = -I.@am__isrc@ depcomp = $(SHELL) $(top_srcdir)/depcomp -am__depfiles_maybe = depfiles +am__maybe_remake_depfiles = depfiles +am__depfiles_remade = ./$(DEPDIR)/commandidentifier.Po \ + ./$(DEPDIR)/confirmmatch.Po ./$(DEPDIR)/dir.Po \ + ./$(DEPDIR)/errormsg.Po ./$(DEPDIR)/fdupes.Po \ + ./$(DEPDIR)/fileaction.Po ./$(DEPDIR)/flags.Po \ + ./$(DEPDIR)/fmatch.Po ./$(DEPDIR)/log.Po \ + ./$(DEPDIR)/mbstowcs_escape_invalid.Po \ + ./$(DEPDIR)/ncurses-commands.Po \ + ./$(DEPDIR)/ncurses-getcommand.Po \ + ./$(DEPDIR)/ncurses-interface.Po ./$(DEPDIR)/ncurses-print.Po \ + ./$(DEPDIR)/ncurses-prompt.Po ./$(DEPDIR)/ncurses-status.Po \ + ./$(DEPDIR)/positive_wcwidth.Po \ + ./$(DEPDIR)/removeifnotchanged.Po ./$(DEPDIR)/sigint.Po \ + ./$(DEPDIR)/wcs.Po md5/$(DEPDIR)/md5.Po am__mv = mv -f COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) @@ -336,66 +368,13 @@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ -@NO_NCURSES_FALSE@fdupes_SOURCES = fdupes.c\ -@NO_NCURSES_FALSE@ fdupes.h\ -@NO_NCURSES_FALSE@ filegroup.h\ -@NO_NCURSES_FALSE@ ncurses-commands.c\ -@NO_NCURSES_FALSE@ ncurses-commands.h\ -@NO_NCURSES_FALSE@ ncurses-getcommand.c\ -@NO_NCURSES_FALSE@ ncurses-getcommand.h\ -@NO_NCURSES_FALSE@ ncurses-interface.c\ -@NO_NCURSES_FALSE@ ncurses-interface.h\ -@NO_NCURSES_FALSE@ ncurses-print.c\ -@NO_NCURSES_FALSE@ ncurses-print.h\ -@NO_NCURSES_FALSE@ ncurses-prompt.c\ -@NO_NCURSES_FALSE@ ncurses-prompt.h\ -@NO_NCURSES_FALSE@ ncurses-status.c\ -@NO_NCURSES_FALSE@ ncurses-status.h\ -@NO_NCURSES_FALSE@ commandidentifier.c\ -@NO_NCURSES_FALSE@ commandidentifier.h\ -@NO_NCURSES_FALSE@ errormsg.c\ -@NO_NCURSES_FALSE@ errormsg.h\ -@NO_NCURSES_FALSE@ wcs.c\ -@NO_NCURSES_FALSE@ wcs.h\ -@NO_NCURSES_FALSE@ dir.c\ -@NO_NCURSES_FALSE@ dir.h\ -@NO_NCURSES_FALSE@ log.c\ -@NO_NCURSES_FALSE@ log.h\ -@NO_NCURSES_FALSE@ fmatch.c\ -@NO_NCURSES_FALSE@ fmatch.h\ -@NO_NCURSES_FALSE@ sigint.c\ -@NO_NCURSES_FALSE@ sigint.h\ -@NO_NCURSES_FALSE@ flags.c\ -@NO_NCURSES_FALSE@ flags.h\ -@NO_NCURSES_FALSE@ mbstowcs_escape_invalid.c\ -@NO_NCURSES_FALSE@ mbstowcs_escape_invalid.h\ -@NO_NCURSES_FALSE@ positive_wcwidth.c\ -@NO_NCURSES_FALSE@ positive_wcwidth.h\ -@NO_NCURSES_FALSE@ md5/md5.c\ -@NO_NCURSES_FALSE@ md5/md5.h - -@NO_NCURSES_TRUE@fdupes_SOURCES = fdupes.c\ -@NO_NCURSES_TRUE@ fdupes.h\ -@NO_NCURSES_TRUE@ errormsg.c\ -@NO_NCURSES_TRUE@ errormsg.h\ -@NO_NCURSES_TRUE@ dir.c\ -@NO_NCURSES_TRUE@ dir.h\ -@NO_NCURSES_TRUE@ log.c\ -@NO_NCURSES_TRUE@ log.h\ -@NO_NCURSES_TRUE@ fmatch.c\ -@NO_NCURSES_TRUE@ fmatch.h\ -@NO_NCURSES_TRUE@ sigint.c\ -@NO_NCURSES_TRUE@ sigint.h\ -@NO_NCURSES_TRUE@ flags.c\ -@NO_NCURSES_TRUE@ flags.h\ -@NO_NCURSES_TRUE@ mbstowcs_escape_invalid.c\ -@NO_NCURSES_TRUE@ mbstowcs_escape_invalid.h\ -@NO_NCURSES_TRUE@ md5/md5.c\ -@NO_NCURSES_TRUE@ md5/md5.h - -@NO_NCURSES_FALSE@dist_man1_MANS = fdupes.1 -@NO_NCURSES_TRUE@dist_man1_MANS = fdupes.1 -@NO_NCURSES_FALSE@dist_man7_MANS = fdupes-help.7 +fdupes_SOURCES = fdupes.c fdupes.h errormsg.c errormsg.h dir.c dir.h \ + log.c log.h fmatch.c fmatch.h sigint.c sigint.h flags.c \ + flags.h confirmmatch.c confirmmatch.h removeifnotchanged.c \ + removeifnotchanged.h mbstowcs_escape_invalid.c \ + mbstowcs_escape_invalid.h md5/md5.c md5/md5.h $(am__append_1) +dist_man1_MANS = fdupes.1 +@WITH_NCURSES_TRUE@dist_man7_MANS = fdupes-help.7 EXTRA_DIST = testdir CHANGES CONTRIBUTORS all: config.h $(MAKE) $(AM_MAKEFLAGS) all-am @@ -423,8 +402,8 @@ echo ' $(SHELL) ./config.status'; \ $(SHELL) ./config.status;; \ *) \ - echo ' cd $(top_builddir) && $(SHELL) ./config.status $@ $(am__depfiles_maybe)'; \ - cd $(top_builddir) && $(SHELL) ./config.status $@ $(am__depfiles_maybe);; \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $@ $(am__maybe_remake_depfiles)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $@ $(am__maybe_remake_depfiles);; \ esac; $(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) @@ -511,25 +490,34 @@ distclean-compile: -rm -f *.tab.c -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/commandidentifier.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dir.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/errormsg.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/fdupes.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/flags.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/fmatch.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/log.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mbstowcs_escape_invalid.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ncurses-commands.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ncurses-getcommand.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ncurses-interface.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ncurses-print.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ncurses-prompt.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ncurses-status.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/positive_wcwidth.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sigint.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/wcs.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@md5/$(DEPDIR)/md5.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/commandidentifier.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/confirmmatch.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dir.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/errormsg.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/fdupes.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/fileaction.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/flags.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/fmatch.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/log.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mbstowcs_escape_invalid.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ncurses-commands.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ncurses-getcommand.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ncurses-interface.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ncurses-print.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ncurses-prompt.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ncurses-status.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/positive_wcwidth.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/removeifnotchanged.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sigint.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/wcs.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@md5/$(DEPDIR)/md5.Po@am__quote@ # am--include-marker +$(am__depfiles_remade): + @$(MKDIR_P) $(@D) + @echo '# dummy' >$@-t && $(am__mv) $@-t $@ + +am--depfiles: $(am__depfiles_remade) + .c.o: @am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.o$$||'`;\ @am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\ @@ -687,7 +675,10 @@ -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags -rm -f cscope.out cscope.in.out cscope.po.out cscope.files -distdir: $(DISTFILES) +distdir: $(BUILT_SOURCES) + $(MAKE) $(AM_MAKEFLAGS) distdir-am + +distdir-am: $(DISTFILES) $(am__remove_distdir) test -d "$(distdir)" || mkdir "$(distdir)" @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ @@ -898,7 +889,27 @@ distclean: distclean-am -rm -f $(am__CONFIG_DISTCLEAN_FILES) - -rm -rf ./$(DEPDIR) md5/$(DEPDIR) + -rm -f ./$(DEPDIR)/commandidentifier.Po + -rm -f ./$(DEPDIR)/confirmmatch.Po + -rm -f ./$(DEPDIR)/dir.Po + -rm -f ./$(DEPDIR)/errormsg.Po + -rm -f ./$(DEPDIR)/fdupes.Po + -rm -f ./$(DEPDIR)/fileaction.Po + -rm -f ./$(DEPDIR)/flags.Po + -rm -f ./$(DEPDIR)/fmatch.Po + -rm -f ./$(DEPDIR)/log.Po + -rm -f ./$(DEPDIR)/mbstowcs_escape_invalid.Po + -rm -f ./$(DEPDIR)/ncurses-commands.Po + -rm -f ./$(DEPDIR)/ncurses-getcommand.Po + -rm -f ./$(DEPDIR)/ncurses-interface.Po + -rm -f ./$(DEPDIR)/ncurses-print.Po + -rm -f ./$(DEPDIR)/ncurses-prompt.Po + -rm -f ./$(DEPDIR)/ncurses-status.Po + -rm -f ./$(DEPDIR)/positive_wcwidth.Po + -rm -f ./$(DEPDIR)/removeifnotchanged.Po + -rm -f ./$(DEPDIR)/sigint.Po + -rm -f ./$(DEPDIR)/wcs.Po + -rm -f md5/$(DEPDIR)/md5.Po -rm -f Makefile distclean-am: clean-am distclean-compile distclean-generic \ distclean-hdr distclean-tags @@ -946,7 +957,27 @@ maintainer-clean: maintainer-clean-am -rm -f $(am__CONFIG_DISTCLEAN_FILES) -rm -rf $(top_srcdir)/autom4te.cache - -rm -rf ./$(DEPDIR) md5/$(DEPDIR) + -rm -f ./$(DEPDIR)/commandidentifier.Po + -rm -f ./$(DEPDIR)/confirmmatch.Po + -rm -f ./$(DEPDIR)/dir.Po + -rm -f ./$(DEPDIR)/errormsg.Po + -rm -f ./$(DEPDIR)/fdupes.Po + -rm -f ./$(DEPDIR)/fileaction.Po + -rm -f ./$(DEPDIR)/flags.Po + -rm -f ./$(DEPDIR)/fmatch.Po + -rm -f ./$(DEPDIR)/log.Po + -rm -f ./$(DEPDIR)/mbstowcs_escape_invalid.Po + -rm -f ./$(DEPDIR)/ncurses-commands.Po + -rm -f ./$(DEPDIR)/ncurses-getcommand.Po + -rm -f ./$(DEPDIR)/ncurses-interface.Po + -rm -f ./$(DEPDIR)/ncurses-print.Po + -rm -f ./$(DEPDIR)/ncurses-prompt.Po + -rm -f ./$(DEPDIR)/ncurses-status.Po + -rm -f ./$(DEPDIR)/positive_wcwidth.Po + -rm -f ./$(DEPDIR)/removeifnotchanged.Po + -rm -f ./$(DEPDIR)/sigint.Po + -rm -f ./$(DEPDIR)/wcs.Po + -rm -f md5/$(DEPDIR)/md5.Po -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic @@ -968,9 +999,9 @@ .MAKE: all install-am install-strip -.PHONY: CTAGS GTAGS TAGS all all-am am--refresh check check-am clean \ - clean-binPROGRAMS clean-cscope clean-generic cscope \ - cscopelist-am ctags ctags-am dist dist-all dist-bzip2 \ +.PHONY: CTAGS GTAGS TAGS all all-am am--depfiles am--refresh check \ + check-am clean clean-binPROGRAMS clean-cscope clean-generic \ + cscope cscopelist-am ctags ctags-am dist dist-all dist-bzip2 \ dist-gzip dist-hook dist-lzip dist-shar dist-tarZ dist-xz \ dist-zip distcheck distclean distclean-compile \ distclean-generic distclean-hdr distclean-tags distcleancheck \ diff -ur fdupes-2.1.2/README fdupes-2.2.1/README --- fdupes-2.1.2/README 2020-08-12 21:09:35 +++ fdupes-2.2.1/README 2022-01-19 21:09:53 @@ -8,65 +8,67 @@ -------------------------------------------------------------------- Usage: fdupes [options] DIRECTORY... - -r --recurse for every directory given follow subdirectories - encountered within - -R --recurse: for each directory given after this option follow - subdirectories encountered within (note the ':' at - the end of the option, manpage for more details) - -s --symlinks follow symlinks - -H --hardlinks normally, when two or more files point to the same - disk area they are treated as non-duplicates; this - option will change this behavior - -G --minsize=SIZE consider only files greater than or equal to SIZE in bytes - -L --maxsize=SIZE consider only files less than or equal to SIZE in bytes - -n --noempty exclude zero-length files from consideration - -A --nohidden exclude hidden files from consideration - -f --omitfirst omit the first file in each set of matches - -1 --sameline list each set of matches on a single line - -S --size show size of duplicate files - -t --time show modification time of duplicate files - -m --summarize summarize dupe information - -q --quiet hide progress indicator - -d --delete prompt user for files to preserve and delete all - others; important: under particular circumstances, - data may be lost when using this option together - with -s or --symlinks, or when specifying a - particular directory more than once; refer to the - fdupes documentation for additional information - -P --plain with --delete, use line-based prompt (as with older - versions of fdupes) instead of screen-mode interface - -N --noprompt together with --delete, preserve the first file in - each set of duplicates and delete the rest without - prompting the user - -I --immediate delete duplicates as they are encountered, without - grouping into sets; implies --noprompt - -p --permissions don't consider files with different owner/group or - permission bits as duplicates - -o --order=BY select sort order for output and deleting; by file - modification time (BY='time'; default), status - change time (BY='ctime'), or filename (BY='name') - -i --reverse reverse order while sorting - -l --log=LOGFILE log file deletion choices to LOGFILE - -v --version display fdupes version - -h --help display this help message + -r --recurse for every directory given follow subdirectories + encountered within + -R --recurse: for each directory given after this option follow + subdirectories encountered within (note the ':' at the + end of the option, manpage for more details) + -s --symlinks follow symlinks + -H --hardlinks normally, when two or more files point to the same + disk area they are treated as non-duplicates; this + option will change this behavior + -G --minsize=SIZE consider only files greater than or equal to SIZE bytes + -L --maxsize=SIZE consider only files less than or equal to SIZE bytes + -n --noempty exclude zero-length files from consideration + -A --nohidden exclude hidden files from consideration + -f --omitfirst omit the first file in each set of matches + -1 --sameline list each set of matches on a single line + -S --size show size of duplicate files + -t --time show modification time of duplicate files + -m --summarize summarize dupe information + -q --quiet hide progress indicator + -d --delete prompt user for files to preserve and delete all + others; important: under particular circumstances, + data may be lost when using this option together + with -s or --symlinks, or when specifying a + particular directory more than once; refer to the + fdupes documentation for additional information + -D --deferconfirmation in interactive mode, defer byte-for-byte confirmation + of duplicates until just before file deletion + -P --plain with --delete, use line-based prompt (as with older + versions of fdupes) instead of screen-mode interface + -N --noprompt together with --delete, preserve the first file in + each set of duplicates and delete the rest without + prompting the user + -I --immediate delete duplicates as they are encountered, without + grouping into sets; implies --noprompt + -p --permissions don't consider files with different owner/group or + permission bits as duplicates + -o --order=BY select sort order for output and deleting; by file + modification time (BY='time'; default), status + change time (BY='ctime'), or filename (BY='name') + -i --reverse reverse order while sorting + -l --log=LOGFILE log file deletion choices to LOGFILE + -v --version display fdupes version + -h --help display this help message -Unless -1 or --sameline is specified, duplicate files are listed +Unless -1 or --sameline is specified, duplicate files are listed together in groups, each file displayed on a separate line. The groups are then separated from each other by blank lines. -When -1 or --sameline is specified, spaces and backslash characters (\) +When -1 or --sameline is specified, spaces and backslash characters (\) appearing in a filename are preceded by a backslash character. For instance, "with spaces" becomes "with\ spaces". When using -d or --delete, care should be taken to insure against accidental data loss. While no information will be immediately -lost, using this option together with -s or --symlink can lead +lost, using this option together with -s or --symlink can lead to confusing information being presented to the user when prompted for files to preserve. Specifically, a user could accidentally preserve a symlink while deleting the file it points to. A similar -problem arises when specifying a particular directory more than +problem arises when specifying a particular directory more than once. All files within that directory will be listed as their own -duplicates, leading to data loss should a user preserve a file +duplicates, leading to data loss should a user preserve a file without its "duplicate" (the file itself!). diff -ur fdupes-2.1.2/aclocal.m4 fdupes-2.2.1/aclocal.m4 --- fdupes-2.1.2/aclocal.m4 2020-08-12 21:10:04 +++ fdupes-2.2.1/aclocal.m4 2022-09-09 09:52:53 @@ -1,6 +1,6 @@ -# generated automatically by aclocal 1.15.1 -*- Autoconf -*- +# generated automatically by aclocal 1.16.1 -*- Autoconf -*- -# Copyright (C) 1996-2017 Free Software Foundation, Inc. +# Copyright (C) 1996-2018 Free Software Foundation, Inc. # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, @@ -296,7 +296,7 @@ AS_VAR_IF([$1], [""], [$5], [$4])dnl ])dnl PKG_CHECK_VAR -# Copyright (C) 2002-2017 Free Software Foundation, Inc. +# Copyright (C) 2002-2018 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, @@ -308,10 +308,10 @@ # generated from the m4 files accompanying Automake X.Y. # (This private macro should not be called outside this file.) AC_DEFUN([AM_AUTOMAKE_VERSION], -[am__api_version='1.15' +[am__api_version='1.16' dnl Some users find AM_AUTOMAKE_VERSION and mistake it for a way to dnl require some minimum version. Point them to the right macro. -m4_if([$1], [1.15.1], [], +m4_if([$1], [1.16.1], [], [AC_FATAL([Do not call $0, use AM_INIT_AUTOMAKE([$1]).])])dnl ]) @@ -327,14 +327,14 @@ # Call AM_AUTOMAKE_VERSION and AM_AUTOMAKE_VERSION so they can be traced. # This function is AC_REQUIREd by AM_INIT_AUTOMAKE. AC_DEFUN([AM_SET_CURRENT_AUTOMAKE_VERSION], -[AM_AUTOMAKE_VERSION([1.15.1])dnl +[AM_AUTOMAKE_VERSION([1.16.1])dnl m4_ifndef([AC_AUTOCONF_VERSION], [m4_copy([m4_PACKAGE_VERSION], [AC_AUTOCONF_VERSION])])dnl _AM_AUTOCONF_VERSION(m4_defn([AC_AUTOCONF_VERSION]))]) # AM_AUX_DIR_EXPAND -*- Autoconf -*- -# Copyright (C) 2001-2017 Free Software Foundation, Inc. +# Copyright (C) 2001-2018 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, @@ -386,7 +386,7 @@ # AM_CONDITIONAL -*- Autoconf -*- -# Copyright (C) 1997-2017 Free Software Foundation, Inc. +# Copyright (C) 1997-2018 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, @@ -417,7 +417,7 @@ Usually this means the macro was only invoked conditionally.]]) fi])]) -# Copyright (C) 1999-2017 Free Software Foundation, Inc. +# Copyright (C) 1999-2018 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, @@ -608,13 +608,12 @@ # Generate code to set up dependency tracking. -*- Autoconf -*- -# Copyright (C) 1999-2017 Free Software Foundation, Inc. +# Copyright (C) 1999-2018 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. - # _AM_OUTPUT_DEPENDENCY_COMMANDS # ------------------------------ AC_DEFUN([_AM_OUTPUT_DEPENDENCY_COMMANDS], @@ -622,49 +621,41 @@ # Older Autoconf quotes --file arguments for eval, but not when files # are listed without --file. Let's play safe and only enable the eval # if we detect the quoting. - case $CONFIG_FILES in - *\'*) eval set x "$CONFIG_FILES" ;; - *) set x $CONFIG_FILES ;; - esac + # TODO: see whether this extra hack can be removed once we start + # requiring Autoconf 2.70 or later. + AS_CASE([$CONFIG_FILES], + [*\'*], [eval set x "$CONFIG_FILES"], + [*], [set x $CONFIG_FILES]) shift - for mf + # Used to flag and report bootstrapping failures. + am_rc=0 + for am_mf do # Strip MF so we end up with the name of the file. - mf=`echo "$mf" | sed -e 's/:.*$//'` - # Check whether this is an Automake generated Makefile or not. - # We used to match only the files named 'Makefile.in', but - # some people rename them; so instead we look at the file content. - # Grep'ing the first line is not enough: some people post-process - # each Makefile.in and add a new line on top of each file to say so. - # Grep'ing the whole file is not good either: AIX grep has a line + am_mf=`AS_ECHO(["$am_mf"]) | sed -e 's/:.*$//'` + # Check whether this is an Automake generated Makefile which includes + # dependency-tracking related rules and includes. + # Grep'ing the whole file directly is not great: AIX grep has a line # limit of 2048, but all sed's we know have understand at least 4000. - if sed -n 's,^#.*generated by automake.*,X,p' "$mf" | grep X >/dev/null 2>&1; then - dirpart=`AS_DIRNAME("$mf")` - else - continue - fi - # Extract the definition of DEPDIR, am__include, and am__quote - # from the Makefile without running 'make'. - DEPDIR=`sed -n 's/^DEPDIR = //p' < "$mf"` - test -z "$DEPDIR" && continue - am__include=`sed -n 's/^am__include = //p' < "$mf"` - test -z "$am__include" && continue - am__quote=`sed -n 's/^am__quote = //p' < "$mf"` - # Find all dependency output files, they are included files with - # $(DEPDIR) in their names. We invoke sed twice because it is the - # simplest approach to changing $(DEPDIR) to its actual value in the - # expansion. - for file in `sed -n " - s/^$am__include $am__quote\(.*(DEPDIR).*\)$am__quote"'$/\1/p' <"$mf" | \ - sed -e 's/\$(DEPDIR)/'"$DEPDIR"'/g'`; do - # Make sure the directory exists. - test -f "$dirpart/$file" && continue - fdir=`AS_DIRNAME(["$file"])` - AS_MKDIR_P([$dirpart/$fdir]) - # echo "creating $dirpart/$file" - echo '# dummy' > "$dirpart/$file" - done + sed -n 's,^am--depfiles:.*,X,p' "$am_mf" | grep X >/dev/null 2>&1 \ + || continue + am_dirpart=`AS_DIRNAME(["$am_mf"])` + am_filepart=`AS_BASENAME(["$am_mf"])` + AM_RUN_LOG([cd "$am_dirpart" \ + && sed -e '/# am--include-marker/d' "$am_filepart" \ + | $MAKE -f - am--depfiles]) || am_rc=$? done + if test $am_rc -ne 0; then + AC_MSG_FAILURE([Something went wrong bootstrapping makefile fragments + for automatic dependency tracking. Try re-running configure with the + '--disable-dependency-tracking' option to at least be able to build + the package (albeit without support for automatic dependency tracking).]) + fi + AS_UNSET([am_dirpart]) + AS_UNSET([am_filepart]) + AS_UNSET([am_mf]) + AS_UNSET([am_rc]) + rm -f conftest-deps.mk } ])# _AM_OUTPUT_DEPENDENCY_COMMANDS @@ -673,18 +664,17 @@ # ----------------------------- # This macro should only be invoked once -- use via AC_REQUIRE. # -# This code is only required when automatic dependency tracking -# is enabled. FIXME. This creates each '.P' file that we will -# need in order to bootstrap the dependency handling code. +# This code is only required when automatic dependency tracking is enabled. +# This creates each '.Po' and '.Plo' makefile fragment that we'll need in +# order to bootstrap the dependency handling code. AC_DEFUN([AM_OUTPUT_DEPENDENCY_COMMANDS], [AC_CONFIG_COMMANDS([depfiles], [test x"$AMDEP_TRUE" != x"" || _AM_OUTPUT_DEPENDENCY_COMMANDS], - [AMDEP_TRUE="$AMDEP_TRUE" ac_aux_dir="$ac_aux_dir"]) -]) + [AMDEP_TRUE="$AMDEP_TRUE" MAKE="${MAKE-make}"])]) # Do all the work for Automake. -*- Autoconf -*- -# Copyright (C) 1996-2017 Free Software Foundation, Inc. +# Copyright (C) 1996-2018 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, @@ -771,8 +761,8 @@ AC_REQUIRE([AC_PROG_MKDIR_P])dnl # For better backward compatibility. To be removed once Automake 1.9.x # dies out for good. For more background, see: -# -# +# +# AC_SUBST([mkdir_p], ['$(MKDIR_P)']) # We need awk for the "check" target (and possibly the TAP driver). The # system "awk" is bad on some platforms. @@ -839,7 +829,7 @@ Aborting the configuration process, to ensure you take notice of the issue. You can download and install GNU coreutils to get an 'rm' implementation -that behaves properly: . +that behaves properly: . If you want to complete the configuration process using your problematic 'rm' anyway, export the environment variable ACCEPT_INFERIOR_RM_PROGRAM @@ -881,7 +871,7 @@ done echo "timestamp for $_am_arg" >`AS_DIRNAME(["$_am_arg"])`/stamp-h[]$_am_stamp_count]) -# Copyright (C) 2001-2017 Free Software Foundation, Inc. +# Copyright (C) 2001-2018 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, @@ -902,7 +892,7 @@ fi AC_SUBST([install_sh])]) -# Copyright (C) 2003-2017 Free Software Foundation, Inc. +# Copyright (C) 2003-2018 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, @@ -923,7 +913,7 @@ # Check to see how 'make' treats includes. -*- Autoconf -*- -# Copyright (C) 2001-2017 Free Software Foundation, Inc. +# Copyright (C) 2001-2018 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, @@ -931,49 +921,42 @@ # AM_MAKE_INCLUDE() # ----------------- -# Check to see how make treats includes. +# Check whether make has an 'include' directive that can support all +# the idioms we need for our automatic dependency tracking code. AC_DEFUN([AM_MAKE_INCLUDE], -[am_make=${MAKE-make} -cat > confinc << 'END' +[AC_MSG_CHECKING([whether ${MAKE-make} supports the include directive]) +cat > confinc.mk << 'END' am__doit: - @echo this is the am__doit target + @echo this is the am__doit target >confinc.out .PHONY: am__doit END -# If we don't find an include directive, just comment out the code. -AC_MSG_CHECKING([for style of include used by $am_make]) am__include="#" am__quote= -_am_result=none -# First try GNU make style include. -echo "include confinc" > confmf -# Ignore all kinds of additional output from 'make'. -case `$am_make -s -f confmf 2> /dev/null` in #( -*the\ am__doit\ target*) - am__include=include - am__quote= - _am_result=GNU - ;; -esac -# Now try BSD make style include. -if test "$am__include" = "#"; then - echo '.include "confinc"' > confmf - case `$am_make -s -f confmf 2> /dev/null` in #( - *the\ am__doit\ target*) - am__include=.include - am__quote="\"" - _am_result=BSD - ;; - esac -fi -AC_SUBST([am__include]) -AC_SUBST([am__quote]) -AC_MSG_RESULT([$_am_result]) -rm -f confinc confmf -]) +# BSD make does it like this. +echo '.include "confinc.mk" # ignored' > confmf.BSD +# Other make implementations (GNU, Solaris 10, AIX) do it like this. +echo 'include confinc.mk # ignored' > confmf.GNU +_am_result=no +for s in GNU BSD; do + AM_RUN_LOG([${MAKE-make} -f confmf.$s && cat confinc.out]) + AS_CASE([$?:`cat confinc.out 2>/dev/null`], + ['0:this is the am__doit target'], + [AS_CASE([$s], + [BSD], [am__include='.include' am__quote='"'], + [am__include='include' am__quote=''])]) + if test "$am__include" != "#"; then + _am_result="yes ($s style)" + break + fi +done +rm -f confinc.* confmf.* +AC_MSG_RESULT([${_am_result}]) +AC_SUBST([am__include])]) +AC_SUBST([am__quote])]) # Fake the existence of programs that GNU maintainers use. -*- Autoconf -*- -# Copyright (C) 1997-2017 Free Software Foundation, Inc. +# Copyright (C) 1997-2018 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, @@ -1012,7 +995,7 @@ # Helper functions for option handling. -*- Autoconf -*- -# Copyright (C) 2001-2017 Free Software Foundation, Inc. +# Copyright (C) 2001-2018 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, @@ -1041,7 +1024,7 @@ AC_DEFUN([_AM_IF_OPTION], [m4_ifset(_AM_MANGLE_OPTION([$1]), [$2], [$3])]) -# Copyright (C) 1999-2017 Free Software Foundation, Inc. +# Copyright (C) 1999-2018 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, @@ -1088,7 +1071,7 @@ # For backward compatibility. AC_DEFUN_ONCE([AM_PROG_CC_C_O], [AC_REQUIRE([AC_PROG_CC])]) -# Copyright (C) 2001-2017 Free Software Foundation, Inc. +# Copyright (C) 2001-2018 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, @@ -1107,7 +1090,7 @@ # Check to make sure that the build environment is sane. -*- Autoconf -*- -# Copyright (C) 1996-2017 Free Software Foundation, Inc. +# Copyright (C) 1996-2018 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, @@ -1188,7 +1171,7 @@ rm -f conftest.file ]) -# Copyright (C) 2009-2017 Free Software Foundation, Inc. +# Copyright (C) 2009-2018 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, @@ -1248,7 +1231,7 @@ _AM_SUBST_NOTMAKE([AM_BACKSLASH])dnl ]) -# Copyright (C) 2001-2017 Free Software Foundation, Inc. +# Copyright (C) 2001-2018 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, @@ -1276,7 +1259,7 @@ INSTALL_STRIP_PROGRAM="\$(install_sh) -c -s" AC_SUBST([INSTALL_STRIP_PROGRAM])]) -# Copyright (C) 2006-2017 Free Software Foundation, Inc. +# Copyright (C) 2006-2018 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, @@ -1295,7 +1278,7 @@ # Check how to create a tarball. -*- Autoconf -*- -# Copyright (C) 2004-2017 Free Software Foundation, Inc. +# Copyright (C) 2004-2018 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, diff -ur fdupes-2.1.2/commandidentifier.c fdupes-2.2.1/commandidentifier.c --- fdupes-2.1.2/commandidentifier.c 2020-08-12 21:09:35 +++ fdupes-2.2.1/commandidentifier.c 2022-09-04 05:59:05 @@ -1,4 +1,4 @@ -/* Copyright (c) 2018 Adrian Lopez +/* Copyright (c) 2018-2022 Adrian Lopez This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff -ur fdupes-2.1.2/commandidentifier.h fdupes-2.2.1/commandidentifier.h --- fdupes-2.1.2/commandidentifier.h 2020-08-12 21:09:35 +++ fdupes-2.2.1/commandidentifier.h 2022-09-04 05:59:05 @@ -1,4 +1,4 @@ -/* Copyright (c) 2018 Adrian Lopez +/* Copyright (c) 2018-2022 Adrian Lopez This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff -ur fdupes-2.1.2/compile fdupes-2.2.1/compile --- fdupes-2.1.2/compile 2020-08-12 21:10:06 +++ fdupes-2.2.1/compile 2022-01-19 21:07:47 @@ -3,7 +3,7 @@ scriptversion=2012-10-14.11; # UTC -# Copyright (C) 1999-2014 Free Software Foundation, Inc. +# Copyright (C) 1999-2013 Free Software Foundation, Inc. # Written by Tom Tromey . # # This program is free software; you can redistribute it and/or modify diff -ur fdupes-2.1.2/config.h.in fdupes-2.2.1/config.h.in --- fdupes-2.1.2/config.h.in 2020-08-12 21:10:05 +++ fdupes-2.2.1/config.h.in 2022-09-09 09:52:57 @@ -1,5 +1,8 @@ /* config.h.in. Generated from configure.ac by autoheader. */ +/* number of bytes to read per read call */ +#undef CHUNK_SIZE + /* Define to 1 if you have the header file. */ #undef HAVE_GETOPT_H @@ -36,6 +39,9 @@ /* fdupes help file */ #undef HELP_COMMAND_STRING +/* size of command buffer (plain interactive mode only) */ +#undef INPUT_SIZE + /* Do not compile against ncurses */ #undef NO_NCURSES @@ -59,6 +65,9 @@ /* Define to the version of this package. */ #undef PACKAGE_VERSION + +/* maximum number of bytes to use when calculating partial hashes */ +#undef PARTIAL_MD5_SIZE /* PCRE2 Code Unit Width */ #undef PCRE2_CODE_UNIT_WIDTH diff -ur fdupes-2.1.2/configure fdupes-2.2.1/configure --- fdupes-2.1.2/configure 2020-08-12 21:10:05 +++ fdupes-2.2.1/configure 2022-09-09 09:52:54 @@ -1,6 +1,6 @@ #! /bin/sh # Guess values for system-dependent variables and create Makefiles. -# Generated by GNU Autoconf 2.69 for fdupes 2.1.2. +# Generated by GNU Autoconf 2.69 for fdupes 2.2.1. # # # Copyright (C) 1992-1996, 1998-2012 Free Software Foundation, Inc. @@ -577,8 +577,8 @@ # Identity of this package. PACKAGE_NAME='fdupes' PACKAGE_TARNAME='fdupes' -PACKAGE_VERSION='2.1.2' -PACKAGE_STRING='fdupes 2.1.2' +PACKAGE_VERSION='2.2.1' +PACKAGE_STRING='fdupes 2.2.1' PACKAGE_BUGREPORT='' PACKAGE_URL='' @@ -622,8 +622,8 @@ am__EXEEXT_TRUE LTLIBOBJS LIBOBJS -NO_NCURSES_FALSE -NO_NCURSES_TRUE +WITH_NCURSES_FALSE +WITH_NCURSES_TRUE NCURSES_LIBS NCURSES_CFLAGS EGREP @@ -636,7 +636,6 @@ AMDEPBACKSLASH AMDEP_FALSE AMDEP_TRUE -am__quote am__include DEPDIR OBJEXT @@ -714,7 +713,8 @@ PACKAGE_TARNAME PACKAGE_NAME PATH_SEPARATOR -SHELL' +SHELL +am__quote' ac_subst_files='' ac_user_opts=' enable_option_checking @@ -1286,7 +1286,7 @@ # Omit some internal or obsolete options to make the list less imposing. # This message is too long to be a string in the A/UX 3.1 sh. cat <<_ACEOF -\`configure' configures fdupes 2.1.2 to adapt to many kinds of systems. +\`configure' configures fdupes 2.2.1 to adapt to many kinds of systems. Usage: $0 [OPTION]... [VAR=VALUE]... @@ -1353,7 +1353,7 @@ if test -n "$ac_init_help"; then case $ac_init_help in - short | recursive ) echo "Configuration of fdupes 2.1.2:";; + short | recursive ) echo "Configuration of fdupes 2.2.1:";; esac cat <<\_ACEOF @@ -1458,7 +1458,7 @@ test -n "$ac_init_help" && exit $ac_status if $ac_init_version; then cat <<\_ACEOF -fdupes configure 2.1.2 +fdupes configure 2.2.1 generated by GNU Autoconf 2.69 Copyright (C) 2012 Free Software Foundation, Inc. @@ -1756,7 +1756,7 @@ This file contains any messages produced by compilers while running configure, to aid debugging if configure makes a mistake. -It was created by fdupes $as_me 2.1.2, which was +It was created by fdupes $as_me 2.2.1, which was generated by GNU Autoconf 2.69. Invocation command line was $ $0 $@ @@ -2105,7 +2105,7 @@ -am__api_version='1.15' +am__api_version='1.16' ac_aux_dir= for ac_dir in "$srcdir" "$srcdir/.." "$srcdir/../.."; do @@ -2620,7 +2620,7 @@ # Define the identity of the package. PACKAGE='fdupes' - VERSION='2.1.2' + VERSION='2.2.1' cat >>confdefs.h <<_ACEOF @@ -2650,8 +2650,8 @@ # For better backward compatibility. To be removed once Automake 1.9.x # dies out for good. For more background, see: -# -# +# +# mkdir_p='$(MKDIR_P)' # We need awk for the "check" target (and possibly the TAP driver). The @@ -2702,7 +2702,7 @@ Aborting the configuration process, to ensure you take notice of the issue. You can download and install GNU coreutils to get an 'rm' implementation -that behaves properly: . +that behaves properly: . If you want to complete the configuration process using your problematic 'rm' anyway, export the environment variable ACCEPT_INFERIOR_RM_PROGRAM @@ -2851,46 +2851,46 @@ ac_config_commands="$ac_config_commands depfiles" - -am_make=${MAKE-make} -cat > confinc << 'END' +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether ${MAKE-make} supports the include directive" >&5 +$as_echo_n "checking whether ${MAKE-make} supports the include directive... " >&6; } +cat > confinc.mk << 'END' am__doit: - @echo this is the am__doit target + @echo this is the am__doit target >confinc.out .PHONY: am__doit END -# If we don't find an include directive, just comment out the code. -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for style of include used by $am_make" >&5 -$as_echo_n "checking for style of include used by $am_make... " >&6; } am__include="#" am__quote= -_am_result=none -# First try GNU make style include. -echo "include confinc" > confmf -# Ignore all kinds of additional output from 'make'. -case `$am_make -s -f confmf 2> /dev/null` in #( -*the\ am__doit\ target*) - am__include=include - am__quote= - _am_result=GNU - ;; -esac -# Now try BSD make style include. -if test "$am__include" = "#"; then - echo '.include "confinc"' > confmf - case `$am_make -s -f confmf 2> /dev/null` in #( - *the\ am__doit\ target*) - am__include=.include - am__quote="\"" - _am_result=BSD +# BSD make does it like this. +echo '.include "confinc.mk" # ignored' > confmf.BSD +# Other make implementations (GNU, Solaris 10, AIX) do it like this. +echo 'include confinc.mk # ignored' > confmf.GNU +_am_result=no +for s in GNU BSD; do + { echo "$as_me:$LINENO: ${MAKE-make} -f confmf.$s && cat confinc.out" >&5 + (${MAKE-make} -f confmf.$s && cat confinc.out) >&5 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } + case $?:`cat confinc.out 2>/dev/null` in #( + '0:this is the am__doit target') : + case $s in #( + BSD) : + am__include='.include' am__quote='"' ;; #( + *) : + am__include='include' am__quote='' ;; +esac ;; #( + *) : ;; - esac -fi +esac + if test "$am__include" != "#"; then + _am_result="yes ($s style)" + break + fi +done +rm -f confinc.* confmf.* +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: ${_am_result}" >&5 +$as_echo "${_am_result}" >&6; } - -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $_am_result" >&5 -$as_echo "$_am_result" >&6; } -rm -f confinc confmf - # Check whether --enable-dependency-tracking was given. if test "${enable_dependency_tracking+set}" = set; then : enableval=$enable_dependency_tracking; @@ -4679,12 +4679,12 @@ fi - if test x"$with_ncurses" = x"no"; then - NO_NCURSES_TRUE= - NO_NCURSES_FALSE='#' + if test x"$with_ncurses" != x"no"; then + WITH_NCURSES_TRUE= + WITH_NCURSES_FALSE='#' else - NO_NCURSES_TRUE='#' - NO_NCURSES_FALSE= + WITH_NCURSES_TRUE='#' + WITH_NCURSES_FALSE= fi @@ -4702,6 +4702,16 @@ $as_echo "#define _FILE_OFFSET_BITS 64" >>confdefs.h + +$as_echo "#define CHUNK_SIZE 8192" >>confdefs.h + + +$as_echo "#define PARTIAL_MD5_SIZE 4096" >>confdefs.h + + +$as_echo "#define INPUT_SIZE 256" >>confdefs.h + + ac_config_files="$ac_config_files Makefile" ac_ext=c @@ -5563,8 +5573,8 @@ as_fn_error $? "conditional \"am__fastdepCC\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi -if test -z "${NO_NCURSES_TRUE}" && test -z "${NO_NCURSES_FALSE}"; then - as_fn_error $? "conditional \"NO_NCURSES\" was never defined. +if test -z "${WITH_NCURSES_TRUE}" && test -z "${WITH_NCURSES_FALSE}"; then + as_fn_error $? "conditional \"WITH_NCURSES\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${am__fastdepCC_TRUE}" && test -z "${am__fastdepCC_FALSE}"; then @@ -5968,7 +5978,7 @@ # report actual input values of CONFIG_FILES etc. instead of their # values after options handling. ac_log=" -This file was extended by fdupes $as_me 2.1.2, which was +This file was extended by fdupes $as_me 2.2.1, which was generated by GNU Autoconf 2.69. Invocation command line was CONFIG_FILES = $CONFIG_FILES @@ -6034,7 +6044,7 @@ cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`" ac_cs_version="\\ -fdupes config.status 2.1.2 +fdupes config.status 2.2.1 configured by $0, generated by GNU Autoconf 2.69, with options \\"\$ac_cs_config\\" @@ -6153,7 +6163,7 @@ # # INIT-COMMANDS # -AMDEP_TRUE="$AMDEP_TRUE" ac_aux_dir="$ac_aux_dir" +AMDEP_TRUE="$AMDEP_TRUE" MAKE="${MAKE-make}" _ACEOF @@ -6765,29 +6775,35 @@ # Older Autoconf quotes --file arguments for eval, but not when files # are listed without --file. Let's play safe and only enable the eval # if we detect the quoting. - case $CONFIG_FILES in - *\'*) eval set x "$CONFIG_FILES" ;; - *) set x $CONFIG_FILES ;; - esac + # TODO: see whether this extra hack can be removed once we start + # requiring Autoconf 2.70 or later. + case $CONFIG_FILES in #( + *\'*) : + eval set x "$CONFIG_FILES" ;; #( + *) : + set x $CONFIG_FILES ;; #( + *) : + ;; +esac shift - for mf + # Used to flag and report bootstrapping failures. + am_rc=0 + for am_mf do # Strip MF so we end up with the name of the file. - mf=`echo "$mf" | sed -e 's/:.*$//'` - # Check whether this is an Automake generated Makefile or not. - # We used to match only the files named 'Makefile.in', but - # some people rename them; so instead we look at the file content. - # Grep'ing the first line is not enough: some people post-process - # each Makefile.in and add a new line on top of each file to say so. - # Grep'ing the whole file is not good either: AIX grep has a line + am_mf=`$as_echo "$am_mf" | sed -e 's/:.*$//'` + # Check whether this is an Automake generated Makefile which includes + # dependency-tracking related rules and includes. + # Grep'ing the whole file directly is not great: AIX grep has a line # limit of 2048, but all sed's we know have understand at least 4000. - if sed -n 's,^#.*generated by automake.*,X,p' "$mf" | grep X >/dev/null 2>&1; then - dirpart=`$as_dirname -- "$mf" || -$as_expr X"$mf" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ - X"$mf" : 'X\(//\)[^/]' \| \ - X"$mf" : 'X\(//\)$' \| \ - X"$mf" : 'X\(/\)' \| . 2>/dev/null || -$as_echo X"$mf" | + sed -n 's,^am--depfiles:.*,X,p' "$am_mf" | grep X >/dev/null 2>&1 \ + || continue + am_dirpart=`$as_dirname -- "$am_mf" || +$as_expr X"$am_mf" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$am_mf" : 'X\(//\)[^/]' \| \ + X"$am_mf" : 'X\(//\)$' \| \ + X"$am_mf" : 'X\(/\)' \| . 2>/dev/null || +$as_echo X"$am_mf" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/ q @@ -6805,53 +6821,48 @@ q } s/.*/./; q'` - else - continue - fi - # Extract the definition of DEPDIR, am__include, and am__quote - # from the Makefile without running 'make'. - DEPDIR=`sed -n 's/^DEPDIR = //p' < "$mf"` - test -z "$DEPDIR" && continue - am__include=`sed -n 's/^am__include = //p' < "$mf"` - test -z "$am__include" && continue - am__quote=`sed -n 's/^am__quote = //p' < "$mf"` - # Find all dependency output files, they are included files with - # $(DEPDIR) in their names. We invoke sed twice because it is the - # simplest approach to changing $(DEPDIR) to its actual value in the - # expansion. - for file in `sed -n " - s/^$am__include $am__quote\(.*(DEPDIR).*\)$am__quote"'$/\1/p' <"$mf" | \ - sed -e 's/\$(DEPDIR)/'"$DEPDIR"'/g'`; do - # Make sure the directory exists. - test -f "$dirpart/$file" && continue - fdir=`$as_dirname -- "$file" || -$as_expr X"$file" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ - X"$file" : 'X\(//\)[^/]' \| \ - X"$file" : 'X\(//\)$' \| \ - X"$file" : 'X\(/\)' \| . 2>/dev/null || -$as_echo X"$file" | - sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ + am_filepart=`$as_basename -- "$am_mf" || +$as_expr X/"$am_mf" : '.*/\([^/][^/]*\)/*$' \| \ + X"$am_mf" : 'X\(//\)$' \| \ + X"$am_mf" : 'X\(/\)' \| . 2>/dev/null || +$as_echo X/"$am_mf" | + sed '/^.*\/\([^/][^/]*\)\/*$/{ s//\1/ q } - /^X\(\/\/\)[^/].*/{ + /^X\/\(\/\/\)$/{ s//\1/ q } - /^X\(\/\/\)$/{ + /^X\/\(\/\).*/{ s//\1/ q } - /^X\(\/\).*/{ - s//\1/ - q - } s/.*/./; q'` - as_dir=$dirpart/$fdir; as_fn_mkdir_p - # echo "creating $dirpart/$file" - echo '# dummy' > "$dirpart/$file" - done + { echo "$as_me:$LINENO: cd "$am_dirpart" \ + && sed -e '/# am--include-marker/d' "$am_filepart" \ + | $MAKE -f - am--depfiles" >&5 + (cd "$am_dirpart" \ + && sed -e '/# am--include-marker/d' "$am_filepart" \ + | $MAKE -f - am--depfiles) >&5 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } || am_rc=$? done + if test $am_rc -ne 0; then + { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +as_fn_error $? "Something went wrong bootstrapping makefile fragments + for automatic dependency tracking. Try re-running configure with the + '--disable-dependency-tracking' option to at least be able to build + the package (albeit without support for automatic dependency tracking). +See \`config.log' for more details" "$LINENO" 5; } + fi + { am_dirpart=; unset am_dirpart;} + { am_filepart=; unset am_filepart;} + { am_mf=; unset am_mf;} + { am_rc=; unset am_rc;} + rm -f conftest-deps.mk } ;; diff -ur fdupes-2.1.2/configure.ac fdupes-2.2.1/configure.ac --- fdupes-2.1.2/configure.ac 2020-08-12 21:09:35 +++ fdupes-2.2.1/configure.ac 2022-09-09 09:52:43 @@ -1,4 +1,4 @@ -AC_INIT([fdupes], [2.1.2]) +AC_INIT([fdupes], [2.2.1]) AM_INIT_AUTOMAKE([foreign subdir-objects]) @@ -27,7 +27,7 @@ [AC_DEFINE([NO_NCURSES], [], [Do not compile against ncurses])] ) -AM_CONDITIONAL([NO_NCURSES], [test x"$with_ncurses" = x"no"]) +AM_CONDITIONAL([WITH_NCURSES], [test x"$with_ncurses" != x"no"]) unescaped_program_transform_name=`echo "${program_transform_name}"|sed -e "s&\\\\$\\\\$&\\\\$&g"` transformed_program_name=`echo "${PACKAGE_NAME}"|sed -e "${unescaped_program_transform_name}"|sed -e "s&\\\\\\\\&\\\\\\\\\\\\\\\\&g"` @@ -36,6 +36,10 @@ AC_DEFINE_UNQUOTED([HELP_COMMAND_STRING], "man 7 ${transformed_manpage_name}", [fdupes help file]) AC_DEFINE([_FILE_OFFSET_BITS], [64], [allow fdupes to handle files greater than (2<<31)-1 bytes]) + +AC_DEFINE([CHUNK_SIZE], [8192], [number of bytes to read per read call]) +AC_DEFINE([PARTIAL_MD5_SIZE], [4096], [maximum number of bytes to use when calculating partial hashes]) +AC_DEFINE([INPUT_SIZE], [256], [size of command buffer (plain interactive mode only)]) AC_CONFIG_FILES([Makefile]) AC_PROG_CC Only in fdupes-2.2.1: confirmmatch.c Only in fdupes-2.2.1: confirmmatch.h diff -ur fdupes-2.1.2/depcomp fdupes-2.2.1/depcomp --- fdupes-2.1.2/depcomp 2020-08-12 21:10:06 +++ fdupes-2.2.1/depcomp 2022-01-19 21:07:47 @@ -1,9 +1,9 @@ #! /bin/sh # depcomp - compile a program generating dependencies as side-effects -scriptversion=2016-01-11.22; # UTC +scriptversion=2013-05-30.07; # UTC -# Copyright (C) 1999-2017 Free Software Foundation, Inc. +# Copyright (C) 1999-2013 Free Software Foundation, Inc. # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by @@ -786,6 +786,6 @@ # eval: (add-hook 'write-file-hooks 'time-stamp) # time-stamp-start: "scriptversion=" # time-stamp-format: "%:y-%02m-%02d.%02H" -# time-stamp-time-zone: "UTC0" +# time-stamp-time-zone: "UTC" # time-stamp-end: "; # UTC" # End: diff -ur fdupes-2.1.2/dir.c fdupes-2.2.1/dir.c --- fdupes-2.1.2/dir.c 2020-08-12 21:09:35 +++ fdupes-2.2.1/dir.c 2022-09-04 05:59:05 @@ -1,4 +1,4 @@ -/* Copyright (c) 2018 Adrian Lopez +/* Copyright (c) 2018-2022 Adrian Lopez This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff -ur fdupes-2.1.2/dir.h fdupes-2.2.1/dir.h --- fdupes-2.1.2/dir.h 2020-08-12 21:09:35 +++ fdupes-2.2.1/dir.h 2022-09-04 05:59:05 @@ -1,4 +1,4 @@ -/* Copyright (c) 2018 Adrian Lopez +/* Copyright (c) 2018-2022 Adrian Lopez This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff -ur fdupes-2.1.2/errormsg.c fdupes-2.2.1/errormsg.c --- fdupes-2.1.2/errormsg.c 2020-08-12 21:09:35 +++ fdupes-2.2.1/errormsg.c 2022-09-04 05:59:05 @@ -1,4 +1,4 @@ -/* Copyright (c) 2018 Adrian Lopez +/* Copyright (c) 2018-2022 Adrian Lopez This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff -ur fdupes-2.1.2/errormsg.h fdupes-2.2.1/errormsg.h --- fdupes-2.1.2/errormsg.h 2020-08-12 21:09:35 +++ fdupes-2.2.1/errormsg.h 2022-09-04 05:59:05 @@ -1,4 +1,4 @@ -/* Copyright (c) 2018 Adrian Lopez +/* Copyright (c) 2018-2022 Adrian Lopez This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff -ur fdupes-2.1.2/fdupes.1 fdupes-2.2.1/fdupes.1 --- fdupes-2.1.2/fdupes.1 2020-08-12 21:09:35 +++ fdupes-2.2.1/fdupes.1 2022-09-09 09:52:05 @@ -34,10 +34,10 @@ treated as non-duplicates; this option will change this behavior .TP .B -G --minsize\fR=\fISIZE\fR -consider only files greater than or equal to SIZE +consider only files greater than or equal to SIZE in bytes .TP .B -L --maxsize=\fR=\fISIZE\fR -consider only files less than or equal to SIZE +consider only files less than or equal to SIZE in bytes .TP .B -n --noempty exclude zero-length files from consideration @@ -67,6 +67,10 @@ prompt user for files to preserve, deleting all others (see .B CAVEATS below) +.TP +.B -D --deferconfirmation +in interactive mode, defer byte-for-byte confirmation of +duplicates until just before file deletion .TP .B -P --plain with --delete, use line-based prompt (as with older versions of diff -ur fdupes-2.1.2/fdupes.c fdupes-2.2.1/fdupes.c --- fdupes-2.1.2/fdupes.c 2020-08-12 21:09:35 +++ fdupes-2.2.1/fdupes.c 2022-09-09 09:52:05 @@ -1,4 +1,4 @@ -/* FDUPES Copyright (c) 1999-2018 Adrian Lopez +/* FDUPES Copyright (c) 1999-2022 Adrian Lopez Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files @@ -44,10 +44,12 @@ #include "ncurses-interface.h" #endif #include "fdupes.h" +#include "confirmmatch.h" #include "errormsg.h" #include "log.h" #include "sigint.h" #include "flags.h" +#include "removeifnotchanged.h" long long minsize = -1; long long maxsize = -1; @@ -62,32 +64,8 @@ ordertype_t ordertype = ORDER_MTIME; -#define CHUNK_SIZE 8192 - -#define INPUT_SIZE 256 - -#define PARTIAL_MD5_SIZE 4096 - #define MD5_DIGEST_LENGTH 16 -/* - -TODO: Partial sums (for working with very large files). - -typedef struct _signature -{ - md5_state_t state; - md5_byte_t digest[16]; -} signature_t; - -typedef struct _signatures -{ - int num_signatures; - signature_t *signatures; -} signatures_t; - -*/ - typedef struct _filetree { file_t *file; struct _filetree *left; @@ -304,7 +282,7 @@ } /* ignore logfile */ - if (info.st_dev == logfile_status->st_dev && info.st_ino == logfile_status->st_ino) + if (logfile_status != 0 && info.st_dev == logfile_status->st_dev && info.st_ino == logfile_status->st_ino) { free(newfile->d_name); free(newfile); @@ -628,7 +606,6 @@ } cmpresult = md5cmp(file->crcpartial, checktree->file->crcpartial); - /*if (cmpresult != 0) errormsg(" on %s vs %s\n", file->d_name, checktree->file->d_name);*/ if (cmpresult == 0) { if (checktree->file->crcsignature == NULL) { @@ -656,11 +633,6 @@ } cmpresult = md5cmp(file->crcsignature, checktree->file->crcsignature); - /*if (cmpresult != 0) errormsg("P on %s vs %s\n", - file->d_name, checktree->file->d_name); - else errormsg("P F on %s vs %s\n", file->d_name, - checktree->file->d_name); - printf("%s matches %s\n", file->d_name, checktree->file->d_name);*/ } } @@ -684,30 +656,6 @@ } } -/* Do a bit-for-bit comparison in case two different files produce the - same signature. Unlikely, but better safe than sorry. */ - -int confirmmatch(FILE *file1, FILE *file2) -{ - unsigned char c1[CHUNK_SIZE]; - unsigned char c2[CHUNK_SIZE]; - size_t r1; - size_t r2; - - fseek(file1, 0, SEEK_SET); - fseek(file2, 0, SEEK_SET); - - do { - r1 = fread(c1, sizeof(unsigned char), sizeof(c1), file1); - r2 = fread(c2, sizeof(unsigned char), sizeof(c2), file2); - - if (r1 != r2) return 0; /* file lengths are different */ - if (memcmp (c1, c2, r1)) return 0; /* file contents are different */ - } while (r2); - - return 1; -} - void summarizematches(file_t *files) { int numsets = 0; @@ -843,6 +791,7 @@ file_t *curfile; file_t **dupelist; int *preserve; + int firstpreserved; char *preservestr; char *token; char *tstr; @@ -853,6 +802,10 @@ int i; struct log_info *loginfo; int log_error; + FILE *file1; + FILE *file2; + int ismatch; + char *errorstring; curfile = files; @@ -1022,18 +975,59 @@ log_file_remaining(loginfo, dupelist[x]->d_name); } else { - if (remove(dupelist[x]->d_name) == 0) { - printf(" [-] %s\n", dupelist[x]->d_name); + if (ISFLAG(flags, F_DEFERCONFIRMATION)) + { + firstpreserved = 0; + for (i = 1; i <= counter; ++i) + { + if (preserve[i]) + { + firstpreserved = i; + break; + } + } - if (loginfo) - log_file_deleted(loginfo, dupelist[x]->d_name); - } else { - printf(" [!] %s ", dupelist[x]->d_name); - printf("-- unable to delete file!\n"); + file1 = fopen(dupelist[x]->d_name, "rb"); + file2 = fopen(dupelist[firstpreserved]->d_name, "rb"); - if (loginfo) - log_file_remaining(loginfo, dupelist[x]->d_name); - } + if (file1 && file2) + ismatch = confirmmatch(file1, file2); + else + ismatch = 0; + + if (file2) + fclose(file2); + + if (file1) + fclose(file1); + } + else + { + ismatch = 1; + } + + if (ismatch) { + if (removeifnotchanged(dupelist[x], &errorstring) == 0) { + printf(" [-] %s\n", dupelist[x]->d_name); + + if (loginfo) + log_file_deleted(loginfo, dupelist[x]->d_name); + } + else { + printf(" [!] %s ", dupelist[x]->d_name); + printf("-- unable to delete file: %s!\n", errorstring); + + if (loginfo) + log_file_remaining(loginfo, dupelist[x]->d_name); + } + } + else { + printf(" [!] %s\n", dupelist[x]->d_name); + printf(" -- unable to confirm match; file not deleted!\n"); + + if (loginfo) + log_file_remaining(loginfo, dupelist[x]->d_name); + } } } printf("\n"); @@ -1133,11 +1127,12 @@ } } -void deletesuccessor(file_t **existing, file_t *duplicate, +void deletesuccessor(file_t **existing, file_t *duplicate, int matchconfirmed, int (*comparef)(file_t *f1, file_t *f2), struct log_info *loginfo) { file_t *to_keep; file_t *to_delete; + char *errorstring; if (comparef(duplicate, *existing) >= 0) { @@ -1162,15 +1157,26 @@ if (loginfo) log_file_remaining(loginfo, to_keep->d_name); - if (remove(to_delete->d_name) == 0) { - printf(" [-] %s\n", to_delete->d_name); + if (matchconfirmed) + { + if (removeifnotchanged(to_delete, &errorstring) == 0) { + printf(" [-] %s\n", to_delete->d_name); - if (loginfo) - log_file_deleted(loginfo, to_delete->d_name); - } else { - printf(" [!] %s ", to_delete->d_name); - printf("-- unable to delete file!\n"); + if (loginfo) + log_file_deleted(loginfo, to_delete->d_name); + } else { + printf(" [!] %s ", to_delete->d_name); + printf("-- unable to delete file: %s!\n", errorstring); + if (loginfo) + log_file_remaining(loginfo, to_delete->d_name); + } + } + else + { + printf(" [!] %s\n", to_delete->d_name); + printf(" -- unable to confirm match; file not deleted!\n"); + if (loginfo) log_file_remaining(loginfo, to_delete->d_name); } @@ -1213,6 +1219,8 @@ printf(" with -s or --symlinks, or when specifying a\n"); printf(" particular directory more than once; refer to the\n"); printf(" fdupes documentation for additional information\n"); + printf(" -D --deferconfirmation in interactive mode, defer byte-for-byte confirmation\n"); + printf(" of duplicates until just before file deletion\n"); #ifndef NO_NCURSES printf(" -P --plain with --delete, use line-based prompt (as with older\n"); printf(" versions of fdupes) instead of screen-mode interface\n"); @@ -1283,6 +1291,7 @@ { "order", 1, 0, 'o' }, { "reverse", 0, 0, 'i' }, { "log", 1, 0, 'l' }, + { "deferconfirmation", 0, 0, 'D' }, { 0, 0, 0, 0 } }; #define GETOPT getopt_long @@ -1296,7 +1305,7 @@ oldargv = cloneargs(argc, argv); - while ((opt = GETOPT(argc, argv, "frRq1StsHG:L:nAdPvhNImpo:il:" + while ((opt = GETOPT(argc, argv, "frRq1StsHG:L:nAdPvhNImpo:il:D" #ifdef HAVE_GETOPT_H , long_options, NULL #endif @@ -1393,6 +1402,9 @@ case 'l': logfile = optarg; break; + case 'D': + SETFLAG(flags, F_DEFERCONFIRMATION); + break; default: fprintf(stderr, "Try `fdupes --help' for more information.\n"); exit(1); @@ -1414,6 +1426,12 @@ exit(1); } + if (ISFLAG(flags, F_DEFERCONFIRMATION) && (!ISFLAG(flags, F_DELETEFILES) || ISFLAG(flags, F_NOPROMPT))) + { + errormsg("--deferconfirmation only works with interactive deletion modes\n"); + exit(1); + } + if (!ISFLAG(flags, F_DELETEFILES)) logfile = 0; @@ -1450,16 +1468,16 @@ /* F_RECURSE is not set for directories before --recurse: */ for (x = optind; x < firstrecurse; x++) - filecount += grokdir(argv[x], &files, &logfile_status); + filecount += grokdir(argv[x], &files, logfile ? &logfile_status : 0); /* Set F_RECURSE for directories after --recurse: */ SETFLAG(flags, F_RECURSE); for (x = firstrecurse; x < argc; x++) - filecount += grokdir(argv[x], &files, &logfile_status); + filecount += grokdir(argv[x], &files, logfile ? &logfile_status : 0); } else { for (x = optind; x < argc; x++) - filecount += grokdir(argv[x], &files, &logfile_status); + filecount += grokdir(argv[x], &files, logfile ? &logfile_status : 0); } if (!files) { @@ -1489,19 +1507,19 @@ continue; } - if (confirmmatch(file1, file2)) { - if (ISFLAG(flags, F_DELETEFILES) && ISFLAG(flags, F_IMMEDIATE)) - deletesuccessor(match, curfile, + if (ISFLAG(flags, F_DELETEFILES) && ISFLAG(flags, F_IMMEDIATE)) + { + deletesuccessor(match, curfile, confirmmatch(file1, file2), ordertype == ORDER_MTIME ? sort_pairs_by_mtime : ordertype == ORDER_CTIME ? sort_pairs_by_ctime : sort_pairs_by_filename, loginfo ); - else - registerpair(match, curfile, - ordertype == ORDER_MTIME ? sort_pairs_by_mtime : - ordertype == ORDER_CTIME ? sort_pairs_by_ctime : - sort_pairs_by_filename ); } - + else if (ISFLAG(flags, F_DEFERCONFIRMATION) || confirmmatch(file1, file2)) + registerpair(match, curfile, + ordertype == ORDER_MTIME ? sort_pairs_by_mtime : + ordertype == ORDER_CTIME ? sort_pairs_by_ctime : + sort_pairs_by_filename ); + fclose(file1); fclose(file2); } diff -ur fdupes-2.1.2/fdupes.h fdupes-2.2.1/fdupes.h --- fdupes-2.1.2/fdupes.h 2020-08-12 21:09:35 +++ fdupes-2.2.1/fdupes.h 2022-09-09 09:51:58 @@ -1,4 +1,4 @@ -/* FDUPES Copyright (c) 2018 Adrian Lopez +/* FDUPES Copyright (c) 2018-2022 Adrian Lopez Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files Only in fdupes-2.2.1: fileaction.c Only in fdupes-2.2.1: fileaction.h diff -ur fdupes-2.1.2/filegroup.h fdupes-2.2.1/filegroup.h --- fdupes-2.1.2/filegroup.h 2020-08-12 21:09:35 +++ fdupes-2.2.1/filegroup.h 2022-09-04 05:59:05 @@ -1,4 +1,4 @@ -/* FDUPES Copyright (c) 2018 Adrian Lopez +/* FDUPES Copyright (c) 2018-2022 Adrian Lopez Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files diff -ur fdupes-2.1.2/flags.h fdupes-2.2.1/flags.h --- fdupes-2.1.2/flags.h 2020-08-12 21:09:35 +++ fdupes-2.2.1/flags.h 2022-09-09 09:52:05 @@ -22,7 +22,8 @@ #define F_IMMEDIATE 0x8000 #define F_PLAINPROMPT 0x10000 #define F_SHOWTIME 0x20000 +#define F_DEFERCONFIRMATION 0x40000 extern unsigned long flags; -#endif \ No newline at end of file +#endif diff -ur fdupes-2.1.2/fmatch.c fdupes-2.2.1/fmatch.c --- fdupes-2.1.2/fmatch.c 2020-08-12 21:09:35 +++ fdupes-2.2.1/fmatch.c 2022-09-04 05:59:05 @@ -1,4 +1,4 @@ -/* Copyright (c) 2018 Adrian Lopez +/* Copyright (c) 2018-2022 Adrian Lopez This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff -ur fdupes-2.1.2/fmatch.h fdupes-2.2.1/fmatch.h --- fdupes-2.1.2/fmatch.h 2020-08-12 21:09:35 +++ fdupes-2.2.1/fmatch.h 2022-09-04 05:59:05 @@ -1,4 +1,4 @@ -/* Copyright (c) 2018 Adrian Lopez +/* Copyright (c) 2018-2022 Adrian Lopez This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff -ur fdupes-2.1.2/install-sh fdupes-2.2.1/install-sh --- fdupes-2.1.2/install-sh 2020-08-12 21:10:06 +++ fdupes-2.2.1/install-sh 2022-01-19 21:07:47 @@ -1,7 +1,7 @@ #!/bin/sh # install - install a program, script, or datafile -scriptversion=2014-09-12.12; # UTC +scriptversion=2011-11-20.07; # UTC # This originates from X11R5 (mit/util/scripts/install.sh), which was # later released in X11R6 (xc/config/util/install.sh) with the @@ -41,15 +41,19 @@ # This script is compatible with the BSD install script, but was written # from scratch. -tab=' ' nl=' ' -IFS=" $tab$nl" +IFS=" "" $nl" -# Set DOITPROG to "echo" to test this script. +# set DOITPROG to echo to test this script +# Don't use :- since 4.3BSD and earlier shells don't like it. doit=${DOITPROG-} -doit_exec=${doit:-exec} +if test -z "$doit"; then + doit_exec=exec +else + doit_exec=$doit +fi # Put in absolute file names if you don't have them in your path; # or use environment vars. @@ -64,6 +68,17 @@ rmprog=${RMPROG-rm} stripprog=${STRIPPROG-strip} +posix_glob='?' +initialize_posix_glob=' + test "$posix_glob" != "?" || { + if (set -f) 2>/dev/null; then + posix_glob= + else + posix_glob=: + fi + } +' + posix_mkdir= # Desired mode of installed file. @@ -82,7 +97,7 @@ dst_arg= copy_on_change=false -is_target_a_directory=possibly +no_target_directory= usage="\ Usage: $0 [OPTION]... [-T] SRCFILE DSTFILE @@ -122,57 +137,46 @@ -d) dir_arg=true;; -g) chgrpcmd="$chgrpprog $2" - shift;; + shift;; --help) echo "$usage"; exit $?;; -m) mode=$2 - case $mode in - *' '* | *"$tab"* | *"$nl"* | *'*'* | *'?'* | *'['*) - echo "$0: invalid mode: $mode" >&2 - exit 1;; - esac - shift;; + case $mode in + *' '* | *' '* | *' +'* | *'*'* | *'?'* | *'['*) + echo "$0: invalid mode: $mode" >&2 + exit 1;; + esac + shift;; -o) chowncmd="$chownprog $2" - shift;; + shift;; -s) stripcmd=$stripprog;; - -t) - is_target_a_directory=always - dst_arg=$2 - # Protect names problematic for 'test' and other utilities. - case $dst_arg in - -* | [=\(\)!]) dst_arg=./$dst_arg;; - esac - shift;; + -t) dst_arg=$2 + # Protect names problematic for 'test' and other utilities. + case $dst_arg in + -* | [=\(\)!]) dst_arg=./$dst_arg;; + esac + shift;; - -T) is_target_a_directory=never;; + -T) no_target_directory=true;; --version) echo "$0 $scriptversion"; exit $?;; - --) shift - break;; + --) shift + break;; - -*) echo "$0: invalid option: $1" >&2 - exit 1;; + -*) echo "$0: invalid option: $1" >&2 + exit 1;; *) break;; esac shift done -# We allow the use of options -d and -T together, by making -d -# take the precedence; this is for compatibility with GNU install. - -if test -n "$dir_arg"; then - if test -n "$dst_arg"; then - echo "$0: target directory not allowed when installing a directory." >&2 - exit 1 - fi -fi - if test $# -ne 0 && test -z "$dir_arg$dst_arg"; then # When -d is used, all remaining arguments are directories to create. # When -t is used, the destination is already specified. @@ -204,15 +208,6 @@ fi if test -z "$dir_arg"; then - if test $# -gt 1 || test "$is_target_a_directory" = always; then - if test ! -d "$dst_arg"; then - echo "$0: $dst_arg: Is not a directory." >&2 - exit 1 - fi - fi -fi - -if test -z "$dir_arg"; then do_exit='(exit $ret); exit $ret' trap "ret=129; $do_exit" 1 trap "ret=130; $do_exit" 2 @@ -228,16 +223,16 @@ *[0-7]) if test -z "$stripcmd"; then - u_plus_rw= + u_plus_rw= else - u_plus_rw='% 200' + u_plus_rw='% 200' fi cp_umask=`expr '(' 777 - $mode % 1000 ')' $u_plus_rw`;; *) if test -z "$stripcmd"; then - u_plus_rw= + u_plus_rw= else - u_plus_rw=,u+rw + u_plus_rw=,u+rw fi cp_umask=$mode$u_plus_rw;; esac @@ -274,15 +269,41 @@ # If destination is a directory, append the input filename; won't work # if double slashes aren't ignored. if test -d "$dst"; then - if test "$is_target_a_directory" = never; then - echo "$0: $dst_arg: Is a directory" >&2 - exit 1 + if test -n "$no_target_directory"; then + echo "$0: $dst_arg: Is a directory" >&2 + exit 1 fi dstdir=$dst dst=$dstdir/`basename "$src"` dstdir_status=0 else - dstdir=`dirname "$dst"` + # Prefer dirname, but fall back on a substitute if dirname fails. + dstdir=` + (dirname "$dst") 2>/dev/null || + expr X"$dst" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$dst" : 'X\(//\)[^/]' \| \ + X"$dst" : 'X\(//\)$' \| \ + X"$dst" : 'X\(/\)' \| . 2>/dev/null || + echo X"$dst" | + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ + s//\1/ + q + } + /^X\(\/\/\)[^/].*/{ + s//\1/ + q + } + /^X\(\/\/\)$/{ + s//\1/ + q + } + /^X\(\/\).*/{ + s//\1/ + q + } + s/.*/./; q' + ` + test -d "$dstdir" dstdir_status=$? fi @@ -293,81 +314,74 @@ if test $dstdir_status != 0; then case $posix_mkdir in '') - # Create intermediate dirs using mode 755 as modified by the umask. - # This is like FreeBSD 'install' as of 1997-10-28. - umask=`umask` - case $stripcmd.$umask in - # Optimize common cases. - *[2367][2367]) mkdir_umask=$umask;; - .*0[02][02] | .[02][02] | .[02]) mkdir_umask=22;; + # Create intermediate dirs using mode 755 as modified by the umask. + # This is like FreeBSD 'install' as of 1997-10-28. + umask=`umask` + case $stripcmd.$umask in + # Optimize common cases. + *[2367][2367]) mkdir_umask=$umask;; + .*0[02][02] | .[02][02] | .[02]) mkdir_umask=22;; - *[0-7]) - mkdir_umask=`expr $umask + 22 \ - - $umask % 100 % 40 + $umask % 20 \ - - $umask % 10 % 4 + $umask % 2 - `;; - *) mkdir_umask=$umask,go-w;; - esac + *[0-7]) + mkdir_umask=`expr $umask + 22 \ + - $umask % 100 % 40 + $umask % 20 \ + - $umask % 10 % 4 + $umask % 2 + `;; + *) mkdir_umask=$umask,go-w;; + esac - # With -d, create the new directory with the user-specified mode. - # Otherwise, rely on $mkdir_umask. - if test -n "$dir_arg"; then - mkdir_mode=-m$mode - else - mkdir_mode= - fi + # With -d, create the new directory with the user-specified mode. + # Otherwise, rely on $mkdir_umask. + if test -n "$dir_arg"; then + mkdir_mode=-m$mode + else + mkdir_mode= + fi - posix_mkdir=false - case $umask in - *[123567][0-7][0-7]) - # POSIX mkdir -p sets u+wx bits regardless of umask, which - # is incompatible with FreeBSD 'install' when (umask & 300) != 0. - ;; - *) - # $RANDOM is not portable (e.g. dash); use it when possible to - # lower collision chance - tmpdir=${TMPDIR-/tmp}/ins$RANDOM-$$ - trap 'ret=$?; rmdir "$tmpdir/a/b" "$tmpdir/a" "$tmpdir" 2>/dev/null; exit $ret' 0 + posix_mkdir=false + case $umask in + *[123567][0-7][0-7]) + # POSIX mkdir -p sets u+wx bits regardless of umask, which + # is incompatible with FreeBSD 'install' when (umask & 300) != 0. + ;; + *) + tmpdir=${TMPDIR-/tmp}/ins$RANDOM-$$ + trap 'ret=$?; rmdir "$tmpdir/d" "$tmpdir" 2>/dev/null; exit $ret' 0 - # As "mkdir -p" follows symlinks and we work in /tmp possibly; so - # create the $tmpdir first (and fail if unsuccessful) to make sure - # that nobody tries to guess the $tmpdir name. - if (umask $mkdir_umask && - $mkdirprog $mkdir_mode "$tmpdir" && - exec $mkdirprog $mkdir_mode -p -- "$tmpdir/a/b") >/dev/null 2>&1 - then - if test -z "$dir_arg" || { - # Check for POSIX incompatibilities with -m. - # HP-UX 11.23 and IRIX 6.5 mkdir -m -p sets group- or - # other-writable bit of parent directory when it shouldn't. - # FreeBSD 6.1 mkdir -m -p sets mode of existing directory. - test_tmpdir="$tmpdir/a" - ls_ld_tmpdir=`ls -ld "$test_tmpdir"` - case $ls_ld_tmpdir in - d????-?r-*) different_mode=700;; - d????-?--*) different_mode=755;; - *) false;; - esac && - $mkdirprog -m$different_mode -p -- "$test_tmpdir" && { - ls_ld_tmpdir_1=`ls -ld "$test_tmpdir"` - test "$ls_ld_tmpdir" = "$ls_ld_tmpdir_1" - } - } - then posix_mkdir=: - fi - rmdir "$tmpdir/a/b" "$tmpdir/a" "$tmpdir" - else - # Remove any dirs left behind by ancient mkdir implementations. - rmdir ./$mkdir_mode ./-p ./-- "$tmpdir" 2>/dev/null - fi - trap '' 0;; - esac;; + if (umask $mkdir_umask && + exec $mkdirprog $mkdir_mode -p -- "$tmpdir/d") >/dev/null 2>&1 + then + if test -z "$dir_arg" || { + # Check for POSIX incompatibilities with -m. + # HP-UX 11.23 and IRIX 6.5 mkdir -m -p sets group- or + # other-writable bit of parent directory when it shouldn't. + # FreeBSD 6.1 mkdir -m -p sets mode of existing directory. + ls_ld_tmpdir=`ls -ld "$tmpdir"` + case $ls_ld_tmpdir in + d????-?r-*) different_mode=700;; + d????-?--*) different_mode=755;; + *) false;; + esac && + $mkdirprog -m$different_mode -p -- "$tmpdir" && { + ls_ld_tmpdir_1=`ls -ld "$tmpdir"` + test "$ls_ld_tmpdir" = "$ls_ld_tmpdir_1" + } + } + then posix_mkdir=: + fi + rmdir "$tmpdir/d" "$tmpdir" + else + # Remove any dirs left behind by ancient mkdir implementations. + rmdir ./$mkdir_mode ./-p ./-- 2>/dev/null + fi + trap '' 0;; + esac;; esac if $posix_mkdir && ( - umask $mkdir_umask && - $doit_exec $mkdirprog $mkdir_mode -p -- "$dstdir" + umask $mkdir_umask && + $doit_exec $mkdirprog $mkdir_mode -p -- "$dstdir" ) then : else @@ -377,51 +391,53 @@ # directory the slow way, step by step, checking for races as we go. case $dstdir in - /*) prefix='/';; - [-=\(\)!]*) prefix='./';; - *) prefix='';; + /*) prefix='/';; + [-=\(\)!]*) prefix='./';; + *) prefix='';; esac + eval "$initialize_posix_glob" + oIFS=$IFS IFS=/ - set -f + $posix_glob set -f set fnord $dstdir shift - set +f + $posix_glob set +f IFS=$oIFS prefixes= for d do - test X"$d" = X && continue + test X"$d" = X && continue - prefix=$prefix$d - if test -d "$prefix"; then - prefixes= - else - if $posix_mkdir; then - (umask=$mkdir_umask && - $doit_exec $mkdirprog $mkdir_mode -p -- "$dstdir") && break - # Don't fail if two instances are running concurrently. - test -d "$prefix" || exit 1 - else - case $prefix in - *\'*) qprefix=`echo "$prefix" | sed "s/'/'\\\\\\\\''/g"`;; - *) qprefix=$prefix;; - esac - prefixes="$prefixes '$qprefix'" - fi - fi - prefix=$prefix/ + prefix=$prefix$d + if test -d "$prefix"; then + prefixes= + else + if $posix_mkdir; then + (umask=$mkdir_umask && + $doit_exec $mkdirprog $mkdir_mode -p -- "$dstdir") && break + # Don't fail if two instances are running concurrently. + test -d "$prefix" || exit 1 + else + case $prefix in + *\'*) qprefix=`echo "$prefix" | sed "s/'/'\\\\\\\\''/g"`;; + *) qprefix=$prefix;; + esac + prefixes="$prefixes '$qprefix'" + fi + fi + prefix=$prefix/ done if test -n "$prefixes"; then - # Don't fail if two instances are running concurrently. - (umask $mkdir_umask && - eval "\$doit_exec \$mkdirprog $prefixes") || - test -d "$dstdir" || exit 1 - obsolete_mkdir_used=true + # Don't fail if two instances are running concurrently. + (umask $mkdir_umask && + eval "\$doit_exec \$mkdirprog $prefixes") || + test -d "$dstdir" || exit 1 + obsolete_mkdir_used=true fi fi fi @@ -456,12 +472,15 @@ # If -C, don't bother to copy if it wouldn't change the file. if $copy_on_change && - old=`LC_ALL=C ls -dlL "$dst" 2>/dev/null` && - new=`LC_ALL=C ls -dlL "$dsttmp" 2>/dev/null` && - set -f && + old=`LC_ALL=C ls -dlL "$dst" 2>/dev/null` && + new=`LC_ALL=C ls -dlL "$dsttmp" 2>/dev/null` && + + eval "$initialize_posix_glob" && + $posix_glob set -f && set X $old && old=:$2:$4:$5:$6 && set X $new && new=:$2:$4:$5:$6 && - set +f && + $posix_glob set +f && + test "$old" = "$new" && $cmpprog "$dst" "$dsttmp" >/dev/null 2>&1 then @@ -474,24 +493,24 @@ # to itself, or perhaps because mv is so ancient that it does not # support -f. { - # Now remove or move aside any old file at destination location. - # We try this two ways since rm can't unlink itself on some - # systems and the destination file might be busy for other - # reasons. In this case, the final cleanup might fail but the new - # file should still install successfully. - { - test ! -f "$dst" || - $doit $rmcmd -f "$dst" 2>/dev/null || - { $doit $mvcmd -f "$dst" "$rmtmp" 2>/dev/null && - { $doit $rmcmd -f "$rmtmp" 2>/dev/null; :; } - } || - { echo "$0: cannot unlink or rename $dst" >&2 - (exit 1); exit 1 - } - } && + # Now remove or move aside any old file at destination location. + # We try this two ways since rm can't unlink itself on some + # systems and the destination file might be busy for other + # reasons. In this case, the final cleanup might fail but the new + # file should still install successfully. + { + test ! -f "$dst" || + $doit $rmcmd -f "$dst" 2>/dev/null || + { $doit $mvcmd -f "$dst" "$rmtmp" 2>/dev/null && + { $doit $rmcmd -f "$rmtmp" 2>/dev/null; :; } + } || + { echo "$0: cannot unlink or rename $dst" >&2 + (exit 1); exit 1 + } + } && - # Now rename the file to the real destination. - $doit $mvcmd "$dsttmp" "$dst" + # Now rename the file to the real destination. + $doit $mvcmd "$dsttmp" "$dst" } fi || exit 1 diff -ur fdupes-2.1.2/log.c fdupes-2.2.1/log.c --- fdupes-2.1.2/log.c 2020-08-12 21:09:35 +++ fdupes-2.2.1/log.c 2022-09-04 05:59:05 @@ -1,4 +1,4 @@ -/* Copyright (c) 2018 Adrian Lopez +/* Copyright (c) 2018-2022 Adrian Lopez This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff -ur fdupes-2.1.2/log.h fdupes-2.2.1/log.h --- fdupes-2.1.2/log.h 2020-08-12 21:09:35 +++ fdupes-2.2.1/log.h 2022-09-04 05:59:05 @@ -1,4 +1,4 @@ -/* Copyright (c) 2018 Adrian Lopez +/* Copyright (c) 2018-2022 Adrian Lopez This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff -ur fdupes-2.1.2/mbstowcs_escape_invalid.c fdupes-2.2.1/mbstowcs_escape_invalid.c --- fdupes-2.1.2/mbstowcs_escape_invalid.c 2020-08-12 21:09:35 +++ fdupes-2.2.1/mbstowcs_escape_invalid.c 2022-09-04 05:59:05 @@ -1,4 +1,4 @@ -/* Copyright (c) 2019 Adrian Lopez +/* Copyright (c) 2019-2022 Adrian Lopez This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff -ur fdupes-2.1.2/mbstowcs_escape_invalid.h fdupes-2.2.1/mbstowcs_escape_invalid.h --- fdupes-2.1.2/mbstowcs_escape_invalid.h 2020-08-12 21:09:35 +++ fdupes-2.2.1/mbstowcs_escape_invalid.h 2022-09-04 05:59:05 @@ -1,4 +1,4 @@ -/* Copyright (c) 2019 Adrian Lopez +/* Copyright (c) 2019-2022 Adrian Lopez This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff -ur fdupes-2.1.2/ncurses-commands.c fdupes-2.2.1/ncurses-commands.c --- fdupes-2.1.2/ncurses-commands.c 2020-08-12 21:09:35 +++ fdupes-2.2.1/ncurses-commands.c 2022-09-09 09:52:05 @@ -1,4 +1,4 @@ -/* FDUPES Copyright (c) 2018 Adrian Lopez +/* FDUPES Copyright (c) 2018-2022 Adrian Lopez Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files @@ -22,9 +22,14 @@ #include "config.h" #include "ncurses-status.h" #include "ncurses-commands.h" +#include "fileaction.h" +#include "flags.h" +#include "confirmmatch.h" +#include "errormsg.h" #include "wcs.h" #include "mbstowcs_escape_invalid.h" #include "log.h" +#include "removeifnotchanged.h" #include #include @@ -619,7 +624,7 @@ { if (groups[g].files[f].selected) { - set_file_action(&groups[g].files[f], 1, deletiontally); + set_file_action(&groups[g].files[f], FILEACTION_KEEP, deletiontally); ++keepfilecount; } } @@ -643,7 +648,7 @@ { if (groups[g].files[f].selected) { - set_file_action(&groups[g].files[f], -1, deletiontally); + set_file_action(&groups[g].files[f], FILEACTION_DELETE, deletiontally); ++deletefilecount; } } @@ -667,7 +672,7 @@ { if (groups[g].files[f].selected) { - set_file_action(&groups[g].files[f], 0, deletiontally); + set_file_action(&groups[g].files[f], FILEACTION_UNRESOLVED, deletiontally); ++resetfilecount; } } @@ -681,12 +686,13 @@ int filerowcount(file_t *file, const int columns, int group_file_count); /* delete files tagged for deletion, delist sets with no untagged files */ -int cmd_prune(struct filegroup *groups, int groupcount, wchar_t *commandarguments, size_t *deletiontally, int *totalgroups, int *cursorgroup, int *cursorfile, int *topline, char *logfile, WINDOW *filewin, struct status_text *status) +int cmd_prune(struct filegroup *groups, int groupcount, wchar_t *commandarguments, size_t *deletiontally, int *totalgroups, int *cursorgroup, int *cursorfile, int *topline, char *logfile, WINDOW *filewin, WINDOW *statuswin, struct status_text *status) { int deletecount; int preservecount; int unresolvedcount; int totaldeleted = 0; + int totalfailed = 0; double deletedbytes = 0; struct log_info *loginfo; int g; @@ -695,6 +701,11 @@ int adjusttopline; int toplineoffset; int groupfirstline; + FILE *file1; + FILE *file2; + int ismatch; + wchar_t *statuscopy; + struct groupfile *firstnotdeleted; if (logfile != 0) loginfo = log_open(logfile, 0); @@ -706,19 +717,31 @@ preservecount = 0; deletecount = 0; unresolvedcount = 0; + firstnotdeleted = 0; for (f = 0; f < groups[g].filecount; ++f) { switch (groups[g].files[f].action) { - case -1: + case FILEACTION_DELETE: ++deletecount; break; - case 0: + + case FILEACTION_UNRESOLVED: + case FILEACTION_ERROR: ++unresolvedcount; + + if (firstnotdeleted == 0) + firstnotdeleted = &groups[g].files[f]; + break; - case 1: + + case FILEACTION_KEEP: ++preservecount; + + if (firstnotdeleted == 0) + firstnotdeleted = &groups[g].files[f]; + break; } } @@ -731,18 +754,49 @@ { for (f = 0; f < groups[g].filecount; ++f) { - if (groups[g].files[f].action == -1) + if (groups[g].files[f].action == FILEACTION_DELETE) { - if (remove(groups[g].files[f].file->d_name) == 0) + if (ISFLAG(flags, F_DEFERCONFIRMATION)) { - set_file_action(&groups[g].files[f], -2, deletiontally); + format_status_left(status, L"Confirming duplicates..."); + print_status(statuswin, status); + wrefresh(statuswin); + file1 = fopen(groups[g].files[f].file->d_name, "rb"); + file2 = fopen(firstnotdeleted->file->d_name, "rb"); + + if (file1 && file2) + ismatch = confirmmatch(file1, file2); + else + ismatch = 0; + + if (file2) + fclose(file2); + + if (file1) + fclose(file1); + } + else + { + ismatch = 1; + } + + if (ismatch && removeifnotchanged(groups[g].files[f].file, 0) == 0) + { + set_file_action(&groups[g].files[f], FILEACTION_DELIST, deletiontally); + deletedbytes += groups[g].files[f].file->size; ++totaldeleted; if (loginfo) log_file_deleted(loginfo, groups[g].files[f].file->d_name); } + else + { + set_file_action(&groups[g].files[f], FILEACTION_ERROR, deletiontally); + unresolvedcount++; + totalfailed++; + } } } @@ -750,7 +804,8 @@ { for (f = 0; f < groups[g].filecount; ++f) { - if (groups[g].files[f].action >= 0) + if (groups[g].files[f].action != FILEACTION_DELETE && + groups[g].files[f].action != FILEACTION_DELIST) log_file_remaining(loginfo, groups[g].files[f].file->d_name); } } @@ -765,8 +820,8 @@ if (unresolvedcount == 0) { for (f = 0; f < groups[g].filecount; ++f) - if (groups[g].files[f].action == 1) - set_file_action(&groups[g].files[f], -2, deletiontally); + if (groups[g].files[f].action == FILEACTION_KEEP) + set_file_action(&groups[g].files[f], FILEACTION_DELIST, deletiontally); preservecount = 0; } @@ -774,14 +829,14 @@ else if (unresolvedcount == 1 && preservecount + deletecount == 0) { for (f = 0; f < groups[g].filecount; ++f) - if (groups[g].files[f].action == 0) - set_file_action(&groups[g].files[f], -2, deletiontally); + if (groups[g].files[f].action == FILEACTION_UNRESOLVED || groups[g].files[f].action == FILEACTION_ERROR) + set_file_action(&groups[g].files[f], FILEACTION_DELIST, deletiontally); } /* delist any files marked for delisting */ to = 0; for (f = 0; f < groups[g].filecount; ++f) - if (groups[g].files[f].action != -2) + if (groups[g].files[f].action != FILEACTION_DELIST) groups[g].files[to++] = groups[g].files[f]; groups[g].filecount = to; @@ -795,13 +850,30 @@ log_close(loginfo); if (deletedbytes < 1000.0) - format_status_left(status, L"Deleted %ld files (occupying %.0f bytes).", totaldeleted, deletedbytes); + format_status_left(status, L"Deleted %ld files (occupying %.0f bytes)%c", totaldeleted, deletedbytes, totalfailed ? ';' : '.'); else if (deletedbytes <= (1000.0 * 1000.0)) - format_status_left(status, L"Deleted %ld files (occupying %.1f KB).", totaldeleted, deletedbytes / 1000.0); + format_status_left(status, L"Deleted %ld files (occupying %.1f KB)%c", totaldeleted, deletedbytes / 1000.0, totalfailed ? ';' : '.'); else if (deletedbytes <= (1000.0 * 1000.0 * 1000.0)) - format_status_left(status, L"Deleted %ld files (occupying %.1f MB).", totaldeleted, deletedbytes / (1000.0 * 1000.0)); + format_status_left(status, L"Deleted %ld files (occupying %.1f MB)%c", totaldeleted, deletedbytes / (1000.0 * 1000.0), totalfailed ? ';' : '.'); else - format_status_left(status, L"Deleted %ld files (occupying %.1f GB).", totaldeleted, deletedbytes / (1000.0 * 1000.0 * 1000.0)); + format_status_left(status, L"Deleted %ld files (occupying %.1f GB)%c", totaldeleted, deletedbytes / (1000.0 * 1000.0 * 1000.0), totalfailed ? ';' : '.'); + + if (totalfailed > 0) + { + statuscopy = malloc(sizeof(wchar_t) * (wcslen(status->left) + 1)); + if (!statuscopy) + { + endwin(); + errormsg("out of memory\n"); + exit(1); + } + + wcsncpy(statuscopy, status->left, wcslen(status->left) + 1); + + format_status_left(status, L"%S %d failed.", statuscopy, totalfailed); + + free(statuscopy); + } /* delist empty groups */ to = 0; diff -ur fdupes-2.1.2/ncurses-commands.h fdupes-2.2.1/ncurses-commands.h --- fdupes-2.1.2/ncurses-commands.h 2020-08-12 21:09:35 +++ fdupes-2.2.1/ncurses-commands.h 2022-09-04 05:59:05 @@ -1,4 +1,4 @@ -/* FDUPES Copyright (c) 2018 Adrian Lopez +/* FDUPES Copyright (c) 2018-2022 Adrian Lopez Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files @@ -71,6 +71,6 @@ int cmd_keep_selected(struct filegroup *groups, int groupcount, wchar_t *commandarguments, size_t *deletiontally, struct status_text *status); int cmd_delete_selected(struct filegroup *groups, int groupcount, wchar_t *commandarguments, size_t *deletiontally, struct status_text *status); int cmd_reset_selected(struct filegroup *groups, int groupcount, wchar_t *commandarguments, size_t *deletiontally, struct status_text *status); -int cmd_prune(struct filegroup *groups, int groupcount, wchar_t *commandarguments, size_t *deletiontally, int *totalgroups, int *cursorgroup, int *cursorfile, int *topline, char *logfile, WINDOW *filewin, struct status_text *status);; +int cmd_prune(struct filegroup *groups, int groupcount, wchar_t *commandarguments, size_t *deletiontally, int *totalgroups, int *cursorgroup, int *cursorfile, int *topline, char *logfile, WINDOW *filewin, WINDOW *statuswin, struct status_text *status);; #endif \ No newline at end of file diff -ur fdupes-2.1.2/ncurses-getcommand.c fdupes-2.2.1/ncurses-getcommand.c --- fdupes-2.1.2/ncurses-getcommand.c 2020-08-12 21:09:35 +++ fdupes-2.2.1/ncurses-getcommand.c 2022-09-04 05:59:05 @@ -1,4 +1,4 @@ -/* FDUPES Copyright (c) 2018 Adrian Lopez +/* FDUPES Copyright (c) 2018-2022 Adrian Lopez Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files diff -ur fdupes-2.1.2/ncurses-getcommand.h fdupes-2.2.1/ncurses-getcommand.h --- fdupes-2.1.2/ncurses-getcommand.h 2020-08-12 21:09:35 +++ fdupes-2.2.1/ncurses-getcommand.h 2022-09-04 05:59:05 @@ -1,4 +1,4 @@ -/* FDUPES Copyright (c) 2018 Adrian Lopez +/* FDUPES Copyright (c) 2018-2022 Adrian Lopez Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files diff -ur fdupes-2.1.2/ncurses-interface.c fdupes-2.2.1/ncurses-interface.c --- fdupes-2.1.2/ncurses-interface.c 2020-08-12 21:09:35 +++ fdupes-2.2.1/ncurses-interface.c 2022-09-04 05:59:05 @@ -1,4 +1,4 @@ -/* FDUPES Copyright (c) 2018 Adrian Lopez +/* FDUPES Copyright (c) 2018-2022 Adrian Lopez Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files @@ -34,6 +34,7 @@ #include "ncurses-prompt.h" #include "ncurses-status.h" #include "ncurses-print.h" +#include "fileaction.h" #include "mbstowcs_escape_invalid.h" #include "positive_wcwidth.h" #include "commandidentifier.h" @@ -182,13 +183,13 @@ { switch (file->action) { - case -1: - if (new_action != -1) + case FILEACTION_DELETE: + if (new_action != FILEACTION_DELETE) --*deletion_tally; break; default: - if (new_action == -1) + if (new_action == FILEACTION_DELETE) ++*deletion_tally; break; } @@ -539,7 +540,7 @@ do { groups[totalgroups].files[groupfilecount].file = dupefile; - groups[totalgroups].files[groupfilecount].action = 0; + groups[totalgroups].files[groupfilecount].action = FILEACTION_UNRESOLVED; groups[totalgroups].files[groupfilecount].selected = 0; ++groupfilecount; @@ -647,7 +648,7 @@ { print_spaces(filewin, index_width); - wprintw(filewin, " [%c] ", groups[groupindex].files[f].action > 0 ? '+' : groups[groupindex].files[f].action < 0 ? '-' : ' '); + wprintw(filewin, " [%c] ", getfileactionchar(groups[groupindex].files[f].action)); if (ISFLAG(flags, F_SHOWTIME)) wprintw(filewin, "[%s] ", fmttime(groups[groupindex].files[f].file->mtime)); @@ -673,7 +674,7 @@ if (cursorgroup == groupindex && cursorfile == f) wattron(filewin, A_REVERSE); - wprintw(filewin, "[%c]", groups[groupindex].files[f].action > 0 ? '+' : groups[groupindex].files[f].action < 0 ? '-' : ' '); + wprintw(filewin, "[%c]", getfileactionchar(groups[groupindex].files[f].action)); if (cursorgroup == groupindex && cursorfile == f) wattroff(filewin, A_REVERSE); wprintw(filewin, " "); @@ -829,7 +830,7 @@ case COMMAND_RESET_GROUP: for (x = 0; x < groups[cursorgroup].filecount; ++x) - set_file_action(&groups[cursorgroup].files[x], 0, &globaldeletiontally); + set_file_action(&groups[cursorgroup].files[x], FILEACTION_UNRESOLVED, &globaldeletiontally); format_status_left(status, L"Reset all files in current group."); @@ -838,7 +839,7 @@ case COMMAND_PRESERVE_ALL: /* mark all files for preservation */ for (x = 0; x < groups[cursorgroup].filecount; ++x) - set_file_action(&groups[cursorgroup].files[x], 1, &globaldeletiontally); + set_file_action(&groups[cursorgroup].files[x], FILEACTION_KEEP, &globaldeletiontally); format_status_left(status, L"%d files marked for preservation", groups[cursorgroup].filecount); @@ -881,7 +882,7 @@ break; case COMMAND_PRUNE: - cmd_prune(groups, totalgroups, commandarguments, &globaldeletiontally, &totalgroups, &cursorgroup, &cursorfile, &topline, logfile, filewin, status); + cmd_prune(groups, totalgroups, commandarguments, &globaldeletiontally, &totalgroups, &cursorgroup, &cursorfile, &topline, logfile, filewin, statuswin, status); break; case COMMAND_EXIT: /* exit program */ @@ -1016,7 +1017,7 @@ if (wcstolcheck != token && *wcstolcheck == '\0') { if (number > 0 && number <= groups[cursorgroup].filecount) - set_file_action(&groups[cursorgroup].files[number - 1], 1, &globaldeletiontally); + set_file_action(&groups[cursorgroup].files[number - 1], FILEACTION_KEEP, &globaldeletiontally); } token = wcstok(NULL, L",", &wcsptr); @@ -1028,9 +1029,9 @@ for (x = 0; x < groups[cursorgroup].filecount; ++x) { - if (groups[cursorgroup].files[x].action == 1) + if (groups[cursorgroup].files[x].action == FILEACTION_KEEP) ++preservecount; - if (groups[cursorgroup].files[x].action == -1) + if (groups[cursorgroup].files[x].action == FILEACTION_DELETE) ++deletecount; } @@ -1038,9 +1039,11 @@ { for (x = 0; x < groups[cursorgroup].filecount; ++x) { - if (groups[cursorgroup].files[x].action == 0) + if (groups[cursorgroup].files[x].action == FILEACTION_UNRESOLVED || + groups[cursorgroup].files[x].action == FILEACTION_ERROR + ) { - set_file_action(&groups[cursorgroup].files[x], -1, &globaldeletiontally); + set_file_action(&groups[cursorgroup].files[x], FILEACTION_DELETE, &globaldeletiontally); ++deletecount; } } @@ -1180,7 +1183,7 @@ break; case KEY_SRIGHT: - set_file_action(&groups[cursorgroup].files[cursorfile], 1, &globaldeletiontally); + set_file_action(&groups[cursorgroup].files[cursorfile], FILEACTION_KEEP, &globaldeletiontally); format_status_left(status, L"1 file marked for preservation."); @@ -1194,12 +1197,12 @@ case KEY_SLEFT: deletecount = 0; - set_file_action(&groups[cursorgroup].files[cursorfile], -1, &globaldeletiontally); + set_file_action(&groups[cursorgroup].files[cursorfile], FILEACTION_DELETE, &globaldeletiontally); format_status_left(status, L"1 file marked for deletion."); for (x = 0; x < groups[cursorgroup].filecount; ++x) - if (groups[cursorgroup].files[x].action == -1) + if (groups[cursorgroup].files[x].action == FILEACTION_DELETE) ++deletecount; if (deletecount < groups[cursorgroup].filecount) @@ -1231,7 +1234,7 @@ break; case KEY_DC: - cmd_prune(groups, totalgroups, commandarguments, &globaldeletiontally, &totalgroups, &cursorgroup, &cursorfile, &topline, logfile, filewin, status); + cmd_prune(groups, totalgroups, commandarguments, &globaldeletiontally, &totalgroups, &cursorgroup, &cursorfile, &topline, logfile, filewin, statuswin, status); break; case KEY_RESIZE: @@ -1267,10 +1270,10 @@ switch (wch) { case '?': - if (groups[cursorgroup].files[cursorfile].action == 0) + if (groups[cursorgroup].files[cursorfile].action == FILEACTION_UNRESOLVED) break; - set_file_action(&groups[cursorgroup].files[cursorfile], 0, &globaldeletiontally); + set_file_action(&groups[cursorgroup].files[cursorfile], FILEACTION_UNRESOLVED, &globaldeletiontally); if (cursorfile < groups[cursorgroup].filecount - 1) move_to_next_file(&topline, &cursorgroup, &cursorfile, groups, filewin); @@ -1285,7 +1288,7 @@ for (x = 0; x < groups[cursorgroup].filecount; ++x) { - if (groups[cursorgroup].files[x].action == 1) + if (groups[cursorgroup].files[x].action == FILEACTION_KEEP) ++preservecount; } @@ -1294,10 +1297,10 @@ for (x = 0; x < groups[cursorgroup].filecount; ++x) { - if (groups[cursorgroup].files[x].action == 0) - set_file_action(&groups[cursorgroup].files[x], -1, &globaldeletiontally); + if (groups[cursorgroup].files[x].action == FILEACTION_UNRESOLVED) + set_file_action(&groups[cursorgroup].files[x], FILEACTION_DELETE, &globaldeletiontally); - if (groups[cursorgroup].files[x].action == -1) + if (groups[cursorgroup].files[x].action == FILEACTION_DELETE) ++deletecount; } diff -ur fdupes-2.1.2/ncurses-interface.h fdupes-2.2.1/ncurses-interface.h --- fdupes-2.1.2/ncurses-interface.h 2020-08-12 21:09:35 +++ fdupes-2.2.1/ncurses-interface.h 2022-09-04 05:59:05 @@ -1,4 +1,4 @@ -/* FDUPES Copyright (c) 2018 Adrian Lopez +/* FDUPES Copyright (c) 2018-2022 Adrian Lopez Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files diff -ur fdupes-2.1.2/ncurses-print.c fdupes-2.2.1/ncurses-print.c --- fdupes-2.1.2/ncurses-print.c 2020-08-12 21:09:35 +++ fdupes-2.2.1/ncurses-print.c 2022-09-04 05:59:05 @@ -1,4 +1,4 @@ -/* FDUPES Copyright (c) 2018 Adrian Lopez +/* FDUPES Copyright (c) 2018-2022 Adrian Lopez Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files diff -ur fdupes-2.1.2/ncurses-print.h fdupes-2.2.1/ncurses-print.h --- fdupes-2.1.2/ncurses-print.h 2020-08-12 21:09:35 +++ fdupes-2.2.1/ncurses-print.h 2022-09-04 05:59:05 @@ -1,4 +1,4 @@ -/* FDUPES Copyright (c) 2018 Adrian Lopez +/* FDUPES Copyright (c) 2018-2022 Adrian Lopez Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files diff -ur fdupes-2.1.2/ncurses-prompt.c fdupes-2.2.1/ncurses-prompt.c --- fdupes-2.1.2/ncurses-prompt.c 2020-08-12 21:09:35 +++ fdupes-2.2.1/ncurses-prompt.c 2022-09-04 05:59:05 @@ -1,4 +1,4 @@ -/* FDUPES Copyright (c) 2018 Adrian Lopez +/* FDUPES Copyright (c) 2018-2022 Adrian Lopez Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files diff -ur fdupes-2.1.2/ncurses-prompt.h fdupes-2.2.1/ncurses-prompt.h --- fdupes-2.1.2/ncurses-prompt.h 2020-08-12 21:09:35 +++ fdupes-2.2.1/ncurses-prompt.h 2022-09-04 05:59:05 @@ -1,4 +1,4 @@ -/* FDUPES Copyright (c) 2018 Adrian Lopez +/* FDUPES Copyright (c) 2018-2022 Adrian Lopez Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files diff -ur fdupes-2.1.2/ncurses-status.c fdupes-2.2.1/ncurses-status.c --- fdupes-2.1.2/ncurses-status.c 2020-08-12 21:09:35 +++ fdupes-2.2.1/ncurses-status.c 2022-09-04 05:59:05 @@ -1,4 +1,4 @@ -/* FDUPES Copyright (c) 2018 Adrian Lopez +/* FDUPES Copyright (c) 2018-2022 Adrian Lopez Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files diff -ur fdupes-2.1.2/ncurses-status.h fdupes-2.2.1/ncurses-status.h --- fdupes-2.1.2/ncurses-status.h 2020-08-12 21:09:35 +++ fdupes-2.2.1/ncurses-status.h 2022-09-04 05:59:05 @@ -1,4 +1,4 @@ -/* FDUPES Copyright (c) 2018 Adrian Lopez +/* FDUPES Copyright (c) 2018-2022 Adrian Lopez Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files diff -ur fdupes-2.1.2/positive_wcwidth.c fdupes-2.2.1/positive_wcwidth.c --- fdupes-2.1.2/positive_wcwidth.c 2020-08-12 21:09:35 +++ fdupes-2.2.1/positive_wcwidth.c 2022-09-04 05:59:05 @@ -1,4 +1,4 @@ -/* Copyright (c) 2019 Adrian Lopez +/* Copyright (c) 2019-2022 Adrian Lopez This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff -ur fdupes-2.1.2/positive_wcwidth.h fdupes-2.2.1/positive_wcwidth.h --- fdupes-2.1.2/positive_wcwidth.h 2020-08-12 21:09:35 +++ fdupes-2.2.1/positive_wcwidth.h 2022-09-04 05:59:05 @@ -1,4 +1,4 @@ -/* Copyright (c) 2019 Adrian Lopez +/* Copyright (c) 2019-2022 Adrian Lopez This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages Only in fdupes-2.2.1: removeifnotchanged.c Only in fdupes-2.2.1: removeifnotchanged.h diff -ur fdupes-2.1.2/sigint.c fdupes-2.2.1/sigint.c --- fdupes-2.1.2/sigint.c 2020-08-12 21:09:35 +++ fdupes-2.2.1/sigint.c 2022-09-04 05:59:05 @@ -1,4 +1,4 @@ -/* Copyright (c) 2018 Adrian Lopez +/* Copyright (c) 2018-2022 Adrian Lopez This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff -ur fdupes-2.1.2/sigint.h fdupes-2.2.1/sigint.h --- fdupes-2.1.2/sigint.h 2020-08-12 21:09:35 +++ fdupes-2.2.1/sigint.h 2022-09-04 05:59:05 @@ -1,4 +1,4 @@ -/* Copyright (c) 2018 Adrian Lopez +/* Copyright (c) 2018-2022 Adrian Lopez This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff -ur fdupes-2.1.2/wcs.c fdupes-2.2.1/wcs.c --- fdupes-2.1.2/wcs.c 2020-08-12 21:09:35 +++ fdupes-2.2.1/wcs.c 2022-09-04 05:59:05 @@ -1,4 +1,4 @@ -/* Copyright (c) 2018 Adrian Lopez +/* Copyright (c) 2018-2022 Adrian Lopez This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff -ur fdupes-2.1.2/wcs.h fdupes-2.2.1/wcs.h --- fdupes-2.1.2/wcs.h 2020-08-12 21:09:35 +++ fdupes-2.2.1/wcs.h 2022-09-04 05:59:05 @@ -1,4 +1,4 @@ -/* Copyright (c) 2018 Adrian Lopez +/* Copyright (c) 2018-2022 Adrian Lopez This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages