⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 map.c

📁 < linux网络编程工具>>配套源码
💻 C
📖 第 1 页 / 共 5 页
字号:
								 : 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 + -