Skip to content

Instantly share code, notes, and snippets.

@sjkillen
Created April 5, 2018 01:59
Show Gist options
  • Save sjkillen/291b2815739abb3430b042bf658fb661 to your computer and use it in GitHub Desktop.
Save sjkillen/291b2815739abb3430b042bf658fb661 to your computer and use it in GitHub Desktop.
/*
* Spencer Killen
* CMPT 360
* Assignment 3
* Dec 5th 2016
* Library used for applying a file lock after a condition is met
*/
#include <sys/inotify.h>
#include <aio.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <fcntl.h>
#include <assert.h>
#include <string.h>
#include <errno.h>
#include <stdbool.h>
#include <stdint.h>
#include "deferred_lock.h"
// stores data needed for monitoring a file asynchronously
struct file_monitor {
struct aiocb async;
int infd;
int inwd;
struct deferred_file_lock *deferred;
struct inotify_event *event;
};
// called by inotify file events, handles checking lock prereq and applying file lock
void file_event(union sigval val)
{
struct file_monitor *monitor = (struct file_monitor *) val.sival_ptr;
if (monitor->deferred->check_cond(monitor->deferred->data, monitor->event->mask)) {
printf("Locking file %d\n", monitor->deferred->fd);
int lock = lockf(monitor->deferred->fd, F_LOCK, 0);
assert(lock == 0);
monitor->deferred->lock_notify(lock, monitor->deferred->fd);
assert(inotify_rm_watch(monitor->infd, monitor->inwd) == 0);
free(monitor->event);
free(monitor);
} else {
memset(monitor->event, 0, sizeof(struct inotify_event));
assert(aio_read(&monitor->async) == 0);
}
}
void defer_lock(struct deferred_file_lock *lock_block)
{
assert(lock_block != NULL);
struct file_monitor *monitor = malloc(sizeof(struct file_monitor));
assert(monitor != NULL);
monitor->event = malloc(sizeof(struct inotify_event));
assert(monitor->event != NULL);
monitor->deferred = lock_block;
monitor->infd = inotify_init();
assert(monitor->infd >= 0);
monitor->inwd = inotify_add_watch(monitor->infd,
monitor->deferred->file,
monitor->deferred->in_event);
assert(monitor->inwd >= 0);
monitor->async = (struct aiocb) {
.aio_fildes = monitor->infd,
.aio_offset = 0,
.aio_buf = monitor->event,
.aio_nbytes = sizeof(struct inotify_event),
.aio_reqprio = 0,
.aio_sigevent = (struct sigevent) {
.sigev_notify = SIGEV_THREAD,
.sigev_notify_function = file_event,
.sigev_notify_attributes = NULL,
.sigev_value = (union sigval) {
.sival_ptr = monitor
}
}
};
assert(aio_read(&monitor->async) == 0);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment