git: 91b52f2c0fd0 - 2023Q4 - sysutils/jdupes: Update to 1.27.3_1

From: Fernando Apesteguía <fernape_at_FreeBSD.org>
Date: Fri, 17 Nov 2023 18:29:49 UTC
The branch 2023Q4 has been updated by fernape:

URL: https://cgit.FreeBSD.org/ports/commit/?id=91b52f2c0fd09ef333fe1a2ac1f0ce5f27d9b741

commit 91b52f2c0fd09ef333fe1a2ac1f0ce5f27d9b741
Author:     Thomas Hurst <tom@hur.st>
AuthorDate: 2023-11-17 07:30:06 +0000
Commit:     Fernando Apesteguía <fernape@FreeBSD.org>
CommitDate: 2023-11-17 18:29:23 +0000

    sysutils/jdupes: Update to 1.27.3_1
    
    ChangeLog:
    https://www.jdupes.com/2023/11/10/news-fix-for-v1-27-3-libjodycode-4-work/
    
    Apply a fix for the jdupes hash database feature to avoid potential
    database loss, resulting from disk-full situations and other write
    failures.
    
    PR:             275128
    Reported by:    tom@hur.st (maintainer)
    MFH:            2023Q4 (bugfix)
    
    (cherry picked from commit efcf734590eaaf1dee0bac5fc758680925501d15)
---
 sysutils/jdupes/Makefile             |   1 +
 sysutils/jdupes/files/patch-hashdb.c | 114 +++++++++++++++++++++++++++++++++++
 2 files changed, 115 insertions(+)

diff --git a/sysutils/jdupes/Makefile b/sysutils/jdupes/Makefile
index ebb0aed66e32..c2eedc8de39d 100644
--- a/sysutils/jdupes/Makefile
+++ b/sysutils/jdupes/Makefile
@@ -1,6 +1,7 @@
 PORTNAME=	jdupes
 DISTVERSIONPREFIX=	v
 DISTVERSION=	1.27.3
+PORTREVISION=	1
 CATEGORIES=	sysutils
 
 MAINTAINER=	tom@hur.st
diff --git a/sysutils/jdupes/files/patch-hashdb.c b/sysutils/jdupes/files/patch-hashdb.c
new file mode 100644
index 000000000000..bc631af357c2
--- /dev/null
+++ b/sysutils/jdupes/files/patch-hashdb.c
@@ -0,0 +1,114 @@
+--- hashdb.c.orig	2023-08-27 01:12:34 UTC
++++ hashdb.c
+@@ -31,6 +31,7 @@ static hashdb_t *hashdb[HT_SIZE];
+ static int hashdb_init = 0;
+ static int hashdb_algo = 0;
+ static int hashdb_dirty = 0;
++static int new_hashdb = 0;
+ 
+ /* Pivot direction for rebalance */
+ enum pivot { PIVOT_LEFT, PIVOT_RIGHT };
+@@ -68,20 +69,35 @@ int save_hash_database(const char * const restrict dbn
+ {
+   FILE *db = NULL;
+   uint64_t cnt = 0;
++  char *dbtemp;
+ 
+   if (dbname == NULL) goto error_hashdb_null;
+   LOUD(fprintf(stderr, "save_hash_database('%s')\n", dbname);)
+   /* Don't save the hash database if it wasn't changed */
+   if (hashdb_dirty == 0 && destroy == 0) return 0;
+   if (hashdb_dirty == 1) {
++
+     errno = 0;
+-    db = fopen(dbname, "w+b");
++    dbtemp = malloc(strlen(dbname) + 5);
++    if (dbtemp == NULL) goto error_hashdb_alloc;
++    strcpy(dbtemp, dbname);
++    strcat(dbtemp, ".tmp");
++    /* Try to remove any existing temporary database, ignoring errors */
++    remove(dbtemp);
++    db = fopen(dbtemp, "rb");
+     if (db == NULL) goto error_hashdb_open;
+   }
+ 
+-  if (write_hashdb_entry(db, NULL, &cnt, destroy) != 0) goto error_hashdb_write;
+   if (hashdb_dirty == 1) {
++    if (write_hashdb_entry(db, NULL, &cnt, destroy) != 0) goto error_hashdb_write;
+     fclose(db);
++    if (new_hashdb == 0) {
++      errno = 0;
++      if (remove(dbname) != 0) {
++        if (errno != ENOENT) goto error_hashdb_remove;
++      }
++    }
++    if (rename(dbtemp, dbname) != 0) goto error_hashdb_rename;
+     LOUD(if (hashdb_dirty == 1) fprintf(stderr, "Wrote %" PRIu64 " items to hash databse '%s'\n", cnt, dbname);)
+     hashdb_dirty = 0;
+   }
+@@ -92,12 +108,22 @@ error_hashdb_null:
+   fprintf(stderr, "error: internal failure: NULL pointer for hashdb\n");
+   return -1;
+ error_hashdb_open:
+-  fprintf(stderr, "error: cannot open hashdb '%s' for writing: %s\n", dbname, strerror(errno));
++  fprintf(stderr, "error: cannot open temp hashdb '%s' for writing: %s\n", dbtemp, strerror(errno));
+   return -2;
+ error_hashdb_write:
+-  fprintf(stderr, "error: writing failed to hashdb '%s': %s\n", dbname, strerror(errno));
++  fprintf(stderr, "error: write failed to temp hashdb '%s': %s\n", dbtemp, strerror(errno));
+   fclose(db);
+   return -3;
++error_hashdb_alloc:
++  fprintf(stderr, "error: cannot allocate memory for temporary hashdb name\n");
++  return -4;
++error_hashdb_remove:
++  fprintf(stderr, "error: cannot delete old hashdb '%s': %s\n", dbname, strerror(errno));
++  remove(dbtemp);
++  return -5;
++error_hashdb_rename:
++  fprintf(stderr, "error: cannot rename temporary hashdb '%s' to '%s'; leaving it alone: %s\n", dbtemp, dbname, strerror(errno));
++  return -6;
+ }
+ 
+ 
+@@ -435,31 +461,40 @@ int64_t load_hash_database(char *dbname)
+     entry->hashcount = hashcount;
+   }
+ 
++  fclose(db);
+   return linenum - 1;
+ 
+ warn_hashdb_open:
+   fprintf(stderr, "Creating a new hash database '%s'\n", dbname);
++  fclose(db);
++  new_hashdb = 1;
+   return 0;
+ error_hashdb_read:
+   fprintf(stderr, "error reading hash database '%s': %s\n", dbname, strerror(errno));
++  fclose(db);
+   return -1;
+ error_hashdb_header:
+   fprintf(stderr, "error in header of hash database '%s'\n", dbname);
++  fclose(db);
+   return -2;
+ error_hashdb_version:
+   fprintf(stderr, "error: bad db version %u in hash database '%s'\n", db_ver, dbname);
++  fclose(db);
+   return -3;
+ error_hashdb_line:
+   fprintf(stderr, "\nerror: bad line %" PRId64 " in hash database '%s':\n\n%s\n\n", linenum, dbname, line);
++  fclose(db);
+   return -4;
+ error_hashdb_add:
+   fprintf(stderr, "error: internal failure allocating a hashdb entry\n");
++  fclose(db);
+   return -5;
+ error_hashdb_null:
+   fprintf(stderr, "error: internal failure: NULL pointer for hashdb\n");
+   return -6;
+ warn_hashdb_algo:
+   fprintf(stderr, "warning: hashdb uses a different hash algorithm than selected; not loading\n");
++  fclose(db);
+   return -7;
+ }
+