#include <errno.h>
#include <fcntl.h>
#include <pthread.h>
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <strings.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include "testlib.h"
#include "mevent.h"
static char *cookie = "Shortcake";
static pthread_mutex_t mtx = PTHREAD_MUTEX_INITIALIZER;
static pthread_cond_t cv = PTHREAD_COND_INITIALIZER;
static void
callback(int fd, enum ev_type ev, void *arg)
{
static off_t size = 0;
struct stat st;
ASSERT_INT_EQ(("bad event"), ev, EVF_VNODE);
ASSERT_PTR_EQ(("bad cookie"), arg, cookie);
if (fstat(fd, &st) != 0)
FAIL_ERRNO("fstat failed");
ASSERT_INT64_NEQ(("File size has not changed"), size, st.st_size);
size = st.st_size;
pthread_mutex_lock(&mtx);
pthread_cond_signal(&cv);
VERBOSE(("wakeup"));
pthread_mutex_unlock(&mtx);
}
static void
test_fd(int fd, char *tag)
{
struct mevent *evp;
int err;
evp = mevent_add_flags(fd, EVF_VNODE, EVFF_ATTRIB, callback, cookie);
ASSERT_PTR_NEQ(("%s: mevent_add", tag), evp, NULL);
for (uint_t i = 0; cookie[i] != '\0'; i++) {
ssize_t written;
if (i > 0) {
if (lseek(fd, -1, SEEK_CUR) == -1)
FAIL_ERRNO("lseek");
if (write(fd, "X", 1) == -1)
FAIL_ERRNO("write");
VERBOSE(("Write within"));
usleep(100);
}
pthread_mutex_lock(&mtx);
written = write(fd, cookie + i, 1);
if (written < 0)
FAIL_ERRNO("bad write");
ASSERT_INT64_EQ(("write byte %d of cookie", i), written, 1);
VERBOSE(("Write extend"));
pthread_cond_wait(&cv, &mtx);
pthread_mutex_unlock(&mtx);
usleep(100);
}
err = mevent_disable(evp);
ASSERT_INT_EQ(("%s: mevent_disable: %s", tag, strerror(err)), err, 0);
(void) printf("PASS %s - %s\n", testlib_prog, tag);
}
int
main(int argc, const char **argv)
{
int fd;
start_test(argv[0], 20);
set_mevent_file_poll_interval_ms(500);
start_event_thread();
char *template = strdup("/tmp/mevent.vnode.XXXXXX");
ASSERT_PTR_NEQ(("strdup"), template, NULL);
fd = mkstemp(template);
if (fd == -1)
FAIL_ERRNO("Couldn't create temporary file with mkstemp");
VERBOSE(("Opened temporary file at '%s'", template));
test_fd(fd, "temporary file");
FILE *fp = tmpfile();
ASSERT_PTR_NEQ(("tmpfile"), fp, NULL);
fd = fileno(fp);
if (fd == -1)
FAIL_ERRNO("Couldn't get file descriptor for temporary file");
test_fd(fd, "anon file");
unlink(template);
free(template);
PASS();
}