/* source: xiolockfile.c */ /* Copyright Gerhard Rieger and contributors (see file CHANGES) */ /* Published under the GNU General Public License V.2, see file COPYING */ /* this file contains socats explicit locking mechanisms */ #include "xiosysincludes.h" #include "compat.h" #include "mytypes.h" #include "error.h" #include "utils.h" #include "sysutils.h" #include "sycls.h" #include "xio.h" #include "xiolockfile.h" /* returns 0 if it could create lock; 1 if the lock exists; -1 on error */ int xiogetlock(const char *lockfile) { char *s; struct stat strat; int fd; pid_t pid; char pidbuf[3*sizeof(pid_t)+1]; size_t bytes; if (Lstat(lockfile, &strat) == 0) { return 1; } switch (errno) { case ENOENT: break; default: Error3("Lstat(\"%s\", %p): %s", lockfile, &strat, strerror(errno)); return -1; } /* in this moment, the file did not exist */ if ((s = Malloc(strlen(lockfile)+8)) == NULL) { errno = ENOMEM; return -1; } strcpy(s, lockfile); strcat(s, ".XXXXXX"); if ((fd = Mkstemp(s)) < 0) { Error2("mkstemp(\"%s\"): %s", s, strerror(errno)); return -1; } pid = Getpid(); bytes = sprintf(pidbuf, F_pid"\n", pid); if (writefull(fd, pidbuf, bytes) < 0) { Error4("write(%d, %p, "F_Zu"): %s", fd, pidbuf, bytes, strerror(errno)); return -1; } Fchmod(fd, 0644); Close(fd); if (Link(s, lockfile) < 0) { int _errno = errno; Error3("link(\"%s\", \"%s\"): %s", s, lockfile, strerror(errno)); Unlink(s); errno = _errno; return -1; } Unlink(s); return 0; } int xiounlock(const char *lockfile) { return Unlink(lockfile); } /* returns 0 when it could create lock, or -1 on error */ int xiowaitlock(const char *lockfile, struct timespec *intervall) { int rc; int level = E_NOTICE; /* first print a notice */ while ((rc = xiogetlock(lockfile)) == 1) { Msg1(level, "waiting for lock \"%s\"", lockfile); level = E_INFO; /* afterwards only make info */ Nanosleep(intervall, NULL); } return rc; } /* returns 0 when it could obtain lock or the lock is not valid (lockfile==NULL), 1 if it could not obtain the lock, or -1 on error */ int xiolock(xiolock_t *lock) { int result; if (lock->lockfile == NULL) { return 0; } if (lock->waitlock) { result = xiowaitlock(lock->lockfile, &lock->intervall); } else { result = xiogetlock(lock->lockfile); } if (result == 0) { Info1("obtained lock \"%s\"", lock->lockfile); } return result; } int xiofiledroplock(xiofile_t *xfd) { if (xfd->tag == XIO_TAG_DUAL) { xiofiledroplock((xiofile_t *)xfd->dual.stream[0]); xiofiledroplock((xiofile_t *)xfd->dual.stream[1]); } else { xfd->stream.havelock = false; } return 0; }