X-Git-Url: https://git.gag.com/?a=blobdiff_plain;f=common-src%2Famflock.c;h=b3f1fc131f6b2fd1c3648f5dda43230eede2df52;hb=HEAD;hp=177266dd07c52bd4f5e03bac41fa23689b59d00e;hpb=d5853102f67d85d8e169f9dbe973ad573306c215;p=debian%2Famanda diff --git a/common-src/amflock.c b/common-src/amflock.c index 177266d..b3f1fc1 100644 --- a/common-src/amflock.c +++ b/common-src/amflock.c @@ -1,6 +1,7 @@ /* * Amanda, The Advanced Maryland Automatic Network Disk Archiver * Copyright (c) 1991-1998 University of Maryland at College Park + * Copyright (c) 2007-2012 Zmanda, Inc. All Rights Reserved. * All Rights Reserved. * * Permission to use, copy, modify, distribute, and sell this software and its @@ -36,8 +37,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 +164,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 +291,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);