/* * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. * * @APPLE_LICENSE_HEADER_START@ * * "Portions Copyright (c) 1999 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@ */ /* * Read an entire NetInfo database. * Copyright (C) 1989 by NeXT, Inc. * * This code is executing when a slave server needs to resynchronize * with the master server and issues a READALL call. The master reads * the entire database with the call readall(). * * XXX: This hangs up master service while the database is read. This * should be rewritten to be multi-threaded with the appropriate locking * so that writes can still occur while readall() executes (a tough * problem, otherwise we would have done it already ;-) */ #include #include #include #include "ni_server.h" #include "ni_globals.h" #include #include #include /* * Recursively reads node and its children, writing it into xdr. * The guts of readall(). */ static bool_t doit( XDR *xdr, void *ni, ni_index object_id ) { ni_index i; bool_t true = TRUE; ni_object object; socket_unlock(); object.nio_id.nii_object = object_id; if (ni_parent(ni, &object.nio_id, &object.nio_parent) != NI_OK) { socket_lock(); system_log(LOG_DEBUG, "couldn't get parent of %d\n", object.nio_id.nii_object); return (FALSE); } NI_INIT(&object.nio_props); if (ni_read(ni, &object.nio_id, &object.nio_props) != NI_OK) { socket_lock(); system_log(LOG_DEBUG, "couldn't read %d\n", object.nio_id.nii_object); return (FALSE); } NI_INIT(&object.nio_children); if (ni_children(ni, &object.nio_id, &object.nio_children) != NI_OK) { socket_lock(); ni_proplist_free(&object.nio_props); system_log(LOG_DEBUG, "couldn't get children of %d\n", object.nio_id.nii_object); return (FALSE); } socket_lock(); errno = 0; /* Start with a known clean errno: no cruft here! */ if (!xdr_bool(xdr, &true) || !xdr_ni_object(xdr, &object)) { system_log(LOG_ERR, "couldn't xdr %d: %m", object.nio_id.nii_object); ni_proplist_free(&object.nio_props); ni_idlist_free(&object.nio_children); return (FALSE); } ni_proplist_free(&object.nio_props); for (i = 0; i < object.nio_children.niil_len; i++) { if (!doit(xdr, ni, object.nio_children.niil_val[i])) { ni_idlist_free(&object.nio_children); return (FALSE); } } ni_idlist_free(&object.nio_children); return (TRUE); } /* * The readall() function. Sends out the netinfo status code, and if * NI_OK, than sends the checksum, the highest id in the list and calls * doit() to recursively descend the database. * */ bool_t readall( XDR *xdr, void *ni ) { ni_id root; bool_t false = FALSE; ni_status status; unsigned checksum; unsigned highestid; socket_unlock(); status = ni_root(ni, &root); socket_lock(); if (!xdr_ni_status(xdr, &status)) { return (FALSE); } if (status == NI_OK) { checksum = ni_getchecksum(db_ni); /* * Send out the checksum... */ if (!xdr_u_int(xdr, &checksum)) { return (FALSE); } socket_unlock(); highestid = ni_highestid(ni); socket_lock(); /* * The highest ID... */ if (!xdr_u_int(xdr, &highestid)) { return (FALSE); } /* * All the data... */ if (!doit(xdr, ni, root.nii_object)) { return (FALSE); } /* * And then terminate the list (more entries == false). */ if (!xdr_bool(xdr, &false)) { return (FALSE); } } return (TRUE); } /* * Ensure readall proxy terminates in a timely fashion upon * receiving a SIGUSR1. */ void proxy_term(void) { system_log(LOG_WARNING, "readall proxy terminating due to SIGUSR1"); /* * It'd be nice just to call ni_shutdown. But, that writes a * checksum file into the database, and that's inappropriate here. * During normal shutdown, the database is flushed and synced. We're * not writing here, so we only need to close the file. * * XXX There's no clean way to get at the contents of these opaque * handles (void * things) floating around: the structure declarations * are private. So, we'll just punt, "knowing" that the kernel will * clean up any open file descriptors for us. */ exit(NI_SYSTEMERR); }