mirror of
https://github.com/OPM/ResInsight.git
synced 2026-10-25 14:40:26 -05:00
94 lines
3.0 KiB
C++
94 lines
3.0 KiB
C++
#include <errno.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
|
|
#include <ert/util/util.h>
|
|
|
|
#include <fcntl.h>
|
|
#include <unistd.h>
|
|
|
|
/**
|
|
This function will TRY to aquire an exclusive lock to the file
|
|
filename. If the file does not exist it will be created. The mode
|
|
will be changed to 'mode' (irrespective of whether it exists
|
|
already or not).
|
|
|
|
Observe that before the lockf() call we *MUST* succeed in opening
|
|
the file, that means that if we do not have the necessary rights
|
|
to open the file (with modes O_WRONLY + O_CREATE), the function
|
|
will fail hard before even reaching the lockf system call.
|
|
|
|
If the lock is aquired the function will return true, otherwise it
|
|
will return false. The lock is only active as long as the lockfile
|
|
is open, we therefore have to keep track of the relevant file
|
|
descriptor; it is passed back to the calling scope through a
|
|
reference. Observe that if the locking fails we close the file
|
|
immediately, and return -1 in the file descriptor argument.
|
|
|
|
When the calling scope is no longer interested in locking the
|
|
resource it should close the file descriptor.
|
|
|
|
** Observe that with this locking scheme the existence of a lockfile
|
|
** is not really interesting.
|
|
|
|
Observe that the lockf() system call, which this function is based
|
|
on, will always succeed in the same process. I.e. this function
|
|
can NOT be used to protect against concurrent update from two
|
|
threads in the same process.
|
|
*/
|
|
|
|
|
|
bool util_try_lockf(const char * lockfile , mode_t mode , int * __fd) {
|
|
int status;
|
|
int lock_fd;
|
|
lock_fd = open(lockfile , O_WRONLY + O_CREAT , mode);
|
|
if (lock_fd == -1)
|
|
util_abort("%s: failed to open lockfile:%s %d/%s\n",__func__ , lockfile,errno , strerror(errno));
|
|
|
|
fchmod(lock_fd , mode);
|
|
status = lockf(lock_fd , F_TLOCK , 0);
|
|
if (status == 0) {
|
|
/* We got the lock for exclusive access - all is hunkadory.*/
|
|
*__fd = lock_fd;
|
|
return true;
|
|
} else {
|
|
if (errno == EACCES || errno == EAGAIN) {
|
|
close(lock_fd);
|
|
*__fd = -1;
|
|
|
|
return false;
|
|
} else {
|
|
util_abort("%s: lockf() system call failed:%d/%s \n",__func__ , errno , strerror(errno));
|
|
return false; /* Compiler shut up. */
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
/*
|
|
Opens a file, and locks it for exclusive acces. fclose() will
|
|
release all locks.
|
|
*/
|
|
|
|
FILE * util_fopen_lockf(const char * filename, const char * mode) {
|
|
int flags = 0; /* Compiler shut up */
|
|
int fd;
|
|
int lock_status;
|
|
|
|
flags = O_RDWR; /* Observe that the open call must have write option to be able to place a lock - even though we only attempt to read from the file. */
|
|
if (strcmp(mode , "w") == 0)
|
|
flags += O_CREAT;
|
|
|
|
fd = open(filename , flags, S_IRUSR|S_IWUSR);
|
|
if (fd == -1)
|
|
util_abort("%s: failed to open:%s with flags:%d \n",__func__ , filename , flags);
|
|
|
|
lock_status = lockf(fd , F_LOCK , 0);
|
|
if (lock_status != 0)
|
|
util_abort("%s: failed to lock file: %s %s(%d) \n",__func__ , filename , strerror(errno) , errno);
|
|
|
|
return fdopen(fd , mode);
|
|
}
|
|
|
|
|