1/*++
2/* NAME
3/*	open_lock 3
4/* SUMMARY
5/*	open or create file and lock it for exclusive access
6/* SYNOPSIS
7/*	#include <open_lock.h>
8/*
9/*	VSTREAM	*open_lock(path, flags, mode, why)
10/*	const char *path;
11/*	int	flags;
12/*	mode_t	mode;
13/*	VSTRING *why;
14/* DESCRIPTION
15/*	This module opens or creates the named file and attempts to
16/*	acquire an exclusive lock.  The lock is lost when the last
17/*	process closes the file.
18/*
19/*	Arguments:
20/* .IP "path, flags, mode"
21/*	These are passed on to safe_open().
22/* .IP why
23/*	storage for diagnostics.
24/* SEE ALSO
25/*	safe_open(3) carefully open or create file
26/*	myflock(3) get exclusive lock on file
27/* DIAGNOSTICS
28/*	In case of problems the result is a null pointer and a problem
29/*	description is returned via the global \fIerrno\fR variable.
30/* LICENSE
31/* .ad
32/* .fi
33/*	The Secure Mailer license must be distributed with this software.
34/* AUTHOR(S)
35/*	Wietse Venema
36/*	IBM T.J. Watson Research
37/*	P.O. Box 704
38/*	Yorktown Heights, NY 10598, USA
39/*--*/
40
41/* System library. */
42
43#include <sys_defs.h>
44#include <unistd.h>
45#include <fcntl.h>
46
47/* Utility library. */
48
49#include <msg.h>
50#include <vstream.h>
51#include <vstring.h>
52#include <safe_open.h>
53#include <myflock.h>
54#include <open_lock.h>
55
56/* open_lock - open file and lock it for exclusive access */
57
58VSTREAM *open_lock(const char *path, int flags, mode_t mode, VSTRING *why)
59{
60    VSTREAM *fp;
61
62    /*
63     * Carefully create or open the file, and lock it down. Some systems
64     * don't have the O_LOCK open() flag, or the flag does not do what we
65     * want, so we roll our own lock.
66     */
67    if ((fp = safe_open(path, flags, mode, (struct stat *) 0, -1, -1, why)) == 0)
68	return (0);
69    if (myflock(vstream_fileno(fp), INTERNAL_LOCK,
70		MYFLOCK_OP_EXCLUSIVE | MYFLOCK_OP_NOWAIT) < 0) {
71	vstring_sprintf(why, "unable to set exclusive lock: %m");
72	vstream_fclose(fp);
73	return (0);
74    }
75    return (fp);
76}
77