Index: head/lib/libc/db/hash/hash.c =================================================================== --- head/lib/libc/db/hash/hash.c (revision 297789) +++ head/lib/libc/db/hash/hash.c (revision 297790) @@ -1,968 +1,968 @@ /*- * Copyright (c) 1990, 1993, 1994 * The Regents of the University of California. All rights reserved. * * This code is derived from software contributed to Berkeley by * Margo Seltzer. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 4. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ #if defined(LIBC_SCCS) && !defined(lint) static char sccsid[] = "@(#)hash.c 8.9 (Berkeley) 6/16/94"; #endif /* LIBC_SCCS and not lint */ #include __FBSDID("$FreeBSD$"); #include "namespace.h" #include #include #include #include #include #include #include #include #ifdef DEBUG #include #endif #include "un-namespace.h" #include #include "hash.h" #include "page.h" #include "extern.h" static int alloc_segs(HTAB *, int); static int flush_meta(HTAB *); static int hash_access(HTAB *, ACTION, DBT *, DBT *); static int hash_close(DB *); static int hash_delete(const DB *, const DBT *, u_int32_t); static int hash_fd(const DB *); static int hash_get(const DB *, const DBT *, DBT *, u_int32_t); static int hash_put(const DB *, DBT *, const DBT *, u_int32_t); static void *hash_realloc(SEGMENT **, int, int); static int hash_seq(const DB *, DBT *, DBT *, u_int32_t); static int hash_sync(const DB *, u_int32_t); static int hdestroy(HTAB *); static HTAB *init_hash(HTAB *, const char *, const HASHINFO *); static int init_htab(HTAB *, int); #if BYTE_ORDER == LITTLE_ENDIAN static void swap_header(HTAB *); static void swap_header_copy(HASHHDR *, HASHHDR *); #endif /* Fast arithmetic, relying on powers of 2, */ #define MOD(x, y) ((x) & ((y) - 1)) #define RETURN_ERROR(ERR, LOC) { save_errno = ERR; goto LOC; } /* Return values */ #define SUCCESS (0) #define ERROR (-1) #define ABNORMAL (1) #ifdef HASH_STATISTICS int hash_accesses, hash_collisions, hash_expansions, hash_overflows; #endif /************************** INTERFACE ROUTINES ***************************/ /* OPEN/CLOSE */ /* ARGSUSED */ DB * __hash_open(const char *file, int flags, int mode, const HASHINFO *info, /* Special directives for create */ int dflags) { HTAB *hashp; struct stat statbuf; DB *dbp; int bpages, hdrsize, new_table, nsegs, save_errno; if ((flags & O_ACCMODE) == O_WRONLY) { errno = EINVAL; return (NULL); } if (!(hashp = (HTAB *)calloc(1, sizeof(HTAB)))) return (NULL); hashp->fp = -1; /* * Even if user wants write only, we need to be able to read * the actual file, so we need to open it read/write. But, the * field in the hashp structure needs to be accurate so that * we can check accesses. */ hashp->flags = flags; if (file) { if ((hashp->fp = _open(file, flags | O_CLOEXEC, mode)) == -1) RETURN_ERROR(errno, error0); new_table = _fstat(hashp->fp, &statbuf) == 0 && statbuf.st_size == 0 && (flags & O_ACCMODE) != O_RDONLY; } else new_table = 1; if (new_table) { if (!(hashp = init_hash(hashp, file, info))) RETURN_ERROR(errno, error1); } else { /* Table already exists */ if (info && info->hash) hashp->hash = info->hash; else hashp->hash = __default_hash; hdrsize = _read(hashp->fp, &hashp->hdr, sizeof(HASHHDR)); #if BYTE_ORDER == LITTLE_ENDIAN swap_header(hashp); #endif if (hdrsize == -1) RETURN_ERROR(errno, error1); if (hdrsize != sizeof(HASHHDR)) RETURN_ERROR(EFTYPE, error1); /* Verify file type, versions and hash function */ if (hashp->MAGIC != HASHMAGIC) RETURN_ERROR(EFTYPE, error1); #define OLDHASHVERSION 1 if (hashp->VERSION != HASHVERSION && hashp->VERSION != OLDHASHVERSION) RETURN_ERROR(EFTYPE, error1); if ((int32_t)hashp->hash(CHARKEY, sizeof(CHARKEY)) != hashp->H_CHARKEY) RETURN_ERROR(EFTYPE, error1); /* * Figure out how many segments we need. Max_Bucket is the * maximum bucket number, so the number of buckets is * max_bucket + 1. */ nsegs = (hashp->MAX_BUCKET + 1 + hashp->SGSIZE - 1) / hashp->SGSIZE; if (alloc_segs(hashp, nsegs)) /* * If alloc_segs fails, table will have been destroyed * and errno will have been set. */ return (NULL); /* Read in bitmaps */ bpages = (hashp->SPARES[hashp->OVFL_POINT] + (hashp->BSIZE << BYTE_SHIFT) - 1) >> (hashp->BSHIFT + BYTE_SHIFT); hashp->nmaps = bpages; (void)memset(&hashp->mapp[0], 0, bpages * sizeof(u_int32_t *)); } /* Initialize Buffer Manager */ if (info && info->cachesize) __buf_init(hashp, info->cachesize); else __buf_init(hashp, DEF_BUFSIZE); hashp->new_file = new_table; hashp->save_file = file && (hashp->flags & O_RDWR); hashp->cbucket = -1; if (!(dbp = (DB *)malloc(sizeof(DB)))) { save_errno = errno; hdestroy(hashp); errno = save_errno; return (NULL); } dbp->internal = hashp; dbp->close = hash_close; dbp->del = hash_delete; dbp->fd = hash_fd; dbp->get = hash_get; dbp->put = hash_put; dbp->seq = hash_seq; dbp->sync = hash_sync; dbp->type = DB_HASH; #ifdef DEBUG (void)fprintf(stderr, "%s\n%s%p\n%s%d\n%s%d\n%s%d\n%s%d\n%s%d\n%s%d\n%s%d\n%s%d\n%s%d\n%s%x\n%s%x\n%s%d\n%s%d\n", "init_htab:", "TABLE POINTER ", hashp, "BUCKET SIZE ", hashp->BSIZE, "BUCKET SHIFT ", hashp->BSHIFT, "DIRECTORY SIZE ", hashp->DSIZE, "SEGMENT SIZE ", hashp->SGSIZE, "SEGMENT SHIFT ", hashp->SSHIFT, "FILL FACTOR ", hashp->FFACTOR, "MAX BUCKET ", hashp->MAX_BUCKET, "OVFL POINT ", hashp->OVFL_POINT, "LAST FREED ", hashp->LAST_FREED, "HIGH MASK ", hashp->HIGH_MASK, "LOW MASK ", hashp->LOW_MASK, "NSEGS ", hashp->nsegs, "NKEYS ", hashp->NKEYS); #endif #ifdef HASH_STATISTICS hash_overflows = hash_accesses = hash_collisions = hash_expansions = 0; #endif return (dbp); error1: if (hashp != NULL) (void)_close(hashp->fp); error0: free(hashp); errno = save_errno; return (NULL); } static int hash_close(DB *dbp) { HTAB *hashp; int retval; if (!dbp) return (ERROR); hashp = (HTAB *)dbp->internal; retval = hdestroy(hashp); free(dbp); return (retval); } static int hash_fd(const DB *dbp) { HTAB *hashp; if (!dbp) return (ERROR); hashp = (HTAB *)dbp->internal; if (hashp->fp == -1) { errno = ENOENT; return (-1); } return (hashp->fp); } /************************** LOCAL CREATION ROUTINES **********************/ static HTAB * init_hash(HTAB *hashp, const char *file, const HASHINFO *info) { struct stat statbuf; int nelem; nelem = 1; hashp->NKEYS = 0; hashp->LORDER = BYTE_ORDER; hashp->BSIZE = DEF_BUCKET_SIZE; hashp->BSHIFT = DEF_BUCKET_SHIFT; hashp->SGSIZE = DEF_SEGSIZE; hashp->SSHIFT = DEF_SEGSIZE_SHIFT; hashp->DSIZE = DEF_DIRSIZE; hashp->FFACTOR = DEF_FFACTOR; hashp->hash = __default_hash; memset(hashp->SPARES, 0, sizeof(hashp->SPARES)); memset(hashp->BITMAPS, 0, sizeof (hashp->BITMAPS)); /* Fix bucket size to be optimal for file system */ if (file != NULL) { if (stat(file, &statbuf)) return (NULL); hashp->BSIZE = statbuf.st_blksize; if (hashp->BSIZE > MAX_BSIZE) hashp->BSIZE = MAX_BSIZE; hashp->BSHIFT = __log2(hashp->BSIZE); } if (info) { if (info->bsize) { /* Round pagesize up to power of 2 */ hashp->BSHIFT = __log2(info->bsize); hashp->BSIZE = 1 << hashp->BSHIFT; if (hashp->BSIZE > MAX_BSIZE) { errno = EINVAL; return (NULL); } } if (info->ffactor) hashp->FFACTOR = info->ffactor; if (info->hash) hashp->hash = info->hash; if (info->nelem) nelem = info->nelem; if (info->lorder) { if (info->lorder != BIG_ENDIAN && info->lorder != LITTLE_ENDIAN) { errno = EINVAL; return (NULL); } hashp->LORDER = info->lorder; } } /* init_htab should destroy the table and set errno if it fails */ if (init_htab(hashp, nelem)) return (NULL); else return (hashp); } /* * This calls alloc_segs which may run out of memory. Alloc_segs will destroy * the table and set errno, so we just pass the error information along. * * Returns 0 on No Error */ static int init_htab(HTAB *hashp, int nelem) { int nbuckets, nsegs, l2; /* * Divide number of elements by the fill factor and determine a * desired number of buckets. Allocate space for the next greater * power of two number of buckets. */ nelem = (nelem - 1) / hashp->FFACTOR + 1; l2 = __log2(MAX(nelem, 2)); nbuckets = 1 << l2; hashp->SPARES[l2] = l2 + 1; hashp->SPARES[l2 + 1] = l2 + 1; hashp->OVFL_POINT = l2; hashp->LAST_FREED = 2; /* First bitmap page is at: splitpoint l2 page offset 1 */ if (__ibitmap(hashp, OADDR_OF(l2, 1), l2 + 1, 0)) return (-1); hashp->MAX_BUCKET = hashp->LOW_MASK = nbuckets - 1; hashp->HIGH_MASK = (nbuckets << 1) - 1; hashp->HDRPAGES = ((MAX(sizeof(HASHHDR), MINHDRSIZE) - 1) >> hashp->BSHIFT) + 1; nsegs = (nbuckets - 1) / hashp->SGSIZE + 1; nsegs = 1 << __log2(nsegs); if (nsegs > hashp->DSIZE) hashp->DSIZE = nsegs; return (alloc_segs(hashp, nsegs)); } /********************** DESTROY/CLOSE ROUTINES ************************/ /* * Flushes any changes to the file if necessary and destroys the hashp * structure, freeing all allocated space. */ static int hdestroy(HTAB *hashp) { int i, save_errno; save_errno = 0; #ifdef HASH_STATISTICS (void)fprintf(stderr, "hdestroy: accesses %ld collisions %ld\n", hash_accesses, hash_collisions); (void)fprintf(stderr, "hdestroy: expansions %ld\n", hash_expansions); (void)fprintf(stderr, "hdestroy: overflows %ld\n", hash_overflows); (void)fprintf(stderr, "keys %ld maxp %d segmentcount %d\n", hashp->NKEYS, hashp->MAX_BUCKET, hashp->nsegs); for (i = 0; i < NCACHED; i++) (void)fprintf(stderr, "spares[%d] = %d\n", i, hashp->SPARES[i]); #endif /* * Call on buffer manager to free buffers, and if required, * write them to disk. */ if (__buf_free(hashp, 1, hashp->save_file)) save_errno = errno; if (hashp->dir) { free(*hashp->dir); /* Free initial segments */ /* Free extra segments */ while (hashp->exsegs--) free(hashp->dir[--hashp->nsegs]); free(hashp->dir); } if (flush_meta(hashp) && !save_errno) save_errno = errno; /* Free Bigmaps */ for (i = 0; i < hashp->nmaps; i++) if (hashp->mapp[i]) free(hashp->mapp[i]); if (hashp->tmp_key) free(hashp->tmp_key); if (hashp->tmp_buf) free(hashp->tmp_buf); if (hashp->fp != -1) { if (hashp->save_file) (void)_fsync(hashp->fp); (void)_close(hashp->fp); } free(hashp); if (save_errno) { errno = save_errno; return (ERROR); } return (SUCCESS); } /* * Write modified pages to disk * * Returns: * 0 == OK * -1 ERROR */ static int hash_sync(const DB *dbp, u_int32_t flags) { HTAB *hashp; if (flags != 0) { errno = EINVAL; return (ERROR); } if (!dbp) return (ERROR); hashp = (HTAB *)dbp->internal; if (!hashp->save_file) return (0); if (__buf_free(hashp, 0, 1) || flush_meta(hashp)) return (ERROR); if (hashp->fp != -1 && _fsync(hashp->fp) != 0) return (ERROR); hashp->new_file = 0; return (0); } /* * Returns: * 0 == OK * -1 indicates that errno should be set */ static int flush_meta(HTAB *hashp) { HASHHDR *whdrp; #if BYTE_ORDER == LITTLE_ENDIAN HASHHDR whdr; #endif int fp, i, wsize; if (!hashp->save_file) return (0); hashp->MAGIC = HASHMAGIC; hashp->VERSION = HASHVERSION; hashp->H_CHARKEY = hashp->hash(CHARKEY, sizeof(CHARKEY)); fp = hashp->fp; whdrp = &hashp->hdr; #if BYTE_ORDER == LITTLE_ENDIAN whdrp = &whdr; swap_header_copy(&hashp->hdr, whdrp); #endif if ((wsize = pwrite(fp, whdrp, sizeof(HASHHDR), (off_t)0)) == -1) return (-1); else if (wsize != sizeof(HASHHDR)) { errno = EFTYPE; hashp->error = errno; return (-1); } for (i = 0; i < NCACHED; i++) if (hashp->mapp[i]) if (__put_page(hashp, (char *)hashp->mapp[i], hashp->BITMAPS[i], 0, 1)) return (-1); return (0); } /*******************************SEARCH ROUTINES *****************************/ /* * All the access routines return * * Returns: * 0 on SUCCESS * 1 to indicate an external ERROR (i.e. key not found, etc) * -1 to indicate an internal ERROR (i.e. out of memory, etc) */ static int hash_get(const DB *dbp, const DBT *key, DBT *data, u_int32_t flag) { HTAB *hashp; hashp = (HTAB *)dbp->internal; if (flag) { hashp->error = errno = EINVAL; return (ERROR); } return (hash_access(hashp, HASH_GET, (DBT *)key, data)); } static int hash_put(const DB *dbp, DBT *key, const DBT *data, u_int32_t flag) { HTAB *hashp; hashp = (HTAB *)dbp->internal; if (flag && flag != R_NOOVERWRITE) { hashp->error = errno = EINVAL; return (ERROR); } if ((hashp->flags & O_ACCMODE) == O_RDONLY) { hashp->error = errno = EPERM; return (ERROR); } return (hash_access(hashp, flag == R_NOOVERWRITE ? HASH_PUTNEW : HASH_PUT, (DBT *)key, (DBT *)data)); } static int hash_delete(const DB *dbp, const DBT *key, u_int32_t flag) /* Ignored */ { HTAB *hashp; hashp = (HTAB *)dbp->internal; if (flag && flag != R_CURSOR) { hashp->error = errno = EINVAL; return (ERROR); } if ((hashp->flags & O_ACCMODE) == O_RDONLY) { hashp->error = errno = EPERM; return (ERROR); } return (hash_access(hashp, HASH_DELETE, (DBT *)key, NULL)); } /* * Assume that hashp has been set in wrapper routine. */ static int hash_access(HTAB *hashp, ACTION action, DBT *key, DBT *val) { BUFHEAD *rbufp; BUFHEAD *bufp, *save_bufp; u_int16_t *bp; int n, ndx, off, size; char *kp; u_int16_t pageno; #ifdef HASH_STATISTICS hash_accesses++; #endif off = hashp->BSIZE; size = key->size; kp = (char *)key->data; rbufp = __get_buf(hashp, __call_hash(hashp, kp, size), NULL, 0); if (!rbufp) return (ERROR); save_bufp = rbufp; /* Pin the bucket chain */ rbufp->flags |= BUF_PIN; for (bp = (u_int16_t *)rbufp->page, n = *bp++, ndx = 1; ndx < n;) if (bp[1] >= REAL_KEY) { /* Real key/data pair */ if (size == off - *bp && memcmp(kp, rbufp->page + *bp, size) == 0) goto found; off = bp[1]; #ifdef HASH_STATISTICS hash_collisions++; #endif bp += 2; ndx += 2; } else if (bp[1] == OVFLPAGE) { rbufp = __get_buf(hashp, *bp, rbufp, 0); if (!rbufp) { save_bufp->flags &= ~BUF_PIN; return (ERROR); } /* FOR LOOP INIT */ bp = (u_int16_t *)rbufp->page; n = *bp++; ndx = 1; off = hashp->BSIZE; } else if (bp[1] < REAL_KEY) { if ((ndx = __find_bigpair(hashp, rbufp, ndx, kp, size)) > 0) goto found; if (ndx == -2) { bufp = rbufp; if (!(pageno = __find_last_page(hashp, &bufp))) { ndx = 0; rbufp = bufp; break; /* FOR */ } rbufp = __get_buf(hashp, pageno, bufp, 0); if (!rbufp) { save_bufp->flags &= ~BUF_PIN; return (ERROR); } /* FOR LOOP INIT */ bp = (u_int16_t *)rbufp->page; n = *bp++; ndx = 1; off = hashp->BSIZE; } else { save_bufp->flags &= ~BUF_PIN; return (ERROR); } } /* Not found */ switch (action) { case HASH_PUT: case HASH_PUTNEW: if (__addel(hashp, rbufp, key, val)) { save_bufp->flags &= ~BUF_PIN; return (ERROR); } else { save_bufp->flags &= ~BUF_PIN; return (SUCCESS); } case HASH_GET: case HASH_DELETE: default: save_bufp->flags &= ~BUF_PIN; return (ABNORMAL); } found: switch (action) { case HASH_PUTNEW: save_bufp->flags &= ~BUF_PIN; return (ABNORMAL); case HASH_GET: bp = (u_int16_t *)rbufp->page; if (bp[ndx + 1] < REAL_KEY) { if (__big_return(hashp, rbufp, ndx, val, 0)) return (ERROR); } else { val->data = (u_char *)rbufp->page + (int)bp[ndx + 1]; val->size = bp[ndx] - bp[ndx + 1]; } break; case HASH_PUT: if ((__delpair(hashp, rbufp, ndx)) || (__addel(hashp, rbufp, key, val))) { save_bufp->flags &= ~BUF_PIN; return (ERROR); } break; case HASH_DELETE: if (__delpair(hashp, rbufp, ndx)) return (ERROR); break; default: abort(); } save_bufp->flags &= ~BUF_PIN; return (SUCCESS); } static int hash_seq(const DB *dbp, DBT *key, DBT *data, u_int32_t flag) { u_int32_t bucket; BUFHEAD *bufp; HTAB *hashp; u_int16_t *bp, ndx; hashp = (HTAB *)dbp->internal; if (flag && flag != R_FIRST && flag != R_NEXT) { hashp->error = errno = EINVAL; return (ERROR); } #ifdef HASH_STATISTICS hash_accesses++; #endif if ((hashp->cbucket < 0) || (flag == R_FIRST)) { hashp->cbucket = 0; hashp->cndx = 1; hashp->cpage = NULL; } next_bucket: for (bp = NULL; !bp || !bp[0]; ) { if (!(bufp = hashp->cpage)) { for (bucket = hashp->cbucket; bucket <= hashp->MAX_BUCKET; bucket++, hashp->cndx = 1) { bufp = __get_buf(hashp, bucket, NULL, 0); if (!bufp) return (ERROR); hashp->cpage = bufp; bp = (u_int16_t *)bufp->page; if (bp[0]) break; } hashp->cbucket = bucket; if ((u_int32_t)hashp->cbucket > hashp->MAX_BUCKET) { hashp->cbucket = -1; return (ABNORMAL); } } else { bp = (u_int16_t *)hashp->cpage->page; if (flag == R_NEXT || flag == 0) { hashp->cndx += 2; if (hashp->cndx > bp[0]) { hashp->cpage = NULL; hashp->cbucket++; hashp->cndx = 1; goto next_bucket; } } } #ifdef DEBUG assert(bp); assert(bufp); #endif while (bp[hashp->cndx + 1] == OVFLPAGE) { bufp = hashp->cpage = __get_buf(hashp, bp[hashp->cndx], bufp, 0); if (!bufp) return (ERROR); bp = (u_int16_t *)(bufp->page); hashp->cndx = 1; } if (!bp[0]) { hashp->cpage = NULL; ++hashp->cbucket; } } ndx = hashp->cndx; if (bp[ndx + 1] < REAL_KEY) { if (__big_keydata(hashp, bufp, key, data, 1)) return (ERROR); } else { - if (hashp->cpage == 0) + if (hashp->cpage == NULL) return (ERROR); key->data = (u_char *)hashp->cpage->page + bp[ndx]; key->size = (ndx > 1 ? bp[ndx - 1] : hashp->BSIZE) - bp[ndx]; data->data = (u_char *)hashp->cpage->page + bp[ndx + 1]; data->size = bp[ndx] - bp[ndx + 1]; } return (SUCCESS); } /********************************* UTILITIES ************************/ /* * Returns: * 0 ==> OK * -1 ==> Error */ int __expand_table(HTAB *hashp) { u_int32_t old_bucket, new_bucket; int dirsize, new_segnum, spare_ndx; #ifdef HASH_STATISTICS hash_expansions++; #endif new_bucket = ++hashp->MAX_BUCKET; old_bucket = (hashp->MAX_BUCKET & hashp->LOW_MASK); new_segnum = new_bucket >> hashp->SSHIFT; /* Check if we need a new segment */ if (new_segnum >= hashp->nsegs) { /* Check if we need to expand directory */ if (new_segnum >= hashp->DSIZE) { /* Reallocate directory */ dirsize = hashp->DSIZE * sizeof(SEGMENT *); if (!hash_realloc(&hashp->dir, dirsize, dirsize << 1)) return (-1); hashp->DSIZE = dirsize << 1; } if ((hashp->dir[new_segnum] = calloc(hashp->SGSIZE, sizeof(SEGMENT))) == NULL) return (-1); hashp->exsegs++; hashp->nsegs++; } /* * If the split point is increasing (MAX_BUCKET's log base 2 * * increases), we need to copy the current contents of the spare * split bucket to the next bucket. */ spare_ndx = __log2(hashp->MAX_BUCKET + 1); if (spare_ndx > hashp->OVFL_POINT) { hashp->SPARES[spare_ndx] = hashp->SPARES[hashp->OVFL_POINT]; hashp->OVFL_POINT = spare_ndx; } if (new_bucket > hashp->HIGH_MASK) { /* Starting a new doubling */ hashp->LOW_MASK = hashp->HIGH_MASK; hashp->HIGH_MASK = new_bucket | hashp->LOW_MASK; } /* Relocate records to the new bucket */ return (__split_page(hashp, old_bucket, new_bucket)); } /* * If realloc guarantees that the pointer is not destroyed if the realloc * fails, then this routine can go away. */ static void * hash_realloc(SEGMENT **p_ptr, int oldsize, int newsize) { void *p; if ( (p = malloc(newsize)) ) { memmove(p, *p_ptr, oldsize); memset((char *)p + oldsize, 0, newsize - oldsize); free(*p_ptr); *p_ptr = p; } return (p); } u_int32_t __call_hash(HTAB *hashp, char *k, int len) { unsigned int n, bucket; n = hashp->hash(k, len); bucket = n & hashp->HIGH_MASK; if (bucket > hashp->MAX_BUCKET) bucket = bucket & hashp->LOW_MASK; return (bucket); } /* * Allocate segment table. On error, destroy the table and set errno. * * Returns 0 on success */ static int alloc_segs(HTAB *hashp, int nsegs) { int i; SEGMENT store; int save_errno; if ((hashp->dir = calloc(hashp->DSIZE, sizeof(SEGMENT *))) == NULL) { save_errno = errno; (void)hdestroy(hashp); errno = save_errno; return (-1); } hashp->nsegs = nsegs; if (nsegs == 0) return (0); /* Allocate segments */ if ((store = calloc(nsegs << hashp->SSHIFT, sizeof(SEGMENT))) == NULL) { save_errno = errno; (void)hdestroy(hashp); errno = save_errno; return (-1); } for (i = 0; i < nsegs; i++) hashp->dir[i] = &store[i << hashp->SSHIFT]; return (0); } #if BYTE_ORDER == LITTLE_ENDIAN /* * Hashp->hdr needs to be byteswapped. */ static void swap_header_copy(HASHHDR *srcp, HASHHDR *destp) { int i; P_32_COPY(srcp->magic, destp->magic); P_32_COPY(srcp->version, destp->version); P_32_COPY(srcp->lorder, destp->lorder); P_32_COPY(srcp->bsize, destp->bsize); P_32_COPY(srcp->bshift, destp->bshift); P_32_COPY(srcp->dsize, destp->dsize); P_32_COPY(srcp->ssize, destp->ssize); P_32_COPY(srcp->sshift, destp->sshift); P_32_COPY(srcp->ovfl_point, destp->ovfl_point); P_32_COPY(srcp->last_freed, destp->last_freed); P_32_COPY(srcp->max_bucket, destp->max_bucket); P_32_COPY(srcp->high_mask, destp->high_mask); P_32_COPY(srcp->low_mask, destp->low_mask); P_32_COPY(srcp->ffactor, destp->ffactor); P_32_COPY(srcp->nkeys, destp->nkeys); P_32_COPY(srcp->hdrpages, destp->hdrpages); P_32_COPY(srcp->h_charkey, destp->h_charkey); for (i = 0; i < NCACHED; i++) { P_32_COPY(srcp->spares[i], destp->spares[i]); P_16_COPY(srcp->bitmaps[i], destp->bitmaps[i]); } } static void swap_header(HTAB *hashp) { HASHHDR *hdrp; int i; hdrp = &hashp->hdr; M_32_SWAP(hdrp->magic); M_32_SWAP(hdrp->version); M_32_SWAP(hdrp->lorder); M_32_SWAP(hdrp->bsize); M_32_SWAP(hdrp->bshift); M_32_SWAP(hdrp->dsize); M_32_SWAP(hdrp->ssize); M_32_SWAP(hdrp->sshift); M_32_SWAP(hdrp->ovfl_point); M_32_SWAP(hdrp->last_freed); M_32_SWAP(hdrp->max_bucket); M_32_SWAP(hdrp->high_mask); M_32_SWAP(hdrp->low_mask); M_32_SWAP(hdrp->ffactor); M_32_SWAP(hdrp->nkeys); M_32_SWAP(hdrp->hdrpages); M_32_SWAP(hdrp->h_charkey); for (i = 0; i < NCACHED; i++) { M_32_SWAP(hdrp->spares[i]); M_16_SWAP(hdrp->bitmaps[i]); } } #endif Index: head/lib/libc/db/hash/hash_buf.c =================================================================== --- head/lib/libc/db/hash/hash_buf.c (revision 297789) +++ head/lib/libc/db/hash/hash_buf.c (revision 297790) @@ -1,358 +1,358 @@ /*- * Copyright (c) 1990, 1993, 1994 * The Regents of the University of California. All rights reserved. * * This code is derived from software contributed to Berkeley by * Margo Seltzer. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 4. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ #if defined(LIBC_SCCS) && !defined(lint) static char sccsid[] = "@(#)hash_buf.c 8.5 (Berkeley) 7/15/94"; #endif /* LIBC_SCCS and not lint */ #include __FBSDID("$FreeBSD$"); /* * PACKAGE: hash * * DESCRIPTION: * Contains buffer management * * ROUTINES: * External * __buf_init * __get_buf * __buf_free * __reclaim_buf * Internal * newbuf */ #include #include #include #include #include #ifdef DEBUG #include #endif #include #include "hash.h" #include "page.h" #include "extern.h" static BUFHEAD *newbuf(HTAB *, u_int32_t, BUFHEAD *); /* Unlink B from its place in the lru */ #define BUF_REMOVE(B) { \ (B)->prev->next = (B)->next; \ (B)->next->prev = (B)->prev; \ } /* Insert B after P */ #define BUF_INSERT(B, P) { \ (B)->next = (P)->next; \ (B)->prev = (P); \ (P)->next = (B); \ (B)->next->prev = (B); \ } #define MRU hashp->bufhead.next #define LRU hashp->bufhead.prev #define MRU_INSERT(B) BUF_INSERT((B), &hashp->bufhead) #define LRU_INSERT(B) BUF_INSERT((B), LRU) /* * We are looking for a buffer with address "addr". If prev_bp is NULL, then * address is a bucket index. If prev_bp is not NULL, then it points to the * page previous to an overflow page that we are trying to find. * * CAVEAT: The buffer header accessed via prev_bp's ovfl field may no longer * be valid. Therefore, you must always verify that its address matches the * address you are seeking. */ BUFHEAD * __get_buf(HTAB *hashp, u_int32_t addr, BUFHEAD *prev_bp, /* If prev_bp set, indicates a new overflow page. */ int newpage) { BUFHEAD *bp; u_int32_t is_disk_mask; int is_disk, segment_ndx; SEGMENT segp; is_disk = 0; is_disk_mask = 0; if (prev_bp) { bp = prev_bp->ovfl; if (!bp || (bp->addr != addr)) bp = NULL; if (!newpage) is_disk = BUF_DISK; } else { /* Grab buffer out of directory */ segment_ndx = addr & (hashp->SGSIZE - 1); /* valid segment ensured by __call_hash() */ segp = hashp->dir[addr >> hashp->SSHIFT]; #ifdef DEBUG assert(segp != NULL); #endif bp = PTROF(segp[segment_ndx]); is_disk_mask = ISDISK(segp[segment_ndx]); is_disk = is_disk_mask || !hashp->new_file; } if (!bp) { bp = newbuf(hashp, addr, prev_bp); if (!bp || __get_page(hashp, bp->page, addr, !prev_bp, is_disk, 0)) return (NULL); if (!prev_bp) segp[segment_ndx] = (BUFHEAD *)((intptr_t)bp | is_disk_mask); } else { BUF_REMOVE(bp); MRU_INSERT(bp); } return (bp); } /* * We need a buffer for this page. Either allocate one, or evict a resident * one (if we have as many buffers as we're allowed) and put this one in. * * If newbuf finds an error (returning NULL), it also sets errno. */ static BUFHEAD * newbuf(HTAB *hashp, u_int32_t addr, BUFHEAD *prev_bp) { BUFHEAD *bp; /* The buffer we're going to use */ BUFHEAD *xbp; /* Temp pointer */ BUFHEAD *next_xbp; SEGMENT segp; int segment_ndx; u_int16_t oaddr, *shortp; oaddr = 0; bp = LRU; /* It is bad to overwrite the page under the cursor. */ if (bp == hashp->cpage) { BUF_REMOVE(bp); MRU_INSERT(bp); bp = LRU; } /* If prev_bp is part of bp overflow, create a new buffer. */ if (hashp->nbufs == 0 && prev_bp && bp->ovfl) { BUFHEAD *ovfl; for (ovfl = bp->ovfl; ovfl ; ovfl = ovfl->ovfl) { if (ovfl == prev_bp) { hashp->nbufs++; break; } } } /* * If LRU buffer is pinned, the buffer pool is too small. We need to * allocate more buffers. */ if (hashp->nbufs || (bp->flags & BUF_PIN) || bp == hashp->cpage) { /* Allocate a new one */ if ((bp = (BUFHEAD *)calloc(1, sizeof(BUFHEAD))) == NULL) return (NULL); if ((bp->page = (char *)calloc(1, hashp->BSIZE)) == NULL) { free(bp); return (NULL); } if (hashp->nbufs) hashp->nbufs--; } else { /* Kick someone out */ BUF_REMOVE(bp); /* * If this is an overflow page with addr 0, it's already been * flushed back in an overflow chain and initialized. */ if ((bp->addr != 0) || (bp->flags & BUF_BUCKET)) { /* * Set oaddr before __put_page so that you get it * before bytes are swapped. */ shortp = (u_int16_t *)bp->page; if (shortp[0]) oaddr = shortp[shortp[0] - 1]; if ((bp->flags & BUF_MOD) && __put_page(hashp, bp->page, bp->addr, (int)IS_BUCKET(bp->flags), 0)) return (NULL); /* * Update the pointer to this page (i.e. invalidate it). * * If this is a new file (i.e. we created it at open * time), make sure that we mark pages which have been * written to disk so we retrieve them from disk later, * rather than allocating new pages. */ if (IS_BUCKET(bp->flags)) { segment_ndx = bp->addr & (hashp->SGSIZE - 1); segp = hashp->dir[bp->addr >> hashp->SSHIFT]; #ifdef DEBUG assert(segp != NULL); #endif if (hashp->new_file && ((bp->flags & BUF_MOD) || ISDISK(segp[segment_ndx]))) segp[segment_ndx] = (BUFHEAD *)BUF_DISK; else segp[segment_ndx] = NULL; } /* * Since overflow pages can only be access by means of * their bucket, free overflow pages associated with * this bucket. */ for (xbp = bp; xbp->ovfl;) { next_xbp = xbp->ovfl; - xbp->ovfl = 0; + xbp->ovfl = NULL; xbp = next_xbp; /* Check that ovfl pointer is up date. */ if (IS_BUCKET(xbp->flags) || (oaddr != xbp->addr)) break; shortp = (u_int16_t *)xbp->page; if (shortp[0]) /* set before __put_page */ oaddr = shortp[shortp[0] - 1]; if ((xbp->flags & BUF_MOD) && __put_page(hashp, xbp->page, xbp->addr, 0, 0)) return (NULL); xbp->addr = 0; xbp->flags = 0; BUF_REMOVE(xbp); LRU_INSERT(xbp); } } } /* Now assign this buffer */ bp->addr = addr; #ifdef DEBUG1 (void)fprintf(stderr, "NEWBUF1: %d->ovfl was %d is now %d\n", bp->addr, (bp->ovfl ? bp->ovfl->addr : 0), 0); #endif bp->ovfl = NULL; if (prev_bp) { /* * If prev_bp is set, this is an overflow page, hook it in to * the buffer overflow links. */ #ifdef DEBUG1 (void)fprintf(stderr, "NEWBUF2: %d->ovfl was %d is now %d\n", prev_bp->addr, (prev_bp->ovfl ? prev_bp->ovfl->addr : 0), (bp ? bp->addr : 0)); #endif prev_bp->ovfl = bp; bp->flags = 0; } else bp->flags = BUF_BUCKET; MRU_INSERT(bp); return (bp); } void __buf_init(HTAB *hashp, int nbytes) { BUFHEAD *bfp; int npages; bfp = &(hashp->bufhead); npages = (nbytes + hashp->BSIZE - 1) >> hashp->BSHIFT; npages = MAX(npages, MIN_BUFFERS); hashp->nbufs = npages; bfp->next = bfp; bfp->prev = bfp; /* * This space is calloc'd so these are already null. * * bfp->ovfl = NULL; * bfp->flags = 0; * bfp->page = NULL; * bfp->addr = 0; */ } int __buf_free(HTAB *hashp, int do_free, int to_disk) { BUFHEAD *bp; /* Need to make sure that buffer manager has been initialized */ if (!LRU) return (0); for (bp = LRU; bp != &hashp->bufhead;) { /* Check that the buffer is valid */ if (bp->addr || IS_BUCKET(bp->flags)) { if (to_disk && (bp->flags & BUF_MOD) && __put_page(hashp, bp->page, bp->addr, IS_BUCKET(bp->flags), 0)) return (-1); } /* Check if we are freeing stuff */ if (do_free) { if (bp->page) { (void)memset(bp->page, 0, hashp->BSIZE); free(bp->page); } BUF_REMOVE(bp); free(bp); bp = LRU; } else bp = bp->prev; } return (0); } void __reclaim_buf(HTAB *hashp, BUFHEAD *bp) { - bp->ovfl = 0; + bp->ovfl = NULL; bp->addr = 0; bp->flags = 0; BUF_REMOVE(bp); LRU_INSERT(bp); } Index: head/lib/libc/gen/err.c =================================================================== --- head/lib/libc/gen/err.c (revision 297789) +++ head/lib/libc/gen/err.c (revision 297790) @@ -1,192 +1,192 @@ /*- * Copyright (c) 1993 * The Regents of the University of California. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 4. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ #if defined(LIBC_SCCS) && !defined(lint) static char sccsid[] = "@(#)err.c 8.1 (Berkeley) 6/4/93"; #endif /* LIBC_SCCS and not lint */ #include __FBSDID("$FreeBSD$"); #include "namespace.h" #include #include #include #include #include #include #include "un-namespace.h" #include "libc_private.h" static FILE *err_file; /* file to use for error output */ static void (*err_exit)(int); /* * This is declared to take a `void *' so that the caller is not required * to include first. However, it is really a `FILE *', and the * manual page documents it as such. */ void err_set_file(void *fp) { if (fp) err_file = fp; else err_file = stderr; } void err_set_exit(void (*ef)(int)) { err_exit = ef; } __weak_reference(_err, err); void _err(int eval, const char *fmt, ...) { va_list ap; va_start(ap, fmt); verrc(eval, errno, fmt, ap); va_end(ap); } void verr(int eval, const char *fmt, va_list ap) { verrc(eval, errno, fmt, ap); } void errc(int eval, int code, const char *fmt, ...) { va_list ap; va_start(ap, fmt); verrc(eval, code, fmt, ap); va_end(ap); } void verrc(int eval, int code, const char *fmt, va_list ap) { - if (err_file == 0) + if (err_file == NULL) err_set_file((FILE *)0); fprintf(err_file, "%s: ", _getprogname()); if (fmt != NULL) { vfprintf(err_file, fmt, ap); fprintf(err_file, ": "); } fprintf(err_file, "%s\n", strerror(code)); if (err_exit) err_exit(eval); exit(eval); } void errx(int eval, const char *fmt, ...) { va_list ap; va_start(ap, fmt); verrx(eval, fmt, ap); va_end(ap); } void verrx(int eval, const char *fmt, va_list ap) { - if (err_file == 0) + if (err_file == NULL) err_set_file((FILE *)0); fprintf(err_file, "%s: ", _getprogname()); if (fmt != NULL) vfprintf(err_file, fmt, ap); fprintf(err_file, "\n"); if (err_exit) err_exit(eval); exit(eval); } __weak_reference(_warn, warn); void _warn(const char *fmt, ...) { va_list ap; va_start(ap, fmt); vwarnc(errno, fmt, ap); va_end(ap); } void vwarn(const char *fmt, va_list ap) { vwarnc(errno, fmt, ap); } void warnc(int code, const char *fmt, ...) { va_list ap; va_start(ap, fmt); vwarnc(code, fmt, ap); va_end(ap); } void vwarnc(int code, const char *fmt, va_list ap) { - if (err_file == 0) + if (err_file == NULL) err_set_file((FILE *)0); fprintf(err_file, "%s: ", _getprogname()); if (fmt != NULL) { vfprintf(err_file, fmt, ap); fprintf(err_file, ": "); } fprintf(err_file, "%s\n", strerror(code)); } void warnx(const char *fmt, ...) { va_list ap; va_start(ap, fmt); vwarnx(fmt, ap); va_end(ap); } void vwarnx(const char *fmt, va_list ap) { - if (err_file == 0) + if (err_file == NULL) err_set_file((FILE *)0); fprintf(err_file, "%s: ", _getprogname()); if (fmt != NULL) vfprintf(err_file, fmt, ap); fprintf(err_file, "\n"); } Index: head/lib/libc/gen/getmntinfo.c =================================================================== --- head/lib/libc/gen/getmntinfo.c (revision 297789) +++ head/lib/libc/gen/getmntinfo.c (revision 297790) @@ -1,66 +1,66 @@ /* * Copyright (c) 1989, 1993 * The Regents of the University of California. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 4. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ #if defined(LIBC_SCCS) && !defined(lint) static char sccsid[] = "@(#)getmntinfo.c 8.1 (Berkeley) 6/4/93"; #endif /* LIBC_SCCS and not lint */ #include __FBSDID("$FreeBSD$"); #include #include #include #include /* * Return information about mounted filesystems. */ int getmntinfo(struct statfs **mntbufp, int flags) { static struct statfs *mntbuf; static int mntsize; static long bufsize; if (mntsize <= 0 && (mntsize = getfsstat(0, 0, MNT_NOWAIT)) < 0) return (0); if (bufsize > 0 && (mntsize = getfsstat(mntbuf, bufsize, flags)) < 0) return (0); while (bufsize <= mntsize * sizeof(struct statfs)) { if (mntbuf) free(mntbuf); bufsize = (mntsize + 1) * sizeof(struct statfs); - if ((mntbuf = (struct statfs *)malloc(bufsize)) == 0) + if ((mntbuf = malloc(bufsize)) == NULL) return (0); if ((mntsize = getfsstat(mntbuf, bufsize, flags)) < 0) return (0); } *mntbufp = mntbuf; return (mntsize); } Index: head/lib/libc/gen/opendir.c =================================================================== --- head/lib/libc/gen/opendir.c (revision 297789) +++ head/lib/libc/gen/opendir.c (revision 297790) @@ -1,360 +1,360 @@ /*- * Copyright (c) 1983, 1993 * The Regents of the University of California. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 4. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ #if defined(LIBC_SCCS) && !defined(lint) static char sccsid[] = "@(#)opendir.c 8.8 (Berkeley) 5/1/95"; #endif /* LIBC_SCCS and not lint */ #include __FBSDID("$FreeBSD$"); #include "namespace.h" #include #include #include #include #include #include #include #include #include #include "un-namespace.h" #include "gen-private.h" #include "telldir.h" static DIR * __opendir_common(int, int, bool); /* * Open a directory. */ DIR * opendir(const char *name) { return (__opendir2(name, DTF_HIDEW|DTF_NODUP)); } /* * Open a directory with existing file descriptor. */ DIR * fdopendir(int fd) { if (_fcntl(fd, F_SETFD, FD_CLOEXEC) == -1) return (NULL); return (__opendir_common(fd, DTF_HIDEW|DTF_NODUP, true)); } DIR * __opendir2(const char *name, int flags) { int fd; DIR *dir; int saved_errno; if ((flags & (__DTF_READALL | __DTF_SKIPREAD)) != 0) return (NULL); if ((fd = _open(name, O_RDONLY | O_NONBLOCK | O_DIRECTORY | O_CLOEXEC)) == -1) return (NULL); dir = __opendir_common(fd, flags, false); if (dir == NULL) { saved_errno = errno; _close(fd); errno = saved_errno; } return (dir); } static int opendir_compar(const void *p1, const void *p2) { return (strcmp((*(const struct dirent **)p1)->d_name, (*(const struct dirent **)p2)->d_name)); } /* * For a directory at the top of a unionfs stack, the entire directory's * contents are read and cached locally until the next call to rewinddir(). * For the fdopendir() case, the initial seek position must be preserved. * For rewinddir(), the full directory should always be re-read from the * beginning. * * If an error occurs, the existing buffer and state of 'dirp' is left * unchanged. */ bool _filldir(DIR *dirp, bool use_current_pos) { struct dirent **dpv; char *buf, *ddptr, *ddeptr; off_t pos; int fd2, incr, len, n, saved_errno, space; len = 0; space = 0; buf = NULL; ddptr = NULL; /* * Use the system page size if that is a multiple of DIRBLKSIZ. * Hopefully this can be a big win someday by allowing page * trades to user space to be done by _getdirentries(). */ incr = getpagesize(); if ((incr % DIRBLKSIZ) != 0) incr = DIRBLKSIZ; /* * The strategy here is to read all the directory * entries into a buffer, sort the buffer, and * remove duplicate entries by setting the inode * number to zero. * * We reopen the directory because _getdirentries() * on a MNT_UNION mount modifies the open directory, * making it refer to the lower directory after the * upper directory's entries are exhausted. * This would otherwise break software that uses * the directory descriptor for fchdir or *at * functions, such as fts.c. */ if ((fd2 = _openat(dirp->dd_fd, ".", O_RDONLY | O_CLOEXEC)) == -1) return (false); if (use_current_pos) { pos = lseek(dirp->dd_fd, 0, SEEK_CUR); if (pos == -1 || lseek(fd2, pos, SEEK_SET) == -1) { saved_errno = errno; _close(fd2); errno = saved_errno; return (false); } } do { /* * Always make at least DIRBLKSIZ bytes * available to _getdirentries */ if (space < DIRBLKSIZ) { space += incr; len += incr; buf = reallocf(buf, len); if (buf == NULL) { saved_errno = errno; _close(fd2); errno = saved_errno; return (false); } ddptr = buf + (len - space); } n = _getdirentries(fd2, ddptr, space, &dirp->dd_seek); if (n > 0) { ddptr += n; space -= n; } if (n < 0) { saved_errno = errno; _close(fd2); errno = saved_errno; return (false); } } while (n > 0); _close(fd2); ddeptr = ddptr; /* * There is now a buffer full of (possibly) duplicate * names. */ dirp->dd_buf = buf; /* * Go round this loop twice... * * Scan through the buffer, counting entries. * On the second pass, save pointers to each one. * Then sort the pointers and remove duplicate names. */ - for (dpv = 0;;) { + for (dpv = NULL;;) { n = 0; ddptr = buf; while (ddptr < ddeptr) { struct dirent *dp; dp = (struct dirent *) ddptr; if ((long)dp & 03L) break; if ((dp->d_reclen <= 0) || (dp->d_reclen > (ddeptr + 1 - ddptr))) break; ddptr += dp->d_reclen; if (dp->d_fileno) { if (dpv) dpv[n] = dp; n++; } } if (dpv) { struct dirent *xp; /* * This sort must be stable. */ mergesort(dpv, n, sizeof(*dpv), opendir_compar); dpv[n] = NULL; xp = NULL; /* * Scan through the buffer in sort order, * zapping the inode number of any * duplicate names. */ for (n = 0; dpv[n]; n++) { struct dirent *dp = dpv[n]; if ((xp == NULL) || strcmp(dp->d_name, xp->d_name)) { xp = dp; } else { dp->d_fileno = 0; } if (dp->d_type == DT_WHT && (dirp->dd_flags & DTF_HIDEW)) dp->d_fileno = 0; } free(dpv); break; } else { dpv = malloc((n+1) * sizeof(struct dirent *)); if (dpv == NULL) break; } } dirp->dd_len = len; dirp->dd_size = ddptr - dirp->dd_buf; return (true); } /* * Common routine for opendir(3), __opendir2(3) and fdopendir(3). */ static DIR * __opendir_common(int fd, int flags, bool use_current_pos) { DIR *dirp; int incr; int saved_errno; int unionstack; if ((dirp = malloc(sizeof(DIR) + sizeof(struct _telldir))) == NULL) return (NULL); dirp->dd_buf = NULL; dirp->dd_fd = fd; dirp->dd_flags = flags; dirp->dd_loc = 0; dirp->dd_lock = NULL; dirp->dd_td = (struct _telldir *)((char *)dirp + sizeof(DIR)); LIST_INIT(&dirp->dd_td->td_locq); dirp->dd_td->td_loccnt = 0; /* * Use the system page size if that is a multiple of DIRBLKSIZ. * Hopefully this can be a big win someday by allowing page * trades to user space to be done by _getdirentries(). */ incr = getpagesize(); if ((incr % DIRBLKSIZ) != 0) incr = DIRBLKSIZ; /* * Determine whether this directory is the top of a union stack. */ if (flags & DTF_NODUP) { struct statfs sfb; if (_fstatfs(fd, &sfb) < 0) goto fail; unionstack = !strcmp(sfb.f_fstypename, "unionfs") || (sfb.f_flags & MNT_UNION); } else { unionstack = 0; } if (unionstack) { if (!_filldir(dirp, use_current_pos)) goto fail; dirp->dd_flags |= __DTF_READALL; } else { dirp->dd_len = incr; dirp->dd_buf = malloc(dirp->dd_len); if (dirp->dd_buf == NULL) goto fail; if (use_current_pos) { /* * Read the first batch of directory entries * to prime dd_seek. This also checks if the * fd passed to fdopendir() is a directory. */ dirp->dd_size = _getdirentries(dirp->dd_fd, dirp->dd_buf, dirp->dd_len, &dirp->dd_seek); if (dirp->dd_size < 0) { if (errno == EINVAL) errno = ENOTDIR; goto fail; } dirp->dd_flags |= __DTF_SKIPREAD; } else { dirp->dd_size = 0; dirp->dd_seek = 0; } } return (dirp); fail: saved_errno = errno; free(dirp->dd_buf); free(dirp); errno = saved_errno; return (NULL); } Index: head/lib/libc/gen/tls.c =================================================================== --- head/lib/libc/gen/tls.c (revision 297789) +++ head/lib/libc/gen/tls.c (revision 297790) @@ -1,328 +1,328 @@ /*- * Copyright (c) 2004 Doug Rabson * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * $FreeBSD$ */ /* * Define stubs for TLS internals so that programs and libraries can * link. These functions will be replaced by functional versions at * runtime from ld-elf.so.1. */ #include #include #include #include #include "libc_private.h" /* Provided by jemalloc to avoid bootstrapping issues. */ void *__je_bootstrap_malloc(size_t size); void *__je_bootstrap_calloc(size_t num, size_t size); void __je_bootstrap_free(void *ptr); __weak_reference(__libc_allocate_tls, _rtld_allocate_tls); __weak_reference(__libc_free_tls, _rtld_free_tls); #ifdef __i386__ __weak_reference(___libc_tls_get_addr, ___tls_get_addr); __attribute__((__regparm__(1))) void * ___libc_tls_get_addr(void *); #endif void * __libc_tls_get_addr(void *); __weak_reference(__libc_tls_get_addr, __tls_get_addr); void *_rtld_allocate_tls(void *oldtls, size_t tcbsize, size_t tcbalign); void _rtld_free_tls(void *tls, size_t tcbsize, size_t tcbalign); void *__libc_allocate_tls(void *oldtls, size_t tcbsize, size_t tcbalign); void __libc_free_tls(void *tls, size_t tcbsize, size_t tcbalign); #if defined(__amd64__) #define TLS_TCB_ALIGN 16 #elif defined(__aarch64__) || defined(__arm__) || defined(__i386__) || \ defined(__mips__) || defined(__powerpc__) || defined(__riscv__) || \ defined(__sparc64__) #define TLS_TCB_ALIGN sizeof(void *) #else #error TLS_TCB_ALIGN undefined for target architecture #endif #if defined(__aarch64__) || defined(__arm__) || defined(__mips__) || \ defined(__powerpc__) || defined(__riscv__) #define TLS_VARIANT_I #endif #if defined(__i386__) || defined(__amd64__) || defined(__sparc64__) #define TLS_VARIANT_II #endif #ifndef PIC #define round(size, align) \ (((size) + (align) - 1) & ~((align) - 1)) static size_t tls_static_space; static size_t tls_init_size; static void *tls_init; #endif #ifdef __i386__ /* GNU ABI */ __attribute__((__regparm__(1))) void * ___libc_tls_get_addr(void *ti __unused) { return (0); } #endif void * __libc_tls_get_addr(void *ti __unused) { return (0); } #ifndef PIC #ifdef TLS_VARIANT_I #define TLS_TCB_SIZE (2 * sizeof(void *)) /* * Free Static TLS using the Variant I method. */ void __libc_free_tls(void *tcb, size_t tcbsize, size_t tcbalign __unused) { Elf_Addr *dtv; Elf_Addr **tls; tls = (Elf_Addr **)((Elf_Addr)tcb + tcbsize - TLS_TCB_SIZE); dtv = tls[0]; __je_bootstrap_free(dtv); __je_bootstrap_free(tcb); } /* * Allocate Static TLS using the Variant I method. */ void * __libc_allocate_tls(void *oldtcb, size_t tcbsize, size_t tcbalign __unused) { Elf_Addr *dtv; Elf_Addr **tls; char *tcb; if (oldtcb != NULL && tcbsize == TLS_TCB_SIZE) return (oldtcb); tcb = __je_bootstrap_calloc(1, tls_static_space + tcbsize - TLS_TCB_SIZE); tls = (Elf_Addr **)(tcb + tcbsize - TLS_TCB_SIZE); if (oldtcb != NULL) { memcpy(tls, oldtcb, tls_static_space); __je_bootstrap_free(oldtcb); /* Adjust the DTV. */ dtv = tls[0]; dtv[2] = (Elf_Addr)tls + TLS_TCB_SIZE; } else { dtv = __je_bootstrap_malloc(3 * sizeof(Elf_Addr)); tls[0] = dtv; dtv[0] = 1; dtv[1] = 1; dtv[2] = (Elf_Addr)tls + TLS_TCB_SIZE; if (tls_init_size > 0) memcpy((void*)dtv[2], tls_init, tls_init_size); if (tls_static_space > tls_init_size) memset((void*)(dtv[2] + tls_init_size), 0, tls_static_space - tls_init_size); } return(tcb); } #endif #ifdef TLS_VARIANT_II #define TLS_TCB_SIZE (3 * sizeof(Elf_Addr)) /* * Free Static TLS using the Variant II method. */ void __libc_free_tls(void *tcb, size_t tcbsize __unused, size_t tcbalign) { size_t size; Elf_Addr* dtv; Elf_Addr tlsstart, tlsend; /* * Figure out the size of the initial TLS block so that we can * find stuff which ___tls_get_addr() allocated dynamically. */ size = round(tls_static_space, tcbalign); dtv = ((Elf_Addr**)tcb)[1]; tlsend = (Elf_Addr) tcb; tlsstart = tlsend - size; __je_bootstrap_free((void*) tlsstart); __je_bootstrap_free(dtv); } /* * Allocate Static TLS using the Variant II method. */ void * __libc_allocate_tls(void *oldtls, size_t tcbsize, size_t tcbalign) { size_t size; char *tls; Elf_Addr *dtv; Elf_Addr segbase, oldsegbase; size = round(tls_static_space, tcbalign); if (tcbsize < 2 * sizeof(Elf_Addr)) tcbsize = 2 * sizeof(Elf_Addr); tls = __je_bootstrap_calloc(1, size + tcbsize); dtv = __je_bootstrap_malloc(3 * sizeof(Elf_Addr)); segbase = (Elf_Addr)(tls + size); ((Elf_Addr*)segbase)[0] = segbase; ((Elf_Addr*)segbase)[1] = (Elf_Addr) dtv; dtv[0] = 1; dtv[1] = 1; dtv[2] = segbase - tls_static_space; if (oldtls) { /* * Copy the static TLS block over whole. */ oldsegbase = (Elf_Addr) oldtls; memcpy((void *)(segbase - tls_static_space), (const void *)(oldsegbase - tls_static_space), tls_static_space); /* * We assume that this block was the one we created with * allocate_initial_tls(). */ _rtld_free_tls(oldtls, 2*sizeof(Elf_Addr), sizeof(Elf_Addr)); } else { memcpy((void *)(segbase - tls_static_space), tls_init, tls_init_size); memset((void *)(segbase - tls_static_space + tls_init_size), 0, tls_static_space - tls_init_size); } return (void*) segbase; } #endif /* TLS_VARIANT_II */ #else void * __libc_allocate_tls(void *oldtls __unused, size_t tcbsize __unused, size_t tcbalign __unused) { return (0); } void __libc_free_tls(void *tcb __unused, size_t tcbsize __unused, size_t tcbalign __unused) { } #endif /* PIC */ extern char **environ; void _init_tls(void) { #ifndef PIC Elf_Addr *sp; Elf_Auxinfo *aux, *auxp; Elf_Phdr *phdr; size_t phent, phnum; int i; void *tls; sp = (Elf_Addr *) environ; while (*sp++ != 0) ; aux = (Elf_Auxinfo *) sp; - phdr = 0; + phdr = NULL; phent = phnum = 0; for (auxp = aux; auxp->a_type != AT_NULL; auxp++) { switch (auxp->a_type) { case AT_PHDR: phdr = auxp->a_un.a_ptr; break; case AT_PHENT: phent = auxp->a_un.a_val; break; case AT_PHNUM: phnum = auxp->a_un.a_val; break; } } - if (phdr == 0 || phent != sizeof(Elf_Phdr) || phnum == 0) + if (phdr == NULL || phent != sizeof(Elf_Phdr) || phnum == 0) return; for (i = 0; (unsigned) i < phnum; i++) { if (phdr[i].p_type == PT_TLS) { tls_static_space = round(phdr[i].p_memsz, phdr[i].p_align); tls_init_size = phdr[i].p_filesz; tls_init = (void*) phdr[i].p_vaddr; } } #ifdef TLS_VARIANT_I /* * tls_static_space should include space for TLS structure */ tls_static_space += TLS_TCB_SIZE; #endif tls = _rtld_allocate_tls(NULL, TLS_TCB_SIZE, TLS_TCB_ALIGN); _set_tp(tls); #endif } Index: head/lib/libc/locale/xlocale_private.h =================================================================== --- head/lib/libc/locale/xlocale_private.h (revision 297789) +++ head/lib/libc/locale/xlocale_private.h (revision 297790) @@ -1,232 +1,231 @@ /*- * Copyright (c) 2011 The FreeBSD Foundation * All rights reserved. * * This software was developed by David Chisnall under sponsorship from * the FreeBSD Foundation. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * $FreeBSD$ */ #ifndef _XLOCALE_PRIVATE__H_ #define _XLOCALE_PRIVATE__H_ #include #include #include #include #include #include #include "setlocale.h" enum { XLC_COLLATE = 0, XLC_CTYPE, XLC_MONETARY, XLC_NUMERIC, XLC_TIME, XLC_MESSAGES, XLC_LAST }; /** * Header used for objects that are reference counted. Objects may optionally * have a destructor associated, which is responsible for destroying the * structure. Global / static versions of the structure should have no * destructor set - they can then have their reference counts manipulated as * normal, but will not do anything with them. * * The header stores a retain count - objects are assumed to have a reference * count of 1 when they are created, but the retain count is 0. When the * retain count is less than 0, they are freed. */ struct xlocale_refcounted { /** Number of references to this component. */ long retain_count; /** Function used to destroy this component, if one is required*/ void(*destructor)(void*); }; /** * Header for a locale component. All locale components must begin with this * header. */ struct xlocale_component { struct xlocale_refcounted header; /** Name of the locale used for this component. */ char locale[ENCODING_LEN+1]; }; /** * xlocale structure, stores per-thread locale information. */ struct _xlocale { struct xlocale_refcounted header; /** Components for the locale. */ struct xlocale_component *components[XLC_LAST]; /** Flag indicating if components[XLC_MONETARY] has changed since the * last call to localeconv_l() with this locale. */ int monetary_locale_changed; /** Flag indicating whether this locale is actually using a locale for * LC_MONETARY (1), or if it should use the C default instead (0). */ int using_monetary_locale; /** Flag indicating if components[XLC_NUMERIC] has changed since the * last call to localeconv_l() with this locale. */ int numeric_locale_changed; /** Flag indicating whether this locale is actually using a locale for * LC_NUMERIC (1), or if it should use the C default instead (0). */ int using_numeric_locale; /** Flag indicating whether this locale is actually using a locale for * LC_TIME (1), or if it should use the C default instead (0). */ int using_time_locale; /** Flag indicating whether this locale is actually using a locale for * LC_MESSAGES (1), or if it should use the C default instead (0). */ int using_messages_locale; /** The structure to be returned from localeconv_l() for this locale. */ struct lconv lconv; /** Persistent state used by mblen() calls. */ __mbstate_t mblen; /** Persistent state used by mbrlen() calls. */ __mbstate_t mbrlen; /** Persistent state used by mbrtoc16() calls. */ __mbstate_t mbrtoc16; /** Persistent state used by mbrtoc32() calls. */ __mbstate_t mbrtoc32; /** Persistent state used by mbrtowc() calls. */ __mbstate_t mbrtowc; /** Persistent state used by mbsnrtowcs() calls. */ __mbstate_t mbsnrtowcs; /** Persistent state used by mbsrtowcs() calls. */ __mbstate_t mbsrtowcs; /** Persistent state used by mbtowc() calls. */ __mbstate_t mbtowc; /** Persistent state used by c16rtomb() calls. */ __mbstate_t c16rtomb; /** Persistent state used by c32rtomb() calls. */ __mbstate_t c32rtomb; /** Persistent state used by wcrtomb() calls. */ __mbstate_t wcrtomb; /** Persistent state used by wcsnrtombs() calls. */ __mbstate_t wcsnrtombs; /** Persistent state used by wcsrtombs() calls. */ __mbstate_t wcsrtombs; /** Persistent state used by wctomb() calls. */ __mbstate_t wctomb; /** Buffer used by nl_langinfo_l() */ char *csym; }; /** * Increments the reference count of a reference-counted structure. */ __attribute__((unused)) static void* xlocale_retain(void *val) { struct xlocale_refcounted *obj = val; atomic_add_long(&(obj->retain_count), 1); return (val); } /** * Decrements the reference count of a reference-counted structure, freeing it * if this is the last reference, calling its destructor if it has one. */ __attribute__((unused)) static void xlocale_release(void *val) { struct xlocale_refcounted *obj = val; - long count = atomic_fetchadd_long(&(obj->retain_count), -1) - 1; - if (count < 0) { - if (0 != obj->destructor) { - obj->destructor(obj); - } - } + long count; + + count = atomic_fetchadd_long(&(obj->retain_count), -1) - 1; + if (count < 0 && obj->destructor != NULL) + obj->destructor(obj); } /** * Load functions. Each takes the name of a locale and a pointer to the data * to be initialised as arguments. Two special values are allowed for the */ extern void* __collate_load(const char*, locale_t); extern void* __ctype_load(const char*, locale_t); extern void* __messages_load(const char*, locale_t); extern void* __monetary_load(const char*, locale_t); extern void* __numeric_load(const char*, locale_t); extern void* __time_load(const char*, locale_t); extern struct _xlocale __xlocale_global_locale; extern struct _xlocale __xlocale_C_locale; /** * Caches the rune table in TLS for fast access. */ void __set_thread_rune_locale(locale_t loc); /** * Flag indicating whether a per-thread locale has been set. If no per-thread * locale has ever been set, then we always use the global locale. */ extern int __has_thread_locale; #ifndef __NO_TLS /** * The per-thread locale. Avoids the need to use pthread lookup functions when * getting the per-thread locale. */ extern _Thread_local locale_t __thread_locale; /** * Returns the current locale for this thread, or the global locale if none is * set. The caller does not have to free the locale. The return value from * this call is not guaranteed to remain valid after the locale changes. As * such, this should only be called within libc functions. */ static inline locale_t __get_locale(void) { if (!__has_thread_locale) { return (&__xlocale_global_locale); } return (__thread_locale ? __thread_locale : &__xlocale_global_locale); } #else locale_t __get_locale(void); #endif /** * Two magic values are allowed for locale_t objects. NULL and -1. This * function maps those to the real locales that they represent. */ static inline locale_t get_real_locale(locale_t locale) { switch ((intptr_t)locale) { case 0: return (&__xlocale_C_locale); case -1: return (&__xlocale_global_locale); default: return (locale); } } /** * Replace a placeholder locale with the real global or thread-local locale_t. */ #define FIX_LOCALE(l) (l = get_real_locale(l)) #endif Index: head/lib/libc/net/base64.c =================================================================== --- head/lib/libc/net/base64.c (revision 297789) +++ head/lib/libc/net/base64.c (revision 297790) @@ -1,320 +1,320 @@ /* * Copyright (c) 1996, 1998 by Internet Software Consortium. * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS * SOFTWARE. */ /* * Portions Copyright (c) 1995 by International Business Machines, Inc. * * International Business Machines, Inc. (hereinafter called IBM) grants * permission under its copyrights to use, copy, modify, and distribute this * Software with or without fee, provided that the above copyright notice and * all paragraphs of this notice appear in all copies, and that the name of IBM * not be used in connection with the marketing of any product incorporating * the Software or modifications thereof, without specific, written prior * permission. * * To the extent it has a right to do so, IBM grants an immunity from suit * under its patents, if any, for the use, sale or manufacture of products to * the extent that such products are used for performing Domain Name System * dynamic updates in TCP/IP networks by means of the Software. No immunity is * granted for any product per se or for any other function of any product. * * THE SOFTWARE IS PROVIDED "AS IS", AND IBM DISCLAIMS ALL WARRANTIES, * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A * PARTICULAR PURPOSE. IN NO EVENT SHALL IBM BE LIABLE FOR ANY SPECIAL, * DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER ARISING * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE, EVEN * IF IBM IS APPRISED OF THE POSSIBILITY OF SUCH DAMAGES. */ #include __FBSDID("$FreeBSD$"); #include #include #include #include #include #include #include #include #include #include #include #define Assert(Cond) if (!(Cond)) abort() static const char Base64[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; static const char Pad64 = '='; /* (From RFC1521 and draft-ietf-dnssec-secext-03.txt) The following encoding technique is taken from RFC 1521 by Borenstein and Freed. It is reproduced here in a slightly edited form for convenience. A 65-character subset of US-ASCII is used, enabling 6 bits to be represented per printable character. (The extra 65th character, "=", is used to signify a special processing function.) The encoding process represents 24-bit groups of input bits as output strings of 4 encoded characters. Proceeding from left to right, a 24-bit input group is formed by concatenating 3 8-bit input groups. These 24 bits are then treated as 4 concatenated 6-bit groups, each of which is translated into a single digit in the base64 alphabet. Each 6-bit group is used as an index into an array of 64 printable characters. The character referenced by the index is placed in the output string. Table 1: The Base64 Alphabet Value Encoding Value Encoding Value Encoding Value Encoding 0 A 17 R 34 i 51 z 1 B 18 S 35 j 52 0 2 C 19 T 36 k 53 1 3 D 20 U 37 l 54 2 4 E 21 V 38 m 55 3 5 F 22 W 39 n 56 4 6 G 23 X 40 o 57 5 7 H 24 Y 41 p 58 6 8 I 25 Z 42 q 59 7 9 J 26 a 43 r 60 8 10 K 27 b 44 s 61 9 11 L 28 c 45 t 62 + 12 M 29 d 46 u 63 / 13 N 30 e 47 v 14 O 31 f 48 w (pad) = 15 P 32 g 49 x 16 Q 33 h 50 y Special processing is performed if fewer than 24 bits are available at the end of the data being encoded. A full encoding quantum is always completed at the end of a quantity. When fewer than 24 input bits are available in an input group, zero bits are added (on the right) to form an integral number of 6-bit groups. Padding at the end of the data is performed using the '=' character. Since all base64 input is an integral number of octets, only the ------------------------------------------------- following cases can arise: (1) the final quantum of encoding input is an integral multiple of 24 bits; here, the final unit of encoded output will be an integral multiple of 4 characters with no "=" padding, (2) the final quantum of encoding input is exactly 8 bits; here, the final unit of encoded output will be two characters followed by two "=" padding characters, or (3) the final quantum of encoding input is exactly 16 bits; here, the final unit of encoded output will be three characters followed by one "=" padding character. */ int b64_ntop(u_char const *src, size_t srclength, char *target, size_t targsize) { size_t datalength = 0; u_char input[3]; u_char output[4]; size_t i; while (2 < srclength) { input[0] = *src++; input[1] = *src++; input[2] = *src++; srclength -= 3; output[0] = input[0] >> 2; output[1] = ((input[0] & 0x03) << 4) + (input[1] >> 4); output[2] = ((input[1] & 0x0f) << 2) + (input[2] >> 6); output[3] = input[2] & 0x3f; Assert(output[0] < 64); Assert(output[1] < 64); Assert(output[2] < 64); Assert(output[3] < 64); if (datalength + 4 > targsize) return (-1); target[datalength++] = Base64[output[0]]; target[datalength++] = Base64[output[1]]; target[datalength++] = Base64[output[2]]; target[datalength++] = Base64[output[3]]; } /* Now we worry about padding. */ if (0 != srclength) { /* Get what's left. */ input[0] = input[1] = input[2] = '\0'; for (i = 0; i < srclength; i++) input[i] = *src++; output[0] = input[0] >> 2; output[1] = ((input[0] & 0x03) << 4) + (input[1] >> 4); output[2] = ((input[1] & 0x0f) << 2) + (input[2] >> 6); Assert(output[0] < 64); Assert(output[1] < 64); Assert(output[2] < 64); if (datalength + 4 > targsize) return (-1); target[datalength++] = Base64[output[0]]; target[datalength++] = Base64[output[1]]; if (srclength == 1) target[datalength++] = Pad64; else target[datalength++] = Base64[output[2]]; target[datalength++] = Pad64; } if (datalength >= targsize) return (-1); target[datalength] = '\0'; /* Returned value doesn't count \0. */ return (datalength); } /* skips all whitespace anywhere. converts characters, four at a time, starting at (or after) src from base - 64 numbers into three 8 bit bytes in the target area. it returns the number of data bytes stored at the target, or -1 on error. */ int b64_pton(const char *src, u_char *target, size_t targsize) { int tarindex, state, ch; u_char nextbyte; char *pos; state = 0; tarindex = 0; while ((ch = *src++) != '\0') { if (isspace((unsigned char)ch)) /* Skip whitespace anywhere. */ continue; if (ch == Pad64) break; pos = strchr(Base64, ch); - if (pos == 0) /* A non-base64 character. */ + if (pos == NULL) /* A non-base64 character. */ return (-1); switch (state) { case 0: if (target) { if ((size_t)tarindex >= targsize) return (-1); target[tarindex] = (pos - Base64) << 2; } state = 1; break; case 1: if (target) { if ((size_t)tarindex >= targsize) return (-1); target[tarindex] |= (pos - Base64) >> 4; nextbyte = ((pos - Base64) & 0x0f) << 4; if ((size_t)tarindex + 1 < targsize) target[tarindex + 1] = nextbyte; else if (nextbyte) return (-1); } tarindex++; state = 2; break; case 2: if (target) { if ((size_t)tarindex >= targsize) return (-1); target[tarindex] |= (pos - Base64) >> 2; nextbyte = ((pos - Base64) & 0x03) << 6; if ((size_t)tarindex + 1 < targsize) target[tarindex + 1] = nextbyte; else if (nextbyte) return (-1); } tarindex++; state = 3; break; case 3: if (target) { if ((size_t)tarindex >= targsize) return (-1); target[tarindex] |= (pos - Base64); } tarindex++; state = 0; break; default: abort(); } } /* * We are done decoding Base-64 chars. Let's see if we ended * on a byte boundary, and/or with erroneous trailing characters. */ if (ch == Pad64) { /* We got a pad char. */ ch = *src++; /* Skip it, get next. */ switch (state) { case 0: /* Invalid = in first position */ case 1: /* Invalid = in second position */ return (-1); case 2: /* Valid, means one byte of info */ /* Skip any number of spaces. */ for ((void)NULL; ch != '\0'; ch = *src++) if (!isspace((unsigned char)ch)) break; /* Make sure there is another trailing = sign. */ if (ch != Pad64) return (-1); ch = *src++; /* Skip the = */ /* Fall through to "single trailing =" case. */ /* FALLTHROUGH */ case 3: /* Valid, means two bytes of info */ /* * We know this char is an =. Is there anything but * whitespace after it? */ for ((void)NULL; ch != '\0'; ch = *src++) if (!isspace((unsigned char)ch)) return (-1); /* * Now make sure for cases 2 and 3 that the "extra" * bits that slopped past the last full byte were * zeros. If we don't check them, they become a * subliminal channel. */ if (target && (size_t)tarindex < targsize && target[tarindex] != 0) return (-1); } } else { /* * We ended by seeing the end of the string. Make sure we * have no partial bytes lying around. */ if (state != 0) return (-1); } return (tarindex); } Index: head/lib/libc/net/getifaddrs.c =================================================================== --- head/lib/libc/net/getifaddrs.c (revision 297789) +++ head/lib/libc/net/getifaddrs.c (revision 297790) @@ -1,343 +1,344 @@ /* $KAME: getifaddrs.c,v 1.9 2001/08/20 02:31:20 itojun Exp $ */ /* * Copyright (c) 1995, 1999 * Berkeley Software Design, Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * THIS SOFTWARE IS PROVIDED BY Berkeley Software Design, Inc. ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL Berkeley Software Design, Inc. BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * BSDI getifaddrs.c,v 2.12 2000/02/23 14:51:59 dab Exp */ /* * NOTE: SIOCGIFCONF case is not LP64 friendly. it also does not perform * try-and-error for region size. */ #include __FBSDID("$FreeBSD$"); #include "namespace.h" #include #include #include #include #ifdef NET_RT_IFLIST #include #include #include #include #endif #include #include #include #include #include "un-namespace.h" #if !defined(AF_LINK) #define SA_LEN(sa) sizeof(struct sockaddr) #endif #if !defined(SA_LEN) #define SA_LEN(sa) (sa)->sa_len #endif #define SALIGN (sizeof(long) - 1) #define SA_RLEN(sa) ((sa)->sa_len ? (((sa)->sa_len + SALIGN) & ~SALIGN) : (SALIGN + 1)) #ifndef ALIGNBYTES /* * On systems with a routing socket, ALIGNBYTES should match the value * that the kernel uses when building the messages. */ #define ALIGNBYTES XXX #endif #ifndef ALIGN #define ALIGN(p) (((u_long)(p) + ALIGNBYTES) &~ ALIGNBYTES) #endif #define MAX_SYSCTL_TRY 5 int getifaddrs(struct ifaddrs **pif) { int icnt = 1; int dcnt = 0; int ncnt = 0; int ntry = 0; int mib[6]; size_t needed; char *buf; char *next; - struct ifaddrs *cif = 0; + struct ifaddrs *cif; char *p, *p0; struct rt_msghdr *rtm; struct if_msghdrl *ifm; struct ifa_msghdrl *ifam; struct sockaddr_dl *dl; struct sockaddr *sa; struct ifaddrs *ifa, *ift; struct if_data *if_data; u_short idx = 0; int i; size_t len, alen; char *data; char *names; mib[0] = CTL_NET; mib[1] = PF_ROUTE; mib[2] = 0; /* protocol */ mib[3] = 0; /* wildcard address family */ mib[4] = NET_RT_IFLISTL;/* extra fields for extensible msghdr structs */ mib[5] = 0; /* no flags */ do { /* * We'll try to get addresses several times in case that * the number of addresses is unexpectedly increased during * the two sysctl calls. This should rarely happen, but we'll * try to do our best for applications that assume success of * this library (which should usually be the case). * Portability note: since FreeBSD does not add margin of * memory at the first sysctl, the possibility of failure on * the second sysctl call is a bit higher. */ if (sysctl(mib, 6, NULL, &needed, NULL, 0) < 0) return (-1); if ((buf = malloc(needed)) == NULL) return (-1); if (sysctl(mib, 6, buf, &needed, NULL, 0) < 0) { if (errno != ENOMEM || ++ntry >= MAX_SYSCTL_TRY) { free(buf); return (-1); } free(buf); buf = NULL; } } while (buf == NULL); for (next = buf; next < buf + needed; next += rtm->rtm_msglen) { rtm = (struct rt_msghdr *)(void *)next; if (rtm->rtm_version != RTM_VERSION) continue; switch (rtm->rtm_type) { case RTM_IFINFO: ifm = (struct if_msghdrl *)(void *)rtm; if (ifm->ifm_addrs & RTA_IFP) { idx = ifm->ifm_index; ++icnt; if_data = IF_MSGHDRL_IFM_DATA(ifm); dcnt += if_data->ifi_datalen; dl = (struct sockaddr_dl *)IF_MSGHDRL_RTA(ifm); dcnt += SA_RLEN((struct sockaddr *)(void*)dl) + ALIGNBYTES; ncnt += dl->sdl_nlen + 1; } else idx = 0; break; case RTM_NEWADDR: ifam = (struct ifa_msghdrl *)(void *)rtm; if (idx && ifam->ifam_index != idx) abort(); /* this cannot happen */ #define RTA_MASKS (RTA_NETMASK | RTA_IFA | RTA_BRD) if (idx == 0 || (ifam->ifam_addrs & RTA_MASKS) == 0) break; p = (char *)IFA_MSGHDRL_RTA(ifam); ++icnt; if_data = IFA_MSGHDRL_IFAM_DATA(ifam); dcnt += if_data->ifi_datalen + ALIGNBYTES; /* Scan to look for length of address */ alen = 0; for (p0 = p, i = 0; i < RTAX_MAX; i++) { if ((RTA_MASKS & ifam->ifam_addrs & (1 << i)) == 0) continue; sa = (struct sockaddr *)(void *)p; len = SA_RLEN(sa); if (i == RTAX_IFA) { alen = len; break; } p += len; } for (p = p0, i = 0; i < RTAX_MAX; i++) { if ((RTA_MASKS & ifam->ifam_addrs & (1 << i)) == 0) continue; sa = (struct sockaddr *)(void *)p; len = SA_RLEN(sa); if (i == RTAX_NETMASK && SA_LEN(sa) == 0) dcnt += alen; else dcnt += len; p += len; } break; } } if (icnt + dcnt + ncnt == 1) { *pif = NULL; free(buf); return (0); } data = malloc(sizeof(struct ifaddrs) * icnt + dcnt + ncnt); if (data == NULL) { free(buf); return(-1); } ifa = (struct ifaddrs *)(void *)data; data += sizeof(struct ifaddrs) * icnt; names = data + dcnt; memset(ifa, 0, sizeof(struct ifaddrs) * icnt); ift = ifa; idx = 0; + cif = NULL; for (next = buf; next < buf + needed; next += rtm->rtm_msglen) { rtm = (struct rt_msghdr *)(void *)next; if (rtm->rtm_version != RTM_VERSION) continue; switch (rtm->rtm_type) { case RTM_IFINFO: ifm = (struct if_msghdrl *)(void *)rtm; if ((ifm->ifm_addrs & RTA_IFP) == 0) { idx = 0; break; } idx = ifm->ifm_index; dl = (struct sockaddr_dl *)IF_MSGHDRL_RTA(ifm); cif = ift; ift->ifa_name = names; ift->ifa_flags = (int)ifm->ifm_flags; memcpy(names, dl->sdl_data, (size_t)dl->sdl_nlen); names[dl->sdl_nlen] = 0; names += dl->sdl_nlen + 1; ift->ifa_addr = (struct sockaddr *)(void *)data; memcpy(data, dl, (size_t)SA_LEN((struct sockaddr *) (void *)dl)); data += SA_RLEN((struct sockaddr *)(void *)dl); if_data = IF_MSGHDRL_IFM_DATA(ifm); /* ifm_data needs to be aligned */ ift->ifa_data = data = (void *)ALIGN(data); memcpy(data, if_data, if_data->ifi_datalen); data += if_data->ifi_datalen; ift = (ift->ifa_next = ift + 1); break; case RTM_NEWADDR: ifam = (struct ifa_msghdrl *)(void *)rtm; if (idx && ifam->ifam_index != idx) abort(); /* this cannot happen */ if (idx == 0 || (ifam->ifam_addrs & RTA_MASKS) == 0) break; ift->ifa_name = cif->ifa_name; ift->ifa_flags = cif->ifa_flags; ift->ifa_data = NULL; p = (char *)IFA_MSGHDRL_RTA(ifam); /* Scan to look for length of address */ alen = 0; for (p0 = p, i = 0; i < RTAX_MAX; i++) { if ((RTA_MASKS & ifam->ifam_addrs & (1 << i)) == 0) continue; sa = (struct sockaddr *)(void *)p; len = SA_RLEN(sa); if (i == RTAX_IFA) { alen = len; break; } p += len; } for (p = p0, i = 0; i < RTAX_MAX; i++) { if ((RTA_MASKS & ifam->ifam_addrs & (1 << i)) == 0) continue; sa = (struct sockaddr *)(void *)p; len = SA_RLEN(sa); switch (i) { case RTAX_IFA: ift->ifa_addr = (struct sockaddr *)(void *)data; memcpy(data, p, len); data += len; break; case RTAX_NETMASK: ift->ifa_netmask = (struct sockaddr *)(void *)data; if (SA_LEN(sa) == 0) { memset(data, 0, alen); data += alen; break; } memcpy(data, p, len); data += len; break; case RTAX_BRD: ift->ifa_broadaddr = (struct sockaddr *)(void *)data; memcpy(data, p, len); data += len; break; } p += len; } if_data = IFA_MSGHDRL_IFAM_DATA(ifam); /* ifam_data needs to be aligned */ ift->ifa_data = data = (void *)ALIGN(data); memcpy(data, if_data, if_data->ifi_datalen); data += if_data->ifi_datalen; ift = (ift->ifa_next = ift + 1); break; } } free(buf); if (--ift >= ifa) { ift->ifa_next = NULL; *pif = ifa; } else { *pif = NULL; free(ifa); } return (0); } void freeifaddrs(struct ifaddrs *ifp) { free(ifp); } Index: head/lib/libc/net/getservent.c =================================================================== --- head/lib/libc/net/getservent.c (revision 297789) +++ head/lib/libc/net/getservent.c (revision 297790) @@ -1,1373 +1,1373 @@ /* * Copyright (c) 1983, 1993 * The Regents of the University of California. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 4. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ #if defined(LIBC_SCCS) && !defined(lint) static char sccsid[] = "@(#)getservent.c 8.1 (Berkeley) 6/4/93"; #endif /* LIBC_SCCS and not lint */ #include __FBSDID("$FreeBSD$"); #include #include #include #include #include #include #include #include #include #include #include #include #include #include #ifdef YP #include #include #include #endif #include "namespace.h" #include "reentrant.h" #include "un-namespace.h" #include "netdb_private.h" #ifdef NS_CACHING #include "nscache.h" #endif #include "nss_tls.h" enum constants { SETSERVENT = 1, ENDSERVENT = 2, SERVENT_STORAGE_INITIAL = 1 << 10, /* 1 KByte */ SERVENT_STORAGE_MAX = 1 << 20, /* 1 MByte */ }; struct servent_mdata { enum nss_lookup_type how; int compat_mode; }; static const ns_src defaultsrc[] = { { NSSRC_COMPAT, NS_SUCCESS }, { NULL, 0 } }; static int servent_unpack(char *, struct servent *, char **, size_t, int *); /* files backend declarations */ struct files_state { FILE *fp; int stayopen; int compat_mode_active; }; static void files_endstate(void *); NSS_TLS_HANDLING(files); static int files_servent(void *, void *, va_list); static int files_setservent(void *, void *, va_list); /* db backend declarations */ struct db_state { DB *db; int stayopen; int keynum; }; static void db_endstate(void *); NSS_TLS_HANDLING(db); static int db_servent(void *, void *, va_list); static int db_setservent(void *, void *, va_list); #ifdef YP /* nis backend declarations */ static int nis_servent(void *, void *, va_list); static int nis_setservent(void *, void *, va_list); struct nis_state { int yp_stepping; char yp_domain[MAXHOSTNAMELEN]; char *yp_key; int yp_keylen; }; static void nis_endstate(void *); NSS_TLS_HANDLING(nis); static int nis_servent(void *, void *, va_list); static int nis_setservent(void *, void *, va_list); #endif /* compat backend declarations */ static int compat_setservent(void *, void *, va_list); /* get** wrappers for get**_r functions declarations */ struct servent_state { struct servent serv; char *buffer; size_t bufsize; }; static void servent_endstate(void *); NSS_TLS_HANDLING(servent); struct key { const char *proto; union { const char *name; int port; }; }; static int wrap_getservbyname_r(struct key, struct servent *, char *, size_t, struct servent **); static int wrap_getservbyport_r(struct key, struct servent *, char *, size_t, struct servent **); static int wrap_getservent_r(struct key, struct servent *, char *, size_t, struct servent **); static struct servent *getserv(int (*fn)(struct key, struct servent *, char *, size_t, struct servent **), struct key); #ifdef NS_CACHING static int serv_id_func(char *, size_t *, va_list, void *); static int serv_marshal_func(char *, size_t *, void *, va_list, void *); static int serv_unmarshal_func(char *, size_t, void *, va_list, void *); #endif static int servent_unpack(char *p, struct servent *serv, char **aliases, size_t aliases_size, int *errnop) { char *cp, **q, *endp; long l; if (*p == '#') return -1; memset(serv, 0, sizeof(struct servent)); cp = strpbrk(p, "#\n"); if (cp != NULL) *cp = '\0'; serv->s_name = p; p = strpbrk(p, " \t"); if (p == NULL) return -1; *p++ = '\0'; while (*p == ' ' || *p == '\t') p++; cp = strpbrk(p, ",/"); if (cp == NULL) return -1; *cp++ = '\0'; l = strtol(p, &endp, 10); if (endp == p || *endp != '\0' || l < 0 || l > USHRT_MAX) return -1; serv->s_port = htons((in_port_t)l); serv->s_proto = cp; q = serv->s_aliases = aliases; cp = strpbrk(cp, " \t"); if (cp != NULL) *cp++ = '\0'; while (cp && *cp) { if (*cp == ' ' || *cp == '\t') { cp++; continue; } if (q < &aliases[aliases_size - 1]) { *q++ = cp; } else { *q = NULL; *errnop = ERANGE; return -1; } cp = strpbrk(cp, " \t"); if (cp != NULL) *cp++ = '\0'; } *q = NULL; return 0; } static int parse_result(struct servent *serv, char *buffer, size_t bufsize, char *resultbuf, size_t resultbuflen, int *errnop) { char **aliases; int aliases_size; if (bufsize <= resultbuflen + _ALIGNBYTES + sizeof(char *)) { *errnop = ERANGE; return (NS_RETURN); } aliases = (char **)_ALIGN(&buffer[resultbuflen + 1]); aliases_size = (buffer + bufsize - (char *)aliases) / sizeof(char *); if (aliases_size < 1) { *errnop = ERANGE; return (NS_RETURN); } memcpy(buffer, resultbuf, resultbuflen); buffer[resultbuflen] = '\0'; if (servent_unpack(buffer, serv, aliases, aliases_size, errnop) != 0) return ((*errnop == 0) ? NS_NOTFOUND : NS_RETURN); return (NS_SUCCESS); } /* files backend implementation */ static void files_endstate(void *p) { FILE * f; if (p == NULL) return; f = ((struct files_state *)p)->fp; if (f != NULL) fclose(f); free(p); } /* * compat structures. compat and files sources functionalities are almost * equal, so they all are managed by files_servent function */ static int files_servent(void *retval, void *mdata, va_list ap) { static const ns_src compat_src[] = { #ifdef YP { NSSRC_NIS, NS_SUCCESS }, #endif { NULL, 0 } }; ns_dtab compat_dtab[] = { { NSSRC_DB, db_servent, (void *)((struct servent_mdata *)mdata)->how }, #ifdef YP { NSSRC_NIS, nis_servent, (void *)((struct servent_mdata *)mdata)->how }, #endif { NULL, NULL, NULL } }; struct files_state *st; int rv; int stayopen; struct servent_mdata *serv_mdata; char *name; char *proto; int port; struct servent *serv; char *buffer; size_t bufsize; int *errnop; size_t linesize; char *line; char **cp; name = NULL; proto = NULL; serv_mdata = (struct servent_mdata *)mdata; switch (serv_mdata->how) { case nss_lt_name: name = va_arg(ap, char *); proto = va_arg(ap, char *); break; case nss_lt_id: port = va_arg(ap, int); proto = va_arg(ap, char *); break; case nss_lt_all: break; default: return NS_NOTFOUND; }; serv = va_arg(ap, struct servent *); buffer = va_arg(ap, char *); bufsize = va_arg(ap, size_t); errnop = va_arg(ap,int *); *errnop = files_getstate(&st); if (*errnop != 0) return (NS_UNAVAIL); if (st->fp == NULL) st->compat_mode_active = 0; if (st->fp == NULL && (st->fp = fopen(_PATH_SERVICES, "re")) == NULL) { *errnop = errno; return (NS_UNAVAIL); } if (serv_mdata->how == nss_lt_all) stayopen = 1; else { rewind(st->fp); stayopen = st->stayopen; } rv = NS_NOTFOUND; do { if (!st->compat_mode_active) { if ((line = fgetln(st->fp, &linesize)) == NULL) { *errnop = errno; rv = NS_RETURN; break; } if (*line=='+' && serv_mdata->compat_mode != 0) st->compat_mode_active = 1; } if (st->compat_mode_active != 0) { switch (serv_mdata->how) { case nss_lt_name: rv = nsdispatch(retval, compat_dtab, NSDB_SERVICES_COMPAT, "getservbyname_r", compat_src, name, proto, serv, buffer, bufsize, errnop); break; case nss_lt_id: rv = nsdispatch(retval, compat_dtab, NSDB_SERVICES_COMPAT, "getservbyport_r", compat_src, port, proto, serv, buffer, bufsize, errnop); break; case nss_lt_all: rv = nsdispatch(retval, compat_dtab, NSDB_SERVICES_COMPAT, "getservent_r", compat_src, serv, buffer, bufsize, errnop); break; } if (!(rv & NS_TERMINATE) || serv_mdata->how != nss_lt_all) st->compat_mode_active = 0; continue; } rv = parse_result(serv, buffer, bufsize, line, linesize, errnop); if (rv == NS_NOTFOUND) continue; if (rv == NS_RETURN) break; rv = NS_NOTFOUND; switch (serv_mdata->how) { case nss_lt_name: if (strcmp(name, serv->s_name) == 0) goto gotname; for (cp = serv->s_aliases; *cp; cp++) if (strcmp(name, *cp) == 0) goto gotname; continue; gotname: - if (proto == 0 || strcmp(serv->s_proto, proto) == 0) + if (proto == NULL || strcmp(serv->s_proto, proto) == 0) rv = NS_SUCCESS; break; case nss_lt_id: if (port != serv->s_port) continue; - if (proto == 0 || strcmp(serv->s_proto, proto) == 0) + if (proto == NULL || strcmp(serv->s_proto, proto) == 0) rv = NS_SUCCESS; break; case nss_lt_all: rv = NS_SUCCESS; break; } } while (!(rv & NS_TERMINATE)); if (!stayopen && st->fp != NULL) { fclose(st->fp); st->fp = NULL; } if ((rv == NS_SUCCESS) && (retval != NULL)) *(struct servent **)retval=serv; return (rv); } static int files_setservent(void *retval, void *mdata, va_list ap) { struct files_state *st; int rv; int f; rv = files_getstate(&st); if (rv != 0) return (NS_UNAVAIL); switch ((enum constants)mdata) { case SETSERVENT: f = va_arg(ap,int); if (st->fp == NULL) st->fp = fopen(_PATH_SERVICES, "re"); else rewind(st->fp); st->stayopen |= f; break; case ENDSERVENT: if (st->fp != NULL) { fclose(st->fp); st->fp = NULL; } st->stayopen = 0; break; default: break; }; st->compat_mode_active = 0; return (NS_UNAVAIL); } /* db backend implementation */ static void db_endstate(void *p) { DB *db; if (p == NULL) return; db = ((struct db_state *)p)->db; if (db != NULL) db->close(db); free(p); } static int db_servent(void *retval, void *mdata, va_list ap) { char buf[BUFSIZ]; DBT key, data, *result; DB *db; struct db_state *st; int rv; int stayopen; enum nss_lookup_type how; char *name; char *proto; int port; struct servent *serv; char *buffer; size_t bufsize; int *errnop; name = NULL; proto = NULL; how = (enum nss_lookup_type)mdata; switch (how) { case nss_lt_name: name = va_arg(ap, char *); proto = va_arg(ap, char *); break; case nss_lt_id: port = va_arg(ap, int); proto = va_arg(ap, char *); break; case nss_lt_all: break; default: return NS_NOTFOUND; }; serv = va_arg(ap, struct servent *); buffer = va_arg(ap, char *); bufsize = va_arg(ap, size_t); errnop = va_arg(ap,int *); *errnop = db_getstate(&st); if (*errnop != 0) return (NS_UNAVAIL); if (how == nss_lt_all && st->keynum < 0) return (NS_NOTFOUND); if (st->db == NULL) { st->db = dbopen(_PATH_SERVICES_DB, O_RDONLY, 0, DB_HASH, NULL); if (st->db == NULL) { *errnop = errno; return (NS_UNAVAIL); } } stayopen = (how == nss_lt_all) ? 1 : st->stayopen; db = st->db; do { switch (how) { case nss_lt_name: key.data = buf; if (proto == NULL) key.size = snprintf(buf, sizeof(buf), "\376%s", name); else key.size = snprintf(buf, sizeof(buf), "\376%s/%s", name, proto); key.size++; if (db->get(db, &key, &data, 0) != 0 || db->get(db, &data, &key, 0) != 0) { rv = NS_NOTFOUND; goto db_fin; } result = &key; break; case nss_lt_id: key.data = buf; port = htons(port); if (proto == NULL) key.size = snprintf(buf, sizeof(buf), "\377%d", port); else key.size = snprintf(buf, sizeof(buf), "\377%d/%s", port, proto); key.size++; if (db->get(db, &key, &data, 0) != 0 || db->get(db, &data, &key, 0) != 0) { rv = NS_NOTFOUND; goto db_fin; } result = &key; break; case nss_lt_all: key.data = buf; key.size = snprintf(buf, sizeof(buf), "%d", st->keynum++); key.size++; if (db->get(db, &key, &data, 0) != 0) { st->keynum = -1; rv = NS_NOTFOUND; goto db_fin; } result = &data; break; } rv = parse_result(serv, buffer, bufsize, result->data, result->size - 1, errnop); } while (!(rv & NS_TERMINATE) && how == nss_lt_all); db_fin: if (!stayopen && st->db != NULL) { db->close(db); st->db = NULL; } if (rv == NS_SUCCESS && retval != NULL) *(struct servent **)retval = serv; return (rv); } static int db_setservent(void *retval, void *mdata, va_list ap) { DB *db; struct db_state *st; int rv; int f; rv = db_getstate(&st); if (rv != 0) return (NS_UNAVAIL); switch ((enum constants)mdata) { case SETSERVENT: f = va_arg(ap, int); st->stayopen |= f; st->keynum = 0; break; case ENDSERVENT: db = st->db; if (db != NULL) { db->close(db); st->db = NULL; } st->stayopen = 0; break; default: break; }; return (NS_UNAVAIL); } /* nis backend implementation */ #ifdef YP static void nis_endstate(void *p) { if (p == NULL) return; free(((struct nis_state *)p)->yp_key); free(p); } static int nis_servent(void *retval, void *mdata, va_list ap) { char *resultbuf, *lastkey; int resultbuflen; char buf[YPMAXRECORD + 2]; struct nis_state *st; int rv; enum nss_lookup_type how; char *name; char *proto; int port; struct servent *serv; char *buffer; size_t bufsize; int *errnop; name = NULL; proto = NULL; how = (enum nss_lookup_type)mdata; switch (how) { case nss_lt_name: name = va_arg(ap, char *); proto = va_arg(ap, char *); break; case nss_lt_id: port = va_arg(ap, int); proto = va_arg(ap, char *); break; case nss_lt_all: break; default: return NS_NOTFOUND; }; serv = va_arg(ap, struct servent *); buffer = va_arg(ap, char *); bufsize = va_arg(ap, size_t); errnop = va_arg(ap, int *); *errnop = nis_getstate(&st); if (*errnop != 0) return (NS_UNAVAIL); if (st->yp_domain[0] == '\0') { if (getdomainname(st->yp_domain, sizeof st->yp_domain)) { *errnop = errno; return (NS_UNAVAIL); } } do { switch (how) { case nss_lt_name: snprintf(buf, sizeof(buf), "%s/%s", name, proto); if (yp_match(st->yp_domain, "services.byname", buf, strlen(buf), &resultbuf, &resultbuflen)) { rv = NS_NOTFOUND; goto fin; } break; case nss_lt_id: snprintf(buf, sizeof(buf), "%d/%s", ntohs(port), proto); /* * We have to be a little flexible * here. Ideally you're supposed to have both * a services.byname and a services.byport * map, but some systems have only * services.byname. FreeBSD cheats a little by * putting the services.byport information in * the same map as services.byname so that * either case will work. We allow for both * possibilities here: if there is no * services.byport map, we try services.byname * instead. */ rv = yp_match(st->yp_domain, "services.byport", buf, strlen(buf), &resultbuf, &resultbuflen); if (rv) { if (rv == YPERR_MAP) { if (yp_match(st->yp_domain, "services.byname", buf, strlen(buf), &resultbuf, &resultbuflen)) { rv = NS_NOTFOUND; goto fin; } } else { rv = NS_NOTFOUND; goto fin; } } break; case nss_lt_all: if (!st->yp_stepping) { free(st->yp_key); rv = yp_first(st->yp_domain, "services.byname", &st->yp_key, &st->yp_keylen, &resultbuf, &resultbuflen); if (rv) { rv = NS_NOTFOUND; goto fin; } st->yp_stepping = 1; } else { lastkey = st->yp_key; rv = yp_next(st->yp_domain, "services.byname", st->yp_key, st->yp_keylen, &st->yp_key, &st->yp_keylen, &resultbuf, &resultbuflen); free(lastkey); if (rv) { st->yp_stepping = 0; rv = NS_NOTFOUND; goto fin; } } break; }; rv = parse_result(serv, buffer, bufsize, resultbuf, resultbuflen, errnop); free(resultbuf); } while (!(rv & NS_TERMINATE) && how == nss_lt_all); fin: if (rv == NS_SUCCESS && retval != NULL) *(struct servent **)retval = serv; return (rv); } static int nis_setservent(void *result, void *mdata, va_list ap) { struct nis_state *st; int rv; rv = nis_getstate(&st); if (rv != 0) return (NS_UNAVAIL); switch ((enum constants)mdata) { case SETSERVENT: case ENDSERVENT: free(st->yp_key); st->yp_key = NULL; st->yp_stepping = 0; break; default: break; }; return (NS_UNAVAIL); } #endif /* compat backend implementation */ static int compat_setservent(void *retval, void *mdata, va_list ap) { static const ns_src compat_src[] = { #ifdef YP { NSSRC_NIS, NS_SUCCESS }, #endif { NULL, 0 } }; ns_dtab compat_dtab[] = { { NSSRC_DB, db_setservent, mdata }, #ifdef YP { NSSRC_NIS, nis_setservent, mdata }, #endif { NULL, NULL, NULL } }; int f; (void)files_setservent(retval, mdata, ap); switch ((enum constants)mdata) { case SETSERVENT: f = va_arg(ap,int); (void)nsdispatch(retval, compat_dtab, NSDB_SERVICES_COMPAT, "setservent", compat_src, f); break; case ENDSERVENT: (void)nsdispatch(retval, compat_dtab, NSDB_SERVICES_COMPAT, "endservent", compat_src); break; default: break; } return (NS_UNAVAIL); } #ifdef NS_CACHING static int serv_id_func(char *buffer, size_t *buffer_size, va_list ap, void *cache_mdata) { char *name; char *proto; int port; size_t desired_size, size, size2; enum nss_lookup_type lookup_type; int res = NS_UNAVAIL; lookup_type = (enum nss_lookup_type)cache_mdata; switch (lookup_type) { case nss_lt_name: name = va_arg(ap, char *); proto = va_arg(ap, char *); size = strlen(name); desired_size = sizeof(enum nss_lookup_type) + size + 1; if (proto != NULL) { size2 = strlen(proto); desired_size += size2 + 1; } else size2 = 0; if (desired_size > *buffer_size) { res = NS_RETURN; goto fin; } memcpy(buffer, &lookup_type, sizeof(enum nss_lookup_type)); memcpy(buffer + sizeof(enum nss_lookup_type), name, size + 1); if (proto != NULL) memcpy(buffer + sizeof(enum nss_lookup_type) + size + 1, proto, size2 + 1); res = NS_SUCCESS; break; case nss_lt_id: port = va_arg(ap, int); proto = va_arg(ap, char *); desired_size = sizeof(enum nss_lookup_type) + sizeof(int); if (proto != NULL) { size = strlen(proto); desired_size += size + 1; } else size = 0; if (desired_size > *buffer_size) { res = NS_RETURN; goto fin; } memcpy(buffer, &lookup_type, sizeof(enum nss_lookup_type)); memcpy(buffer + sizeof(enum nss_lookup_type), &port, sizeof(int)); if (proto != NULL) memcpy(buffer + sizeof(enum nss_lookup_type) + sizeof(int), proto, size + 1); res = NS_SUCCESS; break; default: /* should be unreachable */ return (NS_UNAVAIL); } fin: *buffer_size = desired_size; return (res); } int serv_marshal_func(char *buffer, size_t *buffer_size, void *retval, va_list ap, void *cache_mdata) { char *name; char *proto; int port; struct servent *serv; char *orig_buf; size_t orig_buf_size; struct servent new_serv; size_t desired_size; char **alias; char *p; size_t size; size_t aliases_size; switch ((enum nss_lookup_type)cache_mdata) { case nss_lt_name: name = va_arg(ap, char *); proto = va_arg(ap, char *); break; case nss_lt_id: port = va_arg(ap, int); proto = va_arg(ap, char *); break; case nss_lt_all: break; default: /* should be unreachable */ return (NS_UNAVAIL); } serv = va_arg(ap, struct servent *); orig_buf = va_arg(ap, char *); orig_buf_size = va_arg(ap, size_t); desired_size = _ALIGNBYTES + sizeof(struct servent) + sizeof(char *); if (serv->s_name != NULL) desired_size += strlen(serv->s_name) + 1; if (serv->s_proto != NULL) desired_size += strlen(serv->s_proto) + 1; aliases_size = 0; if (serv->s_aliases != NULL) { for (alias = serv->s_aliases; *alias; ++alias) { desired_size += strlen(*alias) + 1; ++aliases_size; } desired_size += _ALIGNBYTES + sizeof(char *) * (aliases_size + 1); } if (*buffer_size < desired_size) { /* this assignment is here for future use */ *buffer_size = desired_size; return (NS_RETURN); } memcpy(&new_serv, serv, sizeof(struct servent)); memset(buffer, 0, desired_size); *buffer_size = desired_size; p = buffer + sizeof(struct servent) + sizeof(char *); memcpy(buffer + sizeof(struct servent), &p, sizeof(char *)); p = (char *)_ALIGN(p); if (new_serv.s_name != NULL) { size = strlen(new_serv.s_name); memcpy(p, new_serv.s_name, size); new_serv.s_name = p; p += size + 1; } if (new_serv.s_proto != NULL) { size = strlen(new_serv.s_proto); memcpy(p, new_serv.s_proto, size); new_serv.s_proto = p; p += size + 1; } if (new_serv.s_aliases != NULL) { p = (char *)_ALIGN(p); memcpy(p, new_serv.s_aliases, sizeof(char *) * aliases_size); new_serv.s_aliases = (char **)p; p += sizeof(char *) * (aliases_size + 1); for (alias = new_serv.s_aliases; *alias; ++alias) { size = strlen(*alias); memcpy(p, *alias, size); *alias = p; p += size + 1; } } memcpy(buffer, &new_serv, sizeof(struct servent)); return (NS_SUCCESS); } int serv_unmarshal_func(char *buffer, size_t buffer_size, void *retval, va_list ap, void *cache_mdata) { char *name; char *proto; int port; struct servent *serv; char *orig_buf; char *p; char **alias; size_t orig_buf_size; int *ret_errno; switch ((enum nss_lookup_type)cache_mdata) { case nss_lt_name: name = va_arg(ap, char *); proto = va_arg(ap, char *); break; case nss_lt_id: port = va_arg(ap, int); proto = va_arg(ap, char *); break; case nss_lt_all: break; default: /* should be unreachable */ return (NS_UNAVAIL); } serv = va_arg(ap, struct servent *); orig_buf = va_arg(ap, char *); orig_buf_size = va_arg(ap, size_t); ret_errno = va_arg(ap, int *); if (orig_buf_size < buffer_size - sizeof(struct servent) - sizeof(char *)) { *ret_errno = ERANGE; return (NS_RETURN); } memcpy(serv, buffer, sizeof(struct servent)); memcpy(&p, buffer + sizeof(struct servent), sizeof(char *)); orig_buf = (char *)_ALIGN(orig_buf); memcpy(orig_buf, buffer + sizeof(struct servent) + sizeof(char *) + (_ALIGN(p) - (size_t)p), buffer_size - sizeof(struct servent) - sizeof(char *) - (_ALIGN(p) - (size_t)p)); p = (char *)_ALIGN(p); NS_APPLY_OFFSET(serv->s_name, orig_buf, p, char *); NS_APPLY_OFFSET(serv->s_proto, orig_buf, p, char *); if (serv->s_aliases != NULL) { NS_APPLY_OFFSET(serv->s_aliases, orig_buf, p, char **); for (alias = serv->s_aliases; *alias; ++alias) NS_APPLY_OFFSET(*alias, orig_buf, p, char *); } if (retval != NULL) *((struct servent **)retval) = serv; return (NS_SUCCESS); } NSS_MP_CACHE_HANDLING(services); #endif /* NS_CACHING */ /* get**_r functions implementation */ int getservbyname_r(const char *name, const char *proto, struct servent *serv, char *buffer, size_t bufsize, struct servent **result) { static const struct servent_mdata mdata = { nss_lt_name, 0 }; static const struct servent_mdata compat_mdata = { nss_lt_name, 1 }; #ifdef NS_CACHING static const nss_cache_info cache_info = NS_COMMON_CACHE_INFO_INITIALIZER( services, (void *)nss_lt_name, serv_id_func, serv_marshal_func, serv_unmarshal_func); #endif /* NS_CACHING */ static const ns_dtab dtab[] = { { NSSRC_FILES, files_servent, (void *)&mdata }, { NSSRC_DB, db_servent, (void *)nss_lt_name }, #ifdef YP { NSSRC_NIS, nis_servent, (void *)nss_lt_name }, #endif { NSSRC_COMPAT, files_servent, (void *)&compat_mdata }, #ifdef NS_CACHING NS_CACHE_CB(&cache_info) #endif { NULL, NULL, NULL } }; int rv, ret_errno; ret_errno = 0; *result = NULL; rv = nsdispatch(result, dtab, NSDB_SERVICES, "getservbyname_r", defaultsrc, name, proto, serv, buffer, bufsize, &ret_errno); if (rv == NS_SUCCESS) return (0); else return (ret_errno); } int getservbyport_r(int port, const char *proto, struct servent *serv, char *buffer, size_t bufsize, struct servent **result) { static const struct servent_mdata mdata = { nss_lt_id, 0 }; static const struct servent_mdata compat_mdata = { nss_lt_id, 1 }; #ifdef NS_CACHING static const nss_cache_info cache_info = NS_COMMON_CACHE_INFO_INITIALIZER( services, (void *)nss_lt_id, serv_id_func, serv_marshal_func, serv_unmarshal_func); #endif static const ns_dtab dtab[] = { { NSSRC_FILES, files_servent, (void *)&mdata }, { NSSRC_DB, db_servent, (void *)nss_lt_id }, #ifdef YP { NSSRC_NIS, nis_servent, (void *)nss_lt_id }, #endif { NSSRC_COMPAT, files_servent, (void *)&compat_mdata }, #ifdef NS_CACHING NS_CACHE_CB(&cache_info) #endif { NULL, NULL, NULL } }; int rv, ret_errno; ret_errno = 0; *result = NULL; rv = nsdispatch(result, dtab, NSDB_SERVICES, "getservbyport_r", defaultsrc, port, proto, serv, buffer, bufsize, &ret_errno); if (rv == NS_SUCCESS) return (0); else return (ret_errno); } int getservent_r(struct servent *serv, char *buffer, size_t bufsize, struct servent **result) { static const struct servent_mdata mdata = { nss_lt_all, 0 }; static const struct servent_mdata compat_mdata = { nss_lt_all, 1 }; #ifdef NS_CACHING static const nss_cache_info cache_info = NS_MP_CACHE_INFO_INITIALIZER( services, (void *)nss_lt_all, serv_marshal_func, serv_unmarshal_func); #endif static const ns_dtab dtab[] = { { NSSRC_FILES, files_servent, (void *)&mdata }, { NSSRC_DB, db_servent, (void *)nss_lt_all }, #ifdef YP { NSSRC_NIS, nis_servent, (void *)nss_lt_all }, #endif { NSSRC_COMPAT, files_servent, (void *)&compat_mdata }, #ifdef NS_CACHING NS_CACHE_CB(&cache_info) #endif { NULL, NULL, NULL } }; int rv, ret_errno; ret_errno = 0; *result = NULL; rv = nsdispatch(result, dtab, NSDB_SERVICES, "getservent_r", defaultsrc, serv, buffer, bufsize, &ret_errno); if (rv == NS_SUCCESS) return (0); else return (ret_errno); } void setservent(int stayopen) { #ifdef NS_CACHING static const nss_cache_info cache_info = NS_MP_CACHE_INFO_INITIALIZER( services, (void *)nss_lt_all, NULL, NULL); #endif static const ns_dtab dtab[] = { { NSSRC_FILES, files_setservent, (void *)SETSERVENT }, { NSSRC_DB, db_setservent, (void *)SETSERVENT }, #ifdef YP { NSSRC_NIS, nis_setservent, (void *)SETSERVENT }, #endif { NSSRC_COMPAT, compat_setservent, (void *)SETSERVENT }, #ifdef NS_CACHING NS_CACHE_CB(&cache_info) #endif { NULL, NULL, NULL } }; (void)nsdispatch(NULL, dtab, NSDB_SERVICES, "setservent", defaultsrc, stayopen); } void endservent(void) { #ifdef NS_CACHING static const nss_cache_info cache_info = NS_MP_CACHE_INFO_INITIALIZER( services, (void *)nss_lt_all, NULL, NULL); #endif static const ns_dtab dtab[] = { { NSSRC_FILES, files_setservent, (void *)ENDSERVENT }, { NSSRC_DB, db_setservent, (void *)ENDSERVENT }, #ifdef YP { NSSRC_NIS, nis_setservent, (void *)ENDSERVENT }, #endif { NSSRC_COMPAT, compat_setservent, (void *)ENDSERVENT }, #ifdef NS_CACHING NS_CACHE_CB(&cache_info) #endif { NULL, NULL, NULL } }; (void)nsdispatch(NULL, dtab, NSDB_SERVICES, "endservent", defaultsrc); } /* get** wrappers for get**_r functions implementation */ static void servent_endstate(void *p) { if (p == NULL) return; free(((struct servent_state *)p)->buffer); free(p); } static int wrap_getservbyname_r(struct key key, struct servent *serv, char *buffer, size_t bufsize, struct servent **res) { return (getservbyname_r(key.name, key.proto, serv, buffer, bufsize, res)); } static int wrap_getservbyport_r(struct key key, struct servent *serv, char *buffer, size_t bufsize, struct servent **res) { return (getservbyport_r(key.port, key.proto, serv, buffer, bufsize, res)); } static int wrap_getservent_r(struct key key, struct servent *serv, char *buffer, size_t bufsize, struct servent **res) { return (getservent_r(serv, buffer, bufsize, res)); } static struct servent * getserv(int (*fn)(struct key, struct servent *, char *, size_t, struct servent **), struct key key) { int rv; struct servent *res; struct servent_state * st; rv = servent_getstate(&st); if (rv != 0) { errno = rv; return NULL; } if (st->buffer == NULL) { st->buffer = malloc(SERVENT_STORAGE_INITIAL); if (st->buffer == NULL) return (NULL); st->bufsize = SERVENT_STORAGE_INITIAL; } do { rv = fn(key, &st->serv, st->buffer, st->bufsize, &res); if (res == NULL && rv == ERANGE) { free(st->buffer); if ((st->bufsize << 1) > SERVENT_STORAGE_MAX) { st->buffer = NULL; errno = ERANGE; return (NULL); } st->bufsize <<= 1; st->buffer = malloc(st->bufsize); if (st->buffer == NULL) return (NULL); } } while (res == NULL && rv == ERANGE); if (rv != 0) errno = rv; return (res); } struct servent * getservbyname(const char *name, const char *proto) { struct key key; key.name = name; key.proto = proto; return (getserv(wrap_getservbyname_r, key)); } struct servent * getservbyport(int port, const char *proto) { struct key key; key.port = port; key.proto = proto; return (getserv(wrap_getservbyport_r, key)); } struct servent * getservent(void) { struct key key; key.proto = NULL; key.port = 0; return (getserv(wrap_getservent_r, key)); } Index: head/lib/libc/net/rcmd.c =================================================================== --- head/lib/libc/net/rcmd.c (revision 297789) +++ head/lib/libc/net/rcmd.c (revision 297790) @@ -1,733 +1,733 @@ /* * Copyright (c) 1983, 1993, 1994 * The Regents of the University of California. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 4. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ #if defined(LIBC_SCCS) && !defined(lint) static char sccsid[] = "@(#)rcmd.c 8.3 (Berkeley) 3/26/94"; #endif /* LIBC_SCCS and not lint */ #include __FBSDID("$FreeBSD$"); #include "namespace.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #ifdef YP #include #include #endif #include #include "un-namespace.h" #include "libc_private.h" extern int innetgr( const char *, const char *, const char *, const char * ); #define max(a, b) ((a > b) ? a : b) int __ivaliduser(FILE *, u_int32_t, const char *, const char *); int __ivaliduser_af(FILE *,const void *, const char *, const char *, int, int); int __ivaliduser_sa(FILE *, const struct sockaddr *, socklen_t, const char *, const char *); static int __icheckhost(const struct sockaddr *, socklen_t, const char *); char paddr[NI_MAXHOST]; int rcmd(char **ahost, int rport, const char *locuser, const char *remuser, const char *cmd, int *fd2p) { return rcmd_af(ahost, rport, locuser, remuser, cmd, fd2p, AF_INET); } int rcmd_af(char **ahost, int rport, const char *locuser, const char *remuser, const char *cmd, int *fd2p, int af) { struct addrinfo hints, *res, *ai; struct sockaddr_storage from; fd_set reads; sigset_t oldmask, newmask; pid_t pid; int s, aport, lport, timo, error; char c, *p; int refused, nres; char num[8]; static char canonnamebuf[MAXDNAME]; /* is it proper here? */ /* call rcmdsh() with specified remote shell if appropriate. */ if (!issetugid() && (p = getenv("RSH"))) { struct servent *sp = getservbyname("shell", "tcp"); if (sp && sp->s_port == rport) return (rcmdsh(ahost, rport, locuser, remuser, cmd, p)); } /* use rsh(1) if non-root and remote port is shell. */ if (geteuid()) { struct servent *sp = getservbyname("shell", "tcp"); if (sp && sp->s_port == rport) return (rcmdsh(ahost, rport, locuser, remuser, cmd, NULL)); } pid = getpid(); memset(&hints, 0, sizeof(hints)); hints.ai_flags = AI_CANONNAME; hints.ai_family = af; hints.ai_socktype = SOCK_STREAM; hints.ai_protocol = 0; (void)snprintf(num, sizeof(num), "%d", ntohs(rport)); error = getaddrinfo(*ahost, num, &hints, &res); if (error) { fprintf(stderr, "rcmd: getaddrinfo: %s\n", gai_strerror(error)); if (error == EAI_SYSTEM) fprintf(stderr, "rcmd: getaddrinfo: %s\n", strerror(errno)); return (-1); } if (res->ai_canonname && strlen(res->ai_canonname) + 1 < sizeof(canonnamebuf)) { strncpy(canonnamebuf, res->ai_canonname, sizeof(canonnamebuf)); *ahost = canonnamebuf; } nres = 0; for (ai = res; ai; ai = ai->ai_next) nres++; ai = res; refused = 0; sigemptyset(&newmask); sigaddset(&newmask, SIGURG); __libc_sigprocmask(SIG_BLOCK, (const sigset_t *)&newmask, &oldmask); for (timo = 1, lport = IPPORT_RESERVED - 1;;) { s = rresvport_af(&lport, ai->ai_family); if (s < 0) { if (errno != EAGAIN && ai->ai_next) { ai = ai->ai_next; continue; } if (errno == EAGAIN) (void)fprintf(stderr, "rcmd: socket: All ports in use\n"); else (void)fprintf(stderr, "rcmd: socket: %s\n", strerror(errno)); freeaddrinfo(res); __libc_sigprocmask(SIG_SETMASK, (const sigset_t *)&oldmask, NULL); return (-1); } _fcntl(s, F_SETOWN, pid); if (_connect(s, ai->ai_addr, ai->ai_addrlen) >= 0) break; (void)_close(s); if (errno == EADDRINUSE) { lport--; continue; } if (errno == ECONNREFUSED) refused = 1; if (ai->ai_next == NULL && (!refused || timo > 16)) { (void)fprintf(stderr, "%s: %s\n", *ahost, strerror(errno)); freeaddrinfo(res); __libc_sigprocmask(SIG_SETMASK, (const sigset_t *)&oldmask, NULL); return (-1); } if (nres > 1) { int oerrno = errno; getnameinfo(ai->ai_addr, ai->ai_addrlen, paddr, sizeof(paddr), NULL, 0, NI_NUMERICHOST); (void)fprintf(stderr, "connect to address %s: ", paddr); errno = oerrno; perror(0); } if ((ai = ai->ai_next) == NULL) { /* refused && timo <= 16 */ struct timespec time_to_sleep, time_remaining; time_to_sleep.tv_sec = timo; time_to_sleep.tv_nsec = 0; (void)_nanosleep(&time_to_sleep, &time_remaining); timo *= 2; ai = res; refused = 0; } if (nres > 1) { getnameinfo(ai->ai_addr, ai->ai_addrlen, paddr, sizeof(paddr), NULL, 0, NI_NUMERICHOST); fprintf(stderr, "Trying %s...\n", paddr); } } lport--; - if (fd2p == 0) { + if (fd2p == NULL) { _write(s, "", 1); lport = 0; } else { int s2 = rresvport_af(&lport, ai->ai_family), s3; socklen_t len = ai->ai_addrlen; int nfds; if (s2 < 0) goto bad; _listen(s2, 1); (void)snprintf(num, sizeof(num), "%d", lport); if (_write(s, num, strlen(num)+1) != strlen(num)+1) { (void)fprintf(stderr, "rcmd: write (setting up stderr): %s\n", strerror(errno)); (void)_close(s2); goto bad; } nfds = max(s, s2)+1; if(nfds > FD_SETSIZE) { fprintf(stderr, "rcmd: too many files\n"); (void)_close(s2); goto bad; } again: FD_ZERO(&reads); FD_SET(s, &reads); FD_SET(s2, &reads); errno = 0; if (_select(nfds, &reads, 0, 0, 0) < 1 || !FD_ISSET(s2, &reads)){ if (errno != 0) (void)fprintf(stderr, "rcmd: select (setting up stderr): %s\n", strerror(errno)); else (void)fprintf(stderr, "select: protocol failure in circuit setup\n"); (void)_close(s2); goto bad; } s3 = _accept(s2, (struct sockaddr *)&from, &len); switch (from.ss_family) { case AF_INET: aport = ntohs(((struct sockaddr_in *)&from)->sin_port); break; #ifdef INET6 case AF_INET6: aport = ntohs(((struct sockaddr_in6 *)&from)->sin6_port); break; #endif default: aport = 0; /* error */ break; } /* * XXX careful for ftp bounce attacks. If discovered, shut them * down and check for the real auxiliary channel to connect. */ if (aport == 20) { _close(s3); goto again; } (void)_close(s2); if (s3 < 0) { (void)fprintf(stderr, "rcmd: accept: %s\n", strerror(errno)); lport = 0; goto bad; } *fd2p = s3; if (aport >= IPPORT_RESERVED || aport < IPPORT_RESERVED / 2) { (void)fprintf(stderr, "socket: protocol failure in circuit setup.\n"); goto bad2; } } (void)_write(s, locuser, strlen(locuser)+1); (void)_write(s, remuser, strlen(remuser)+1); (void)_write(s, cmd, strlen(cmd)+1); if (_read(s, &c, 1) != 1) { (void)fprintf(stderr, "rcmd: %s: %s\n", *ahost, strerror(errno)); goto bad2; } if (c != 0) { while (_read(s, &c, 1) == 1) { (void)_write(STDERR_FILENO, &c, 1); if (c == '\n') break; } goto bad2; } __libc_sigprocmask(SIG_SETMASK, (const sigset_t *)&oldmask, NULL); freeaddrinfo(res); return (s); bad2: if (lport) (void)_close(*fd2p); bad: (void)_close(s); __libc_sigprocmask(SIG_SETMASK, (const sigset_t *)&oldmask, NULL); freeaddrinfo(res); return (-1); } int rresvport(int *port) { return rresvport_af(port, AF_INET); } int rresvport_af(int *alport, int family) { int s; struct sockaddr_storage ss; u_short *sport; memset(&ss, 0, sizeof(ss)); ss.ss_family = family; switch (family) { case AF_INET: ((struct sockaddr *)&ss)->sa_len = sizeof(struct sockaddr_in); sport = &((struct sockaddr_in *)&ss)->sin_port; ((struct sockaddr_in *)&ss)->sin_addr.s_addr = INADDR_ANY; break; #ifdef INET6 case AF_INET6: ((struct sockaddr *)&ss)->sa_len = sizeof(struct sockaddr_in6); sport = &((struct sockaddr_in6 *)&ss)->sin6_port; ((struct sockaddr_in6 *)&ss)->sin6_addr = in6addr_any; break; #endif default: errno = EAFNOSUPPORT; return -1; } s = _socket(ss.ss_family, SOCK_STREAM, 0); if (s < 0) return (-1); #if 0 /* compat_exact_traditional_rresvport_semantics */ sin.sin_port = htons((u_short)*alport); if (_bind(s, (struct sockaddr *)&sin, sizeof(sin)) >= 0) return (s); if (errno != EADDRINUSE) { (void)_close(s); return (-1); } #endif *sport = 0; if (bindresvport_sa(s, (struct sockaddr *)&ss) == -1) { (void)_close(s); return (-1); } *alport = (int)ntohs(*sport); return (s); } int __check_rhosts_file = 1; char *__rcmd_errstr; int ruserok(const char *rhost, int superuser, const char *ruser, const char *luser) { struct addrinfo hints, *res, *r; int error; memset(&hints, 0, sizeof(hints)); hints.ai_family = PF_UNSPEC; hints.ai_socktype = SOCK_DGRAM; /*dummy*/ error = getaddrinfo(rhost, "0", &hints, &res); if (error) return (-1); for (r = res; r; r = r->ai_next) { if (iruserok_sa(r->ai_addr, r->ai_addrlen, superuser, ruser, luser) == 0) { freeaddrinfo(res); return (0); } } freeaddrinfo(res); return (-1); } /* * New .rhosts strategy: We are passed an ip address. We spin through * hosts.equiv and .rhosts looking for a match. When the .rhosts only * has ip addresses, we don't have to trust a nameserver. When it * contains hostnames, we spin through the list of addresses the nameserver * gives us and look for a match. * * Returns 0 if ok, -1 if not ok. */ int iruserok(unsigned long raddr, int superuser, const char *ruser, const char *luser) { struct sockaddr_in sin; memset(&sin, 0, sizeof(sin)); sin.sin_family = AF_INET; sin.sin_len = sizeof(struct sockaddr_in); memcpy(&sin.sin_addr, &raddr, sizeof(sin.sin_addr)); return iruserok_sa((struct sockaddr *)&sin, sin.sin_len, superuser, ruser, luser); } /* * AF independent extension of iruserok. * * Returns 0 if ok, -1 if not ok. */ int iruserok_sa(const void *ra, int rlen, int superuser, const char *ruser, const char *luser) { char *cp; struct stat sbuf; struct passwd *pwd; FILE *hostf; uid_t uid; int first; char pbuf[MAXPATHLEN]; const struct sockaddr *raddr; struct sockaddr_storage ss; /* avoid alignment issue */ if (rlen > sizeof(ss)) return(-1); memcpy(&ss, ra, rlen); raddr = (struct sockaddr *)&ss; first = 1; hostf = superuser ? NULL : fopen(_PATH_HEQUIV, "re"); again: if (hostf) { if (__ivaliduser_sa(hostf, raddr, rlen, luser, ruser) == 0) { (void)fclose(hostf); return (0); } (void)fclose(hostf); } if (first == 1 && (__check_rhosts_file || superuser)) { first = 0; if ((pwd = getpwnam(luser)) == NULL) return (-1); (void)strcpy(pbuf, pwd->pw_dir); (void)strcat(pbuf, "/.rhosts"); /* * Change effective uid while opening .rhosts. If root and * reading an NFS mounted file system, can't read files that * are protected read/write owner only. */ uid = geteuid(); (void)seteuid(pwd->pw_uid); hostf = fopen(pbuf, "re"); (void)seteuid(uid); if (hostf == NULL) return (-1); /* * If not a regular file, or is owned by someone other than * user or root or if writeable by anyone but the owner, quit. */ cp = NULL; if (lstat(pbuf, &sbuf) < 0) cp = ".rhosts lstat failed"; else if (!S_ISREG(sbuf.st_mode)) cp = ".rhosts not regular file"; else if (_fstat(fileno(hostf), &sbuf) < 0) cp = ".rhosts fstat failed"; else if (sbuf.st_uid && sbuf.st_uid != pwd->pw_uid) cp = "bad .rhosts owner"; else if (sbuf.st_mode & (S_IWGRP|S_IWOTH)) cp = ".rhosts writeable by other than owner"; /* If there were any problems, quit. */ if (cp) { __rcmd_errstr = cp; (void)fclose(hostf); return (-1); } goto again; } return (-1); } /* * XXX * Don't make static, used by lpd(8). * * Returns 0 if ok, -1 if not ok. */ int __ivaliduser(FILE *hostf, u_int32_t raddr, const char *luser, const char *ruser) { struct sockaddr_in sin; memset(&sin, 0, sizeof(sin)); sin.sin_family = AF_INET; sin.sin_len = sizeof(struct sockaddr_in); memcpy(&sin.sin_addr, &raddr, sizeof(sin.sin_addr)); return __ivaliduser_sa(hostf, (struct sockaddr *)&sin, sin.sin_len, luser, ruser); } /* * Returns 0 if ok, -1 if not ok. * * XXX obsolete API. */ int __ivaliduser_af(FILE *hostf, const void *raddr, const char *luser, const char *ruser, int af, int len) { struct sockaddr *sa = NULL; struct sockaddr_in *sin = NULL; #ifdef INET6 struct sockaddr_in6 *sin6 = NULL; #endif struct sockaddr_storage ss; memset(&ss, 0, sizeof(ss)); switch (af) { case AF_INET: if (len != sizeof(sin->sin_addr)) return -1; sin = (struct sockaddr_in *)&ss; sin->sin_family = AF_INET; sin->sin_len = sizeof(struct sockaddr_in); memcpy(&sin->sin_addr, raddr, sizeof(sin->sin_addr)); break; #ifdef INET6 case AF_INET6: if (len != sizeof(sin6->sin6_addr)) return -1; /* you will lose scope info */ sin6 = (struct sockaddr_in6 *)&ss; sin6->sin6_family = AF_INET6; sin6->sin6_len = sizeof(struct sockaddr_in6); memcpy(&sin6->sin6_addr, raddr, sizeof(sin6->sin6_addr)); break; #endif default: return -1; } sa = (struct sockaddr *)&ss; return __ivaliduser_sa(hostf, sa, sa->sa_len, luser, ruser); } int __ivaliduser_sa(FILE *hostf, const struct sockaddr *raddr, socklen_t salen, const char *luser, const char *ruser) { char *user, *p; int ch; char buf[MAXHOSTNAMELEN + 128]; /* host + login */ char hname[MAXHOSTNAMELEN]; /* Presumed guilty until proven innocent. */ int userok = 0, hostok = 0; #ifdef YP char *ypdomain; if (yp_get_default_domain(&ypdomain)) ypdomain = NULL; #else #define ypdomain NULL #endif /* We need to get the damn hostname back for netgroup matching. */ if (getnameinfo(raddr, salen, hname, sizeof(hname), NULL, 0, NI_NAMEREQD) != 0) hname[0] = '\0'; while (fgets(buf, sizeof(buf), hostf)) { p = buf; /* Skip lines that are too long. */ if (strchr(p, '\n') == NULL) { while ((ch = getc(hostf)) != '\n' && ch != EOF); continue; } if (*p == '\n' || *p == '#') { /* comment... */ continue; } while (*p != '\n' && *p != ' ' && *p != '\t' && *p != '\0') { *p = isupper((unsigned char)*p) ? tolower((unsigned char)*p) : *p; p++; } if (*p == ' ' || *p == '\t') { *p++ = '\0'; while (*p == ' ' || *p == '\t') p++; user = p; while (*p != '\n' && *p != ' ' && *p != '\t' && *p != '\0') p++; } else user = p; *p = '\0'; /* * Do +/- and +@/-@ checking. This looks really nasty, * but it matches SunOS's behavior so far as I can tell. */ switch(buf[0]) { case '+': if (!buf[1]) { /* '+' matches all hosts */ hostok = 1; break; } if (buf[1] == '@') /* match a host by netgroup */ hostok = hname[0] != '\0' && innetgr(&buf[2], hname, NULL, ypdomain); else /* match a host by addr */ hostok = __icheckhost(raddr, salen, (char *)&buf[1]); break; case '-': /* reject '-' hosts and all their users */ if (buf[1] == '@') { if (hname[0] == '\0' || innetgr(&buf[2], hname, NULL, ypdomain)) return(-1); } else { if (__icheckhost(raddr, salen, (char *)&buf[1])) return(-1); } break; default: /* if no '+' or '-', do a simple match */ hostok = __icheckhost(raddr, salen, buf); break; } switch(*user) { case '+': if (!*(user+1)) { /* '+' matches all users */ userok = 1; break; } if (*(user+1) == '@') /* match a user by netgroup */ userok = innetgr(user+2, NULL, ruser, ypdomain); else /* match a user by direct specification */ userok = !(strcmp(ruser, user+1)); break; case '-': /* if we matched a hostname, */ if (hostok) { /* check for user field rejections */ if (!*(user+1)) return(-1); if (*(user+1) == '@') { if (innetgr(user+2, NULL, ruser, ypdomain)) return(-1); } else { if (!strcmp(ruser, user+1)) return(-1); } } break; default: /* no rejections: try to match the user */ if (hostok) userok = !(strcmp(ruser,*user ? user : luser)); break; } if (hostok && userok) return(0); } return (-1); } /* * Returns "true" if match, 0 if no match. */ static int __icheckhost(const struct sockaddr *raddr, socklen_t salen, const char *lhost) { struct sockaddr_in sin; struct sockaddr_in6 *sin6; struct addrinfo hints, *res, *r; int error; char h1[NI_MAXHOST], h2[NI_MAXHOST]; if (raddr->sa_family == AF_INET6) { sin6 = (struct sockaddr_in6 *)raddr; if (IN6_IS_ADDR_V4MAPPED(&sin6->sin6_addr)) { memset(&sin, 0, sizeof(sin)); sin.sin_family = AF_INET; sin.sin_len = sizeof(struct sockaddr_in); memcpy(&sin.sin_addr, &sin6->sin6_addr.s6_addr[12], sizeof(sin.sin_addr)); raddr = (struct sockaddr *)&sin; salen = sin.sin_len; } } h1[0] = '\0'; if (getnameinfo(raddr, salen, h1, sizeof(h1), NULL, 0, NI_NUMERICHOST) != 0) return (0); /* Resolve laddr into sockaddr */ memset(&hints, 0, sizeof(hints)); hints.ai_family = raddr->sa_family; hints.ai_socktype = SOCK_DGRAM; /*XXX dummy*/ res = NULL; error = getaddrinfo(lhost, "0", &hints, &res); if (error) return (0); for (r = res; r ; r = r->ai_next) { h2[0] = '\0'; if (getnameinfo(r->ai_addr, r->ai_addrlen, h2, sizeof(h2), NULL, 0, NI_NUMERICHOST) != 0) continue; if (strcmp(h1, h2) == 0) { freeaddrinfo(res); return (1); } } /* No match. */ freeaddrinfo(res); return (0); } Index: head/lib/libc/posix1e/acl_support_nfs4.c =================================================================== --- head/lib/libc/posix1e/acl_support_nfs4.c (revision 297789) +++ head/lib/libc/posix1e/acl_support_nfs4.c (revision 297790) @@ -1,261 +1,261 @@ /*- * Copyright (c) 2008, 2009 Edward Tomasz Napierała * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ #include __FBSDID("$FreeBSD$"); #include #include #include #include #include #include #include "acl_support.h" struct flagnames_struct { uint32_t flag; const char *name; char letter; }; struct flagnames_struct a_flags[] = {{ ACL_ENTRY_FILE_INHERIT, "file_inherit", 'f'}, { ACL_ENTRY_DIRECTORY_INHERIT, "dir_inherit", 'd'}, { ACL_ENTRY_INHERIT_ONLY, "inherit_only", 'i'}, { ACL_ENTRY_NO_PROPAGATE_INHERIT, "no_propagate", 'n'}, { ACL_ENTRY_SUCCESSFUL_ACCESS, "successfull_access", 'S'}, { ACL_ENTRY_FAILED_ACCESS, "failed_access", 'F'}, { ACL_ENTRY_INHERITED, "inherited", 'I' }, /* * There is no ACE_IDENTIFIER_GROUP here - SunOS does not show it * in the "flags" field. There is no ACE_OWNER, ACE_GROUP or * ACE_EVERYONE either, for obvious reasons. */ { 0, 0, 0}}; struct flagnames_struct a_access_masks[] = {{ ACL_READ_DATA, "read_data", 'r'}, { ACL_WRITE_DATA, "write_data", 'w'}, { ACL_EXECUTE, "execute", 'x'}, { ACL_APPEND_DATA, "append_data", 'p'}, { ACL_DELETE_CHILD, "delete_child", 'D'}, { ACL_DELETE, "delete", 'd'}, { ACL_READ_ATTRIBUTES, "read_attributes", 'a'}, { ACL_WRITE_ATTRIBUTES, "write_attributes", 'A'}, { ACL_READ_NAMED_ATTRS, "read_xattr", 'R'}, { ACL_WRITE_NAMED_ATTRS, "write_xattr", 'W'}, { ACL_READ_ACL, "read_acl", 'c'}, { ACL_WRITE_ACL, "write_acl", 'C'}, { ACL_WRITE_OWNER, "write_owner", 'o'}, { ACL_SYNCHRONIZE, "synchronize", 's'}, { ACL_FULL_SET, "full_set", '\0'}, { ACL_MODIFY_SET, "modify_set", '\0'}, { ACL_READ_SET, "read_set", '\0'}, { ACL_WRITE_SET, "write_set", '\0'}, { 0, 0, 0}}; static const char * format_flag(uint32_t *var, const struct flagnames_struct *flags) { - for (; flags->name != 0; flags++) { + for (; flags->name != NULL; flags++) { if ((flags->flag & *var) == 0) continue; *var &= ~flags->flag; return (flags->name); } return (NULL); } static int format_flags_verbose(char *str, size_t size, uint32_t var, const struct flagnames_struct *flags) { size_t off = 0; const char *tmp; while ((tmp = format_flag(&var, flags)) != NULL) { off += snprintf(str + off, size - off, "%s/", tmp); assert (off < size); } /* If there were any flags added... */ if (off > 0) { off--; /* ... then remove the last slash. */ assert(str[off] == '/'); } str[off] = '\0'; return (0); } static int format_flags_compact(char *str, size_t size, uint32_t var, const struct flagnames_struct *flags) { size_t i; for (i = 0; flags[i].letter != '\0'; i++) { assert(i < size); if ((flags[i].flag & var) == 0) str[i] = '-'; else str[i] = flags[i].letter; } str[i] = '\0'; return (0); } static int parse_flags_verbose(const char *strp, uint32_t *var, const struct flagnames_struct *flags, const char *flags_name, int *try_compact) { int i, found, ever_found = 0; char *str, *flag; str = strdup(strp); *try_compact = 0; *var = 0; while (str != NULL) { flag = strsep(&str, "/:"); found = 0; for (i = 0; flags[i].name != NULL; i++) { if (strcmp(flags[i].name, flag) == 0) { *var |= flags[i].flag; found = 1; ever_found = 1; } } if (!found) { if (ever_found) warnx("malformed ACL: \"%s\" field contains " "invalid flag \"%s\"", flags_name, flag); else *try_compact = 1; free(str); return (-1); } } free(str); return (0); } static int parse_flags_compact(const char *str, uint32_t *var, const struct flagnames_struct *flags, const char *flags_name) { int i, j, found; *var = 0; for (i = 0;; i++) { if (str[i] == '\0') return (0); /* Ignore minus signs. */ if (str[i] == '-') continue; found = 0; for (j = 0; flags[j].name != NULL; j++) { if (flags[j].letter == str[i]) { *var |= flags[j].flag; found = 1; break; } } if (!found) { warnx("malformed ACL: \"%s\" field contains " "invalid flag \"%c\"", flags_name, str[i]); return (-1); } } } int _nfs4_format_flags(char *str, size_t size, acl_flag_t var, int verbose) { if (verbose) return (format_flags_verbose(str, size, var, a_flags)); return (format_flags_compact(str, size, var, a_flags)); } int _nfs4_format_access_mask(char *str, size_t size, acl_perm_t var, int verbose) { if (verbose) return (format_flags_verbose(str, size, var, a_access_masks)); return (format_flags_compact(str, size, var, a_access_masks)); } int _nfs4_parse_flags(const char *str, acl_flag_t *flags) { int error, try_compact; int tmpflags; error = parse_flags_verbose(str, &tmpflags, a_flags, "flags", &try_compact); if (error && try_compact) error = parse_flags_compact(str, &tmpflags, a_flags, "flags"); *flags = tmpflags; return (error); } int _nfs4_parse_access_mask(const char *str, acl_perm_t *perms) { int error, try_compact; int tmpperms; error = parse_flags_verbose(str, &tmpperms, a_access_masks, "access permissions", &try_compact); if (error && try_compact) error = parse_flags_compact(str, &tmpperms, a_access_masks, "access permissions"); *perms = tmpperms; return (error); } Index: head/lib/libc/resolv/mtctxres.c =================================================================== --- head/lib/libc/resolv/mtctxres.c (revision 297789) +++ head/lib/libc/resolv/mtctxres.c (revision 297790) @@ -1,141 +1,138 @@ #include __FBSDID("$FreeBSD$"); #include #ifdef DO_PTHREADS #include #ifdef _LIBC #include #endif #endif #include #include #include #include #include #include #ifdef DO_PTHREADS static pthread_key_t key; static int mt_key_initialized = 0; static int __res_init_ctx(void); static void __res_destroy_ctx(void *); #if defined(sun) && !defined(__GNUC__) #pragma init (_mtctxres_init) #endif #endif static mtctxres_t sharedctx; #ifdef DO_PTHREADS /* * Initialize the TSD key. By doing this at library load time, we're * implicitly running without interference from other threads, so there's * no need for locking. */ static void _mtctxres_init(void) { int pthread_keycreate_ret; pthread_keycreate_ret = pthread_key_create(&key, __res_destroy_ctx); if (pthread_keycreate_ret == 0) mt_key_initialized = 1; } #endif #ifndef _LIBC /* * To support binaries that used the private MT-safe interface in * Solaris 8, we still need to provide the __res_enable_mt() * and __res_disable_mt() entry points. They're do-nothing routines. */ int __res_enable_mt(void) { return (-1); } int __res_disable_mt(void) { return (0); } #endif #ifdef DO_PTHREADS static int __res_init_ctx(void) { mtctxres_t *mt; int ret; if (pthread_getspecific(key) != 0) { /* Already exists */ return (0); } - if ((mt = malloc(sizeof (mtctxres_t))) == 0) { + if ((mt = malloc(sizeof(mtctxres_t))) == NULL) { errno = ENOMEM; return (-1); } memset(mt, 0, sizeof (mtctxres_t)); if ((ret = pthread_setspecific(key, mt)) != 0) { free(mt); errno = ret; return (-1); } return (0); } static void __res_destroy_ctx(void *value) { - mtctxres_t *mt = (mtctxres_t *)value; - - if (mt != 0) - free(mt); + free(value); } #endif mtctxres_t * ___mtctxres(void) { #ifdef DO_PTHREADS mtctxres_t *mt; #ifdef _LIBC if (pthread_main_np() != 0) return (&sharedctx); #endif /* * This if clause should only be executed if we are linking * statically. When linked dynamically _mtctxres_init() should * be called at binding time due the #pragma above. */ if (!mt_key_initialized) { static pthread_mutex_t keylock = PTHREAD_MUTEX_INITIALIZER; if (pthread_mutex_lock(&keylock) == 0) { _mtctxres_init(); (void) pthread_mutex_unlock(&keylock); } } /* * If we have already been called in this thread return the existing * context. Otherwise recreat a new context and return it. If * that fails return a global context. */ if (mt_key_initialized) { - if (((mt = pthread_getspecific(key)) != 0) || + if (((mt = pthread_getspecific(key)) != NULL) || (__res_init_ctx() == 0 && - (mt = pthread_getspecific(key)) != 0)) { + (mt = pthread_getspecific(key)) != NULL)) { return (mt); } } #endif return (&sharedctx); } Index: head/lib/libc/resolv/res_init.c =================================================================== --- head/lib/libc/resolv/res_init.c (revision 297789) +++ head/lib/libc/resolv/res_init.c (revision 297790) @@ -1,948 +1,948 @@ /* * Copyright (c) 1985, 1989, 1993 * The Regents of the University of California. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 4. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ /* * Portions Copyright (c) 1993 by Digital Equipment Corporation. * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies, and that * the name of Digital Equipment Corporation not be used in advertising or * publicity pertaining to distribution of the document or software without * specific, written prior permission. * * THE SOFTWARE IS PROVIDED "AS IS" AND DIGITAL EQUIPMENT CORP. DISCLAIMS ALL * WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL DIGITAL EQUIPMENT * CORPORATION BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS * SOFTWARE. */ /* * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC") * Portions Copyright (c) 1996-1999 by Internet Software Consortium. * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ #if defined(LIBC_SCCS) && !defined(lint) static const char sccsid[] = "@(#)res_init.c 8.1 (Berkeley) 6/7/93"; static const char rcsid[] = "$Id: res_init.c,v 1.26 2008/12/11 09:59:00 marka Exp $"; #endif /* LIBC_SCCS and not lint */ #include __FBSDID("$FreeBSD$"); #include "port_before.h" #include "namespace.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #ifndef HAVE_MD5 # include "../dst/md5.h" #else # ifdef SOLARIS2 # include # elif _LIBC # include # endif #endif #ifndef _MD5_H_ # define _MD5_H_ 1 /*%< make sure we do not include rsaref md5.h file */ #endif #include "un-namespace.h" #include "port_after.h" /* ensure that sockaddr_in6 and IN6ADDR_ANY_INIT are declared / defined */ #include #include "res_private.h" /*% Options. Should all be left alone. */ #define RESOLVSORT #ifndef DEBUG #define DEBUG #endif #ifdef SOLARIS2 #include #endif static void res_setoptions(res_state, const char *, const char *); #ifdef RESOLVSORT static const char sort_mask[] = "/&"; #define ISSORTMASK(ch) (strchr(sort_mask, ch) != NULL) static u_int32_t net_mask(struct in_addr); #endif #if !defined(isascii) /*%< XXX - could be a function */ # define isascii(c) (!(c & 0200)) #endif /* * Resolver state default settings. */ /*% * Set up default settings. If the configuration file exist, the values * there will have precedence. Otherwise, the server address is set to * INADDR_ANY and the default domain name comes from the gethostname(). * * An interrim version of this code (BIND 4.9, pre-4.4BSD) used 127.0.0.1 * rather than INADDR_ANY ("0.0.0.0") as the default name server address * since it was noted that INADDR_ANY actually meant ``the first interface * you "ifconfig"'d at boot time'' and if this was a SLIP or PPP interface, * it had to be "up" in order for you to reach your own name server. It * was later decided that since the recommended practice is to always * install local static routes through 127.0.0.1 for all your network * interfaces, that we could solve this problem without a code change. * * The configuration file should always be used, since it is the only way * to specify a default domain. If you are running a server on your local * machine, you should say "nameserver 0.0.0.0" or "nameserver 127.0.0.1" * in the configuration file. * * Return 0 if completes successfully, -1 on error */ int res_ninit(res_state statp) { extern int __res_vinit(res_state, int); return (__res_vinit(statp, 0)); } /*% This function has to be reachable by res_data.c but not publically. */ int __res_vinit(res_state statp, int preinit) { FILE *fp; char *cp, **pp; int n; char buf[BUFSIZ]; int nserv = 0; /*%< number of nameserver records read from file */ int haveenv = 0; int havesearch = 0; #ifdef RESOLVSORT int nsort = 0; char *net; #endif int dots; union res_sockaddr_union u[2]; int maxns = MAXNS; RES_SET_H_ERRNO(statp, 0); if (statp->_u._ext.ext != NULL) res_ndestroy(statp); if (!preinit) { statp->retrans = RES_TIMEOUT; statp->retry = RES_DFLRETRY; statp->options = RES_DEFAULT; } statp->_rnd = malloc(16); res_rndinit(statp); statp->id = res_nrandomid(statp); memset(u, 0, sizeof(u)); #ifdef USELOOPBACK u[nserv].sin.sin_addr = inet_makeaddr(IN_LOOPBACKNET, 1); #else u[nserv].sin.sin_addr.s_addr = INADDR_ANY; #endif u[nserv].sin.sin_family = AF_INET; u[nserv].sin.sin_port = htons(NAMESERVER_PORT); #ifdef HAVE_SA_LEN u[nserv].sin.sin_len = sizeof(struct sockaddr_in); #endif nserv++; #ifdef HAS_INET6_STRUCTS #ifdef USELOOPBACK u[nserv].sin6.sin6_addr = in6addr_loopback; #else u[nserv].sin6.sin6_addr = in6addr_any; #endif u[nserv].sin6.sin6_family = AF_INET6; u[nserv].sin6.sin6_port = htons(NAMESERVER_PORT); #ifdef HAVE_SA_LEN u[nserv].sin6.sin6_len = sizeof(struct sockaddr_in6); #endif nserv++; #endif statp->nscount = 0; statp->ndots = 1; statp->pfcode = 0; statp->_vcsock = -1; statp->_flags = 0; statp->qhook = NULL; statp->rhook = NULL; statp->_u._ext.nscount = 0; statp->_u._ext.ext = malloc(sizeof(*statp->_u._ext.ext)); if (statp->_u._ext.ext != NULL) { memset(statp->_u._ext.ext, 0, sizeof(*statp->_u._ext.ext)); statp->_u._ext.ext->nsaddrs[0].sin = statp->nsaddr; strcpy(statp->_u._ext.ext->nsuffix, "ip6.arpa"); strcpy(statp->_u._ext.ext->nsuffix2, "ip6.int"); statp->_u._ext.ext->reload_period = 2; } else { /* * Historically res_init() rarely, if at all, failed. * Examples and applications exist which do not check * our return code. Furthermore several applications * simply call us to get the systems domainname. So * rather then immediately fail here we store the * failure, which is returned later, in h_errno. And * prevent the collection of 'nameserver' information * by setting maxns to 0. Thus applications that fail * to check our return code wont be able to make * queries anyhow. */ RES_SET_H_ERRNO(statp, NETDB_INTERNAL); maxns = 0; } #ifdef RESOLVSORT statp->nsort = 0; #endif res_setservers(statp, u, nserv); #ifdef SOLARIS2 /* * The old libresolv derived the defaultdomain from NIS/NIS+. * We want to keep this behaviour */ { char buf[sizeof(statp->defdname)], *cp; int ret; if ((ret = sysinfo(SI_SRPC_DOMAIN, buf, sizeof(buf))) > 0 && (unsigned int)ret <= sizeof(buf)) { if (buf[0] == '+') buf[0] = '.'; cp = strchr(buf, '.'); cp = (cp == NULL) ? buf : (cp + 1); strncpy(statp->defdname, cp, sizeof(statp->defdname) - 1); statp->defdname[sizeof(statp->defdname) - 1] = '\0'; } } #endif /* SOLARIS2 */ /* Allow user to override the local domain definition */ if (issetugid() == 0 && (cp = getenv("LOCALDOMAIN")) != NULL) { (void)strncpy(statp->defdname, cp, sizeof(statp->defdname) - 1); statp->defdname[sizeof(statp->defdname) - 1] = '\0'; haveenv++; /* * Set search list to be blank-separated strings * from rest of env value. Permits users of LOCALDOMAIN * to still have a search list, and anyone to set the * one that they want to use as an individual (even more * important now that the rfc1535 stuff restricts searches) */ cp = statp->defdname; pp = statp->dnsrch; *pp++ = cp; for (n = 0; *cp && pp < statp->dnsrch + MAXDNSRCH; cp++) { if (*cp == '\n') /*%< silly backwards compat */ break; else if (*cp == ' ' || *cp == '\t') { *cp = 0; n = 1; } else if (n) { *pp++ = cp; n = 0; havesearch = 1; } } /* null terminate last domain if there are excess */ while (*cp != '\0' && *cp != ' ' && *cp != '\t' && *cp != '\n') cp++; *cp = '\0'; - *pp++ = 0; + *pp++ = NULL; } #define MATCH(line, name) \ (!strncmp(line, name, sizeof(name) - 1) && \ (line[sizeof(name) - 1] == ' ' || \ line[sizeof(name) - 1] == '\t')) nserv = 0; if ((fp = fopen(_PATH_RESCONF, "re")) != NULL) { struct stat sb; struct timespec now; if (statp->_u._ext.ext != NULL) { if (_fstat(fileno(fp), &sb) == 0) { statp->_u._ext.ext->conf_mtim = sb.st_mtim; if (clock_gettime(CLOCK_MONOTONIC_FAST, &now) == 0) { statp->_u._ext.ext->conf_stat = now.tv_sec; } } } /* read the config file */ while (fgets(buf, sizeof(buf), fp) != NULL) { /* skip comments */ if (*buf == ';' || *buf == '#') continue; /* read default domain name */ if (MATCH(buf, "domain")) { if (haveenv) /*%< skip if have from environ */ continue; cp = buf + sizeof("domain") - 1; while (*cp == ' ' || *cp == '\t') cp++; if ((*cp == '\0') || (*cp == '\n')) continue; strncpy(statp->defdname, cp, sizeof(statp->defdname) - 1); statp->defdname[sizeof(statp->defdname) - 1] = '\0'; if ((cp = strpbrk(statp->defdname, " \t\n")) != NULL) *cp = '\0'; havesearch = 0; continue; } /* set search list */ if (MATCH(buf, "search")) { if (haveenv) /*%< skip if have from environ */ continue; cp = buf + sizeof("search") - 1; while (*cp == ' ' || *cp == '\t') cp++; if ((*cp == '\0') || (*cp == '\n')) continue; strncpy(statp->defdname, cp, sizeof(statp->defdname) - 1); statp->defdname[sizeof(statp->defdname) - 1] = '\0'; if ((cp = strchr(statp->defdname, '\n')) != NULL) *cp = '\0'; /* * Set search list to be blank-separated strings * on rest of line. */ cp = statp->defdname; pp = statp->dnsrch; *pp++ = cp; for (n = 0; *cp && pp < statp->dnsrch + MAXDNSRCH; cp++) { if (*cp == ' ' || *cp == '\t') { *cp = 0; n = 1; } else if (n) { *pp++ = cp; n = 0; } } /* null terminate last domain if there are excess */ while (*cp != '\0' && *cp != ' ' && *cp != '\t') cp++; *cp = '\0'; - *pp++ = 0; + *pp++ = NULL; havesearch = 1; continue; } /* read nameservers to query */ if (MATCH(buf, "nameserver") && nserv < maxns) { struct addrinfo hints, *ai; char sbuf[NI_MAXSERV]; const size_t minsiz = sizeof(statp->_u._ext.ext->nsaddrs[0]); cp = buf + sizeof("nameserver") - 1; while (*cp == ' ' || *cp == '\t') cp++; cp[strcspn(cp, ";# \t\n")] = '\0'; if ((*cp != '\0') && (*cp != '\n')) { memset(&hints, 0, sizeof(hints)); hints.ai_family = PF_UNSPEC; hints.ai_socktype = SOCK_DGRAM; /*dummy*/ hints.ai_flags = AI_NUMERICHOST; sprintf(sbuf, "%u", NAMESERVER_PORT); if (getaddrinfo(cp, sbuf, &hints, &ai) == 0 && ai->ai_addrlen <= minsiz) { if (statp->_u._ext.ext != NULL) { memcpy(&statp->_u._ext.ext->nsaddrs[nserv], ai->ai_addr, ai->ai_addrlen); } if (ai->ai_addrlen <= sizeof(statp->nsaddr_list[nserv])) { memcpy(&statp->nsaddr_list[nserv], ai->ai_addr, ai->ai_addrlen); } else statp->nsaddr_list[nserv].sin_family = 0; freeaddrinfo(ai); nserv++; } } continue; } #ifdef RESOLVSORT if (MATCH(buf, "sortlist")) { struct in_addr a; struct in6_addr a6; int m, i; u_char *u; struct __res_state_ext *ext = statp->_u._ext.ext; cp = buf + sizeof("sortlist") - 1; while (nsort < MAXRESOLVSORT) { while (*cp == ' ' || *cp == '\t') cp++; if (*cp == '\0' || *cp == '\n' || *cp == ';') break; net = cp; while (*cp && !ISSORTMASK(*cp) && *cp != ';' && isascii(*cp) && !isspace((unsigned char)*cp)) cp++; n = *cp; *cp = 0; if (inet_aton(net, &a)) { statp->sort_list[nsort].addr = a; if (ISSORTMASK(n)) { *cp++ = n; net = cp; while (*cp && *cp != ';' && isascii(*cp) && !isspace((unsigned char)*cp)) cp++; n = *cp; *cp = 0; if (inet_aton(net, &a)) { statp->sort_list[nsort].mask = a.s_addr; } else { statp->sort_list[nsort].mask = net_mask(statp->sort_list[nsort].addr); } } else { statp->sort_list[nsort].mask = net_mask(statp->sort_list[nsort].addr); } ext->sort_list[nsort].af = AF_INET; ext->sort_list[nsort].addr.ina = statp->sort_list[nsort].addr; ext->sort_list[nsort].mask.ina.s_addr = statp->sort_list[nsort].mask; nsort++; } else if (inet_pton(AF_INET6, net, &a6) == 1) { ext->sort_list[nsort].af = AF_INET6; ext->sort_list[nsort].addr.in6a = a6; u = (u_char *)&ext->sort_list[nsort].mask.in6a; *cp++ = n; net = cp; while (*cp && *cp != ';' && isascii(*cp) && !isspace(*cp)) cp++; m = n; n = *cp; *cp = 0; switch (m) { case '/': m = atoi(net); break; case '&': if (inet_pton(AF_INET6, net, u) == 1) { m = -1; break; } /*FALLTHROUGH*/ default: m = sizeof(struct in6_addr) * CHAR_BIT; break; } if (m >= 0) { for (i = 0; i < sizeof(struct in6_addr); i++) { if (m <= 0) { *u = 0; } else { m -= CHAR_BIT; *u = (u_char)~0; if (m < 0) *u <<= -m; } u++; } } statp->sort_list[nsort].addr.s_addr = (u_int32_t)0xffffffff; statp->sort_list[nsort].mask = (u_int32_t)0xffffffff; nsort++; } *cp = n; } continue; } #endif if (MATCH(buf, "options")) { res_setoptions(statp, buf + sizeof("options") - 1, "conf"); continue; } } if (nserv > 0) statp->nscount = nserv; #ifdef RESOLVSORT statp->nsort = nsort; #endif (void) fclose(fp); } /* * Last chance to get a nameserver. This should not normally * be necessary */ #ifdef NO_RESOLV_CONF if(nserv == 0) nserv = get_nameservers(statp); #endif if (statp->defdname[0] == 0 && gethostname(buf, sizeof(statp->defdname) - 1) == 0 && (cp = strchr(buf, '.')) != NULL) strcpy(statp->defdname, cp + 1); /* find components of local domain that might be searched */ if (havesearch == 0) { pp = statp->dnsrch; *pp++ = statp->defdname; *pp = NULL; dots = 0; for (cp = statp->defdname; *cp; cp++) dots += (*cp == '.'); cp = statp->defdname; while (pp < statp->dnsrch + MAXDFLSRCH) { if (dots < LOCALDOMAINPARTS) break; cp = strchr(cp, '.') + 1; /*%< we know there is one */ *pp++ = cp; dots--; } *pp = NULL; #ifdef DEBUG if (statp->options & RES_DEBUG) { printf(";; res_init()... default dnsrch list:\n"); for (pp = statp->dnsrch; *pp; pp++) printf(";;\t%s\n", *pp); printf(";;\t..END..\n"); } #endif } if (issetugid()) statp->options |= RES_NOALIASES; else if ((cp = getenv("RES_OPTIONS")) != NULL) res_setoptions(statp, cp, "env"); statp->options |= RES_INIT; return (statp->res_h_errno); } static void res_setoptions(res_state statp, const char *options, const char *source) { const char *cp = options; int i; struct __res_state_ext *ext = statp->_u._ext.ext; #ifdef DEBUG if (statp->options & RES_DEBUG) printf(";; res_setoptions(\"%s\", \"%s\")...\n", options, source); #endif while (*cp) { /* skip leading and inner runs of spaces */ while (*cp == ' ' || *cp == '\t') cp++; /* search for and process individual options */ if (!strncmp(cp, "ndots:", sizeof("ndots:") - 1)) { i = atoi(cp + sizeof("ndots:") - 1); if (i <= RES_MAXNDOTS) statp->ndots = i; else statp->ndots = RES_MAXNDOTS; #ifdef DEBUG if (statp->options & RES_DEBUG) printf(";;\tndots=%d\n", statp->ndots); #endif } else if (!strncmp(cp, "timeout:", sizeof("timeout:") - 1)) { i = atoi(cp + sizeof("timeout:") - 1); if (i <= RES_MAXRETRANS) statp->retrans = i; else statp->retrans = RES_MAXRETRANS; #ifdef DEBUG if (statp->options & RES_DEBUG) printf(";;\ttimeout=%d\n", statp->retrans); #endif #ifdef SOLARIS2 } else if (!strncmp(cp, "retrans:", sizeof("retrans:") - 1)) { /* * For backward compatibility, 'retrans' is * supported as an alias for 'timeout', though * without an imposed maximum. */ statp->retrans = atoi(cp + sizeof("retrans:") - 1); } else if (!strncmp(cp, "retry:", sizeof("retry:") - 1)){ /* * For backward compatibility, 'retry' is * supported as an alias for 'attempts', though * without an imposed maximum. */ statp->retry = atoi(cp + sizeof("retry:") - 1); #endif /* SOLARIS2 */ } else if (!strncmp(cp, "attempts:", sizeof("attempts:") - 1)){ i = atoi(cp + sizeof("attempts:") - 1); if (i <= RES_MAXRETRY) statp->retry = i; else statp->retry = RES_MAXRETRY; #ifdef DEBUG if (statp->options & RES_DEBUG) printf(";;\tattempts=%d\n", statp->retry); #endif } else if (!strncmp(cp, "debug", sizeof("debug") - 1)) { #ifdef DEBUG if (!(statp->options & RES_DEBUG)) { printf(";; res_setoptions(\"%s\", \"%s\")..\n", options, source); statp->options |= RES_DEBUG; } printf(";;\tdebug\n"); #endif } else if (!strncmp(cp, "no_tld_query", sizeof("no_tld_query") - 1) || !strncmp(cp, "no-tld-query", sizeof("no-tld-query") - 1)) { statp->options |= RES_NOTLDQUERY; } else if (!strncmp(cp, "inet6", sizeof("inet6") - 1)) { statp->options |= RES_USE_INET6; } else if (!strncmp(cp, "insecure1", sizeof("insecure1") - 1)) { statp->options |= RES_INSECURE1; } else if (!strncmp(cp, "insecure2", sizeof("insecure2") - 1)) { statp->options |= RES_INSECURE2; } else if (!strncmp(cp, "rotate", sizeof("rotate") - 1)) { statp->options |= RES_ROTATE; } else if (!strncmp(cp, "no-check-names", sizeof("no-check-names") - 1)) { statp->options |= RES_NOCHECKNAME; } else if (!strncmp(cp, "reload-period:", sizeof("reload-period:") - 1)) { if (ext != NULL) { ext->reload_period = (u_short) atoi(cp + sizeof("reload-period:") - 1); } } #ifdef RES_USE_EDNS0 else if (!strncmp(cp, "edns0", sizeof("edns0") - 1)) { statp->options |= RES_USE_EDNS0; } #endif #ifndef _LIBC else if (!strncmp(cp, "dname", sizeof("dname") - 1)) { statp->options |= RES_USE_DNAME; } else if (!strncmp(cp, "nibble:", sizeof("nibble:") - 1)) { if (ext == NULL) goto skip; cp += sizeof("nibble:") - 1; i = MIN(strcspn(cp, " \t"), sizeof(ext->nsuffix) - 1); strncpy(ext->nsuffix, cp, i); ext->nsuffix[i] = '\0'; } else if (!strncmp(cp, "nibble2:", sizeof("nibble2:") - 1)) { if (ext == NULL) goto skip; cp += sizeof("nibble2:") - 1; i = MIN(strcspn(cp, " \t"), sizeof(ext->nsuffix2) - 1); strncpy(ext->nsuffix2, cp, i); ext->nsuffix2[i] = '\0'; } else if (!strncmp(cp, "v6revmode:", sizeof("v6revmode:") - 1)) { cp += sizeof("v6revmode:") - 1; /* "nibble" and "bitstring" used to be valid */ if (!strncmp(cp, "single", sizeof("single") - 1)) { statp->options |= RES_NO_NIBBLE2; } else if (!strncmp(cp, "both", sizeof("both") - 1)) { statp->options &= ~RES_NO_NIBBLE2; } } #endif else { /* XXX - print a warning here? */ } #ifndef _LIBC skip: #endif /* skip to next run of spaces */ while (*cp && *cp != ' ' && *cp != '\t') cp++; } } #ifdef RESOLVSORT /* XXX - should really support CIDR which means explicit masks always. */ static u_int32_t net_mask(struct in_addr in) /*!< XXX - should really use system's version of this */ { u_int32_t i = ntohl(in.s_addr); if (IN_CLASSA(i)) return (htonl(IN_CLASSA_NET)); else if (IN_CLASSB(i)) return (htonl(IN_CLASSB_NET)); return (htonl(IN_CLASSC_NET)); } #endif static u_char srnd[16]; void res_rndinit(res_state statp) { struct timeval now; u_int32_t u32; u_int16_t u16; u_char *rnd = statp->_rnd == NULL ? srnd : statp->_rnd; gettimeofday(&now, NULL); u32 = now.tv_sec; memcpy(rnd, &u32, 4); u32 = now.tv_usec; memcpy(rnd + 4, &u32, 4); u32 += now.tv_sec; memcpy(rnd + 8, &u32, 4); u16 = getpid(); memcpy(rnd + 12, &u16, 2); } u_int res_nrandomid(res_state statp) { struct timeval now; u_int16_t u16; MD5_CTX ctx; u_char *rnd = statp->_rnd == NULL ? srnd : statp->_rnd; gettimeofday(&now, NULL); u16 = (u_int16_t) (now.tv_sec ^ now.tv_usec); memcpy(rnd + 14, &u16, 2); #ifndef HAVE_MD5 MD5_Init(&ctx); MD5_Update(&ctx, rnd, 16); MD5_Final(rnd, &ctx); #else MD5Init(&ctx); MD5Update(&ctx, rnd, 16); MD5Final(rnd, &ctx); #endif memcpy(&u16, rnd + 14, 2); return ((u_int) u16); } /*% * This routine is for closing the socket if a virtual circuit is used and * the program wants to close it. This provides support for endhostent() * which expects to close the socket. * * This routine is not expected to be user visible. */ void res_nclose(res_state statp) { int ns; if (statp->_vcsock >= 0) { (void) _close(statp->_vcsock); statp->_vcsock = -1; statp->_flags &= ~(RES_F_VC | RES_F_CONN); } for (ns = 0; ns < statp->_u._ext.nscount; ns++) { if (statp->_u._ext.nssocks[ns] != -1) { (void) _close(statp->_u._ext.nssocks[ns]); statp->_u._ext.nssocks[ns] = -1; } } } void res_ndestroy(res_state statp) { res_nclose(statp); if (statp->_u._ext.ext != NULL) { free(statp->_u._ext.ext); statp->_u._ext.ext = NULL; } if (statp->_rnd != NULL) { free(statp->_rnd); statp->_rnd = NULL; } statp->options &= ~RES_INIT; } #ifndef _LIBC const char * res_get_nibblesuffix(res_state statp) { if (statp->_u._ext.ext) return (statp->_u._ext.ext->nsuffix); return ("ip6.arpa"); } const char * res_get_nibblesuffix2(res_state statp) { if (statp->_u._ext.ext) return (statp->_u._ext.ext->nsuffix2); return ("ip6.int"); } #endif void res_setservers(res_state statp, const union res_sockaddr_union *set, int cnt) { int i, nserv; size_t size; /* close open servers */ res_nclose(statp); /* cause rtt times to be forgotten */ statp->_u._ext.nscount = 0; nserv = 0; for (i = 0; i < cnt && nserv < MAXNS; i++) { switch (set->sin.sin_family) { case AF_INET: size = sizeof(set->sin); if (statp->_u._ext.ext) memcpy(&statp->_u._ext.ext->nsaddrs[nserv], &set->sin, size); if (size <= sizeof(statp->nsaddr_list[nserv])) memcpy(&statp->nsaddr_list[nserv], &set->sin, size); else statp->nsaddr_list[nserv].sin_family = 0; nserv++; break; #ifdef HAS_INET6_STRUCTS case AF_INET6: size = sizeof(set->sin6); if (statp->_u._ext.ext) memcpy(&statp->_u._ext.ext->nsaddrs[nserv], &set->sin6, size); if (size <= sizeof(statp->nsaddr_list[nserv])) memcpy(&statp->nsaddr_list[nserv], &set->sin6, size); else statp->nsaddr_list[nserv].sin_family = 0; nserv++; break; #endif default: break; } set++; } statp->nscount = nserv; } int res_getservers(res_state statp, union res_sockaddr_union *set, int cnt) { int i; size_t size; u_int16_t family; for (i = 0; i < statp->nscount && i < cnt; i++) { if (statp->_u._ext.ext) family = statp->_u._ext.ext->nsaddrs[i].sin.sin_family; else family = statp->nsaddr_list[i].sin_family; switch (family) { case AF_INET: size = sizeof(set->sin); if (statp->_u._ext.ext) memcpy(&set->sin, &statp->_u._ext.ext->nsaddrs[i], size); else memcpy(&set->sin, &statp->nsaddr_list[i], size); break; #ifdef HAS_INET6_STRUCTS case AF_INET6: size = sizeof(set->sin6); if (statp->_u._ext.ext) memcpy(&set->sin6, &statp->_u._ext.ext->nsaddrs[i], size); else memcpy(&set->sin6, &statp->nsaddr_list[i], size); break; #endif default: set->sin.sin_family = 0; break; } set++; } return (statp->nscount); } /*! \file */ Index: head/lib/libc/resolv/res_mkupdate.c =================================================================== --- head/lib/libc/resolv/res_mkupdate.c (revision 297789) +++ head/lib/libc/resolv/res_mkupdate.c (revision 297790) @@ -1,1199 +1,1199 @@ /* * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC") * Copyright (c) 1996-1999 by Internet Software Consortium. * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ /*! \file * \brief * Based on the Dynamic DNS reference implementation by Viraj Bais * <viraj_bais@ccm.fm.intel.com> */ #if !defined(lint) && !defined(SABER) static const char rcsid[] = "$Id: res_mkupdate.c,v 1.10 2008/12/11 09:59:00 marka Exp $"; #endif /* not lint */ #include __FBSDID("$FreeBSD$"); #include "port_before.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #ifdef _LIBC #include #endif #include "port_after.h" /* Options. Leave them on. */ #ifndef DEBUG #define DEBUG #endif #define MAXPORT 1024 static int getnum_str(u_char **, u_char *); static int gethexnum_str(u_char **, u_char *); static int getword_str(char *, int, u_char **, u_char *); static int getstr_str(char *, int, u_char **, u_char *); #define ShrinkBuffer(x) if ((buflen -= x) < 0) return (-2); /* Forward. */ #ifdef _LIBC static #endif int res_protocolnumber(const char *); #ifdef _LIBC static #endif int res_servicenumber(const char *); /*% * Form update packets. * Returns the size of the resulting packet if no error * * On error, * returns *\li -1 if error in reading a word/number in rdata * portion for update packets *\li -2 if length of buffer passed is insufficient *\li -3 if zone section is not the first section in * the linked list, or section order has a problem *\li -4 on a number overflow *\li -5 unknown operation or no records */ int res_nmkupdate(res_state statp, ns_updrec *rrecp_in, u_char *buf, int buflen) { ns_updrec *rrecp_start = rrecp_in; HEADER *hp; u_char *cp, *sp2, *startp, *endp; int n, i, soanum, multiline; ns_updrec *rrecp; struct in_addr ina; struct in6_addr in6a; char buf2[MAXDNAME]; u_char buf3[MAXDNAME]; int section, numrrs = 0, counts[ns_s_max]; u_int16_t rtype, rclass; u_int32_t n1, rttl; u_char *dnptrs[20], **dpp, **lastdnptr; #ifndef _LIBC int siglen; #endif int keylen, certlen; /* * Initialize header fields. */ if ((buf == NULL) || (buflen < HFIXEDSZ)) return (-1); memset(buf, 0, HFIXEDSZ); hp = (HEADER *) buf; statp->id = res_nrandomid(statp); hp->id = htons(statp->id); hp->opcode = ns_o_update; hp->rcode = NOERROR; cp = buf + HFIXEDSZ; buflen -= HFIXEDSZ; dpp = dnptrs; *dpp++ = buf; *dpp++ = NULL; lastdnptr = dnptrs + sizeof dnptrs / sizeof dnptrs[0]; if (rrecp_start == NULL) return (-5); else if (rrecp_start->r_section != S_ZONE) return (-3); memset(counts, 0, sizeof counts); for (rrecp = rrecp_start; rrecp; rrecp = NEXT(rrecp, r_glink)) { numrrs++; section = rrecp->r_section; if (section < 0 || section >= ns_s_max) return (-1); counts[section]++; for (i = section + 1; i < ns_s_max; i++) if (counts[i]) return (-3); rtype = rrecp->r_type; rclass = rrecp->r_class; rttl = rrecp->r_ttl; /* overload class and type */ if (section == S_PREREQ) { rttl = 0; switch (rrecp->r_opcode) { case YXDOMAIN: rclass = C_ANY; rtype = T_ANY; rrecp->r_size = 0; break; case NXDOMAIN: rclass = C_NONE; rtype = T_ANY; rrecp->r_size = 0; break; case NXRRSET: rclass = C_NONE; rrecp->r_size = 0; break; case YXRRSET: if (rrecp->r_size == 0) rclass = C_ANY; break; default: fprintf(stderr, "res_mkupdate: incorrect opcode: %d\n", rrecp->r_opcode); fflush(stderr); return (-1); } } else if (section == S_UPDATE) { switch (rrecp->r_opcode) { case DELETE: rclass = rrecp->r_size == 0 ? C_ANY : C_NONE; break; case ADD: break; default: fprintf(stderr, "res_mkupdate: incorrect opcode: %d\n", rrecp->r_opcode); fflush(stderr); return (-1); } } /* * XXX appending default domain to owner name is omitted, * fqdn must be provided */ if ((n = dn_comp(rrecp->r_dname, cp, buflen, dnptrs, lastdnptr)) < 0) return (-1); cp += n; ShrinkBuffer(n + 2*INT16SZ); PUTSHORT(rtype, cp); PUTSHORT(rclass, cp); if (section == S_ZONE) { if (numrrs != 1 || rrecp->r_type != T_SOA) return (-3); continue; } ShrinkBuffer(INT32SZ + INT16SZ); PUTLONG(rttl, cp); sp2 = cp; /*%< save pointer to length byte */ cp += INT16SZ; if (rrecp->r_size == 0) { if (section == S_UPDATE && rclass != C_ANY) return (-1); else { PUTSHORT(0, sp2); continue; } } startp = rrecp->r_data; endp = startp + rrecp->r_size - 1; /* XXX this should be done centrally. */ switch (rrecp->r_type) { case T_A: if (!getword_str(buf2, sizeof buf2, &startp, endp)) return (-1); if (!inet_aton(buf2, &ina)) return (-1); n1 = ntohl(ina.s_addr); ShrinkBuffer(INT32SZ); PUTLONG(n1, cp); break; case T_CNAME: case T_MB: case T_MG: case T_MR: case T_NS: case T_PTR: case ns_t_dname: if (!getword_str(buf2, sizeof buf2, &startp, endp)) return (-1); n = dn_comp(buf2, cp, buflen, dnptrs, lastdnptr); if (n < 0) return (-1); cp += n; ShrinkBuffer(n); break; case T_MINFO: case T_SOA: case T_RP: for (i = 0; i < 2; i++) { if (!getword_str(buf2, sizeof buf2, &startp, endp)) return (-1); n = dn_comp(buf2, cp, buflen, dnptrs, lastdnptr); if (n < 0) return (-1); cp += n; ShrinkBuffer(n); } if (rrecp->r_type == T_SOA) { ShrinkBuffer(5 * INT32SZ); while (isspace(*startp) || !*startp) startp++; if (*startp == '(') { multiline = 1; startp++; } else multiline = 0; /* serial, refresh, retry, expire, minimum */ for (i = 0; i < 5; i++) { soanum = getnum_str(&startp, endp); if (soanum < 0) return (-1); PUTLONG(soanum, cp); } if (multiline) { while (isspace(*startp) || !*startp) startp++; if (*startp != ')') return (-1); } } break; case T_MX: case T_AFSDB: case T_RT: n = getnum_str(&startp, endp); if (n < 0) return (-1); ShrinkBuffer(INT16SZ); PUTSHORT(n, cp); if (!getword_str(buf2, sizeof buf2, &startp, endp)) return (-1); n = dn_comp(buf2, cp, buflen, dnptrs, lastdnptr); if (n < 0) return (-1); cp += n; ShrinkBuffer(n); break; case T_SRV: n = getnum_str(&startp, endp); if (n < 0) return (-1); ShrinkBuffer(INT16SZ); PUTSHORT(n, cp); n = getnum_str(&startp, endp); if (n < 0) return (-1); ShrinkBuffer(INT16SZ); PUTSHORT(n, cp); n = getnum_str(&startp, endp); if (n < 0) return (-1); ShrinkBuffer(INT16SZ); PUTSHORT(n, cp); if (!getword_str(buf2, sizeof buf2, &startp, endp)) return (-1); n = dn_comp(buf2, cp, buflen, NULL, NULL); if (n < 0) return (-1); cp += n; ShrinkBuffer(n); break; case T_PX: n = getnum_str(&startp, endp); if (n < 0) return (-1); PUTSHORT(n, cp); ShrinkBuffer(INT16SZ); for (i = 0; i < 2; i++) { if (!getword_str(buf2, sizeof buf2, &startp, endp)) return (-1); n = dn_comp(buf2, cp, buflen, dnptrs, lastdnptr); if (n < 0) return (-1); cp += n; ShrinkBuffer(n); } break; case T_WKS: { char bm[MAXPORT/8]; unsigned int maxbm = 0; if (!getword_str(buf2, sizeof buf2, &startp, endp)) return (-1); if (!inet_aton(buf2, &ina)) return (-1); n1 = ntohl(ina.s_addr); ShrinkBuffer(INT32SZ); PUTLONG(n1, cp); if (!getword_str(buf2, sizeof buf2, &startp, endp)) return (-1); if ((i = res_protocolnumber(buf2)) < 0) return (-1); ShrinkBuffer(1); *cp++ = i & 0xff; for (i = 0; i < MAXPORT/8 ; i++) bm[i] = 0; while (getword_str(buf2, sizeof buf2, &startp, endp)) { if ((n = res_servicenumber(buf2)) <= 0) return (-1); if (n < MAXPORT) { bm[n/8] |= (0x80>>(n%8)); if ((unsigned)n > maxbm) maxbm = n; } else return (-1); } maxbm = maxbm/8 + 1; ShrinkBuffer(maxbm); memcpy(cp, bm, maxbm); cp += maxbm; break; } case T_HINFO: for (i = 0; i < 2; i++) { if ((n = getstr_str(buf2, sizeof buf2, &startp, endp)) < 0) return (-1); if (n > 255) return (-1); ShrinkBuffer(n+1); *cp++ = n; memcpy(cp, buf2, n); cp += n; } break; case T_TXT: for (;;) { if ((n = getstr_str(buf2, sizeof buf2, &startp, endp)) < 0) { if (cp != (sp2 + INT16SZ)) break; return (-1); } if (n > 255) return (-1); ShrinkBuffer(n+1); *cp++ = n; memcpy(cp, buf2, n); cp += n; } break; case T_X25: /* RFC1183 */ if ((n = getstr_str(buf2, sizeof buf2, &startp, endp)) < 0) return (-1); if (n > 255) return (-1); ShrinkBuffer(n+1); *cp++ = n; memcpy(cp, buf2, n); cp += n; break; case T_ISDN: /* RFC1183 */ if ((n = getstr_str(buf2, sizeof buf2, &startp, endp)) < 0) return (-1); if ((n > 255) || (n == 0)) return (-1); ShrinkBuffer(n+1); *cp++ = n; memcpy(cp, buf2, n); cp += n; if ((n = getstr_str(buf2, sizeof buf2, &startp, endp)) < 0) n = 0; if (n > 255) return (-1); ShrinkBuffer(n+1); *cp++ = n; memcpy(cp, buf2, n); cp += n; break; case T_NSAP: if ((n = inet_nsap_addr((char *)startp, (u_char *)buf2, sizeof(buf2))) != 0) { ShrinkBuffer(n); memcpy(cp, buf2, n); cp += n; } else { return (-1); } break; case T_LOC: if ((n = loc_aton((char *)startp, (u_char *)buf2)) != 0) { ShrinkBuffer(n); memcpy(cp, buf2, n); cp += n; } else return (-1); break; case ns_t_sig: #ifdef _LIBC return (-1); #else { int sig_type, success, dateerror; u_int32_t exptime, timesigned; /* type */ if ((n = getword_str(buf2, sizeof buf2, &startp, endp)) < 0) return (-1); sig_type = sym_ston(__p_type_syms, buf2, &success); if (!success || sig_type == ns_t_any) return (-1); ShrinkBuffer(INT16SZ); PUTSHORT(sig_type, cp); /* alg */ n = getnum_str(&startp, endp); if (n < 0) return (-1); ShrinkBuffer(1); *cp++ = n; /* labels */ n = getnum_str(&startp, endp); if (n <= 0 || n > 255) return (-1); ShrinkBuffer(1); *cp++ = n; /* ottl & expire */ if (!getword_str(buf2, sizeof buf2, &startp, endp)) return (-1); exptime = ns_datetosecs(buf2, &dateerror); if (!dateerror) { ShrinkBuffer(INT32SZ); PUTLONG(rttl, cp); } else { char *ulendp; u_int32_t ottl; errno = 0; ottl = strtoul(buf2, &ulendp, 10); if (errno != 0 || (ulendp != NULL && *ulendp != '\0')) return (-1); ShrinkBuffer(INT32SZ); PUTLONG(ottl, cp); if (!getword_str(buf2, sizeof buf2, &startp, endp)) return (-1); exptime = ns_datetosecs(buf2, &dateerror); if (dateerror) return (-1); } /* expire */ ShrinkBuffer(INT32SZ); PUTLONG(exptime, cp); /* timesigned */ if (!getword_str(buf2, sizeof buf2, &startp, endp)) return (-1); timesigned = ns_datetosecs(buf2, &dateerror); if (!dateerror) { ShrinkBuffer(INT32SZ); PUTLONG(timesigned, cp); } else return (-1); /* footprint */ n = getnum_str(&startp, endp); if (n < 0) return (-1); ShrinkBuffer(INT16SZ); PUTSHORT(n, cp); /* signer name */ if (!getword_str(buf2, sizeof buf2, &startp, endp)) return (-1); n = dn_comp(buf2, cp, buflen, dnptrs, lastdnptr); if (n < 0) return (-1); cp += n; ShrinkBuffer(n); /* sig */ if ((n = getword_str(buf2, sizeof buf2, &startp, endp)) < 0) return (-1); siglen = b64_pton(buf2, buf3, sizeof(buf3)); if (siglen < 0) return (-1); ShrinkBuffer(siglen); memcpy(cp, buf3, siglen); cp += siglen; break; } #endif case ns_t_key: /* flags */ n = gethexnum_str(&startp, endp); if (n < 0) return (-1); ShrinkBuffer(INT16SZ); PUTSHORT(n, cp); /* proto */ n = getnum_str(&startp, endp); if (n < 0) return (-1); ShrinkBuffer(1); *cp++ = n; /* alg */ n = getnum_str(&startp, endp); if (n < 0) return (-1); ShrinkBuffer(1); *cp++ = n; /* key */ if ((n = getword_str(buf2, sizeof buf2, &startp, endp)) < 0) return (-1); keylen = b64_pton(buf2, buf3, sizeof(buf3)); if (keylen < 0) return (-1); ShrinkBuffer(keylen); memcpy(cp, buf3, keylen); cp += keylen; break; case ns_t_nxt: { int success, nxt_type; u_char data[32]; int maxtype; /* next name */ if (!getword_str(buf2, sizeof buf2, &startp, endp)) return (-1); n = dn_comp(buf2, cp, buflen, NULL, NULL); if (n < 0) return (-1); cp += n; ShrinkBuffer(n); maxtype = 0; memset(data, 0, sizeof data); for (;;) { if (!getword_str(buf2, sizeof buf2, &startp, endp)) break; nxt_type = sym_ston(__p_type_syms, buf2, &success); if (!success || !ns_t_rr_p(nxt_type)) return (-1); NS_NXT_BIT_SET(nxt_type, data); if (nxt_type > maxtype) maxtype = nxt_type; } n = maxtype/NS_NXT_BITS+1; ShrinkBuffer(n); memcpy(cp, data, n); cp += n; break; } case ns_t_cert: /* type */ n = getnum_str(&startp, endp); if (n < 0) return (-1); ShrinkBuffer(INT16SZ); PUTSHORT(n, cp); /* key tag */ n = getnum_str(&startp, endp); if (n < 0) return (-1); ShrinkBuffer(INT16SZ); PUTSHORT(n, cp); /* alg */ n = getnum_str(&startp, endp); if (n < 0) return (-1); ShrinkBuffer(1); *cp++ = n; /* cert */ if ((n = getword_str(buf2, sizeof buf2, &startp, endp)) < 0) return (-1); certlen = b64_pton(buf2, buf3, sizeof(buf3)); if (certlen < 0) return (-1); ShrinkBuffer(certlen); memcpy(cp, buf3, certlen); cp += certlen; break; case ns_t_aaaa: if (!getword_str(buf2, sizeof buf2, &startp, endp)) return (-1); if (inet_pton(AF_INET6, buf2, &in6a) <= 0) return (-1); ShrinkBuffer(NS_IN6ADDRSZ); memcpy(cp, &in6a, NS_IN6ADDRSZ); cp += NS_IN6ADDRSZ; break; case ns_t_naptr: /* Order Preference Flags Service Replacement Regexp */ /* Order */ n = getnum_str(&startp, endp); if (n < 0 || n > 65535) return (-1); ShrinkBuffer(INT16SZ); PUTSHORT(n, cp); /* Preference */ n = getnum_str(&startp, endp); if (n < 0 || n > 65535) return (-1); ShrinkBuffer(INT16SZ); PUTSHORT(n, cp); /* Flags */ if ((n = getstr_str(buf2, sizeof buf2, &startp, endp)) < 0) { return (-1); } if (n > 255) return (-1); ShrinkBuffer(n+1); *cp++ = n; memcpy(cp, buf2, n); cp += n; /* Service Classes */ if ((n = getstr_str(buf2, sizeof buf2, &startp, endp)) < 0) { return (-1); } if (n > 255) return (-1); ShrinkBuffer(n+1); *cp++ = n; memcpy(cp, buf2, n); cp += n; /* Pattern */ if ((n = getstr_str(buf2, sizeof buf2, &startp, endp)) < 0) { return (-1); } if (n > 255) return (-1); ShrinkBuffer(n+1); *cp++ = n; memcpy(cp, buf2, n); cp += n; /* Replacement */ if (!getword_str(buf2, sizeof buf2, &startp, endp)) return (-1); n = dn_comp(buf2, cp, buflen, NULL, NULL); if (n < 0) return (-1); cp += n; ShrinkBuffer(n); break; default: return (-1); } /*switch*/ n = (u_int16_t)((cp - sp2) - INT16SZ); PUTSHORT(n, sp2); } /*for*/ hp->qdcount = htons(counts[0]); hp->ancount = htons(counts[1]); hp->nscount = htons(counts[2]); hp->arcount = htons(counts[3]); return (cp - buf); } /*% * Get a whitespace delimited word from a string (not file) * into buf. modify the start pointer to point after the * word in the string. */ static int getword_str(char *buf, int size, u_char **startpp, u_char *endp) { char *cp; int c; for (cp = buf; *startpp <= endp; ) { c = **startpp; if (isspace(c) || c == '\0') { if (cp != buf) /*%< trailing whitespace */ break; else { /*%< leading whitespace */ (*startpp)++; continue; } } (*startpp)++; if (cp >= buf+size-1) break; *cp++ = (u_char)c; } *cp = '\0'; return (cp != buf); } /*% * get a white spae delimited string from memory. Process quoted strings * and \\DDD escapes. Return length or -1 on error. Returned string may * contain nulls. */ static char digits[] = "0123456789"; static int getstr_str(char *buf, int size, u_char **startpp, u_char *endp) { char *cp; int c, c1 = 0; int inquote = 0; int seen_quote = 0; int escape = 0; int dig = 0; for (cp = buf; *startpp <= endp; ) { if ((c = **startpp) == '\0') break; /* leading white space */ if ((cp == buf) && !seen_quote && isspace(c)) { (*startpp)++; continue; } switch (c) { case '\\': if (!escape) { escape = 1; dig = 0; c1 = 0; (*startpp)++; continue; } goto do_escape; case '"': if (!escape) { inquote = !inquote; seen_quote = 1; (*startpp)++; continue; } /* fall through */ default: do_escape: if (escape) { switch (c) { case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': c1 = c1 * 10 + (strchr(digits, c) - digits); if (++dig == 3) { c = c1 &0xff; break; } (*startpp)++; continue; } escape = 0; } else if (!inquote && isspace(c)) goto done; if (cp >= buf+size-1) goto done; *cp++ = (u_char)c; (*startpp)++; } } done: *cp = '\0'; return ((cp == buf)? (seen_quote? 0: -1): (cp - buf)); } /*% * Get a whitespace delimited base 16 number from a string (not file) into buf * update the start pointer to point after the number in the string. */ static int gethexnum_str(u_char **startpp, u_char *endp) { int c, n; int seendigit = 0; int m = 0; if (*startpp + 2 >= endp || strncasecmp((char *)*startpp, "0x", 2) != 0) return getnum_str(startpp, endp); (*startpp)+=2; for (n = 0; *startpp <= endp; ) { c = **startpp; if (isspace(c) || c == '\0') { if (seendigit) /*%< trailing whitespace */ break; else { /*%< leading whitespace */ (*startpp)++; continue; } } if (c == ';') { while ((*startpp <= endp) && ((c = **startpp) != '\n')) (*startpp)++; if (seendigit) break; continue; } if (!isxdigit(c)) { if (c == ')' && seendigit) { (*startpp)--; break; } return (-1); } (*startpp)++; if (isdigit(c)) n = n * 16 + (c - '0'); else n = n * 16 + (tolower(c) - 'a' + 10); seendigit = 1; } return (n + m); } /*% * Get a whitespace delimited base 10 number from a string (not file) into buf * update the start pointer to point after the number in the string. */ static int getnum_str(u_char **startpp, u_char *endp) { int c, n; int seendigit = 0; int m = 0; for (n = 0; *startpp <= endp; ) { c = **startpp; if (isspace(c) || c == '\0') { if (seendigit) /*%< trailing whitespace */ break; else { /*%< leading whitespace */ (*startpp)++; continue; } } if (c == ';') { while ((*startpp <= endp) && ((c = **startpp) != '\n')) (*startpp)++; if (seendigit) break; continue; } if (!isdigit(c)) { if (c == ')' && seendigit) { (*startpp)--; break; } return (-1); } (*startpp)++; n = n * 10 + (c - '0'); seendigit = 1; } return (n + m); } /*% * Allocate a resource record buffer & save rr info. */ ns_updrec * res_mkupdrec(int section, const char *dname, u_int class, u_int type, u_long ttl) { ns_updrec *rrecp = (ns_updrec *)calloc(1, sizeof(ns_updrec)); if (!rrecp || !(rrecp->r_dname = strdup(dname))) { if (rrecp) free((char *)rrecp); return (NULL); } INIT_LINK(rrecp, r_link); INIT_LINK(rrecp, r_glink); rrecp->r_class = (ns_class)class; rrecp->r_type = (ns_type)type; rrecp->r_ttl = ttl; rrecp->r_section = (ns_sect)section; return (rrecp); } /*% * Free a resource record buffer created by res_mkupdrec. */ void res_freeupdrec(ns_updrec *rrecp) { /* Note: freeing r_dp is the caller's responsibility. */ if (rrecp->r_dname != NULL) free(rrecp->r_dname); free(rrecp); } struct valuelist { struct valuelist * next; struct valuelist * prev; char * name; char * proto; int port; }; static struct valuelist *servicelist, *protolist; static void res_buildservicelist(void) { struct servent *sp; struct valuelist *slp; #ifdef MAYBE_HESIOD setservent(0); #else setservent(1); #endif while ((sp = getservent()) != NULL) { slp = (struct valuelist *)malloc(sizeof(struct valuelist)); if (!slp) break; slp->name = strdup(sp->s_name); slp->proto = strdup(sp->s_proto); if ((slp->name == NULL) || (slp->proto == NULL)) { if (slp->name) free(slp->name); if (slp->proto) free(slp->proto); free(slp); break; } slp->port = ntohs((u_int16_t)sp->s_port); /*%< host byt order */ slp->next = servicelist; slp->prev = NULL; if (servicelist) servicelist->prev = slp; servicelist = slp; } endservent(); } #ifndef _LIBC void res_destroyservicelist() { struct valuelist *slp, *slp_next; for (slp = servicelist; slp != NULL; slp = slp_next) { slp_next = slp->next; free(slp->name); free(slp->proto); free(slp); } servicelist = (struct valuelist *)0; } #endif #ifdef _LIBC static #endif void res_buildprotolist(void) { struct protoent *pp; struct valuelist *slp; #ifdef MAYBE_HESIOD setprotoent(0); #else setprotoent(1); #endif while ((pp = getprotoent()) != NULL) { slp = (struct valuelist *)malloc(sizeof(struct valuelist)); if (!slp) break; slp->name = strdup(pp->p_name); if (slp->name == NULL) { free(slp); break; } slp->port = pp->p_proto; /*%< host byte order */ slp->next = protolist; slp->prev = NULL; if (protolist) protolist->prev = slp; protolist = slp; } endprotoent(); } #ifndef _LIBC void res_destroyprotolist(void) { struct valuelist *plp, *plp_next; for (plp = protolist; plp != NULL; plp = plp_next) { plp_next = plp->next; free(plp->name); free(plp); } protolist = (struct valuelist *)0; } #endif static int findservice(const char *s, struct valuelist **list) { struct valuelist *lp = *list; int n; for (; lp != NULL; lp = lp->next) if (strcasecmp(lp->name, s) == 0) { if (lp != *list) { lp->prev->next = lp->next; if (lp->next) lp->next->prev = lp->prev; (*list)->prev = lp; lp->next = *list; *list = lp; } return (lp->port); /*%< host byte order */ } if (sscanf(s, "%d", &n) != 1 || n <= 0) n = -1; return (n); } /*% * Convert service name or (ascii) number to int. */ #ifdef _LIBC static #endif int res_servicenumber(const char *p) { if (servicelist == (struct valuelist *)0) res_buildservicelist(); return (findservice(p, &servicelist)); } /*% * Convert protocol name or (ascii) number to int. */ #ifdef _LIBC static #endif int res_protocolnumber(const char *p) { if (protolist == (struct valuelist *)0) res_buildprotolist(); return (findservice(p, &protolist)); } #ifndef _LIBC static struct servent * cgetservbyport(u_int16_t port, const char *proto) { /*%< Host byte order. */ struct valuelist **list = &servicelist; struct valuelist *lp = *list; static struct servent serv; port = ntohs(port); for (; lp != NULL; lp = lp->next) { if (port != (u_int16_t)lp->port) /*%< Host byte order. */ continue; if (strcasecmp(lp->proto, proto) == 0) { if (lp != *list) { lp->prev->next = lp->next; if (lp->next) lp->next->prev = lp->prev; (*list)->prev = lp; lp->next = *list; *list = lp; } serv.s_name = lp->name; serv.s_port = htons((u_int16_t)lp->port); serv.s_proto = lp->proto; return (&serv); } } return (0); } static struct protoent * cgetprotobynumber(int proto) { /*%< Host byte order. */ struct valuelist **list = &protolist; struct valuelist *lp = *list; static struct protoent prot; for (; lp != NULL; lp = lp->next) if (lp->port == proto) { /*%< Host byte order. */ if (lp != *list) { lp->prev->next = lp->next; if (lp->next) lp->next->prev = lp->prev; (*list)->prev = lp; lp->next = *list; *list = lp; } prot.p_name = lp->name; prot.p_proto = lp->port; /*%< Host byte order. */ return (&prot); } return (0); } const char * res_protocolname(int num) { static char number[8]; struct protoent *pp; if (protolist == (struct valuelist *)0) res_buildprotolist(); pp = cgetprotobynumber(num); - if (pp == 0) { + if (pp == NULL) { (void) sprintf(number, "%d", num); return (number); } return (pp->p_name); } const char * res_servicename(u_int16_t port, const char *proto) { /*%< Host byte order. */ static char number[8]; struct servent *ss; if (servicelist == (struct valuelist *)0) res_buildservicelist(); ss = cgetservbyport(htons(port), proto); - if (ss == 0) { + if (ss == NULL) { (void) sprintf(number, "%d", port); return (number); } return (ss->s_name); } #endif Index: head/lib/libc/rpc/auth_none.c =================================================================== --- head/lib/libc/rpc/auth_none.c (revision 297789) +++ head/lib/libc/rpc/auth_none.c (revision 297790) @@ -1,175 +1,175 @@ /* $NetBSD: auth_none.c,v 1.13 2000/01/22 22:19:17 mycroft Exp $ */ /*- * Copyright (c) 2009, Sun Microsystems, Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * - Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * - Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * - Neither the name of Sun Microsystems, Inc. nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ #if defined(LIBC_SCCS) && !defined(lint) static char *sccsid2 = "@(#)auth_none.c 1.19 87/08/11 Copyr 1984 Sun Micro"; static char *sccsid = "@(#)auth_none.c 2.1 88/07/29 4.0 RPCSRC"; #endif #include __FBSDID("$FreeBSD$"); /* * auth_none.c * Creates a client authentication handle for passing "null" * credentials and verifiers to remote systems. * * Copyright (C) 1984, Sun Microsystems, Inc. */ #include "namespace.h" #include "reentrant.h" #include #include #include #include #include #include "un-namespace.h" #include "mt_misc.h" #define MAX_MARSHAL_SIZE 20 /* * Authenticator operations routines */ static bool_t authnone_marshal (AUTH *, XDR *); static void authnone_verf (AUTH *); static bool_t authnone_validate (AUTH *, struct opaque_auth *); static bool_t authnone_refresh (AUTH *, void *); static void authnone_destroy (AUTH *); extern bool_t xdr_opaque_auth(XDR *, struct opaque_auth *); static struct auth_ops *authnone_ops(void); static struct authnone_private { AUTH no_client; char marshalled_client[MAX_MARSHAL_SIZE]; u_int mcnt; } *authnone_private; AUTH * authnone_create(void) { struct authnone_private *ap = authnone_private; XDR xdr_stream; XDR *xdrs; mutex_lock(&authnone_lock); - if (ap == 0) { - ap = (struct authnone_private *)calloc(1, sizeof (*ap)); - if (ap == 0) { + if (ap == NULL) { + ap = calloc(1, sizeof (*ap)); + if (ap == NULL) { mutex_unlock(&authnone_lock); return (0); } authnone_private = ap; } if (!ap->mcnt) { ap->no_client.ah_cred = ap->no_client.ah_verf = _null_auth; ap->no_client.ah_ops = authnone_ops(); xdrs = &xdr_stream; xdrmem_create(xdrs, ap->marshalled_client, (u_int)MAX_MARSHAL_SIZE, XDR_ENCODE); (void)xdr_opaque_auth(xdrs, &ap->no_client.ah_cred); (void)xdr_opaque_auth(xdrs, &ap->no_client.ah_verf); ap->mcnt = XDR_GETPOS(xdrs); XDR_DESTROY(xdrs); } mutex_unlock(&authnone_lock); return (&ap->no_client); } /*ARGSUSED*/ static bool_t authnone_marshal(AUTH *client, XDR *xdrs) { struct authnone_private *ap; bool_t dummy; assert(xdrs != NULL); ap = authnone_private; if (ap == NULL) { mutex_unlock(&authnone_lock); return (FALSE); } dummy = (*xdrs->x_ops->x_putbytes)(xdrs, ap->marshalled_client, ap->mcnt); mutex_unlock(&authnone_lock); return (dummy); } /* All these unused parameters are required to keep ANSI-C from grumbling */ /*ARGSUSED*/ static void authnone_verf(AUTH *client) { } /*ARGSUSED*/ static bool_t authnone_validate(AUTH *client, struct opaque_auth *opaque) { return (TRUE); } /*ARGSUSED*/ static bool_t authnone_refresh(AUTH *client, void *dummy) { return (FALSE); } /*ARGSUSED*/ static void authnone_destroy(AUTH *client) { } static struct auth_ops * authnone_ops(void) { static struct auth_ops ops; /* VARIABLES PROTECTED BY ops_lock: ops */ mutex_lock(&ops_lock); if (ops.ah_nextverf == NULL) { ops.ah_nextverf = authnone_verf; ops.ah_marshal = authnone_marshal; ops.ah_validate = authnone_validate; ops.ah_refresh = authnone_refresh; ops.ah_destroy = authnone_destroy; } mutex_unlock(&ops_lock); return (&ops); } Index: head/lib/libc/rpc/clnt_perror.c =================================================================== --- head/lib/libc/rpc/clnt_perror.c (revision 297789) +++ head/lib/libc/rpc/clnt_perror.c (revision 297790) @@ -1,323 +1,323 @@ /* $NetBSD: clnt_perror.c,v 1.24 2000/06/02 23:11:07 fvdl Exp $ */ /*- * Copyright (c) 2009, Sun Microsystems, Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * - Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * - Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * - Neither the name of Sun Microsystems, Inc. nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ #if defined(LIBC_SCCS) && !defined(lint) static char *sccsid2 = "@(#)clnt_perror.c 1.15 87/10/07 Copyr 1984 Sun Micro"; static char *sccsid = "@(#)clnt_perror.c 2.1 88/07/29 4.0 RPCSRC"; #endif #include __FBSDID("$FreeBSD$"); /* * clnt_perror.c * * Copyright (C) 1984, Sun Microsystems, Inc. * */ #include "namespace.h" #include #include #include #include #include #include #include #include #include "un-namespace.h" static char *buf; static char *_buf(void); static char *auth_errmsg(enum auth_stat); #define CLNT_PERROR_BUFLEN 256 static char * _buf(void) { - if (buf == 0) - buf = (char *)malloc(CLNT_PERROR_BUFLEN); + if (buf == NULL) + buf = malloc(CLNT_PERROR_BUFLEN); return (buf); } /* * Print reply error info */ char * clnt_sperror(CLIENT *rpch, const char *s) { struct rpc_err e; char *err; char *str; char *strstart; size_t len, i; assert(rpch != NULL); assert(s != NULL); str = _buf(); /* side effect: sets CLNT_PERROR_BUFLEN */ - if (str == 0) + if (str == NULL) return (0); len = CLNT_PERROR_BUFLEN; strstart = str; CLNT_GETERR(rpch, &e); if ((i = snprintf(str, len, "%s: ", s)) > 0) { str += i; len -= i; } (void)strncpy(str, clnt_sperrno(e.re_status), len - 1); i = strlen(str); str += i; len -= i; switch (e.re_status) { case RPC_SUCCESS: case RPC_CANTENCODEARGS: case RPC_CANTDECODERES: case RPC_TIMEDOUT: case RPC_PROGUNAVAIL: case RPC_PROCUNAVAIL: case RPC_CANTDECODEARGS: case RPC_SYSTEMERROR: case RPC_UNKNOWNHOST: case RPC_UNKNOWNPROTO: case RPC_PMAPFAILURE: case RPC_PROGNOTREGISTERED: case RPC_FAILED: break; case RPC_CANTSEND: case RPC_CANTRECV: i = snprintf(str, len, "; errno = %s", strerror(e.re_errno)); if (i > 0) { str += i; len -= i; } break; case RPC_VERSMISMATCH: i = snprintf(str, len, "; low version = %u, high version = %u", e.re_vers.low, e.re_vers.high); if (i > 0) { str += i; len -= i; } break; case RPC_AUTHERROR: err = auth_errmsg(e.re_why); i = snprintf(str, len, "; why = "); if (i > 0) { str += i; len -= i; } if (err != NULL) { i = snprintf(str, len, "%s",err); } else { i = snprintf(str, len, "(unknown authentication error - %d)", (int) e.re_why); } if (i > 0) { str += i; len -= i; } break; case RPC_PROGVERSMISMATCH: i = snprintf(str, len, "; low version = %u, high version = %u", e.re_vers.low, e.re_vers.high); if (i > 0) { str += i; len -= i; } break; default: /* unknown */ i = snprintf(str, len, "; s1 = %u, s2 = %u", e.re_lb.s1, e.re_lb.s2); if (i > 0) { str += i; len -= i; } break; } strstart[CLNT_PERROR_BUFLEN-1] = '\0'; return(strstart) ; } void clnt_perror(CLIENT *rpch, const char *s) { assert(rpch != NULL); assert(s != NULL); (void) fprintf(stderr, "%s\n", clnt_sperror(rpch,s)); } static const char *const rpc_errlist[] = { "RPC: Success", /* 0 - RPC_SUCCESS */ "RPC: Can't encode arguments", /* 1 - RPC_CANTENCODEARGS */ "RPC: Can't decode result", /* 2 - RPC_CANTDECODERES */ "RPC: Unable to send", /* 3 - RPC_CANTSEND */ "RPC: Unable to receive", /* 4 - RPC_CANTRECV */ "RPC: Timed out", /* 5 - RPC_TIMEDOUT */ "RPC: Incompatible versions of RPC", /* 6 - RPC_VERSMISMATCH */ "RPC: Authentication error", /* 7 - RPC_AUTHERROR */ "RPC: Program unavailable", /* 8 - RPC_PROGUNAVAIL */ "RPC: Program/version mismatch", /* 9 - RPC_PROGVERSMISMATCH */ "RPC: Procedure unavailable", /* 10 - RPC_PROCUNAVAIL */ "RPC: Server can't decode arguments", /* 11 - RPC_CANTDECODEARGS */ "RPC: Remote system error", /* 12 - RPC_SYSTEMERROR */ "RPC: Unknown host", /* 13 - RPC_UNKNOWNHOST */ "RPC: Port mapper failure", /* 14 - RPC_PMAPFAILURE */ "RPC: Program not registered", /* 15 - RPC_PROGNOTREGISTERED */ "RPC: Failed (unspecified error)", /* 16 - RPC_FAILED */ "RPC: Unknown protocol" /* 17 - RPC_UNKNOWNPROTO */ }; /* * This interface for use by clntrpc */ char * clnt_sperrno(enum clnt_stat stat) { unsigned int errnum = stat; if (errnum < (sizeof(rpc_errlist)/sizeof(rpc_errlist[0]))) /* LINTED interface problem */ return (char *)rpc_errlist[errnum]; return ("RPC: (unknown error code)"); } void clnt_perrno(enum clnt_stat num) { (void) fprintf(stderr, "%s\n", clnt_sperrno(num)); } char * clnt_spcreateerror(const char *s) { char *str; size_t len, i; assert(s != NULL); str = _buf(); /* side effect: sets CLNT_PERROR_BUFLEN */ - if (str == 0) + if (str == NULL) return(0); len = CLNT_PERROR_BUFLEN; i = snprintf(str, len, "%s: ", s); if (i > 0) len -= i; (void)strncat(str, clnt_sperrno(rpc_createerr.cf_stat), len - 1); switch (rpc_createerr.cf_stat) { case RPC_PMAPFAILURE: (void) strncat(str, " - ", len - 1); (void) strncat(str, clnt_sperrno(rpc_createerr.cf_error.re_status), len - 4); break; case RPC_SYSTEMERROR: (void)strncat(str, " - ", len - 1); (void)strncat(str, strerror(rpc_createerr.cf_error.re_errno), len - 4); break; case RPC_CANTSEND: case RPC_CANTDECODERES: case RPC_CANTENCODEARGS: case RPC_SUCCESS: case RPC_UNKNOWNPROTO: case RPC_PROGNOTREGISTERED: case RPC_FAILED: case RPC_UNKNOWNHOST: case RPC_CANTDECODEARGS: case RPC_PROCUNAVAIL: case RPC_PROGVERSMISMATCH: case RPC_PROGUNAVAIL: case RPC_AUTHERROR: case RPC_VERSMISMATCH: case RPC_TIMEDOUT: case RPC_CANTRECV: default: break; } str[CLNT_PERROR_BUFLEN-1] = '\0'; return (str); } void clnt_pcreateerror(const char *s) { assert(s != NULL); (void) fprintf(stderr, "%s\n", clnt_spcreateerror(s)); } static const char *const auth_errlist[] = { "Authentication OK", /* 0 - AUTH_OK */ "Invalid client credential", /* 1 - AUTH_BADCRED */ "Server rejected credential", /* 2 - AUTH_REJECTEDCRED */ "Invalid client verifier", /* 3 - AUTH_BADVERF */ "Server rejected verifier", /* 4 - AUTH_REJECTEDVERF */ "Client credential too weak", /* 5 - AUTH_TOOWEAK */ "Invalid server verifier", /* 6 - AUTH_INVALIDRESP */ "Failed (unspecified error)", /* 7 - AUTH_FAILED */ "Kerberos generic error", /* 8 - AUTH_KERB_GENERIC*/ "Kerberos credential expired", /* 9 - AUTH_TIMEEXPIRE */ "Bad kerberos ticket file", /* 10 - AUTH_TKT_FILE */ "Can't decode kerberos authenticator", /* 11 - AUTH_DECODE */ "Address wrong in kerberos ticket", /* 12 - AUTH_NET_ADDR */ "GSS-API crediential problem", /* 13 - RPCSEC_GSS_CREDPROBLEM */ "GSS-API context problem" /* 14 - RPCSEC_GSS_CTXPROBLEM */ }; static char * auth_errmsg(enum auth_stat stat) { unsigned int errnum = stat; if (errnum < (sizeof(auth_errlist)/sizeof(auth_errlist[0]))) /* LINTED interface problem */ return (char *)auth_errlist[errnum]; return(NULL); } Index: head/lib/libc/rpc/mt_misc.c =================================================================== --- head/lib/libc/rpc/mt_misc.c (revision 297789) +++ head/lib/libc/rpc/mt_misc.c (revision 297790) @@ -1,116 +1,116 @@ /* $NetBSD: mt_misc.c,v 1.1 2000/06/02 23:11:11 fvdl Exp $ */ /* #pragma ident "@(#)mt_misc.c 1.24 93/04/29 SMI" */ #include __FBSDID("$FreeBSD$"); #include "namespace.h" #include "reentrant.h" #include #include #include #include #include "un-namespace.h" #include "mt_misc.h" /* Take these objects out of the application namespace. */ #define svc_lock __svc_lock #define svc_fd_lock __svc_fd_lock #define rpcbaddr_cache_lock __rpcbaddr_cache_lock #define authdes_ops_lock __authdes_ops_lock #define authnone_lock __authnone_lock #define authsvc_lock __authsvc_lock #define clnt_fd_lock __clnt_fd_lock #define clntraw_lock __clntraw_lock #define dupreq_lock __dupreq_lock #define loopnconf_lock __loopnconf_lock #define ops_lock __ops_lock #define proglst_lock __proglst_lock #define rpcsoc_lock __rpcsoc_lock #define svcraw_lock __svcraw_lock #define xprtlist_lock __xprtlist_lock /* protects the services list (svc.c) */ pthread_rwlock_t svc_lock = PTHREAD_RWLOCK_INITIALIZER; /* protects svc_fdset and the xports[] array */ pthread_rwlock_t svc_fd_lock = PTHREAD_RWLOCK_INITIALIZER; /* protects the RPCBIND address cache */ pthread_rwlock_t rpcbaddr_cache_lock = PTHREAD_RWLOCK_INITIALIZER; /* serializes authdes ops initializations */ pthread_mutex_t authdes_ops_lock = PTHREAD_MUTEX_INITIALIZER; /* protects des stats list */ pthread_mutex_t svcauthdesstats_lock = PTHREAD_MUTEX_INITIALIZER; /* auth_none.c serialization */ pthread_mutex_t authnone_lock = PTHREAD_MUTEX_INITIALIZER; /* protects the Auths list (svc_auth.c) */ pthread_mutex_t authsvc_lock = PTHREAD_MUTEX_INITIALIZER; /* protects client-side fd lock array */ pthread_mutex_t clnt_fd_lock = PTHREAD_MUTEX_INITIALIZER; /* clnt_raw.c serialization */ pthread_mutex_t clntraw_lock = PTHREAD_MUTEX_INITIALIZER; /* dupreq variables (svc_dg.c) */ pthread_mutex_t dupreq_lock = PTHREAD_MUTEX_INITIALIZER; /* loopnconf (rpcb_clnt.c) */ pthread_mutex_t loopnconf_lock = PTHREAD_MUTEX_INITIALIZER; /* serializes ops initializations */ pthread_mutex_t ops_lock = PTHREAD_MUTEX_INITIALIZER; /* protects proglst list (svc_simple.c) */ pthread_mutex_t proglst_lock = PTHREAD_MUTEX_INITIALIZER; /* serializes clnt_com_create() (rpc_soc.c) */ pthread_mutex_t rpcsoc_lock = PTHREAD_MUTEX_INITIALIZER; /* svc_raw.c serialization */ pthread_mutex_t svcraw_lock = PTHREAD_MUTEX_INITIALIZER; /* xprtlist (svc_generic.c) */ pthread_mutex_t xprtlist_lock = PTHREAD_MUTEX_INITIALIZER; #undef rpc_createerr struct rpc_createerr rpc_createerr; static thread_key_t rce_key; static once_t rce_once = ONCE_INITIALIZER; static int rce_key_error; static void rce_key_init(void) { rce_key_error = thr_keycreate(&rce_key, free); } struct rpc_createerr * __rpc_createerr(void) { - struct rpc_createerr *rce_addr = 0; + struct rpc_createerr *rce_addr = NULL; if (thr_main()) return (&rpc_createerr); if (thr_once(&rce_once, rce_key_init) != 0 || rce_key_error != 0) return (&rpc_createerr); rce_addr = (struct rpc_createerr *)thr_getspecific(rce_key); if (!rce_addr) { rce_addr = (struct rpc_createerr *) malloc(sizeof (struct rpc_createerr)); if (thr_setspecific(rce_key, (void *) rce_addr) != 0) { free(rce_addr); return (&rpc_createerr); } memset(rce_addr, 0, sizeof (struct rpc_createerr)); return (rce_addr); } return (rce_addr); } Index: head/lib/libc/rpc/rpcdname.c =================================================================== --- head/lib/libc/rpc/rpcdname.c (revision 297789) +++ head/lib/libc/rpc/rpcdname.c (revision 297790) @@ -1,79 +1,79 @@ /*- * Copyright (c) 2009, Sun Microsystems, Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * - Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * - Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * - Neither the name of Sun Microsystems, Inc. nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ #if defined(LIBC_SCCS) && !defined(lint) static char sccsid[] = "@(#)rpcdname.c 1.7 91/03/11 Copyr 1989 Sun Micro"; #endif #include __FBSDID("$FreeBSD$"); /* * rpcdname.c * Gets the default domain name */ #include "namespace.h" #include #include #include #include "un-namespace.h" -static char *default_domain = 0; +static char *default_domain; static char * get_default_domain(void) { char temp[256]; - if (default_domain) + if (default_domain != NULL) return (default_domain); if (getdomainname(temp, sizeof(temp)) < 0) return (0); if ((int) strlen(temp) > 0) { - default_domain = (char *)malloc((strlen(temp)+(unsigned)1)); - if (default_domain == 0) + default_domain = malloc((strlen(temp) + (unsigned)1)); + if (default_domain == NULL) return (0); (void) strcpy(default_domain, temp); return (default_domain); } return (0); } /* * This is a wrapper for the system call getdomainname which returns a * ypclnt.h error code in the failure case. It also checks to see that * the domain name is non-null, knowing that the null string is going to * get rejected elsewhere in the NIS client package. */ int __rpc_get_default_domain(char **domain) { - if ((*domain = get_default_domain()) != 0) + if ((*domain = get_default_domain()) != NULL) return (0); return (-1); } Index: head/lib/libc/softfloat/timesoftfloat.c =================================================================== --- head/lib/libc/softfloat/timesoftfloat.c (revision 297789) +++ head/lib/libc/softfloat/timesoftfloat.c (revision 297790) @@ -1,2639 +1,2639 @@ /* $NetBSD: timesoftfloat.c,v 1.1 2000/06/06 08:15:11 bjh21 Exp $ */ /* =============================================================================== This C source file is part of the SoftFloat IEC/IEEE Floating-point Arithmetic Package, Release 2a. Written by John R. Hauser. This work was made possible in part by the International Computer Science Institute, located at Suite 600, 1947 Center Street, Berkeley, California 94704. Funding was partially provided by the National Science Foundation under grant MIP-9311980. The original version of this code was written as part of a project to build a fixed-point vector processor in collaboration with the University of California at Berkeley, overseen by Profs. Nelson Morgan and John Wawrzynek. More information is available through the Web page `http://HTTP.CS.Berkeley.EDU/~jhauser/ arithmetic/SoftFloat.html'. THIS SOFTWARE IS DISTRIBUTED AS IS, FOR FREE. Although reasonable effort has been made to avoid it, THIS SOFTWARE MAY CONTAIN FAULTS THAT WILL AT TIMES RESULT IN INCORRECT BEHAVIOR. USE OF THIS SOFTWARE IS RESTRICTED TO PERSONS AND ORGANIZATIONS WHO CAN AND WILL TAKE FULL RESPONSIBILITY FOR ANY AND ALL LOSSES, COSTS, OR OTHER PROBLEMS ARISING FROM ITS USE. Derivative works are acceptable, even for commercial purposes, so long as (1) they include prominent notice that the work is derivative, and (2) they include prominent notice akin to these four paragraphs for those parts of this code that are retained. =============================================================================== */ #include __FBSDID("$FreeBSD$"); #include #include #include #include #include #include "milieu.h" #include "softfloat.h" enum { minIterations = 1000 }; static void fail( const char *message, ... ) { va_list varArgs; fputs( "timesoftfloat: ", stderr ); va_start( varArgs, message ); vfprintf( stderr, message, varArgs ); va_end( varArgs ); fputs( ".\n", stderr ); exit( EXIT_FAILURE ); } static char *functionName; static char *roundingPrecisionName, *roundingModeName, *tininessModeName; static void reportTime( int32 count, long clocks ) { printf( "%8.1f kops/s: %s", ( count / ( ( (float) clocks ) / CLOCKS_PER_SEC ) ) / 1000, functionName ); if ( roundingModeName ) { if ( roundingPrecisionName ) { fputs( ", precision ", stdout ); fputs( roundingPrecisionName, stdout ); } fputs( ", rounding ", stdout ); fputs( roundingModeName, stdout ); if ( tininessModeName ) { fputs( ", tininess ", stdout ); fputs( tininessModeName, stdout ); fputs( " rounding", stdout ); } } fputc( '\n', stdout ); } enum { numInputs_int32 = 32 }; static const int32 inputs_int32[ numInputs_int32 ] = { 0xFFFFBB79, 0x405CF80F, 0x00000000, 0xFFFFFD04, 0xFFF20002, 0x0C8EF795, 0xF00011FF, 0x000006CA, 0x00009BFE, 0xFF4862E3, 0x9FFFEFFE, 0xFFFFFFB7, 0x0BFF7FFF, 0x0000F37A, 0x0011DFFE, 0x00000006, 0xFFF02006, 0xFFFFF7D1, 0x10200003, 0xDE8DF765, 0x00003E02, 0x000019E8, 0x0008FFFE, 0xFFFFFB5C, 0xFFDF7FFE, 0x07C42FBF, 0x0FFFE3FF, 0x040B9F13, 0xBFFFFFF8, 0x0001BF56, 0x000017F6, 0x000A908A }; static void time_a_int32_z_float32( float32 function( int32 ) ) { clock_t startClock, endClock; int32 count, i; int8 inputNum; count = 0; inputNum = 0; startClock = clock(); do { for ( i = minIterations; i; --i ) { function( inputs_int32[ inputNum ] ); inputNum = ( inputNum + 1 ) & ( numInputs_int32 - 1 ); } count += minIterations; } while ( clock() - startClock < CLOCKS_PER_SEC ); inputNum = 0; startClock = clock(); for ( i = count; i; --i ) { function( inputs_int32[ inputNum ] ); inputNum = ( inputNum + 1 ) & ( numInputs_int32 - 1 ); } endClock = clock(); reportTime( count, endClock - startClock ); } static void time_a_int32_z_float64( float64 function( int32 ) ) { clock_t startClock, endClock; int32 count, i; int8 inputNum; count = 0; inputNum = 0; startClock = clock(); do { for ( i = minIterations; i; --i ) { function( inputs_int32[ inputNum ] ); inputNum = ( inputNum + 1 ) & ( numInputs_int32 - 1 ); } count += minIterations; } while ( clock() - startClock < CLOCKS_PER_SEC ); inputNum = 0; startClock = clock(); for ( i = count; i; --i ) { function( inputs_int32[ inputNum ] ); inputNum = ( inputNum + 1 ) & ( numInputs_int32 - 1 ); } endClock = clock(); reportTime( count, endClock - startClock ); } #ifdef FLOATX80 static void time_a_int32_z_floatx80( floatx80 function( int32 ) ) { clock_t startClock, endClock; int32 count, i; int8 inputNum; count = 0; inputNum = 0; startClock = clock(); do { for ( i = minIterations; i; --i ) { function( inputs_int32[ inputNum ] ); inputNum = ( inputNum + 1 ) & ( numInputs_int32 - 1 ); } count += minIterations; } while ( clock() - startClock < CLOCKS_PER_SEC ); inputNum = 0; startClock = clock(); for ( i = count; i; --i ) { function( inputs_int32[ inputNum ] ); inputNum = ( inputNum + 1 ) & ( numInputs_int32 - 1 ); } endClock = clock(); reportTime( count, endClock - startClock ); } #endif #ifdef FLOAT128 static void time_a_int32_z_float128( float128 function( int32 ) ) { clock_t startClock, endClock; int32 count, i; int8 inputNum; count = 0; inputNum = 0; startClock = clock(); do { for ( i = minIterations; i; --i ) { function( inputs_int32[ inputNum ] ); inputNum = ( inputNum + 1 ) & ( numInputs_int32 - 1 ); } count += minIterations; } while ( clock() - startClock < CLOCKS_PER_SEC ); inputNum = 0; startClock = clock(); for ( i = count; i; --i ) { function( inputs_int32[ inputNum ] ); inputNum = ( inputNum + 1 ) & ( numInputs_int32 - 1 ); } endClock = clock(); reportTime( count, endClock - startClock ); } #endif enum { numInputs_int64 = 32 }; static const int64 inputs_int64[ numInputs_int64 ] = { LIT64( 0xFBFFC3FFFFFFFFFF ), LIT64( 0x0000000003C589BC ), LIT64( 0x00000000400013FE ), LIT64( 0x0000000000186171 ), LIT64( 0xFFFFFFFFFFFEFBFA ), LIT64( 0xFFFFFD79E6DFFC73 ), LIT64( 0x0000000010001DFF ), LIT64( 0xDD1A0F0C78513710 ), LIT64( 0xFFFF83FFFFFEFFFE ), LIT64( 0x00756EBD1AD0C1C7 ), LIT64( 0x0003FDFFFFFFFFBE ), LIT64( 0x0007D0FB2C2CA951 ), LIT64( 0x0007FC0007FFFFFE ), LIT64( 0x0000001F942B18BB ), LIT64( 0x0000080101FFFFFE ), LIT64( 0xFFFFFFFFFFFF0978 ), LIT64( 0x000000000008BFFF ), LIT64( 0x0000000006F5AF08 ), LIT64( 0xFFDEFF7FFFFFFFFE ), LIT64( 0x0000000000000003 ), LIT64( 0x3FFFFFFFFF80007D ), LIT64( 0x0000000000000078 ), LIT64( 0xFFF80000007FDFFD ), LIT64( 0x1BBC775B78016AB0 ), LIT64( 0xFFF9001FFFFFFFFE ), LIT64( 0xFFFD4767AB98E43F ), LIT64( 0xFFFFFEFFFE00001E ), LIT64( 0xFFFFFFFFFFF04EFD ), LIT64( 0x07FFFFFFFFFFF7FF ), LIT64( 0xFFFC9EAA38F89050 ), LIT64( 0x00000020FBFFFFFE ), LIT64( 0x0000099AE6455357 ) }; static void time_a_int64_z_float32( float32 function( int64 ) ) { clock_t startClock, endClock; int32 count, i; int8 inputNum; count = 0; inputNum = 0; startClock = clock(); do { for ( i = minIterations; i; --i ) { function( inputs_int64[ inputNum ] ); inputNum = ( inputNum + 1 ) & ( numInputs_int64 - 1 ); } count += minIterations; } while ( clock() - startClock < CLOCKS_PER_SEC ); inputNum = 0; startClock = clock(); for ( i = count; i; --i ) { function( inputs_int64[ inputNum ] ); inputNum = ( inputNum + 1 ) & ( numInputs_int64 - 1 ); } endClock = clock(); reportTime( count, endClock - startClock ); } static void time_a_int64_z_float64( float64 function( int64 ) ) { clock_t startClock, endClock; int32 count, i; int8 inputNum; count = 0; inputNum = 0; startClock = clock(); do { for ( i = minIterations; i; --i ) { function( inputs_int64[ inputNum ] ); inputNum = ( inputNum + 1 ) & ( numInputs_int64 - 1 ); } count += minIterations; } while ( clock() - startClock < CLOCKS_PER_SEC ); inputNum = 0; startClock = clock(); for ( i = count; i; --i ) { function( inputs_int64[ inputNum ] ); inputNum = ( inputNum + 1 ) & ( numInputs_int64 - 1 ); } endClock = clock(); reportTime( count, endClock - startClock ); } #ifdef FLOATX80 static void time_a_int64_z_floatx80( floatx80 function( int64 ) ) { clock_t startClock, endClock; int32 count, i; int8 inputNum; count = 0; inputNum = 0; startClock = clock(); do { for ( i = minIterations; i; --i ) { function( inputs_int64[ inputNum ] ); inputNum = ( inputNum + 1 ) & ( numInputs_int64 - 1 ); } count += minIterations; } while ( clock() - startClock < CLOCKS_PER_SEC ); inputNum = 0; startClock = clock(); for ( i = count; i; --i ) { function( inputs_int64[ inputNum ] ); inputNum = ( inputNum + 1 ) & ( numInputs_int64 - 1 ); } endClock = clock(); reportTime( count, endClock - startClock ); } #endif #ifdef FLOAT128 static void time_a_int64_z_float128( float128 function( int64 ) ) { clock_t startClock, endClock; int32 count, i; int8 inputNum; count = 0; inputNum = 0; startClock = clock(); do { for ( i = minIterations; i; --i ) { function( inputs_int64[ inputNum ] ); inputNum = ( inputNum + 1 ) & ( numInputs_int64 - 1 ); } count += minIterations; } while ( clock() - startClock < CLOCKS_PER_SEC ); inputNum = 0; startClock = clock(); for ( i = count; i; --i ) { function( inputs_int64[ inputNum ] ); inputNum = ( inputNum + 1 ) & ( numInputs_int64 - 1 ); } endClock = clock(); reportTime( count, endClock - startClock ); } #endif enum { numInputs_float32 = 32 }; static const float32 inputs_float32[ numInputs_float32 ] = { 0x4EFA0000, 0xC1D0B328, 0x80000000, 0x3E69A31E, 0xAF803EFF, 0x3F800000, 0x17BF8000, 0xE74A301A, 0x4E010003, 0x7EE3C75D, 0xBD803FE0, 0xBFFEFF00, 0x7981F800, 0x431FFFFC, 0xC100C000, 0x3D87EFFF, 0x4103FEFE, 0xBC000007, 0xBF01F7FF, 0x4E6C6B5C, 0xC187FFFE, 0xC58B9F13, 0x4F88007F, 0xDF004007, 0xB7FFD7FE, 0x7E8001FB, 0x46EFFBFF, 0x31C10000, 0xDB428661, 0x33F89B1F, 0xA3BFEFFF, 0x537BFFBE }; static void time_a_float32_z_int32( int32 function( float32 ) ) { clock_t startClock, endClock; int32 count, i; int8 inputNum; count = 0; inputNum = 0; startClock = clock(); do { for ( i = minIterations; i; --i ) { function( inputs_float32[ inputNum ] ); inputNum = ( inputNum + 1 ) & ( numInputs_float32 - 1 ); } count += minIterations; } while ( clock() - startClock < CLOCKS_PER_SEC ); inputNum = 0; startClock = clock(); for ( i = count; i; --i ) { function( inputs_float32[ inputNum ] ); inputNum = ( inputNum + 1 ) & ( numInputs_float32 - 1 ); } endClock = clock(); reportTime( count, endClock - startClock ); } static void time_a_float32_z_int64( int64 function( float32 ) ) { clock_t startClock, endClock; int32 count, i; int8 inputNum; count = 0; inputNum = 0; startClock = clock(); do { for ( i = minIterations; i; --i ) { function( inputs_float32[ inputNum ] ); inputNum = ( inputNum + 1 ) & ( numInputs_float32 - 1 ); } count += minIterations; } while ( clock() - startClock < CLOCKS_PER_SEC ); inputNum = 0; startClock = clock(); for ( i = count; i; --i ) { function( inputs_float32[ inputNum ] ); inputNum = ( inputNum + 1 ) & ( numInputs_float32 - 1 ); } endClock = clock(); reportTime( count, endClock - startClock ); } static void time_a_float32_z_float64( float64 function( float32 ) ) { clock_t startClock, endClock; int32 count, i; int8 inputNum; count = 0; inputNum = 0; startClock = clock(); do { for ( i = minIterations; i; --i ) { function( inputs_float32[ inputNum ] ); inputNum = ( inputNum + 1 ) & ( numInputs_float32 - 1 ); } count += minIterations; } while ( clock() - startClock < CLOCKS_PER_SEC ); inputNum = 0; startClock = clock(); for ( i = count; i; --i ) { function( inputs_float32[ inputNum ] ); inputNum = ( inputNum + 1 ) & ( numInputs_float32 - 1 ); } endClock = clock(); reportTime( count, endClock - startClock ); } #ifdef FLOATX80 static void time_a_float32_z_floatx80( floatx80 function( float32 ) ) { clock_t startClock, endClock; int32 count, i; int8 inputNum; count = 0; inputNum = 0; startClock = clock(); do { for ( i = minIterations; i; --i ) { function( inputs_float32[ inputNum ] ); inputNum = ( inputNum + 1 ) & ( numInputs_float32 - 1 ); } count += minIterations; } while ( clock() - startClock < CLOCKS_PER_SEC ); inputNum = 0; startClock = clock(); for ( i = count; i; --i ) { function( inputs_float32[ inputNum ] ); inputNum = ( inputNum + 1 ) & ( numInputs_float32 - 1 ); } endClock = clock(); reportTime( count, endClock - startClock ); } #endif #ifdef FLOAT128 static void time_a_float32_z_float128( float128 function( float32 ) ) { clock_t startClock, endClock; int32 count, i; int8 inputNum; count = 0; inputNum = 0; startClock = clock(); do { for ( i = minIterations; i; --i ) { function( inputs_float32[ inputNum ] ); inputNum = ( inputNum + 1 ) & ( numInputs_float32 - 1 ); } count += minIterations; } while ( clock() - startClock < CLOCKS_PER_SEC ); inputNum = 0; startClock = clock(); for ( i = count; i; --i ) { function( inputs_float32[ inputNum ] ); inputNum = ( inputNum + 1 ) & ( numInputs_float32 - 1 ); } endClock = clock(); reportTime( count, endClock - startClock ); } #endif static void time_az_float32( float32 function( float32 ) ) { clock_t startClock, endClock; int32 count, i; int8 inputNum; count = 0; inputNum = 0; startClock = clock(); do { for ( i = minIterations; i; --i ) { function( inputs_float32[ inputNum ] ); inputNum = ( inputNum + 1 ) & ( numInputs_float32 - 1 ); } count += minIterations; } while ( clock() - startClock < CLOCKS_PER_SEC ); inputNum = 0; startClock = clock(); for ( i = count; i; --i ) { function( inputs_float32[ inputNum ] ); inputNum = ( inputNum + 1 ) & ( numInputs_float32 - 1 ); } endClock = clock(); reportTime( count, endClock - startClock ); } static void time_ab_float32_z_flag( flag function( float32, float32 ) ) { clock_t startClock, endClock; int32 count, i; int8 inputNumA, inputNumB; count = 0; inputNumA = 0; inputNumB = 0; startClock = clock(); do { for ( i = minIterations; i; --i ) { function( inputs_float32[ inputNumA ], inputs_float32[ inputNumB ] ); inputNumA = ( inputNumA + 1 ) & ( numInputs_float32 - 1 ); if ( inputNumA == 0 ) ++inputNumB; inputNumB = ( inputNumB + 1 ) & ( numInputs_float32 - 1 ); } count += minIterations; } while ( clock() - startClock < CLOCKS_PER_SEC ); inputNumA = 0; inputNumB = 0; startClock = clock(); for ( i = count; i; --i ) { function( inputs_float32[ inputNumA ], inputs_float32[ inputNumB ] ); inputNumA = ( inputNumA + 1 ) & ( numInputs_float32 - 1 ); if ( inputNumA == 0 ) ++inputNumB; inputNumB = ( inputNumB + 1 ) & ( numInputs_float32 - 1 ); } endClock = clock(); reportTime( count, endClock - startClock ); } static void time_abz_float32( float32 function( float32, float32 ) ) { clock_t startClock, endClock; int32 count, i; int8 inputNumA, inputNumB; count = 0; inputNumA = 0; inputNumB = 0; startClock = clock(); do { for ( i = minIterations; i; --i ) { function( inputs_float32[ inputNumA ], inputs_float32[ inputNumB ] ); inputNumA = ( inputNumA + 1 ) & ( numInputs_float32 - 1 ); if ( inputNumA == 0 ) ++inputNumB; inputNumB = ( inputNumB + 1 ) & ( numInputs_float32 - 1 ); } count += minIterations; } while ( clock() - startClock < CLOCKS_PER_SEC ); inputNumA = 0; inputNumB = 0; startClock = clock(); for ( i = count; i; --i ) { function( inputs_float32[ inputNumA ], inputs_float32[ inputNumB ] ); inputNumA = ( inputNumA + 1 ) & ( numInputs_float32 - 1 ); if ( inputNumA == 0 ) ++inputNumB; inputNumB = ( inputNumB + 1 ) & ( numInputs_float32 - 1 ); } endClock = clock(); reportTime( count, endClock - startClock ); } static const float32 inputs_float32_pos[ numInputs_float32 ] = { 0x4EFA0000, 0x41D0B328, 0x00000000, 0x3E69A31E, 0x2F803EFF, 0x3F800000, 0x17BF8000, 0x674A301A, 0x4E010003, 0x7EE3C75D, 0x3D803FE0, 0x3FFEFF00, 0x7981F800, 0x431FFFFC, 0x4100C000, 0x3D87EFFF, 0x4103FEFE, 0x3C000007, 0x3F01F7FF, 0x4E6C6B5C, 0x4187FFFE, 0x458B9F13, 0x4F88007F, 0x5F004007, 0x37FFD7FE, 0x7E8001FB, 0x46EFFBFF, 0x31C10000, 0x5B428661, 0x33F89B1F, 0x23BFEFFF, 0x537BFFBE }; static void time_az_float32_pos( float32 function( float32 ) ) { clock_t startClock, endClock; int32 count, i; int8 inputNum; count = 0; inputNum = 0; startClock = clock(); do { for ( i = minIterations; i; --i ) { function( inputs_float32_pos[ inputNum ] ); inputNum = ( inputNum + 1 ) & ( numInputs_float32 - 1 ); } count += minIterations; } while ( clock() - startClock < CLOCKS_PER_SEC ); inputNum = 0; startClock = clock(); for ( i = count; i; --i ) { function( inputs_float32_pos[ inputNum ] ); inputNum = ( inputNum + 1 ) & ( numInputs_float32 - 1 ); } endClock = clock(); reportTime( count, endClock - startClock ); } enum { numInputs_float64 = 32 }; static const float64 inputs_float64[ numInputs_float64 ] = { LIT64( 0x422FFFC008000000 ), LIT64( 0xB7E0000480000000 ), LIT64( 0xF3FD2546120B7935 ), LIT64( 0x3FF0000000000000 ), LIT64( 0xCE07F766F09588D6 ), LIT64( 0x8000000000000000 ), LIT64( 0x3FCE000400000000 ), LIT64( 0x8313B60F0032BED8 ), LIT64( 0xC1EFFFFFC0002000 ), LIT64( 0x3FB3C75D224F2B0F ), LIT64( 0x7FD00000004000FF ), LIT64( 0xA12FFF8000001FFF ), LIT64( 0x3EE0000000FE0000 ), LIT64( 0x0010000080000004 ), LIT64( 0x41CFFFFE00000020 ), LIT64( 0x40303FFFFFFFFFFD ), LIT64( 0x3FD000003FEFFFFF ), LIT64( 0xBFD0000010000000 ), LIT64( 0xB7FC6B5C16CA55CF ), LIT64( 0x413EEB940B9D1301 ), LIT64( 0xC7E00200001FFFFF ), LIT64( 0x47F00021FFFFFFFE ), LIT64( 0xBFFFFFFFF80000FF ), LIT64( 0xC07FFFFFE00FFFFF ), LIT64( 0x001497A63740C5E8 ), LIT64( 0xC4BFFFE0001FFFFF ), LIT64( 0x96FFDFFEFFFFFFFF ), LIT64( 0x403FC000000001FE ), LIT64( 0xFFD00000000001F6 ), LIT64( 0x0640400002000000 ), LIT64( 0x479CEE1E4F789FE0 ), LIT64( 0xC237FFFFFFFFFDFE ) }; static void time_a_float64_z_int32( int32 function( float64 ) ) { clock_t startClock, endClock; int32 count, i; int8 inputNum; count = 0; inputNum = 0; startClock = clock(); do { for ( i = minIterations; i; --i ) { function( inputs_float64[ inputNum ] ); inputNum = ( inputNum + 1 ) & ( numInputs_float64 - 1 ); } count += minIterations; } while ( clock() - startClock < CLOCKS_PER_SEC ); inputNum = 0; startClock = clock(); for ( i = count; i; --i ) { function( inputs_float64[ inputNum ] ); inputNum = ( inputNum + 1 ) & ( numInputs_float64 - 1 ); } endClock = clock(); reportTime( count, endClock - startClock ); } static void time_a_float64_z_int64( int64 function( float64 ) ) { clock_t startClock, endClock; int32 count, i; int8 inputNum; count = 0; inputNum = 0; startClock = clock(); do { for ( i = minIterations; i; --i ) { function( inputs_float64[ inputNum ] ); inputNum = ( inputNum + 1 ) & ( numInputs_float64 - 1 ); } count += minIterations; } while ( clock() - startClock < CLOCKS_PER_SEC ); inputNum = 0; startClock = clock(); for ( i = count; i; --i ) { function( inputs_float64[ inputNum ] ); inputNum = ( inputNum + 1 ) & ( numInputs_float64 - 1 ); } endClock = clock(); reportTime( count, endClock - startClock ); } static void time_a_float64_z_float32( float32 function( float64 ) ) { clock_t startClock, endClock; int32 count, i; int8 inputNum; count = 0; inputNum = 0; startClock = clock(); do { for ( i = minIterations; i; --i ) { function( inputs_float64[ inputNum ] ); inputNum = ( inputNum + 1 ) & ( numInputs_float64 - 1 ); } count += minIterations; } while ( clock() - startClock < CLOCKS_PER_SEC ); inputNum = 0; startClock = clock(); for ( i = count; i; --i ) { function( inputs_float64[ inputNum ] ); inputNum = ( inputNum + 1 ) & ( numInputs_float64 - 1 ); } endClock = clock(); reportTime( count, endClock - startClock ); } #ifdef FLOATX80 static void time_a_float64_z_floatx80( floatx80 function( float64 ) ) { clock_t startClock, endClock; int32 count, i; int8 inputNum; count = 0; inputNum = 0; startClock = clock(); do { for ( i = minIterations; i; --i ) { function( inputs_float64[ inputNum ] ); inputNum = ( inputNum + 1 ) & ( numInputs_float64 - 1 ); } count += minIterations; } while ( clock() - startClock < CLOCKS_PER_SEC ); inputNum = 0; startClock = clock(); for ( i = count; i; --i ) { function( inputs_float64[ inputNum ] ); inputNum = ( inputNum + 1 ) & ( numInputs_float64 - 1 ); } endClock = clock(); reportTime( count, endClock - startClock ); } #endif #ifdef FLOAT128 static void time_a_float64_z_float128( float128 function( float64 ) ) { clock_t startClock, endClock; int32 count, i; int8 inputNum; count = 0; inputNum = 0; startClock = clock(); do { for ( i = minIterations; i; --i ) { function( inputs_float64[ inputNum ] ); inputNum = ( inputNum + 1 ) & ( numInputs_float64 - 1 ); } count += minIterations; } while ( clock() - startClock < CLOCKS_PER_SEC ); inputNum = 0; startClock = clock(); for ( i = count; i; --i ) { function( inputs_float64[ inputNum ] ); inputNum = ( inputNum + 1 ) & ( numInputs_float64 - 1 ); } endClock = clock(); reportTime( count, endClock - startClock ); } #endif static void time_az_float64( float64 function( float64 ) ) { clock_t startClock, endClock; int32 count, i; int8 inputNum; count = 0; inputNum = 0; startClock = clock(); do { for ( i = minIterations; i; --i ) { function( inputs_float64[ inputNum ] ); inputNum = ( inputNum + 1 ) & ( numInputs_float64 - 1 ); } count += minIterations; } while ( clock() - startClock < CLOCKS_PER_SEC ); inputNum = 0; startClock = clock(); for ( i = count; i; --i ) { function( inputs_float64[ inputNum ] ); inputNum = ( inputNum + 1 ) & ( numInputs_float64 - 1 ); } endClock = clock(); reportTime( count, endClock - startClock ); } static void time_ab_float64_z_flag( flag function( float64, float64 ) ) { clock_t startClock, endClock; int32 count, i; int8 inputNumA, inputNumB; count = 0; inputNumA = 0; inputNumB = 0; startClock = clock(); do { for ( i = minIterations; i; --i ) { function( inputs_float64[ inputNumA ], inputs_float64[ inputNumB ] ); inputNumA = ( inputNumA + 1 ) & ( numInputs_float64 - 1 ); if ( inputNumA == 0 ) ++inputNumB; inputNumB = ( inputNumB + 1 ) & ( numInputs_float64 - 1 ); } count += minIterations; } while ( clock() - startClock < CLOCKS_PER_SEC ); inputNumA = 0; inputNumB = 0; startClock = clock(); for ( i = count; i; --i ) { function( inputs_float64[ inputNumA ], inputs_float64[ inputNumB ] ); inputNumA = ( inputNumA + 1 ) & ( numInputs_float64 - 1 ); if ( inputNumA == 0 ) ++inputNumB; inputNumB = ( inputNumB + 1 ) & ( numInputs_float64 - 1 ); } endClock = clock(); reportTime( count, endClock - startClock ); } static void time_abz_float64( float64 function( float64, float64 ) ) { clock_t startClock, endClock; int32 count, i; int8 inputNumA, inputNumB; count = 0; inputNumA = 0; inputNumB = 0; startClock = clock(); do { for ( i = minIterations; i; --i ) { function( inputs_float64[ inputNumA ], inputs_float64[ inputNumB ] ); inputNumA = ( inputNumA + 1 ) & ( numInputs_float64 - 1 ); if ( inputNumA == 0 ) ++inputNumB; inputNumB = ( inputNumB + 1 ) & ( numInputs_float64 - 1 ); } count += minIterations; } while ( clock() - startClock < CLOCKS_PER_SEC ); inputNumA = 0; inputNumB = 0; startClock = clock(); for ( i = count; i; --i ) { function( inputs_float64[ inputNumA ], inputs_float64[ inputNumB ] ); inputNumA = ( inputNumA + 1 ) & ( numInputs_float64 - 1 ); if ( inputNumA == 0 ) ++inputNumB; inputNumB = ( inputNumB + 1 ) & ( numInputs_float64 - 1 ); } endClock = clock(); reportTime( count, endClock - startClock ); } static const float64 inputs_float64_pos[ numInputs_float64 ] = { LIT64( 0x422FFFC008000000 ), LIT64( 0x37E0000480000000 ), LIT64( 0x73FD2546120B7935 ), LIT64( 0x3FF0000000000000 ), LIT64( 0x4E07F766F09588D6 ), LIT64( 0x0000000000000000 ), LIT64( 0x3FCE000400000000 ), LIT64( 0x0313B60F0032BED8 ), LIT64( 0x41EFFFFFC0002000 ), LIT64( 0x3FB3C75D224F2B0F ), LIT64( 0x7FD00000004000FF ), LIT64( 0x212FFF8000001FFF ), LIT64( 0x3EE0000000FE0000 ), LIT64( 0x0010000080000004 ), LIT64( 0x41CFFFFE00000020 ), LIT64( 0x40303FFFFFFFFFFD ), LIT64( 0x3FD000003FEFFFFF ), LIT64( 0x3FD0000010000000 ), LIT64( 0x37FC6B5C16CA55CF ), LIT64( 0x413EEB940B9D1301 ), LIT64( 0x47E00200001FFFFF ), LIT64( 0x47F00021FFFFFFFE ), LIT64( 0x3FFFFFFFF80000FF ), LIT64( 0x407FFFFFE00FFFFF ), LIT64( 0x001497A63740C5E8 ), LIT64( 0x44BFFFE0001FFFFF ), LIT64( 0x16FFDFFEFFFFFFFF ), LIT64( 0x403FC000000001FE ), LIT64( 0x7FD00000000001F6 ), LIT64( 0x0640400002000000 ), LIT64( 0x479CEE1E4F789FE0 ), LIT64( 0x4237FFFFFFFFFDFE ) }; static void time_az_float64_pos( float64 function( float64 ) ) { clock_t startClock, endClock; int32 count, i; int8 inputNum; count = 0; inputNum = 0; startClock = clock(); do { for ( i = minIterations; i; --i ) { function( inputs_float64_pos[ inputNum ] ); inputNum = ( inputNum + 1 ) & ( numInputs_float64 - 1 ); } count += minIterations; } while ( clock() - startClock < CLOCKS_PER_SEC ); inputNum = 0; startClock = clock(); for ( i = count; i; --i ) { function( inputs_float64_pos[ inputNum ] ); inputNum = ( inputNum + 1 ) & ( numInputs_float64 - 1 ); } endClock = clock(); reportTime( count, endClock - startClock ); } #ifdef FLOATX80 enum { numInputs_floatx80 = 32 }; static const struct { bits16 high; bits64 low; } inputs_floatx80[ numInputs_floatx80 ] = { { 0xC03F, LIT64( 0xA9BE15A19C1E8B62 ) }, { 0x8000, LIT64( 0x0000000000000000 ) }, { 0x75A8, LIT64( 0xE59591E4788957A5 ) }, { 0xBFFF, LIT64( 0xFFF0000000000040 ) }, { 0x0CD8, LIT64( 0xFC000000000007FE ) }, { 0x43BA, LIT64( 0x99A4000000000000 ) }, { 0x3FFF, LIT64( 0x8000000000000000 ) }, { 0x4081, LIT64( 0x94FBF1BCEB5545F0 ) }, { 0x403E, LIT64( 0xFFF0000000002000 ) }, { 0x3FFE, LIT64( 0xC860E3C75D224F28 ) }, { 0x407E, LIT64( 0xFC00000FFFFFFFFE ) }, { 0x737A, LIT64( 0x800000007FFDFFFE ) }, { 0x4044, LIT64( 0xFFFFFF80000FFFFF ) }, { 0xBBFE, LIT64( 0x8000040000001FFE ) }, { 0xC002, LIT64( 0xFF80000000000020 ) }, { 0xDE8D, LIT64( 0xFFFFFFFFFFE00004 ) }, { 0xC004, LIT64( 0x8000000000003FFB ) }, { 0x407F, LIT64( 0x800000000003FFFE ) }, { 0xC000, LIT64( 0xA459EE6A5C16CA55 ) }, { 0x8003, LIT64( 0xC42CBF7399AEEB94 ) }, { 0xBF7F, LIT64( 0xF800000000000006 ) }, { 0xC07F, LIT64( 0xBF56BE8871F28FEA ) }, { 0xC07E, LIT64( 0xFFFF77FFFFFFFFFE ) }, { 0xADC9, LIT64( 0x8000000FFFFFFFDE ) }, { 0xC001, LIT64( 0xEFF7FFFFFFFFFFFF ) }, { 0x4001, LIT64( 0xBE84F30125C497A6 ) }, { 0xC06B, LIT64( 0xEFFFFFFFFFFFFFFF ) }, { 0x4080, LIT64( 0xFFFFFFFFBFFFFFFF ) }, { 0x87E9, LIT64( 0x81FFFFFFFFFFFBFF ) }, { 0xA63F, LIT64( 0x801FFFFFFEFFFFFE ) }, { 0x403C, LIT64( 0x801FFFFFFFF7FFFF ) }, { 0x4018, LIT64( 0x8000000000080003 ) } }; static void time_a_floatx80_z_int32( int32 function( floatx80 ) ) { clock_t startClock, endClock; int32 count, i; int8 inputNum; floatx80 a; count = 0; inputNum = 0; startClock = clock(); do { for ( i = minIterations; i; --i ) { a.low = inputs_floatx80[ inputNum ].low; a.high = inputs_floatx80[ inputNum ].high; function( a ); inputNum = ( inputNum + 1 ) & ( numInputs_floatx80 - 1 ); } count += minIterations; } while ( clock() - startClock < CLOCKS_PER_SEC ); inputNum = 0; startClock = clock(); for ( i = count; i; --i ) { a.low = inputs_floatx80[ inputNum ].low; a.high = inputs_floatx80[ inputNum ].high; function( a ); inputNum = ( inputNum + 1 ) & ( numInputs_floatx80 - 1 ); } endClock = clock(); reportTime( count, endClock - startClock ); } static void time_a_floatx80_z_int64( int64 function( floatx80 ) ) { clock_t startClock, endClock; int32 count, i; int8 inputNum; floatx80 a; count = 0; inputNum = 0; startClock = clock(); do { for ( i = minIterations; i; --i ) { a.low = inputs_floatx80[ inputNum ].low; a.high = inputs_floatx80[ inputNum ].high; function( a ); inputNum = ( inputNum + 1 ) & ( numInputs_floatx80 - 1 ); } count += minIterations; } while ( clock() - startClock < CLOCKS_PER_SEC ); inputNum = 0; startClock = clock(); for ( i = count; i; --i ) { a.low = inputs_floatx80[ inputNum ].low; a.high = inputs_floatx80[ inputNum ].high; function( a ); inputNum = ( inputNum + 1 ) & ( numInputs_floatx80 - 1 ); } endClock = clock(); reportTime( count, endClock - startClock ); } static void time_a_floatx80_z_float32( float32 function( floatx80 ) ) { clock_t startClock, endClock; int32 count, i; int8 inputNum; floatx80 a; count = 0; inputNum = 0; startClock = clock(); do { for ( i = minIterations; i; --i ) { a.low = inputs_floatx80[ inputNum ].low; a.high = inputs_floatx80[ inputNum ].high; function( a ); inputNum = ( inputNum + 1 ) & ( numInputs_floatx80 - 1 ); } count += minIterations; } while ( clock() - startClock < CLOCKS_PER_SEC ); inputNum = 0; startClock = clock(); for ( i = count; i; --i ) { a.low = inputs_floatx80[ inputNum ].low; a.high = inputs_floatx80[ inputNum ].high; function( a ); inputNum = ( inputNum + 1 ) & ( numInputs_floatx80 - 1 ); } endClock = clock(); reportTime( count, endClock - startClock ); } static void time_a_floatx80_z_float64( float64 function( floatx80 ) ) { clock_t startClock, endClock; int32 count, i; int8 inputNum; floatx80 a; count = 0; inputNum = 0; startClock = clock(); do { for ( i = minIterations; i; --i ) { a.low = inputs_floatx80[ inputNum ].low; a.high = inputs_floatx80[ inputNum ].high; function( a ); inputNum = ( inputNum + 1 ) & ( numInputs_floatx80 - 1 ); } count += minIterations; } while ( clock() - startClock < CLOCKS_PER_SEC ); inputNum = 0; startClock = clock(); for ( i = count; i; --i ) { a.low = inputs_floatx80[ inputNum ].low; a.high = inputs_floatx80[ inputNum ].high; function( a ); inputNum = ( inputNum + 1 ) & ( numInputs_floatx80 - 1 ); } endClock = clock(); reportTime( count, endClock - startClock ); } #ifdef FLOAT128 static void time_a_floatx80_z_float128( float128 function( floatx80 ) ) { clock_t startClock, endClock; int32 count, i; int8 inputNum; floatx80 a; count = 0; inputNum = 0; startClock = clock(); do { for ( i = minIterations; i; --i ) { a.low = inputs_floatx80[ inputNum ].low; a.high = inputs_floatx80[ inputNum ].high; function( a ); inputNum = ( inputNum + 1 ) & ( numInputs_floatx80 - 1 ); } count += minIterations; } while ( clock() - startClock < CLOCKS_PER_SEC ); inputNum = 0; startClock = clock(); for ( i = count; i; --i ) { a.low = inputs_floatx80[ inputNum ].low; a.high = inputs_floatx80[ inputNum ].high; function( a ); inputNum = ( inputNum + 1 ) & ( numInputs_floatx80 - 1 ); } endClock = clock(); reportTime( count, endClock - startClock ); } #endif static void time_az_floatx80( floatx80 function( floatx80 ) ) { clock_t startClock, endClock; int32 count, i; int8 inputNum; floatx80 a; count = 0; inputNum = 0; startClock = clock(); do { for ( i = minIterations; i; --i ) { a.low = inputs_floatx80[ inputNum ].low; a.high = inputs_floatx80[ inputNum ].high; function( a ); inputNum = ( inputNum + 1 ) & ( numInputs_floatx80 - 1 ); } count += minIterations; } while ( clock() - startClock < CLOCKS_PER_SEC ); inputNum = 0; startClock = clock(); for ( i = count; i; --i ) { a.low = inputs_floatx80[ inputNum ].low; a.high = inputs_floatx80[ inputNum ].high; function( a ); inputNum = ( inputNum + 1 ) & ( numInputs_floatx80 - 1 ); } endClock = clock(); reportTime( count, endClock - startClock ); } static void time_ab_floatx80_z_flag( flag function( floatx80, floatx80 ) ) { clock_t startClock, endClock; int32 count, i; int8 inputNumA, inputNumB; floatx80 a, b; count = 0; inputNumA = 0; inputNumB = 0; startClock = clock(); do { for ( i = minIterations; i; --i ) { a.low = inputs_floatx80[ inputNumA ].low; a.high = inputs_floatx80[ inputNumA ].high; b.low = inputs_floatx80[ inputNumB ].low; b.high = inputs_floatx80[ inputNumB ].high; function( a, b ); inputNumA = ( inputNumA + 1 ) & ( numInputs_floatx80 - 1 ); if ( inputNumA == 0 ) ++inputNumB; inputNumB = ( inputNumB + 1 ) & ( numInputs_floatx80 - 1 ); } count += minIterations; } while ( clock() - startClock < CLOCKS_PER_SEC ); inputNumA = 0; inputNumB = 0; startClock = clock(); for ( i = count; i; --i ) { a.low = inputs_floatx80[ inputNumA ].low; a.high = inputs_floatx80[ inputNumA ].high; b.low = inputs_floatx80[ inputNumB ].low; b.high = inputs_floatx80[ inputNumB ].high; function( a, b ); inputNumA = ( inputNumA + 1 ) & ( numInputs_floatx80 - 1 ); if ( inputNumA == 0 ) ++inputNumB; inputNumB = ( inputNumB + 1 ) & ( numInputs_floatx80 - 1 ); } endClock = clock(); reportTime( count, endClock - startClock ); } static void time_abz_floatx80( floatx80 function( floatx80, floatx80 ) ) { clock_t startClock, endClock; int32 count, i; int8 inputNumA, inputNumB; floatx80 a, b; count = 0; inputNumA = 0; inputNumB = 0; startClock = clock(); do { for ( i = minIterations; i; --i ) { a.low = inputs_floatx80[ inputNumA ].low; a.high = inputs_floatx80[ inputNumA ].high; b.low = inputs_floatx80[ inputNumB ].low; b.high = inputs_floatx80[ inputNumB ].high; function( a, b ); inputNumA = ( inputNumA + 1 ) & ( numInputs_floatx80 - 1 ); if ( inputNumA == 0 ) ++inputNumB; inputNumB = ( inputNumB + 1 ) & ( numInputs_floatx80 - 1 ); } count += minIterations; } while ( clock() - startClock < CLOCKS_PER_SEC ); inputNumA = 0; inputNumB = 0; startClock = clock(); for ( i = count; i; --i ) { a.low = inputs_floatx80[ inputNumA ].low; a.high = inputs_floatx80[ inputNumA ].high; b.low = inputs_floatx80[ inputNumB ].low; b.high = inputs_floatx80[ inputNumB ].high; function( a, b ); inputNumA = ( inputNumA + 1 ) & ( numInputs_floatx80 - 1 ); if ( inputNumA == 0 ) ++inputNumB; inputNumB = ( inputNumB + 1 ) & ( numInputs_floatx80 - 1 ); } endClock = clock(); reportTime( count, endClock - startClock ); } static const struct { bits16 high; bits64 low; } inputs_floatx80_pos[ numInputs_floatx80 ] = { { 0x403F, LIT64( 0xA9BE15A19C1E8B62 ) }, { 0x0000, LIT64( 0x0000000000000000 ) }, { 0x75A8, LIT64( 0xE59591E4788957A5 ) }, { 0x3FFF, LIT64( 0xFFF0000000000040 ) }, { 0x0CD8, LIT64( 0xFC000000000007FE ) }, { 0x43BA, LIT64( 0x99A4000000000000 ) }, { 0x3FFF, LIT64( 0x8000000000000000 ) }, { 0x4081, LIT64( 0x94FBF1BCEB5545F0 ) }, { 0x403E, LIT64( 0xFFF0000000002000 ) }, { 0x3FFE, LIT64( 0xC860E3C75D224F28 ) }, { 0x407E, LIT64( 0xFC00000FFFFFFFFE ) }, { 0x737A, LIT64( 0x800000007FFDFFFE ) }, { 0x4044, LIT64( 0xFFFFFF80000FFFFF ) }, { 0x3BFE, LIT64( 0x8000040000001FFE ) }, { 0x4002, LIT64( 0xFF80000000000020 ) }, { 0x5E8D, LIT64( 0xFFFFFFFFFFE00004 ) }, { 0x4004, LIT64( 0x8000000000003FFB ) }, { 0x407F, LIT64( 0x800000000003FFFE ) }, { 0x4000, LIT64( 0xA459EE6A5C16CA55 ) }, { 0x0003, LIT64( 0xC42CBF7399AEEB94 ) }, { 0x3F7F, LIT64( 0xF800000000000006 ) }, { 0x407F, LIT64( 0xBF56BE8871F28FEA ) }, { 0x407E, LIT64( 0xFFFF77FFFFFFFFFE ) }, { 0x2DC9, LIT64( 0x8000000FFFFFFFDE ) }, { 0x4001, LIT64( 0xEFF7FFFFFFFFFFFF ) }, { 0x4001, LIT64( 0xBE84F30125C497A6 ) }, { 0x406B, LIT64( 0xEFFFFFFFFFFFFFFF ) }, { 0x4080, LIT64( 0xFFFFFFFFBFFFFFFF ) }, { 0x07E9, LIT64( 0x81FFFFFFFFFFFBFF ) }, { 0x263F, LIT64( 0x801FFFFFFEFFFFFE ) }, { 0x403C, LIT64( 0x801FFFFFFFF7FFFF ) }, { 0x4018, LIT64( 0x8000000000080003 ) } }; static void time_az_floatx80_pos( floatx80 function( floatx80 ) ) { clock_t startClock, endClock; int32 count, i; int8 inputNum; floatx80 a; count = 0; inputNum = 0; startClock = clock(); do { for ( i = minIterations; i; --i ) { a.low = inputs_floatx80_pos[ inputNum ].low; a.high = inputs_floatx80_pos[ inputNum ].high; function( a ); inputNum = ( inputNum + 1 ) & ( numInputs_floatx80 - 1 ); } count += minIterations; } while ( clock() - startClock < CLOCKS_PER_SEC ); inputNum = 0; startClock = clock(); for ( i = count; i; --i ) { a.low = inputs_floatx80_pos[ inputNum ].low; a.high = inputs_floatx80_pos[ inputNum ].high; function( a ); inputNum = ( inputNum + 1 ) & ( numInputs_floatx80 - 1 ); } endClock = clock(); reportTime( count, endClock - startClock ); } #endif #ifdef FLOAT128 enum { numInputs_float128 = 32 }; static const struct { bits64 high, low; } inputs_float128[ numInputs_float128 ] = { { LIT64( 0x3FDA200000100000 ), LIT64( 0x0000000000000000 ) }, { LIT64( 0x3FFF000000000000 ), LIT64( 0x0000000000000000 ) }, { LIT64( 0x85F14776190C8306 ), LIT64( 0xD8715F4E3D54BB92 ) }, { LIT64( 0xF2B00000007FFFFF ), LIT64( 0xFFFFFFFFFFF7FFFF ) }, { LIT64( 0x8000000000000000 ), LIT64( 0x0000000000000000 ) }, { LIT64( 0xBFFFFFFFFFE00000 ), LIT64( 0x0000008000000000 ) }, { LIT64( 0x407F1719CE722F3E ), LIT64( 0xDA6B3FE5FF29425B ) }, { LIT64( 0x43FFFF8000000000 ), LIT64( 0x0000000000400000 ) }, { LIT64( 0x401E000000000100 ), LIT64( 0x0000000000002000 ) }, { LIT64( 0x3FFED71DACDA8E47 ), LIT64( 0x4860E3C75D224F28 ) }, { LIT64( 0xBF7ECFC1E90647D1 ), LIT64( 0x7A124FE55623EE44 ) }, { LIT64( 0x0DF7007FFFFFFFFF ), LIT64( 0xFFFFFFFFEFFFFFFF ) }, { LIT64( 0x3FE5FFEFFFFFFFFF ), LIT64( 0xFFFFFFFFFFFFEFFF ) }, { LIT64( 0x403FFFFFFFFFFFFF ), LIT64( 0xFFFFFFFFFFFFFBFE ) }, { LIT64( 0xBFFB2FBF7399AFEB ), LIT64( 0xA459EE6A5C16CA55 ) }, { LIT64( 0xBDB8FFFFFFFFFFFC ), LIT64( 0x0000000000000400 ) }, { LIT64( 0x3FC8FFDFFFFFFFFF ), LIT64( 0xFFFFFFFFF0000000 ) }, { LIT64( 0x3FFBFFFFFFDFFFFF ), LIT64( 0xFFF8000000000000 ) }, { LIT64( 0x407043C11737BE84 ), LIT64( 0xDDD58212ADC937F4 ) }, { LIT64( 0x8001000000000000 ), LIT64( 0x0000001000000001 ) }, { LIT64( 0xC036FFFFFFFFFFFF ), LIT64( 0xFE40000000000000 ) }, { LIT64( 0x4002FFFFFE000002 ), LIT64( 0x0000000000000000 ) }, { LIT64( 0x4000C3FEDE897773 ), LIT64( 0x326AC4FD8EFBE6DC ) }, { LIT64( 0xBFFF0000000FFFFF ), LIT64( 0xFFFFFE0000000000 ) }, { LIT64( 0x62C3E502146E426D ), LIT64( 0x43F3CAA0DC7DF1A0 ) }, { LIT64( 0xB5CBD32E52BB570E ), LIT64( 0xBCC477CB11C6236C ) }, { LIT64( 0xE228FFFFFFC00000 ), LIT64( 0x0000000000000000 ) }, { LIT64( 0x3F80000000000000 ), LIT64( 0x0000000080000008 ) }, { LIT64( 0xC1AFFFDFFFFFFFFF ), LIT64( 0xFFFC000000000000 ) }, { LIT64( 0xC96F000000000000 ), LIT64( 0x00000001FFFBFFFF ) }, { LIT64( 0x3DE09BFE7923A338 ), LIT64( 0xBCC8FBBD7CEC1F4F ) }, { LIT64( 0x401CFFFFFFFFFFFF ), LIT64( 0xFFFFFFFEFFFFFF80 ) } }; static void time_a_float128_z_int32( int32 function( float128 ) ) { clock_t startClock, endClock; int32 count, i; int8 inputNum; float128 a; count = 0; inputNum = 0; startClock = clock(); do { for ( i = minIterations; i; --i ) { a.low = inputs_float128[ inputNum ].low; a.high = inputs_float128[ inputNum ].high; function( a ); inputNum = ( inputNum + 1 ) & ( numInputs_float128 - 1 ); } count += minIterations; } while ( clock() - startClock < CLOCKS_PER_SEC ); inputNum = 0; startClock = clock(); for ( i = count; i; --i ) { a.low = inputs_float128[ inputNum ].low; a.high = inputs_float128[ inputNum ].high; function( a ); inputNum = ( inputNum + 1 ) & ( numInputs_float128 - 1 ); } endClock = clock(); reportTime( count, endClock - startClock ); } static void time_a_float128_z_int64( int64 function( float128 ) ) { clock_t startClock, endClock; int32 count, i; int8 inputNum; float128 a; count = 0; inputNum = 0; startClock = clock(); do { for ( i = minIterations; i; --i ) { a.low = inputs_float128[ inputNum ].low; a.high = inputs_float128[ inputNum ].high; function( a ); inputNum = ( inputNum + 1 ) & ( numInputs_float128 - 1 ); } count += minIterations; } while ( clock() - startClock < CLOCKS_PER_SEC ); inputNum = 0; startClock = clock(); for ( i = count; i; --i ) { a.low = inputs_float128[ inputNum ].low; a.high = inputs_float128[ inputNum ].high; function( a ); inputNum = ( inputNum + 1 ) & ( numInputs_float128 - 1 ); } endClock = clock(); reportTime( count, endClock - startClock ); } static void time_a_float128_z_float32( float32 function( float128 ) ) { clock_t startClock, endClock; int32 count, i; int8 inputNum; float128 a; count = 0; inputNum = 0; startClock = clock(); do { for ( i = minIterations; i; --i ) { a.low = inputs_float128[ inputNum ].low; a.high = inputs_float128[ inputNum ].high; function( a ); inputNum = ( inputNum + 1 ) & ( numInputs_float128 - 1 ); } count += minIterations; } while ( clock() - startClock < CLOCKS_PER_SEC ); inputNum = 0; startClock = clock(); for ( i = count; i; --i ) { a.low = inputs_float128[ inputNum ].low; a.high = inputs_float128[ inputNum ].high; function( a ); inputNum = ( inputNum + 1 ) & ( numInputs_float128 - 1 ); } endClock = clock(); reportTime( count, endClock - startClock ); } static void time_a_float128_z_float64( float64 function( float128 ) ) { clock_t startClock, endClock; int32 count, i; int8 inputNum; float128 a; count = 0; inputNum = 0; startClock = clock(); do { for ( i = minIterations; i; --i ) { a.low = inputs_float128[ inputNum ].low; a.high = inputs_float128[ inputNum ].high; function( a ); inputNum = ( inputNum + 1 ) & ( numInputs_float128 - 1 ); } count += minIterations; } while ( clock() - startClock < CLOCKS_PER_SEC ); inputNum = 0; startClock = clock(); for ( i = count; i; --i ) { a.low = inputs_float128[ inputNum ].low; a.high = inputs_float128[ inputNum ].high; function( a ); inputNum = ( inputNum + 1 ) & ( numInputs_float128 - 1 ); } endClock = clock(); reportTime( count, endClock - startClock ); } #ifdef FLOATX80 static void time_a_float128_z_floatx80( floatx80 function( float128 ) ) { clock_t startClock, endClock; int32 count, i; int8 inputNum; float128 a; count = 0; inputNum = 0; startClock = clock(); do { for ( i = minIterations; i; --i ) { a.low = inputs_float128[ inputNum ].low; a.high = inputs_float128[ inputNum ].high; function( a ); inputNum = ( inputNum + 1 ) & ( numInputs_float128 - 1 ); } count += minIterations; } while ( clock() - startClock < CLOCKS_PER_SEC ); inputNum = 0; startClock = clock(); for ( i = count; i; --i ) { a.low = inputs_float128[ inputNum ].low; a.high = inputs_float128[ inputNum ].high; function( a ); inputNum = ( inputNum + 1 ) & ( numInputs_float128 - 1 ); } endClock = clock(); reportTime( count, endClock - startClock ); } #endif static void time_az_float128( float128 function( float128 ) ) { clock_t startClock, endClock; int32 count, i; int8 inputNum; float128 a; count = 0; inputNum = 0; startClock = clock(); do { for ( i = minIterations; i; --i ) { a.low = inputs_float128[ inputNum ].low; a.high = inputs_float128[ inputNum ].high; function( a ); inputNum = ( inputNum + 1 ) & ( numInputs_float128 - 1 ); } count += minIterations; } while ( clock() - startClock < CLOCKS_PER_SEC ); inputNum = 0; startClock = clock(); for ( i = count; i; --i ) { a.low = inputs_float128[ inputNum ].low; a.high = inputs_float128[ inputNum ].high; function( a ); inputNum = ( inputNum + 1 ) & ( numInputs_float128 - 1 ); } endClock = clock(); reportTime( count, endClock - startClock ); } static void time_ab_float128_z_flag( flag function( float128, float128 ) ) { clock_t startClock, endClock; int32 count, i; int8 inputNumA, inputNumB; float128 a, b; count = 0; inputNumA = 0; inputNumB = 0; startClock = clock(); do { for ( i = minIterations; i; --i ) { a.low = inputs_float128[ inputNumA ].low; a.high = inputs_float128[ inputNumA ].high; b.low = inputs_float128[ inputNumB ].low; b.high = inputs_float128[ inputNumB ].high; function( a, b ); inputNumA = ( inputNumA + 1 ) & ( numInputs_float128 - 1 ); if ( inputNumA == 0 ) ++inputNumB; inputNumB = ( inputNumB + 1 ) & ( numInputs_float128 - 1 ); } count += minIterations; } while ( clock() - startClock < CLOCKS_PER_SEC ); inputNumA = 0; inputNumB = 0; startClock = clock(); for ( i = count; i; --i ) { a.low = inputs_float128[ inputNumA ].low; a.high = inputs_float128[ inputNumA ].high; b.low = inputs_float128[ inputNumB ].low; b.high = inputs_float128[ inputNumB ].high; function( a, b ); inputNumA = ( inputNumA + 1 ) & ( numInputs_float128 - 1 ); if ( inputNumA == 0 ) ++inputNumB; inputNumB = ( inputNumB + 1 ) & ( numInputs_float128 - 1 ); } endClock = clock(); reportTime( count, endClock - startClock ); } static void time_abz_float128( float128 function( float128, float128 ) ) { clock_t startClock, endClock; int32 count, i; int8 inputNumA, inputNumB; float128 a, b; count = 0; inputNumA = 0; inputNumB = 0; startClock = clock(); do { for ( i = minIterations; i; --i ) { a.low = inputs_float128[ inputNumA ].low; a.high = inputs_float128[ inputNumA ].high; b.low = inputs_float128[ inputNumB ].low; b.high = inputs_float128[ inputNumB ].high; function( a, b ); inputNumA = ( inputNumA + 1 ) & ( numInputs_float128 - 1 ); if ( inputNumA == 0 ) ++inputNumB; inputNumB = ( inputNumB + 1 ) & ( numInputs_float128 - 1 ); } count += minIterations; } while ( clock() - startClock < CLOCKS_PER_SEC ); inputNumA = 0; inputNumB = 0; startClock = clock(); for ( i = count; i; --i ) { a.low = inputs_float128[ inputNumA ].low; a.high = inputs_float128[ inputNumA ].high; b.low = inputs_float128[ inputNumB ].low; b.high = inputs_float128[ inputNumB ].high; function( a, b ); inputNumA = ( inputNumA + 1 ) & ( numInputs_float128 - 1 ); if ( inputNumA == 0 ) ++inputNumB; inputNumB = ( inputNumB + 1 ) & ( numInputs_float128 - 1 ); } endClock = clock(); reportTime( count, endClock - startClock ); } static const struct { bits64 high, low; } inputs_float128_pos[ numInputs_float128 ] = { { LIT64( 0x3FDA200000100000 ), LIT64( 0x0000000000000000 ) }, { LIT64( 0x3FFF000000000000 ), LIT64( 0x0000000000000000 ) }, { LIT64( 0x05F14776190C8306 ), LIT64( 0xD8715F4E3D54BB92 ) }, { LIT64( 0x72B00000007FFFFF ), LIT64( 0xFFFFFFFFFFF7FFFF ) }, { LIT64( 0x0000000000000000 ), LIT64( 0x0000000000000000 ) }, { LIT64( 0x3FFFFFFFFFE00000 ), LIT64( 0x0000008000000000 ) }, { LIT64( 0x407F1719CE722F3E ), LIT64( 0xDA6B3FE5FF29425B ) }, { LIT64( 0x43FFFF8000000000 ), LIT64( 0x0000000000400000 ) }, { LIT64( 0x401E000000000100 ), LIT64( 0x0000000000002000 ) }, { LIT64( 0x3FFED71DACDA8E47 ), LIT64( 0x4860E3C75D224F28 ) }, { LIT64( 0x3F7ECFC1E90647D1 ), LIT64( 0x7A124FE55623EE44 ) }, { LIT64( 0x0DF7007FFFFFFFFF ), LIT64( 0xFFFFFFFFEFFFFFFF ) }, { LIT64( 0x3FE5FFEFFFFFFFFF ), LIT64( 0xFFFFFFFFFFFFEFFF ) }, { LIT64( 0x403FFFFFFFFFFFFF ), LIT64( 0xFFFFFFFFFFFFFBFE ) }, { LIT64( 0x3FFB2FBF7399AFEB ), LIT64( 0xA459EE6A5C16CA55 ) }, { LIT64( 0x3DB8FFFFFFFFFFFC ), LIT64( 0x0000000000000400 ) }, { LIT64( 0x3FC8FFDFFFFFFFFF ), LIT64( 0xFFFFFFFFF0000000 ) }, { LIT64( 0x3FFBFFFFFFDFFFFF ), LIT64( 0xFFF8000000000000 ) }, { LIT64( 0x407043C11737BE84 ), LIT64( 0xDDD58212ADC937F4 ) }, { LIT64( 0x0001000000000000 ), LIT64( 0x0000001000000001 ) }, { LIT64( 0x4036FFFFFFFFFFFF ), LIT64( 0xFE40000000000000 ) }, { LIT64( 0x4002FFFFFE000002 ), LIT64( 0x0000000000000000 ) }, { LIT64( 0x4000C3FEDE897773 ), LIT64( 0x326AC4FD8EFBE6DC ) }, { LIT64( 0x3FFF0000000FFFFF ), LIT64( 0xFFFFFE0000000000 ) }, { LIT64( 0x62C3E502146E426D ), LIT64( 0x43F3CAA0DC7DF1A0 ) }, { LIT64( 0x35CBD32E52BB570E ), LIT64( 0xBCC477CB11C6236C ) }, { LIT64( 0x6228FFFFFFC00000 ), LIT64( 0x0000000000000000 ) }, { LIT64( 0x3F80000000000000 ), LIT64( 0x0000000080000008 ) }, { LIT64( 0x41AFFFDFFFFFFFFF ), LIT64( 0xFFFC000000000000 ) }, { LIT64( 0x496F000000000000 ), LIT64( 0x00000001FFFBFFFF ) }, { LIT64( 0x3DE09BFE7923A338 ), LIT64( 0xBCC8FBBD7CEC1F4F ) }, { LIT64( 0x401CFFFFFFFFFFFF ), LIT64( 0xFFFFFFFEFFFFFF80 ) } }; static void time_az_float128_pos( float128 function( float128 ) ) { clock_t startClock, endClock; int32 count, i; int8 inputNum; float128 a; count = 0; inputNum = 0; startClock = clock(); do { for ( i = minIterations; i; --i ) { a.low = inputs_float128_pos[ inputNum ].low; a.high = inputs_float128_pos[ inputNum ].high; function( a ); inputNum = ( inputNum + 1 ) & ( numInputs_float128 - 1 ); } count += minIterations; } while ( clock() - startClock < CLOCKS_PER_SEC ); inputNum = 0; startClock = clock(); for ( i = count; i; --i ) { a.low = inputs_float128_pos[ inputNum ].low; a.high = inputs_float128_pos[ inputNum ].high; function( a ); inputNum = ( inputNum + 1 ) & ( numInputs_float128 - 1 ); } endClock = clock(); reportTime( count, endClock - startClock ); } #endif enum { INT32_TO_FLOAT32 = 1, INT32_TO_FLOAT64, #ifdef FLOATX80 INT32_TO_FLOATX80, #endif #ifdef FLOAT128 INT32_TO_FLOAT128, #endif INT64_TO_FLOAT32, INT64_TO_FLOAT64, #ifdef FLOATX80 INT64_TO_FLOATX80, #endif #ifdef FLOAT128 INT64_TO_FLOAT128, #endif FLOAT32_TO_INT32, FLOAT32_TO_INT32_ROUND_TO_ZERO, FLOAT32_TO_INT64, FLOAT32_TO_INT64_ROUND_TO_ZERO, FLOAT32_TO_FLOAT64, #ifdef FLOATX80 FLOAT32_TO_FLOATX80, #endif #ifdef FLOAT128 FLOAT32_TO_FLOAT128, #endif FLOAT32_ROUND_TO_INT, FLOAT32_ADD, FLOAT32_SUB, FLOAT32_MUL, FLOAT32_DIV, FLOAT32_REM, FLOAT32_SQRT, FLOAT32_EQ, FLOAT32_LE, FLOAT32_LT, FLOAT32_EQ_SIGNALING, FLOAT32_LE_QUIET, FLOAT32_LT_QUIET, FLOAT64_TO_INT32, FLOAT64_TO_INT32_ROUND_TO_ZERO, FLOAT64_TO_INT64, FLOAT64_TO_INT64_ROUND_TO_ZERO, FLOAT64_TO_FLOAT32, #ifdef FLOATX80 FLOAT64_TO_FLOATX80, #endif #ifdef FLOAT128 FLOAT64_TO_FLOAT128, #endif FLOAT64_ROUND_TO_INT, FLOAT64_ADD, FLOAT64_SUB, FLOAT64_MUL, FLOAT64_DIV, FLOAT64_REM, FLOAT64_SQRT, FLOAT64_EQ, FLOAT64_LE, FLOAT64_LT, FLOAT64_EQ_SIGNALING, FLOAT64_LE_QUIET, FLOAT64_LT_QUIET, #ifdef FLOATX80 FLOATX80_TO_INT32, FLOATX80_TO_INT32_ROUND_TO_ZERO, FLOATX80_TO_INT64, FLOATX80_TO_INT64_ROUND_TO_ZERO, FLOATX80_TO_FLOAT32, FLOATX80_TO_FLOAT64, #ifdef FLOAT128 FLOATX80_TO_FLOAT128, #endif FLOATX80_ROUND_TO_INT, FLOATX80_ADD, FLOATX80_SUB, FLOATX80_MUL, FLOATX80_DIV, FLOATX80_REM, FLOATX80_SQRT, FLOATX80_EQ, FLOATX80_LE, FLOATX80_LT, FLOATX80_EQ_SIGNALING, FLOATX80_LE_QUIET, FLOATX80_LT_QUIET, #endif #ifdef FLOAT128 FLOAT128_TO_INT32, FLOAT128_TO_INT32_ROUND_TO_ZERO, FLOAT128_TO_INT64, FLOAT128_TO_INT64_ROUND_TO_ZERO, FLOAT128_TO_FLOAT32, FLOAT128_TO_FLOAT64, #ifdef FLOATX80 FLOAT128_TO_FLOATX80, #endif FLOAT128_ROUND_TO_INT, FLOAT128_ADD, FLOAT128_SUB, FLOAT128_MUL, FLOAT128_DIV, FLOAT128_REM, FLOAT128_SQRT, FLOAT128_EQ, FLOAT128_LE, FLOAT128_LT, FLOAT128_EQ_SIGNALING, FLOAT128_LE_QUIET, FLOAT128_LT_QUIET, #endif NUM_FUNCTIONS }; static struct { char *name; int8 numInputs; flag roundingPrecision, roundingMode; flag tininessMode, tininessModeAtReducedPrecision; } functions[ NUM_FUNCTIONS ] = { { 0, 0, 0, 0, 0, 0 }, { "int32_to_float32", 1, FALSE, TRUE, FALSE, FALSE }, { "int32_to_float64", 1, FALSE, FALSE, FALSE, FALSE }, #ifdef FLOATX80 { "int32_to_floatx80", 1, FALSE, FALSE, FALSE, FALSE }, #endif #ifdef FLOAT128 { "int32_to_float128", 1, FALSE, FALSE, FALSE, FALSE }, #endif { "int64_to_float32", 1, FALSE, TRUE, FALSE, FALSE }, { "int64_to_float64", 1, FALSE, TRUE, FALSE, FALSE }, #ifdef FLOATX80 { "int64_to_floatx80", 1, FALSE, FALSE, FALSE, FALSE }, #endif #ifdef FLOAT128 { "int64_to_float128", 1, FALSE, FALSE, FALSE, FALSE }, #endif { "float32_to_int32", 1, FALSE, TRUE, FALSE, FALSE }, { "float32_to_int32_round_to_zero", 1, FALSE, FALSE, FALSE, FALSE }, { "float32_to_int64", 1, FALSE, TRUE, FALSE, FALSE }, { "float32_to_int64_round_to_zero", 1, FALSE, FALSE, FALSE, FALSE }, { "float32_to_float64", 1, FALSE, FALSE, FALSE, FALSE }, #ifdef FLOATX80 { "float32_to_floatx80", 1, FALSE, FALSE, FALSE, FALSE }, #endif #ifdef FLOAT128 { "float32_to_float128", 1, FALSE, FALSE, FALSE, FALSE }, #endif { "float32_round_to_int", 1, FALSE, TRUE, FALSE, FALSE }, { "float32_add", 2, FALSE, TRUE, FALSE, FALSE }, { "float32_sub", 2, FALSE, TRUE, FALSE, FALSE }, { "float32_mul", 2, FALSE, TRUE, TRUE, FALSE }, { "float32_div", 2, FALSE, TRUE, FALSE, FALSE }, { "float32_rem", 2, FALSE, FALSE, FALSE, FALSE }, { "float32_sqrt", 1, FALSE, TRUE, FALSE, FALSE }, { "float32_eq", 2, FALSE, FALSE, FALSE, FALSE }, { "float32_le", 2, FALSE, FALSE, FALSE, FALSE }, { "float32_lt", 2, FALSE, FALSE, FALSE, FALSE }, { "float32_eq_signaling", 2, FALSE, FALSE, FALSE, FALSE }, { "float32_le_quiet", 2, FALSE, FALSE, FALSE, FALSE }, { "float32_lt_quiet", 2, FALSE, FALSE, FALSE, FALSE }, { "float64_to_int32", 1, FALSE, TRUE, FALSE, FALSE }, { "float64_to_int32_round_to_zero", 1, FALSE, FALSE, FALSE, FALSE }, { "float64_to_int64", 1, FALSE, TRUE, FALSE, FALSE }, { "float64_to_int64_round_to_zero", 1, FALSE, FALSE, FALSE, FALSE }, { "float64_to_float32", 1, FALSE, TRUE, TRUE, FALSE }, #ifdef FLOATX80 { "float64_to_floatx80", 1, FALSE, FALSE, FALSE, FALSE }, #endif #ifdef FLOAT128 { "float64_to_float128", 1, FALSE, FALSE, FALSE, FALSE }, #endif { "float64_round_to_int", 1, FALSE, TRUE, FALSE, FALSE }, { "float64_add", 2, FALSE, TRUE, FALSE, FALSE }, { "float64_sub", 2, FALSE, TRUE, FALSE, FALSE }, { "float64_mul", 2, FALSE, TRUE, TRUE, FALSE }, { "float64_div", 2, FALSE, TRUE, FALSE, FALSE }, { "float64_rem", 2, FALSE, FALSE, FALSE, FALSE }, { "float64_sqrt", 1, FALSE, TRUE, FALSE, FALSE }, { "float64_eq", 2, FALSE, FALSE, FALSE, FALSE }, { "float64_le", 2, FALSE, FALSE, FALSE, FALSE }, { "float64_lt", 2, FALSE, FALSE, FALSE, FALSE }, { "float64_eq_signaling", 2, FALSE, FALSE, FALSE, FALSE }, { "float64_le_quiet", 2, FALSE, FALSE, FALSE, FALSE }, { "float64_lt_quiet", 2, FALSE, FALSE, FALSE, FALSE }, #ifdef FLOATX80 { "floatx80_to_int32", 1, FALSE, TRUE, FALSE, FALSE }, { "floatx80_to_int32_round_to_zero", 1, FALSE, FALSE, FALSE, FALSE }, { "floatx80_to_int64", 1, FALSE, TRUE, FALSE, FALSE }, { "floatx80_to_int64_round_to_zero", 1, FALSE, FALSE, FALSE, FALSE }, { "floatx80_to_float32", 1, FALSE, TRUE, TRUE, FALSE }, { "floatx80_to_float64", 1, FALSE, TRUE, TRUE, FALSE }, #ifdef FLOAT128 { "floatx80_to_float128", 1, FALSE, FALSE, FALSE, FALSE }, #endif { "floatx80_round_to_int", 1, FALSE, TRUE, FALSE, FALSE }, { "floatx80_add", 2, TRUE, TRUE, FALSE, TRUE }, { "floatx80_sub", 2, TRUE, TRUE, FALSE, TRUE }, { "floatx80_mul", 2, TRUE, TRUE, TRUE, TRUE }, { "floatx80_div", 2, TRUE, TRUE, FALSE, TRUE }, { "floatx80_rem", 2, FALSE, FALSE, FALSE, FALSE }, { "floatx80_sqrt", 1, TRUE, TRUE, FALSE, FALSE }, { "floatx80_eq", 2, FALSE, FALSE, FALSE, FALSE }, { "floatx80_le", 2, FALSE, FALSE, FALSE, FALSE }, { "floatx80_lt", 2, FALSE, FALSE, FALSE, FALSE }, { "floatx80_eq_signaling", 2, FALSE, FALSE, FALSE, FALSE }, { "floatx80_le_quiet", 2, FALSE, FALSE, FALSE, FALSE }, { "floatx80_lt_quiet", 2, FALSE, FALSE, FALSE, FALSE }, #endif #ifdef FLOAT128 { "float128_to_int32", 1, FALSE, TRUE, FALSE, FALSE }, { "float128_to_int32_round_to_zero", 1, FALSE, FALSE, FALSE, FALSE }, { "float128_to_int64", 1, FALSE, TRUE, FALSE, FALSE }, { "float128_to_int64_round_to_zero", 1, FALSE, FALSE, FALSE, FALSE }, { "float128_to_float32", 1, FALSE, TRUE, TRUE, FALSE }, { "float128_to_float64", 1, FALSE, TRUE, TRUE, FALSE }, #ifdef FLOATX80 { "float128_to_floatx80", 1, FALSE, TRUE, TRUE, FALSE }, #endif { "float128_round_to_int", 1, FALSE, TRUE, FALSE, FALSE }, { "float128_add", 2, FALSE, TRUE, FALSE, FALSE }, { "float128_sub", 2, FALSE, TRUE, FALSE, FALSE }, { "float128_mul", 2, FALSE, TRUE, TRUE, FALSE }, { "float128_div", 2, FALSE, TRUE, FALSE, FALSE }, { "float128_rem", 2, FALSE, FALSE, FALSE, FALSE }, { "float128_sqrt", 1, FALSE, TRUE, FALSE, FALSE }, { "float128_eq", 2, FALSE, FALSE, FALSE, FALSE }, { "float128_le", 2, FALSE, FALSE, FALSE, FALSE }, { "float128_lt", 2, FALSE, FALSE, FALSE, FALSE }, { "float128_eq_signaling", 2, FALSE, FALSE, FALSE, FALSE }, { "float128_le_quiet", 2, FALSE, FALSE, FALSE, FALSE }, { "float128_lt_quiet", 2, FALSE, FALSE, FALSE, FALSE }, #endif }; enum { ROUND_NEAREST_EVEN = 1, ROUND_TO_ZERO, ROUND_DOWN, ROUND_UP, NUM_ROUNDINGMODES }; enum { TININESS_BEFORE_ROUNDING = 1, TININESS_AFTER_ROUNDING, NUM_TININESSMODES }; static void timeFunctionVariety( uint8 functionCode, int8 roundingPrecision, int8 roundingMode, int8 tininessMode ) { uint8 roundingCode; int8 tininessCode; functionName = functions[ functionCode ].name; if ( roundingPrecision == 32 ) { roundingPrecisionName = "32"; } else if ( roundingPrecision == 64 ) { roundingPrecisionName = "64"; } else if ( roundingPrecision == 80 ) { roundingPrecisionName = "80"; } else { - roundingPrecisionName = 0; + roundingPrecisionName = NULL; } #ifdef FLOATX80 floatx80_rounding_precision = roundingPrecision; #endif switch ( roundingMode ) { case 0: - roundingModeName = 0; + roundingModeName = NULL; roundingCode = float_round_nearest_even; break; case ROUND_NEAREST_EVEN: roundingModeName = "nearest_even"; roundingCode = float_round_nearest_even; break; case ROUND_TO_ZERO: roundingModeName = "to_zero"; roundingCode = float_round_to_zero; break; case ROUND_DOWN: roundingModeName = "down"; roundingCode = float_round_down; break; case ROUND_UP: roundingModeName = "up"; roundingCode = float_round_up; break; } float_rounding_mode = roundingCode; switch ( tininessMode ) { case 0: - tininessModeName = 0; + tininessModeName = NULL; tininessCode = float_tininess_after_rounding; break; case TININESS_BEFORE_ROUNDING: tininessModeName = "before"; tininessCode = float_tininess_before_rounding; break; case TININESS_AFTER_ROUNDING: tininessModeName = "after"; tininessCode = float_tininess_after_rounding; break; } float_detect_tininess = tininessCode; switch ( functionCode ) { case INT32_TO_FLOAT32: time_a_int32_z_float32( int32_to_float32 ); break; case INT32_TO_FLOAT64: time_a_int32_z_float64( int32_to_float64 ); break; #ifdef FLOATX80 case INT32_TO_FLOATX80: time_a_int32_z_floatx80( int32_to_floatx80 ); break; #endif #ifdef FLOAT128 case INT32_TO_FLOAT128: time_a_int32_z_float128( int32_to_float128 ); break; #endif case INT64_TO_FLOAT32: time_a_int64_z_float32( int64_to_float32 ); break; case INT64_TO_FLOAT64: time_a_int64_z_float64( int64_to_float64 ); break; #ifdef FLOATX80 case INT64_TO_FLOATX80: time_a_int64_z_floatx80( int64_to_floatx80 ); break; #endif #ifdef FLOAT128 case INT64_TO_FLOAT128: time_a_int64_z_float128( int64_to_float128 ); break; #endif case FLOAT32_TO_INT32: time_a_float32_z_int32( float32_to_int32 ); break; case FLOAT32_TO_INT32_ROUND_TO_ZERO: time_a_float32_z_int32( float32_to_int32_round_to_zero ); break; case FLOAT32_TO_INT64: time_a_float32_z_int64( float32_to_int64 ); break; case FLOAT32_TO_INT64_ROUND_TO_ZERO: time_a_float32_z_int64( float32_to_int64_round_to_zero ); break; case FLOAT32_TO_FLOAT64: time_a_float32_z_float64( float32_to_float64 ); break; #ifdef FLOATX80 case FLOAT32_TO_FLOATX80: time_a_float32_z_floatx80( float32_to_floatx80 ); break; #endif #ifdef FLOAT128 case FLOAT32_TO_FLOAT128: time_a_float32_z_float128( float32_to_float128 ); break; #endif case FLOAT32_ROUND_TO_INT: time_az_float32( float32_round_to_int ); break; case FLOAT32_ADD: time_abz_float32( float32_add ); break; case FLOAT32_SUB: time_abz_float32( float32_sub ); break; case FLOAT32_MUL: time_abz_float32( float32_mul ); break; case FLOAT32_DIV: time_abz_float32( float32_div ); break; case FLOAT32_REM: time_abz_float32( float32_rem ); break; case FLOAT32_SQRT: time_az_float32_pos( float32_sqrt ); break; case FLOAT32_EQ: time_ab_float32_z_flag( float32_eq ); break; case FLOAT32_LE: time_ab_float32_z_flag( float32_le ); break; case FLOAT32_LT: time_ab_float32_z_flag( float32_lt ); break; case FLOAT32_EQ_SIGNALING: time_ab_float32_z_flag( float32_eq_signaling ); break; case FLOAT32_LE_QUIET: time_ab_float32_z_flag( float32_le_quiet ); break; case FLOAT32_LT_QUIET: time_ab_float32_z_flag( float32_lt_quiet ); break; case FLOAT64_TO_INT32: time_a_float64_z_int32( float64_to_int32 ); break; case FLOAT64_TO_INT32_ROUND_TO_ZERO: time_a_float64_z_int32( float64_to_int32_round_to_zero ); break; case FLOAT64_TO_INT64: time_a_float64_z_int64( float64_to_int64 ); break; case FLOAT64_TO_INT64_ROUND_TO_ZERO: time_a_float64_z_int64( float64_to_int64_round_to_zero ); break; case FLOAT64_TO_FLOAT32: time_a_float64_z_float32( float64_to_float32 ); break; #ifdef FLOATX80 case FLOAT64_TO_FLOATX80: time_a_float64_z_floatx80( float64_to_floatx80 ); break; #endif #ifdef FLOAT128 case FLOAT64_TO_FLOAT128: time_a_float64_z_float128( float64_to_float128 ); break; #endif case FLOAT64_ROUND_TO_INT: time_az_float64( float64_round_to_int ); break; case FLOAT64_ADD: time_abz_float64( float64_add ); break; case FLOAT64_SUB: time_abz_float64( float64_sub ); break; case FLOAT64_MUL: time_abz_float64( float64_mul ); break; case FLOAT64_DIV: time_abz_float64( float64_div ); break; case FLOAT64_REM: time_abz_float64( float64_rem ); break; case FLOAT64_SQRT: time_az_float64_pos( float64_sqrt ); break; case FLOAT64_EQ: time_ab_float64_z_flag( float64_eq ); break; case FLOAT64_LE: time_ab_float64_z_flag( float64_le ); break; case FLOAT64_LT: time_ab_float64_z_flag( float64_lt ); break; case FLOAT64_EQ_SIGNALING: time_ab_float64_z_flag( float64_eq_signaling ); break; case FLOAT64_LE_QUIET: time_ab_float64_z_flag( float64_le_quiet ); break; case FLOAT64_LT_QUIET: time_ab_float64_z_flag( float64_lt_quiet ); break; #ifdef FLOATX80 case FLOATX80_TO_INT32: time_a_floatx80_z_int32( floatx80_to_int32 ); break; case FLOATX80_TO_INT32_ROUND_TO_ZERO: time_a_floatx80_z_int32( floatx80_to_int32_round_to_zero ); break; case FLOATX80_TO_INT64: time_a_floatx80_z_int64( floatx80_to_int64 ); break; case FLOATX80_TO_INT64_ROUND_TO_ZERO: time_a_floatx80_z_int64( floatx80_to_int64_round_to_zero ); break; case FLOATX80_TO_FLOAT32: time_a_floatx80_z_float32( floatx80_to_float32 ); break; case FLOATX80_TO_FLOAT64: time_a_floatx80_z_float64( floatx80_to_float64 ); break; #ifdef FLOAT128 case FLOATX80_TO_FLOAT128: time_a_floatx80_z_float128( floatx80_to_float128 ); break; #endif case FLOATX80_ROUND_TO_INT: time_az_floatx80( floatx80_round_to_int ); break; case FLOATX80_ADD: time_abz_floatx80( floatx80_add ); break; case FLOATX80_SUB: time_abz_floatx80( floatx80_sub ); break; case FLOATX80_MUL: time_abz_floatx80( floatx80_mul ); break; case FLOATX80_DIV: time_abz_floatx80( floatx80_div ); break; case FLOATX80_REM: time_abz_floatx80( floatx80_rem ); break; case FLOATX80_SQRT: time_az_floatx80_pos( floatx80_sqrt ); break; case FLOATX80_EQ: time_ab_floatx80_z_flag( floatx80_eq ); break; case FLOATX80_LE: time_ab_floatx80_z_flag( floatx80_le ); break; case FLOATX80_LT: time_ab_floatx80_z_flag( floatx80_lt ); break; case FLOATX80_EQ_SIGNALING: time_ab_floatx80_z_flag( floatx80_eq_signaling ); break; case FLOATX80_LE_QUIET: time_ab_floatx80_z_flag( floatx80_le_quiet ); break; case FLOATX80_LT_QUIET: time_ab_floatx80_z_flag( floatx80_lt_quiet ); break; #endif #ifdef FLOAT128 case FLOAT128_TO_INT32: time_a_float128_z_int32( float128_to_int32 ); break; case FLOAT128_TO_INT32_ROUND_TO_ZERO: time_a_float128_z_int32( float128_to_int32_round_to_zero ); break; case FLOAT128_TO_INT64: time_a_float128_z_int64( float128_to_int64 ); break; case FLOAT128_TO_INT64_ROUND_TO_ZERO: time_a_float128_z_int64( float128_to_int64_round_to_zero ); break; case FLOAT128_TO_FLOAT32: time_a_float128_z_float32( float128_to_float32 ); break; case FLOAT128_TO_FLOAT64: time_a_float128_z_float64( float128_to_float64 ); break; #ifdef FLOATX80 case FLOAT128_TO_FLOATX80: time_a_float128_z_floatx80( float128_to_floatx80 ); break; #endif case FLOAT128_ROUND_TO_INT: time_az_float128( float128_round_to_int ); break; case FLOAT128_ADD: time_abz_float128( float128_add ); break; case FLOAT128_SUB: time_abz_float128( float128_sub ); break; case FLOAT128_MUL: time_abz_float128( float128_mul ); break; case FLOAT128_DIV: time_abz_float128( float128_div ); break; case FLOAT128_REM: time_abz_float128( float128_rem ); break; case FLOAT128_SQRT: time_az_float128_pos( float128_sqrt ); break; case FLOAT128_EQ: time_ab_float128_z_flag( float128_eq ); break; case FLOAT128_LE: time_ab_float128_z_flag( float128_le ); break; case FLOAT128_LT: time_ab_float128_z_flag( float128_lt ); break; case FLOAT128_EQ_SIGNALING: time_ab_float128_z_flag( float128_eq_signaling ); break; case FLOAT128_LE_QUIET: time_ab_float128_z_flag( float128_le_quiet ); break; case FLOAT128_LT_QUIET: time_ab_float128_z_flag( float128_lt_quiet ); break; #endif } } static void timeFunction( uint8 functionCode, int8 roundingPrecisionIn, int8 roundingModeIn, int8 tininessModeIn ) { int8 roundingPrecision, roundingMode, tininessMode; roundingPrecision = 32; for (;;) { if ( ! functions[ functionCode ].roundingPrecision ) { roundingPrecision = 0; } else if ( roundingPrecisionIn ) { roundingPrecision = roundingPrecisionIn; } for ( roundingMode = 1; roundingMode < NUM_ROUNDINGMODES; ++roundingMode ) { if ( ! functions[ functionCode ].roundingMode ) { roundingMode = 0; } else if ( roundingModeIn ) { roundingMode = roundingModeIn; } for ( tininessMode = 1; tininessMode < NUM_TININESSMODES; ++tininessMode ) { if ( ( roundingPrecision == 32 ) || ( roundingPrecision == 64 ) ) { if ( ! functions[ functionCode ] .tininessModeAtReducedPrecision ) { tininessMode = 0; } else if ( tininessModeIn ) { tininessMode = tininessModeIn; } } else { if ( ! functions[ functionCode ].tininessMode ) { tininessMode = 0; } else if ( tininessModeIn ) { tininessMode = tininessModeIn; } } timeFunctionVariety( functionCode, roundingPrecision, roundingMode, tininessMode ); if ( tininessModeIn || ! tininessMode ) break; } if ( roundingModeIn || ! roundingMode ) break; } if ( roundingPrecisionIn || ! roundingPrecision ) break; if ( roundingPrecision == 80 ) { break; } else if ( roundingPrecision == 64 ) { roundingPrecision = 80; } else if ( roundingPrecision == 32 ) { roundingPrecision = 64; } } } main( int argc, char **argv ) { char *argPtr; flag functionArgument; uint8 functionCode; int8 operands, roundingPrecision, roundingMode, tininessMode; if ( argc <= 1 ) goto writeHelpMessage; functionArgument = FALSE; functionCode = 0; operands = 0; roundingPrecision = 0; roundingMode = 0; tininessMode = 0; --argc; ++argv; while ( argc && ( argPtr = argv[ 0 ] ) ) { if ( argPtr[ 0 ] == '-' ) ++argPtr; if ( strcmp( argPtr, "help" ) == 0 ) { writeHelpMessage: fputs( "timesoftfloat [