Added
Link Here
|
0 |
- |
1 |
--- hashdb.c.orig 2023-08-27 01:12:34 UTC |
|
|
2 |
+++ hashdb.c |
3 |
@@ -31,6 +31,7 @@ static hashdb_t *hashdb[HT_SIZE]; |
4 |
static int hashdb_init = 0; |
5 |
static int hashdb_algo = 0; |
6 |
static int hashdb_dirty = 0; |
7 |
+static int new_hashdb = 0; |
8 |
|
9 |
/* Pivot direction for rebalance */ |
10 |
enum pivot { PIVOT_LEFT, PIVOT_RIGHT }; |
11 |
@@ -68,20 +69,35 @@ int save_hash_database(const char * const restrict dbn |
12 |
{ |
13 |
FILE *db = NULL; |
14 |
uint64_t cnt = 0; |
15 |
+ char *dbtemp; |
16 |
|
17 |
if (dbname == NULL) goto error_hashdb_null; |
18 |
LOUD(fprintf(stderr, "save_hash_database('%s')\n", dbname);) |
19 |
/* Don't save the hash database if it wasn't changed */ |
20 |
if (hashdb_dirty == 0 && destroy == 0) return 0; |
21 |
if (hashdb_dirty == 1) { |
22 |
+ |
23 |
errno = 0; |
24 |
- db = fopen(dbname, "w+b"); |
25 |
+ dbtemp = malloc(strlen(dbname) + 5); |
26 |
+ if (dbtemp == NULL) goto error_hashdb_alloc; |
27 |
+ strcpy(dbtemp, dbname); |
28 |
+ strcat(dbtemp, ".tmp"); |
29 |
+ /* Try to remove any existing temporary database, ignoring errors */ |
30 |
+ remove(dbtemp); |
31 |
+ db = fopen(dbtemp, "rb"); |
32 |
if (db == NULL) goto error_hashdb_open; |
33 |
} |
34 |
|
35 |
- if (write_hashdb_entry(db, NULL, &cnt, destroy) != 0) goto error_hashdb_write; |
36 |
if (hashdb_dirty == 1) { |
37 |
+ if (write_hashdb_entry(db, NULL, &cnt, destroy) != 0) goto error_hashdb_write; |
38 |
fclose(db); |
39 |
+ if (new_hashdb == 0) { |
40 |
+ errno = 0; |
41 |
+ if (remove(dbname) != 0) { |
42 |
+ if (errno != ENOENT) goto error_hashdb_remove; |
43 |
+ } |
44 |
+ } |
45 |
+ if (rename(dbtemp, dbname) != 0) goto error_hashdb_rename; |
46 |
LOUD(if (hashdb_dirty == 1) fprintf(stderr, "Wrote %" PRIu64 " items to hash databse '%s'\n", cnt, dbname);) |
47 |
hashdb_dirty = 0; |
48 |
} |
49 |
@@ -92,12 +108,22 @@ error_hashdb_null: |
50 |
fprintf(stderr, "error: internal failure: NULL pointer for hashdb\n"); |
51 |
return -1; |
52 |
error_hashdb_open: |
53 |
- fprintf(stderr, "error: cannot open hashdb '%s' for writing: %s\n", dbname, strerror(errno)); |
54 |
+ fprintf(stderr, "error: cannot open temp hashdb '%s' for writing: %s\n", dbtemp, strerror(errno)); |
55 |
return -2; |
56 |
error_hashdb_write: |
57 |
- fprintf(stderr, "error: writing failed to hashdb '%s': %s\n", dbname, strerror(errno)); |
58 |
+ fprintf(stderr, "error: write failed to temp hashdb '%s': %s\n", dbtemp, strerror(errno)); |
59 |
fclose(db); |
60 |
return -3; |
61 |
+error_hashdb_alloc: |
62 |
+ fprintf(stderr, "error: cannot allocate memory for temporary hashdb name\n"); |
63 |
+ return -4; |
64 |
+error_hashdb_remove: |
65 |
+ fprintf(stderr, "error: cannot delete old hashdb '%s': %s\n", dbname, strerror(errno)); |
66 |
+ remove(dbtemp); |
67 |
+ return -5; |
68 |
+error_hashdb_rename: |
69 |
+ fprintf(stderr, "error: cannot rename temporary hashdb '%s' to '%s'; leaving it alone: %s\n", dbtemp, dbname, strerror(errno)); |
70 |
+ return -6; |
71 |
} |
72 |
|
73 |
|
74 |
@@ -435,31 +461,40 @@ int64_t load_hash_database(char *dbname) |
75 |
entry->hashcount = hashcount; |
76 |
} |
77 |
|
78 |
+ fclose(db); |
79 |
return linenum - 1; |
80 |
|
81 |
warn_hashdb_open: |
82 |
fprintf(stderr, "Creating a new hash database '%s'\n", dbname); |
83 |
+ fclose(db); |
84 |
+ new_hashdb = 1; |
85 |
return 0; |
86 |
error_hashdb_read: |
87 |
fprintf(stderr, "error reading hash database '%s': %s\n", dbname, strerror(errno)); |
88 |
+ fclose(db); |
89 |
return -1; |
90 |
error_hashdb_header: |
91 |
fprintf(stderr, "error in header of hash database '%s'\n", dbname); |
92 |
+ fclose(db); |
93 |
return -2; |
94 |
error_hashdb_version: |
95 |
fprintf(stderr, "error: bad db version %u in hash database '%s'\n", db_ver, dbname); |
96 |
+ fclose(db); |
97 |
return -3; |
98 |
error_hashdb_line: |
99 |
fprintf(stderr, "\nerror: bad line %" PRId64 " in hash database '%s':\n\n%s\n\n", linenum, dbname, line); |
100 |
+ fclose(db); |
101 |
return -4; |
102 |
error_hashdb_add: |
103 |
fprintf(stderr, "error: internal failure allocating a hashdb entry\n"); |
104 |
+ fclose(db); |
105 |
return -5; |
106 |
error_hashdb_null: |
107 |
fprintf(stderr, "error: internal failure: NULL pointer for hashdb\n"); |
108 |
return -6; |
109 |
warn_hashdb_algo: |
110 |
fprintf(stderr, "warning: hashdb uses a different hash algorithm than selected; not loading\n"); |
111 |
+ fclose(db); |
112 |
return -7; |
113 |
} |
114 |
|