データ構造 | |
struct | notify_context |
struct | notify_list |
関数 | |
static NTSTATUS | notify_remove_all (struct notify_context *notify, const struct server_id *server) |
static void | notify_handler (struct messaging_context *msg_ctx, void *private_data, uint32_t msg_type, struct server_id server_id, DATA_BLOB *data) |
static int | notify_destructor (struct notify_context *notify) |
notify_context * | notify_init (TALLOC_CTX *mem_ctx, struct server_id server, struct messaging_context *messaging_ctx, struct event_context *ev, connection_struct *conn) |
static NTSTATUS | notify_lock (struct notify_context *notify) |
static void | notify_unlock (struct notify_context *notify) |
static NTSTATUS | notify_load (struct notify_context *notify) |
static int | notify_compare (const void *p1, const void *p2) |
static NTSTATUS | notify_save (struct notify_context *notify) |
static void | notify_handler (struct messaging_context *msg_ctx, void *private_data, uint32_t msg_type, struct server_id server_id, DATA_BLOB *data) |
static void | sys_notify_callback (struct sys_notify_context *ctx, void *ptr, struct notify_event *ev) |
static NTSTATUS | notify_add_array (struct notify_context *notify, struct notify_entry *e, void *private_data, int depth) |
NTSTATUS | notify_add (struct notify_context *notify, struct notify_entry *e0, void(*callback)(void *, const struct notify_event *), void *private_data) |
NTSTATUS | notify_remove (struct notify_context *notify, void *private_data) |
static NTSTATUS | notify_send (struct notify_context *notify, struct notify_entry *e, const char *path, uint32_t action) |
void | notify_trigger (struct notify_context *notify, uint32_t action, uint32_t filter, const char *path) |
static NTSTATUS notify_remove_all | ( | struct notify_context * | notify, | |
const struct server_id * | server | |||
) | [static] |
notify_internal.c の 501 行で定義されています。
参照先 notify_context::array・cluster_id_equal()・notify_array::depth・notify_load()・notify_lock()・notify_unlock()・notify_array::num_depths・notify_depth::num_entries・server・status.
参照元 notify_destructor()・notify_trigger().
00503 { 00504 NTSTATUS status; 00505 int i, depth, del_count=0; 00506 00507 status = notify_lock(notify); 00508 NT_STATUS_NOT_OK_RETURN(status); 00509 00510 status = notify_load(notify); 00511 if (!NT_STATUS_IS_OK(status)) { 00512 notify_unlock(notify); 00513 return status; 00514 } 00515 00516 /* we have to search for all entries across all depths, looking for matches 00517 for the server id */ 00518 for (depth=0;depth<notify->array->num_depths;depth++) { 00519 struct notify_depth *d = ¬ify->array->depth[depth]; 00520 for (i=0;i<d->num_entries;i++) { 00521 if (cluster_id_equal(server, &d->entries[i].server)) { 00522 if (i < d->num_entries-1) { 00523 memmove(&d->entries[i], &d->entries[i+1], 00524 sizeof(d->entries[i])*(d->num_entries-(i+1))); 00525 } 00526 i--; 00527 d->num_entries--; 00528 del_count++; 00529 } 00530 } 00531 } 00532 00533 if (del_count > 0) { 00534 status = notify_save(notify); 00535 } 00536 00537 notify_unlock(notify); 00538 00539 return status; 00540 }
static void notify_handler | ( | struct messaging_context * | msg_ctx, | |
void * | private_data, | |||
uint32_t | msg_type, | |||
struct server_id | server_id, | |||
DATA_BLOB * | data | |||
) | [static] |
参照元 notify_init().
static int notify_destructor | ( | struct notify_context * | notify | ) | [static] |
notify_internal.c の 62 行で定義されています。
参照先 notify_context::list・notify_context::messaging_ctx・messaging_deregister()・notify_remove_all()・notify_context::server.
参照元 notify_init().
00063 { 00064 messaging_deregister(notify->messaging_ctx, MSG_PVFS_NOTIFY, notify); 00065 00066 if (notify->list != NULL) { 00067 notify_remove_all(notify, ¬ify->server); 00068 } 00069 00070 return 0; 00071 }
struct notify_context* notify_init | ( | TALLOC_CTX * | mem_ctx, | |
struct server_id | server, | |||
struct messaging_context * | messaging_ctx, | |||
struct event_context * | ev, | |||
connection_struct * | conn | |||
) |
notify_internal.c の 78 行で定義されています。
参照先 notify_context::array・notify_context::list・lock_path()・notify_context::messaging_ctx・messaging_register()・notify_destructor()・notify_handler()・connection_struct::params・notify_context::seqnum・server・notify_context::server・sys_notify_context_create()・notify_context::sys_notify_ctx・talloc_free()・tdb_wrap::tdb・tdb_get_seqnum()・tdb_wrap_open()・notify_context::w.
00082 { 00083 struct notify_context *notify; 00084 00085 if (!lp_change_notify(conn->params)) { 00086 return NULL; 00087 } 00088 00089 notify = talloc(mem_ctx, struct notify_context); 00090 if (notify == NULL) { 00091 return NULL; 00092 } 00093 00094 notify->w = tdb_wrap_open(notify, lock_path("notify.tdb"), 00095 0, TDB_SEQNUM|TDB_CLEAR_IF_FIRST, 00096 O_RDWR|O_CREAT, 0644); 00097 if (notify->w == NULL) { 00098 talloc_free(notify); 00099 return NULL; 00100 } 00101 00102 notify->server = server; 00103 notify->messaging_ctx = messaging_ctx; 00104 notify->list = NULL; 00105 notify->array = NULL; 00106 notify->seqnum = tdb_get_seqnum(notify->w->tdb); 00107 00108 talloc_set_destructor(notify, notify_destructor); 00109 00110 /* register with the messaging subsystem for the notify 00111 message type */ 00112 messaging_register(notify->messaging_ctx, notify, 00113 MSG_PVFS_NOTIFY, notify_handler); 00114 00115 notify->sys_notify_ctx = sys_notify_context_create(conn, notify, ev); 00116 00117 return notify; 00118 }
static NTSTATUS notify_lock | ( | struct notify_context * | notify | ) | [static] |
notify_internal.c の 124 行で定義されています。
参照先 tdb_wrap::tdb・tdb_lock_bystring()・notify_context::w.
参照元 notify_add()・notify_remove()・notify_remove_all().
00125 { 00126 if (tdb_lock_bystring(notify->w->tdb, NOTIFY_KEY) != 0) { 00127 return NT_STATUS_INTERNAL_DB_CORRUPTION; 00128 } 00129 return NT_STATUS_OK; 00130 }
static void notify_unlock | ( | struct notify_context * | notify | ) | [static] |
notify_internal.c の 135 行で定義されています。
参照先 tdb_wrap::tdb・tdb_unlock_bystring()・notify_context::w.
参照元 notify_add()・notify_remove()・notify_remove_all().
00136 { 00137 tdb_unlock_bystring(notify->w->tdb, NOTIFY_KEY); 00138 }
static NTSTATUS notify_load | ( | struct notify_context * | notify | ) | [static] |
notify_internal.c の 143 行で定義されています。
参照先 notify_context::array・data_blob_::data・DEBUGLEVEL・TDB_DATA::dptr・TDB_DATA::dsize・data_blob_::length・ndr_pull_notify_array()・notify_context::seqnum・status・talloc_free()・tdb_wrap::tdb・tdb_fetch_bystring()・tdb_get_seqnum()・notify_context::w.
参照元 notify_add()・notify_remove()・notify_remove_all()・notify_trigger().
00144 { 00145 TDB_DATA dbuf; 00146 DATA_BLOB blob; 00147 NTSTATUS status; 00148 int seqnum; 00149 00150 seqnum = tdb_get_seqnum(notify->w->tdb); 00151 00152 if (seqnum == notify->seqnum && notify->array != NULL) { 00153 return NT_STATUS_OK; 00154 } 00155 00156 notify->seqnum = seqnum; 00157 00158 talloc_free(notify->array); 00159 notify->array = TALLOC_ZERO_P(notify, struct notify_array); 00160 NT_STATUS_HAVE_NO_MEMORY(notify->array); 00161 00162 dbuf = tdb_fetch_bystring(notify->w->tdb, NOTIFY_KEY); 00163 if (dbuf.dptr == NULL) { 00164 return NT_STATUS_OK; 00165 } 00166 00167 blob.data = (uint8 *)dbuf.dptr; 00168 blob.length = dbuf.dsize; 00169 00170 status = ndr_pull_struct_blob(&blob, notify->array, notify->array, 00171 (ndr_pull_flags_fn_t)ndr_pull_notify_array); 00172 00173 if (DEBUGLEVEL >= 10) { 00174 DEBUG(10, ("notify_load:\n")); 00175 NDR_PRINT_DEBUG(notify_array, notify->array); 00176 } 00177 00178 free(dbuf.dptr); 00179 00180 return status; 00181 }
static int notify_compare | ( | const void * | p1, | |
const void * | p2 | |||
) | [static] |
notify_internal.c の 186 行で定義されています。
参照先 notify_entry::path.
参照元 notify_add_array().
00187 { 00188 const struct notify_entry *e1 = (const struct notify_entry *)p1; 00189 const struct notify_entry *e2 = (const struct notify_entry *)p2; 00190 return strcmp(e1->path, e2->path); 00191 }
static NTSTATUS notify_save | ( | struct notify_context * | notify | ) | [static] |
notify_internal.c の 196 行で定義されています。
参照先 notify_context::array・data_blob_::data・DEBUGLEVEL・notify_array::depth・TDB_DATA::dptr・TDB_DATA::dsize・data_blob_::length・ndr_push_notify_array()・notify_array::num_depths・status・talloc_free()・tdb_wrap::tdb・tdb_delete_bystring()・tdb_store_bystring()・notify_context::w.
参照元 notify_add_array().
00197 { 00198 TDB_DATA dbuf; 00199 DATA_BLOB blob; 00200 NTSTATUS status; 00201 int ret; 00202 TALLOC_CTX *tmp_ctx; 00203 00204 /* if possible, remove some depth arrays */ 00205 while (notify->array->num_depths > 0 && 00206 notify->array->depth[notify->array->num_depths-1].num_entries == 0) { 00207 notify->array->num_depths--; 00208 } 00209 00210 /* we might just be able to delete the record */ 00211 if (notify->array->num_depths == 0) { 00212 ret = tdb_delete_bystring(notify->w->tdb, NOTIFY_KEY); 00213 if (ret != 0) { 00214 return NT_STATUS_INTERNAL_DB_CORRUPTION; 00215 } 00216 return NT_STATUS_OK; 00217 } 00218 00219 tmp_ctx = talloc_new(notify); 00220 NT_STATUS_HAVE_NO_MEMORY(tmp_ctx); 00221 00222 status = ndr_push_struct_blob(&blob, tmp_ctx, notify->array, 00223 (ndr_push_flags_fn_t)ndr_push_notify_array); 00224 if (!NT_STATUS_IS_OK(status)) { 00225 talloc_free(tmp_ctx); 00226 return status; 00227 } 00228 00229 if (DEBUGLEVEL >= 10) { 00230 DEBUG(10, ("notify_save:\n")); 00231 NDR_PRINT_DEBUG(notify_array, notify->array); 00232 } 00233 00234 dbuf.dptr = (char *)blob.data; 00235 dbuf.dsize = blob.length; 00236 00237 ret = tdb_store_bystring(notify->w->tdb, NOTIFY_KEY, dbuf, TDB_REPLACE); 00238 talloc_free(tmp_ctx); 00239 if (ret != 0) { 00240 return NT_STATUS_INTERNAL_DB_CORRUPTION; 00241 } 00242 00243 return NT_STATUS_OK; 00244 }
static void notify_handler | ( | struct messaging_context * | msg_ctx, | |
void * | private_data, | |||
uint32_t | msg_type, | |||
struct server_id | server_id, | |||
DATA_BLOB * | data | |||
) | [static] |
notify_internal.c の 250 行で定義されています。
参照先 notify_list::callback・notify_context::list・ndr_pull_notify_event()・notify_list::next・notify_event::private_data・notify_list::private_data・status・talloc_free().
00252 { 00253 struct notify_context *notify = talloc_get_type(private_data, struct notify_context); 00254 NTSTATUS status; 00255 struct notify_event ev; 00256 TALLOC_CTX *tmp_ctx = talloc_new(notify); 00257 struct notify_list *listel; 00258 00259 if (tmp_ctx == NULL) { 00260 return; 00261 } 00262 00263 status = ndr_pull_struct_blob(data, tmp_ctx, &ev, 00264 (ndr_pull_flags_fn_t)ndr_pull_notify_event); 00265 if (!NT_STATUS_IS_OK(status)) { 00266 talloc_free(tmp_ctx); 00267 return; 00268 } 00269 00270 for (listel=notify->list;listel;listel=listel->next) { 00271 if (listel->private_data == ev.private_data) { 00272 listel->callback(listel->private_data, &ev); 00273 break; 00274 } 00275 } 00276 00277 talloc_free(tmp_ctx); 00278 }
static void sys_notify_callback | ( | struct sys_notify_context * | ctx, | |
void * | ptr, | |||
struct notify_event * | ev | |||
) | [static] |
notify_internal.c の 283 行で定義されています。
参照先 notify_event::action・notify_list::callback・notify_event::path・notify_list::private_data・notify_event::private_data.
参照元 notify_add().
00285 { 00286 struct notify_list *listel = talloc_get_type(ptr, struct notify_list); 00287 ev->private_data = listel; 00288 DEBUG(10, ("sys_notify_callback called with action=%d, for %s\n", 00289 ev->action, ev->path)); 00290 listel->callback(listel->private_data, ev); 00291 }
static NTSTATUS notify_add_array | ( | struct notify_context * | notify, | |
struct notify_entry * | e, | |||
void * | private_data, | |||
int | depth | |||
) | [static] |
notify_internal.c の 296 行で定義されています。
参照先 notify_context::array・notify_array::depth・notify_depth::entries・notify_entry::filter・notify_depth::max_mask・notify_depth::max_mask_subdir・notify_compare()・notify_save()・notify_array::num_depths・notify_depth::num_entries・notify_entry::path・notify_entry::path_len・notify_entry::private_data・notify_context::server・notify_entry::server・notify_entry::subdir_filter.
参照元 notify_add().
00298 { 00299 int i; 00300 struct notify_depth *d; 00301 struct notify_entry *ee; 00302 00303 /* possibly expand the depths array */ 00304 if (depth >= notify->array->num_depths) { 00305 d = talloc_realloc(notify->array, notify->array->depth, 00306 struct notify_depth, depth+1); 00307 NT_STATUS_HAVE_NO_MEMORY(d); 00308 for (i=notify->array->num_depths;i<=depth;i++) { 00309 ZERO_STRUCT(d[i]); 00310 } 00311 notify->array->depth = d; 00312 notify->array->num_depths = depth+1; 00313 } 00314 d = ¬ify->array->depth[depth]; 00315 00316 /* expand the entries array */ 00317 ee = talloc_realloc(notify->array->depth, d->entries, struct notify_entry, 00318 d->num_entries+1); 00319 NT_STATUS_HAVE_NO_MEMORY(ee); 00320 d->entries = ee; 00321 00322 d->entries[d->num_entries] = *e; 00323 d->entries[d->num_entries].private_data = private_data; 00324 d->entries[d->num_entries].server = notify->server; 00325 d->entries[d->num_entries].path_len = strlen(e->path); 00326 d->num_entries++; 00327 00328 d->max_mask |= e->filter; 00329 d->max_mask_subdir |= e->subdir_filter; 00330 00331 if (d->num_entries > 1) { 00332 qsort(d->entries, d->num_entries, sizeof(d->entries[0]), notify_compare); 00333 } 00334 00335 /* recalculate the maximum masks */ 00336 d->max_mask = 0; 00337 d->max_mask_subdir = 0; 00338 00339 for (i=0;i<d->num_entries;i++) { 00340 d->max_mask |= d->entries[i].filter; 00341 d->max_mask_subdir |= d->entries[i].subdir_filter; 00342 } 00343 00344 return notify_save(notify); 00345 }
NTSTATUS notify_add | ( | struct notify_context * | notify, | |
struct notify_entry * | e0, | |||
void(*)(void *, const struct notify_event *) | callback, | |||
void * | private_data | |||
) |
notify_internal.c の 351 行で定義されています。
参照先 notify_list::callback・count_chars()・notify_list::depth・notify_entry::filter・len・notify_context::list・notify_add_array()・notify_load()・notify_lock()・notify_unlock()・notify_entry::path・notify_list::private_data・status・notify_entry::subdir_filter・sys_notify_callback()・notify_context::sys_notify_ctx・notify_list::sys_notify_handle・sys_notify_watch()・talloc_free()・talloc_strndup().
00354 { 00355 struct notify_entry e = *e0; 00356 NTSTATUS status; 00357 char *tmp_path = NULL; 00358 struct notify_list *listel; 00359 size_t len; 00360 int depth; 00361 00362 /* see if change notify is enabled at all */ 00363 if (notify == NULL) { 00364 return NT_STATUS_NOT_IMPLEMENTED; 00365 } 00366 00367 status = notify_lock(notify); 00368 NT_STATUS_NOT_OK_RETURN(status); 00369 00370 status = notify_load(notify); 00371 if (!NT_STATUS_IS_OK(status)) { 00372 goto done; 00373 } 00374 00375 /* cope with /. on the end of the path */ 00376 len = strlen(e.path); 00377 if (len > 1 && e.path[len-1] == '.' && e.path[len-2] == '/') { 00378 tmp_path = talloc_strndup(notify, e.path, len-2); 00379 if (tmp_path == NULL) { 00380 status = NT_STATUS_NO_MEMORY; 00381 goto done; 00382 } 00383 e.path = tmp_path; 00384 } 00385 00386 depth = count_chars(e.path, '/'); 00387 00388 listel = TALLOC_ZERO_P(notify, struct notify_list); 00389 if (listel == NULL) { 00390 status = NT_STATUS_NO_MEMORY; 00391 goto done; 00392 } 00393 00394 listel->private_data = private_data; 00395 listel->callback = callback; 00396 listel->depth = depth; 00397 DLIST_ADD(notify->list, listel); 00398 00399 /* ignore failures from sys_notify */ 00400 if (notify->sys_notify_ctx != NULL) { 00401 /* 00402 this call will modify e.filter and e.subdir_filter 00403 to remove bits handled by the backend 00404 */ 00405 status = sys_notify_watch(notify->sys_notify_ctx, &e, 00406 sys_notify_callback, listel, 00407 &listel->sys_notify_handle); 00408 if (NT_STATUS_IS_OK(status)) { 00409 talloc_steal(listel, listel->sys_notify_handle); 00410 } 00411 } 00412 00413 /* if the system notify handler couldn't handle some of the 00414 filter bits, or couldn't handle a request for recursion 00415 then we need to install it in the array used for the 00416 intra-samba notify handling */ 00417 if (e.filter != 0 || e.subdir_filter != 0) { 00418 status = notify_add_array(notify, &e, private_data, depth); 00419 } 00420 00421 done: 00422 notify_unlock(notify); 00423 talloc_free(tmp_path); 00424 00425 return status; 00426 }
NTSTATUS notify_remove | ( | struct notify_context * | notify, | |
void * | private_data | |||
) |
notify_internal.c の 431 行で定義されています。
参照先 notify_context::array・cluster_id_equal()・notify_array::depth・notify_list::depth・notify_depth::entries・notify_context::list・notify_list::next・notify_load()・notify_lock()・notify_unlock()・notify_array::num_depths・notify_depth::num_entries・notify_entry::private_data・notify_list::private_data・notify_entry::server・notify_context::server・status・talloc_free().
参照元 file_free().
00432 { 00433 NTSTATUS status; 00434 struct notify_list *listel; 00435 int i, depth; 00436 struct notify_depth *d; 00437 00438 /* see if change notify is enabled at all */ 00439 if (notify == NULL) { 00440 return NT_STATUS_NOT_IMPLEMENTED; 00441 } 00442 00443 for (listel=notify->list;listel;listel=listel->next) { 00444 if (listel->private_data == private_data) { 00445 DLIST_REMOVE(notify->list, listel); 00446 break; 00447 } 00448 } 00449 if (listel == NULL) { 00450 return NT_STATUS_OBJECT_NAME_NOT_FOUND; 00451 } 00452 00453 depth = listel->depth; 00454 00455 talloc_free(listel); 00456 00457 status = notify_lock(notify); 00458 NT_STATUS_NOT_OK_RETURN(status); 00459 00460 status = notify_load(notify); 00461 if (!NT_STATUS_IS_OK(status)) { 00462 notify_unlock(notify); 00463 return status; 00464 } 00465 00466 if (depth >= notify->array->num_depths) { 00467 notify_unlock(notify); 00468 return NT_STATUS_OBJECT_NAME_NOT_FOUND; 00469 } 00470 00471 /* we only have to search at the depth of this element */ 00472 d = ¬ify->array->depth[depth]; 00473 00474 for (i=0;i<d->num_entries;i++) { 00475 if (private_data == d->entries[i].private_data && 00476 cluster_id_equal(¬ify->server, &d->entries[i].server)) { 00477 break; 00478 } 00479 } 00480 if (i == d->num_entries) { 00481 notify_unlock(notify); 00482 return NT_STATUS_OBJECT_NAME_NOT_FOUND; 00483 } 00484 00485 if (i < d->num_entries-1) { 00486 memmove(&d->entries[i], &d->entries[i+1], 00487 sizeof(d->entries[i])*(d->num_entries-(i+1))); 00488 } 00489 d->num_entries--; 00490 00491 status = notify_save(notify); 00492 00493 notify_unlock(notify); 00494 00495 return status; 00496 }
static NTSTATUS notify_send | ( | struct notify_context * | notify, | |
struct notify_entry * | e, | |||
const char * | path, | |||
uint32_t | action | |||
) | [static] |
notify_internal.c の 546 行で定義されています。
参照先 notify_event::action・notify_context::messaging_ctx・messaging_send()・ndr_push_notify_event()・notify_event::path・notify_entry::private_data・notify_event::private_data・notify_entry::server・status・talloc_free().
参照元 notify_trigger().
00548 { 00549 struct notify_event ev; 00550 DATA_BLOB data; 00551 NTSTATUS status; 00552 TALLOC_CTX *tmp_ctx; 00553 00554 ev.action = action; 00555 ev.path = path; 00556 ev.private_data = e->private_data; 00557 00558 tmp_ctx = talloc_new(notify); 00559 00560 status = ndr_push_struct_blob(&data, tmp_ctx, &ev, 00561 (ndr_push_flags_fn_t)ndr_push_notify_event); 00562 if (!NT_STATUS_IS_OK(status)) { 00563 talloc_free(tmp_ctx); 00564 return status; 00565 } 00566 00567 status = messaging_send(notify->messaging_ctx, e->server, 00568 MSG_PVFS_NOTIFY, &data); 00569 talloc_free(tmp_ctx); 00570 return status; 00571 }
void notify_trigger | ( | struct notify_context * | notify, | |
uint32_t | action, | |||
uint32_t | filter, | |||
const char * | path | |||
) |
notify_internal.c の 581 行で定義されています。
参照先 notify_context::array・notify_array::depth・notify_depth::entries・notify_depth::max_mask・notify_depth::max_mask_subdir・notify_load()・notify_remove_all()・notify_send()・notify_array::num_depths・notify_depth::num_entries・notify_entry::path・notify_entry::path_len・procid_str_static()・server・status.
参照元 notify_fname().
00583 { 00584 NTSTATUS status; 00585 int depth; 00586 const char *p, *next_p; 00587 00588 DEBUG(10, ("notify_trigger called action=0x%x, filter=0x%x, " 00589 "path=%s\n", (unsigned)action, (unsigned)filter, path)); 00590 00591 /* see if change notify is enabled at all */ 00592 if (notify == NULL) { 00593 return; 00594 } 00595 00596 again: 00597 status = notify_load(notify); 00598 if (!NT_STATUS_IS_OK(status)) { 00599 return; 00600 } 00601 00602 /* loop along the given path, working with each directory depth separately */ 00603 for (depth=0,p=path; 00604 p && depth < notify->array->num_depths; 00605 p=next_p,depth++) { 00606 int p_len = p - path; 00607 int min_i, max_i, i; 00608 struct notify_depth *d = ¬ify->array->depth[depth]; 00609 next_p = strchr(p+1, '/'); 00610 00611 /* see if there are any entries at this depth */ 00612 if (d->num_entries == 0) continue; 00613 00614 /* try to skip based on the maximum mask. If next_p is 00615 NULL then we know it will be a 'this directory' 00616 match, otherwise it must be a subdir match */ 00617 if (next_p != NULL) { 00618 if (0 == (filter & d->max_mask_subdir)) { 00619 continue; 00620 } 00621 } else { 00622 if (0 == (filter & d->max_mask)) { 00623 continue; 00624 } 00625 } 00626 00627 /* we know there is an entry here worth looking 00628 for. Use a bisection search to find the first entry 00629 with a matching path */ 00630 min_i = 0; 00631 max_i = d->num_entries-1; 00632 00633 while (min_i < max_i) { 00634 struct notify_entry *e; 00635 int cmp; 00636 i = (min_i+max_i)/2; 00637 e = &d->entries[i]; 00638 cmp = strncmp(path, e->path, p_len); 00639 if (cmp == 0) { 00640 if (p_len == e->path_len) { 00641 max_i = i; 00642 } else { 00643 max_i = i-1; 00644 } 00645 } else if (cmp < 0) { 00646 max_i = i-1; 00647 } else { 00648 min_i = i+1; 00649 } 00650 } 00651 00652 if (min_i != max_i) { 00653 /* none match */ 00654 continue; 00655 } 00656 00657 /* we now know that the entries start at min_i */ 00658 for (i=min_i;i<d->num_entries;i++) { 00659 struct notify_entry *e = &d->entries[i]; 00660 if (p_len != e->path_len || 00661 strncmp(path, e->path, p_len) != 0) break; 00662 if (next_p != NULL) { 00663 if (0 == (filter & e->subdir_filter)) { 00664 continue; 00665 } 00666 } else { 00667 if (0 == (filter & e->filter)) { 00668 continue; 00669 } 00670 } 00671 status = notify_send(notify, e, path + e->path_len + 1, 00672 action); 00673 00674 if (NT_STATUS_EQUAL( 00675 status, NT_STATUS_INVALID_HANDLE)) { 00676 struct server_id server = e->server; 00677 00678 DEBUG(10, ("Deleting notify entries for " 00679 "process %s because it's gone\n", 00680 procid_str_static(&e->server.id))); 00681 notify_remove_all(notify, &server); 00682 goto again; 00683 } 00684 } 00685 } 00686 }