Version 1.8.0.0
[socat.git] / xiolockfile.c
blobc6896d49a1c2a0b71cbfdf544af1da369b7cd89c
1 /* source: xiolockfile.c */
2 /* Copyright Gerhard Rieger and contributors (see file CHANGES) */
3 /* Published under the GNU General Public License V.2, see file COPYING */
5 /* this file contains socats explicit locking mechanisms */
7 #include "xiosysincludes.h"
9 #include "compat.h"
10 #include "mytypes.h"
11 #include "error.h"
12 #include "utils.h"
13 #include "sysutils.h"
15 #include "sycls.h"
17 #include "xio.h"
18 #include "xiolockfile.h"
21 /* returns 0 if it could create lock; 1 if the lock exists; -1 on error */
22 int xiogetlock(const char *lockfile) {
23 char *s;
24 struct stat strat;
25 int fd;
26 pid_t pid;
27 char pidbuf[3*sizeof(pid_t)+1];
28 size_t bytes;
30 if (Lstat(lockfile, &strat) == 0) {
31 return 1;
33 switch (errno) {
34 case ENOENT: break;
35 default:
36 Error3("Lstat(\"%s\", %p): %s", lockfile, &strat, strerror(errno));
37 return -1;
39 /* in this moment, the file did not exist */
41 if ((s = Malloc(strlen(lockfile)+8)) == NULL) {
42 errno = ENOMEM;
43 return -1;
45 strcpy(s, lockfile);
46 strcat(s, ".XXXXXX");
48 if ((fd = Mkstemp(s)) < 0) {
49 Error2("mkstemp(\"%s\"): %s", s, strerror(errno));
50 return -1;
53 pid = Getpid();
54 bytes = sprintf(pidbuf, F_pid"\n", pid);
55 if (writefull(fd, pidbuf, bytes) < 0) {
56 Error4("write(%d, %p, "F_Zu"): %s", fd, pidbuf, bytes, strerror(errno));
57 return -1;
59 Fchmod(fd, 0644);
60 Close(fd);
62 if (Link(s, lockfile) < 0) {
63 int _errno = errno;
64 Error3("link(\"%s\", \"%s\"): %s", s, lockfile, strerror(errno));
65 Unlink(s);
66 errno = _errno;
67 return -1;
69 Unlink(s);
71 return 0;
74 int xiounlock(const char *lockfile) {
75 return Unlink(lockfile);
79 /* returns 0 when it could create lock, or -1 on error */
80 int xiowaitlock(const char *lockfile, struct timespec *intervall) {
81 int rc;
82 int level = E_NOTICE; /* first print a notice */
84 while ((rc = xiogetlock(lockfile)) == 1) {
85 Msg1(level, "waiting for lock \"%s\"", lockfile);
86 level = E_INFO; /* afterwards only make info */
87 Nanosleep(intervall, NULL);
89 return rc;
93 /* returns 0 when it could obtain lock or the lock is not valid
94 (lockfile==NULL), 1 if it could not obtain the lock, or -1 on error */
95 int xiolock(xiolock_t *lock) {
96 int result;
98 if (lock->lockfile == NULL) {
99 return 0;
101 if (lock->waitlock) {
102 result = xiowaitlock(lock->lockfile, &lock->intervall);
103 } else {
104 result = xiogetlock(lock->lockfile);
106 if (result == 0) {
107 Info1("obtained lock \"%s\"", lock->lockfile);
109 return result;
113 int xiofiledroplock(xiofile_t *xfd) {
114 if (xfd->tag == XIO_TAG_DUAL) {
115 xiofiledroplock((xiofile_t *)xfd->dual.stream[0]);
116 xiofiledroplock((xiofile_t *)xfd->dual.stream[1]);
117 } else {
118 xfd->stream.havelock = false;
120 return 0;