Home | History | Annotate | Line # | Download | only in util
      1 /*	$NetBSD: mkmap_dbm.c,v 1.2 2023/12/23 20:30:46 christos Exp $	*/
      2 
      3 /*++
      4 /* NAME
      5 /*	mkmap_dbm 3
      6 /* SUMMARY
      7 /*	create or open database, DBM style
      8 /* SYNOPSIS
      9 /*	#include <dict_dbm.h>
     10 /*
     11 /*	MKMAP	*mkmap_dbm_open(path)
     12 /*	const char *path;
     13 /* DESCRIPTION
     14 /*	This module implements support for creating DBM databases.
     15 /*
     16 /*	mkmap_dbm_open() takes a file name, appends the ".dir" and ".pag"
     17 /*	suffixes, and creates or opens the named DBM database.
     18 /*	This routine is a DBM-specific helper for the more general
     19 /*	mkmap_open() routine.
     20 /*
     21 /*	All errors are fatal.
     22 /* SEE ALSO
     23 /*	dict_dbm(3), DBM 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_dbm.h>
     51 #include <myflock.h>
     52 
     53 #ifdef HAS_DBM
     54 #ifdef PATH_NDBM_H
     55 #include PATH_NDBM_H
     56 #else
     57 #include <ndbm.h>
     58 #endif
     59 
     60 typedef struct MKMAP_DBM {
     61     MKMAP   mkmap;			/* parent class */
     62     char   *lock_file;			/* path name */
     63     int     lock_fd;			/* -1 or open locked file */
     64 } MKMAP_DBM;
     65 
     66 /* mkmap_dbm_after_close - clean up after closing database */
     67 
     68 static void mkmap_dbm_after_close(MKMAP *mp)
     69 {
     70     MKMAP_DBM *mkmap = (MKMAP_DBM *) mp;
     71 
     72     if (mkmap->lock_fd >= 0 && close(mkmap->lock_fd) < 0)
     73 	msg_warn("close %s: %m", mkmap->lock_file);
     74     myfree(mkmap->lock_file);
     75 }
     76 
     77 /* mkmap_dbm_open - create or open database */
     78 
     79 MKMAP  *mkmap_dbm_open(const char *path)
     80 {
     81     MKMAP_DBM *mkmap = (MKMAP_DBM *) mymalloc(sizeof(*mkmap));
     82     char   *pag_file;
     83     int     pag_fd;
     84 
     85     /*
     86      * Fill in the generic members.
     87      */
     88     mkmap->lock_file = concatenate(path, ".dir", (char *) 0);
     89     mkmap->mkmap.open = dict_dbm_open;
     90     mkmap->mkmap.after_open = 0;
     91     mkmap->mkmap.after_close = mkmap_dbm_after_close;
     92 
     93     /*
     94      * Unfortunately, not all systems support locking on open(), so we open
     95      * the .dir and .pag files before truncating them. Keep one file open for
     96      * locking.
     97      */
     98     if ((mkmap->lock_fd = open(mkmap->lock_file, O_CREAT | O_RDWR, 0644)) < 0)
     99 	msg_fatal("open %s: %m", mkmap->lock_file);
    100 
    101     pag_file = concatenate(path, ".pag", (char *) 0);
    102     if ((pag_fd = open(pag_file, O_CREAT | O_RDWR, 0644)) < 0)
    103 	msg_fatal("open %s: %m", pag_file);
    104     if (close(pag_fd))
    105 	msg_warn("close %s: %m", pag_file);
    106     myfree(pag_file);
    107 
    108     /*
    109      * Get an exclusive lock - we're going to change the database so we can't
    110      * have any spectators.
    111      */
    112     if (myflock(mkmap->lock_fd, INTERNAL_LOCK, MYFLOCK_OP_EXCLUSIVE) < 0)
    113 	msg_fatal("lock %s: %m", mkmap->lock_file);
    114 
    115     return (&mkmap->mkmap);
    116 }
    117 
    118 #endif
    119