X-Git-Url: https://git.gag.com/?a=blobdiff_plain;f=common-src%2Famflock.c;h=20fad47868cf605dc9680dae553b3704d4309473;hb=949b8910a5e23c4285d0b1aedacfc82a14dc97a5;hp=177266dd07c52bd4f5e03bac41fa23689b59d00e;hpb=fd48f3e498442f0cbff5f3606c7c403d0566150e;p=debian%2Famanda diff --git a/common-src/amflock.c b/common-src/amflock.c index 177266d..20fad47 100644 --- a/common-src/amflock.c +++ b/common-src/amflock.c @@ -36,8 +36,16 @@ * New Implementation */ -static GStaticMutex lock_lock = G_STATIC_MUTEX_INIT; +#if (GLIB_MAJOR_VERSION > 2 || (GLIB_MAJOR_VERSION == 2 && GLIB_MINOR_VERSION >= 31)) +# pragma GCC diagnostic push +# pragma GCC diagnostic ignored "-Wmissing-field-initializers" + static GStaticMutex lock_lock = G_STATIC_MUTEX_INIT; +# pragma GCC diagnostic pop +#else + static GStaticMutex lock_lock = G_STATIC_MUTEX_INIT; +#endif static GHashTable *locally_locked_files = NULL; +static int lock_rw_rd(file_lock *lock, short l_type); file_lock * file_lock_new( @@ -155,6 +163,90 @@ done: return rv; } +static int +lock_rw_rd( + file_lock *lock, + short l_type) +{ + int rv = -2; + int fd = -1; + int saved_errno; + struct flock lock_buf; + struct stat stat_buf; + + g_assert(!lock->locked); + + /* protect from overlapping lock operations within a process */ + g_static_mutex_lock(&lock_lock); + + /* The locks are advisory, so an error here never means the lock is already + * taken. */ + lock->fd = fd = open(lock->filename, O_CREAT|O_RDWR, 0666); + if (fd < 0) { + rv = -1; + goto done; + } + + /* now try locking it */ + lock_buf.l_type = l_type; + lock_buf.l_start = 0; + lock_buf.l_whence = SEEK_SET; + lock_buf.l_len = 0; /* to EOF */ + if (fcntl(fd, F_SETLK, &lock_buf) < 0) { + if (errno == EACCES || errno == EAGAIN) + rv = 1; + else + rv = -1; + goto done; + } + + /* and read the file in its entirety */ + if (fstat(fd, &stat_buf) < 0) { + rv = -1; + goto done; + } + + if (!(stat_buf.st_mode & S_IFREG)) { + rv = -1; + errno = EINVAL; + goto done; + } + + fd = -1; /* we'll keep the file now */ + lock->locked = TRUE; + + rv = 0; + +done: + saved_errno = errno; + g_static_mutex_unlock(&lock_lock); + if (fd >= 0) /* close and unlock if an error occurred */ + close(fd); + errno = saved_errno; + return rv; +} + +int +file_lock_lock_wr( + file_lock *lock) +{ + return lock_rw_rd(lock, F_WRLCK); +} + +int +file_lock_lock_rd( + file_lock *lock) +{ + return lock_rw_rd(lock, F_RDLCK); +} + +int +file_lock_locked( + file_lock *lock) +{ + return lock->locked; +} + int file_lock_write( file_lock *lock, @@ -198,7 +290,9 @@ file_lock_unlock( close(lock->fd); /* and the hash table entry */ - g_hash_table_remove(locally_locked_files, lock->filename); + if (locally_locked_files) { + g_hash_table_remove(locally_locked_files, lock->filename); + } g_static_mutex_unlock(&lock_lock);