- if ((type == FSE_RENAME || type == FSE_EXCHANGE) && reuse_type != KFSE_RECYCLED) {
- panic("add_fsevent: type == %d but reuse type == %d!\n", type, reuse_type);
- } else if ((kfse->type == FSE_RENAME || kfse->type == FSE_EXCHANGE) && kfse->dest == NULL) {
- panic("add_fsevent: bogus kfse %p (type %d, but dest is NULL)\n", kfse, kfse->type);
- } else if (kfse->type == FSE_RENAME || kfse->type == FSE_EXCHANGE) {
- panic("add_fsevent: we should never re-use rename events (kfse %p reuse type %d)!\n", kfse, reuse_type);
- }
-
- if (reuse_type == KFSE_COLLAPSED) {
- if (str) {
- const char *tmp_ptr, *new_str;
-
- //
- // if we collapsed and have a string we have to chop off the
- // tail component of the pathname to get the parent.
- //
- // NOTE: it is VERY IMPORTANT that we leave the trailing slash
- // on the pathname. user-level code depends on this.
- //
- if (str[0] == '\0' || longest_match_len <= 1) {
- printf("add_fsevent: strange state (str %s / longest_match_len %d)\n", str, longest_match_len);
- if (longest_match_len < 0) {
- panic("add_fsevent: longest_match_len %d\n", longest_match_len);
- }
- }
- // chop off the tail component if it's not the
- // first character...
- if (longest_match_len > 1) {
- str[longest_match_len] = '\0';
- } else if (longest_match_len == 0) {
- longest_match_len = 1;
- }
-
- new_str = vfs_addname(str, longest_match_len, 0, 0);
- if (new_str == NULL || new_str[0] == '\0') {
- panic("add_fsevent: longest match is strange (new_str %p).\n", new_str);
- }
-
- lck_rw_lock_exclusive(&event_handling_lock);
-
- kfse->len = longest_match_len;
- tmp_ptr = kfse->str;
- kfse->str = new_str;
- kfse->ino = 0;
- kfse->mode = 0;
- kfse->uid = 0;
- kfse->gid = 0;
-
- lck_rw_unlock_exclusive(&event_handling_lock);
-
- vfs_removename(tmp_ptr);
- } else {
- panic("add_fsevent: don't have a vnode or a string pointer (kfse %p)\n", kfse);
- }
- }
-
- if (reuse_type == KFSE_RECYCLED && (type == FSE_RENAME || type == FSE_EXCHANGE)) {
-
- // if we're recycling this kfse and we have a rename or
- // exchange event then we need to also get an event for
- // kfse_dest.
- //
- if (did_alloc) {
- // only happens if we allocated one but then failed
- // for kfse_dest (and thus free'd the first one we
- // allocated)
- kfse_dest = zalloc_noblock(event_zone);
- if (kfse_dest != NULL) {
- memset(kfse_dest, 0, sizeof(kfs_event));
- kfse_dest->refcount = 1;
- OSBitOrAtomic16(KFSE_BEING_CREATED, &kfse_dest->flags);
- } else {
- did_alloc = 0;
- }
- }
-
- if (kfse_dest == NULL) {
- int dest_reuse_type, dest_match_len;
-
- kfse_dest = find_an_event(NULL, 0, kfse, &dest_reuse_type, &dest_match_len);
-
- if (kfse_dest == NULL) {
- // nothing we can do... gotta bail out
- goto bail_early;
- }
-
- if (dest_reuse_type != KFSE_RECYCLED) {
- panic("add_fsevent: type == %d but dest_reuse type == %d!\n", type, dest_reuse_type);
- }
- }
- }
-
-
- //
- // Here we check for some fast-path cases so that we can
- // jump over the normal initialization and just get on
- // with delivering the event. These cases are when we're
- // combining/collapsing an event and so basically there is
- // no more work to do (aside from a little book-keeping)
- //
- if (str && kfse->len != 0) {
- kfse->abstime = now;
- OSAddAtomic(1, &kfse->refcount);
- skip_init = 1;
-
- if (reuse_type == KFSE_COMBINED) {
- num_combined_events++;
- } else if (reuse_type == KFSE_COLLAPSED) {
- num_added_to_parent++;
- }
- } else if (reuse_type != KFSE_RECYCLED) {
- panic("add_fsevent: I'm so confused! (reuse_type %d str %p kfse->len %d)\n",
- reuse_type, str, kfse->len);
- }
-
- va_end(ap);
-
-
- if (skip_init) {
- if (kfse->refcount < 1) {
- panic("add_fsevent: line %d: kfse recount %d but should be at least 1\n", __LINE__, kfse->refcount);
- }
-
- last_event_ptr = kfse;
- unlock_fs_event_list();
- goto normal_delivery;
-
- } else if (reuse_type == KFSE_RECYCLED || reuse_type == KFSE_COMBINED) {
-
- //
- // If we're here we have to clear out the kfs_event(s)
- // that we were given by find_an_event() and set it
- // up to be re-filled in by the normal code path.
- //
- va_start(ap, ctx);
-
- need_event_unlock = 1;
- lck_rw_lock_exclusive(&event_handling_lock);
-
- OSAddAtomic(1, &kfse->refcount);
-
- if (kfse->refcount < 1) {
- panic("add_fsevent: line %d: kfse recount %d but should be at least 1\n", __LINE__, kfse->refcount);
- }
-
- if (kfse->len == 0) {
- panic("%s:%d: no more fref.vp\n", __FILE__, __LINE__);
- // vnode_rele_ext(kfse->fref.vp, O_EVTONLY, 0);
- } else {
- vfs_removename(kfse->str);
- kfse->len = 0;
- }
- kfse->str = NULL;
-
- if (kfse->kevent_list.le_prev != NULL) {
- num_events_outstanding--;
- if (kfse->type == FSE_RENAME) {
- num_pending_rename--;
- }
- LIST_REMOVE(kfse, kevent_list);
- memset(&kfse->kevent_list, 0, sizeof(kfse->kevent_list));
- }
-
- kfse->flags = 0 | KFSE_RECYCLED_EVENT;
-
- if (kfse_dest) {
- OSAddAtomic(1, &kfse_dest->refcount);
- kfse_dest->flags = 0 | KFSE_RECYCLED_EVENT;
-
- if (did_alloc == 0) {
- if (kfse_dest->len == 0) {
- panic("%s:%d: no more fref.vp\n", __FILE__, __LINE__);
- // vnode_rele_ext(kfse_dest->fref.vp, O_EVTONLY, 0);
- } else {
- vfs_removename(kfse_dest->str);
- kfse_dest->len = 0;
- }
- kfse_dest->str = NULL;
-
- if (kfse_dest->kevent_list.le_prev != NULL) {
- num_events_outstanding--;
- LIST_REMOVE(kfse_dest, kevent_list);
- memset(&kfse_dest->kevent_list, 0, sizeof(kfse_dest->kevent_list));
- }
-
- if (kfse_dest->dest) {
- panic("add_fsevent: should never recycle a rename event! kfse %p\n", kfse);
- }
- }
- }
-
- OSBitOrAtomic16(KFSE_BEING_CREATED, &kfse->flags);
- if (kfse_dest) {
- OSBitOrAtomic16(KFSE_BEING_CREATED, &kfse_dest->flags);
- }
-
- goto process_normally;
- }
- }
-
- if (reuse_type != 0) {
- panic("fsevents: we have a reuse_type (%d) but are about to clear out kfse %p\n", reuse_type, kfse);
- }
-
- //
- // we only want to do this for brand new events, not
- // events which have been recycled.
- //