1/* 2 Unix SMB/CIFS implementation. 3 4 Copyright (C) Andrew Tridgell 2006 5 6 This program is free software; you can redistribute it and/or modify 7 it under the terms of the GNU General Public License as published by 8 the Free Software Foundation; either version 3 of the License, or 9 (at your option) any later version. 10 11 This program is distributed in the hope that it will be useful, 12 but WITHOUT ANY WARRANTY; without even the implied warranty of 13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 GNU General Public License for more details. 15 16 You should have received a copy of the GNU General Public License 17 along with this program. If not, see <http://www.gnu.org/licenses/>. 18*/ 19 20/* 21 abstract the various kernel interfaces to change notify into a 22 single Samba friendly interface 23*/ 24 25#include "includes.h" 26#include "system/filesys.h" 27#include "ntvfs/sysdep/sys_notify.h" 28#include "../lib/tevent/tevent.h" 29#include "../lib/util/dlinklist.h" 30#include "param/param.h" 31 32/* list of registered backends */ 33static struct sys_notify_backend *backends; 34static uint32_t num_backends; 35 36#define NOTIFY_BACKEND "notify:backend" 37 38/* 39 initialise a system change notify backend 40*/ 41_PUBLIC_ struct sys_notify_context *sys_notify_context_create(struct share_config *scfg, 42 TALLOC_CTX *mem_ctx, 43 struct tevent_context *ev) 44{ 45 struct sys_notify_context *ctx; 46 const char *bname; 47 int i; 48 49 if (num_backends == 0) { 50 return NULL; 51 } 52 53 if (ev == NULL) { 54 return NULL; 55 } 56 57 ctx = talloc_zero(mem_ctx, struct sys_notify_context); 58 if (ctx == NULL) { 59 return NULL; 60 } 61 62 ctx->ev = ev; 63 64 bname = share_string_option(scfg, NOTIFY_BACKEND, NULL); 65 if (!bname) { 66 if (num_backends) { 67 bname = backends[0].name; 68 } else { 69 bname = "__unknown__"; 70 } 71 } 72 73 for (i=0;i<num_backends;i++) { 74 char *enable_opt_name; 75 bool enabled; 76 77 enable_opt_name = talloc_asprintf(mem_ctx, "notify:%s", 78 backends[i].name); 79 enabled = share_bool_option(scfg, enable_opt_name, true); 80 talloc_free(enable_opt_name); 81 82 if (!enabled) 83 continue; 84 85 if (strcasecmp(backends[i].name, bname) == 0) { 86 bname = backends[i].name; 87 break; 88 } 89 } 90 91 ctx->name = bname; 92 ctx->notify_watch = NULL; 93 94 if (i < num_backends) { 95 ctx->notify_watch = backends[i].notify_watch; 96 } 97 98 return ctx; 99} 100 101/* 102 add a watch 103 104 note that this call must modify the e->filter and e->subdir_filter 105 bits to remove ones handled by this backend. Any remaining bits will 106 be handled by the generic notify layer 107*/ 108_PUBLIC_ NTSTATUS sys_notify_watch(struct sys_notify_context *ctx, 109 struct notify_entry *e, 110 sys_notify_callback_t callback, 111 void *private_data, void *handle) 112{ 113 if (!ctx->notify_watch) { 114 return NT_STATUS_INVALID_SYSTEM_SERVICE; 115 } 116 return ctx->notify_watch(ctx, e, callback, private_data, handle); 117} 118 119/* 120 register a notify backend 121*/ 122_PUBLIC_ NTSTATUS sys_notify_register(struct sys_notify_backend *backend) 123{ 124 struct sys_notify_backend *b; 125 b = talloc_realloc(talloc_autofree_context(), backends, 126 struct sys_notify_backend, num_backends+1); 127 NT_STATUS_HAVE_NO_MEMORY(b); 128 backends = b; 129 backends[num_backends] = *backend; 130 num_backends++; 131 return NT_STATUS_OK; 132} 133 134_PUBLIC_ NTSTATUS sys_notify_init(void) 135{ 136 static bool initialized = false; 137 extern NTSTATUS sys_notify_inotify_init(void); 138 139 init_module_fn static_init[] = { STATIC_sys_notify_MODULES }; 140 141 if (initialized) return NT_STATUS_OK; 142 initialized = true; 143 144 run_init_functions(static_init); 145 146 return NT_STATUS_OK; 147} 148