2N/A * The contents of this file are subject to the terms of the 2N/A * Common Development and Distribution License, Version 1.0 only 2N/A * (the "License"). You may not use this file except in compliance 2N/A * See the License for the specific language governing permissions 2N/A * and limitations under the License. 2N/A * When distributing Covered Code, include this CDDL HEADER in each 2N/A * If applicable, add the following below this CDDL HEADER, with the 2N/A * fields enclosed by brackets "[]" replaced with your own identifying 2N/A * information: Portions Copyright [yyyy] [name of copyright owner] 2N/A * Copyright (c) 2000-2001 by Sun Microsystems, Inc. 2N/A * All rights reserved. 2N/A#
pragma ident "%Z%%M% %I% %E% SMI" 2N/A * Internal libdhcpsvc public module utility functions: a collection of 2N/A * general-purpose routines that are used by assorted public modules. 2N/A * Someday we should integrate this into the build process a bit more 2N/A * Open a file at path `pathname'; depending on the flags passed in through 2N/A * `dsvc_flags', this file may be optionally created or opened read-only. 2N/A * On success, DSVC_SUCCESS is returned and `fdp' points to the opened file 2N/A * descriptor. On failure, a DSVC_* error code is returned. 2N/A * Note that we always open with read access, independent of 2N/A * dsvc_flags, because an update operation (add, delete, modify) 2N/A * needs to lookup records to detect collisions. 2N/A * Read input a chunk at a time, avoiding as much copying as possible. To 2N/A * this end, we don't read into a temporary buffer, but rather read 2N/A * directly into dynamically reallocated storage (on the assumption that 2N/A * most of the time we will have to return something). Returns NULL either 2N/A * on failure or EOF; use feof(3C) on `fp' to determine which condition 2N/A * See if we need to grow the buffer; we always try to read 2N/A * `chunksize' bytes, so we need at least `chunksize' around; 2N/A * grab a little more just to avoid constant realloc'ing 2N/A * Hit EOF; if we never read any data, then free 2N/A * `new_result' and return NULL. If we are 2N/A * returning data, it's in `new_result', not 2N/A * If we read a newline, then see if the preceding 2N/A * character was an escape. If so, remove the escape and 2N/A * continue; otherwise we're done. Note that we need to 2N/A * do the strrchr() on `&result[len]' so that NUL's that 2N/A * may be lurking elsewhere on the line don't confuse us. 2N/A * We either `chunksize' worth of data or we hit a 2N/A * NUL somewhere in the data stream. If we hit a 2N/A * NUL, then we can't "see" beyond the NUL; just 2N/A * advance to the NUL itself and continue. 2N/A * Given a buffer `buf' of words separated by one or more of the characters 2N/A * in `seps', split it into at most `nfields' fields, by changing the 2N/A * separator character following a field to a NUL character. Set 2N/A * `fields[i]' to point to the beginning of field i in `buf'. Return the 2N/A * number of fields set in `fields[]'. This routine is quite similar to 2N/A * bufsplit(3G), but less general, faster, and also handles multiple 2N/A * multiple whitespace separator characters differently. 2N/A * Look for the field separator, byte-at-a-time; ignore 2N/A * separators that have been escaped. Believe it or not, 2N/A * strchr(3C) will match `seps' if `*buf' is the NUL byte 2N/A * (which indicates we're done). 2N/A * If this is the last field, then consider any remaining 2N/A * text on the line part of the last field. This is 2N/A * similar to how `read' in sh(1) works. 2N/A * If separator is whitespace, then skip all consecutive 2N/A * pieces of whitespace. 2N/A * Map a standard errno into a corresponding DSVC_* code. If there 2N/A * is no translation, default to DSVC_INTERNAL. 2N/A * Convert an object of `len' bytes pointed to by `srcraw' between 2N/A * network-order and host-order and store in `dstraw'. The length `len' 2N/A * must be the actual length of the objects pointed to by `srcraw' and 2N/A * `dstraw' (or zero) or the results are undefined. Note that `srcraw' and 2N/A * `dstraw' may be the same, in which case the object is converted 2N/A * in-place. This routine will convert from host-order to network-order or 2N/A * network-order to host-order, since the conversion is the same. 2N/A * If both `srcraw' and `dstraw' are 32-bit aligned and `len' is 4, 2N/A * then use ntohl() to do the byteswap, since it's hand-tuned. 2N/A for (i = 0; i <
len /
2; i++) {
2N/A * Positioned n-byte read: read `buflen' bytes at offset `off' at open file 2N/A * `fd' into `buffer', or "read" none at all. Returns -1 if all `buflen' 2N/A * bytes cannot be read; otherwise, returns 0. 2N/A * Positioned n-byte write: write `buflen' bytes from `buffer' to offset 2N/A * `off' in open file `fd'. Tries to write all `buflen' bytes, but does 2N/A * not attempt to "undo" what it has done in the case of failure. Returns 2N/A * -1 if all `buflen' bytes cannot be written, otherwise returns 0. 2N/A * Copy `nbytes' efficiently from offset `srcoff' in `srcfd' to offset 2N/A * `dstoff' in `dstfd'; returns a DSVC_* return code. Note that we make 2N/A * `nbytes' a uint64_t (rather than a size_t) so that we can copy 2^64 2N/A * bits even when compiled ILP32. 2N/A * Handle trivial copy specially so we don't call munmap() below. 2N/A * The `off' argument to mmap(2) must be page-aligned, so align it; 2N/A * compute how many bytes we need to skip over in the mmap()'d 2N/A * buffer as a result. 2N/A * Unescape all instances of `delimiter' in `buffer' and store result in 2N/A * `unescaped', which is `size' bytes. To guarantee that all data is 2N/A * copied, `unescaped' should be at least as long as `buffer'. 2N/A * Escape all instances of `delimiter' in `buffer' and store result in 2N/A * `escaped', which is `size' bytes. To guarantee that all data is 2N/A * copied, `escaped' should be at least twice as long as `buffer'. 2N/A * Generate a signature for a new record. The signature is conceptually 2N/A * divided into two pieces: a random 16-bit "generation number" and a 2N/A * 48-bit monotonically increasing integer. The generation number protects 2N/A * against stale updates to records that have been deleted and since