summaryrefslogtreecommitdiffstats
path: root/lib/libutil
diff options
context:
space:
mode:
authorache <ache@FreeBSD.org>1997-08-10 18:42:39 +0000
committerache <ache@FreeBSD.org>1997-08-10 18:42:39 +0000
commitcda69874ef4c7bc9289ad428e079718847f8cc8f (patch)
treec1faf086a6db24e822d86b23c95aa3dee9396c85 /lib/libutil
parent30859a202baea2f73b6ad22eb439dc5be9313d6c (diff)
downloadFreeBSD-src-cda69874ef4c7bc9289ad428e079718847f8cc8f.zip
FreeBSD-src-cda69874ef4c7bc9289ad428e079718847f8cc8f.tar.gz
Implement canonical locking protocol
Suggested by: joerg
Diffstat (limited to 'lib/libutil')
-rw-r--r--lib/libutil/libutil.h6
-rw-r--r--lib/libutil/uucplock.318
-rw-r--r--lib/libutil/uucplock.c121
3 files changed, 83 insertions, 62 deletions
diff --git a/lib/libutil/libutil.h b/lib/libutil/libutil.h
index 5404a1f..d6bb5de 100644
--- a/lib/libutil/libutil.h
+++ b/lib/libutil/libutil.h
@@ -18,7 +18,7 @@
* 5. Modifications may be freely made to this file providing the above
* conditions are met.
*
- * $Id: libutil.h,v 1.8 1997/05/12 10:36:13 brian Exp $
+ * $Id: libutil.h,v 1.9 1997/05/19 10:04:15 peter Exp $
*/
#ifndef _LIBUTIL_H_
@@ -51,7 +51,9 @@ __END_DECLS
#define UU_LOCK_OK (0)
#define UU_LOCK_OPEN_ERR (-1)
#define UU_LOCK_READ_ERR (-2)
-#define UU_LOCK_SEEK_ERR (-3)
+#define UU_LOCK_CREAT_ERR (-3)
#define UU_LOCK_WRITE_ERR (-4)
+#define UU_LOCK_LINK_ERR (-5)
+#define UU_LOCK_TRY_ERR (-6)
#endif /* !_LIBUTIL_H_ */
diff --git a/lib/libutil/uucplock.3 b/lib/libutil/uucplock.3
index 7f93aa0..5be50a3 100644
--- a/lib/libutil/uucplock.3
+++ b/lib/libutil/uucplock.3
@@ -23,7 +23,7 @@
.\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
.\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
.\"
-.\" $Id: uucplock.3,v 1.6 1997/05/11 08:50:33 davidn Exp $
+.\" $Id: uucplock.3,v 1.7 1997/05/12 10:36:14 brian Exp $
.\" "
.Dd March 30, 1997
.Os
@@ -99,17 +99,21 @@ The lock file could not be opened via
The lock file could not be read via
.Xr read 2 .
.Pp
-.Dv UU_LOCK_SEEK_ERR:
-The lock file was
-.Dq stale ,
-but the call to
-.Xr lseek 2
-necessary to write the current process id failed.
+.Dv UU_LOCK_CREAT_ERR:
+Can't create temporary lock file via
+.Xr creat 2 .
.Pp
.Dv UU_LOCK_WRITE_ERR:
The current process id could not be written to the lock file via a call to
.Xr write 2 .
.Pp
+.Dv UU_LOCK_LINK_ERR:
+Can't link temporary lock file via
+.Xr link 2 .
+.Pp
+.Dv UU_LOCK_TRY_ERR:
+Locking attempts are failed after 5 tries.
+.Pp
If a value of
.Dv UU_LOCK_OK
is passed to
diff --git a/lib/libutil/uucplock.c b/lib/libutil/uucplock.c
index 837558a..8e037e4 100644
--- a/lib/libutil/uucplock.c
+++ b/lib/libutil/uucplock.c
@@ -30,7 +30,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * $Id: uucplock.c,v 1.6 1997/05/12 10:36:14 brian Exp $
+ * $Id: uucplock.c,v 1.7 1997/08/05 12:58:02 ache Exp $
*
*/
@@ -50,72 +50,81 @@ static const char sccsid[] = "@(#)uucplock.c 8.1 (Berkeley) 6/6/93";
#include <string.h>
#include "libutil.h"
+#define MAXTRIES 5
+
+#define LOCKTMP "LCKTMP..%d"
#define LOCKFMT "LCK..%s"
+#define GORET(level, val) { err = errno; uuerr = (val); \
+ goto __CONCAT(ret, level); }
+
/* Forward declarations */
static int put_pid (int fd, pid_t pid);
static pid_t get_pid (int fd,int *err);
/*
* uucp style locking routines
- * return: 0 - success
- * -1 - failure
*/
int uu_lock (const char *ttyname)
{
- int fd;
+ int fd, tmpfd, i;
pid_t pid;
- char tbuf[sizeof(_PATH_UUCPLOCK) + MAXNAMLEN];
- int err;
-
- (void)snprintf(tbuf, sizeof(tbuf), _PATH_UUCPLOCK LOCKFMT, ttyname);
- fd = open(tbuf, O_RDWR|O_CREAT|O_EXCL|O_EXLOCK, 0660);
- if (fd < 0) {
- /*
- * file is already locked
- * check to see if the process holding the lock still exists
- */
- fd = open(tbuf, O_RDWR|O_SHLOCK);
- if (fd < 0)
- return UU_LOCK_OPEN_ERR;
-
- if ((pid = get_pid (fd, &err)) == -1) {
- (void)close(fd);
- errno = err;
- return UU_LOCK_READ_ERR;
- }
+ char lckname[sizeof(_PATH_UUCPLOCK) + MAXNAMLEN],
+ lcktmpname[sizeof(_PATH_UUCPLOCK) + MAXNAMLEN];
+ int err, uuerr;
- if (kill(pid, 0) == 0 || errno != ESRCH) {
- (void)close(fd); /* process is still running */
- return UU_LOCK_INUSE;
- }
- /*
- * The process that locked the file isn't running, so
- * we'll lock it ourselves
- */
- if (lseek(fd, (off_t) 0, L_SET) < 0) {
- err = errno;
- (void)close(fd);
- errno = err;
- return UU_LOCK_SEEK_ERR;
- }
- if (flock(fd, LOCK_EX|LOCK_NB) < 0) {
- (void)close(fd);
- return UU_LOCK_INUSE;
- }
- /* fall out and finish the locking process */
- }
pid = getpid();
- if (!put_pid (fd, pid)) {
- err = errno;
- (void)unlink(tbuf);
- (void)close(fd);
- errno = err;
- return UU_LOCK_WRITE_ERR;
+ (void)snprintf(lcktmpname, sizeof(lcktmpname), _PATH_UUCPLOCK LOCKTMP,
+ pid);
+ (void)snprintf(lckname, sizeof(lckname), _PATH_UUCPLOCK LOCKFMT,
+ ttyname);
+ if ((tmpfd = creat(lcktmpname, 0664)) < 0)
+ GORET(0, UU_LOCK_CREAT_ERR);
+
+ for (i = 0; i < MAXTRIES; i++) {
+ if (link (lcktmpname, lckname) < 0) {
+ if (errno != EEXIST)
+ GORET(1, UU_LOCK_LINK_ERR);
+ /*
+ * file is already locked
+ * check to see if the process holding the lock
+ * still exists
+ */
+ if ((fd = open(lckname, O_RDONLY)) < 0)
+ GORET(1, UU_LOCK_OPEN_ERR);
+
+ if ((pid = get_pid (fd, &err)) == -1)
+ GORET(2, UU_LOCK_READ_ERR);
+
+ close(fd);
+
+ if (kill(pid, 0) == 0 || errno != ESRCH)
+ GORET(1, UU_LOCK_INUSE);
+ /*
+ * The process that locked the file isn't running, so
+ * we'll lock it ourselves
+ */
+ (void)unlink(lckname);
+ } else {
+ if (!put_pid (tmpfd, pid))
+ GORET(3, UU_LOCK_WRITE_ERR);
+ break;
+ }
}
+ GORET(1, (i >= MAXTRIES) ? UU_LOCK_TRY_ERR : UU_LOCK_OK);
+
+ret3:
+ (void)unlink(lckname);
+ goto ret1;
+ret2:
(void)close(fd);
- return UU_LOCK_OK;
+ret1:
+ (void)close(tmpfd);
+ (void)unlink(lcktmpname);
+ret0:
+ errno = err;
+ return uuerr;
}
int uu_unlock (const char *ttyname)
@@ -142,12 +151,18 @@ const char *uu_lockerr (int uu_lockresult)
case UU_LOCK_READ_ERR:
fmt = "read error: %s";
break;
- case UU_LOCK_SEEK_ERR:
- fmt = "seek error: %s";
+ case UU_LOCK_CREAT_ERR:
+ fmt = "creat error: %s";
break;
case UU_LOCK_WRITE_ERR:
fmt = "write error: %s";
break;
+ case UU_LOCK_LINK_ERR:
+ fmt = "link error: %s";
+ break;
+ case UU_LOCK_TRY_ERR:
+ fmt = "too many tries: %s";
+ break;
default:
fmt = "undefined error: %s";
break;
@@ -166,7 +181,7 @@ static int put_pid (int fd, pid_t pid)
return write (fd, buf, len) == len;
}
-static pid_t get_pid (int fd,int *err)
+static pid_t get_pid (int fd, int *err)
{
int bytes_read;
char buf[32];
OpenPOWER on IntegriCloud