/* copied from pp_sys.c */ #ifndef FLOCK #ifdef HAS_FLOCK # define FLOCK flock #else /* no flock() */ /* fcntl.h might not have been included, even if it exists, because the current Configure only sets I_FCNTL if it's needed to pick up the *_OK constants. Make sure it has been included before testing the fcntl() locking constants. */ # if defined(HAS_FCNTL) && !defined(I_FCNTL) # include # endif # if defined(HAS_FCNTL) && defined(FCNTL_CAN_LOCK) # define FLOCK fcntl_emulate_flock # define FCNTL_EMULATE_FLOCK # else /* no flock() or fcntl(F_SETLK,...) */ # ifdef HAS_LOCKF # define FLOCK lockf_emulate_flock # define LOCKF_EMULATE_FLOCK # endif /* lockf */ # endif /* no flock() or fcntl(F_SETLK,...) */ # ifdef FLOCK static int FLOCK (int, int); /* * These are the flock() constants. Since this sytems doesn't have * flock(), the values of the constants are probably not available. */ # ifndef LOCK_SH # define LOCK_SH 1 # endif # ifndef LOCK_EX # define LOCK_EX 2 # endif # ifndef LOCK_NB # define LOCK_NB 4 # endif # ifndef LOCK_UN # define LOCK_UN 8 # endif # endif /* emulating flock() */ #endif /* no flock() */ #ifdef FCNTL_EMULATE_FLOCK /* XXX Emulate flock() with fcntl(). What's really needed is a good file locking module. */ static int fcntl_emulate_flock(int fd, int operation) { struct flock flock; switch (operation & ~LOCK_NB) { case LOCK_SH: flock.l_type = F_RDLCK; break; case LOCK_EX: flock.l_type = F_WRLCK; break; case LOCK_UN: flock.l_type = F_UNLCK; break; default: errno = EINVAL; return -1; } flock.l_whence = SEEK_SET; flock.l_start = flock.l_len = (Off_t)0; return fcntl(fd, (operation & LOCK_NB) ? F_SETLK : F_SETLKW, &flock); } #endif /* FCNTL_EMULATE_FLOCK */ #ifdef LOCKF_EMULATE_FLOCK /* XXX Emulate flock() with lockf(). This is just to increase portability of scripts. The calls are not completely interchangeable. What's really needed is a good file locking module. */ /* The lockf() constants might have been defined in . Unfortunately, causes troubles on some mixed (BSD/POSIX) systems, such as SunOS 4.1.3. Further, the lockf() constants aren't POSIX, so they might not be visible if we're compiling with _POSIX_SOURCE defined. Thus, we'll just stick in the SVID values and be done with it. Sigh. */ # ifndef F_ULOCK # define F_ULOCK 0 /* Unlock a previously locked region */ # endif # ifndef F_LOCK # define F_LOCK 1 /* Lock a region for exclusive use */ # endif # ifndef F_TLOCK # define F_TLOCK 2 /* Test and lock a region for exclusive use */ # endif # ifndef F_TEST # define F_TEST 3 /* Test a region for other processes locks */ # endif static int lockf_emulate_flock(int fd, int operation) { int i; const int save_errno = errno; Off_t pos; /* flock locks entire file so for lockf we need to do the same */ pos = PerlLIO_lseek(fd, (Off_t)0, SEEK_CUR); /* get pos to restore later */ if (pos > 0) /* is seekable and needs to be repositioned */ if (PerlLIO_lseek(fd, (Off_t)0, SEEK_SET) < 0) pos = -1; /* seek failed, so don't seek back afterwards */ errno = save_errno; switch (operation) { /* LOCK_SH - get a shared lock */ case LOCK_SH: /* LOCK_EX - get an exclusive lock */ case LOCK_EX: i = lockf (fd, F_LOCK, 0); break; /* LOCK_SH|LOCK_NB - get a non-blocking shared lock */ case LOCK_SH|LOCK_NB: /* LOCK_EX|LOCK_NB - get a non-blocking exclusive lock */ case LOCK_EX|LOCK_NB: i = lockf (fd, F_TLOCK, 0); if (i == -1) if ((errno == EAGAIN) || (errno == EACCES)) errno = EWOULDBLOCK; break; /* LOCK_UN - unlock (non-blocking is a no-op) */ case LOCK_UN: case LOCK_UN|LOCK_NB: i = lockf (fd, F_ULOCK, 0); break; /* Default - can't decipher operation */ default: i = -1; errno = EINVAL; break; } if (pos > 0) /* need to restore position of the handle */ PerlLIO_lseek(fd, pos, SEEK_SET); /* ignore error here */ return (i); } #endif /* LOCKF_EMULATE_FLOCK */ #endif /* perlflock.h */