📄 map.c
字号:
: O_RDONLY;
if (fd >= 0 && !bitset(MF_LOCKED, map->map_mflags))
(void) lockfile(fd, map->map_file, ".dir", LOCK_UN);
map->map_class->map_close(map);
map->map_mflags &= ~(MF_OPEN|MF_WRITABLE);
if (map->map_class->map_open(map, omode))
{
map->map_mflags |= MF_OPEN;
map->map_pid = getpid();
if ((omode && O_ACCMODE) == O_RDWR)
map->map_mflags |= MF_WRITABLE;
goto lockdbm;
}
else
{
if (!bitset(MF_OPTIONAL, map->map_mflags))
{
extern MAPCLASS BogusMapClass;
*statp = EX_TEMPFAIL;
map->map_class = &BogusMapClass;
map->map_mflags |= MF_OPEN;
map->map_pid = getpid();
syserr("Cannot reopen NDBM database %s",
map->map_file);
}
return NULL;
}
}
val.dptr = NULL;
if (bitset(MF_TRY0NULL, map->map_mflags))
{
val = dbm_fetch((DBM *) map->map_db1, key);
if (val.dptr != NULL)
map->map_mflags &= ~MF_TRY1NULL;
}
if (val.dptr == NULL && bitset(MF_TRY1NULL, map->map_mflags))
{
key.dsize++;
val = dbm_fetch((DBM *) map->map_db1, key);
if (val.dptr != NULL)
map->map_mflags &= ~MF_TRY0NULL;
}
if (fd >= 0 && !bitset(MF_LOCKED, map->map_mflags))
(void) lockfile(fd, map->map_file, ".dir", LOCK_UN);
if (val.dptr == NULL)
return NULL;
if (bitset(MF_MATCHONLY, map->map_mflags))
return map_rewrite(map, name, strlen(name), NULL);
else
return map_rewrite(map, val.dptr, val.dsize, av);
}
/*
** NDBM_MAP_STORE -- store a datum in the database
*/
void
ndbm_map_store(map, lhs, rhs)
register MAP *map;
char *lhs;
char *rhs;
{
datum key;
datum data;
int status;
char keybuf[MAXNAME + 1];
if (tTd(38, 12))
dprintf("ndbm_map_store(%s, %s, %s)\n",
map->map_mname, lhs, rhs);
key.dsize = strlen(lhs);
key.dptr = lhs;
if (!bitset(MF_NOFOLDCASE, map->map_mflags))
{
if (key.dsize > sizeof keybuf - 1)
key.dsize = sizeof keybuf - 1;
memmove(keybuf, key.dptr, key.dsize);
keybuf[key.dsize] = '\0';
makelower(keybuf);
key.dptr = keybuf;
}
data.dsize = strlen(rhs);
data.dptr = rhs;
if (bitset(MF_INCLNULL, map->map_mflags))
{
key.dsize++;
data.dsize++;
}
status = dbm_store((DBM *) map->map_db1, key, data, DBM_INSERT);
if (status > 0)
{
if (!bitset(MF_APPEND, map->map_mflags))
message("050 Warning: duplicate alias name %s", lhs);
else
{
static char *buf = NULL;
static int bufsiz = 0;
auto int xstat;
datum old;
old.dptr = ndbm_map_lookup(map, key.dptr,
(char **)NULL, &xstat);
if (old.dptr != NULL && *(char *) old.dptr != '\0')
{
old.dsize = strlen(old.dptr);
if (data.dsize + old.dsize + 2 > bufsiz)
{
if (buf != NULL)
(void) free(buf);
bufsiz = data.dsize + old.dsize + 2;
buf = xalloc(bufsiz);
}
snprintf(buf, bufsiz, "%s,%s",
data.dptr, old.dptr);
data.dsize = data.dsize + old.dsize + 1;
data.dptr = buf;
if (tTd(38, 9))
dprintf("ndbm_map_store append=%s\n",
data.dptr);
}
}
status = dbm_store((DBM *) map->map_db1,
key, data, DBM_REPLACE);
}
if (status != 0)
syserr("readaliases: dbm put (%s): %d", lhs, status);
}
/*
** NDBM_MAP_CLOSE -- close the database
*/
void
ndbm_map_close(map)
register MAP *map;
{
if (tTd(38, 9))
dprintf("ndbm_map_close(%s, %s, %lx)\n",
map->map_mname, map->map_file, map->map_mflags);
if (bitset(MF_WRITABLE, map->map_mflags))
{
# ifdef NDBM_YP_COMPAT
bool inclnull;
char buf[MAXHOSTNAMELEN];
inclnull = bitset(MF_INCLNULL, map->map_mflags);
map->map_mflags &= ~MF_INCLNULL;
if (strstr(map->map_file, "/yp/") != NULL)
{
long save_mflags = map->map_mflags;
map->map_mflags |= MF_NOFOLDCASE;
(void) snprintf(buf, sizeof buf, "%010ld", curtime());
ndbm_map_store(map, "YP_LAST_MODIFIED", buf);
(void) gethostname(buf, sizeof buf);
ndbm_map_store(map, "YP_MASTER_NAME", buf);
map->map_mflags = save_mflags;
}
if (inclnull)
map->map_mflags |= MF_INCLNULL;
# endif /* NDBM_YP_COMPAT */
/* write out the distinguished alias */
ndbm_map_store(map, "@", "@");
}
dbm_close((DBM *) map->map_db1);
/* release lock (if needed) */
# if !LOCK_ON_OPEN
if (map->map_lockfd >= 0)
(void) close(map->map_lockfd);
# endif /* !LOCK_ON_OPEN */
}
#endif /* NDBM */
/*
** NEWDB (Hash and BTree) Modules
*/
#ifdef NEWDB
/*
** BT_MAP_OPEN, HASH_MAP_OPEN -- database open primitives.
**
** These do rather bizarre locking. If you can lock on open,
** do that to avoid the condition of opening a database that
** is being rebuilt. If you don't, we'll try to fake it, but
** there will be a race condition. If opening for read-only,
** we immediately release the lock to avoid freezing things up.
** We really ought to hold the lock, but guarantee that we won't
** be pokey about it. That's hard to do.
*/
/* these should be K line arguments */
# if DB_VERSION_MAJOR < 2
# define db_cachesize cachesize
# define h_nelem nelem
# ifndef DB_CACHE_SIZE
# define DB_CACHE_SIZE (1024 * 1024) /* database memory cache size */
# endif /* ! DB_CACHE_SIZE */
# ifndef DB_HASH_NELEM
# define DB_HASH_NELEM 4096 /* (starting) size of hash table */
# endif /* ! DB_HASH_NELEM */
# endif /* DB_VERSION_MAJOR < 2 */
bool
bt_map_open(map, mode)
MAP *map;
int mode;
{
# if DB_VERSION_MAJOR < 2
BTREEINFO btinfo;
# endif /* DB_VERSION_MAJOR < 2 */
# if DB_VERSION_MAJOR == 2
DB_INFO btinfo;
# endif /* DB_VERSION_MAJOR == 2 */
# if DB_VERSION_MAJOR > 2
void *btinfo = NULL;
# endif /* DB_VERSION_MAJOR > 2 */
if (tTd(38, 2))
dprintf("bt_map_open(%s, %s, %d)\n",
map->map_mname, map->map_file, mode);
# if DB_VERSION_MAJOR < 3
memset(&btinfo, '\0', sizeof btinfo);
# ifdef DB_CACHE_SIZE
btinfo.db_cachesize = DB_CACHE_SIZE;
# endif /* DB_CACHE_SIZE */
# endif /* DB_VERSION_MAJOR < 3 */
return db_map_open(map, mode, "btree", DB_BTREE, &btinfo);
}
bool
hash_map_open(map, mode)
MAP *map;
int mode;
{
# if DB_VERSION_MAJOR < 2
HASHINFO hinfo;
# endif /* DB_VERSION_MAJOR < 2 */
# if DB_VERSION_MAJOR == 2
DB_INFO hinfo;
# endif /* DB_VERSION_MAJOR == 2 */
# if DB_VERSION_MAJOR > 2
void *hinfo = NULL;
# endif /* DB_VERSION_MAJOR > 2 */
if (tTd(38, 2))
dprintf("hash_map_open(%s, %s, %d)\n",
map->map_mname, map->map_file, mode);
# if DB_VERSION_MAJOR < 3
memset(&hinfo, '\0', sizeof hinfo);
# ifdef DB_HASH_NELEM
hinfo.h_nelem = DB_HASH_NELEM;
# endif /* DB_HASH_NELEM */
# ifdef DB_CACHE_SIZE
hinfo.db_cachesize = DB_CACHE_SIZE;
# endif /* DB_CACHE_SIZE */
# endif /* DB_VERSION_MAJOR < 3 */
return db_map_open(map, mode, "hash", DB_HASH, &hinfo);
}
static bool
db_map_open(map, mode, mapclassname, dbtype, openinfo)
MAP *map;
int mode;
char *mapclassname;
DBTYPE dbtype;
# if DB_VERSION_MAJOR < 2
const void *openinfo;
# endif /* DB_VERSION_MAJOR < 2 */
# if DB_VERSION_MAJOR == 2
DB_INFO *openinfo;
# endif /* DB_VERSION_MAJOR == 2 */
# if DB_VERSION_MAJOR > 2
void **openinfo;
# endif /* DB_VERSION_MAJOR > 2 */
{
DB *db = NULL;
int i;
int omode;
int smode = S_IREAD;
int fd;
long sff;
int save_errno;
struct stat st;
char buf[MAXNAME + 1];
/* do initial file and directory checks */
(void) strlcpy(buf, map->map_file, sizeof buf - 3);
i = strlen(buf);
if (i < 3 || strcmp(&buf[i - 3], ".db") != 0)
(void) strlcat(buf, ".db", sizeof buf);
mode &= O_ACCMODE;
omode = mode;
sff = SFF_ROOTOK|SFF_REGONLY;
if (mode == O_RDWR)
{
sff |= SFF_CREAT;
if (!bitnset(DBS_WRITEMAPTOSYMLINK, DontBlameSendmail))
sff |= SFF_NOSLINK;
if (!bitnset(DBS_WRITEMAPTOHARDLINK, DontBlameSendmail))
sff |= SFF_NOHLINK;
smode = S_IWRITE;
}
else
{
if (!bitnset(DBS_LINKEDMAPINWRITABLEDIR, DontBlameSendmail))
sff |= SFF_NOWLINK;
}
if (!bitnset(DBS_MAPINUNSAFEDIRPATH, DontBlameSendmail))
sff |= SFF_SAFEDIRPATH;
i = safefile(buf, RunAsUid, RunAsGid, RunAsUserName, sff, smode, &st);
# if !_FFR_REMOVE_AUTOREBUILD
if (i == ENOENT && AutoRebuild &&
bitset(MCF_REBUILDABLE, map->map_class->map_cflags) &&
(bitset(MF_IMPL_HASH, map->map_mflags) ||
bitset(MF_ALIAS, map->map_mflags)) &&
mode == O_RDONLY)
{
bool impl = bitset(MF_IMPL_HASH, map->map_mflags);
/* may be able to rebuild */
map->map_mflags &= ~MF_IMPL_HASH;
if (!rebuildaliases(map, TRUE))
return FALSE;
if (impl)
return impl_map_open(map, O_RDONLY);
else
return db_map_open(map, O_RDONLY, mapclassname,
dbtype, openinfo);
}
# endif /* !_FFR_REMOVE_AUTOREBUILD */
if (i != 0)
{
char *prob = "unsafe";
/* cannot open this map */
if (i == ENOENT)
prob = "missing";
if (tTd(38, 2))
dprintf("\t%s map file: %s\n", prob, errstring(i));
errno = i;
if (!bitset(MF_OPTIONAL, map->map_mflags))
syserr("%s map \"%s\": %s map file %s",
mapclassname, map->map_mname, prob, buf);
return FALSE;
}
if (st.st_mode == ST_MODE_NOFILE)
omode |= O_CREAT|O_EXCL;
map->map_lockfd = -1;
# if LOCK_ON_OPEN
if (mode == O_RDWR)
omode |= O_TRUNC|O_EXLOCK;
else
omode |= O_SHLOCK;
# else /* LOCK_ON_OPEN */
/*
** Pre-lock the file to avoid race conditions. In particular,
** since dbopen returns NULL if the file is zero length, we
** must have a locked instance around the dbopen.
*/
fd = open(buf, omode, DBMMODE);
if (fd < 0)
{
if (!bitset(MF_OPTIONAL, map->map_mflags))
syserr("db_map_open: cannot pre-open database %s", buf);
return FALSE;
}
/* make sure no baddies slipped in just before the open... */
if (filechanged(buf, fd, &st))
{
save_errno = errno;
(void) close(fd);
errno = save_errno;
syserr("db_map_open(%s): file changed after pre-open", buf);
return FALSE;
}
/* if new file, get the "before" bits for later filechanged check */
if (st.st_mode == ST_MODE_NOFILE && fstat(fd, &st) < 0)
{
save_errno = errno;
(void) close(fd);
errno = save_errno;
syserr("db_map_open(%s): cannot fstat pre-opened file",
buf);
return FALSE;
}
/* actually lock the pre-opened file */
if (!lockfile(fd, buf, NULL, mode == O_RDONLY ? LOCK_SH : LOCK_EX))
syserr("db_map_open: cannot lock %s", buf);
/* set up mode bits for dbopen */
if (mode == O_RDWR)
omode |= O_TRUNC;
omode &= ~(O_EXCL|O_CREAT);
# endif /* LOCK_ON_OPEN */
# if DB_VERSION_MAJOR < 2
db = dbopen(buf, omode, DBMMODE, dbtype, openinfo);
# else /* DB_VERSION_MAJOR < 2 */
{
int flags = 0;
# if DB_VERSION_MAJOR > 2
int ret;
# endif /* DB_VERSION_MAJOR > 2 */
if (mode == O_RDONLY)
flags |= DB_RDONLY;
if (bitset(O_CREAT, omode))
flags |= DB_CREATE;
if (bitset(O_TRUNC, omode))
flags |= DB_TRUNCATE;
# if !HASFLOCK && defined(DB_FCNTL_LOCKING)
flags |= DB_FCNTL_LOCKING;
# endif /* !HASFLOCK && defined(DB_FCNTL_LOCKING) */
# if DB_VERSION_MAJOR > 2
ret = db_create(&db, NULL, 0);
# ifdef DB_CACHE_SIZE
if (ret == 0 && db != NULL)
{
ret = db->set_cachesize(db, 0, DB_CACHE_SIZE, 0);
if (ret != 0)
{
(void) db->close(db, 0);
db = NULL;
}
}
# endif /* DB_CACHE_SIZE */
# ifdef DB_HASH_NELEM
if (dbtype == DB_HASH && ret == 0 && db != NULL)
{
ret = db->set_h_nelem(db, DB_HASH_NELEM);
if (ret != 0)
{
(void) db->close(db, 0);
db = NULL;
}
}
# endif /* DB_HASH_NELEM */
if (ret == 0 && db != NULL)
{
ret = db->open(db, buf, NULL, dbtype, flags, DBMMODE);
if (ret != 0)
{
(void) db->close(db, 0);
db = NULL;
}
}
errno = ret;
# else /* DB_VERSION_MAJOR > 2 */
errno = db_open(buf, dbtype, flags, DBMMODE,
NULL, openinfo, &db);
# endif /* DB_VERSION_MAJOR > 2 */
}
# endif /* DB_VERSION_MAJOR < 2 */
save_errno = errno;
# if !LOCK_ON_OPEN
if (mode == O_RDWR)
map->map_lockfd = fd;
else
(void) close(fd);
# endif /* !LOCK_ON_OPEN */
if (db == NULL)
{
if (mode == O_RDONLY && bitset(MF_ALIAS, map->map_mflags) &&
aliaswait(map, ".db", FALSE))
return TRUE;
# if !LOCK_ON_OPEN
if (map->map_lockfd >= 0)
(void) close(map->map_lockfd);
# endif /* !LOCK_ON_OPEN */
errno = save_errno;
if (!bitset(MF_OPTIONAL, map->map_mflags))
syserr("Cannot open %s database %s",
mapclassname, buf);
return FALSE;
}
# if DB_VERSION_MAJOR < 2
fd = db->fd(db);
# else /* DB_VERSION_MAJOR < 2 */
fd = -1;
errno = db->fd(db, &fd);
# endif /* DB_VERSION_MAJOR < 2 */
if (filechanged(buf, fd, &st))
{
save_errno = errno;
# if DB_VERSION_MAJOR < 2
(void) db->close(db);
# else /* DB_VERSION_MAJOR < 2 */
errno = db->close(db, 0);
# endif /* DB_VERSION_MAJOR < 2 */
# if !LOCK_ON_OPEN
if (map->map_lockfd >= 0)
(void) close(map->map_lockfd);
# endif /* !LOCK_ON_OPEN */
errno = save_errno;
syserr("db_map_open(%s): file changed after open", buf);
return FALSE;
}
if (mode == O_RDWR)
map->map_mflags |= MF_LOCKED;
# if LOCK_ON_OPEN
if (fd >= 0 && mode == O_RDONLY)
{
(void) lockfile(fd, buf, NULL, LOCK_UN);
}
# endif /* LOCK_ON_OPEN */
/* try to make sure that at least the database header is on disk */
if (mode == O_RDWR)
{
(void) db->sync(db, 0);
if (geteuid() == 0 && TrustedUid != 0)
{
# if HASFCHOWN
if (fchown(fd, TrustedUid, -1) < 0)
{
int err = errno;
sm_syslog(LOG_ALERT, NOQID,
"ownership change on %s failed: %s",
buf, errstring(err));
message("050 ownership change on %s failed: %s",
buf, errstring(err));
}
# endif /* HASFCHOWN */
}
}
map->map_db2 = (ARBPTR_T) db;
/*
** Need to set map_mtime before the call to aliaswait()
** as aliaswait() will call map_lookup() which requires
** map_mtime to be set
*/
if (fd >= 0 && fstat(fd, &st) >= 0)
map->map_mtime = st.st_mtime;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -