Home | History | Annotate | Line # | Download | only in util
      1 /*	$NetBSD: mkmap_sdbm.c,v 1.2 2023/12/23 20:30:46 christos Exp $	*/
      2 
      3 /*++
      4 /* NAME
      5 /*	mkmap_sdbm 3
      6 /* SUMMARY
      7 /*	create or open database, SDBM style
      8 /* SYNOPSIS
      9 /*	#include <dict_sdbm.h>
     10 /*
     11 /*	MKMAP	*mkmap_sdbm_open(path)
     12 /*	const char *path;
     13 /* DESCRIPTION
     14 /*	This module implements support for creating SDBM databases.
     15 /*
     16 /*	mkmap_sdbm_open() takes a file name, appends the ".dir" and ".pag"
     17 /*	suffixes, and creates or opens the named SDBM database.
     18 /*	This routine is a SDBM-specific helper for the more general
     19 /*	mkmap_open() routine.
     20 /*
     21 /*	All errors are fatal.
     22 /* SEE ALSO
     23 /*	dict_sdbm(3), SDBM dictionary interface.
     24 /* LICENSE
     25 /* .ad
     26 /* .fi
     27 /*	The Secure Mailer license must be distributed with this software.
     28 /* AUTHOR(S)
     29 /*	Wietse Venema
     30 /*	IBM T.J. Watson Research
     31 /*	P.O. Box 704
     32 /*	Yorktown Heights, NY 10598, USA
     33 /*
     34 /*	Wietse Venema
     35 /*	Google, Inc.
     36 /*	111 8th Avenue
     37 /*	New York, NY 10011, USA
     38 /*--*/
     39 
     40 /* System library. */
     41 
     42 #include <sys_defs.h>
     43 #include <unistd.h>
     44 
     45 /* Utility library. */
     46 
     47 #include <msg.h>
     48 #include <mymalloc.h>
     49 #include <stringops.h>
     50 #include <dict_sdbm.h>
     51 #include <myflock.h>
     52 
     53 #ifdef HAS_SDBM
     54 
     55 #include <sdbm.h>
     56 
     57 typedef struct MKMAP_SDBM {
     58     MKMAP   mkmap;			/* parent class */
     59     char   *lock_file;			/* path name */
     60     int     lock_fd;			/* -1 or open locked file */
     61 } MKMAP_SDBM;
     62 
     63 /* mkmap_sdbm_after_close - clean up after closing database */
     64 
     65 static void mkmap_sdbm_after_close(MKMAP *mp)
     66 {
     67     MKMAP_SDBM *mkmap = (MKMAP_SDBM *) mp;
     68 
     69     if (mkmap->lock_fd >= 0 && close(mkmap->lock_fd) < 0)
     70 	msg_warn("close %s: %m", mkmap->lock_file);
     71     myfree(mkmap->lock_file);
     72 }
     73 
     74 /* mkmap_sdbm_open - create or open database */
     75 
     76 MKMAP  *mkmap_sdbm_open(const char *path)
     77 {
     78     MKMAP_SDBM *mkmap = (MKMAP_SDBM *) mymalloc(sizeof(*mkmap));
     79     char   *pag_file;
     80     int     pag_fd;
     81 
     82     /*
     83      * Fill in the generic members.
     84      */
     85     mkmap->lock_file = concatenate(path, ".dir", (char *) 0);
     86     mkmap->mkmap.open = dict_sdbm_open;
     87     mkmap->mkmap.after_open = 0;
     88     mkmap->mkmap.after_close = mkmap_sdbm_after_close;
     89 
     90     /*
     91      * Unfortunately, not all systems support locking on open(), so we open
     92      * the .dir and .pag files before truncating them. Keep one file open for
     93      * locking.
     94      */
     95     if ((mkmap->lock_fd = open(mkmap->lock_file, O_CREAT | O_RDWR, 0644)) < 0)
     96 	msg_fatal("open %s: %m", mkmap->lock_file);
     97 
     98     pag_file = concatenate(path, ".pag", (char *) 0);
     99     if ((pag_fd = open(pag_file, O_CREAT | O_RDWR, 0644)) < 0)
    100 	msg_fatal("open %s: %m", pag_file);
    101     if (close(pag_fd))
    102 	msg_warn("close %s: %m", pag_file);
    103     myfree(pag_file);
    104 
    105     /*
    106      * Get an exclusive lock - we're going to change the database so we can't
    107      * have any spectators.
    108      */
    109     if (myflock(mkmap->lock_fd, INTERNAL_LOCK, MYFLOCK_OP_EXCLUSIVE) < 0)
    110 	msg_fatal("lock %s: %m", mkmap->lock_file);
    111 
    112     return (&mkmap->mkmap);
    113 }
    114 
    115 #endif
    116