1 #ifdef COPYRIGHT_INFORMATION
2 #include "gplv3.h"
3 #endif
4 /*
5 * Copyright (C) 2002-2016 Edscott Wilson Garcia
6 * EMail: edscott@imp.mx
7 *
8 *
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 3 of the License, or
12 * (at your option) any later version.
13 *
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
18 *
19 * You should have received a copy of the GNU General Public License
20 * along with this program; if not, write to the Free Software
21 * Foundation.
22 */
23
24 // This file contains definitions of static functions
25 // No exported functions or symbols should be in this file.
26
27
28 static int open_timeout = 0;
29 static pthread_mutex_t new_mutex = PTHREAD_MUTEX_INITIALIZER;
30
31 static int sdbh_writeheader (DBHashTable * dbh, int flush);
32 static int sdbh_updateBranch (DBHashTable *, FILE_POINTER);
33 static unsigned char sdbh_readBranches (DBHashTable *, FILE_POINTER);
34
35 static FILE_POINTER *sdbh_locate (DBHashTable *, FILE_POINTER *);
36 static FILE_POINTER *sdbh_locateTop (DBHashTable *, FILE_POINTER *, int);
37 static FILE_POINTER *sdbh_locateFind (DBHashTable *, FILE_POINTER *, int);
38 static void sdbh_cuenta (unsigned char *, unsigned char, FILE_POINTER);
39 static FILE_POINTER sdbh_write (char, DBHashTable *, unsigned char);
40 static int sdbh_read (char, DBHashTable *, unsigned char);
41 static int sdbh_readheader (DBHashTable *);
42
43 #ifdef TURN
44 static FILE_POINTER sdbh_turnaround (FILE_POINTER);
45 #endif
46 static FILE_POINTER sdbh_z (unsigned char, unsigned char);
47 static unsigned char sdbh_cuantumR (FILE_POINTER, unsigned char, FILE_POINTER *);
48 static unsigned char sdbh_cuantum (FILE_POINTER, unsigned char, FILE_POINTER *);
49 static void sdbh_cifra (unsigned char *, unsigned char, unsigned char, FILE_POINTER *);
50
51 static int sdbh_reversebarre (DBHashTable *, FILE_POINTER, int);
52 static int sdbh_barre (DBHashTable *, FILE_POINTER, int);
53
54 static void sdbh_transfer (DBHashTable *);
55 static DBHashTable *sdbh_open_S (const char *, int, int);
56
57 static int sdbh_size (DBHashTable *, FILE_POINTER);
58
59 #ifdef PARALLEL_SAFE
60 static char *lock_name(const char *archivo);
61 #endif
62
63 /*************************************************************************/
my_open(const char * filename,int flags)64 static int my_open(const char *filename, int flags){
65 #ifndef HAVE_WINDOWS_H
66 if (flags & O_CREAT) return open(filename, flags, 0640);
67 return open(filename, flags);
68 #else
69 if (flags & O_CREAT) return open(filename, flags|_O_BINARY, 0640);
70 return open(filename, flags|_O_BINARY);
71 #endif
72 }
73
74 #if 0
75 // Faster without this.
76 static int
77 sync_fd (int fd) {
78 /*if (fsync(fd) < 0) {
79 // this should not happen, really.
80 ERR("fsync(): %s\n", strerror(errno));
81 return 0;
82 } */
83 return 1;
84 }
85 #endif
86
87 static int
advance_fp(DBHashTable * dbh,FILE_POINTER offset)88 advance_fp (DBHashTable * dbh, FILE_POINTER offset) {
89 //if (!sync_fd(dbh->fd)) return 0;
90 if(lseek (dbh->fd, (off_t) offset, SEEK_CUR) < 0) {
91 errno = EBADF;
92 ERR( "Error: advance_fp failed to advance fp %lld\n", (long long)offset);
93 return 0;
94 }
95 return 1;
96 }
97
98 static int
place_fp_at(DBHashTable * dbh,off_t seek)99 place_fp_at (DBHashTable * dbh, off_t seek) {
100 //if (!sync_fd(dbh->fd)) return 0;
101 if(lseek (dbh->fd, (off_t) seek, SEEK_SET) != seek) {
102 // this should not happen...
103 errno = EBADF;
104 ERR( "Error: sdbh_locate() cannot place file pointer at bof=0x%llu\n", (long long unsigned)seek);
105 return 0;
106 }
107 return 1;
108 }
109
110 static FILE_POINTER
place_eof(DBHashTable * dbh)111 place_eof (DBHashTable * dbh) {
112 //if (!sync_fd(dbh->fd)) return 0;
113 FILE_POINTER eof;
114 eof = (FILE_POINTER) lseek (dbh->fd, (off_t) 0L, SEEK_END);
115 if(eof < sizeof (dbh_header_t)) {
116 errno = EBADF;
117 ERR( "Error: tell_eof() < sizeof (dbh_header_t)\n");
118 eof = -1;
119 }
120 if(eof < 0) {
121 // this should not happen...
122 errno = EBADF;
123 ERR( "Error: tell_eof() cannot place file pointer at eof\n");
124 }
125 return eof;
126 }
127
128 /* Funciones nivel 0: */
129 static void
sdbh_operate(DBHashTable * dbh)130 sdbh_operate (DBHashTable * dbh) {
131 if(dbh == NULL) {
132 ERR ("Must define function operate(place*) before doing a sweep\n");
133 }
134 }
135
136 static char *
sdbh_randomfilename(DBHashTable * dbh,char code)137 sdbh_randomfilename (DBHashTable * dbh, char code) {
138 time_t segundos;
139 FILE_POINTER divisor;
140 char *archivo;
141 const char *tmpdir;
142 if(!dbh) return NULL;
143 // determine best tmp directory
144 if(dbh->head_info->user_tmpdir == 0) {
145 struct stat dbh_st, tmp_st;
146 if (stat (dbh->path, &dbh_st) < 0){
147 ERR("Unable to stat: %s\n", dbh->path);
148 return NULL;
149 }
150 #ifdef HAVE_WINDOWS_H
151 const char * tmp = getenv("TEMP");
152 if (!tmp || access(tmp,W_OK) < 0) tmp ="c:\\";
153 #else
154 const char *tmp = "/tmp";
155 #endif
156
157 if (stat (tmp, &tmp_st) < 0){
158 ERR("Unable to stat: %s\n", tmp);
159 return NULL;
160 }
161 if (dbh->tmpdir) {
162 free(dbh->tmpdir);
163 }
164 dbh->tmpdir = NULL;
165 // Make sure tmp dir is on same device.
166 DBG("system temp dir is %s \n", tmp);
167 if(dbh_st.st_dev == tmp_st.st_dev) {
168 dbh->tmpdir = (char *)malloc (strlen (tmp) + 1);
169 if (dbh->tmpdir == NULL) {
170 ERR( "malloc dbh->tmpdir: %s\n", strerror(errno));
171 return NULL;
172 }
173 strcpy (dbh->tmpdir, tmp);
174 } else {
175 // system tmp dir is not on the same device.
176 #ifdef HAVE_WINDOWS_H
177 dbh->tmpdir = (char *)malloc (strlen (tmp) + 1);
178 strcpy (dbh->tmpdir, tmp);
179 #else
180 if (*(dbh->path) =='/') {
181 dbh->tmpdir = (char *)malloc (strlen (dbh->path) + 1);
182 if (dbh->tmpdir == NULL) {
183 ERR( "malloc dbh->tmpdir: %s\n", strerror(errno));
184 return NULL;
185 }
186 strcpy (dbh->tmpdir, dbh->path);
187 *(strrchr(dbh->tmpdir, '/')) = 0;
188 } else {
189 dbh->tmpdir = (char *)malloc (1024);
190 if (dbh->tmpdir == NULL) {
191 ERR( "malloc dbh->tmpdir: %s\n", strerror(errno));
192 return NULL;
193 }
194 if (!getcwd(dbh->tmpdir, 1024)){
195 ERR( "!getcwd: %s\n", strerror(errno));
196 return NULL;
197 }
198 }
199 #endif
200 }
201 }
202 tmpdir = dbh->tmpdir;
203
204 time (&segundos);
205 int try=0;
206 retry:
207 srand ((unsigned)segundos);
208 divisor = RAND_MAX / 10000;
209 // Usage of rand is not security related. Just to get a random temporary file name.
210 // coverity[dont_call : FALSE]
211 if((segundos = rand () / divisor) > 100000L)
212 segundos = 50001;
213 archivo = (char *)malloc (strlen (tmpdir) + 1 + 1 + 6 + 4 + 1);
214 if (archivo == NULL) {
215 ERR( "malloc filename: %s\n", strerror(errno));
216 return NULL;
217 }
218 #ifdef HAVE_WINDOWS_H
219 sprintf (archivo, "%s%c%c%ld.tmp", tmpdir, '\\', code, (long)segundos);
220 #else
221 sprintf (archivo, "%s/%c%ld.tmp", tmpdir, code, (long)segundos);
222 #endif
223
224 // if the file exists (fat chance), retry with a different random number...
225 struct stat st;
226 if (stat(archivo, &st)==0){
227 if (segundos > 0) segundos--;
228 else segundos++;
229 if (try++ < 3) {
230 free(archivo);
231 goto retry;
232 }
233 free(archivo);
234 return NULL;
235 }
236
237 return archivo;
238 } /*******************************************************************************/
239
240 #if 0
241 this is unreliable in Linux...
242 //mode=1 --> write lock
243 static void
244 lock_fd (int fd, int mode, const char *archivo) {
245 // return;
246 // get the file lock, wait if necesary:
247 struct flock lock;
248
249 lock.l_whence = SEEK_SET;
250 lock.l_start = 0;
251 lock.l_len = 0; // to eof
252
253 if(mode) {
254 lock.l_type = F_WRLCK;
255 } else {
256 lock.l_type = F_RDLCK;
257 }
258
259 int try=0;
260 retry:
261 if(fcntl (fd, F_SETLKW, &lock) < 0) {
262 if (try++ < 3) {
263 sleep(1);
264 goto retry;
265 }
266 DBG( "fcntl(F_SETLKW)(%s): %s\n", archivo, strerror (errno));
267 }
268 }
269
270 static void
271 unlock (int fd) {
272
273
274 // release the lock:
275 struct flock lock;
276
277 lock.l_whence = SEEK_SET;
278 lock.l_start = 0;
279 lock.l_len = 0; // to eof
280
281 lock.l_type = F_UNLCK;
282 int try=0;
283 retry:
284 if(fcntl (fd, F_SETLKW, &lock) < 0) {
285 if (try++ < 3) {
286 sleep(1);
287 goto retry;
288 }
289 DBG( "fcntl(F_SETLKW): %s\n", strerror (errno));
290 }
291 }
292 #endif
293
294
295 /* Functions: ************************************************************** */
296 static unsigned char
sdbh_readBranches(DBHashTable * dbh,FILE_POINTER seek)297 sdbh_readBranches (DBHashTable * dbh, FILE_POINTER seek) {
298 FILE_POINTER *rama;
299 unsigned char ramas;
300 rama = dbh->newbranch;
301 TRACE ("sdbh_readBranches\n");
302
303 if(!place_fp_at (dbh, (off_t)seek)){
304 return 0;
305 }
306 if(read (dbh->fd, &ramas, 1) != 1) {
307 ERR ("sdbh_readBranches error 3.1\n");
308 return 0;
309 }
310 if (ramas > dbh->head_info->n_limit){
311 ERR ("Corrupted loop boundary \"ramas\"\n");
312 return 0;
313 }
314 DBG ("sdbh_readBranches ramas=%lld\n", (long long)ramas);
315 if(!advance_fp (dbh, 1L + sizeof (FILE_POINTER))) {
316 return 0;
317 }
318
319 if(read (dbh->fd, rama, sizeof (FILE_POINTER) * ramas) != sizeof (FILE_POINTER) * ramas) {
320 ERR ("sdbh_readBranches error 3.2\n");
321 return 0;
322 }
323 DBG ("read:");
324 int i;
325 for(i = 0; i < ramas; i++){
326 DBG (" rama[%d]=0x%llu\n", i, (long long unsigned)(rama[i]));
327 }
328 #ifdef TURN
329 {
330 int i;
331 for(i = 0; i < ramas; i++)
332 rama[i] = sdbh_turnaround (rama[i]);
333 }
334 #endif
335 return ramas;
336 } /***************************************************/
337
338 static int
sdbh_updateBranch(DBHashTable * dbh,FILE_POINTER seek)339 sdbh_updateBranch (DBHashTable * dbh, FILE_POINTER seek) {
340 TRACE ("sdbh_updateBranch\n");
341 FILE_POINTER *rama;
342 unsigned char ramas;
343 rama = dbh->newbranch;
344 if(!place_fp_at (dbh, (off_t)seek)) {
345 return 0;
346 }
347 if(read (dbh->fd, &ramas, 1) != 1) {
348 ERR ("sdbh_updateBranch read error 4.1\n");
349 return 0;
350 }
351
352 if(!advance_fp (dbh, 1L + sizeof (FILE_POINTER))){
353 return 0;
354 }
355
356 #ifdef TURN
357 {
358 int i;
359 for(i = 0; i < ramas; i++)
360 rama[i] = sdbh_turnaround (rama[i]);
361 }
362 #endif
363 DBG ("Updating branch information for new record:");
364 int i;
365 if (ramas > dbh->head_info->n_limit){
366 ERR ("Corrupted loop boundary \"ramas\"\n");
367 return 0;
368 }
369 for(i = 0; i < ramas; i++){
370 DBG (" rama[%d]=0x%llu\n", i, (long long unsigned)(rama[i]));
371 }
372
373 if(write (dbh->fd, rama, sizeof (FILE_POINTER) * ramas) != sizeof (FILE_POINTER) * ramas) {
374 ERR ("sdbh_updateBranch write error 4.2\n");
375 return 0;
376 }
377 #ifdef TURN
378 {
379 int i;
380 for(i = 0; i < ramas; i++)
381 rama[i] = sdbh_turnaround (rama[i]);
382 }
383 #endif
384 return 1;
385 } /*****************************************************/
386
387 #define BRANCHOFF (dbh->head_info->n_limit-dbh->newbranches)
388 #define CURRENTSEEK fp[0]
389 #define LASTSEEK fp[1]
390 #define CURR_BRANCH fp[2]
391 #define SWITCHED (dbh->head_info->reservedD)
392 //FILE_POINTER *fp must have size = 3
393 static FILE_POINTER *
sdbh_locate(DBHashTable * dbh,FILE_POINTER * fp)394 sdbh_locate (DBHashTable * dbh, FILE_POINTER * fp) {
395 TRACE ("sdbh_locate\n");
396 FILE_POINTER currentseek,
397 lastseek;
398 int i; /*,offset; */
399 lastseek = currentseek = 0;
400 CURRENTSEEK = LASTSEEK = CURR_BRANCH = 0; /* ERROR value assigned */
401 currentseek = dbh->head_info->bof;
402
403 if(!place_fp_at (dbh, (off_t)currentseek)) {
404 return NULL;
405 }
406
407 if(!sdbh_read (NEW, dbh, 1)) {
408 return fp;
409 }
410 loop:
411 #define OFFSET (i+(dbh->head_info->n_limit-dbh->newbranches))
412 for(i = 0; i < dbh->newbranches; i++) {
413 if(*(dbh->key + OFFSET) != *(dbh->newkey + OFFSET))
414 {
415 lastseek = currentseek;
416 if((currentseek = *(dbh->newbranch + i)) == 0) {
417 CURR_BRANCH = i;
418 break;
419 }
420 if(!place_fp_at (dbh, (off_t)currentseek)) {
421 return NULL;
422 }
423 if(!sdbh_read (NEW, dbh, 1)) {
424 return fp;
425 }
426 goto loop;
427 }
428 }
429 CURRENTSEEK = currentseek;
430 LASTSEEK = lastseek;
431 return fp;
432 }
433
434 static FILE_POINTER *
sdbh_locateTop(DBHashTable * dbh,FILE_POINTER * fp,int key_length)435 sdbh_locateTop (DBHashTable * dbh, FILE_POINTER * fp, int key_length) {
436 TRACE ("sdbh_locateFind\n");
437 FILE_POINTER currentseek,
438 lastseek;
439 int i;
440 lastseek = currentseek = 0;
441 CURRENTSEEK = LASTSEEK = CURR_BRANCH = 0; /* ERROR value assigned */
442 currentseek = dbh->head_info->bof;
443
444 if(!place_fp_at (dbh, (off_t)currentseek)) {
445 return NULL;
446 }
447
448 if(!sdbh_read (NEW, dbh, 1)) {
449 return fp;
450 }
451 if (key_length > dbh->newbranches) key_length = dbh->newbranches;
452 // fprintf(stderr, "*branch %d: newkey=%s branches=%d\n", 0, dbh->newkey, dbh->newbranches);
453 // fprintf(stderr, "looking for %s ...\n", dbh->key);
454
455 FILE_POINTER addr[key_length];
456 memcpy(addr, dbh->newbranch, key_length*sizeof(FILE_POINTER));
457 if (memcmp((void *)(dbh->key), (void *)(dbh->newkey), key_length) == 0){
458 CURRENTSEEK = currentseek;
459 return fp;
460 }
461
462 int j=0;
463 loop:
464 for (i=0; i<key_length; i++){
465 // fprintf(stderr, "%d) %c ?= %c\n", j, *(dbh->key + j),*(dbh->newkey + OFFSET));
466 if (*(dbh->key + j) != *(dbh->newkey + OFFSET)){
467 if (!dbh->newbranch[i]) return NULL; // no next node
468 // otherwise, read next node:
469 // fprintf(stderr, "next branch %d: (addr:%p)\n", i, dbh->newbranch[i]);
470 lastseek = currentseek;
471 currentseek = dbh->newbranch[i];
472 if(!place_fp_at (dbh, (off_t)currentseek)) {
473 return NULL;
474 }
475 if(!sdbh_read (NEW, dbh, 1)) {
476 return NULL;
477 }
478 if (memcmp((void *)(dbh->key), (void *)(dbh->newkey), key_length) == 0) {
479 //fprintf(stderr, "branch %d: (addr:%p) newkey=%s newbranches=%d\n", i, dbh->newbranch[i], dbh->newkey, dbh->newbranches);
480 CURRENTSEEK = currentseek;
481 //fprintf(stderr, "fp: %p %p %p\n", fp[0], fp[1], fp[2]);
482 return fp;
483 }
484 goto loop;
485 }
486 j++;
487 }
488 return NULL;
489 }
490
491 static FILE_POINTER *
sdbh_locateFind(DBHashTable * dbh,FILE_POINTER * fp,int keys)492 sdbh_locateFind (DBHashTable * dbh, FILE_POINTER * fp, int keys) {
493 TRACE ("sdbh_locateFind\n");
494 FILE_POINTER currentseek,
495 lastseek;
496 int i;
497 lastseek = currentseek = 0;
498 CURRENTSEEK = LASTSEEK = CURR_BRANCH = 0; /* ERROR value assigned */
499 currentseek = dbh->head_info->bof;
500
501 if(!place_fp_at (dbh, (off_t)currentseek)) {
502 return NULL;
503 }
504
505 if(!sdbh_read (NEW, dbh, 1)) {
506 return fp;
507 }
508 if(keys > dbh->head_info->n_limit)
509 keys = dbh->head_info->n_limit;
510 loop:
511 for(i = 0; i < dbh->newbranches - (dbh->head_info->n_limit - keys); i++) {
512 /* offset=i+(dbh->head_info->n_limit-dbh->newbranches); */
513 if(*(dbh->key + OFFSET) != *(dbh->newkey + OFFSET)) {
514 lastseek = currentseek;
515 if((currentseek = *(dbh->newbranch + i)) == 0) {
516 CURR_BRANCH = i;
517 break;
518 }
519 if(!place_fp_at (dbh, (off_t)currentseek)) {
520 return NULL;
521 }
522 if(!sdbh_read (NEW, dbh, 1)) {
523 return fp;
524 }
525 goto loop;
526 }
527 }
528 CURRENTSEEK = currentseek;
529 LASTSEEK = lastseek;
530 return fp;
531 }
532
533 #ifdef PARALLEL_SAFE
lock_name(const char * archivo)534 static char *lock_name(const char *archivo){
535 if (!archivo || strlen(archivo)==0){
536 ERR("Cannot determine lock name for %s\n",
537 (archivo)?archivo:"NULL");
538 return NULL;
539 }
540
541 char *path;
542
543 #ifdef HAVE_REALPATH
544 path = realpath(archivo, NULL);
545 if (!path) {
546 ERR( "realpath(%s): %s\n", archivo, strerror(errno));
547 }
548 #else
549 path = (char *)malloc(strlen(archivo)+1);
550 if (path) strcpy(path, archivo);
551 #endif
552
553 if (!path){
554 ERR( "1.malloc path %s: %s\n", path, strerror(errno));
555 return NULL;
556 }
557
558
559 // Get inode information:
560 struct stat st;
561 if (stat(path, &st) < 0){
562 // This is a valid return value.
563 NOOP("Cannot stat %s: %s\n", path, strerror(errno));
564 free(path);
565 return NULL;
566 }
567
568 // Build shm_name
569 char buffer[1024];
570 memset(buffer, 0, 1024);
571 sprintf(buffer, "/%d-%d", (int)st.st_dev, (int)st.st_ino);
572
573 char *shm_name = (char *)malloc((strlen(buffer)+1)*sizeof(char));
574 if (!shm_name) {
575 ERR("Cannot malloc lock name for %s\n", path);
576 return NULL;
577 }
578 memset(shm_name, 0, strlen(buffer)+1);
579 sprintf(shm_name, "%s", buffer);
580 free(path);
581 return shm_name;
582 }
583
sem_name(const char * archivo)584 static char *sem_name(const char *archivo){
585 char *untagged_name = lock_name(archivo);
586 if (!untagged_name) return NULL;
587 char *name = (char *)malloc((strlen(untagged_name)+strlen("-ns")+1)*sizeof(char));
588 if (!name){
589 errno=ENOMEM;
590 free(untagged_name);
591 return NULL;
592 }
593 sprintf(name, "%s-ns", untagged_name);
594 free(untagged_name);
595 return name;
596 }
597
598
599
600
601
602 #endif
603
604 static dbh_lock_t *
open_shm_lock(const char * archivo)605 open_shm_lock(const char *archivo){
606 #ifndef PARALLEL_SAFE
607 return NULL;
608 #else
609 char *shm_name=lock_name(archivo);
610 if (!shm_name){
611 // This would indicate something is wrong...
612 ERR("Cannot get lock name for %s\n",
613 archivo);
614 return NULL;
615 }
616
617 int fd = shm_open (shm_name, O_RDWR, S_IRUSR | S_IWUSR);
618 if (fd > 0){
619 NOOP("Lockfile exists %s -> %s\n", archivo, shm_name);
620 } else {
621 fd = shm_open (shm_name, O_RDWR | O_CREAT, S_IRUSR | S_IWUSR);
622 }
623 if(fd < 0) {
624 ERR("Cannot open shared memory file descriptor for %s (%s): %s\n",
625 shm_name, archivo, strerror (errno));
626 free(shm_name);
627 return NULL;
628 } else {
629 if(ftruncate (fd, sizeof(dbh_lock_t)) < 0) {
630 ERR("Cannot ftruncate shared memory item for %s: %s\n",
631 archivo, strerror (errno));
632 free(shm_name);
633 close(fd);
634 return NULL;
635 }
636 }
637 dbh_lock_t *lock_p = (dbh_lock_t *) mmap (NULL, sizeof(dbh_lock_t),
638 PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
639 if (lock_p == MAP_FAILED){
640 ERR("Cannot mmap shared memory item for %s: %s\n",
641 archivo, strerror (errno));
642 close (fd);
643 shm_unlink (shm_name);
644 char *nsem_name = sem_name(archivo);
645 if (nsem_name){
646 sem_unlink (nsem_name);
647 free(nsem_name);
648 }
649 free(shm_name);
650 return NULL;
651 }
652
653
654 free(shm_name);
655 close (fd);
656 return lock_p;
657 #endif
658 }
659
660 static void
destroy_shm_lock(char * archivo,dbh_lock_t * lock_p)661 destroy_shm_lock(char *archivo, dbh_lock_t *lock_p){
662 #ifdef PARALLEL_SAFE
663 if (!lock_p) return;
664 char *shm_name=lock_name(archivo);
665 if (!shm_name) {
666 // Nothing to destroy.
667 return;
668 }
669 munmap (lock_p, sizeof(dbh_lock_t));
670 shm_unlink (shm_name);
671 free(shm_name);
672 #endif
673 }
674
675 static void
clear_shm_lock(const char * archivo)676 clear_shm_lock(const char *archivo){
677 #ifndef PARALLEL_SAFE
678 return;
679 #else
680 char *shm_name=lock_name(archivo);
681 if (!shm_name){
682 // Nothing to clear.
683 return;
684 }
685 // open it.
686 dbh_lock_t *lock_p = open_shm_lock(archivo);
687 // clear it.
688
689 lock_p->write_lock_count = 0;
690 lock_p->write_lock = 0;
691 lock_p->read_lock_count = 0;
692
693 if(msync (lock_p, sizeof(dbh_lock_t), MS_ASYNC) < 0){
694 ERR("(1) Cannot msync shared memory item for %s: %s\n",
695 archivo, strerror (errno));
696 }
697
698 munmap (lock_p, sizeof(dbh_lock_t));
699 // erase it (if not open elsewhere)
700 shm_unlink (shm_name);
701 free(shm_name);
702 char *nsem_name = sem_name(archivo);
703 if (nsem_name){
704 sem_unlink(nsem_name);
705 free(nsem_name);
706 }
707 return;
708 #endif
709 }
710
711
712 static DBHashTable *
sdbh_create(const char * path,unsigned char key_length,int flags)713 sdbh_create (const char *path, unsigned char key_length, int flags) {
714 DBHashTable *dbh;
715 if (key_length > 254){
716 ERR("sdbh_create(%s): key_length is limited to 254 bytes...\n", path);
717 return NULL;
718 }
719 dbh = (DBHashTable *) malloc (sizeof (DBHashTable));
720 if(dbh == NULL){
721 ERR( "malloc(%ld): %s\n", (long)sizeof (DBHashTable), strerror(errno));
722 return NULL;
723 }
724 memset (dbh, 0, sizeof (DBHashTable));
725 dbh->lock_attempt_limit = open_timeout;
726 /////////////////////////////////////////////
727
728 unlink (path);
729 dbh->fd = my_open (path, O_CREAT | O_RDWR | O_TRUNC);
730 if(dbh->fd < 0) {
731 free (dbh);
732 ERR("sdbh_create(%s): %s\n", path, strerror (errno));
733 return NULL;
734 }
735
736 dbh->head_info = (dbh_header_t *) malloc (sizeof (dbh_header_t));
737 if (dbh->head_info == NULL) {
738 free (dbh);
739 ERR( "malloc(%ld): %s\n", (long)sizeof (dbh_header_t), strerror(errno));
740 return NULL;
741 }
742
743 memset ((void *)(dbh->head_info), 0, sizeof (dbh_header_t));
744 #ifdef PARALLEL_SAFE
745 if (flags & DBH_PARALLEL_SAFE){
746 char *nsem_name = sem_name(path);
747 if (!nsem_name) {
748 ERR( "malloc(%ld): %s\n", (long)strlen(path), strerror(errno));
749 free (dbh);
750 return NULL;
751 }
752 dbh->sem = sem_open(nsem_name, O_CREAT, 0700, 1);
753 free(nsem_name);
754
755 clear_shm_lock(path);
756 dbh->lock_p = open_shm_lock(path);
757 }
758 #endif
759
760 dbh->head_info->bof = sizeof (dbh_header_t);
761 dbh->head_info->n_limit = key_length;
762 dbh->head_info->user_tmpdir = 0;
763 dbh->head_info->sweep_erased = 0;
764 dbh->head_info->total_space = dbh->head_info->data_space = dbh->head_info->erased_space = 0;
765 strncpy (dbh->head_info->version, DBH_FILE_VERSION, 15);
766 dbh->head_info->records = 0;
767 dbh->operate = sdbh_operate;
768 dbh->branch = (FILE_POINTER *) malloc (dbh->head_info->n_limit * sizeof (FILE_POINTER));
769 if (dbh->branch == NULL) {
770 ERR( "malloc dbh->branch: %s\n", strerror(errno));
771 dbh_close(dbh);
772 return NULL;
773 }
774 dbh->newbranch = (FILE_POINTER *) malloc (dbh->head_info->n_limit * sizeof (FILE_POINTER));
775 if (dbh->newbranch == NULL) {
776 ERR( "malloc dbh->newbranch: %s\n", strerror(errno));
777 dbh_close(dbh);
778 return NULL;
779 }
780 dbh->key = (unsigned char *)malloc (key_length);
781 if (dbh->key == NULL) {
782 ERR( "malloc dbh->key: %s\n", strerror(errno));
783 dbh_close(dbh);
784 return NULL;
785 }
786 dbh->newkey = (unsigned char *)malloc (key_length);
787 if (dbh->newkey == NULL) {
788 ERR( "malloc dbh->newkey: %s\n", strerror(errno));
789 dbh_close(dbh);
790 return NULL;
791 }
792 dbh->path = (char *)malloc (strlen (path) + 1);
793 if (dbh->path == NULL || dbh->newbranch == NULL ||
794 dbh->key == NULL || dbh->newkey == NULL || dbh->path == NULL) {
795 ERR( "malloc dbh->path: %s\n", strerror(errno));
796 dbh_close(dbh);
797 return NULL;
798 }
799
800 strcpy (dbh->path, path);
801
802 dbh->head_info->record_length = 0;
803 dbh->head_info->writeOK = 1;
804 sdbh_size (dbh, DEFAULT_DBH_DATASIZE);
805 dbh->bytes_userdata = 0;
806
807 sdbh_writeheader (dbh, 1);
808 DBG (" created %s \n", path);
809 return dbh;
810 }
811
812 static DBHashTable *
sdbh_open_S(const char * archivo,int mode,int flags)813 sdbh_open_S (const char *archivo, int mode, int flags) {
814 TRACE ("sdbh_open_S: %s\n", archivo);
815 DBHashTable *dbh;
816 int fd;
817 if(mode) {
818 fd = my_open (archivo, O_RDWR);
819 } else {
820 fd = my_open (archivo, O_RDONLY);
821 }
822
823
824
825 if(fd < 0) {
826 DBG ("open(%s) %s failed: %s\n", archivo, (mode)?"O_RDWR":"O_RDONLY", strerror (errno));
827 return NULL;
828 }
829 dbh = (DBHashTable *) malloc (sizeof (DBHashTable));
830 if (dbh == NULL) {
831 DBG( "malloc(%ld) failed: %s\n", (long)sizeof (DBHashTable), strerror(errno));
832 close(fd);
833 return NULL;
834 }
835 memset (dbh, 0, sizeof (DBHashTable));
836 dbh->lock_attempt_limit = open_timeout;
837 dbh->fd = fd;
838
839 /////////////////////////////////////////////
840 #ifdef PARALLEL_SAFE
841 if (flags & DBH_PARALLEL_SAFE){
842 char *nsem_name = sem_name(archivo);
843 if (!nsem_name) {
844 DBG( "sem_name(%s) failed: %s\n", archivo, strerror(errno));
845 dbh_close(dbh);
846 return NULL;
847 }
848 dbh->sem = sem_open(nsem_name, O_CREAT, 0700, 1);
849 free(nsem_name);
850 dbh->lock_p = open_shm_lock(archivo);
851 }
852 #endif
853
854 dbh->head_info = (dbh_header_t *) malloc (sizeof (dbh_header_t));
855 if (dbh->head_info == NULL) {
856 DBG( "malloc(%ld) failed: %s\n", (long)sizeof (dbh_header_t), strerror(errno));
857 dbh_close(dbh);
858 return NULL;
859 }
860 FILE_POINTER eof = place_eof (dbh);
861 if(eof < 0) {
862 DBG( "place_eof(%s) failed: %s\n", archivo, strerror(errno));
863 dbh_close(dbh);
864 return NULL;
865 }
866
867 dbh->path = (char *)malloc (strlen (archivo) + 1);
868 if (dbh->path == NULL) {
869 DBG( "malloc(%ld) failed: %s\n", (long)(strlen (archivo) + 1), strerror(errno));
870 dbh_close(dbh);
871 return NULL;
872 }
873 strcpy (dbh->path, archivo);
874
875 if(!sdbh_readheader (dbh)) {
876 dbh_close(dbh);
877 DBG( "readheader(%s) failed: %s\n", archivo, strerror(errno));
878 return NULL;
879 }
880 dbh->operate = sdbh_operate;
881 dbh->branch = (FILE_POINTER *) malloc (dbh->head_info->n_limit * sizeof (FILE_POINTER));
882 if (dbh->branch == NULL) {
883 ERR( "malloc dbh->branch: %s\n", strerror(errno));
884 dbh_close(dbh);
885 return NULL;
886 }
887 dbh->newbranch = (FILE_POINTER *) malloc (dbh->head_info->n_limit * sizeof (FILE_POINTER));
888 if (dbh->newbranch == NULL) {
889 ERR( "malloc dbh->newbranch: %s\n", strerror(errno));
890 dbh_close(dbh);
891 return NULL;
892 }
893 dbh->key = (unsigned char *)malloc (dbh->head_info->n_limit);
894 if (dbh->key == NULL) {
895 ERR( "malloc dbh->key: %s\n", strerror(errno));
896 dbh_close(dbh);
897 return NULL;
898 }
899 dbh->newkey = (unsigned char *)malloc (dbh->head_info->n_limit);
900 if (dbh->newkey == NULL) {
901 ERR( "malloc dbh->newkey: %s\n", strerror(errno));
902 dbh_close(dbh);
903 return NULL;
904 }
905 if(mode == WRITE)
906 dbh->head_info->writeOK = 1;
907 else
908 dbh->head_info->writeOK = 0;
909 sdbh_size (dbh, (int)dbh->head_info->record_length);
910 DBG (" opened %s \n", archivo);
911 return dbh;
912 } /****************************************************************************/
913
914 static void
sdbh_cuenta(unsigned char * numero,unsigned char orden,FILE_POINTER cuanto)915 sdbh_cuenta (unsigned char *numero, unsigned char orden, FILE_POINTER cuanto) {
916 unsigned char q;
917 FILE_POINTER m;
918 if(orden == 0)
919 numero[0] = 0;
920 if(orden == 1)
921 numero[0] = (unsigned char)cuanto;
922 q = sdbh_cuantumR (cuanto, orden, &m); /* en que cuantum estamos */
923 orden--;
924 sdbh_cifra (numero, q, orden, &m);
925 /* sdbh_cifra(numero,q,orden-1,&m);*/
926 } /***********************************************************************/
927
928 #define RECORD_EXTENT ( 2 + sizeof(FILE_POINTER)*(*how_many_branches+1) + dbh->head_info->n_limit + the_user_databytes )
929 static FILE_POINTER
sdbh_write(char newinfo,DBHashTable * dbh,unsigned char write_branches)930 sdbh_write (char newinfo, DBHashTable * dbh, unsigned char write_branches) {
931 TRACE ("sdbh_write\n");
932 int i;
933 void *the_data;
934 unsigned char *how_many_branches;
935 FILE_POINTER the_user_databytes;
936 FILE_POINTER *the_branches;
937 unsigned char *the_key;
938 if(newinfo) {
939 the_branches = dbh->newbranch;
940 } else {
941 the_branches = dbh->branch;
942 }
943 the_data = dbh->data;
944 how_many_branches = &(dbh->newbranches);
945 the_user_databytes = dbh->bytes_userdata;
946 the_key = dbh->key;
947
948 if(the_user_databytes > dbh->head_info->record_length) {
949 ERR(
950 "dbh->bytes_userdata (%lld) is greater than dbh->head_info->record_length (%lld). This is wrong and I stubbornly refuse to write\n",
951 (long long)dbh->bytes_userdata, (long long)dbh->head_info->record_length);
952 ERR("*** sdbh_write() error 1\n");
953 return 0;
954 }
955 DBG("Starting write at offset %lld\n", (long long)lseek(dbh->fd, 0, SEEK_CUR));
956 if(write (dbh->fd, how_many_branches, 1) != 1){
957 ERR("*** sdbh_write() error 2\n");
958 return 0;
959 }
960 if(write (dbh->fd, &(dbh->flag), 1) != 1){
961 ERR("*** sdbh_write() error 3\n");
962 return 0;
963 }
964
965 i = write (dbh->fd, &the_user_databytes, sizeof (FILE_POINTER));
966 if(i != sizeof (FILE_POINTER)){
967 ERR("*** sdbh_write() error 4\n");
968 return 0;
969 }
970
971 if(write_branches) {
972 #ifdef TURN
973 for(i = 0; i < *how_many_branches; i++)
974 the_branches[i] = sdbh_turnaround (the_branches[i]);
975 #endif
976 i = write (dbh->fd, the_branches, sizeof (FILE_POINTER) * (*how_many_branches));
977 if(i != sizeof (FILE_POINTER) * (*how_many_branches)){
978 ERR("*** sdbh_write() error 5\n");
979 return 0;
980 }
981
982 #ifdef TURN
983 for(i = 0; i < *how_many_branches; i++)
984 the_branches[i] = sdbh_turnaround (the_branches[i]);
985 #endif
986 } else {
987 if(!advance_fp (dbh, *how_many_branches * sizeof (FILE_POINTER))){
988 ERR("*** sdbh_write() error 6\n");
989 return 0;
990 }
991
992
993 }
994 if(write (dbh->fd, the_key, dbh->head_info->n_limit) != dbh->head_info->n_limit) {
995 ERR( "fwrite: %s\n", strerror (errno));
996 return 0;
997 }
998 if(the_user_databytes) {
999 if(dbh->head_info->reservedC){
1000 the_user_databytes = write (dbh->fd, the_data, dbh->head_info->record_length);
1001 } else {
1002 the_user_databytes = write (dbh->fd, the_data, the_user_databytes);
1003 }
1004 return (the_user_databytes);
1005 }
1006 NOOP("*** sdbh_write() Data length for record is zero.\n");
1007 return (0);
1008
1009 } /************************************************************************************/
1010
1011 static int
sdbh_read(char newinfo,DBHashTable * dbh,unsigned char read_data)1012 sdbh_read (char newinfo, DBHashTable * dbh, unsigned char read_data) {
1013 TRACE ("sdbh_read\n");
1014 unsigned char keylength;
1015 void *the_data;
1016 unsigned char *how_many_branches;
1017 FILE_POINTER *the_user_databytes;
1018 FILE_POINTER *the_branches;
1019 unsigned char *the_key;
1020 if(newinfo) {
1021 the_branches = dbh->newbranch;
1022 the_data = dbh->newdata;
1023 how_many_branches = &(dbh->newbranches);
1024 the_user_databytes = &(dbh->newbytes_userdata);
1025 the_key = dbh->newkey;
1026 } else {
1027 the_branches = dbh->branch;
1028 the_data = dbh->data;
1029 how_many_branches = &(dbh->branches);
1030 the_user_databytes = &(dbh->bytes_userdata);
1031 the_key = dbh->key;
1032 }
1033 keylength = dbh->head_info->n_limit;
1034
1035 if (DBH_MAXIMUM_RECORD_SIZE(dbh) < 16 * 4096) {
1036 /* new code: reduce read() call count from 3 to 1,
1037 * but only with reasonable maximum data size (stack size is limited)
1038 * the value 16 * 4096 is arbitrary, but sounds OK. */
1039 /*
1040 * Minimum bytes to read: 2+sizeof(FILE_POINTER)
1041 * (unsigned char, unsigned char, FILE_POINTER)
1042 * Maximum bytes to read: 2+sizeof(FILE_POINTER) + 256 + 256 * sizeof(FILE_POINTER)
1043 * (add 256 FILE_POINTERs and 256 unsigned chars for the key and maximum data size)
1044 * */
1045 int min_bytes = 2+sizeof(FILE_POINTER);
1046 int max_bytes = min_bytes + 256 + (256 * sizeof(FILE_POINTER)) + DBH_MAXIMUM_RECORD_SIZE(dbh);
1047 unsigned char buffer[max_bytes];
1048 int bytes = read (dbh->fd, buffer, max_bytes);
1049 if (bytes < min_bytes){
1050 DBG ("read error 2.1.1 (on empty dbh file this is OK)\n");
1051 return 0;
1052 }
1053 memcpy(how_many_branches, buffer, 1);
1054 memcpy(&(dbh->flag), buffer+1, 1);
1055 memcpy (the_user_databytes, buffer+2, sizeof(FILE_POINTER));
1056 #ifdef TURN
1057 *the_user_databytes = sdbh_turnaround (*the_user_databytes);
1058 #endif
1059
1060 if(*the_user_databytes > dbh->head_info->record_length) {
1061 ERR("sdbh_read(): user databytes is greater than head_info->record_length. This should not happen.\n");
1062 return 0;
1063 }
1064 if(*the_user_databytes == 0) {
1065 DBG ( "dbh_RECORD_SIZE() == 0. If this is not intentional, use dbh_set_recordsize() to set record size for %s.\n",
1066 dbh->path);
1067 return 0;
1068 }
1069 int structure_buffer_size = (sizeof (FILE_POINTER) * (*how_many_branches)) + keylength;
1070 int correct_bytes = min_bytes + structure_buffer_size + *the_user_databytes;
1071 if(bytes < correct_bytes) {
1072 ERR ("fread error 2.4\n");
1073 return 0;
1074 }
1075 void *structure_buffer = buffer + min_bytes;
1076 memcpy(the_branches, structure_buffer, structure_buffer_size - keylength);
1077 memcpy(the_key, structure_buffer + (structure_buffer_size - keylength), keylength);
1078 #ifdef TURN
1079 {
1080 int i; for(i = 0; i < *how_many_branches; i++)
1081 the_branches[i] = sdbh_turnaround (the_branches[i]);
1082 }
1083 #endif
1084 if(read_data) {
1085 memcpy(the_data, structure_buffer + structure_buffer_size, *the_user_databytes);
1086 }
1087 } else {
1088 int buffer_size = 2+sizeof(FILE_POINTER);
1089 unsigned char buffer[buffer_size];
1090 if(read (dbh->fd, buffer, buffer_size) != buffer_size) {
1091 DBG ("read error 2.1.1 (on empty dbh file this is OK)\n");
1092 return 0;
1093 }
1094 memcpy(how_many_branches, buffer, 1);
1095 memcpy(&(dbh->flag), buffer+1, 1);
1096 memcpy (the_user_databytes, buffer+2, sizeof(FILE_POINTER));
1097 #ifdef TURN
1098 *the_user_databytes = sdbh_turnaround (*the_user_databytes);
1099 #endif
1100
1101 if(*the_user_databytes > dbh->head_info->record_length) {
1102 ERR("sdbh_read(): user databytes is greater than head_info->record_length. This should not happen.\n");
1103 return 0;
1104 }
1105 if(*the_user_databytes == 0) {
1106 ERR ( "dbh_RECORD_SIZE() == 0. If this is not intentional, use dbh_set_recordsize() to set record size for %s.\n", dbh->path);
1107 return 0;
1108 }
1109
1110 int structure_buffer_size = (sizeof (FILE_POINTER) * (*how_many_branches)) + keylength;
1111 unsigned char structure_buffer[structure_buffer_size];
1112 if(read (dbh->fd, structure_buffer, structure_buffer_size) != structure_buffer_size) {
1113 ERR ("fread error 2.4\n");
1114 return 0;
1115 }
1116 memcpy(the_branches, structure_buffer, structure_buffer_size - keylength);
1117 memcpy(the_key, structure_buffer + (structure_buffer_size - keylength), keylength);
1118 #ifdef TURN
1119 {
1120 int i; for(i = 0; i < *how_many_branches; i++)
1121 the_branches[i] = sdbh_turnaround (the_branches[i]);
1122 }
1123 #endif
1124 // This may be a very big read, better left by itself.
1125 if(read_data) {
1126 // if data is tainted, there will be no overrun since value is checked against
1127 // dbh->head_info->record_length above.
1128 // coverity[tainted_data : FALSE]
1129 if(read (dbh->fd, the_data, *the_user_databytes) != *the_user_databytes) {
1130 ERR ("fread error 2.51: blocksize=%lld\n", (long long)(*the_user_databytes));
1131
1132 return 0;
1133 }
1134 }
1135 }
1136 //
1137 return 1;
1138 } /************************************************************************************/
1139
1140 static int
sdbh_readheader(DBHashTable * dbh)1141 sdbh_readheader (DBHashTable * dbh) {
1142 TRACE ("sdbh_readheader\n");
1143 if(!place_fp_at (dbh, (off_t)0)) {
1144 ERR("*** sdbh_readheader() error 1; !place_fp_at (dbh, 0)\n");
1145 return 0;
1146 }
1147 // dbh->head_info is *not* a string. It is a fixed length structure
1148 // coverity[string_null_argument : FALSE]
1149 size_t bytes = read (dbh->fd, (void *)(dbh->head_info), sizeof (dbh_header_t));
1150
1151 if (bytes != sizeof (dbh_header_t)) {
1152 ERR( "Failed to read header for %s: %s\nsizeof (dbh_header_t)=%ld read=%ld\n",
1153 dbh->path, strerror (errno),
1154 (long)sizeof (dbh_header_t), (long)bytes);
1155 return 0;
1156 }
1157 if(strncmp (dbh->head_info->version, DBH_FILE_VERSION, 15) != 0) {
1158 ERR(
1159 "Failed to read header for %s at sdbh_readheader(): strncmp (\"%s\",\"%s\")\n",
1160 dbh->path, dbh->head_info->version, DBH_FILE_VERSION);
1161 return 0;
1162 }
1163 /* volatile values: */
1164 dbh->head_info->user_tmpdir = 0;
1165
1166 #ifdef TURN
1167 dbh->head_info->bof = sdbh_turnaround (dbh->head_info->bof);
1168 dbh->head_info->record_length = sdbh_turnaround (dbh->head_info->record_length);
1169 dbh->head_info->total_space = sdbh_turnaround (dbh->head_info->total_space);
1170 dbh->head_info->data_space = sdbh_turnaround (dbh->head_info->data_space);
1171 dbh->head_info->erased_space = sdbh_turnaround (dbh->head_info->erased_space);
1172 dbh->head_info->records = sdbh_turnaround (dbh->head_info->records);
1173 #endif
1174 return 1;
1175 } /************************************************************************************/
1176
1177 #ifdef TURN
1178 static FILE_POINTER
sdbh_turnaround(FILE_POINTER x)1179 sdbh_turnaround (FILE_POINTER x) {
1180 char *where,
1181 temp;
1182 where = (char *)&x;
1183 temp = where[0];
1184 where[0] = where[3];
1185 where[3] = temp;
1186 temp = where[1];
1187 where[1] = where[2];
1188 where[2] = temp;
1189 return x;
1190 } /************************************************************************************/
1191 #endif
1192
1193 static FILE_POINTER
sdbh_z(unsigned char n,unsigned char m)1194 sdbh_z (unsigned char n, unsigned char m) { /* n=cuantum m=orden */
1195 FILE_POINTER s = 0;
1196 unsigned char i;
1197 if(m < 2)
1198 return 1;
1199 if(m == 2)
1200 return (n + 1);
1201 m--;
1202 for(i = n; i > 0; i--)
1203 s += sdbh_z (i, m);
1204 /* for (i=n;i>0;i--) s += sdbh_z(i,m-1);*/
1205 return (s + 1);
1206 } /************************************************************************************/
1207
1208 static unsigned char
sdbh_cuantumR(FILE_POINTER cuanto,unsigned char orden,FILE_POINTER * m)1209 sdbh_cuantumR (FILE_POINTER cuanto, unsigned char orden, FILE_POINTER * m) {
1210 unsigned char i;
1211 FILE_POINTER ztotal,
1212 grandtotal = 0;
1213 for(i = 0; 1; i++) {
1214 if(i == orden)
1215 ztotal = grandtotal;
1216 else
1217 ztotal = sdbh_z (i, orden);
1218 grandtotal += ztotal;
1219 if(cuanto <= grandtotal) {
1220 if(m)
1221 *m = grandtotal - cuanto + 1;
1222 break;
1223 }
1224 }
1225 return i;
1226 } /************************************************************************************/
1227
1228 static unsigned char
sdbh_cuantum(FILE_POINTER cuanto,unsigned char orden,FILE_POINTER * m)1229 sdbh_cuantum (FILE_POINTER cuanto, unsigned char orden, FILE_POINTER * m) {
1230 unsigned char i;
1231 FILE_POINTER ztotal,
1232 grandtotal = 0;
1233 for(i = 0; 1; i++) {
1234 if(i == orden)
1235 ztotal = grandtotal;
1236 else
1237 ztotal = sdbh_z (i, orden);
1238 grandtotal += ztotal;
1239 if(cuanto <= grandtotal)
1240 break;
1241 if(m)
1242 *m = cuanto - grandtotal;
1243 }
1244 return i;
1245 } /************************************************************************************/
1246
1247 static void
sdbh_cifra(unsigned char * numero,unsigned char q,unsigned char orden,FILE_POINTER * m)1248 sdbh_cifra (unsigned char *numero, unsigned char q, unsigned char orden, FILE_POINTER * m) {
1249 unsigned char subcuantum;
1250 int t;
1251 if(orden == 1) {
1252 t = q - (*m - 1);
1253 numero[0] = (unsigned char)t;
1254 /* numero[0]=q - (*m-1);*/
1255 t = *m - 1;
1256 numero[1] = (unsigned char)t;
1257 /* numero[1]= *m-1;*/
1258 return;
1259 }
1260 subcuantum = sdbh_cuantum (*m, orden, m);
1261 t = q - subcuantum;
1262 numero[0] = (unsigned char)t;
1263 /* numero[0]=q-subcuantum;*/
1264 orden--;
1265 sdbh_cifra (numero + 1, subcuantum, orden, m);
1266 /* sdbh_cifra(numero+1,subcuantum,orden-1,m); */
1267 return;
1268 } /************************************************************************************/
1269
1270 #if 0
1271 // legacy code
1272 static int
1273 sdbh_barrelong (DBHashTable * dbh, FILE_POINTER startadd, int ramas) {
1274 unsigned char i;
1275 if(dbh_load_address (dbh, startadd) == 0)
1276 return 0;
1277 if(dbh->head_info->dbh_exit)
1278 return 2;
1279 if(!ERASED || (ERASED && dbh->head_info->sweep_erased))
1280 (*(dbh->operate)) (dbh);
1281 if(ramas) {
1282 if((ramas = dbh->branches - ramas) < 0)
1283 ramas = 0;
1284 }
1285 for(i = dbh->branches; i > ramas; i--) {
1286 if(dbh->branch[i - 1])
1287 sdbh_barrelong (dbh, dbh->branch[i - 1], 0);
1288 dbh_load_address (dbh, startadd);
1289 }
1290 return 1;
1291 } /**********************************************************************/
1292
1293 static int
1294 sdbh_reversebarrelong (DBHashTable * dbh, FILE_POINTER startadd, int ramas) {
1295 int i;
1296 if(dbh_load_address (dbh, startadd) == 0)
1297 return 0;
1298 if(dbh->head_info->dbh_exit)
1299 return 2;
1300 if(!ERASED || (ERASED && dbh->head_info->sweep_erased))
1301 (*(dbh->operate)) (dbh);
1302 /* if (!ERASED) (*(dbh->operate))(dbh);*/
1303 if(ramas) {
1304 if((ramas = dbh->branches - ramas) < 0)
1305 ramas = 0;
1306 }
1307 for(i = ramas; i < dbh->branches; i++) {
1308 if(dbh->branch[i])
1309 sdbh_reversebarrelong (dbh, dbh->branch[i], 0);
1310 dbh_load_address (dbh, startadd);
1311 }
1312 return 1;
1313 } /******************************************************************************/
1314 #endif
1315
1316 static int
sdbh_reversebarre(DBHashTable * dbh,FILE_POINTER startadd,int ramas)1317 sdbh_reversebarre (DBHashTable * dbh, FILE_POINTER startadd, int ramas) {
1318 int i;
1319 unsigned char oldbranches;
1320 FILE_POINTER *oldbranch;
1321 if(dbh_load_address (dbh, startadd) == 0)
1322 return 0;
1323 if(dbh->head_info->dbh_exit)
1324 return 2;
1325 if(!ERASED || (ERASED && dbh->head_info->sweep_erased))
1326 (*(dbh->operate)) (dbh);
1327 /* if (!ERASED) (*(dbh->operate))(dbh);*/
1328 oldbranch = (FILE_POINTER *) malloc (dbh->branches * sizeof (FILE_POINTER));
1329 if (oldbranch == NULL) {
1330 ERR( "malloc oldbranch: %s\n", strerror(errno));
1331 return 0;
1332 }
1333 oldbranches = dbh->branches;
1334 if(ramas) {
1335 if((ramas = dbh->branches - ramas) < 0)
1336 ramas = 0;
1337 }
1338 #if 1
1339 for(i = 0; i < oldbranches; i++)
1340 oldbranch[i] = dbh->branch[i];
1341 for(i = ramas; i < oldbranches; i++)
1342 if(oldbranch[i])
1343 sdbh_reversebarre (dbh, oldbranch[i], 0);
1344 free (oldbranch);
1345 #else
1346 // legacy code
1347 if(oldbranch == NULL) fullmemory = 1;
1348 char fullmemory = 0;
1349 if(!fullmemory) {
1350 for(i = 0; i < oldbranches; i++)
1351 oldbranch[i] = dbh->branch[i];
1352 for(i = ramas; i < oldbranches; i++)
1353 if(oldbranch[i])
1354 sdbh_reversebarre (dbh, oldbranch[i], 0);
1355 free (oldbranch);
1356 } else
1357 for(i = ramas; i < oldbranches; i++) {
1358 if(dbh->branch[i])
1359 sdbh_reversebarrelong (dbh, dbh->branch[i], 0);
1360 dbh_load_address (dbh, startadd);
1361 }
1362 #endif
1363 return 1;
1364 } /******************************************************************************/
1365
1366 static int
sdbh_barre(DBHashTable * dbh,FILE_POINTER startadd,int ramas)1367 sdbh_barre (DBHashTable * dbh, FILE_POINTER startadd, int ramas) {
1368 unsigned char i;
1369 FILE_POINTER *oldbranch;
1370 if(dbh_load_address (dbh, startadd) == 0)
1371 return 0;
1372 if(dbh->head_info->dbh_exit)
1373 return 2;
1374 #if 0
1375 printf ("barre: currentseek at %lu\n", (long unsigned)startadd);
1376 printf ("record is erased? -> %d\n", ERASED);
1377 #endif
1378 if(!ERASED || (ERASED && dbh->head_info->sweep_erased))
1379 (*(dbh->operate)) (dbh);
1380 /* if (!ERASED) (*(dbh->operate))(dbh);*/
1381 oldbranch = (FILE_POINTER *) malloc (dbh->branches * sizeof (FILE_POINTER));
1382 if (oldbranch == NULL) {
1383 ERR( "malloc oldbranch: %s\n", strerror(errno));
1384 return 0;
1385 }
1386 if(ramas) {
1387 if((ramas = dbh->branches - ramas) < 0)
1388 ramas = 0;
1389 }
1390 #if 1
1391 for(i = 0; i < dbh->branches; i++)
1392 oldbranch[i] = dbh->branch[i];
1393 for(i = dbh->branches; i > ramas; i--)
1394 if(oldbranch[i - 1])
1395 sdbh_barre (dbh, oldbranch[i - 1], 0);
1396 free (oldbranch);
1397 #else
1398 // legacy code
1399 char fullmemory = 0;
1400 if(!fullmemory) {
1401 for(i = 0; i < dbh->branches; i++)
1402 oldbranch[i] = dbh->branch[i];
1403 for(i = dbh->branches; i > ramas; i--)
1404 if(oldbranch[i - 1])
1405 sdbh_barre (dbh, oldbranch[i - 1], 0);
1406 free (oldbranch);
1407 } else
1408 for(i = dbh->branches; i > ramas; i--) {
1409 if(dbh->branch[i - 1])
1410 sdbh_barrelong (dbh, dbh->branch[i - 1], 0);
1411 dbh_load_address (dbh, startadd);
1412 }
1413 #endif
1414 return 1;
1415 } /************************************************************************/
1416
1417 /* Functions: */
1418 static void
sdbh_transfer(DBHashTable * srcdbh)1419 sdbh_transfer (DBHashTable * srcdbh) {
1420 DBHashTable *dbh_desdbh = srcdbh->dbh_desdbh;
1421 dbh_desdbh->bytes_userdata = srcdbh->bytes_userdata;
1422 dbh_update (dbh_desdbh);
1423 /* if ((count++ % 100)==0) printf("\n %ld registros procesados",count);*/
1424 return;
1425 } /***************************************************************************/
1426
1427 /*****************************************************************************/
1428 /*** old non static functions ***/
1429 /*****************************************************************************/
1430
1431 static int
sdbh_size(DBHashTable * dbh,FILE_POINTER record_length)1432 sdbh_size (DBHashTable * dbh, FILE_POINTER record_length) {
1433
1434 /* despues de abrir DBHashTable */
1435 if(dbh == NULL) {
1436 ERR( "sdbh_size(): dbh != NULL not met\n");
1437 return 0;
1438 }
1439 if(dbh->head_info == NULL) {
1440 ERR( "sdbh_size(): dbh->head_info != NULL not met\n");
1441 return 0;
1442 }
1443
1444 if(record_length < dbh->head_info->record_length) {
1445 /*
1446 ERR ("sdbh_size(): may not shrink! current size=%lld requested size=%ld\n",
1447 (long long)dbh->head_info->record_length, (long)record_length);
1448 */
1449 return 0;
1450 }
1451
1452 void *data = malloc (record_length);
1453 if (data == NULL) {
1454 ERR( "malloc data: %s\n", strerror(errno));
1455 return 0;
1456 }
1457 void *newdata = malloc (record_length);
1458 if (newdata == NULL) {
1459 free(data);
1460 ERR( "malloc newdata: %s\n", strerror(errno));
1461 return 0;
1462 }
1463 memset (data, 0, record_length);
1464 memset (newdata, 0, record_length);
1465 if(dbh->data != NULL) {
1466 memcpy (data, dbh->data, dbh->head_info->record_length);
1467 free (dbh->data);
1468 }
1469 if(dbh->newdata != NULL) {
1470 memcpy (newdata, dbh->newdata, dbh->head_info->record_length);
1471 free (dbh->newdata);
1472 }
1473 dbh->data = data;
1474 dbh->newdata = newdata;
1475
1476 if (dbh->head_info->record_length != record_length) {
1477 dbh->head_info->record_length = record_length;
1478 if(dbh->head_info->writeOK) sdbh_writeheader (dbh, 1);
1479 }
1480 return 1;
1481 } /****************************************************************************************/
1482
1483 #if 0
1484 // legacy code
1485 static int
1486 sdbh_barrelong2 (DBHashTable * dbh, DBHashFunc2 operate, void *data,
1487 FILE_POINTER startadd, int ramas) {
1488 unsigned char i;
1489 if(dbh_load_address (dbh, startadd) == 0)
1490 return 0;
1491 if(dbh->head_info->dbh_exit)
1492 return 2;
1493 if(!ERASED || (ERASED && dbh->head_info->sweep_erased))
1494 (*(dbh->operate)) (dbh);
1495 if(ramas) {
1496 if((ramas = dbh->branches - ramas) < 0)
1497 ramas = 0;
1498 }
1499 for(i = dbh->branches; i > ramas; i--) {
1500 if(dbh->branch[i - 1])
1501 sdbh_barrelong2 (dbh, operate, data, dbh->branch[i - 1], 0);
1502 dbh_load_address (dbh, startadd);
1503 }
1504 return 1;
1505 } /**********************************************************************/
1506 #endif
1507
1508 static int
sdbh_barre2(DBHashTable * dbh,DBHashFunc2 operate,void * data,FILE_POINTER startadd,int ramas)1509 sdbh_barre2 (DBHashTable * dbh, DBHashFunc2 operate, void *data,
1510 FILE_POINTER startadd, int ramas) {
1511 unsigned char i;
1512 FILE_POINTER *oldbranch;
1513 if(dbh_load_address (dbh, startadd) == 0)
1514 return 0;
1515 if(dbh->head_info->dbh_exit)
1516 return 2;
1517 #if 0
1518 printf ("barre: currentseek at %lu\n", (long unsigned)startadd);
1519 printf ("record is erased? -> %d\n", ERASED);
1520 #endif
1521 if(!ERASED || (ERASED && dbh->head_info->sweep_erased))
1522 (operate) (dbh, data);
1523 /* if (!ERASED) (*(dbh->operate))(dbh);*/
1524 oldbranch = (FILE_POINTER *) malloc (dbh->branches * sizeof (FILE_POINTER));
1525 if (oldbranch == NULL) {
1526 ERR( "malloc oldbranch: %s\n", strerror(errno));
1527 return 0;
1528 }
1529 if(ramas) {
1530 if((ramas = dbh->branches - ramas) < 0)
1531 ramas = 0;
1532 }
1533 #if 1
1534 for(i = 0; i < dbh->branches; i++)
1535 oldbranch[i] = dbh->branch[i];
1536 for(i = dbh->branches; i > ramas; i--)
1537 if(oldbranch[i - 1])
1538 sdbh_barre2 (dbh, operate, data, oldbranch[i - 1], 0);
1539 free (oldbranch);
1540 #else
1541 // legacy code
1542 char fullmemory = 0;
1543 if(!fullmemory)
1544 {
1545 for(i = 0; i < dbh->branches; i++)
1546 oldbranch[i] = dbh->branch[i];
1547 for(i = dbh->branches; i > ramas; i--)
1548 if(oldbranch[i - 1])
1549 sdbh_barre2 (dbh, operate, data, oldbranch[i - 1], 0);
1550 free (oldbranch);
1551 } else
1552 for(i = dbh->branches; i > ramas; i--) {
1553 if(dbh->branch[i - 1])
1554 sdbh_barrelong2 (dbh, operate, data, dbh->branch[i - 1], 0);
1555 dbh_load_address (dbh, startadd);
1556 }
1557 #endif
1558 return 1;
1559 } /************************************************************************/
1560
1561
1562 static int
sdbh_newbarre2(DBHashTable * dbh,DBHashFunc2 operate,void * data)1563 sdbh_newbarre2 (DBHashTable * dbh, DBHashFunc2 operate, void *data) {
1564 if(!dbh) {
1565 ERR( "sdbh_newbarre(): %s\n", strerror (EBADF));
1566 return 0;
1567 }
1568
1569 dbh->head_info->dbh_exit = 0;
1570 sdbh_barre2 (dbh, operate, data, dbh->head_info->bof, 0);
1571
1572
1573
1574 return 1;
1575 } /***************************************************************************************/
1576
1577 static int
sdbh_newbarre(DBHashTable * dbh,unsigned char * key1,unsigned char * key2,unsigned char keylength)1578 sdbh_newbarre (DBHashTable * dbh, unsigned char *key1, unsigned char *key2, unsigned char keylength) {
1579 int i;
1580 FILE_POINTER pointer;
1581 if(!dbh) {
1582 ERR( "sdbh_newbarre(): %s\n", strerror (EBADF));
1583
1584 return 0;
1585 }
1586
1587 dbh->head_info->dbh_exit = 0;
1588 if(key1 == NULL) {
1589 sdbh_barre (dbh, dbh->head_info->bof, 0);
1590 return 1;
1591 }
1592 if(key2 != NULL) {
1593 memcpy ((void *)(dbh->key), (void *)key1, dbh->head_info->n_limit);
1594
1595 for(i = 0; i < dbh->head_info->n_limit; i++)
1596 if(key1[i] != key2[i])
1597 break;
1598 /* que pedo con ERASED?? (load returns errorvalue on ERASED */
1599 pointer = dbh_load (dbh);
1600 if((pointer == 0) && !(ERASED))
1601 return 0;
1602 /* if ((pointer=dbh_load(dbh)) == 0) return 0;*/
1603 /* aqui hay que considerar que el nodo puede estar marcado como ERASED */
1604 else {
1605 pointer = dbh_find (dbh, i);
1606 sdbh_barre (dbh, pointer, dbh->head_info->n_limit - i);
1607 }
1608 } else if(keylength) {
1609 memcpy ((void *)(dbh->key), (void *)key1, keylength);
1610 pointer = dbh_find (dbh, keylength);
1611 if(pointer == 0)
1612 return 0;
1613 sdbh_barre (dbh, pointer, dbh->head_info->n_limit - keylength);
1614 }
1615 return 1;
1616 } /***************************************************************************************/
1617
1618 static int
sdbh_newreversebarre(DBHashTable * dbh,unsigned char * key1,unsigned char * key2,unsigned char keylength)1619 sdbh_newreversebarre (DBHashTable * dbh, unsigned char *key1, unsigned char *key2, unsigned char keylength) {
1620 int i;
1621 FILE_POINTER pointer;
1622 if(!dbh) {
1623 ERR( "sdbh_newreversebarre(): %s\n", strerror (EBADF));
1624
1625 return 0;
1626 }
1627
1628 dbh->head_info->dbh_exit = 0;
1629 if(key1 == NULL) {
1630 sdbh_reversebarre (dbh, dbh->head_info->bof, 0);
1631 return 1;
1632 }
1633 if(key2 != NULL) {
1634 memcpy ((void *)(dbh->key), (void *)key1, dbh->head_info->n_limit);
1635 for(i = 0; i < dbh->head_info->n_limit; i++)
1636 if(key1[i] != key2[i])
1637 break;
1638 /* que pedo con ERASED?? (load returns errorvalue on ERASED */
1639 pointer = dbh_load (dbh);
1640 if((pointer == 0) && !(ERASED))
1641 return 0;
1642 /* if ((pointer=dbh_load(dbh)) == 0) return 0;*/
1643 else {
1644 pointer = dbh_find (dbh, i);
1645 sdbh_reversebarre (dbh, pointer, i);
1646 }
1647 } else if(keylength != 0) {
1648 memcpy ((void *)dbh->key, (void *)key1, keylength);
1649
1650 pointer = dbh_find (dbh, keylength);
1651 if(pointer == 0)
1652 return 0;
1653 sdbh_reversebarre (dbh, pointer, keylength);
1654 }
1655 return 1;
1656 } /************************************************************************************/
1657
1658 static DBHashTable *
sdbh_regen(DBHashTable * dbh,int sweep)1659 sdbh_regen (DBHashTable * dbh, int sweep) {
1660 void *temp, *newtemp;
1661 char *archivo2, *archivo;
1662 DBHashTable *newdbh;
1663 unsigned char *tempkey, *newtempkey;
1664 void (*fun) (DBHashTable *);
1665
1666 if(!dbh) {
1667 ERR( "sdbh_regen(): %s\n", strerror (EBADF));
1668 return NULL;
1669 }
1670 if (dbh->protection_flags & DBH_READ_ONLY){
1671 ERR( "DBH table is read only: %s\n", dbh->path);
1672 return NULL;
1673 }
1674 dbh_lock_write (dbh);
1675
1676 archivo2 = sdbh_randomfilename (dbh, 's');
1677 if (!archivo2){
1678 ERR( "Cannot open temporary file: DBHashtable will not be regenerated\n");
1679 return NULL;
1680 }
1681
1682 archivo = (char *)malloc (strlen (dbh->path) + 1);
1683 if (archivo == NULL) {
1684 ERR( "malloc(%ld): %s\n", (long)(strlen (dbh->path) + 1), strerror(errno));
1685 free(archivo2);
1686 return NULL;
1687 }
1688 strcpy (archivo, dbh->path);
1689 struct stat st_old;
1690 // No problem with TOCTOU, since at TOU, rename will return error
1691 // if synchronization mismatch occurs.
1692 // coverity[fs_check_call : FALSE]
1693 if (stat (archivo, &st_old) < 0){
1694 ERR( "unable to stat: %s\n", archivo);
1695 free(archivo);
1696 free(archivo2);
1697 return NULL;
1698 }
1699
1700 char *archivobak = (char *)malloc (strlen (archivo) + strlen (".bak") + 1);
1701 if (archivobak == NULL) {
1702 free(archivo);
1703 free(archivo2);
1704 ERR( "malloc archivobak: %s\n", strerror(errno));
1705 return NULL;
1706 }
1707 sprintf (archivobak, "%s.bak", archivo);
1708
1709 // Set thread safe characteristics to new table.
1710 int flags = dbh->protection_flags & (DBH_PARALLEL_SAFE|DBH_THREAD_SAFE);
1711 DBHashTable *dbh_desdbh = sdbh_create (archivo2, dbh->head_info->n_limit, flags);
1712 if(!dbh_desdbh) {
1713 ERR( "Cannot open for write: %s\n", archivo2);
1714 free(archivo);
1715 free(archivo2);
1716 free(archivobak);
1717 return NULL;
1718 }
1719
1720 struct stat st_new;
1721 // No problem with TOCTOU, since at TOU, rename will return error
1722 // if synchronization mismatch occurs.
1723 // coverity[fs_check_call : FALSE]
1724 if (stat (archivo2, &st_new) < 0){
1725 ERR( "unable to stat: %s\n", archivo2);
1726 free(archivo);
1727 free(archivo2);
1728 free(archivobak);
1729 dbh_close(dbh_desdbh);
1730 return NULL;
1731 }
1732 dbh_lock_write (dbh_desdbh);
1733
1734
1735 dbh->dbh_desdbh = dbh_desdbh;
1736
1737 tempkey = dbh_desdbh->key;
1738 newtempkey = dbh_desdbh->newkey;
1739 temp = dbh_desdbh->data;
1740 newtemp = dbh_desdbh->newdata;
1741 dbh_desdbh->key = dbh->key;
1742 dbh_desdbh->newkey = dbh->newkey;
1743 dbh_desdbh->data = dbh->data;
1744 dbh_desdbh->newdata = dbh->newdata;
1745
1746
1747
1748 dbh_desdbh->head_info->record_length = dbh->head_info->record_length;
1749 fun = dbh->operate;
1750
1751 dbh->operate = sdbh_transfer;
1752 if(sweep) {
1753 sdbh_newbarre (dbh, NULL, NULL, 0);
1754 } else {
1755 sdbh_newreversebarre (dbh, NULL, NULL, 0);
1756 }
1757
1758 dbh_desdbh->data = temp;
1759 dbh_desdbh->newdata = newtemp;
1760 dbh_desdbh->key = tempkey;
1761 dbh_desdbh->newkey = newtempkey;
1762
1763 dbh_unlock_write (dbh_desdbh);
1764 dbh_close (dbh_desdbh);
1765 dbh_unlock_write (dbh);
1766 dbh_close (dbh);
1767
1768
1769
1770
1771 if(unlink (archivobak) < 0 && errno != ENOENT) {
1772 ERR( "cannot remove old backup file: %s (%s)\n",
1773 archivobak, strerror(errno));
1774 }
1775
1776 DBG ("rename %s %s\n", archivo, archivobak);
1777 if(rename (archivo, archivobak) < 0) {
1778 ERR( "*** DBH: cannot rename %s to %s (%s)\n",
1779 archivo, archivobak, strerror (errno)); ;
1780 }
1781 free (archivobak);
1782
1783 if(st_old.st_dev == st_new.st_dev) {
1784 DBG (" rename %s %s\n", archivo2, archivo);
1785 if(rename (archivo2, archivo) < 0) {
1786 ERR( "*** DBH: cannot rename %s to %s (%s)\n",
1787 archivo2, archivo, strerror (errno));
1788 }
1789 } else {
1790 DBG (" mv %s %s\n", archivo2, archivo);
1791 #ifdef HAVE_FORK
1792 pid_t pid = fork ();
1793 if(!pid) {
1794 execlp ("mv", "mv", archivo2, archivo, NULL);
1795 _exit (123);
1796 } else {
1797 int status;
1798 waitpid (pid, &status, 0);
1799 }
1800 #else
1801 # ifdef HAVE__SPAWNVP
1802 const int mode = P_WAIT; // also P_NOWAIT
1803 const char *_argv[]={"copy", archivo2, archivo, NULL};
1804 const char *argv0 = _argv[0];
1805 _spawnvp (mode, argv0, _argv);
1806 # else
1807 ERR( "Cannot regenerate %s\n", archivo);
1808 free (archivo);
1809 free (archivo2);
1810 return NULL;
1811 # endif
1812 #endif
1813 }
1814
1815 newdbh = dbh_new (archivo, NULL, flags);
1816 free (archivo);
1817 free (archivo2);
1818 newdbh->operate = fun;
1819 return newdbh;
1820 }
1821
1822 static void
prune_mark_erased(DBHashTable * dbh)1823 prune_mark_erased (DBHashTable * dbh) {
1824 SET_ERASED;
1825 /* set file pointer at record flag byte */
1826 if(place_fp_at (dbh, (off_t)((dbh->reservedB) + 1)) < 0) {
1827 return;
1828 }
1829 /* write the flag to the file */
1830 /* printf("flag for erase=0x%x\n",dbh->flag); */
1831 if(write (dbh->fd, &(dbh->flag), 1) != 1) {
1832 ERR( "unable to erase: %s\n", strerror (errno));
1833 return;
1834 }
1835 /*printf("erasing %s flag at %lu\n",(char *)dbh->data,
1836 (long unsigned)(dbh->reservedB+1)); */
1837 /* update file header information */
1838 dbh->head_info->data_space -= dbh->bytes_userdata;
1839 dbh->head_info->erased_space += (dbh->bytes_userdata);
1840 return;
1841 }
1842
1843 static void
prune_mark_unerased(DBHashTable * dbh)1844 prune_mark_unerased (DBHashTable * dbh) {
1845 SET_UNERASED;
1846 /* set file pointer at record flag byte */
1847 if(place_fp_at (dbh, (off_t)(dbh->reservedB + 1)) < 0){
1848 return;
1849 }
1850 /* write the flag to the file */
1851 if(write (dbh->fd, &(dbh->flag), 1) != 1) {
1852 ERR( "unable to unerase: %s\n", strerror (errno));
1853 return;
1854 }
1855 /* update file header information */
1856 dbh->head_info->data_space += dbh->bytes_userdata;
1857 dbh->head_info->erased_space -= (dbh->bytes_userdata);
1858 return;
1859 }
1860
1861
sdbh_writeheader(DBHashTable * dbh,int flush)1862 static int sdbh_writeheader (DBHashTable * dbh, int flush) {
1863 TRACE("sdbh_writeheader\n");
1864 if(!dbh || !(dbh->head_info)) {
1865 ERR("sdbh_writeheader(): %s\n", strerror (EBADF));
1866 return 0;
1867 }
1868 if(!(dbh->head_info->writeOK)){
1869 ERR("sdbh_writeheader() is invalid in a read only DBH Table\n");
1870 return 0;
1871 }
1872
1873 if(strlen (COPYRIGHT) > 127) {
1874 ERR("This should never happen, strlen(\"%s\")>127\n", COPYRIGHT);
1875 return 0;
1876 }
1877 if (!strlen(dbh->head_info->copyright)){
1878 strcpy ((char *)(dbh->head_info->copyright), COPYRIGHT);
1879 }
1880
1881 #ifdef TURN
1882 dbh->head_info->bof = sdbh_turnaround (dbh->head_info->bof);
1883 dbh->head_info->record_length = sdbh_turnaround (dbh->head_info->record_length);
1884 dbh->head_info->total_space = sdbh_turnaround (dbh->head_info->total_space);
1885 dbh->head_info->data_space = sdbh_turnaround (dbh->head_info->data_space);
1886 dbh->head_info->erased_space = sdbh_turnaround (dbh->head_info->erased_space);
1887 dbh->head_info->records = sdbh_turnaround (dbh->head_info->records);
1888 #endif
1889
1890
1891 dbh_lock_write (dbh);
1892 if(!place_fp_at (dbh, (off_t)0)){
1893 dbh_unlock_write (dbh);
1894 ERR("*** sdbh_writeheader(): error 1; cannot place at 0L\n");
1895 return 0;
1896 }
1897
1898
1899 size_t bytes = write (dbh->fd, (void *)dbh->head_info, sizeof (dbh_header_t));
1900 if(bytes != sizeof (dbh_header_t)) {
1901 dbh_unlock_write (dbh);
1902 ERR("*** sdbh_writeheader(): error 2; write count %lu != %lu\n",
1903 (long unsigned)sizeof (dbh_header_t),
1904 (long unsigned)bytes);
1905 return 0;
1906 }
1907 dbh_unlock_write (dbh);
1908
1909
1910 #ifdef TURN
1911 dbh->head_info->bof = sdbh_turnaround (dbh->head_info->bof);
1912 dbh->head_info->record_length = sdbh_turnaround (dbh->head_info->record_length);
1913 dbh->head_info->total_space = sdbh_turnaround (dbh->head_info->total_space);
1914 dbh->head_info->data_space = sdbh_turnaround (dbh->head_info->data_space);
1915 dbh->head_info->erased_space = sdbh_turnaround (dbh->head_info->erased_space);
1916 dbh->head_info->records = sdbh_turnaround (dbh->head_info->records);
1917 #endif
1918 if (!flush) return 1;
1919
1920 #if HAVE_FSYNC
1921 fsync(dbh->fd);
1922 #endif
1923 #if HAVE_WINDOWS_H
1924 FlushFileBuffers ((HANDLE) _get_osfhandle (dbh->fd));
1925 #endif
1926
1927 #ifdef DEBUG_TRACE
1928 dbh_header_t tmp;
1929 lseek(dbh->fd, 0, SEEK_SET);
1930 DBG("--- > testing written header... got %ld bytes\n",
1931 (long)read(dbh->fd, (void *)(&tmp), sizeof(dbh_header_t)));
1932 #endif
1933 return 1;
1934 }
1935
1936 #ifdef PARALLEL_SAFE
1937 static int
lock_it(DBHashTable * dbh,int for_write)1938 lock_it (DBHashTable * dbh, int for_write){
1939 TRACE("DBH: locking file %s (write = %d)\n", dbh->path, for_write);
1940 if (for_write) {
1941 dbh->lock_p->write_lock_count++;
1942 dbh->lock_p->write_lock = getpid();
1943 } else {
1944 dbh->lock_p->read_lock_count++;
1945 }
1946 if(msync (dbh->lock_p, sizeof(dbh_lock_t), MS_ASYNC) < 0){
1947 ERR("(2:lock_p=%p) Cannot msync shared memory item for %s: %s\n",
1948 dbh->lock_p, dbh->path, strerror (errno));
1949 }
1950 return 1;
1951 }
1952
1953 static int
lock_ok(DBHashTable * dbh,int for_write)1954 lock_ok (DBHashTable * dbh, int for_write){
1955 int lock_condition;
1956 if (for_write){
1957 lock_condition = (dbh->lock_p->read_lock_count ||
1958 (dbh->lock_p->write_lock_count && dbh->lock_p->write_lock != getpid()));
1959 } else {
1960 lock_condition = dbh->lock_p->write_lock_count;
1961 }
1962 if (lock_condition) return 0;
1963 return 1;
1964 }
1965
1966 static int
sdbh_lock(DBHashTable * dbh,int for_write)1967 sdbh_lock (DBHashTable * dbh, int for_write){
1968 if (!(dbh->protection_flags & DBH_PARALLEL_SAFE)){
1969 return 0;
1970 }
1971 if (dbh->lock_attempt_limit == 0) sem_wait(dbh->sem);
1972 else {
1973 struct timespec timeout;
1974 timeout.tv_sec = time(NULL) + dbh->lock_attempt_limit;
1975 timeout.tv_nsec = 0;
1976 if (sem_timedwait(dbh->sem, &timeout) < 0){
1977 ERR("DBH: sdbh_lock() unable to unlock semaphore for %s (%s), proceeding on timeout...\n", dbh->path, strerror(errno));
1978 }
1979 }
1980 if (lock_ok(dbh, for_write)){
1981 lock_it(dbh, for_write);
1982 sem_post(dbh->sem);
1983 return 1;
1984 }
1985 sem_post(dbh->sem);
1986 return 0;
1987 }
1988
1989 static int
sdbh_unlock(DBHashTable * dbh,int for_write)1990 sdbh_unlock (DBHashTable * dbh, int for_write){
1991 if (!(dbh->protection_flags & DBH_PARALLEL_SAFE)){
1992 return 0;
1993 }
1994 if (dbh->lock_attempt_limit == 0) sem_wait(dbh->sem);
1995 else {
1996 struct timespec timeout;
1997 timeout.tv_sec = time(NULL) + dbh->lock_attempt_limit;
1998 timeout.tv_nsec = 0;
1999 if (sem_timedwait(dbh->sem, &timeout) < 0){
2000 ERR("DBH: sdbh_unlock() unable to unlock semaphore for %s (%s), proceeding on timeout...\n", dbh->path, strerror(errno));
2001 }
2002 }
2003 if (for_write){
2004 dbh->lock_p->write_lock_count = 0;
2005 dbh->lock_p->write_lock = 0;
2006 } else {
2007 if (dbh->lock_p->read_lock_count > 0) dbh->lock_p->read_lock_count--;
2008 }
2009 if(msync (dbh->lock_p, sizeof(dbh_lock_t), MS_ASYNC) < 0){
2010 ERR("(3:lock_p=%p) Cannot msync shared memory item for %s: %s\n",
2011 dbh->lock_p, dbh->path, strerror (errno));
2012 }
2013 sem_post(dbh->sem);
2014 return 1;
2015 }
2016 #endif
2017
2018