164562Sgshapiro/*
290792Sgshapiro * Copyright (c) 1998-2001 Sendmail, Inc. and its suppliers.
364562Sgshapiro *	All rights reserved.
464562Sgshapiro * Copyright (c) 1983, 1995-1997 Eric P. Allman.  All rights reserved.
564562Sgshapiro * Copyright (c) 1988, 1993
664562Sgshapiro *	The Regents of the University of California.  All rights reserved.
764562Sgshapiro *
864562Sgshapiro * By using this file, you agree to the terms and conditions set
964562Sgshapiro * forth in the LICENSE file which can be found at the top level of
1064562Sgshapiro * the sendmail distribution.
1164562Sgshapiro *
1264562Sgshapiro */
1364562Sgshapiro
1464562Sgshapiro#include <sendmail.h>
1564562Sgshapiro
16132943SgshapiroSM_RCSID("@(#)$Id: lockfile.c,v 8.21 2003/11/10 22:57:38 ca Exp $")
1790792Sgshapiro
1890792Sgshapiro
1990792Sgshapiro/*
2064562Sgshapiro**  LOCKFILE -- lock a file using flock or (shudder) fcntl locking
2164562Sgshapiro**
2264562Sgshapiro**	Parameters:
2364562Sgshapiro**		fd -- the file descriptor of the file.
2464562Sgshapiro**		filename -- the file name (for error messages). [unused]
2564562Sgshapiro**		ext -- the filename extension. [unused]
2664562Sgshapiro**		type -- type of the lock.  Bits can be:
2764562Sgshapiro**			LOCK_EX -- exclusive lock.
2864562Sgshapiro**			LOCK_NB -- non-blocking.
2971345Sgshapiro**			LOCK_UN -- unlock.
3064562Sgshapiro**
3164562Sgshapiro**	Returns:
3290792Sgshapiro**		true if the lock was acquired.
3390792Sgshapiro**		false otherwise.
3464562Sgshapiro*/
3564562Sgshapiro
3664562Sgshapirobool
3764562Sgshapirolockfile(fd, filename, ext, type)
3864562Sgshapiro	int fd;
3964562Sgshapiro	char *filename;
4064562Sgshapiro	char *ext;
4164562Sgshapiro	int type;
4264562Sgshapiro{
4364562Sgshapiro#if !HASFLOCK
4464562Sgshapiro	int action;
4564562Sgshapiro	struct flock lfd;
4664562Sgshapiro
4764562Sgshapiro	memset(&lfd, '\0', sizeof lfd);
4864562Sgshapiro	if (bitset(LOCK_UN, type))
4964562Sgshapiro		lfd.l_type = F_UNLCK;
5064562Sgshapiro	else if (bitset(LOCK_EX, type))
5164562Sgshapiro		lfd.l_type = F_WRLCK;
5264562Sgshapiro	else
5364562Sgshapiro		lfd.l_type = F_RDLCK;
5464562Sgshapiro	if (bitset(LOCK_NB, type))
5564562Sgshapiro		action = F_SETLK;
5664562Sgshapiro	else
5764562Sgshapiro		action = F_SETLKW;
5864562Sgshapiro
5964562Sgshapiro	if (fcntl(fd, action, &lfd) >= 0)
6090792Sgshapiro		return true;
6164562Sgshapiro
6264562Sgshapiro	/*
6364562Sgshapiro	**  On SunOS, if you are testing using -oQ/tmp/mqueue or
6464562Sgshapiro	**  -oA/tmp/aliases or anything like that, and /tmp is mounted
6564562Sgshapiro	**  as type "tmp" (that is, served from swap space), the
6664562Sgshapiro	**  previous fcntl will fail with "Invalid argument" errors.
6764562Sgshapiro	**  Since this is fairly common during testing, we will assume
6864562Sgshapiro	**  that this indicates that the lock is successfully grabbed.
6964562Sgshapiro	*/
7064562Sgshapiro
7164562Sgshapiro	if (errno == EINVAL)
7290792Sgshapiro		return true;
7364562Sgshapiro
7464562Sgshapiro#else /* !HASFLOCK */
7564562Sgshapiro
7664562Sgshapiro	if (flock(fd, type) >= 0)
7790792Sgshapiro		return true;
7864562Sgshapiro
7964562Sgshapiro#endif /* !HASFLOCK */
8064562Sgshapiro
8190792Sgshapiro	return false;
8264562Sgshapiro}
83