Implement EVFILT_FS (partially)

This commit is contained in:
Lubos Dolezel 2017-04-21 09:54:13 +02:00
parent 9f7cfeaef7
commit b5750589d7
3 changed files with 142 additions and 4 deletions

View File

@ -76,6 +76,7 @@ else()
src/linux/read.c
src/linux/proc.c
src/linux/machport.c
src/linux/fs.c
src/common/*.h
src/common/filter.c
src/common/knote.c

View File

@ -31,6 +31,7 @@ extern const struct filter evfilt_proc;
extern const struct filter evfilt_timer;
extern const struct filter evfilt_user;
extern const struct filter evfilt_machport;
extern const struct filter evfilt_fs;
static int
filter_register(struct kqueue *kq, short filter, const struct filter *src)
@ -104,6 +105,7 @@ filter_register_all(struct kqueue *kq)
rv += filter_register(kq, EVFILT_TIMER, &evfilt_timer);
rv += filter_register(kq, EVFILT_USER, &evfilt_user);
rv += filter_register(kq, EVFILT_MACHPORT, &evfilt_machport);
rv += filter_register(kq, EVFILT_FS, &evfilt_fs);
kq->kq_nfds++;
if (rv != 0) {
filter_unregister_all(kq);
@ -168,11 +170,12 @@ filter_name(short filt)
"EVFILT_SIGNAL",
"EVFILT_TIMER",
"EVFILT_MACHPORT",
"EVFILT_FS",
// "EVFILT_LIO",
"EVFILT_FS",
"EVFILT_USER",
// EVFILT_VM!
"EVFILT_NETDEV",
"EVFILT_VM",
"EVFILT_SOCK",
"EVFILT_MEMORYSTATUS",
"EVFILT_EXCEPT",
};
id = ~filt;

134
src/linux/fs.c Normal file
View File

@ -0,0 +1,134 @@
/*
* Copyright (c) 2017 Lubos Dolezel
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#include <errno.h>
#include <fcntl.h>
#include <sys/ioctl.h>
#include <pthread.h>
#include <signal.h>
#include <stdlib.h>
#include <stdio.h>
#include <sys/ioctl.h>
#include <sys/queue.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <sys/mount.h>
#include <string.h>
#include <unistd.h>
#include "private.h"
int
evfilt_fs_copyout(struct kevent64_s *dst, struct knote *src, void *ptr)
{
struct epoll_event * const ev = (struct epoll_event *) ptr;
epoll_event_dump(ev);
kevent_int_to_64(&src->kev, dst);
// TODO: filter out events
// TODO: provide real event fflags
dst->fflags = VQ_MOUNT;
return (0);
}
int
evfilt_fs_knote_create(struct filter *filt, struct knote *kn)
{
struct epoll_event ev;
/* Convert the kevent into an epoll_event */
kn->data.events = EPOLLERR;
kn->kn_epollfd = filter_epfd(filt);
memset(&ev, 0, sizeof(ev));
ev.events = kn->data.events;
ev.data.ptr = kn;
kn->kdata.kn_dupfd = open("/proc/mounts", O_RDONLY);
if (kn->kdata.kn_dupfd == -1) {
dbg_printf("open /proc/mounts: %s", strerror(errno));
return (-1);
}
if (epoll_ctl(kn->kn_epollfd, EPOLL_CTL_ADD, kn->kdata.kn_dupfd, &ev) < 0) {
dbg_printf("epoll_ctl(2): %s", strerror(errno));
return (-1);
}
return 0;
}
int
evfilt_fs_knote_modify(struct filter *filt, struct knote *kn,
const struct kevent64_s *kev)
{
return 0;
}
int
evfilt_fs_knote_delete(struct filter *filt, struct knote *kn)
{
if (kn->kev.flags & EV_DISABLE)
return (0);
else {
if (epoll_ctl(kn->kn_epollfd, EPOLL_CTL_DEL, kn->kdata.kn_dupfd, NULL) < 0) {
dbg_perror("epoll_ctl(2)");
return (-1);
}
(void) close(kn->kdata.kn_dupfd);
kn->kdata.kn_dupfd = -1;
return 0;
}
}
int
evfilt_fs_knote_enable(struct filter *filt, struct knote *kn)
{
struct epoll_event ev;
memset(&ev, 0, sizeof(ev));
ev.events = kn->data.events;
ev.data.ptr = kn;
if (epoll_ctl(kn->kn_epollfd, EPOLL_CTL_ADD, kn->kdata.kn_dupfd, &ev) < 0) {
dbg_perror("epoll_ctl(2)");
return (-1);
}
return (0);
}
int
evfilt_fs_knote_disable(struct filter *filt, struct knote *kn)
{
if (epoll_ctl(kn->kn_epollfd, EPOLL_CTL_DEL, kn->kdata.kn_dupfd, NULL) < 0) {
dbg_perror("epoll_ctl(2)");
return (-1);
}
return (0);
}
const struct filter evfilt_fs = {
EVFILT_MACHPORT,
NULL,
NULL,
evfilt_fs_copyout,
evfilt_fs_knote_create,
evfilt_fs_knote_modify,
evfilt_fs_knote_delete,
evfilt_fs_knote_enable,
evfilt_fs_knote_disable,
};