inotify_c.c 2.86 KB
Newer Older
Camil Staps's avatar
Camil Staps committed
1 2 3 4 5 6 7 8
#include <errno.h>
#include <poll.h>
#include <string.h>
#include <sys/inotify.h>
#include <unistd.h>

#include "Clean.h"

9 10 11 12 13 14 15 16
/**
 * Poll an inotify file descriptor
 *
 * fd            The inotify file descriptor to poll
 * timeout       The timeout (negative for no timeout)
 * re_nrevents   Will be set to the number of polled events
 * re_fd         Will be set to fd (needed for uniqueness)
 */
Camil Staps's avatar
Camil Staps committed
17 18 19 20 21
void clean_poll (int fd,int timeout,int *re_nrevents,int *re_fd)
{
	struct pollfd pfd={fd,POLLIN,0};
	*re_nrevents=poll (&pfd,1,timeout);
	*re_fd=fd;
Camil Staps's avatar
Camil Staps committed
22 23
}

24 25 26 27
/**
 * CleanStrings that are returned from clean_inotify_check (so that we don't
 * have to malloc all the time.)
 */
Camil Staps's avatar
Camil Staps committed
28 29 30
static CleanStringVariable (wds_string,1024);
static CleanStringVariable (masks_string,1024);
static CleanStringVariable (names_string,4096);
Camil Staps's avatar
Camil Staps committed
31

32 33 34 35 36 37 38 39 40 41 42 43 44 45 46
/**
 * Check for events on an inotify file descriptor.
 *
 * fd            The inotify file descriptor
 * re_ok         Will be set to 1 on success, 0 on failure
 * re_wds        An array of ints, the watch descriptors that had events
 * re_masks      An array of ints, the events
 * re_fnames     A list of strings, the filenames of the events (may be empty)
 * re_fd         Will be set to fd (needed for uniqueness)
 *
 * re_wds, re_masks and re_fnames are hacks because ccall doesn't allow
 * returning {#Int} or {#String}. The int arrays can be read by taking 4 chars
 * at a time and casting that to an int. The string array can be read by
 * splitting on \0 (since they are filenames, \0 cannot occur).
 */
Camil Staps's avatar
Camil Staps committed
47 48 49 50
void clean_inotify_check (int fd,
		int *re_ok,CleanString *re_wds,CleanString *re_masks,
		CleanString *re_fnames, int *re_fd)
{
Camil Staps's avatar
Camil Staps committed
51 52 53 54 55
	char buf[4096] __attribute__((aligned(__alignof__(struct inotify_event))));
	const struct inotify_event *ev;
	ssize_t len;
	char *ptr;

Camil Staps's avatar
Camil Staps committed
56
	struct pollfd pfd={fd,POLLIN,0};
Camil Staps's avatar
Camil Staps committed
57 58
	int poll_n;

Camil Staps's avatar
Camil Staps committed
59 60 61 62 63 64
	char *wds_ptr=CleanStringCharacters (wds_string);
	char *masks_ptr=CleanStringCharacters (masks_string);
	char *names_ptr=CleanStringCharacters (names_string);
	CleanStringLength (wds_string)=0;
	CleanStringLength (masks_string)=0;
	CleanStringLength (names_string)=0;
Camil Staps's avatar
Camil Staps committed
65

Camil Staps's avatar
Camil Staps committed
66 67
	*re_ok=0;
	*re_fd=fd;
Camil Staps's avatar
Camil Staps committed
68

Camil Staps's avatar
Camil Staps committed
69 70 71
	*re_wds=(CleanString) wds_string;
	*re_masks=(CleanString) masks_string;
	*re_fnames=(CleanString) names_string;
Camil Staps's avatar
Camil Staps committed
72

Camil Staps's avatar
Camil Staps committed
73 74 75
	for (;;){
		poll_n=poll (&pfd,1,0);
		if (poll_n<0)
Camil Staps's avatar
Camil Staps committed
76
			return;
Camil Staps's avatar
Camil Staps committed
77
		if (poll_n==0)
Camil Staps's avatar
Camil Staps committed
78 79
			break;

Camil Staps's avatar
Camil Staps committed
80 81
		len=read (fd,buf,sizeof (buf));
		if (len==-1 && errno!=EAGAIN)
Camil Staps's avatar
Camil Staps committed
82
			return;
Camil Staps's avatar
Camil Staps committed
83
		if (len<=0)
Camil Staps's avatar
Camil Staps committed
84 85
			break;

Camil Staps's avatar
Camil Staps committed
86 87
		for (ptr=buf; ptr<buf+len; ptr+=sizeof (struct inotify_event)+ev->len){
			ev=(const struct inotify_event*) ptr;
Camil Staps's avatar
Camil Staps committed
88

Camil Staps's avatar
Camil Staps committed
89 90 91
			memcpy (masks_ptr,&ev->mask,4);
			masks_ptr+=4;
			CleanStringLength (masks_string)+=4;
Camil Staps's avatar
Camil Staps committed
92

Camil Staps's avatar
Camil Staps committed
93 94 95
			memcpy (wds_ptr,&ev->wd,sizeof (int));
			wds_ptr+=sizeof (int);
			CleanStringLength (wds_string)+=sizeof (int);
96

97 98 99 100
			memcpy (names_ptr,&ev->name,ev->len);
			names_ptr+=ev->len+1;
			*(names_ptr-1)='\0';
			CleanStringLength (names_string)+=ev->len+1;
Camil Staps's avatar
Camil Staps committed
101 102 103
		}
	}

Camil Staps's avatar
Camil Staps committed
104
	*re_ok=1;
Camil Staps's avatar
Camil Staps committed
105
}