/* * Copyright (c) 2003 Apple Computer, Inc. All rights reserved. * * @APPLE_LICENSE_HEADER_START@ * * "Portions Copyright (c) 2003 Apple Computer, Inc. All Rights * Reserved. This file contains Original Code and/or Modifications of * Original Code as defined in and that are subject to the Apple Public * Source License Version 1.0 (the 'License'). You may not use this file * except in compliance with the License. Please obtain a copy of the * License at http://www.apple.com/publicsource and read it before using * this file. * * The Original Code and all software distributed under the License are * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the * License for the specific language governing rights and limitations * under the License." * * @APPLE_LICENSE_HEADER_END@ */ #include #include "watcher.h" #include "daemon.h" list_t *watch_list = NULL; uint32_t watcher_id = 0; watcher_t * watcher_new() { watcher_t *w; list_t *n; w = (watcher_t *)calloc(1, sizeof(watcher_t)); if (w == NULL) return NULL; w->wid = ++watcher_id; w->refcount = 1; n = _nc_list_new(w); watch_list = _nc_list_prepend(watch_list, n); return w; } watcher_t * watcher_retain(watcher_t *w) { if (w == NULL) return NULL; w->refcount++; return w; } void watcher_release_deferred(watcher_t *w) { if (w == NULL) return; if (w->refcount > 0) w->refcount--; } void watcher_release(watcher_t *w) { int i; if (w == NULL) return; if (w->refcount > 0) w->refcount--; if (w->refcount > 0) return; watch_list = _nc_list_find_release(watch_list, w); if (w->sub_free != NULL) w->sub_free(w); if (w->name != NULL) { for (i = 0; w->name[i] != NULL; i++) free(w->name[i]); free(w->name); } if (w->fwd != NULL) free(w->fwd); free(w); } void watcher_add_name(watcher_t *w, const char *name) { int i; if (w == NULL) return; if (name == NULL) return; if (w->name == NULL) { w->name = (char **)calloc(2, sizeof(char *)); w->name[0] = strdup(name); return; } for (i = 0; w->name[i] != NULL; i++) { if (!strcmp(w->name[i], name)) return; } w->name = (char **)realloc(w->name, (i + 2) * sizeof(char *)); w->name[i] = strdup(name); w->name[i + 1] = NULL; } void watcher_remove_name(watcher_t *w, const char *name) { int i, j; if (w == NULL) return; if (name == NULL) return; if (w->name == NULL) return; for (i = 0; w->name[i] != NULL; i++) { if (!strcmp(w->name[i], name)) { free(w->name[i]); for (j = i + 1; w->name[j] != NULL; j++) w->name[j - 1] = w->name[j]; w->name[j - 1] = NULL; w->name = (char **)realloc(w->name, j * sizeof(char *)); return; } } } static void watcher_internal_trigger(watcher_t *w, uint32_t t, uint32_t flags, uint32_t level) { uint32_t i, postit; if (w == NULL) return; if (w->wid != t) return; #ifdef DEBUG log_message(LOG_DEBUG, "watcher_trigger %u level %u", t, level); #endif postit = 0; if (w->sub_trigger != NULL) postit = w->sub_trigger(w, flags, level); if ((w->name != NULL) && (postit != 0)) { for (i = 0; w->name[i] != NULL; i++) daemon_post(w->name[i], 0, 0); } for (i = 0; i < w->count; i++) watcher_trigger(w->fwd[i], 0, level + 1); } void watcher_add_forward(watcher_t *w, uint32_t t) { uint32_t i; if (w == NULL) return; for (i = 0; i < w->count; i++) { if (w->fwd[i] == t) return; } if (w->count == 0) { w->fwd = (uint32_t *)malloc(sizeof(uint32_t)); } else { w->fwd = (uint32_t *)realloc(w->fwd, (w->count + 1) * sizeof(uint32_t)); } w->fwd[w->count] = t; w->count++; } void watcher_remove_forward(watcher_t *w, uint32_t t) { uint32_t i, x; if (w->count == 0) return; x = w->count + 1; for (i = 0; i < w->count; i++) { if (w->fwd[i] == t) { x = i; break; } } if (x > w->count) return; if (w->count == 1) { free(w->fwd); w->fwd = NULL; w->count = 0; return; } for (i = x + 1; i < w->count; i++) w->fwd[i - 1] = w->fwd[i]; w->count--; w->fwd = (uint32_t *)realloc(w->fwd, w->count * sizeof(uint32_t)); } void watcher_trigger(uint32_t t, uint32_t flags, uint32_t level) { watcher_t *w; list_t *n, *x; for (n = watch_list; n != NULL; n = _nc_list_next(n)) { w = _nc_list_data(n); watcher_internal_trigger(w, t, flags, level); } if (level == 0) { for (n = watch_list; n != NULL; n = x) { x = _nc_list_next(n); w = _nc_list_data(n); if (w->refcount == 0) watcher_release(w); } } } void watcher_shutdown() { watcher_t *w; list_t *n; for (n = watch_list; n != NULL; n = _nc_list_next(n)) { w = _nc_list_data(n); watcher_release(w); } _nc_list_release_list(watch_list); } void watcher_printf(watcher_t *w, FILE *f) { uint32_t i; if (w == NULL) { fprintf(f, "-nil-\n"); return; } fprintf(f, "Watcher %u\n", w->wid); fprintf(f, "Name:"); if (w->name == NULL) fprintf(f, " -nil-"); else for (i = 0; w->name[i] != NULL; i++) fprintf(f, " %s", w->name[i]); fprintf(f, "\n"); fprintf(f, "Type: %u\n", w->type); fprintf(f, "Refcount: %u\n", w->refcount); fprintf(f, "Forward (%u):", w->count); for (i = 0; i < w->count; i++) fprintf(f, " %u", w->fwd[i]); fprintf(f, "\n"); if (w->sub_printf != NULL) w->sub_printf(w, f); }