summaryrefslogtreecommitdiff
path: root/source3/smbd/notify_kernel.c
diff options
context:
space:
mode:
Diffstat (limited to 'source3/smbd/notify_kernel.c')
-rw-r--r--source3/smbd/notify_kernel.c287
1 files changed, 0 insertions, 287 deletions
diff --git a/source3/smbd/notify_kernel.c b/source3/smbd/notify_kernel.c
deleted file mode 100644
index f90414dc79..0000000000
--- a/source3/smbd/notify_kernel.c
+++ /dev/null
@@ -1,287 +0,0 @@
-/*
- Unix SMB/Netbios implementation.
- Version 3.0
- change notify handling - linux kernel based implementation
- Copyright (C) Andrew Tridgell 2000
- Copyright (C) Volker Lendecke 2007
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
-*/
-
-#include "includes.h"
-
-#if HAVE_KERNEL_CHANGE_NOTIFY
-
-#ifndef DN_ACCESS
-#define DN_ACCESS 0x00000001 /* File accessed in directory */
-#define DN_MODIFY 0x00000002 /* File modified in directory */
-#define DN_CREATE 0x00000004 /* File created in directory */
-#define DN_DELETE 0x00000008 /* File removed from directory */
-#define DN_RENAME 0x00000010 /* File renamed in directory */
-#define DN_ATTRIB 0x00000020 /* File changed attribute */
-#define DN_MULTISHOT 0x80000000 /* Don't remove notifier */
-#endif
-
-
-#ifndef RT_SIGNAL_NOTIFY
-#define RT_SIGNAL_NOTIFY (SIGRTMIN+2)
-#endif
-
-#ifndef F_SETSIG
-#define F_SETSIG 10
-#endif
-
-#ifndef F_NOTIFY
-#define F_NOTIFY 1026
-#endif
-
-/****************************************************************************
- This is the structure to keep the information needed to
- determine if a directory has changed.
-*****************************************************************************/
-
-struct dnotify_ctx {
- struct dnotify_ctx *prev, *next;
-
- int fd;
- files_struct *fsp;
-};
-
-static struct dnotify_ctx *dnotify_list;
-static int dnotify_signal_pipe[2];
-
-/****************************************************************************
- The signal handler for change notify.
- The Linux kernel has a bug in that we should be able to block any
- further delivery of RT signals until the kernel_check_notify() function
- unblocks them, but it seems that any signal mask we're setting here is
- being overwritten on exit from this handler. I should create a standalone
- test case for the kernel hackers. JRA.
-*****************************************************************************/
-
-static void dnotify_signal_handler(int sig, siginfo_t *info, void *unused)
-{
- int saved_errno;
-
- /*
- * According to http://www.opengroup.org/onlinepubs/009695399/ write
- * to a pipe either writes all or nothing, so we can safely write a
- * full sizeof(int) and not risk the pipe to become out of sync with
- * the receiving end.
- *
- * We don't care about the result of the write() call. If the pipe is
- * full, then this signal is lost, we can't do anything about it.
- */
-
- saved_errno = errno;
- write(dnotify_signal_pipe[1], (const void *)&info->si_fd, sizeof(int));
- errno = saved_errno;
-
- sys_select_signal(RT_SIGNAL_NOTIFY);
-}
-
-/****************************************************************************
- The upper level handler informed when the pipe is ready for reading
-*****************************************************************************/
-
-static void dnotify_pipe_handler(struct event_context *event_ctx,
- struct fd_event *event,
- uint16 flags,
- void *private_data)
-{
- int res, fd;
- struct dnotify_ctx *ctx;
-
- res = read(dnotify_signal_pipe[0], (void *)&fd, sizeof(int));
-
- if (res == -1) {
- DEBUG(0, ("Read from the dnotify pipe failed: %s\n",
- strerror(errno)));
- TALLOC_FREE(event); /* Don't try again */
- return;
- }
-
- if (res != sizeof(int)) {
- smb_panic("read from dnotify pipe gave wrong number of "
- "bytes\n");
- }
-
- for (ctx = dnotify_list; ctx; ctx = ctx->next) {
- if (ctx->fd == fd) {
- notify_fsp(ctx->fsp, 0, NULL);
- }
- }
-}
-
-/****************************************************************************
- Register a change notify request.
-*****************************************************************************/
-
-static int kernel_register_notify(connection_struct *conn, char *path,
- uint32 flags)
-{
- int fd;
- unsigned long kernel_flags;
-
- fd = sys_open(path,O_RDONLY, 0);
-
- if (fd == -1) {
- DEBUG(3,("Failed to open directory %s for change notify\n",
- path));
- return -1;
- }
-
- if (sys_fcntl_long(fd, F_SETSIG, RT_SIGNAL_NOTIFY) == -1) {
- DEBUG(3,("Failed to set signal handler for change notify\n"));
- close(fd);
- return -1;
- }
-
- kernel_flags = DN_CREATE|DN_DELETE|DN_RENAME; /* creation/deletion
- * changes
- * everything! */
- if (flags & FILE_NOTIFY_CHANGE_FILE_NAME) kernel_flags |= DN_MODIFY;
- if (flags & FILE_NOTIFY_CHANGE_DIR_NAME) kernel_flags
- |= DN_RENAME
- |DN_DELETE;
- if (flags & FILE_NOTIFY_CHANGE_ATTRIBUTES) kernel_flags |= DN_ATTRIB;
- if (flags & FILE_NOTIFY_CHANGE_SIZE) kernel_flags |= DN_MODIFY;
- if (flags & FILE_NOTIFY_CHANGE_LAST_WRITE) kernel_flags |= DN_MODIFY;
- if (flags & FILE_NOTIFY_CHANGE_LAST_ACCESS) kernel_flags |= DN_ACCESS;
- if (flags & FILE_NOTIFY_CHANGE_CREATION) kernel_flags |= DN_CREATE;
- if (flags & FILE_NOTIFY_CHANGE_SECURITY) kernel_flags |= DN_ATTRIB;
- if (flags & FILE_NOTIFY_CHANGE_EA) kernel_flags |= DN_ATTRIB;
- if (flags & FILE_NOTIFY_CHANGE_FILE_NAME) kernel_flags
- |= DN_RENAME
- |DN_DELETE;
-
- if (sys_fcntl_long(fd, F_NOTIFY, kernel_flags) == -1) {
- DEBUG(3,("Failed to set async flag for change notify\n"));
- close(fd);
- return -1;
- }
-
- DEBUG(3,("kernel change notify on %s (ntflags=0x%x flags=0x%x) "
- "fd=%d\n", path, (int)flags, (int)kernel_flags, fd));
-
- return fd;
-}
-
-/****************************************************************************
- See if the kernel supports change notify.
-****************************************************************************/
-
-static BOOL kernel_notify_available(void)
-{
- int fd, ret;
- fd = open("/tmp", O_RDONLY);
- if (fd == -1)
- return False; /* uggh! */
- ret = sys_fcntl_long(fd, F_NOTIFY, 0);
- close(fd);
- return ret == 0;
-}
-
-static int dnotify_ctx_destructor(struct dnotify_ctx *ctx)
-{
- close(ctx->fd);
- DLIST_REMOVE(dnotify_list, ctx);
- return 0;
-}
-
-static void *kernel_notify_add(TALLOC_CTX *mem_ctx,
- struct event_context *event_ctx,
- files_struct *fsp,
- uint32 *filter)
-{
- struct dnotify_ctx *ctx;
-
- if (!(ctx = TALLOC_P(mem_ctx, struct dnotify_ctx))) {
- DEBUG(0, ("talloc failed\n"));
- return NULL;
- }
-
- ctx->fsp = fsp;
- ctx->fd = kernel_register_notify(fsp->conn, fsp->fsp_name, *filter);
-
- if (ctx->fd == -1) {
- TALLOC_FREE(ctx);
- return NULL;
- }
-
- DLIST_ADD(dnotify_list, ctx);
- talloc_set_destructor(ctx, dnotify_ctx_destructor);
-
- return ctx;
-}
-
-/****************************************************************************
- Setup kernel based change notify.
-****************************************************************************/
-
-struct cnotify_fns *kernel_notify_init(struct event_context *event_ctx)
-{
- static struct cnotify_fns cnotify;
- struct sigaction act;
-
- if (pipe(dnotify_signal_pipe) == -1) {
- DEBUG(0, ("Failed to create signal pipe: %s\n",
- strerror(errno)));
- return NULL;
- }
-
- if ((set_blocking(dnotify_signal_pipe[0], False) == -1)
- || (set_blocking(dnotify_signal_pipe[1], False) == -1)) {
- DEBUG(0, ("Failed to set signal pipe to non-blocking: %s\n",
- strerror(errno)));
- close(dnotify_signal_pipe[0]);
- close(dnotify_signal_pipe[1]);
- return NULL;
- }
-
- if (event_add_fd(event_ctx, NULL, dnotify_signal_pipe[0],
- EVENT_FD_READ, dnotify_pipe_handler, NULL) == NULL) {
- DEBUG(0, ("Failed to set signal event handler\n"));
- close(dnotify_signal_pipe[0]);
- close(dnotify_signal_pipe[1]);
- return NULL;
- }
-
- ZERO_STRUCT(act);
-
- act.sa_sigaction = dnotify_signal_handler;
- act.sa_flags = SA_SIGINFO;
- sigemptyset( &act.sa_mask );
- if (sigaction(RT_SIGNAL_NOTIFY, &act, NULL) != 0) {
- DEBUG(0,("Failed to setup RT_SIGNAL_NOTIFY handler\n"));
- return NULL;
- }
-
- if (!kernel_notify_available())
- return NULL;
-
- cnotify.notify_add = kernel_notify_add;
-
- /* the signal can start off blocked due to a bug in bash */
- BlockSignals(False, RT_SIGNAL_NOTIFY);
-
- return &cnotify;
-}
-
-#else
- void notify_kernel_dummy(void);
-
- void notify_kernel_dummy(void) {}
-#endif /* HAVE_KERNEL_CHANGE_NOTIFY */