diff options
author | ngie <ngie@FreeBSD.org> | 2015-11-16 02:00:12 +0000 |
---|---|---|
committer | ngie <ngie@FreeBSD.org> | 2015-11-16 02:00:12 +0000 |
commit | fd9367ff35d3ef67f52f8612ba6df3c487b90f4d (patch) | |
tree | 68c676723f5f9cd1d66be903cfdce6b37dcc3719 /lib/libc | |
parent | 3d588fbc9bc229fdd93d6aaf6340583c2bcaca9f (diff) | |
parent | b708fe19431dfeacfe97dbc276190934bd53b483 (diff) | |
download | FreeBSD-src-fd9367ff35d3ef67f52f8612ba6df3c487b90f4d.zip FreeBSD-src-fd9367ff35d3ef67f52f8612ba6df3c487b90f4d.tar.gz |
MFhead @ r290899
Diffstat (limited to 'lib/libc')
117 files changed, 9960 insertions, 978 deletions
diff --git a/lib/libc/gen/getgrent.c b/lib/libc/gen/getgrent.c index 31d2af1..2179fb2 100644 --- a/lib/libc/gen/getgrent.c +++ b/lib/libc/gen/getgrent.c @@ -660,14 +660,13 @@ __getgroupmembership(const char *uname, gid_t agroup, gid_t *groups, NS_FALLBACK_CB(getgroupmembership_fallback) { NULL, NULL, NULL } }; - int rv; assert(uname != NULL); /* groups may be NULL if just sizing when invoked with maxgrp = 0 */ assert(grpcnt != NULL); *grpcnt = 0; - rv = _nsdispatch(NULL, dtab, NSDB_GROUP, "getgroupmembership", + (void)_nsdispatch(NULL, dtab, NSDB_GROUP, "getgroupmembership", defaultsrc, uname, agroup, groups, maxgrp, grpcnt); /* too many groups found? */ @@ -1239,14 +1238,13 @@ compat_setgrent(void *retval, void *mdata, va_list ap) int rv, stayopen; #define set_setent(x, y) do { \ - unsigned int i; \ - \ - for (i = 0; i < (sizeof(x)/sizeof(x[0])) - 1; i++) \ + int i; \ + for (i = 0; i < (int)(nitems(x) - 1); i++) \ x[i].mdata = (void *)y; \ } while (0) rv = compat_getstate(&st); - if (rv != 0) + if (rv != 0) return (NS_UNAVAIL); switch ((enum constants)mdata) { case SETGRENT: @@ -1309,9 +1307,8 @@ compat_group(void *retval, void *mdata, va_list ap) int rv, stayopen, *errnop; #define set_lookup_type(x, y) do { \ - unsigned int i; \ - \ - for (i = 0; i < (sizeof(x)/sizeof(x[0])) - 1; i++) \ + int i; \ + for (i = 0; i < (int)(nitems(x) - 1); i++) \ x[i].mdata = (void *)y; \ } while (0) diff --git a/lib/libc/gen/getpwent.c b/lib/libc/gen/getpwent.c index 6546f587..8617ecc 100644 --- a/lib/libc/gen/getpwent.c +++ b/lib/libc/gen/getpwent.c @@ -1607,10 +1607,9 @@ compat_redispatch(struct compat_state *st, enum nss_lookup_type how, { NULL, NULL, NULL } }; void *discard; - int rv, e; - unsigned int i; + int e, i, rv; - for (i = 0; i < sizeof(dtab)/sizeof(dtab[0]) - 1; i++) + for (i = 0; i < (int)(nitems(dtab) - 1); i++) dtab[i].mdata = (void *)lookup_how; more: pwd_init(pwd); @@ -1703,9 +1702,8 @@ compat_setpwent(void *retval, void *mdata, va_list ap) int rv, stayopen; #define set_setent(x, y) do { \ - unsigned int i; \ - \ - for (i = 0; i < (sizeof(x)/sizeof(x[0])) - 1; i++) \ + int i; \ + for (i = 0; i < (int)(nitems(x) - 1); i++) \ x[i].mdata = (void *)y; \ } while (0) diff --git a/lib/libc/iconv/bsd_iconv.c b/lib/libc/iconv/bsd_iconv.c index e032a5b..e9ff688 100644 --- a/lib/libc/iconv/bsd_iconv.c +++ b/lib/libc/iconv/bsd_iconv.c @@ -207,43 +207,51 @@ __bsd_iconvlist(int (*do_one) (unsigned int, const char * const *, const char * const *np; char *curitem, *curkey, *slashpos; size_t sz; - unsigned int i, j; + unsigned int i, j, n; i = 0; + names = NULL; - if (__bsd___iconv_get_list(&list, &sz, true)) + if (__bsd___iconv_get_list(&list, &sz, true)) { list = NULL; + goto out; + } qsort((void *)list, sz, sizeof(char *), qsort_helper); while (i < sz) { j = 0; slashpos = strchr(list[i], '/'); - curkey = (char *)malloc(slashpos - list[i] + 2); - names = (char **)malloc(sz * sizeof(char *)); - if ((curkey == NULL) || (names == NULL)) { - __bsd___iconv_free_list(list, sz); - return; - } - strlcpy(curkey, list[i], slashpos - list[i] + 1); + names = malloc(sz * sizeof(char *)); + if (names == NULL) + goto out; + curkey = strndup(list[i], slashpos - list[i]); + if (curkey == NULL) + goto out; names[j++] = curkey; for (; (i < sz) && (memcmp(curkey, list[i], strlen(curkey)) == 0); i++) { slashpos = strchr(list[i], '/'); - curitem = (char *)malloc(strlen(slashpos) + 1); - if (curitem == NULL) { - __bsd___iconv_free_list(list, sz); - return; - } - strlcpy(curitem, &slashpos[1], strlen(slashpos) + 1); - if (strcmp(curkey, curitem) == 0) { + if (strcmp(curkey, &slashpos[1]) == 0) continue; - } + curitem = strdup(&slashpos[1]); + if (curitem == NULL) + goto out; names[j++] = curitem; } np = (const char * const *)names; do_one(j, np, data); + for (n = 0; n < j; n++) + free(names[n]); free(names); + names = NULL; } - __bsd___iconv_free_list(list, sz); +out: + if (names != NULL) { + for (n = 0; n < j; n++) + free(names[n]); + free(names); + } + if (list != NULL) + __bsd___iconv_free_list(list, sz); } __inline const char * diff --git a/lib/libc/iconv/citrus_esdb.c b/lib/libc/iconv/citrus_esdb.c index 578cbc1..ed404a6 100644 --- a/lib/libc/iconv/citrus_esdb.c +++ b/lib/libc/iconv/citrus_esdb.c @@ -328,7 +328,7 @@ _citrus_esdb_get_list(char ***rlist, size_t *rnum, bool sorted) (int)_region_size(&data), (const char *)_region_head(&data)); if ((p = strchr(buf1, '/')) != NULL) - memcpy(buf1, p + 1, strlen(p) - 1); + memmove(buf1, p + 1, strlen(p) - 1); if ((p = strstr(buf1, ".esdb")) != NULL) *p = '\0'; snprintf(buf, sizeof(buf), "%s/%.*s", buf1, diff --git a/lib/libc/locale/ascii.c b/lib/libc/locale/ascii.c index 784814d..3e625e4 100644 --- a/lib/libc/locale/ascii.c +++ b/lib/libc/locale/ascii.c @@ -1,4 +1,6 @@ -/*- +/* + * Copyright 2013 Garrett D'Amore <garrett@damore.org> + * Copyright 2010 Nexenta Systems, Inc. All rights reserved. * Copyright (c) 2002-2004 Tim J. Robbins. All rights reserved. * Copyright (c) 1993 * The Regents of the University of California. All rights reserved. @@ -34,6 +36,8 @@ * 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. + * + * @(#)none.c 8.1 (Berkeley) 6/4/93 */ #include <sys/cdefs.h> @@ -61,7 +65,7 @@ static size_t _ascii_wcsnrtombs(char * __restrict, const wchar_t ** __restrict, size_t, size_t, mbstate_t * __restrict); int -_ascii_init(struct xlocale_ctype *l,_RuneLocale *rl) +_ascii_init(struct xlocale_ctype *l, _RuneLocale *rl) { l->__mbrtowc = _ascii_mbrtowc; @@ -78,7 +82,6 @@ _ascii_init(struct xlocale_ctype *l,_RuneLocale *rl) static int _ascii_mbsinit(const mbstate_t *ps __unused) { - /* * Encoding is not state dependent - we are always in the * initial state. @@ -90,7 +93,6 @@ static size_t _ascii_mbrtowc(wchar_t * __restrict pwc, const char * __restrict s, size_t n, mbstate_t * __restrict ps __unused) { - if (s == NULL) /* Reset to initial shift state (no-op) */ return (0); @@ -130,13 +132,12 @@ _ascii_mbsnrtowcs(wchar_t * __restrict dst, const char ** __restrict src, size_t nchr; if (dst == NULL) { - for (s = *src; nms > 0 && *s != '\0'; s++, nms--) { - if (*s & 0x80) { - errno = EILSEQ; - return ((size_t)-1); - } + s = memchr(*src, '\0', nms); + if (*s & 0x80) { + errno = EILSEQ; + return ((size_t)-1); } - return (s - *src); + return (s != NULL ? s - *src : nms); } s = *src; @@ -189,4 +190,3 @@ _ascii_wcsnrtombs(char * __restrict dst, const wchar_t ** __restrict src, *src = s; return (nchr); } - diff --git a/lib/libc/locale/big5.c b/lib/libc/locale/big5.c index 4b37265..c1f94d3 100644 --- a/lib/libc/locale/big5.c +++ b/lib/libc/locale/big5.c @@ -1,4 +1,6 @@ /*- + * Copyright 2013 Garrett D'Amore <garrett@damore.org> + * Copyright 2010 Nexenta Systems, Inc. All rights reserved. * Copyright (c) 2002-2004 Tim J. Robbins. All rights reserved. * Copyright (c) 1993 * The Regents of the University of California. All rights reserved. @@ -19,11 +21,7 @@ * 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. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors + * 3. 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. * @@ -61,6 +59,12 @@ static size_t _BIG5_mbrtowc(wchar_t * __restrict, const char * __restrict, static int _BIG5_mbsinit(const mbstate_t *); static size_t _BIG5_wcrtomb(char * __restrict, wchar_t, mbstate_t * __restrict); +static size_t _BIG5_mbsnrtowcs(wchar_t * __restrict, + const char ** __restrict, size_t, size_t, + mbstate_t * __restrict); +static size_t _BIG5_wcsnrtombs(char * __restrict, + const wchar_t ** __restrict, size_t, size_t, + mbstate_t * __restrict); typedef struct { wchar_t ch; @@ -72,6 +76,8 @@ _BIG5_init(struct xlocale_ctype *l, _RuneLocale *rl) l->__mbrtowc = _BIG5_mbrtowc; l->__wcrtomb = _BIG5_wcrtomb; + l->__mbsnrtowcs = _BIG5_mbsnrtowcs; + l->__wcsnrtombs = _BIG5_wcsnrtombs; l->__mbsinit = _BIG5_mbsinit; l->runes = rl; l->__mb_cur_max = 2; @@ -147,7 +153,7 @@ _BIG5_mbrtowc(wchar_t * __restrict pwc, const char * __restrict s, size_t n, wc = (wc << 8) | (*s++ & 0xff); if (pwc != NULL) *pwc = wc; - return (2); + return (2); } else { if (pwc != NULL) *pwc = wc; @@ -178,3 +184,17 @@ _BIG5_wcrtomb(char * __restrict s, wchar_t wc, mbstate_t * __restrict ps) *s = wc & 0xff; return (1); } + +static size_t +_BIG5_mbsnrtowcs(wchar_t * __restrict dst, const char ** __restrict src, + size_t nms, size_t len, mbstate_t * __restrict ps) +{ + return (__mbsnrtowcs_std(dst, src, nms, len, ps, _BIG5_mbrtowc)); +} + +static size_t +_BIG5_wcsnrtombs(char * __restrict dst, const wchar_t ** __restrict src, + size_t nwc, size_t len, mbstate_t * __restrict ps) +{ + return (__wcsnrtombs_std(dst, src, nwc, len, ps, _BIG5_wcrtomb)); +} diff --git a/lib/libc/locale/collate.c b/lib/libc/locale/collate.c index 56513f4..d0ed152 100644 --- a/lib/libc/locale/collate.c +++ b/lib/libc/locale/collate.c @@ -1,4 +1,6 @@ /*- + * Copyright 2014 Garrett D'Amore <garrett@damore.org> + * Copyright 2010 Nexenta Systems, Inc. All rights reserved. * Copyright (c) 1995 Alex Tatmanjants <alex@elvisti.kiev.ua> * at Electronni Visti IA, Kiev, Ukraine. * All rights reserved. @@ -28,66 +30,57 @@ * 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. + * + * Adapted to xlocale by John Marino <draco@marino.st> */ #include <sys/cdefs.h> __FBSDID("$FreeBSD$"); #include "namespace.h" -#include <arpa/inet.h> + +#include <sys/types.h> +#include <sys/stat.h> +#include <sys/mman.h> + +#include <assert.h> #include <stdio.h> #include <stdlib.h> #include <string.h> +#include <wchar.h> #include <errno.h> #include <unistd.h> -#include <sysexits.h> +#include <fcntl.h> #include "un-namespace.h" #include "collate.h" #include "setlocale.h" #include "ldpart.h" - #include "libc_private.h" -/* - * To avoid modifying the original (single-threaded) code too much, we'll just - * define the old globals as fields inside the table. - * - * We also modify the collation table test functions to search the thread-local - * table first and the global table second. - */ -#define __collate_substitute_nontrivial (table->__collate_substitute_nontrivial) -#define __collate_substitute_table_ptr (table->__collate_substitute_table_ptr) -#define __collate_char_pri_table_ptr (table->__collate_char_pri_table_ptr) -#define __collate_chain_pri_table (table->__collate_chain_pri_table) -int __collate_load_error; - - struct xlocale_collate __xlocale_global_collate = { - {{0}, "C"}, 1, 0 + {{0}, "C"}, 1, 0, 0, 0 }; - struct xlocale_collate __xlocale_C_collate = { - {{0}, "C"}, 1, 0 +struct xlocale_collate __xlocale_C_collate = { + {{0}, "C"}, 1, 0, 0, 0 }; -void __collate_err(int ex, const char *f) __dead2; - -int +static int __collate_load_tables_l(const char *encoding, struct xlocale_collate *table); static void destruct_collate(void *t) { struct xlocale_collate *table = t; - if (__collate_chain_pri_table) { - free(__collate_chain_pri_table); + if (table->map && (table->maplen > 0)) { + (void) munmap(table->map, table->maplen); } free(t); } void * -__collate_load(const char *encoding, locale_t unused) +__collate_load(const char *encoding, __unused locale_t unused) { if (strcmp(encoding, "C") == 0 || strcmp(encoding, "POSIX") == 0) { return &__xlocale_C_collate; @@ -109,237 +102,602 @@ __collate_load(const char *encoding, locale_t unused) int __collate_load_tables(const char *encoding) { - int ret = __collate_load_tables_l(encoding, &__xlocale_global_collate); - __collate_load_error = __xlocale_global_collate.__collate_load_error; - return ret; + + return (__collate_load_tables_l(encoding, &__xlocale_global_collate)); } int __collate_load_tables_l(const char *encoding, struct xlocale_collate *table) { - FILE *fp; - int i, saverr, chains; - uint32_t u32; - char strbuf[STR_LEN], buf[PATH_MAX]; - void *TMP_substitute_table, *TMP_char_pri_table, *TMP_chain_pri_table; + int i, chains, z; + char *buf; + char *TMP; + char *map; + collate_info_t *info; + struct stat sbuf; + int fd; + + table->__collate_load_error = 1; /* 'encoding' must be already checked. */ if (strcmp(encoding, "C") == 0 || strcmp(encoding, "POSIX") == 0) { - table->__collate_load_error = 1; return (_LDP_CACHE); } - /* 'PathLocale' must be already set & checked. */ - /* Range checking not needed, encoding has fixed size */ - (void)strcpy(buf, _PathLocale); - (void)strcat(buf, "/"); - (void)strcat(buf, encoding); - (void)strcat(buf, "/LC_COLLATE"); - if ((fp = fopen(buf, "re")) == NULL) + asprintf(&buf, "%s/%s/LC_COLLATE", _PathLocale, encoding); + if (buf == NULL) return (_LDP_ERROR); - if (fread(strbuf, sizeof(strbuf), 1, fp) != 1) { - saverr = errno; - (void)fclose(fp); - errno = saverr; + if ((fd = _open(buf, O_RDONLY)) < 0) { + free(buf); return (_LDP_ERROR); } - chains = -1; - if (strcmp(strbuf, COLLATE_VERSION) == 0) - chains = 0; - else if (strcmp(strbuf, COLLATE_VERSION1_2) == 0) - chains = 1; - if (chains < 0) { - (void)fclose(fp); - errno = EFTYPE; + free(buf); + if (_fstat(fd, &sbuf) < 0) { + (void) _close(fd); return (_LDP_ERROR); } - if (chains) { - if (fread(&u32, sizeof(u32), 1, fp) != 1) { - saverr = errno; - (void)fclose(fp); - errno = saverr; - return (_LDP_ERROR); - } - if ((chains = (int)ntohl(u32)) < 1) { - (void)fclose(fp); - errno = EFTYPE; - return (_LDP_ERROR); - } - } else - chains = TABLE_SIZE; - - if ((TMP_substitute_table = - malloc(sizeof(__collate_substitute_table))) == NULL) { - saverr = errno; - (void)fclose(fp); - errno = saverr; + if (sbuf.st_size < (COLLATE_STR_LEN + sizeof (info))) { + (void) _close(fd); + errno = EINVAL; return (_LDP_ERROR); } - if ((TMP_char_pri_table = - malloc(sizeof(__collate_char_pri_table))) == NULL) { - saverr = errno; - free(TMP_substitute_table); - (void)fclose(fp); - errno = saverr; + map = mmap(NULL, sbuf.st_size, PROT_READ, MAP_PRIVATE, fd, 0); + (void) _close(fd); + if ((TMP = map) == NULL) { return (_LDP_ERROR); } - if ((TMP_chain_pri_table = - malloc(sizeof(*__collate_chain_pri_table) * chains)) == NULL) { - saverr = errno; - free(TMP_substitute_table); - free(TMP_char_pri_table); - (void)fclose(fp); - errno = saverr; + + if (strncmp(TMP, COLLATE_VERSION, COLLATE_STR_LEN) != 0) { + (void) munmap(map, sbuf.st_size); + errno = EINVAL; return (_LDP_ERROR); } + TMP += COLLATE_STR_LEN; -#define FREAD(a, b, c, d) \ -{ \ - if (fread(a, b, c, d) != c) { \ - saverr = errno; \ - free(TMP_substitute_table); \ - free(TMP_char_pri_table); \ - free(TMP_chain_pri_table); \ - (void)fclose(d); \ - errno = saverr; \ - return (_LDP_ERROR); \ - } \ -} + info = (void *)TMP; + TMP += sizeof (*info); + + if ((info->directive_count < 1) || + (info->directive_count >= COLL_WEIGHTS_MAX) || + ((chains = info->chain_count) < 0)) { + (void) munmap(map, sbuf.st_size); + errno = EINVAL; + return (_LDP_ERROR); + } - FREAD(TMP_substitute_table, sizeof(__collate_substitute_table), 1, fp); - FREAD(TMP_char_pri_table, sizeof(__collate_char_pri_table), 1, fp); - FREAD(TMP_chain_pri_table, - sizeof(*__collate_chain_pri_table), chains, fp); - (void)fclose(fp); - - if (__collate_substitute_table_ptr != NULL) - free(__collate_substitute_table_ptr); - __collate_substitute_table_ptr = TMP_substitute_table; - if (__collate_char_pri_table_ptr != NULL) - free(__collate_char_pri_table_ptr); - __collate_char_pri_table_ptr = TMP_char_pri_table; - for (i = 0; i < UCHAR_MAX + 1; i++) { - __collate_char_pri_table[i].prim = - ntohl(__collate_char_pri_table[i].prim); - __collate_char_pri_table[i].sec = - ntohl(__collate_char_pri_table[i].sec); + i = (sizeof (collate_char_t) * (UCHAR_MAX + 1)) + + (sizeof (collate_chain_t) * chains) + + (sizeof (collate_large_t) * info->large_count); + for (z = 0; z < info->directive_count; z++) { + i += sizeof (collate_subst_t) * info->subst_count[z]; } - if (__collate_chain_pri_table != NULL) - free(__collate_chain_pri_table); - __collate_chain_pri_table = TMP_chain_pri_table; - for (i = 0; i < chains; i++) { - __collate_chain_pri_table[i].prim = - ntohl(__collate_chain_pri_table[i].prim); - __collate_chain_pri_table[i].sec = - ntohl(__collate_chain_pri_table[i].sec); + if (i != (sbuf.st_size - (TMP - map))) { + (void) munmap(map, sbuf.st_size); + errno = EINVAL; + return (_LDP_ERROR); } - __collate_substitute_nontrivial = 0; - for (i = 0; i < UCHAR_MAX + 1; i++) { - if (__collate_substitute_table[i][0] != i || - __collate_substitute_table[i][1] != 0) { - __collate_substitute_nontrivial = 1; - break; + + table->info = info; + table->char_pri_table = (void *)TMP; + TMP += sizeof (collate_char_t) * (UCHAR_MAX + 1); + + for (z = 0; z < info->directive_count; z++) { + if (info->subst_count[z] > 0) { + table->subst_table[z] = (void *)TMP; + TMP += info->subst_count[z] * sizeof (collate_subst_t); + } else { + table->subst_table[z] = NULL; } } - table->__collate_load_error = 0; + if (chains > 0) { + table->chain_pri_table = (void *)TMP; + TMP += chains * sizeof (collate_chain_t); + } else + table->chain_pri_table = NULL; + if (info->large_count > 0) + table->large_pri_table = (void *)TMP; + else + table->large_pri_table = NULL; + + table->__collate_load_error = 0; return (_LDP_LOADED); } -u_char * -__collate_substitute(struct xlocale_collate *table, const u_char *s) +static const int32_t * +substsearch(struct xlocale_collate *table, const wchar_t key, int pass) { - int dest_len, len, nlen; - int delta = strlen(s); - u_char *dest_str = NULL; - - if (s == NULL || *s == '\0') - return (__collate_strdup("")); - delta += delta / 8; - dest_str = malloc(dest_len = delta); - if (dest_str == NULL) - __collate_err(EX_OSERR, __func__); - len = 0; - while (*s) { - nlen = len + strlen(__collate_substitute_table[*s]); - if (dest_len <= nlen) { - dest_str = reallocf(dest_str, dest_len = nlen + delta); - if (dest_str == NULL) - __collate_err(EX_OSERR, __func__); + const collate_subst_t *p; + int n = table->info->subst_count[pass]; + + if (n == 0) + return (NULL); + + if (pass >= table->info->directive_count) + return (NULL); + + if (!(key & COLLATE_SUBST_PRIORITY)) + return (NULL); + + p = table->subst_table[pass] + (key & ~COLLATE_SUBST_PRIORITY); + assert(p->key == key); + return (p->pri); +} + +static collate_chain_t * +chainsearch(struct xlocale_collate *table, const wchar_t *key, int *len) +{ + int low = 0; + int high = table->info->chain_count - 1;; + int next, compar, l; + collate_chain_t *p; + collate_chain_t *tab = table->chain_pri_table; + + if (high < 0) + return (NULL); + + while (low <= high) { + next = (low + high) / 2; + p = tab + next; + compar = *key - *p->str; + if (compar == 0) { + l = wcsnlen(p->str, COLLATE_STR_LEN); + compar = wcsncmp(key, p->str, l); + if (compar == 0) { + *len = l; + return (p); + } } - (void)strcpy(dest_str + len, __collate_substitute_table[*s++]); - len = nlen; + if (compar > 0) + low = next + 1; + else + high = next - 1; + } + return (NULL); +} + +static collate_large_t * +largesearch(struct xlocale_collate *table, const wchar_t key) +{ + int low = 0; + int high = table->info->large_count - 1; + int next, compar; + collate_large_t *p; + collate_large_t *tab = table->large_pri_table; + + if (high < 0) + return (NULL); + + while (low <= high) { + next = (low + high) / 2; + p = tab + next; + compar = key - p->val; + if (compar == 0) + return (p); + if (compar > 0) + low = next + 1; + else + high = next - 1; } - return (dest_str); + return (NULL); } void -__collate_lookup(struct xlocale_collate *table, const u_char *t, int *len, int *prim, int *sec) +_collate_lookup(struct xlocale_collate *table, const wchar_t *t, int *len, + int *pri, int which, const int **state) { - struct __collate_st_chain_pri *p2; + collate_chain_t *p2; + collate_large_t *match; + int p, l; + const int *sptr; + + /* + * If this is the "last" pass for the UNDEFINED, then + * we just return the priority itself. + */ + if (which >= table->info->directive_count) { + *pri = *t; + *len = 1; + *state = NULL; + return; + } + + /* + * If we have remaining substitution data from a previous + * call, consume it first. + */ + if ((sptr = *state) != NULL) { + *pri = *sptr; + sptr++; + if ((sptr == *state) || (sptr == NULL)) + *state = NULL; + else + *state = sptr; + *len = 0; + return; + } + /* No active substitutions */ *len = 1; - *prim = *sec = 0; - for (p2 = __collate_chain_pri_table; p2->str[0] != '\0'; p2++) { - if (*t == p2->str[0] && - strncmp(t, p2->str, strlen(p2->str)) == 0) { - *len = strlen(p2->str); - *prim = p2->prim; - *sec = p2->sec; - return; + + /* + * Check for composites such as dipthongs that collate as a + * single element (aka chains or collating-elements). + */ + if (((p2 = chainsearch(table, t, &l)) != NULL) && + ((p = p2->pri[which]) >= 0)) { + + *len = l; + *pri = p; + + } else if (*t <= UCHAR_MAX) { + + /* + * Character is a small (8-bit) character. + * We just look these up directly for speed. + */ + *pri = table->char_pri_table[*t].pri[which]; + + } else if ((table->info->large_count > 0) && + ((match = largesearch(table, *t)) != NULL)) { + + /* + * Character was found in the extended table. + */ + *pri = match->pri.pri[which]; + + } else { + /* + * Character lacks a specific definition. + */ + if (table->info->directive[which] & DIRECTIVE_UNDEFINED) { + /* Mask off sign bit to prevent ordering confusion. */ + *pri = (*t & COLLATE_MAX_PRIORITY); + } else { + *pri = table->info->undef_pri[which]; + } + /* No substitutions for undefined characters! */ + return; + } + + /* + * Try substituting (expanding) the character. We are + * currently doing this *after* the chain compression. I + * think it should not matter, but this way might be slightly + * faster. + * + * We do this after the priority search, as this will help us + * to identify a single key value. In order for this to work, + * its important that the priority assigned to a given element + * to be substituted be unique for that level. The localedef + * code ensures this for us. + */ + if ((sptr = substsearch(table, *pri, which)) != NULL) { + if ((*pri = *sptr) > 0) { + sptr++; + *state = *sptr ? sptr : NULL; } } - *prim = __collate_char_pri_table[*t].prim; - *sec = __collate_char_pri_table[*t].sec; + } -u_char * -__collate_strdup(u_char *s) +/* + * This is the meaty part of wcsxfrm & strxfrm. Note that it does + * NOT NULL terminate. That is left to the caller. + */ +size_t +_collate_wxfrm(struct xlocale_collate *table, const wchar_t *src, wchar_t *xf, + size_t room) { - u_char *t = strdup(s); + int pri; + int len; + const wchar_t *t; + wchar_t *tr = NULL; + int direc; + int pass; + const int32_t *state; + size_t want = 0; + size_t need = 0; + int ndir = table->info->directive_count; + + assert(src); + + for (pass = 0; pass <= ndir; pass++) { + + state = NULL; + + if (pass != 0) { + /* insert level separator from the previous pass */ + if (room) { + *xf++ = 1; + room--; + } + want++; + } + + /* special pass for undefined */ + if (pass == ndir) { + direc = DIRECTIVE_FORWARD | DIRECTIVE_UNDEFINED; + } else { + direc = table->info->directive[pass]; + } - if (t == NULL) - __collate_err(EX_OSERR, __func__); - return (t); + t = src; + + if (direc & DIRECTIVE_BACKWARD) { + wchar_t *bp, *fp, c; + free(tr); + if ((tr = wcsdup(t)) == NULL) { + errno = ENOMEM; + goto fail; + } + bp = tr; + fp = tr + wcslen(tr) - 1; + while (bp < fp) { + c = *bp; + *bp++ = *fp; + *fp-- = c; + } + t = (const wchar_t *)tr; + } + + if (direc & DIRECTIVE_POSITION) { + while (*t || state) { + _collate_lookup(table, t, &len, &pri, pass, &state); + t += len; + if (pri <= 0) { + if (pri < 0) { + errno = EINVAL; + goto fail; + } + pri = COLLATE_MAX_PRIORITY; + } + if (room) { + *xf++ = pri; + room--; + } + want++; + need = want; + } + } else { + while (*t || state) { + _collate_lookup(table, t, &len, &pri, pass, &state); + t += len; + if (pri <= 0) { + if (pri < 0) { + errno = EINVAL; + goto fail; + } + continue; + } + if (room) { + *xf++ = pri; + room--; + } + want++; + need = want; + } + } + } + free(tr); + return (need); + +fail: + free(tr); + return ((size_t)(-1)); } -void -__collate_err(int ex, const char *f) +/* + * In the non-POSIX case, we transform each character into a string of + * characters representing the character's priority. Since char is usually + * signed, we are limited by 7 bits per byte. To avoid zero, we need to add + * XFRM_OFFSET, so we can't use a full 7 bits. For simplicity, we choose 6 + * bits per byte. + * + * It turns out that we sometimes have real priorities that are + * 31-bits wide. (But: be careful using priorities where the high + * order bit is set -- i.e. the priority is negative. The sort order + * may be surprising!) + * + * TODO: This would be a good area to optimize somewhat. It turns out + * that real prioririties *except for the last UNDEFINED pass* are generally + * very small. We need the localedef code to precalculate the max + * priority for us, and ideally also give us a mask, and then we could + * severely limit what we expand to. + */ +#define XFRM_BYTES 6 +#define XFRM_OFFSET ('0') /* make all printable characters */ +#define XFRM_SHIFT 6 +#define XFRM_MASK ((1 << XFRM_SHIFT) - 1) +#define XFRM_SEP ('.') /* chosen to be less than XFRM_OFFSET */ + +static int +xfrm(struct xlocale_collate *table, unsigned char *p, int pri, int pass) { - const char *s; - int serrno = errno; - - s = _getprogname(); - _write(STDERR_FILENO, s, strlen(s)); - _write(STDERR_FILENO, ": ", 2); - s = f; - _write(STDERR_FILENO, s, strlen(s)); - _write(STDERR_FILENO, ": ", 2); - s = strerror(serrno); - _write(STDERR_FILENO, s, strlen(s)); - _write(STDERR_FILENO, "\n", 1); - exit(ex); + /* we use unsigned to ensure zero fill on right shift */ + uint32_t val = (uint32_t)table->info->pri_count[pass]; + int nc = 0; + + while (val) { + *p = (pri & XFRM_MASK) + XFRM_OFFSET; + pri >>= XFRM_SHIFT; + val >>= XFRM_SHIFT; + p++; + nc++; + } + return (nc); } -#ifdef COLLATE_DEBUG -void -__collate_print_tables() +size_t +_collate_sxfrm(struct xlocale_collate *table, const wchar_t *src, char *xf, + size_t room) { - int i; - struct __collate_st_chain_pri *p2; - - printf("Substitute table:\n"); - for (i = 0; i < UCHAR_MAX + 1; i++) - if (i != *__collate_substitute_table[i]) - printf("\t'%c' --> \"%s\"\n", i, - __collate_substitute_table[i]); - printf("Chain priority table:\n"); - for (p2 = __collate_chain_pri_table; p2->str[0] != '\0'; p2++) - printf("\t\"%s\" : %d %d\n", p2->str, p2->prim, p2->sec); - printf("Char priority table:\n"); - for (i = 0; i < UCHAR_MAX + 1; i++) - printf("\t'%c' : %d %d\n", i, __collate_char_pri_table[i].prim, - __collate_char_pri_table[i].sec); + int pri; + int len; + const wchar_t *t; + wchar_t *tr = NULL; + int direc; + int pass; + const int32_t *state; + size_t want = 0; + size_t need = 0; + int b; + uint8_t buf[XFRM_BYTES]; + int ndir = table->info->directive_count; + + assert(src); + + for (pass = 0; pass <= ndir; pass++) { + + state = NULL; + + if (pass != 0) { + /* insert level separator from the previous pass */ + if (room) { + *xf++ = XFRM_SEP; + room--; + } + want++; + } + + /* special pass for undefined */ + if (pass == ndir) { + direc = DIRECTIVE_FORWARD | DIRECTIVE_UNDEFINED; + } else { + direc = table->info->directive[pass]; + } + + t = src; + + if (direc & DIRECTIVE_BACKWARD) { + wchar_t *bp, *fp, c; + free(tr); + if ((tr = wcsdup(t)) == NULL) { + errno = ENOMEM; + goto fail; + } + bp = tr; + fp = tr + wcslen(tr) - 1; + while (bp < fp) { + c = *bp; + *bp++ = *fp; + *fp-- = c; + } + t = (const wchar_t *)tr; + } + + if (direc & DIRECTIVE_POSITION) { + while (*t || state) { + + _collate_lookup(table, t, &len, &pri, pass, &state); + t += len; + if (pri <= 0) { + if (pri < 0) { + errno = EINVAL; + goto fail; + } + pri = COLLATE_MAX_PRIORITY; + } + + b = xfrm(table, buf, pri, pass); + want += b; + if (room) { + while (b) { + b--; + if (room) { + *xf++ = buf[b]; + room--; + } + } + } + need = want; + } + } else { + while (*t || state) { + _collate_lookup(table, t, &len, &pri, pass, &state); + t += len; + if (pri <= 0) { + if (pri < 0) { + errno = EINVAL; + goto fail; + } + continue; + } + + b = xfrm(table, buf, pri, pass); + want += b; + if (room) { + + while (b) { + b--; + if (room) { + *xf++ = buf[b]; + room--; + } + } + } + need = want; + } + } + } + free(tr); + return (need); + +fail: + free(tr); + return ((size_t)(-1)); +} + +/* + * __collate_equiv_value returns the primary collation value for the given + * collating symbol specified by str and len. Zero or negative is returned + * if the collating symbol was not found. This function is used by bracket + * code in the TRE regex library. + */ +int +__collate_equiv_value(locale_t locale, const wchar_t *str, size_t len) +{ + int32_t e; + + if (len < 1 || len >= COLLATE_STR_LEN) + return (-1); + + FIX_LOCALE(locale); + struct xlocale_collate *table = + (struct xlocale_collate*)locale->components[XLC_COLLATE]; + + if (table->__collate_load_error) + return ((len == 1 && *str <= UCHAR_MAX) ? *str : -1); + + if (len == 1) { + e = -1; + if (*str <= UCHAR_MAX) + e = table->char_pri_table[*str].pri[0]; + else if (table->info->large_count > 0) { + collate_large_t *match_large; + match_large = largesearch(table, *str); + if (match_large) + e = match_large->pri.pri[0]; + } + if (e == 0) + return (1); + return (e > 0 ? e : 0); + } + if (table->info->chain_count > 0) { + wchar_t name[COLLATE_STR_LEN]; + collate_chain_t *match_chain; + int clen; + + wcsncpy (name, str, len); + name[len] = 0; + match_chain = chainsearch(table, name, &clen); + if (match_chain) { + e = match_chain->pri[0]; + if (e == 0) + return (1); + return (e < 0 ? -e : e); + } + } + return (0); } -#endif diff --git a/lib/libc/locale/collate.h b/lib/libc/locale/collate.h index ad034d4..9812589 100644 --- a/lib/libc/locale/collate.h +++ b/lib/libc/locale/collate.h @@ -1,4 +1,5 @@ /*- + * Copyright 2010 Nexenta Systems, Inc. All rights reserved. * Copyright (c) 1995 Alex Tatmanjants <alex@elvisti.kiev.ua> * at Electronni Visti IA, Kiev, Ukraine. * All rights reserved. @@ -40,42 +41,98 @@ #include <limits.h> #include "xlocale_private.h" -#define STR_LEN 10 -#define TABLE_SIZE 100 -#define COLLATE_VERSION "1.0\n" -#define COLLATE_VERSION1_2 "1.2\n" +/* + * Work around buildworld bootstrapping from older systems whose limits.h + * sets COLL_WEIGHTS_MAX to 0. + */ +#if COLL_WEIGHTS_MAX == 0 +#undef COLL_WEIGHTS_MAX +#define COLL_WEIGHTS_MAX 10 +#endif -struct __collate_st_char_pri { - int prim, sec; -}; -struct __collate_st_chain_pri { - u_char str[STR_LEN]; - int prim, sec; -}; +#define COLLATE_STR_LEN 24 /* should be 64-bit multiple */ +#define COLLATE_VERSION "BSD 1.0\n" + +#define COLLATE_MAX_PRIORITY (0x7fffffff) /* max signed value */ +#define COLLATE_SUBST_PRIORITY (0x40000000) /* bit indicates subst table */ -#define __collate_substitute_table (*__collate_substitute_table_ptr) -#define __collate_char_pri_table (*__collate_char_pri_table_ptr) +#define DIRECTIVE_UNDEF 0x00 +#define DIRECTIVE_FORWARD 0x01 +#define DIRECTIVE_BACKWARD 0x02 +#define DIRECTIVE_POSITION 0x04 +#define DIRECTIVE_UNDEFINED 0x08 /* special last weight for UNDEFINED */ + +#define DIRECTIVE_DIRECTION_MASK (DIRECTIVE_FORWARD | DIRECTIVE_BACKWARD) + +/* + * The collate file format is as follows: + * + * char version[COLLATE_STR_LEN]; // must be COLLATE_VERSION + * collate_info_t info; // see below, includes padding + * collate_char_pri_t char_data[256]; // 8 bit char values + * collate_subst_t subst[*]; // 0 or more substitutions + * collate_chain_pri_t chains[*]; // 0 or more chains + * collate_large_pri_t large[*]; // extended char priorities + * + * Note that all structures must be 32-bit aligned, as each structure + * contains 32-bit member fields. The entire file is mmap'd, so its + * critical that alignment be observed. It is not generally safe to + * use any 64-bit values in the structures. + */ + +typedef struct collate_info { + uint8_t directive_count; + uint8_t directive[COLL_WEIGHTS_MAX]; + int32_t pri_count[COLL_WEIGHTS_MAX]; + int32_t flags; + int32_t chain_count; + int32_t large_count; + int32_t subst_count[COLL_WEIGHTS_MAX]; + int32_t undef_pri[COLL_WEIGHTS_MAX]; +} collate_info_t; + +typedef struct collate_char { + int32_t pri[COLL_WEIGHTS_MAX]; +} collate_char_t; + +typedef struct collate_chain { + wchar_t str[COLLATE_STR_LEN]; + int32_t pri[COLL_WEIGHTS_MAX]; +} collate_chain_t; + +typedef struct collate_large { + int32_t val; + collate_char_t pri; +} collate_large_t; + +typedef struct collate_subst { + int32_t key; + int32_t pri[COLLATE_STR_LEN]; +} collate_subst_t; struct xlocale_collate { struct xlocale_component header; int __collate_load_error; - int __collate_substitute_nontrivial; + char * map; + size_t maplen; - u_char (*__collate_substitute_table_ptr)[UCHAR_MAX + 1][STR_LEN]; - struct __collate_st_char_pri (*__collate_char_pri_table_ptr)[UCHAR_MAX + 1]; - struct __collate_st_chain_pri *__collate_chain_pri_table; + collate_info_t *info; + collate_char_t *char_pri_table; + collate_large_t *large_pri_table; + collate_chain_t *chain_pri_table; + collate_subst_t *subst_table[COLL_WEIGHTS_MAX]; }; - __BEGIN_DECLS -u_char *__collate_strdup(u_char *); -u_char *__collate_substitute(struct xlocale_collate *, const u_char *); int __collate_load_tables(const char *); -void __collate_lookup(struct xlocale_collate *, const u_char *, int *, int *, int *); -int __collate_range_cmp(struct xlocale_collate *, int, int); -#ifdef COLLATE_DEBUG -void __collate_print_tables(void); -#endif +int __collate_equiv_value(locale_t, const wchar_t *, size_t); +void _collate_lookup(struct xlocale_collate *,const wchar_t *, int *, int *, + int, const int **); +int __collate_range_cmp(struct xlocale_collate *, wchar_t, wchar_t); +size_t _collate_wxfrm(struct xlocale_collate *, const wchar_t *, wchar_t *, + size_t); +size_t _collate_sxfrm(struct xlocale_collate *, const wchar_t *, char *, + size_t); __END_DECLS #endif /* !_COLLATE_H_ */ diff --git a/lib/libc/locale/collcmp.c b/lib/libc/locale/collcmp.c index aa17afd..102fbfb 100644 --- a/lib/libc/locale/collcmp.c +++ b/lib/libc/locale/collcmp.c @@ -33,6 +33,7 @@ __FBSDID("$FreeBSD$"); #include <string.h> +#include <wchar.h> #include <xlocale.h> #include "collate.h" @@ -40,13 +41,15 @@ __FBSDID("$FreeBSD$"); * Compare two characters using collate */ -int __collate_range_cmp(struct xlocale_collate *table, int c1, int c2) +int __collate_range_cmp(struct xlocale_collate *table, wchar_t c1, wchar_t c2) { - static char s1[2], s2[2]; + wchar_t s1[2], s2[2]; s1[0] = c1; + s1[1] = 0; s2[0] = c2; + s2[1] = 0; struct _xlocale l = {{0}}; l.components[XLC_COLLATE] = (struct xlocale_component *)table; - return (strcoll_l(s1, s2, &l)); + return (wcscoll_l(s1, s2, &l)); } diff --git a/lib/libc/locale/euc.c b/lib/libc/locale/euc.c index 26ad413..c2a2e3b 100644 --- a/lib/libc/locale/euc.c +++ b/lib/libc/locale/euc.c @@ -1,4 +1,6 @@ /*- + * Copyright 2013 Garrett D'Amore <garrett@damore.org> + * Copyright 2011 Nexenta Systems, Inc. All rights reserved. * Copyright (c) 2002-2004 Tim J. Robbins. All rights reserved. * Copyright (c) 1993 * The Regents of the University of California. All rights reserved. @@ -19,11 +21,7 @@ * 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. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors + * 3. 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. * @@ -56,17 +54,56 @@ __FBSDID("$FreeBSD$"); extern int __mb_sb_limit; -static size_t _EUC_mbrtowc(wchar_t * __restrict, const char * __restrict, +static size_t _EUC_mbrtowc_impl(wchar_t * __restrict, const char * __restrict, + size_t, mbstate_t * __restrict, uint8_t, uint8_t, uint8_t, uint8_t); +static size_t _EUC_wcrtomb_impl(char * __restrict, wchar_t, + mbstate_t * __restrict, uint8_t, uint8_t, uint8_t, uint8_t); + +static size_t _EUC_CN_mbrtowc(wchar_t * __restrict, const char * __restrict, size_t, mbstate_t * __restrict); -static int _EUC_mbsinit(const mbstate_t *); -static size_t _EUC_wcrtomb(char * __restrict, wchar_t, +static size_t _EUC_JP_mbrtowc(wchar_t * __restrict, const char * __restrict, + size_t, mbstate_t * __restrict); +static size_t _EUC_KR_mbrtowc(wchar_t * __restrict, const char * __restrict, + size_t, mbstate_t * __restrict); +static size_t _EUC_TW_mbrtowc(wchar_t * __restrict, const char * __restrict, + size_t, mbstate_t * __restrict); + +static size_t _EUC_CN_wcrtomb(char * __restrict, wchar_t, + mbstate_t * __restrict); +static size_t _EUC_JP_wcrtomb(char * __restrict, wchar_t, + mbstate_t * __restrict); +static size_t _EUC_KR_wcrtomb(char * __restrict, wchar_t, + mbstate_t * __restrict); +static size_t _EUC_TW_wcrtomb(char * __restrict, wchar_t, mbstate_t * __restrict); -typedef struct { - int count[4]; - wchar_t bits[4]; - wchar_t mask; -} _EucInfo; +static size_t _EUC_CN_mbsnrtowcs(wchar_t * __restrict, + const char ** __restrict, size_t, size_t, + mbstate_t * __restrict); +static size_t _EUC_JP_mbsnrtowcs(wchar_t * __restrict, + const char ** __restrict, size_t, size_t, + mbstate_t * __restrict); +static size_t _EUC_KR_mbsnrtowcs(wchar_t * __restrict, + const char ** __restrict, size_t, size_t, + mbstate_t * __restrict); +static size_t _EUC_TW_mbsnrtowcs(wchar_t * __restrict, + const char ** __restrict, size_t, size_t, + mbstate_t * __restrict); + +static size_t _EUC_CN_wcsnrtombs(char * __restrict, + const wchar_t ** __restrict, size_t, size_t, + mbstate_t * __restrict); +static size_t _EUC_JP_wcsnrtombs(char * __restrict, + const wchar_t ** __restrict, size_t, size_t, + mbstate_t * __restrict); +static size_t _EUC_KR_wcsnrtombs(char * __restrict, + const wchar_t ** __restrict, size_t, size_t, + mbstate_t * __restrict); +static size_t _EUC_TW_wcsnrtombs(char * __restrict, + const wchar_t ** __restrict, size_t, size_t, + mbstate_t * __restrict); + +static int _EUC_mbsinit(const mbstate_t *); typedef struct { wchar_t ch; @@ -74,94 +111,218 @@ typedef struct { int want; } _EucState; +static int +_EUC_mbsinit(const mbstate_t *ps) +{ + + return (ps == NULL || ((const _EucState *)ps)->want == 0); +} + +/* + * EUC-CN uses CS0, CS1 and CS2 (4 bytes). + */ int -_EUC_init(struct xlocale_ctype *l, _RuneLocale *rl) +_EUC_CN_init(struct xlocale_ctype *l, _RuneLocale *rl) { - _EucInfo *ei; - int x, new__mb_cur_max; - char *v, *e; + l->__mbrtowc = _EUC_CN_mbrtowc; + l->__wcrtomb = _EUC_CN_wcrtomb; + l->__mbsnrtowcs = _EUC_CN_mbsnrtowcs; + l->__wcsnrtombs = _EUC_CN_wcsnrtombs; + l->__mbsinit = _EUC_mbsinit; - if (rl->__variable == NULL) - return (EFTYPE); + l->runes = rl; + l->__mb_cur_max = 4; + l->__mb_sb_limit = 256; + return (0); +} - v = (char *)rl->__variable; +static size_t +_EUC_CN_mbrtowc(wchar_t * __restrict pwc, const char * __restrict s, + size_t n, mbstate_t * __restrict ps) +{ + return (_EUC_mbrtowc_impl(pwc, s, n, ps, SS2, 4, 0, 0)); +} - while (*v == ' ' || *v == '\t') - ++v; +static size_t +_EUC_CN_mbsnrtowcs(wchar_t * __restrict dst, + const char ** __restrict src, + size_t nms, size_t len, mbstate_t * __restrict ps) +{ + return (__mbsnrtowcs_std(dst, src, nms, len, ps, _EUC_CN_mbrtowc)); +} - if ((ei = malloc(sizeof(_EucInfo))) == NULL) - return (errno == 0 ? ENOMEM : errno); +static size_t +_EUC_CN_wcrtomb(char * __restrict s, wchar_t wc, + mbstate_t * __restrict ps) +{ + return (_EUC_wcrtomb_impl(s, wc, ps, SS2, 4, 0, 0)); +} - new__mb_cur_max = 0; - for (x = 0; x < 4; ++x) { - ei->count[x] = (int)strtol(v, &e, 0); - if (v == e || !(v = e)) { - free(ei); - return (EFTYPE); - } - if (new__mb_cur_max < ei->count[x]) - new__mb_cur_max = ei->count[x]; - while (*v == ' ' || *v == '\t') - ++v; - ei->bits[x] = (int)strtol(v, &e, 0); - if (v == e || !(v = e)) { - free(ei); - return (EFTYPE); - } - while (*v == ' ' || *v == '\t') - ++v; - } - ei->mask = (int)strtol(v, &e, 0); - if (v == e || !(v = e)) { - free(ei); - return (EFTYPE); - } - rl->__variable = ei; - rl->__variable_len = sizeof(_EucInfo); - l->runes = rl; - l->__mb_cur_max = new__mb_cur_max; - l->__mbrtowc = _EUC_mbrtowc; - l->__wcrtomb = _EUC_wcrtomb; +static size_t +_EUC_CN_wcsnrtombs(char * __restrict dst, const wchar_t ** __restrict src, + size_t nwc, size_t len, mbstate_t * __restrict ps) +{ + return (__wcsnrtombs_std(dst, src, nwc, len, ps, _EUC_CN_wcrtomb)); +} + +/* + * EUC-KR uses only CS0 and CS1. + */ +int +_EUC_KR_init(struct xlocale_ctype *l, _RuneLocale *rl) +{ + l->__mbrtowc = _EUC_KR_mbrtowc; + l->__wcrtomb = _EUC_KR_wcrtomb; + l->__mbsnrtowcs = _EUC_KR_mbsnrtowcs; + l->__wcsnrtombs = _EUC_KR_wcsnrtombs; l->__mbsinit = _EUC_mbsinit; - l->__mb_sb_limit = 256; + + l->runes = rl; + l->__mb_cur_max = 2; + l->__mb_sb_limit = 128; return (0); } -static int -_EUC_mbsinit(const mbstate_t *ps) +static size_t +_EUC_KR_mbrtowc(wchar_t * __restrict pwc, const char * __restrict s, + size_t n, mbstate_t * __restrict ps) { + return (_EUC_mbrtowc_impl(pwc, s, n, ps, 0, 0, 0, 0)); +} - return (ps == NULL || ((const _EucState *)ps)->want == 0); +static size_t +_EUC_KR_mbsnrtowcs(wchar_t * __restrict dst, + const char ** __restrict src, + size_t nms, size_t len, mbstate_t * __restrict ps) +{ + return (__mbsnrtowcs_std(dst, src, nms, len, ps, _EUC_KR_mbrtowc)); } -#define CEI ((_EucInfo *)(_CurrentRuneLocale->__variable)) +static size_t +_EUC_KR_wcrtomb(char * __restrict s, wchar_t wc, + mbstate_t * __restrict ps) +{ + return (_EUC_wcrtomb_impl(s, wc, ps, 0, 0, 0, 0)); +} -#define _SS2 0x008e -#define _SS3 0x008f +static size_t +_EUC_KR_wcsnrtombs(char * __restrict dst, const wchar_t ** __restrict src, + size_t nwc, size_t len, mbstate_t * __restrict ps) +{ + return (__wcsnrtombs_std(dst, src, nwc, len, ps, _EUC_KR_wcrtomb)); +} -#define GR_BITS 0x80808080 /* XXX: to be fixed */ +/* + * EUC-JP uses CS0, CS1, CS2, and CS3. + */ +int +_EUC_JP_init(struct xlocale_ctype *l, _RuneLocale *rl) +{ + l->__mbrtowc = _EUC_JP_mbrtowc; + l->__wcrtomb = _EUC_JP_wcrtomb; + l->__mbsnrtowcs = _EUC_JP_mbsnrtowcs; + l->__wcsnrtombs = _EUC_JP_wcsnrtombs; + l->__mbsinit = _EUC_mbsinit; -static __inline int -_euc_set(u_int c) + l->runes = rl; + l->__mb_cur_max = 3; + l->__mb_sb_limit = 196; + return (0); +} + +static size_t +_EUC_JP_mbrtowc(wchar_t * __restrict pwc, const char * __restrict s, + size_t n, mbstate_t * __restrict ps) { + return (_EUC_mbrtowc_impl(pwc, s, n, ps, SS2, 2, SS3, 3)); +} - c &= 0xff; - return ((c & 0x80) ? c == _SS3 ? 3 : c == _SS2 ? 2 : 1 : 0); +static size_t +_EUC_JP_mbsnrtowcs(wchar_t * __restrict dst, + const char ** __restrict src, + size_t nms, size_t len, mbstate_t * __restrict ps) +{ + return (__mbsnrtowcs_std(dst, src, nms, len, ps, _EUC_JP_mbrtowc)); } static size_t -_EUC_mbrtowc(wchar_t * __restrict pwc, const char * __restrict s, size_t n, +_EUC_JP_wcrtomb(char * __restrict s, wchar_t wc, mbstate_t * __restrict ps) { + return (_EUC_wcrtomb_impl(s, wc, ps, SS2, 2, SS3, 3)); +} + +static size_t +_EUC_JP_wcsnrtombs(char * __restrict dst, const wchar_t ** __restrict src, + size_t nwc, size_t len, mbstate_t * __restrict ps) +{ + return (__wcsnrtombs_std(dst, src, nwc, len, ps, _EUC_JP_wcrtomb)); +} + +/* + * EUC-TW uses CS0, CS1, and CS2. + */ +int +_EUC_TW_init(struct xlocale_ctype *l, _RuneLocale *rl) +{ + l->__mbrtowc = _EUC_TW_mbrtowc; + l->__wcrtomb = _EUC_TW_wcrtomb; + l->__mbsnrtowcs = _EUC_TW_mbsnrtowcs; + l->__wcsnrtombs = _EUC_TW_wcsnrtombs; + l->__mbsinit = _EUC_mbsinit; + + l->runes = rl; + l->__mb_cur_max = 4; + l->__mb_sb_limit = 256; + return (0); +} + +static size_t +_EUC_TW_mbrtowc(wchar_t * __restrict pwc, const char * __restrict s, + size_t n, mbstate_t * __restrict ps) +{ + return (_EUC_mbrtowc_impl(pwc, s, n, ps, SS2, 4, 0, 0)); +} + +static size_t +_EUC_TW_mbsnrtowcs(wchar_t * __restrict dst, + const char ** __restrict src, + size_t nms, size_t len, mbstate_t * __restrict ps) +{ + return (__mbsnrtowcs_std(dst, src, nms, len, ps, _EUC_TW_mbrtowc)); +} + +static size_t +_EUC_TW_wcrtomb(char * __restrict s, wchar_t wc, + mbstate_t * __restrict ps) +{ + return (_EUC_wcrtomb_impl(s, wc, ps, SS2, 4, 0, 0)); +} + +static size_t +_EUC_TW_wcsnrtombs(char * __restrict dst, const wchar_t ** __restrict src, + size_t nwc, size_t len, mbstate_t * __restrict ps) +{ + return (__wcsnrtombs_std(dst, src, nwc, len, ps, _EUC_TW_wcrtomb)); +} + +/* + * Common EUC code. + */ + +static size_t +_EUC_mbrtowc_impl(wchar_t * __restrict pwc, const char * __restrict s, + size_t n, mbstate_t * __restrict ps, + uint8_t cs2, uint8_t cs2width, uint8_t cs3, uint8_t cs3width) +{ _EucState *es; - int i, set, want; - wchar_t wc; - const char *os; + int i, want; + wchar_t wc = 0; + unsigned char ch, chs; es = (_EucState *)ps; - if (es->want < 0 || es->want > MB_CUR_MAX || es->set < 0 || - es->set > 3) { + if (es->want < 0 || es->want > MB_CUR_MAX) { errno = EINVAL; return ((size_t)-1); } @@ -176,58 +337,61 @@ _EUC_mbrtowc(wchar_t * __restrict pwc, const char * __restrict s, size_t n, /* Incomplete multibyte sequence */ return ((size_t)-2); - os = s; - if (es->want == 0) { - want = CEI->count[set = _euc_set(*s)]; - if (set == 2 || set == 3) { - --want; - if (--n == 0) { - /* Incomplete multibyte sequence */ - es->set = set; - es->want = want; - es->ch = 0; - return ((size_t)-2); - } - ++s; - if (*s == '\0') { - errno = EILSEQ; - return ((size_t)-1); - } + /* Fast path for plain ASCII (CS0) */ + if (((ch = (unsigned char)*s) & 0x80) == 0) { + if (pwc != NULL) + *pwc = ch; + return (ch != '\0' ? 1 : 0); } - wc = (unsigned char)*s++; + + if (ch >= 0xa1) { + /* CS1 */ + want = 2; + } else if (ch == cs2) { + want = cs2width; + } else if (ch == cs3) { + want = cs3width; + } else { + errno = EILSEQ; + return ((size_t)-1); + } + + + es->want = want; + es->ch = 0; } else { - set = es->set; want = es->want; wc = es->ch; } - for (i = (es->want == 0) ? 1 : 0; i < MIN(want, n); i++) { - if (*s == '\0') { - errno = EILSEQ; - return ((size_t)-1); - } - wc = (wc << 8) | (unsigned char)*s++; + + for (i = 0; i < MIN(want, n); i++) { + wc <<= 8; + chs = *s; + wc |= chs; + s++; } if (i < want) { /* Incomplete multibyte sequence */ - es->set = set; es->want = want - i; es->ch = wc; + errno = EILSEQ; return ((size_t)-2); } - wc = (wc & ~CEI->mask) | CEI->bits[set]; if (pwc != NULL) *pwc = wc; es->want = 0; - return (wc == L'\0' ? 0 : s - os); + return (wc == L'\0' ? 0 : want); } static size_t -_EUC_wcrtomb(char * __restrict s, wchar_t wc, mbstate_t * __restrict ps) +_EUC_wcrtomb_impl(char * __restrict s, wchar_t wc, + mbstate_t * __restrict ps, + uint8_t cs2, uint8_t cs2width, uint8_t cs3, uint8_t cs3width) { _EucState *es; - wchar_t m, nm; int i, len; + wchar_t nm; es = (_EucState *)ps; @@ -240,34 +404,52 @@ _EUC_wcrtomb(char * __restrict s, wchar_t wc, mbstate_t * __restrict ps) /* Reset to initial shift state (no-op) */ return (1); - m = wc & CEI->mask; - nm = wc & ~m; + if ((wc & ~0x7f) == 0) { + /* Fast path for plain ASCII (CS0) */ + *s = (char)wc; + return (1); + } - if (m == CEI->bits[1]) { -CodeSet1: - /* Codeset 1: The first byte must have 0x80 in it. */ - i = len = CEI->count[1]; - while (i-- > 0) - *s++ = (nm >> (i << 3)) | 0x80; + /* Determine the "length" */ + if ((unsigned)wc > 0xffffff) { + len = 4; + } else if ((unsigned)wc > 0xffff) { + len = 3; + } else if ((unsigned)wc > 0xff) { + len = 2; } else { - if (m == CEI->bits[0]) - i = len = CEI->count[0]; - else if (m == CEI->bits[2]) { - i = len = CEI->count[2]; - *s++ = _SS2; - --i; - /* SS2 designates G2 into GR */ - nm |= GR_BITS; - } else if (m == CEI->bits[3]) { - i = len = CEI->count[3]; - *s++ = _SS3; - --i; - /* SS3 designates G3 into GR */ - nm |= GR_BITS; - } else - goto CodeSet1; /* Bletch */ - while (i-- > 0) - *s++ = (nm >> (i << 3)) & 0xff; + len = 1; + } + + if (len > MB_CUR_MAX) { + errno = EILSEQ; + return ((size_t)-1); + } + + /* This first check excludes CS1, which is implicitly valid. */ + if ((wc < 0xa100) || (wc > 0xffff)) { + /* Check for valid CS2 or CS3 */ + nm = (wc >> ((len - 1) * 8)); + if (nm == cs2) { + if (len != cs2width) { + errno = EILSEQ; + return ((size_t)-1); + } + } else if (nm == cs3) { + if (len != cs3width) { + errno = EILSEQ; + return ((size_t)-1); + } + } else { + errno = EILSEQ; + return ((size_t)-1); + } + } + + /* Stash the bytes, least significant last */ + for (i = len - 1; i >= 0; i--) { + s[i] = (wc & 0xff); + wc >>= 8; } return (len); } diff --git a/lib/libc/locale/gb18030.c b/lib/libc/locale/gb18030.c index 9214385..d87b6f7 100644 --- a/lib/libc/locale/gb18030.c +++ b/lib/libc/locale/gb18030.c @@ -1,4 +1,6 @@ /*- + * Copyright 2013 Garrett D'Amore <garrett@damore.org> + * Copyright 2010 Nexenta Systems, Inc. All rights reserved. * Copyright (c) 2002-2004 Tim J. Robbins * All rights reserved. * @@ -28,6 +30,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ + /* * PRC National Standard GB 18030-2000 encoding of Chinese text. * @@ -49,6 +52,13 @@ static size_t _GB18030_mbrtowc(wchar_t * __restrict, const char * __restrict, static int _GB18030_mbsinit(const mbstate_t *); static size_t _GB18030_wcrtomb(char * __restrict, wchar_t, mbstate_t * __restrict); +static size_t _GB18030_mbsnrtowcs(wchar_t * __restrict, + const char ** __restrict, size_t, size_t, + mbstate_t * __restrict); +static size_t _GB18030_wcsnrtombs(char * __restrict, + const wchar_t ** __restrict, size_t, size_t, + mbstate_t * __restrict); + typedef struct { int count; @@ -62,6 +72,8 @@ _GB18030_init(struct xlocale_ctype *l, _RuneLocale *rl) l->__mbrtowc = _GB18030_mbrtowc; l->__wcrtomb = _GB18030_wcrtomb; l->__mbsinit = _GB18030_mbsinit; + l->__mbsnrtowcs = _GB18030_mbsnrtowcs; + l->__wcsnrtombs = _GB18030_wcsnrtombs; l->runes = rl; l->__mb_cur_max = 4; l->__mb_sb_limit = 128; @@ -222,3 +234,19 @@ ilseq: errno = EILSEQ; return ((size_t)-1); } + +static size_t +_GB18030_mbsnrtowcs(wchar_t * __restrict dst, + const char ** __restrict src, size_t nms, size_t len, + mbstate_t * __restrict ps) +{ + return (__mbsnrtowcs_std(dst, src, nms, len, ps, _GB18030_mbrtowc)); +} + +static size_t +_GB18030_wcsnrtombs(char * __restrict dst, + const wchar_t ** __restrict src, size_t nwc, size_t len, + mbstate_t * __restrict ps) +{ + return (__wcsnrtombs_std(dst, src, nwc, len, ps, _GB18030_wcrtomb)); +} diff --git a/lib/libc/locale/gb2312.c b/lib/libc/locale/gb2312.c index 5fbc07d..032a3e2 100644 --- a/lib/libc/locale/gb2312.c +++ b/lib/libc/locale/gb2312.c @@ -1,4 +1,6 @@ /*- + * Copyright 2013 Garrett D'Amore <garrett@damore.org> + * Copyright 2010 Nexenta Systems, Inc. All rights reserved. * Copyright (c) 2004 Tim J. Robbins. All rights reserved. * Copyright (c) 2003 David Xu <davidxu@freebsd.org> * All rights reserved. @@ -45,6 +47,13 @@ static size_t _GB2312_mbrtowc(wchar_t * __restrict, const char * __restrict, static int _GB2312_mbsinit(const mbstate_t *); static size_t _GB2312_wcrtomb(char * __restrict, wchar_t, mbstate_t * __restrict); +static size_t _GB2312_mbsnrtowcs(wchar_t * __restrict, + const char ** __restrict, size_t, size_t, + mbstate_t * __restrict); +static size_t _GB2312_wcsnrtombs(char * __restrict, + const wchar_t ** __restrict, size_t, size_t, + mbstate_t * __restrict); + typedef struct { int count; @@ -59,6 +68,8 @@ _GB2312_init(struct xlocale_ctype *l, _RuneLocale *rl) l->__mbrtowc = _GB2312_mbrtowc; l->__wcrtomb = _GB2312_wcrtomb; l->__mbsinit = _GB2312_mbsinit; + l->__mbsnrtowcs = _GB2312_mbsnrtowcs; + l->__wcsnrtombs = _GB2312_wcsnrtombs; l->__mb_cur_max = 2; l->__mb_sb_limit = 128; return (0); @@ -71,7 +82,7 @@ _GB2312_mbsinit(const mbstate_t *ps) return (ps == NULL || ((const _GB2312State *)ps)->count == 0); } -static __inline int +static int _GB2312_check(const char *str, size_t n) { const u_char *s = (const u_char *)str; @@ -90,7 +101,7 @@ _GB2312_check(const char *str, size_t n) } else if (s[0] & 0x80) { /* Invalid multibyte sequence */ return (-1); - } + } return (1); } @@ -158,3 +169,19 @@ _GB2312_wcrtomb(char * __restrict s, wchar_t wc, mbstate_t * __restrict ps) *s = wc & 0xff; return (1); } + +static size_t +_GB2312_mbsnrtowcs(wchar_t * __restrict dst, + const char ** __restrict src, size_t nms, size_t len, + mbstate_t * __restrict ps) +{ + return (__mbsnrtowcs_std(dst, src, nms, len, ps, _GB2312_mbrtowc)); +} + +static size_t +_GB2312_wcsnrtombs(char * __restrict dst, + const wchar_t ** __restrict src, size_t nwc, size_t len, + mbstate_t * __restrict ps) +{ + return (__wcsnrtombs_std(dst, src, nwc, len, ps, _GB2312_wcrtomb)); +} diff --git a/lib/libc/locale/gbk.c b/lib/libc/locale/gbk.c index 43269c7..c3d16f6 100644 --- a/lib/libc/locale/gbk.c +++ b/lib/libc/locale/gbk.c @@ -1,4 +1,6 @@ /*- + * Copyright 2013 Garrett D'Amore <garrett@damore.org> + * Copyright 2010 Nexenta Systems, Inc. All rights reserved. * Copyright (c) 2002-2004 Tim J. Robbins. All rights reserved. * Copyright (c) 1993 * The Regents of the University of California. All rights reserved. @@ -54,6 +56,12 @@ static size_t _GBK_mbrtowc(wchar_t * __restrict, const char * __restrict, static int _GBK_mbsinit(const mbstate_t *); static size_t _GBK_wcrtomb(char * __restrict, wchar_t, mbstate_t * __restrict); +static size_t _GBK_mbsnrtowcs(wchar_t * __restrict, + const char ** __restrict, size_t, size_t, + mbstate_t * __restrict); +static size_t _GBK_wcsnrtombs(char * __restrict, + const wchar_t ** __restrict, size_t, size_t, + mbstate_t * __restrict); typedef struct { wchar_t ch; @@ -66,6 +74,8 @@ _GBK_init(struct xlocale_ctype *l, _RuneLocale *rl) l->__mbrtowc = _GBK_mbrtowc; l->__wcrtomb = _GBK_wcrtomb; l->__mbsinit = _GBK_mbsinit; + l->__mbsnrtowcs = _GBK_mbsnrtowcs; + l->__wcsnrtombs = _GBK_wcsnrtombs; l->runes = rl; l->__mb_cur_max = 2; l->__mb_sb_limit = 128; @@ -79,7 +89,7 @@ _GBK_mbsinit(const mbstate_t *ps) return (ps == NULL || ((const _GBKState *)ps)->ch == 0); } -static __inline int +static int _gbk_check(u_int c) { @@ -140,7 +150,7 @@ _GBK_mbrtowc(wchar_t * __restrict pwc, const char * __restrict s, size_t n, wc = (wc << 8) | (*s++ & 0xff); if (pwc != NULL) *pwc = wc; - return (2); + return (2); } else { if (pwc != NULL) *pwc = wc; @@ -171,3 +181,17 @@ _GBK_wcrtomb(char * __restrict s, wchar_t wc, mbstate_t * __restrict ps) *s = wc & 0xff; return (1); } + +static size_t +_GBK_mbsnrtowcs(wchar_t * __restrict dst, const char ** __restrict src, + size_t nms, size_t len, mbstate_t * __restrict ps) +{ + return (__mbsnrtowcs_std(dst, src, nms, len, ps, _GBK_mbrtowc)); +} + +static size_t +_GBK_wcsnrtombs(char * __restrict dst, const wchar_t ** __restrict src, + size_t nwc, size_t len, mbstate_t * __restrict ps) +{ + return (__wcsnrtombs_std(dst, src, nwc, len, ps, _GBK_wcrtomb)); +} diff --git a/lib/libc/locale/isctype.c b/lib/libc/locale/isctype.c index 2550534..8f93f19 100644 --- a/lib/libc/locale/isctype.c +++ b/lib/libc/locale/isctype.c @@ -54,7 +54,7 @@ digittoint(int c) int isalnum(int c) { - return (__sbistype(c, _CTYPE_A|_CTYPE_D)); + return (__sbistype(c, _CTYPE_A|_CTYPE_N)); } #undef isalpha @@ -124,7 +124,7 @@ islower(int c) int isnumber(int c) { - return (__sbistype(c, _CTYPE_D)); + return (__sbistype(c, _CTYPE_N)); } #undef isphonogram diff --git a/lib/libc/locale/iswctype.c b/lib/libc/locale/iswctype.c index 59d432c..dad0621 100644 --- a/lib/libc/locale/iswctype.c +++ b/lib/libc/locale/iswctype.c @@ -44,7 +44,7 @@ __FBSDID("$FreeBSD$"); int iswalnum(wint_t wc) { - return (__istype(wc, _CTYPE_A|_CTYPE_D)); + return (__istype(wc, _CTYPE_A|_CTYPE_N)); } #undef iswalpha @@ -79,7 +79,7 @@ iswcntrl(wint_t wc) int iswdigit(wint_t wc) { - return (__isctype(wc, _CTYPE_D)); + return (__istype(wc, _CTYPE_D)); } #undef iswgraph @@ -114,7 +114,7 @@ iswlower(wint_t wc) int iswnumber(wint_t wc) { - return (__istype(wc, _CTYPE_D)); + return (__istype(wc, _CTYPE_N)); } #undef iswphonogram @@ -170,7 +170,7 @@ iswupper(wint_t wc) int iswxdigit(wint_t wc) { - return (__isctype(wc, _CTYPE_X)); + return (__istype(wc, _CTYPE_X)); } #undef towlower diff --git a/lib/libc/locale/mblocal.h b/lib/libc/locale/mblocal.h index d172764..75eab96 100644 --- a/lib/libc/locale/mblocal.h +++ b/lib/libc/locale/mblocal.h @@ -1,4 +1,6 @@ /*- + * Copyright 2013 Garrett D'Amore <garrett@damore.org> + * Copyright 2011 Nexenta Systems, Inc. All rights reserved. * Copyright (c) 2004 Tim J. Robbins. * All rights reserved. * @@ -37,6 +39,8 @@ #include <runetype.h> #include "xlocale_private.h" +#define SS2 0x008e +#define SS3 0x008f /* * Conversion function pointers for current encoding. @@ -62,18 +66,25 @@ extern struct xlocale_ctype __xlocale_global_ctype; * Rune initialization function prototypes. */ int _none_init(struct xlocale_ctype *, _RuneLocale *); -int _ascii_init(struct xlocale_ctype *, _RuneLocale *); int _UTF8_init(struct xlocale_ctype *, _RuneLocale *); -int _EUC_init(struct xlocale_ctype *, _RuneLocale *); +int _EUC_CN_init(struct xlocale_ctype *, _RuneLocale *); +int _EUC_JP_init(struct xlocale_ctype *, _RuneLocale *); +int _EUC_KR_init(struct xlocale_ctype *, _RuneLocale *); +int _EUC_TW_init(struct xlocale_ctype *, _RuneLocale *); int _GB18030_init(struct xlocale_ctype *, _RuneLocale *); int _GB2312_init(struct xlocale_ctype *, _RuneLocale *); int _GBK_init(struct xlocale_ctype *, _RuneLocale *); int _BIG5_init(struct xlocale_ctype *, _RuneLocale *); int _MSKanji_init(struct xlocale_ctype *, _RuneLocale *); +int _ascii_init(struct xlocale_ctype *, _RuneLocale *); -extern size_t __mbsnrtowcs_std(wchar_t * __restrict, const char ** __restrict, - size_t, size_t, mbstate_t * __restrict); -extern size_t __wcsnrtombs_std(char * __restrict, const wchar_t ** __restrict, - size_t, size_t, mbstate_t * __restrict); +typedef size_t (*mbrtowc_pfn_t)(wchar_t * __restrict, + const char * __restrict, size_t, mbstate_t * __restrict); +typedef size_t (*wcrtomb_pfn_t)(char * __restrict, wchar_t, + mbstate_t * __restrict); +size_t __mbsnrtowcs_std(wchar_t * __restrict, const char ** __restrict, + size_t, size_t, mbstate_t * __restrict, mbrtowc_pfn_t); +size_t __wcsnrtombs_std(char * __restrict, const wchar_t ** __restrict, + size_t, size_t, mbstate_t * __restrict, wcrtomb_pfn_t); #endif /* _MBLOCAL_H_ */ diff --git a/lib/libc/locale/mbsnrtowcs.c b/lib/libc/locale/mbsnrtowcs.c index 15b48dd7..9e6baad 100644 --- a/lib/libc/locale/mbsnrtowcs.c +++ b/lib/libc/locale/mbsnrtowcs.c @@ -1,4 +1,6 @@ /*- + * Copyright 2013 Garrett D'Amore <garrett@damore.org> + * Copyright 2010 Nexenta Systems, Inc. All rights reserved. * Copyright (c) 2002-2004 Tim J. Robbins. * * Copyright (c) 2011 The FreeBSD Foundation @@ -56,20 +58,20 @@ mbsnrtowcs(wchar_t * __restrict dst, const char ** __restrict src, size_t __mbsnrtowcs_std(wchar_t * __restrict dst, const char ** __restrict src, - size_t nms, size_t len, mbstate_t * __restrict ps) + size_t nms, size_t len, mbstate_t * __restrict ps, + mbrtowc_pfn_t pmbrtowc) { const char *s; size_t nchr; wchar_t wc; size_t nb; - struct xlocale_ctype *ct = XLOCALE_CTYPE(__get_locale()); s = *src; nchr = 0; if (dst == NULL) { for (;;) { - if ((nb = ct->__mbrtowc(&wc, s, nms, ps)) == (size_t)-1) + if ((nb = pmbrtowc(&wc, s, nms, ps)) == (size_t)-1) /* Invalid sequence - mbrtowc() sets errno. */ return ((size_t)-1); else if (nb == 0 || nb == (size_t)-2) @@ -82,7 +84,7 @@ __mbsnrtowcs_std(wchar_t * __restrict dst, const char ** __restrict src, } while (len-- > 0) { - if ((nb = ct->__mbrtowc(dst, s, nms, ps)) == (size_t)-1) { + if ((nb = pmbrtowc(dst, s, nms, ps)) == (size_t)-1) { *src = s; return ((size_t)-1); } else if (nb == (size_t)-2) { diff --git a/lib/libc/locale/mskanji.c b/lib/libc/locale/mskanji.c index 9fdd080..dc2d0e1 100644 --- a/lib/libc/locale/mskanji.c +++ b/lib/libc/locale/mskanji.c @@ -1,4 +1,6 @@ /* + * Copyright 2013 Garrett D'Amore <garrett@damore.org> + * Copyright 2010 Nexenta Systems, Inc. All rights reserved. * Copyright (c) 2002-2004 Tim J. Robbins. All rights reserved. * * ja_JP.SJIS locale table for BSD4.4/rune @@ -28,14 +30,14 @@ * 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. + * 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) @@ -59,6 +61,12 @@ static size_t _MSKanji_mbrtowc(wchar_t * __restrict, const char * __restrict, static int _MSKanji_mbsinit(const mbstate_t *); static size_t _MSKanji_wcrtomb(char * __restrict, wchar_t, mbstate_t * __restrict); +static size_t _MSKanji_mbsnrtowcs(wchar_t * __restrict, + const char ** __restrict, size_t, size_t, + mbstate_t * __restrict); +static size_t _MSKanji_wcsnrtombs(char * __restrict, + const wchar_t ** __restrict, size_t, size_t, + mbstate_t * __restrict); typedef struct { wchar_t ch; @@ -70,6 +78,8 @@ _MSKanji_init(struct xlocale_ctype *l, _RuneLocale *rl) l->__mbrtowc = _MSKanji_mbrtowc; l->__wcrtomb = _MSKanji_wcrtomb; + l->__mbsnrtowcs = _MSKanji_mbsnrtowcs; + l->__wcsnrtombs = _MSKanji_wcsnrtombs; l->__mbsinit = _MSKanji_mbsinit; l->runes = rl; l->__mb_cur_max = 2; @@ -163,3 +173,19 @@ _MSKanji_wcrtomb(char * __restrict s, wchar_t wc, mbstate_t * __restrict ps) *s++ = wc >> (i << 3); return (len); } + +static size_t +_MSKanji_mbsnrtowcs(wchar_t * __restrict dst, + const char ** __restrict src, size_t nms, + size_t len, mbstate_t * __restrict ps) +{ + return (__mbsnrtowcs_std(dst, src, nms, len, ps, _MSKanji_mbrtowc)); +} + +static size_t +_MSKanji_wcsnrtombs(char * __restrict dst, + const wchar_t ** __restrict src, size_t nwc, + size_t len, mbstate_t * __restrict ps) +{ + return (__wcsnrtombs_std(dst, src, nwc, len, ps, _MSKanji_wcrtomb)); +} diff --git a/lib/libc/locale/nl_langinfo.c b/lib/libc/locale/nl_langinfo.c index 3e8fe7c..e3b370a 100644 --- a/lib/libc/locale/nl_langinfo.c +++ b/lib/libc/locale/nl_langinfo.c @@ -37,7 +37,10 @@ __FBSDID("$FreeBSD$"); #include <locale.h> #include <stdlib.h> #include <string.h> +#include <runetype.h> +#include <wchar.h> +#include "mblocal.h" #include "lnumeric.h" #include "lmessages.h" #include "lmonetary.h" @@ -54,14 +57,25 @@ nl_langinfo_l(nl_item item, locale_t loc) switch (item) { case CODESET: - ret = ""; - if ((s = querylocale(LC_CTYPE_MASK, loc)) != NULL) { - if ((cs = strchr(s, '.')) != NULL) - ret = cs + 1; - else if (strcmp(s, "C") == 0 || - strcmp(s, "POSIX") == 0) - ret = "US-ASCII"; - } + s = XLOCALE_CTYPE(loc)->runes->__encoding; + if (strcmp(s, "EUC-CN") == 0) + ret = "eucCN"; + else if (strcmp(s, "EUC-JP") == 0) + ret = "eucJP"; + else if (strcmp(s, "EUC-KR") == 0) + ret = "eucKR"; + else if (strcmp(s, "EUC-TW") == 0) + ret = "eucTW"; + else if (strcmp(s, "BIG5") == 0) + ret = "Big5"; + else if (strcmp(s, "MSKanji") == 0) + ret = "SJIS"; + else if (strcmp(s, "NONE") == 0) + ret = "US-ASCII"; + else if (strncmp(s, "NONE:", 5) == 0) + ret = (char *)(s + 5); + else + ret = (char *)s; break; case D_T_FMT: ret = (char *) __get_current_time_locale(loc)->c_fmt; diff --git a/lib/libc/locale/none.c b/lib/libc/locale/none.c index cacfd73..c4695fd 100644 --- a/lib/libc/locale/none.c +++ b/lib/libc/locale/none.c @@ -1,4 +1,6 @@ /*- + * Copyright 2013 Garrett D'Amore <garrett@damore.org> + * Copyright 2010 Nexenta Systems, Inc. All rights reserved. * Copyright (c) 2002-2004 Tim J. Robbins. All rights reserved. * Copyright (c) 1993 * The Regents of the University of California. All rights reserved. @@ -187,16 +189,6 @@ _none_wcsnrtombs(char * __restrict dst, const wchar_t ** __restrict src, /* setup defaults */ -size_t (*__mbrtowc)(wchar_t * __restrict, const char * __restrict, size_t, - mbstate_t * __restrict) = _none_mbrtowc; -int (*__mbsinit)(const mbstate_t *) = _none_mbsinit; -size_t (*__mbsnrtowcs)(wchar_t * __restrict, const char ** __restrict, - size_t, size_t, mbstate_t * __restrict) = _none_mbsnrtowcs; -size_t (*__wcrtomb)(char * __restrict, wchar_t, mbstate_t * __restrict) = - _none_wcrtomb; -size_t (*__wcsnrtombs)(char * __restrict, const wchar_t ** __restrict, - size_t, size_t, mbstate_t * __restrict) = _none_wcsnrtombs; - struct xlocale_ctype __xlocale_global_ctype = { {{0}, "C"}, (_RuneLocale*)&_DefaultRuneLocale, diff --git a/lib/libc/locale/rune.c b/lib/libc/locale/rune.c index f72ba74..00ef19b 100644 --- a/lib/libc/locale/rune.c +++ b/lib/libc/locale/rune.c @@ -1,4 +1,6 @@ /*- + * Copyright 2014 Garrett D'Amore <garrett@damore.org> + * Copyright 2010 Nexenta Systems, Inc. All rights reserved. * Copyright (c) 1993 * The Regents of the University of California. All rights reserved. * @@ -45,14 +47,15 @@ __FBSDID("$FreeBSD$"); #include <stdlib.h> #include <sys/types.h> #include <sys/stat.h> +#include <sys/mman.h> +#include <fcntl.h> +#include <unistd.h> #include "un-namespace.h" #include "runefile.h" -_RuneLocale *_Read_RuneMagi(FILE *); - _RuneLocale * -_Read_RuneMagi(FILE *fp) +_Read_RuneMagi(const char *fname) { char *fdata, *data; void *lastp; @@ -67,119 +70,77 @@ _Read_RuneMagi(FILE *fp) _FileRuneEntry *maplower_ext_ranges; _FileRuneEntry *mapupper_ext_ranges; int runetype_ext_len = 0; + int fd; - if (_fstat(fileno(fp), &sb) < 0) + if ((fd = _open(fname, O_RDONLY)) < 0) { + errno = EINVAL; return (NULL); + } - if ((size_t)sb.st_size < sizeof(_FileRuneLocale)) { - errno = EFTYPE; + if (_fstat(fd, &sb) < 0) { + (void) _close(fd); + errno = EINVAL; return (NULL); } - if ((fdata = malloc(sb.st_size)) == NULL) - return (NULL); - - errno = 0; - rewind(fp); /* Someone might have read the magic number once already */ - if (errno) { - saverr = errno; - free(fdata); - errno = saverr; + if ((size_t)sb.st_size < sizeof (_FileRuneLocale)) { + (void) _close(fd); + errno = EINVAL; return (NULL); } - if (fread(fdata, sb.st_size, 1, fp) != 1) { - saverr = errno; - free(fdata); - errno = saverr; + + fdata = mmap(NULL, sb.st_size, PROT_READ, MAP_PRIVATE, fd, 0); + (void) _close(fd); + if (fdata == NULL) { + errno = EINVAL; return (NULL); } - frl = (_FileRuneLocale *)fdata; + frl = (_FileRuneLocale *)(void *)fdata; lastp = fdata + sb.st_size; variable = frl + 1; - if (memcmp(frl->magic, _FILE_RUNE_MAGIC_1, sizeof(frl->magic))) { - free(fdata); - errno = EFTYPE; - return (NULL); - } - - frl->variable_len = ntohl(frl->variable_len); - frl->runetype_ext_nranges = ntohl(frl->runetype_ext_nranges); - frl->maplower_ext_nranges = ntohl(frl->maplower_ext_nranges); - frl->mapupper_ext_nranges = ntohl(frl->mapupper_ext_nranges); - - for (x = 0; x < _CACHED_RUNES; ++x) { - frl->runetype[x] = ntohl(frl->runetype[x]); - frl->maplower[x] = ntohl(frl->maplower[x]); - frl->mapupper[x] = ntohl(frl->mapupper[x]); + if (memcmp(frl->magic, _FILE_RUNE_MAGIC_1, sizeof (frl->magic))) { + goto invalid; } runetype_ext_ranges = (_FileRuneEntry *)variable; variable = runetype_ext_ranges + frl->runetype_ext_nranges; if (variable > lastp) { - free(fdata); - errno = EFTYPE; - return (NULL); + goto invalid; } maplower_ext_ranges = (_FileRuneEntry *)variable; variable = maplower_ext_ranges + frl->maplower_ext_nranges; if (variable > lastp) { - free(fdata); - errno = EFTYPE; - return (NULL); + goto invalid; } mapupper_ext_ranges = (_FileRuneEntry *)variable; variable = mapupper_ext_ranges + frl->mapupper_ext_nranges; if (variable > lastp) { - free(fdata); - errno = EFTYPE; - return (NULL); + goto invalid; } frr = runetype_ext_ranges; for (x = 0; x < frl->runetype_ext_nranges; ++x) { uint32_t *types; - frr[x].min = ntohl(frr[x].min); - frr[x].max = ntohl(frr[x].max); - frr[x].map = ntohl(frr[x].map); if (frr[x].map == 0) { int len = frr[x].max - frr[x].min + 1; types = variable; variable = types + len; runetype_ext_len += len; if (variable > lastp) { - free(fdata); - errno = EFTYPE; - return (NULL); + goto invalid; } - while (len-- > 0) - types[len] = ntohl(types[len]); } } - frr = maplower_ext_ranges; - for (x = 0; x < frl->maplower_ext_nranges; ++x) { - frr[x].min = ntohl(frr[x].min); - frr[x].max = ntohl(frr[x].max); - frr[x].map = ntohl(frr[x].map); - } - - frr = mapupper_ext_ranges; - for (x = 0; x < frl->mapupper_ext_nranges; ++x) { - frr[x].min = ntohl(frr[x].min); - frr[x].max = ntohl(frr[x].max); - frr[x].map = ntohl(frr[x].map); - } if ((char *)variable + frl->variable_len > (char *)lastp) { - free(fdata); - errno = EFTYPE; - return (NULL); + goto invalid; } /* @@ -192,7 +153,7 @@ _Read_RuneMagi(FILE *fp) frl->variable_len); if (data == NULL) { saverr = errno; - free(fdata); + munmap(fdata, sb.st_size); errno = saverr; return (NULL); } @@ -202,7 +163,6 @@ _Read_RuneMagi(FILE *fp) memcpy(rl->__magic, _RUNE_MAGIC_1, sizeof(rl->__magic)); memcpy(rl->__encoding, frl->encoding, sizeof(rl->__encoding)); - rl->__invalid_rune = 0; rl->__variable_len = frl->variable_len; rl->__runetype_ext.__nranges = frl->runetype_ext_nranges; @@ -265,7 +225,7 @@ _Read_RuneMagi(FILE *fp) } memcpy(rl->__variable, variable, rl->__variable_len); - free(fdata); + munmap(fdata, sb.st_size); /* * Go out and zero pointers that should be zero. @@ -283,4 +243,9 @@ _Read_RuneMagi(FILE *fp) rl->__mapupper_ext.__ranges = NULL; return (rl); + +invalid: + munmap(fdata, sb.st_size); + errno = EINVAL; + return (NULL); } diff --git a/lib/libc/locale/setrunelocale.c b/lib/libc/locale/setrunelocale.c index 0a0943f..1ebfc38 100644 --- a/lib/libc/locale/setrunelocale.c +++ b/lib/libc/locale/setrunelocale.c @@ -63,23 +63,15 @@ _Thread_local const _RuneLocale *_ThreadRuneLocale; extern int __mb_sb_limit; -extern _RuneLocale *_Read_RuneMagi(FILE *); +extern _RuneLocale *_Read_RuneMagi(const char *); static int __setrunelocale(struct xlocale_ctype *l, const char *); -#define __collate_substitute_nontrivial (table->__collate_substitute_nontrivial) -#define __collate_substitute_table_ptr (table->__collate_substitute_table_ptr) -#define __collate_char_pri_table_ptr (table->__collate_char_pri_table_ptr) -#define __collate_chain_pri_table (table->__collate_chain_pri_table) - - static void destruct_ctype(void *v) { struct xlocale_ctype *l = v; - if (strcmp(l->runes->__encoding, "EUC") == 0) - free(l->runes->__variable); if (&_DefaultRuneLocale != l->runes) free(l->runes); free(l); @@ -95,12 +87,7 @@ __getCurrentRuneLocale(void) static void free_runes(_RuneLocale *rl) { - - /* FIXME: The "EUC" check here is a hideous abstraction violation. */ if ((rl != &_DefaultRuneLocale) && (rl)) { - if (strcmp(rl->__encoding, "EUC") == 0) { - free(rl->__variable); - } free(rl); } } @@ -108,10 +95,9 @@ free_runes(_RuneLocale *rl) static int __setrunelocale(struct xlocale_ctype *l, const char *encoding) { - FILE *fp; - char name[PATH_MAX]; _RuneLocale *rl; - int saverr, ret; + int ret; + char *path; struct xlocale_ctype saved = *l; /* @@ -124,37 +110,39 @@ __setrunelocale(struct xlocale_ctype *l, const char *encoding) } /* Range checking not needed, encoding length already checked before */ - (void) strcpy(name, _PathLocale); - (void) strcat(name, "/"); - (void) strcat(name, encoding); - (void) strcat(name, "/LC_CTYPE"); - - if ((fp = fopen(name, "re")) == NULL) - return (errno == 0 ? ENOENT : errno); - - if ((rl = _Read_RuneMagi(fp)) == NULL) { - saverr = (errno == 0 ? EFTYPE : errno); - (void)fclose(fp); - return (saverr); + asprintf(&path, "%s/%s/LC_CTYPE", _PathLocale, encoding); + if (path == NULL) + return (0); + + if ((rl = _Read_RuneMagi(path)) == NULL) { + free(path); + errno = EINVAL; + return (errno); } - (void)fclose(fp); + free(path); l->__mbrtowc = NULL; l->__mbsinit = NULL; - l->__mbsnrtowcs = __mbsnrtowcs_std; + l->__mbsnrtowcs = NULL; l->__wcrtomb = NULL; - l->__wcsnrtombs = __wcsnrtombs_std; + l->__wcsnrtombs = NULL; rl->__sputrune = NULL; rl->__sgetrune = NULL; - if (strcmp(rl->__encoding, "NONE") == 0) - ret = _none_init(l, rl); - else if (strcmp(rl->__encoding, "ASCII") == 0) + if (strcmp(rl->__encoding, "NONE:US-ASCII") == 0) ret = _ascii_init(l, rl); + else if (strncmp(rl->__encoding, "NONE", 4) == 0) + ret = _none_init(l, rl); else if (strcmp(rl->__encoding, "UTF-8") == 0) ret = _UTF8_init(l, rl); - else if (strcmp(rl->__encoding, "EUC") == 0) - ret = _EUC_init(l, rl); + else if (strcmp(rl->__encoding, "EUC-CN") == 0) + ret = _EUC_CN_init(l, rl); + else if (strcmp(rl->__encoding, "EUC-JP") == 0) + ret = _EUC_JP_init(l, rl); + else if (strcmp(rl->__encoding, "EUC-KR") == 0) + ret = _EUC_KR_init(l, rl); + else if (strcmp(rl->__encoding, "EUC-TW") == 0) + ret = _EUC_TW_init(l, rl); else if (strcmp(rl->__encoding, "GB18030") == 0) ret = _GB18030_init(l, rl); else if (strcmp(rl->__encoding, "GB2312") == 0) @@ -211,7 +199,7 @@ __set_thread_rune_locale(locale_t loc) #endif void * -__ctype_load(const char *locale, locale_t unused) +__ctype_load(const char *locale, locale_t unused __unused) { struct xlocale_ctype *l = calloc(sizeof(struct xlocale_ctype), 1); diff --git a/lib/libc/locale/table.c b/lib/libc/locale/table.c index e89d479..80b19f5 100644 --- a/lib/libc/locale/table.c +++ b/lib/libc/locale/table.c @@ -101,16 +101,16 @@ const _RuneLocale _DefaultRuneLocale = { _CTYPE_P|_CTYPE_R|_CTYPE_G, _CTYPE_P|_CTYPE_R|_CTYPE_G, _CTYPE_P|_CTYPE_R|_CTYPE_G, - /*30*/ _CTYPE_D|_CTYPE_R|_CTYPE_G|_CTYPE_X|0, - _CTYPE_D|_CTYPE_R|_CTYPE_G|_CTYPE_X|1, - _CTYPE_D|_CTYPE_R|_CTYPE_G|_CTYPE_X|2, - _CTYPE_D|_CTYPE_R|_CTYPE_G|_CTYPE_X|3, - _CTYPE_D|_CTYPE_R|_CTYPE_G|_CTYPE_X|4, - _CTYPE_D|_CTYPE_R|_CTYPE_G|_CTYPE_X|5, - _CTYPE_D|_CTYPE_R|_CTYPE_G|_CTYPE_X|6, - _CTYPE_D|_CTYPE_R|_CTYPE_G|_CTYPE_X|7, - /*38*/ _CTYPE_D|_CTYPE_R|_CTYPE_G|_CTYPE_X|8, - _CTYPE_D|_CTYPE_R|_CTYPE_G|_CTYPE_X|9, + /*30*/ _CTYPE_D|_CTYPE_R|_CTYPE_G|_CTYPE_X|_CTYPE_N|0, + _CTYPE_D|_CTYPE_R|_CTYPE_G|_CTYPE_X|_CTYPE_N|1, + _CTYPE_D|_CTYPE_R|_CTYPE_G|_CTYPE_X|_CTYPE_N|2, + _CTYPE_D|_CTYPE_R|_CTYPE_G|_CTYPE_X|_CTYPE_N|3, + _CTYPE_D|_CTYPE_R|_CTYPE_G|_CTYPE_X|_CTYPE_N|4, + _CTYPE_D|_CTYPE_R|_CTYPE_G|_CTYPE_X|_CTYPE_N|5, + _CTYPE_D|_CTYPE_R|_CTYPE_G|_CTYPE_X|_CTYPE_N|6, + _CTYPE_D|_CTYPE_R|_CTYPE_G|_CTYPE_X|_CTYPE_N|7, + /*38*/ _CTYPE_D|_CTYPE_R|_CTYPE_G|_CTYPE_X|_CTYPE_N|8, + _CTYPE_D|_CTYPE_R|_CTYPE_G|_CTYPE_X|_CTYPE_N|9, _CTYPE_P|_CTYPE_R|_CTYPE_G, _CTYPE_P|_CTYPE_R|_CTYPE_G, _CTYPE_P|_CTYPE_R|_CTYPE_G, diff --git a/lib/libc/locale/utf8.c b/lib/libc/locale/utf8.c index 8ccfdb1..e096b87 100644 --- a/lib/libc/locale/utf8.c +++ b/lib/libc/locale/utf8.c @@ -1,4 +1,5 @@ /*- + * Copyright 2013 Garrett D'Amore <garrett@damore.org> * Copyright 2011 Nexenta Systems, Inc. All rights reserved. * Copyright (c) 2002-2004 Tim J. Robbins * All rights reserved. @@ -70,7 +71,7 @@ _UTF8_init(struct xlocale_ctype *l, _RuneLocale *rl) l->__mbsnrtowcs = _UTF8_mbsnrtowcs; l->__wcsnrtombs = _UTF8_wcsnrtombs; l->runes = rl; - l->__mb_cur_max = 6; + l->__mb_cur_max = 4; /* * UCS-4 encoding used as the internal representation, so * slots 0x0080-0x00FF are occuped and must be excluded @@ -165,6 +166,7 @@ _UTF8_mbrtowc(wchar_t * __restrict pwc, const char * __restrict s, size_t n, wch = (unsigned char)*s++ & mask; else wch = us->ch; + for (i = (us->want == 0) ? 1 : 0; i < MIN(want, n); i++) { if ((*s & 0xc0) != 0x80) { /* diff --git a/lib/libc/locale/wcsnrtombs.c b/lib/libc/locale/wcsnrtombs.c index 2f3bf1e..ce77ebb 100644 --- a/lib/libc/locale/wcsnrtombs.c +++ b/lib/libc/locale/wcsnrtombs.c @@ -1,4 +1,6 @@ /*- + * Copyright 2013 Garrett D'Amore <garrett@damore.org> + * Copyright 2010 Nexenta Systems, Inc. All rights reserved. * Copyright (c) 2002-2004 Tim J. Robbins. * All rights reserved. * @@ -57,21 +59,21 @@ wcsnrtombs(char * __restrict dst, const wchar_t ** __restrict src, size_t nwc, size_t __wcsnrtombs_std(char * __restrict dst, const wchar_t ** __restrict src, - size_t nwc, size_t len, mbstate_t * __restrict ps) + size_t nwc, size_t len, mbstate_t * __restrict ps, + wcrtomb_pfn_t pwcrtomb) { mbstate_t mbsbak; char buf[MB_LEN_MAX]; const wchar_t *s; size_t nbytes; size_t nb; - struct xlocale_ctype *l = XLOCALE_CTYPE(__get_locale()); s = *src; nbytes = 0; if (dst == NULL) { while (nwc-- > 0) { - if ((nb = l->__wcrtomb(buf, *s, ps)) == (size_t)-1) + if ((nb = pwcrtomb(buf, *s, ps)) == (size_t)-1) /* Invalid character - wcrtomb() sets errno. */ return ((size_t)-1); else if (*s == L'\0') @@ -85,7 +87,7 @@ __wcsnrtombs_std(char * __restrict dst, const wchar_t ** __restrict src, while (len > 0 && nwc-- > 0) { if (len > (size_t)MB_CUR_MAX) { /* Enough space to translate in-place. */ - if ((nb = l->__wcrtomb(dst, *s, ps)) == (size_t)-1) { + if ((nb = pwcrtomb(dst, *s, ps)) == (size_t)-1) { *src = s; return ((size_t)-1); } @@ -98,7 +100,7 @@ __wcsnrtombs_std(char * __restrict dst, const wchar_t ** __restrict src, * character is too long for the buffer. */ mbsbak = *ps; - if ((nb = l->__wcrtomb(buf, *s, ps)) == (size_t)-1) { + if ((nb = pwcrtomb(buf, *s, ps)) == (size_t)-1) { *src = s; return ((size_t)-1); } diff --git a/lib/libc/locale/wctype.c b/lib/libc/locale/wctype.c index de880b4..e207121 100644 --- a/lib/libc/locale/wctype.c +++ b/lib/libc/locale/wctype.c @@ -73,9 +73,10 @@ wctype_l(const char *property, locale_t locale) "ideogram\0" /* BSD extension */ "special\0" /* BSD extension */ "phonogram\0" /* BSD extension */ + "number\0" /* BSD extension */ "rune\0"; /* BSD extension */ static const wctype_t propmasks[] = { - _CTYPE_A|_CTYPE_D, + _CTYPE_A|_CTYPE_N, _CTYPE_A, _CTYPE_B, _CTYPE_C, @@ -90,6 +91,7 @@ wctype_l(const char *property, locale_t locale) _CTYPE_I, _CTYPE_T, _CTYPE_Q, + _CTYPE_N, 0xFFFFFF00L }; size_t len1, len2; diff --git a/lib/libc/net/getnameinfo.c b/lib/libc/net/getnameinfo.c index c813189..4b7aecb 100644 --- a/lib/libc/net/getnameinfo.c +++ b/lib/libc/net/getnameinfo.c @@ -122,7 +122,8 @@ getnameinfo(const struct sockaddr *sa, socklen_t salen, afd = find_afd(sa->sa_family); if (afd == NULL) return (EAI_FAMILY); - if (sa->sa_family == PF_LOCAL) { + switch (sa->sa_family) { + case PF_LOCAL: /* * PF_LOCAL uses variable sa->sa_len depending on the * content length of sun_path. Require 1 byte in @@ -132,8 +133,17 @@ getnameinfo(const struct sockaddr *sa, socklen_t salen, salen <= afd->a_socklen - sizeofmember(struct sockaddr_un, sun_path)) return (EAI_FAIL); - } else if (salen != afd->a_socklen) - return (EAI_FAIL); + break; + case PF_LINK: + if (salen <= afd->a_socklen - + sizeofmember(struct sockaddr_dl, sdl_data)) + return (EAI_FAIL); + break; + default: + if (salen != afd->a_socklen) + return (EAI_FAIL); + break; + } return ((*afd->a_func)(afd, sa, salen, host, hostlen, serv, servlen, flags)); diff --git a/lib/libc/resolv/res_data.c b/lib/libc/resolv/res_data.c index f020838..e2f905f 100644 --- a/lib/libc/resolv/res_data.c +++ b/lib/libc/resolv/res_data.c @@ -77,9 +77,10 @@ const char *_res_sectioncodes[] = { int res_ourserver_p(const res_state, const struct sockaddr_in *); -int +__noinline int res_init(void) { extern int __res_vinit(res_state, int); + res_state statp = &_res; /* * These three fields used to be statically initialized. This made @@ -100,14 +101,14 @@ res_init(void) { * set in RES_DEFAULT). Our solution is to declare such applications * "broken". They could fool us by setting RES_INIT but none do (yet). */ - if (!_res.retrans) - _res.retrans = RES_TIMEOUT; - if (!_res.retry) - _res.retry = RES_DFLRETRY; - if (!(_res.options & RES_INIT)) - _res.options = RES_DEFAULT; - - return (__res_vinit(&_res, 1)); + if (!statp->retrans) + statp->retrans = RES_TIMEOUT; + if (!statp->retry) + statp->retry = RES_DFLRETRY; + if (!(statp->options & RES_INIT)) + statp->options = RES_DEFAULT; + + return (__res_vinit(statp, 1)); } void @@ -122,10 +123,11 @@ fp_query(const u_char *msg, FILE *file) { void fp_nquery(const u_char *msg, int len, FILE *file) { - if ((_res.options & RES_INIT) == 0U && res_init() == -1) + res_state statp = &_res; + if ((statp->options & RES_INIT) == 0U && res_init() == -1) return; - res_pquery(&_res, msg, len, file); + res_pquery(statp, msg, len, file); } int @@ -138,23 +140,25 @@ res_mkquery(int op, /*!< opcode of query */ u_char *buf, /*!< buffer to put query */ int buflen) /*!< size of buffer */ { - if ((_res.options & RES_INIT) == 0U && res_init() == -1) { - RES_SET_H_ERRNO(&_res, NETDB_INTERNAL); + res_state statp = &_res; + if ((statp->options & RES_INIT) == 0U && res_init() == -1) { + RES_SET_H_ERRNO(statp, NETDB_INTERNAL); return (-1); } - return (res_nmkquery(&_res, op, dname, class, type, + return (res_nmkquery(statp, op, dname, class, type, data, datalen, newrr_in, buf, buflen)); } int res_mkupdate(ns_updrec *rrecp_in, u_char *buf, int buflen) { - if ((_res.options & RES_INIT) == 0U && res_init() == -1) { - RES_SET_H_ERRNO(&_res, NETDB_INTERNAL); + res_state statp = &_res; + if ((statp->options & RES_INIT) == 0U && res_init() == -1) { + RES_SET_H_ERRNO(statp, NETDB_INTERNAL); return (-1); } - return (res_nmkupdate(&_res, rrecp_in, buf, buflen)); + return (res_nmkupdate(statp, rrecp_in, buf, buflen)); } int @@ -163,11 +167,12 @@ res_query(const char *name, /*!< domain name */ u_char *answer, /*!< buffer to put answer */ int anslen) /*!< size of answer buffer */ { - if ((_res.options & RES_INIT) == 0U && res_init() == -1) { - RES_SET_H_ERRNO(&_res, NETDB_INTERNAL); + res_state statp = &_res; + if ((statp->options & RES_INIT) == 0U && res_init() == -1) { + RES_SET_H_ERRNO(statp, NETDB_INTERNAL); return (-1); } - return (res_nquery(&_res, name, class, type, answer, anslen)); + return (res_nquery(statp, name, class, type, answer, anslen)); } #ifndef _LIBC @@ -189,12 +194,13 @@ res_isourserver(const struct sockaddr_in *inp) { int res_send(const u_char *buf, int buflen, u_char *ans, int anssiz) { - if ((_res.options & RES_INIT) == 0U && res_init() == -1) { + res_state statp = &_res; + if ((statp->options & RES_INIT) == 0U && res_init() == -1) { /* errno should have been set by res_init() in this case. */ return (-1); } - return (res_nsend(&_res, buf, buflen, ans, anssiz)); + return (res_nsend(statp, buf, buflen, ans, anssiz)); } #ifndef _LIBC @@ -202,12 +208,13 @@ int res_sendsigned(const u_char *buf, int buflen, ns_tsig_key *key, u_char *ans, int anssiz) { - if ((_res.options & RES_INIT) == 0U && res_init() == -1) { + res_state statp = &_res; + if ((statp->options & RES_INIT) == 0U && res_init() == -1) { /* errno should have been set by res_init() in this case. */ return (-1); } - return (res_nsendsigned(&_res, buf, buflen, key, ans, anssiz)); + return (res_nsendsigned(statp, buf, buflen, key, ans, anssiz)); } #endif @@ -218,12 +225,13 @@ res_close(void) { int res_update(ns_updrec *rrecp_in) { - if ((_res.options & RES_INIT) == 0U && res_init() == -1) { - RES_SET_H_ERRNO(&_res, NETDB_INTERNAL); + res_state statp = &_res; + if ((statp->options & RES_INIT) == 0U && res_init() == -1) { + RES_SET_H_ERRNO(statp, NETDB_INTERNAL); return (-1); } - return (res_nupdate(&_res, rrecp_in, NULL)); + return (res_nupdate(statp, rrecp_in, NULL)); } int @@ -232,12 +240,13 @@ res_search(const char *name, /*!< domain name */ u_char *answer, /*!< buffer to put answer */ int anslen) /*!< size of answer */ { - if ((_res.options & RES_INIT) == 0U && res_init() == -1) { - RES_SET_H_ERRNO(&_res, NETDB_INTERNAL); + res_state statp = &_res; + if ((statp->options & RES_INIT) == 0U && res_init() == -1) { + RES_SET_H_ERRNO(statp, NETDB_INTERNAL); return (-1); } - return (res_nsearch(&_res, name, class, type, answer, anslen)); + return (res_nsearch(statp, name, class, type, answer, anslen)); } int @@ -247,24 +256,26 @@ res_querydomain(const char *name, u_char *answer, /*!< buffer to put answer */ int anslen) /*!< size of answer */ { - if ((_res.options & RES_INIT) == 0U && res_init() == -1) { - RES_SET_H_ERRNO(&_res, NETDB_INTERNAL); + res_state statp = &_res; + if ((statp->options & RES_INIT) == 0U && res_init() == -1) { + RES_SET_H_ERRNO(statp, NETDB_INTERNAL); return (-1); } - return (res_nquerydomain(&_res, name, domain, + return (res_nquerydomain(statp, name, domain, class, type, answer, anslen)); } u_int res_randomid(void) { - if ((_res.options & RES_INIT) == 0U && res_init() == -1) { - RES_SET_H_ERRNO(&_res, NETDB_INTERNAL); + res_state statp = &_res; + if ((statp->options & RES_INIT) == 0U && res_init() == -1) { + RES_SET_H_ERRNO(statp, NETDB_INTERNAL); return (-1); } - return (res_nrandomid(&_res)); + return (res_nrandomid(statp)); } int @@ -284,13 +295,15 @@ hostalias(const char *name) { int local_hostname_length(const char *hostname) { int len_host, len_domain; + res_state statp; - if (!*_res.defdname) + statp = &_res; + if (!*statp->defdname) res_init(); len_host = strlen(hostname); - len_domain = strlen(_res.defdname); + len_domain = strlen(statp->defdname); if (len_host > len_domain && - !strcasecmp(hostname + len_host - len_domain, _res.defdname) && + !strcasecmp(hostname + len_host - len_domain, statp->defdname) && hostname[len_host - len_domain - 1] == '.') return (len_host - len_domain - 1); return (0); diff --git a/lib/libc/rpc/clnt_bcast.c b/lib/libc/rpc/clnt_bcast.c index 7242aa4..a194ba6 100644 --- a/lib/libc/rpc/clnt_bcast.c +++ b/lib/libc/rpc/clnt_bcast.c @@ -636,13 +636,10 @@ rpc_broadcast_exp(rpcprog_t prog, rpcvers_t vers, rpcproc_t proc, } /* The giant for loop */ done_broad: - if (inbuf) - (void) free(inbuf); - if (outbuf) - (void) free(outbuf); + free(inbuf); + free(outbuf); #ifdef PORTMAP - if (outbuf_pmap) - (void) free(outbuf_pmap); + free(outbuf_pmap); #endif /* PORTMAP */ for (i = 0; i < fdlistno; i++) { (void)_close(fdlist[i].fd); diff --git a/lib/libc/rpc/clnt_vc.c b/lib/libc/rpc/clnt_vc.c index e463165..aa16b96 100644 --- a/lib/libc/rpc/clnt_vc.c +++ b/lib/libc/rpc/clnt_vc.c @@ -651,8 +651,7 @@ clnt_vc_destroy(CLIENT *cl) (void)_close(ct->ct_fd); } XDR_DESTROY(&(ct->ct_xdrs)); - if (ct->ct_addr.buf) - free(ct->ct_addr.buf); + free(ct->ct_addr.buf); mem_free(ct, sizeof(struct ct_data)); if (cl->cl_netid && cl->cl_netid[0]) mem_free(cl->cl_netid, strlen(cl->cl_netid) +1); diff --git a/lib/libc/rpc/getnetconfig.c b/lib/libc/rpc/getnetconfig.c index c1e22da..6d668bf 100644 --- a/lib/libc/rpc/getnetconfig.c +++ b/lib/libc/rpc/getnetconfig.c @@ -164,8 +164,7 @@ __nc_error(void) if ((nc_addr = (int *)thr_getspecific(nc_key)) == NULL) { nc_addr = (int *)malloc(sizeof (int)); if (thr_setspecific(nc_key, (void *) nc_addr) != 0) { - if (nc_addr) - free(nc_addr); + free(nc_addr); return (&nc_error); } *nc_addr = 0; @@ -417,7 +416,7 @@ endnetconfig(void *handlep) while (q != NULL) { p = q->next; - if (q->ncp->nc_lookups != NULL) free(q->ncp->nc_lookups); + free(q->ncp->nc_lookups); free(q->ncp); free(q->linep); free(q); @@ -537,8 +536,7 @@ freenetconfigent(struct netconfig *netconfigp) { if (netconfigp != NULL) { free(netconfigp->nc_netid); /* holds all netconfigp's strings */ - if (netconfigp->nc_lookups != NULL) - free(netconfigp->nc_lookups); + free(netconfigp->nc_lookups); free(netconfigp); } return; @@ -628,8 +626,7 @@ parse_ncp(char *stringp, struct netconfig *ncp) } else { char *cp; /* tmp string */ - if (ncp->nc_lookups != NULL) /* from last visit */ - free(ncp->nc_lookups); + free(ncp->nc_lookups); /* from last visit */ ncp->nc_lookups = NULL; ncp->nc_nlookups = 0; while ((cp = tokenp) != NULL) { diff --git a/lib/libc/rpc/mt_misc.c b/lib/libc/rpc/mt_misc.c index 2e17c27..0ec4d8a 100644 --- a/lib/libc/rpc/mt_misc.c +++ b/lib/libc/rpc/mt_misc.c @@ -106,8 +106,7 @@ __rpc_createerr(void) rce_addr = (struct rpc_createerr *) malloc(sizeof (struct rpc_createerr)); if (thr_setspecific(rce_key, (void *) rce_addr) != 0) { - if (rce_addr) - free(rce_addr); + free(rce_addr); return (&rpc_createerr); } memset(rce_addr, 0, sizeof (struct rpc_createerr)); diff --git a/lib/libc/rpc/rpc_soc.c b/lib/libc/rpc/rpc_soc.c index 8fc91ff..11fc803 100644 --- a/lib/libc/rpc/rpc_soc.c +++ b/lib/libc/rpc/rpc_soc.c @@ -432,8 +432,7 @@ clntunix_create(struct sockaddr_un *raddr, u_long prog, u_long vers, int *sockp, if ((raddr->sun_len == 0) || ((svcaddr = malloc(sizeof(struct netbuf))) == NULL ) || ((svcaddr->buf = malloc(sizeof(struct sockaddr_un))) == NULL)) { - if (svcaddr != NULL) - free(svcaddr); + free(svcaddr); rpc_createerr.cf_stat = RPC_SYSTEMERROR; rpc_createerr.cf_error.re_errno = errno; return(cl); diff --git a/lib/libc/rpc/rpcb_clnt.c b/lib/libc/rpc/rpcb_clnt.c index d53d908..49300ed 100644 --- a/lib/libc/rpc/rpcb_clnt.c +++ b/lib/libc/rpc/rpcb_clnt.c @@ -179,8 +179,7 @@ delete_cache(struct netbuf *addr) free(cptr->ac_netid); free(cptr->ac_taddr->buf); free(cptr->ac_taddr); - if (cptr->ac_uaddr) - free(cptr->ac_uaddr); + free(cptr->ac_uaddr); if (prevptr) prevptr->ac_next = cptr->ac_next; else @@ -216,14 +215,10 @@ add_cache(const char *host, const char *netid, struct netbuf *taddr, ad_cache->ac_taddr->buf = (char *) malloc(taddr->len); if (ad_cache->ac_taddr->buf == NULL) { out: - if (ad_cache->ac_host) - free(ad_cache->ac_host); - if (ad_cache->ac_netid) - free(ad_cache->ac_netid); - if (ad_cache->ac_uaddr) - free(ad_cache->ac_uaddr); - if (ad_cache->ac_taddr) - free(ad_cache->ac_taddr); + free(ad_cache->ac_host); + free(ad_cache->ac_netid); + free(ad_cache->ac_uaddr); + free(ad_cache->ac_taddr); free(ad_cache); return; } @@ -256,8 +251,7 @@ out: free(cptr->ac_netid); free(cptr->ac_taddr->buf); free(cptr->ac_taddr); - if (cptr->ac_uaddr) - free(cptr->ac_uaddr); + free(cptr->ac_uaddr); if (prevptr) { prevptr->ac_next = NULL; @@ -798,10 +792,8 @@ __rpcb_findaddr_timed(rpcprog_t program, rpcvers_t version, malloc(remote.len)) == NULL)) { rpc_createerr.cf_stat = RPC_SYSTEMERROR; clnt_geterr(client, &rpc_createerr.cf_error); - if (address) { - free(address); - address = NULL; - } + free(address); + address = NULL; goto error; } memcpy(address->buf, remote.buf, remote.len); diff --git a/lib/libc/rpc/svc.c b/lib/libc/rpc/svc.c index 38cbb79..d68fa9f 100644 --- a/lib/libc/rpc/svc.c +++ b/lib/libc/rpc/svc.c @@ -198,8 +198,7 @@ svc_reg(SVCXPRT *xprt, const rpcprog_t prog, const rpcvers_t vers, rwlock_wrlock(&svc_lock); if ((s = svc_find(prog, vers, &prev, netid)) != NULL) { - if (netid) - free(netid); + free(netid); if (s->sc_dispatch == dispatch) goto rpcb_it; /* he is registering another xptr */ rwlock_unlock(&svc_lock); @@ -207,8 +206,7 @@ svc_reg(SVCXPRT *xprt, const rpcprog_t prog, const rpcvers_t vers, } s = mem_alloc(sizeof (struct svc_callout)); if (s == NULL) { - if (netid) - free(netid); + free(netid); rwlock_unlock(&svc_lock); return (FALSE); } diff --git a/lib/libc/rpc/svc_dg.c b/lib/libc/rpc/svc_dg.c index 1957d64..5d9baaa 100644 --- a/lib/libc/rpc/svc_dg.c +++ b/lib/libc/rpc/svc_dg.c @@ -406,8 +406,7 @@ svc_dg_destroy(SVCXPRT *xprt) (void) mem_free(xprt->xp_rtaddr.buf, xprt->xp_rtaddr.maxlen); if (xprt->xp_ltaddr.buf) (void) mem_free(xprt->xp_ltaddr.buf, xprt->xp_ltaddr.maxlen); - if (xprt->xp_tp) - (void) free(xprt->xp_tp); + free(xprt->xp_tp); svc_xprt_free(xprt); } diff --git a/lib/libc/rpc/svc_simple.c b/lib/libc/rpc/svc_simple.c index 4713efc..9ce3f8d 100644 --- a/lib/libc/rpc/svc_simple.c +++ b/lib/libc/rpc/svc_simple.c @@ -166,10 +166,8 @@ rpc_reg(rpcprog_t prognum, rpcvers_t versnum, rpcproc_t procnum, if (((xdrbuf = malloc((unsigned)recvsz)) == NULL) || ((netid = strdup(nconf->nc_netid)) == NULL)) { warnx(rpc_reg_err, rpc_reg_msg, __no_mem_str); - if (xdrbuf != NULL) - free(xdrbuf); - if (netid != NULL) - free(netid); + free(xdrbuf); + free(netid); SVC_DESTROY(svcxprt); break; } diff --git a/lib/libc/rpc/svc_vc.c b/lib/libc/rpc/svc_vc.c index ca4b93e..bafb725 100644 --- a/lib/libc/rpc/svc_vc.c +++ b/lib/libc/rpc/svc_vc.c @@ -394,10 +394,8 @@ __svc_vc_dodestroy(SVCXPRT *xprt) mem_free(xprt->xp_rtaddr.buf, xprt->xp_rtaddr.maxlen); if (xprt->xp_ltaddr.buf) mem_free(xprt->xp_ltaddr.buf, xprt->xp_ltaddr.maxlen); - if (xprt->xp_tp) - free(xprt->xp_tp); - if (xprt->xp_netid) - free(xprt->xp_netid); + free(xprt->xp_tp); + free(xprt->xp_netid); svc_xprt_free(xprt); } diff --git a/lib/libc/sparc64/fpu/fpu.c b/lib/libc/sparc64/fpu/fpu.c index 431207f..e01701c 100644 --- a/lib/libc/sparc64/fpu/fpu.c +++ b/lib/libc/sparc64/fpu/fpu.c @@ -270,7 +270,7 @@ __fpu_execute(struct utrapframe *uf, struct fpemu *fe, u_int32_t insn, u_long tstate) { struct fpn *fp; - int opf, rs1, rs2, rd, type, mask, cx, cond; + int opf, rs1, rs2, rd, type, mask, cx, cond __unused; u_long reg, fsr; u_int space[4]; diff --git a/lib/libc/stdio/fdopen.c b/lib/libc/stdio/fdopen.c index b936998..fbe37e8 100644 --- a/lib/libc/stdio/fdopen.c +++ b/lib/libc/stdio/fdopen.c @@ -91,7 +91,9 @@ fdopen(int fd, const char *mode) * O_APPEND bit set, assert __SAPP so that __swrite() caller * will _sseek() to the end before write. */ - if ((oflags & O_APPEND) && !(fdflags & O_APPEND)) + if (fdflags & O_APPEND) + fp->_flags2 |= __S2OAP; + else if (oflags & O_APPEND) fp->_flags |= __SAPP; fp->_file = fd; fp->_cookie = fp; diff --git a/lib/libc/stdio/findfp.c b/lib/libc/stdio/findfp.c index 0eabe82..b8bb5af 100644 --- a/lib/libc/stdio/findfp.c +++ b/lib/libc/stdio/findfp.c @@ -155,6 +155,7 @@ found: /* fp->_fl_mutex = NULL; */ /* once set always set (reused) */ fp->_orientation = 0; memset(&fp->_mbstate, 0, sizeof(mbstate_t)); + fp->_flags2 = 0; return (fp); } diff --git a/lib/libc/stdio/fmemopen.c b/lib/libc/stdio/fmemopen.c index ebd3596..bcf187d 100644 --- a/lib/libc/stdio/fmemopen.c +++ b/lib/libc/stdio/fmemopen.c @@ -149,6 +149,9 @@ fmemopen(void * __restrict buf, size_t size, const char * __restrict mode) return (NULL); } + if (mode[0] == 'a') + f->_flags |= __SAPP; + /* * Turn off buffering, so a write past the end of the buffer * correctly returns a short object count. diff --git a/lib/libc/stdio/fopen.c b/lib/libc/stdio/fopen.c index b08e336..9ab61ba 100644 --- a/lib/libc/stdio/fopen.c +++ b/lib/libc/stdio/fopen.c @@ -91,7 +91,9 @@ fopen(const char * __restrict file, const char * __restrict mode) * we can do about this. (We could set __SAPP and check in * fseek and ftell.) */ - if (oflags & O_APPEND) + if (oflags & O_APPEND) { + fp->_flags2 |= __S2OAP; (void)_sseek(fp, (fpos_t)0, SEEK_END); + } return (fp); } diff --git a/lib/libc/stdio/freopen.c b/lib/libc/stdio/freopen.c index 4dcd50f..e0104c8 100644 --- a/lib/libc/stdio/freopen.c +++ b/lib/libc/stdio/freopen.c @@ -187,6 +187,7 @@ finish: fp->_lb._size = 0; fp->_orientation = 0; memset(&fp->_mbstate, 0, sizeof(mbstate_t)); + fp->_flags2 = 0; if (f < 0) { /* did not get it after all */ if (isopen) @@ -240,8 +241,10 @@ finish: * we can do about this. (We could set __SAPP and check in * fseek and ftell.) */ - if (oflags & O_APPEND) + if (oflags & O_APPEND) { + fp->_flags2 |= __S2OAP; (void) _sseek(fp, (fpos_t)0, SEEK_END); + } FUNLOCKFILE(fp); return (fp); } diff --git a/lib/libc/stdio/ftell.c b/lib/libc/stdio/ftell.c index 745d500..fc792af 100644 --- a/lib/libc/stdio/ftell.c +++ b/lib/libc/stdio/ftell.c @@ -39,7 +39,6 @@ __FBSDID("$FreeBSD$"); #include "namespace.h" #include <sys/types.h> #include <errno.h> -#include <fcntl.h> #include <limits.h> #include <stdio.h> #include "un-namespace.h" @@ -88,7 +87,6 @@ _ftello(FILE *fp, fpos_t *offset) { fpos_t pos; size_t n; - int dflags; if (fp->_seek == NULL) { errno = ESPIPE; /* historic practice */ @@ -99,7 +97,13 @@ _ftello(FILE *fp, fpos_t *offset) * Find offset of underlying I/O object, then * adjust for buffered bytes. */ - if (fp->_flags & __SOFF) + if (!(fp->_flags & __SRD) && (fp->_flags & __SWR) && + fp->_p != NULL && fp->_p - fp->_bf._base > 0 && + ((fp->_flags & __SAPP) || (fp->_flags2 & __S2OAP))) { + pos = _sseek(fp, (fpos_t)0, SEEK_END); + if (pos == -1) + return (1); + } else if (fp->_flags & __SOFF) pos = fp->_offset; else { pos = _sseek(fp, (fpos_t)0, SEEK_CUR); @@ -119,29 +123,13 @@ _ftello(FILE *fp, fpos_t *offset) } if (HASUB(fp)) pos -= fp->_r; /* Can be negative at this point. */ - } else if ((fp->_flags & __SWR) && fp->_p != NULL) { - dflags = 0; - if (fp->_flags & __SAPP) - dflags = O_APPEND; - else if (fp->_file != -1 && - (dflags = _fcntl(fp->_file, F_GETFL)) < 0) - return (1); - if ((dflags & O_APPEND) && - (pos = _sseek(fp, (fpos_t)0, SEEK_END)) == -1) { - if ((fp->_flags & __SOPT) || __sflush(fp) || - (pos = _sseek(fp, (fpos_t)0, SEEK_CUR)) == -1) - return (1); - else { - *offset = pos; - return (0); - } - } + } else if ((fp->_flags & __SWR) && fp->_p != NULL && + (n = fp->_p - fp->_bf._base) > 0) { /* * Writing. Any buffered characters cause the * position to be greater than that in the * underlying object. */ - n = fp->_p - fp->_bf._base; if (pos > OFF_MAX - n) { errno = EOVERFLOW; return (1); diff --git a/lib/libc/stdio/stdio.c b/lib/libc/stdio/stdio.c index 44ee0ab..5d6fb9a 100644 --- a/lib/libc/stdio/stdio.c +++ b/lib/libc/stdio/stdio.c @@ -117,7 +117,7 @@ _swrite(FILE *fp, char const *buf, int n) ret = (*fp->_write)(fp->_cookie, buf, n); /* __SOFF removed even on success in case O_APPEND mode is set. */ if (ret >= 0) { - if ((fp->_flags & (__SAPP|__SOFF)) == (__SAPP|__SOFF) && + if ((fp->_flags & __SOFF) && !(fp->_flags2 & __S2OAP) && fp->_offset <= OFF_MAX - ret) fp->_offset += ret; else diff --git a/lib/libc/string/strcoll.c b/lib/libc/string/strcoll.c index a918fca..7675e0a 100644 --- a/lib/libc/string/strcoll.c +++ b/lib/libc/string/strcoll.c @@ -1,4 +1,5 @@ /*- + * Copyright 2010 Nexenta Systems, Inc. All rights reserved. * Copyright (c) 1995 Alex Tatmanjants <alex@elvisti.kiev.ua> * at Electronni Visti IA, Kiev, Ukraine. * All rights reserved. @@ -35,63 +36,78 @@ __FBSDID("$FreeBSD$"); #include <stdlib.h> #include <string.h> +#include <errno.h> +#include <wchar.h> #include "collate.h" -#include <stdio.h> +/* + * In order to properly handle multibyte locales, its easiest to just + * convert to wide characters and then use wcscoll. However if an + * error occurs, we gracefully fall back to simple strcmp. Caller + * should check errno. + */ int strcoll_l(const char *s, const char *s2, locale_t locale) { - int len, len2, prim, prim2, sec, sec2, ret, ret2; - const char *t, *t2; - char *tt, *tt2; + int ret; + wchar_t *t1 = NULL, *t2 = NULL; + wchar_t *w1 = NULL, *w2 = NULL; + const char *cs1, *cs2; + mbstate_t mbs1; + mbstate_t mbs2; + size_t sz1, sz2; + + memset(&mbs1, 0, sizeof (mbstate_t)); + memset(&mbs2, 0, sizeof (mbstate_t)); + + /* + * The mbsrtowcs_l function can set the src pointer to null upon + * failure, so it should act on a copy to avoid: + * - sending null pointer to strcmp + * - having strcoll/strcoll_l change *s or *s2 to null + */ + cs1 = s; + cs2 = s2; + FIX_LOCALE(locale); struct xlocale_collate *table = (struct xlocale_collate*)locale->components[XLC_COLLATE]; if (table->__collate_load_error) - return strcmp(s, s2); - - len = len2 = 1; - ret = ret2 = 0; - if (table->__collate_substitute_nontrivial) { - t = tt = __collate_substitute(table, s); - t2 = tt2 = __collate_substitute(table, s2); - } else { - tt = tt2 = NULL; - t = s; - t2 = s2; - } - while(*t && *t2) { - prim = prim2 = 0; - while(*t && !prim) { - __collate_lookup(table, t, &len, &prim, &sec); - t += len; - } - while(*t2 && !prim2) { - __collate_lookup(table, t2, &len2, &prim2, &sec2); - t2 += len2; - } - if(!prim || !prim2) - break; - if(prim != prim2) { - ret = prim - prim2; - goto end; - } - if(!ret2) - ret2 = sec - sec2; - } - if(!*t && *t2) - ret = -(int)((u_char)*t2); - else if(*t && !*t2) - ret = (u_char)*t; - else if(!*t && !*t2) - ret = ret2; - end: - free(tt); - free(tt2); - - return ret; + goto error; + + sz1 = strlen(s) + 1; + sz2 = strlen(s2) + 1; + + /* + * Simple assumption: conversion to wide format is strictly + * reducing, i.e. a single byte (or multibyte character) + * cannot result in multiple wide characters. + */ + if ((t1 = malloc(sz1 * sizeof (wchar_t))) == NULL) + goto error; + w1 = t1; + if ((t2 = malloc(sz2 * sizeof (wchar_t))) == NULL) + goto error; + w2 = t2; + + if ((mbsrtowcs_l(w1, &cs1, sz1, &mbs1, locale)) == (size_t)-1) + goto error; + + if ((mbsrtowcs_l(w2, &cs2, sz2, &mbs2, locale)) == (size_t)-1) + goto error; + + ret = wcscoll_l(w1, w2, locale); + free(t1); + free(t2); + + return (ret); + +error: + free(t1); + free(t2); + return (strcmp(s, s2)); } int diff --git a/lib/libc/string/strxfrm.c b/lib/libc/string/strxfrm.c index b758b0c..06ae639 100644 --- a/lib/libc/string/strxfrm.c +++ b/lib/libc/string/strxfrm.c @@ -1,4 +1,5 @@ /*- + * Copyright 2010 Nexenta Systems, Inc. All rights reserved. * Copyright (c) 1995 Alex Tatmanjants <alex@elvisti.kiev.ua> * at Electronni Visti IA, Kiev, Ukraine. * All rights reserved. @@ -35,6 +36,8 @@ __FBSDID("$FreeBSD$"); #include <stdlib.h> #include <string.h> +#include <errno.h> +#include <wchar.h> #include "collate.h" size_t @@ -48,9 +51,10 @@ strxfrm(char * __restrict dest, const char * __restrict src, size_t len) size_t strxfrm_l(char * __restrict dest, const char * __restrict src, size_t len, locale_t locale) { - int prim, sec, l; size_t slen; - char *s, *ss; + size_t xlen; + wchar_t *wcs = NULL; + FIX_LOCALE(locale); struct xlocale_collate *table = (struct xlocale_collate*)locale->components[XLC_COLLATE]; @@ -58,32 +62,42 @@ strxfrm_l(char * __restrict dest, const char * __restrict src, size_t len, local if (!*src) { if (len > 0) *dest = '\0'; - return 0; + return (0); } + /* + * The conversion from multibyte to wide character strings is + * strictly reducing (one byte of an mbs cannot expand to more + * than one wide character.) + */ + slen = strlen(src); + if (table->__collate_load_error) - return strlcpy(dest, src, len); - - slen = 0; - prim = sec = 0; - ss = s = __collate_substitute(table, src); - while (*s) { - while (*s && !prim) { - __collate_lookup(table, s, &l, &prim, &sec); - s += l; - } - if (prim) { - if (len > 1) { - *dest++ = (char)prim; - len--; - } - slen++; - prim = 0; - } + goto error; + + if ((wcs = malloc((slen + 1) * sizeof (wchar_t))) == NULL) + goto error; + + if (mbstowcs_l(wcs, src, slen + 1, locale) == (size_t)-1) + goto error; + + if ((xlen = _collate_sxfrm(table, wcs, dest, len)) == (size_t)-1) + goto error; + + free(wcs); + + if (len > xlen) { + dest[xlen] = 0; + } else if (len) { + dest[len-1] = 0; } - free(ss); - if (len > 0) - *dest = '\0'; - return slen; + return (xlen); + +error: + /* errno should be set to ENOMEM if malloc failed */ + free(wcs); + strlcpy(dest, src, len); + + return (slen); } diff --git a/lib/libc/string/wcscoll.c b/lib/libc/string/wcscoll.c index 3c51015..ee0e72a 100644 --- a/lib/libc/string/wcscoll.c +++ b/lib/libc/string/wcscoll.c @@ -1,4 +1,5 @@ /*- + * Copyright 2010 Nexenta Systems, Inc. All rights reserved. * Copyright (c) 2002 Tim J. Robbins * All rights reserved. * @@ -38,50 +39,181 @@ __FBSDID("$FreeBSD$"); #include <wchar.h> #include "collate.h" -static char *__mbsdup(const wchar_t *); - -/* - * Placeholder implementation of wcscoll(). Attempts to use the single-byte - * collation ordering where possible, and falls back on wcscmp() in locales - * with extended character sets. - */ int wcscoll_l(const wchar_t *ws1, const wchar_t *ws2, locale_t locale) { - char *mbs1, *mbs2; - int diff, sverrno; + int len1, len2, pri1, pri2, ret; + wchar_t *tr1 = NULL, *tr2 = NULL; + int direc, pass; + FIX_LOCALE(locale); struct xlocale_collate *table = (struct xlocale_collate*)locale->components[XLC_COLLATE]; - if (table->__collate_load_error || MB_CUR_MAX > 1) + if (table->__collate_load_error) /* - * Locale has no special collating order, could not be - * loaded, or has an extended character set; do a fast binary - * comparison. + * Locale has no special collating order or could not be + * loaded, do a fast binary comparison. */ return (wcscmp(ws1, ws2)); - if ((mbs1 = __mbsdup(ws1)) == NULL || (mbs2 = __mbsdup(ws2)) == NULL) { - /* - * Out of memory or illegal wide chars; fall back to wcscmp() - * but leave errno indicating the error. Callers that don't - * check for error will get a reasonable but often slightly - * incorrect result. - */ - sverrno = errno; - free(mbs1); - errno = sverrno; - return (wcscmp(ws1, ws2)); + ret = 0; + + /* + * Once upon a time we had code to try to optimize this, but + * it turns out that you really can't make many assumptions + * safely. You absolutely have to run this pass by pass, + * because some passes will be ignored for a given character, + * while others will not. Simpler locales will benefit from + * having fewer passes, and most comparisions should resolve + * during the primary pass anyway. + * + * Note that we do one final extra pass at the end to pick + * up UNDEFINED elements. There is special handling for them. + */ + for (pass = 0; pass <= table->info->directive_count; pass++) { + + const int32_t *st1 = NULL; + const int32_t *st2 = NULL; + const wchar_t *w1 = ws1; + const wchar_t *w2 = ws2; + int check1, check2; + + /* special pass for UNDEFINED */ + if (pass == table->info->directive_count) { + direc = DIRECTIVE_FORWARD | DIRECTIVE_UNDEFINED; + } else { + direc = table->info->directive[pass]; + } + + if (direc & DIRECTIVE_BACKWARD) { + wchar_t *bp, *fp, c; + if ((tr1 = wcsdup(w1)) == NULL) + goto fail; + bp = tr1; + fp = tr1 + wcslen(tr1) - 1; + while (bp < fp) { + c = *bp; + *bp++ = *fp; + *fp-- = c; + } + if ((tr2 = wcsdup(w2)) == NULL) + goto fail; + bp = tr2; + fp = tr2 + wcslen(tr2) - 1; + while (bp < fp) { + c = *bp; + *bp++ = *fp; + *fp-- = c; + } + w1 = tr1; + w2 = tr2; + } + + if (direc & DIRECTIVE_POSITION) { + while (*w1 && *w2) { + pri1 = pri2 = 0; + check1 = check2 = 1; + while ((pri1 == pri2) && (check1 || check2)) { + if (check1) { + _collate_lookup(table, w1, &len1, + &pri1, pass, &st1); + if (pri1 < 0) { + errno = EINVAL; + goto fail; + } + if (!pri1) { + pri1 = COLLATE_MAX_PRIORITY; + st1 = NULL; + } + check1 = (st1 != NULL); + } + if (check2) { + _collate_lookup(table, w2, &len2, + &pri2, pass, &st2); + if (pri2 < 0) { + errno = EINVAL; + goto fail; + } + if (!pri2) { + pri2 = COLLATE_MAX_PRIORITY; + st2 = NULL; + } + check2 = (st2 != NULL); + } + } + if (pri1 != pri2) { + ret = pri1 - pri2; + goto end; + } + w1 += len1; + w2 += len2; + } + } else { + while (*w1 && *w2) { + pri1 = pri2 = 0; + check1 = check2 = 1; + while ((pri1 == pri2) && (check1 || check2)) { + while (check1 && *w1) { + _collate_lookup(table, w1, + &len1, &pri1, pass, &st1); + if (pri1 > 0) + break; + if (pri1 < 0) { + errno = EINVAL; + goto fail; + } + st1 = NULL; + w1 += 1; + } + check1 = (st1 != NULL); + while (check2 && *w2) { + _collate_lookup(table, w2, + &len2, &pri2, pass, &st2); + if (pri2 > 0) + break; + if (pri2 < 0) { + errno = EINVAL; + goto fail; + } + st2 = NULL; + w2 += 1; + } + check2 = (st2 != NULL); + if (!pri1 || !pri2) + break; + } + if (!pri1 || !pri2) + break; + if (pri1 != pri2) { + ret = pri1 - pri2; + goto end; + } + w1 += len1; + w2 += len2; + } + } + if (!*w1) { + if (*w2) { + ret = -(int)*w2; + goto end; + } + } else { + ret = *w1; + goto end; + } } + ret = 0; - diff = strcoll_l(mbs1, mbs2, locale); - sverrno = errno; - free(mbs1); - free(mbs2); - errno = sverrno; +end: + free(tr1); + free(tr2); - return (diff); + return (ret); + +fail: + ret = wcscmp(ws1, ws2); + goto end; } int @@ -89,24 +221,3 @@ wcscoll(const wchar_t *ws1, const wchar_t *ws2) { return wcscoll_l(ws1, ws2, __get_locale()); } - -static char * -__mbsdup(const wchar_t *ws) -{ - static const mbstate_t initial; - mbstate_t st; - const wchar_t *wcp; - size_t len; - char *mbs; - - wcp = ws; - st = initial; - if ((len = wcsrtombs(NULL, &wcp, 0, &st)) == (size_t)-1) - return (NULL); - if ((mbs = malloc(len + 1)) == NULL) - return (NULL); - st = initial; - wcsrtombs(mbs, &ws, len + 1, &st); - - return (mbs); -} diff --git a/lib/libc/string/wcsxfrm.c b/lib/libc/string/wcsxfrm.c index cea667e..3d6c960 100644 --- a/lib/libc/string/wcsxfrm.c +++ b/lib/libc/string/wcsxfrm.c @@ -1,4 +1,5 @@ /*- + * Copyright 2010 Nexenta Systems, Inc. All rights reserved. * Copyright (c) 1995 Alex Tatmanjants <alex@elvisti.kiev.ua> * at Electronni Visti IA, Kiev, Ukraine. * All rights reserved. @@ -31,9 +32,6 @@ */ #include <sys/cdefs.h> -#if 0 -__FBSDID("FreeBSD: src/lib/libc/string/strxfrm.c,v 1.15 2002/09/06 11:24:06 tjr Exp "); -#endif __FBSDID("$FreeBSD$"); #include <stdlib.h> @@ -41,18 +39,10 @@ __FBSDID("$FreeBSD$"); #include <wchar.h> #include "collate.h" -static char *__mbsdup(const wchar_t *); - -/* - * Placeholder wcsxfrm() implementation. See wcscoll.c for a description of - * the logic used. - */ size_t wcsxfrm_l(wchar_t * __restrict dest, const wchar_t * __restrict src, size_t len, locale_t locale) { - int prim, sec, l; size_t slen; - char *mbsrc, *s, *ss; FIX_LOCALE(locale); struct xlocale_collate *table = (struct xlocale_collate*)locale->components[XLC_COLLATE]; @@ -63,67 +53,33 @@ wcsxfrm_l(wchar_t * __restrict dest, const wchar_t * __restrict src, size_t len, return (0); } - if (table->__collate_load_error || MB_CUR_MAX > 1) { - slen = wcslen(src); - if (len > 0) { - if (slen < len) - wcscpy(dest, src); - else { - wcsncpy(dest, src, len - 1); - dest[len - 1] = L'\0'; - } - } - return (slen); + if ((table->__collate_load_error) || + ((slen = _collate_wxfrm(table, src, dest, len)) == (size_t)-1)) { + goto error; } - mbsrc = __mbsdup(src); - slen = 0; - prim = sec = 0; - ss = s = __collate_substitute(table, mbsrc); - while (*s != '\0') { - while (*s != '\0' && prim == 0) { - __collate_lookup(table, s, &l, &prim, &sec); - s += l; - } - if (prim != 0) { - if (len > 1) { - *dest++ = (wchar_t)prim; - len--; - } - slen++; - prim = 0; - } + /* Add null termination at the correct location. */ + if (len > slen) { + dest[slen] = 0; + } else if (len) { + dest[len-1] = 0; } - free(ss); - free(mbsrc); - if (len != 0) - *dest = L'\0'; return (slen); + +error: + slen = wcslen(src); + if (slen < len) + (void) wcscpy(dest, src); + else { + (void) wcsncpy(dest, src, len - 1); + dest[len - 1] = L'\0'; + } + return (slen); } + size_t wcsxfrm(wchar_t * __restrict dest, const wchar_t * __restrict src, size_t len) { return wcsxfrm_l(dest, src, len, __get_locale()); } - -static char * -__mbsdup(const wchar_t *ws) -{ - static const mbstate_t initial; - mbstate_t st; - const wchar_t *wcp; - size_t len; - char *mbs; - - wcp = ws; - st = initial; - if ((len = wcsrtombs(NULL, &wcp, 0, &st)) == (size_t)-1) - return (NULL); - if ((mbs = malloc(len + 1)) == NULL) - return (NULL); - st = initial; - wcsrtombs(mbs, &ws, len + 1, &st); - - return (mbs); -} diff --git a/lib/libc/sys/cpuset.2 b/lib/libc/sys/cpuset.2 index 8349566..d16b3ff 100644 --- a/lib/libc/sys/cpuset.2 +++ b/lib/libc/sys/cpuset.2 @@ -25,7 +25,7 @@ .\" .\" $FreeBSD$ .\" -.Dd January 8, 2015 +.Dd October 20, 2015 .Dt CPUSET 2 .Os .Sh NAME @@ -219,7 +219,8 @@ for allocation. .Xr cpuset_getaffinity 2 , .Xr cpuset_setaffinity 2 , .Xr pthread_affinity_np 3 , -.Xr pthread_attr_affinity_np 3 +.Xr pthread_attr_affinity_np 3 , +.Xr cpuset 9 .Sh HISTORY The .Nm diff --git a/lib/libc/sys/cpuset_getaffinity.2 b/lib/libc/sys/cpuset_getaffinity.2 index 810a03c..7032d2e 100644 --- a/lib/libc/sys/cpuset_getaffinity.2 +++ b/lib/libc/sys/cpuset_getaffinity.2 @@ -25,7 +25,7 @@ .\" .\" $FreeBSD$ .\" -.Dd September 10, 2010 +.Dd October 20, 2015 .Dt CPUSET_GETAFFINITY 2 .Os .Sh NAME @@ -153,7 +153,8 @@ operation. .Xr cpuset_getid 2 , .Xr cpuset_setid 2 , .Xr pthread_affinity_np 3 , -.Xr pthread_attr_affinity_np 3 +.Xr pthread_attr_affinity_np 3 , +.Xr cpuset 9 .Sh HISTORY The .Nm diff --git a/lib/libc/sys/ptrace.2 b/lib/libc/sys/ptrace.2 index 5c93438..a94e314 100644 --- a/lib/libc/sys/ptrace.2 +++ b/lib/libc/sys/ptrace.2 @@ -2,7 +2,7 @@ .\" $NetBSD: ptrace.2,v 1.2 1995/02/27 12:35:37 cgd Exp $ .\" .\" This file is in the public domain. -.Dd October 6, 2015 +.Dd October 20, 2015 .Dt PTRACE 2 .Os .Sh NAME @@ -306,7 +306,7 @@ struct ptrace_lwpinfo { sigset_t pl_siglist; siginfo_t pl_siginfo; char pl_tdname[MAXCOMLEN + 1]; - int pl_child_pid; + pid_t pl_child_pid; u_int pl_syscall_code; u_int pl_syscall_narg; }; diff --git a/lib/libc/tests/Makefile b/lib/libc/tests/Makefile index 2e97151..e6ddc15 100644 --- a/lib/libc/tests/Makefile +++ b/lib/libc/tests/Makefile @@ -11,6 +11,7 @@ TESTS_SUBDIRS+= hash TESTS_SUBDIRS+= inet TESTS_SUBDIRS+= net TESTS_SUBDIRS+= regex +TESTS_SUBDIRS+= rpc TESTS_SUBDIRS+= stdio TESTS_SUBDIRS+= stdlib TESTS_SUBDIRS+= string diff --git a/lib/libc/tests/Makefile.netbsd-tests b/lib/libc/tests/Makefile.netbsd-tests index 3238518..18b0276 100644 --- a/lib/libc/tests/Makefile.netbsd-tests +++ b/lib/libc/tests/Makefile.netbsd-tests @@ -4,4 +4,6 @@ TESTSRC:= ${SRCTOP}/contrib/netbsd-tests/${RELDIR:C/libc\/tests/libc/} TESTSDIR:= ${TESTSBASE}/${RELDIR:C/libc\/tests/libc/} +WARNS?= 2 + .include <netbsd-tests.test.mk> diff --git a/lib/libc/tests/c063/Makefile b/lib/libc/tests/c063/Makefile index 2e4565c..05da6ea 100644 --- a/lib/libc/tests/c063/Makefile +++ b/lib/libc/tests/c063/Makefile @@ -2,21 +2,21 @@ #TODO: t_o_search -NETBSD_ATF_TESTS_C= faccessat -NETBSD_ATF_TESTS_C+= fchmodat -NETBSD_ATF_TESTS_C+= fchownat -NETBSD_ATF_TESTS_C+= fexecve -NETBSD_ATF_TESTS_C+= fstatat -NETBSD_ATF_TESTS_C+= linkat -NETBSD_ATF_TESTS_C+= mkdirat -NETBSD_ATF_TESTS_C+= mkfifoat -NETBSD_ATF_TESTS_C+= mknodat -NETBSD_ATF_TESTS_C+= openat -NETBSD_ATF_TESTS_C+= readlinkat -NETBSD_ATF_TESTS_C+= renameat -NETBSD_ATF_TESTS_C+= symlinkat -NETBSD_ATF_TESTS_C+= unlinkat -NETBSD_ATF_TESTS_C+= utimensat +NETBSD_ATF_TESTS_C= faccessat_test +NETBSD_ATF_TESTS_C+= fchmodat_test +NETBSD_ATF_TESTS_C+= fchownat_test +NETBSD_ATF_TESTS_C+= fexecve_test +NETBSD_ATF_TESTS_C+= fstatat_test +NETBSD_ATF_TESTS_C+= linkat_test +NETBSD_ATF_TESTS_C+= mkdirat_test +NETBSD_ATF_TESTS_C+= mkfifoat_test +NETBSD_ATF_TESTS_C+= mknodat_test +NETBSD_ATF_TESTS_C+= openat_test +NETBSD_ATF_TESTS_C+= readlinkat_test +NETBSD_ATF_TESTS_C+= renameat_test +NETBSD_ATF_TESTS_C+= symlinkat_test +NETBSD_ATF_TESTS_C+= unlinkat_test +NETBSD_ATF_TESTS_C+= utimensat_test CFLAGS+= -D_INCOMPLETE_XOPEN_C063 diff --git a/lib/libc/tests/gen/Makefile b/lib/libc/tests/gen/Makefile index 90f6573..476b5b7 100644 --- a/lib/libc/tests/gen/Makefile +++ b/lib/libc/tests/gen/Makefile @@ -2,8 +2,15 @@ .include <bsd.own.mk> -ATF_TESTS_C= arc4random_test +ATF_TESTS_C+= arc4random_test +ATF_TESTS_C+= fmtcheck2_test +ATF_TESTS_C+= fmtmsg_test +ATF_TESTS_C+= fnmatch2_test ATF_TESTS_C+= fpclassify2_test +ATF_TESTS_C+= ftw_test +ATF_TESTS_C+= popen_test +ATF_TESTS_C+= posix_spawn_test +ATF_TESTS_C+= wordexp_test # TODO: t_closefrom, t_cpuset, t_fmtcheck, t_randomid, t_sleep # TODO: t_siginfo (fixes require further inspection) @@ -53,7 +60,25 @@ DPADD.nice_test+= ${LIBPTHREAD} LDADD.syslog_test+= -lpthread DPADD.syslog_test+= ${LIBPTHREAD} +CFLAGS+= -I${.CURDIR} + +SRCS.fmtcheck2_test= fmtcheck_test.c +SRCS.fnmatch2_test= fnmatch_test.c + TESTS_SUBDIRS= execve TESTS_SUBDIRS+= posix_spawn +# The old testcase name +TEST_FNMATCH= test-fnmatch +CLEANFILES+= ${GEN_SH_CASE_TESTCASES} +sh-tests: .PHONY +.for target in clean obj depend all + @cd ${.CURDIR} && ${MAKE} PROG=${TEST_FNMATCH} \ + -DNO_SUBDIR ${target} +.endfor + @cd ${.OBJDIR} && ./${TEST_FNMATCH} -s 1 > \ + ${SRCTOP}/bin/sh/tests/builtins/case2.0 + @cd ${.OBJDIR} && ./${TEST_FNMATCH} -s 2 > \ + ${SRCTOP}/bin/sh/tests/builtins/case3.0 + .include <bsd.test.mk> diff --git a/lib/libc/tests/gen/arc4random_test.c b/lib/libc/tests/gen/arc4random_test.c index ec82c32..a28db30 100644 --- a/lib/libc/tests/gen/arc4random_test.c +++ b/lib/libc/tests/gen/arc4random_test.c @@ -30,10 +30,12 @@ __FBSDID("$FreeBSD$"); #include <sys/types.h> #include <sys/mman.h> #include <sys/wait.h> +#include <errno.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <unistd.h> + #include <atf-c.h> /* @@ -56,14 +58,9 @@ ATF_TC_BODY(test_arc4random, tc) pid_t pid; char c; - printf("1..1\n"); - page = mmap(NULL, sizeof(struct shared_page), PROT_READ | PROT_WRITE, MAP_ANON | MAP_SHARED, -1, 0); - if (page == MAP_FAILED) { - printf("fail 1 - mmap\n"); - exit(1); - } + ATF_REQUIRE_MSG(page != MAP_FAILED, "mmap failed; errno=%d", errno); arc4random_buf(&c, 1); diff --git a/lib/libc/tests/gen/fmtcheck_test.c b/lib/libc/tests/gen/fmtcheck_test.c new file mode 100644 index 0000000..3e180c9 --- /dev/null +++ b/lib/libc/tests/gen/fmtcheck_test.c @@ -0,0 +1,105 @@ +/* $NetBSD: tfmtcheck.c,v 1.3 2008/04/28 20:23:04 martin Exp $ */ + +/*- + * Copyright (c) 2000 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code was contributed to The NetBSD Foundation by Allen Briggs. + * + * 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 NETBSD FOUNDATION, INC. 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 FOUNDATION 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 <sys/cdefs.h> +__FBSDID("$FreeBSD$"); + +#include <sys/param.h> +#include <err.h> +#include <stdio.h> +#include <stdlib.h> + +#include <atf-c.h> + +struct test_fmt { + char *fmt1; + char *fmt2; + int correct; +} test_fmts[] = { + { "%d", "%d", 1 }, + { "%2d", "%2.2d", 1 }, + { "%x", "%d", 1 }, + { "%u", "%d", 1 }, + { "%03d", "%d", 1 }, + { "%-2d", "%d", 1 }, + { "%d", "%-12.1d", 1 }, + { "%d", "%-01.3d", 1 }, + { "%X", "%-01.3d", 1 }, + { "%D", "%ld", 1 }, + { "%s", "%s", 1 }, + { "%s", "This is a %s test", 1 }, + { "Hi, there. This is a %s test", "%s", 1 }, + { "%d", "%s", 2 }, + { "%e", "%s", 2 }, + { "%r", "%d", 2 }, + { "%*.2d", "%*d", 1 }, + { "%2.*d", "%*d", 2 }, + { "%*d", "%*d", 1 }, + { "%-3", "%d", 2 }, + { "%d %s", "%d", 2 }, + { "%*.*.*d", "%*.*.*d", 2 }, + { "%d", "%d %s", 1 }, + { "%40s", "%20s", 1 }, + { "%x %x %x", "%o %u %d", 1 }, + { "%o %u %d", "%x %x %X", 1 }, + { "%#o %u %#-d", "%x %#x %X", 1 }, + { "%qd", "%llx", 1 }, + { "%%", "%llx", 1 }, + { "%p %30s %#llx %-10.*e", "This number %lu%% and string %s has %qd numbers and %.*g floats", 1 }, +}; + +ATF_TC_WITHOUT_HEAD(fmtcheck_test); +ATF_TC_BODY(fmtcheck_test, tc) +{ + int i; + const char *f, *cf, *f1, *f2; + + for (i = 0; i < nitems(test_fmts); i++) { + f1 = test_fmts[i].fmt1; + f2 = test_fmts[i].fmt2; + f = fmtcheck(f1, f2); + if (test_fmts[i].correct == 1) + cf = f1; + else + cf = f2; + ATF_CHECK_MSG(f == cf, + "Test %d: (%s) vs. (%s) failed " + "(should have returned %s)", i + 1, f1, f2, + (test_fmts[i].correct == 1) ? "1st" : "2nd"); + } +} + +ATF_TP_ADD_TCS(tp) +{ + + ATF_TP_ADD_TC(tp, fmtcheck_test); + + return (atf_no_error()); +} diff --git a/lib/libc/tests/gen/fmtmsg_test.c b/lib/libc/tests/gen/fmtmsg_test.c new file mode 100644 index 0000000..aa3ca19 --- /dev/null +++ b/lib/libc/tests/gen/fmtmsg_test.c @@ -0,0 +1,252 @@ +/*- + * Copyright (c) 2012 Jilles Tjoelker + * 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 <sys/cdefs.h> +__FBSDID("$FreeBSD$"); + +#include <sys/param.h> +#include <sys/wait.h> +#include <err.h> +#include <errno.h> +#include <fmtmsg.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> + +#include <atf-c.h> + +static char *run_test(long classification, const char *label, int severity, + const char *text, const char *action, const char *tag); + +struct testcase { + long classification; + const char *label; + int severity; + const char *text; + const char *action; + const char *tag; + const char *msgverb; + const char *result; +} testcases[] = { + { + MM_UTIL | MM_PRINT, "BSD:ls", MM_ERROR, + "illegal option -- z", "refer to manual", "BSD:ls:001", + NULL, + "BSD:ls: ERROR: illegal option -- z\n" + "TO FIX: refer to manual BSD:ls:001\n" + }, + { + MM_UTIL | MM_PRINT, "BSD:ls", MM_ERROR, + "illegal option -- z", "refer to manual", "BSD:ls:001", + "text:severity:action:tag", + "illegal option -- z: ERROR\n" + "TO FIX: refer to manual BSD:ls:001\n" + }, + { + MM_UTIL | MM_PRINT, "BSD:ls", MM_ERROR, + "illegal option -- z", "refer to manual", "BSD:ls:001", + "text", + "illegal option -- z\n" + }, + { + MM_UTIL | MM_PRINT, "BSD:ls", MM_ERROR, + "illegal option -- z", "refer to manual", "BSD:ls:001", + "severity:text", + "ERROR: illegal option -- z\n" + }, + { + MM_UTIL | MM_PRINT, "BSD:ls", MM_ERROR, + "illegal option -- z", "refer to manual", "BSD:ls:001", + "ignore me", + "BSD:ls: ERROR: illegal option -- z\n" + "TO FIX: refer to manual BSD:ls:001\n" + }, + { + MM_UTIL | MM_PRINT, "BSD:ls", MM_ERROR, + "illegal option -- z", "refer to manual", "BSD:ls:001", + "tag:severity:text:nothing:action", + "BSD:ls: ERROR: illegal option -- z\n" + "TO FIX: refer to manual BSD:ls:001\n" + }, + { + MM_UTIL | MM_PRINT, "BSD:ls", MM_ERROR, + "illegal option -- z", "refer to manual", "BSD:ls:001", + "", + "BSD:ls: ERROR: illegal option -- z\n" + "TO FIX: refer to manual BSD:ls:001\n" + }, + { + MM_UTIL | MM_PRINT, MM_NULLLBL, MM_ERROR, + "illegal option -- z", "refer to manual", "BSD:ls:001", + NULL, + "ERROR: illegal option -- z\n" + "TO FIX: refer to manual BSD:ls:001\n" + }, + { + MM_UTIL | MM_PRINT, "BSD:ls", MM_ERROR, + "illegal option -- z", MM_NULLACT, MM_NULLTAG, + NULL, + "BSD:ls: ERROR: illegal option -- z\n" + }, + { + MM_UTIL | MM_NULLMC, "BSD:ls", MM_ERROR, + "illegal option -- z", "refer to manual", "BSD:ls:001", + NULL, + "" + }, + { + MM_APPL | MM_PRINT, "ABCDEFGHIJ:abcdefghijklmn", MM_INFO, + "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" + "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" + "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" + "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", + "refer to manual", "ABCDEFGHIJ:abcdefghijklmn:001", + NULL, + "ABCDEFGHIJ:abcdefghijklmn: INFO: " + "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" + "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" + "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" + "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx\n" + "TO FIX: refer to manual ABCDEFGHIJ:abcdefghijklmn:001\n" + }, + { + MM_OPSYS | MM_PRINT, "TEST:test", MM_HALT, + "failed", "nothing can help me", "NOTHING", + NULL, + "TEST:test: HALT: failed\n" + "TO FIX: nothing can help me NOTHING\n" + }, + { + MM_OPSYS | MM_PRINT, "TEST:test", MM_WARNING, + "failed", "nothing can help me", "NOTHING", + NULL, + "TEST:test: WARNING: failed\n" + "TO FIX: nothing can help me NOTHING\n" + }, + { + MM_OPSYS | MM_PRINT, "TEST:test", MM_NOSEV, + "failed", "nothing can help me", "NOTHING", + NULL, + "TEST:test: failed\n" + "TO FIX: nothing can help me NOTHING\n" + } +}; + +static char * +run_test(long classification, const char *label, int severity, + const char *text, const char *action, const char *tag) +{ + int pip[2]; + pid_t pid, wpid; + char *result, *p; + size_t resultsize; + ssize_t n; + int status; + + if (pipe(pip) == -1) + err(2, "pipe"); + pid = fork(); + if (pid == -1) + err(2, "fork"); + if (pid == 0) { + close(pip[0]); + if (pip[1] != STDERR_FILENO && + dup2(pip[1], STDERR_FILENO) == -1) + _exit(2); + if (fmtmsg(classification, label, severity, text, action, tag) + != MM_OK) + _exit(1); + else + _exit(0); + } + close(pip[1]); + resultsize = 1024; + result = malloc(resultsize); + p = result; + while ((n = read(pip[0], p, result + resultsize - p - 1)) != 0) { + if (n == -1) { + if (errno == EINTR) + continue; + else + err(2, "read"); + } + p += n; + if (result + resultsize == p - 1) { + resultsize *= 2; + result = realloc(result, resultsize); + if (result == NULL) + err(2, "realloc"); + } + } + if (memchr(result, '\0', p - result) != NULL) { + free(result); + return (NULL); + } + *p = '\0'; + close(pip[0]); + while ((wpid = waitpid(pid, &status, 0)) == -1 && errno == EINTR) + ; + if (wpid == -1) + err(2, "waitpid"); + if (status != 0) { + free(result); + return (NULL); + } + return (result); +} + +ATF_TC_WITHOUT_HEAD(fmtmsg_test); +ATF_TC_BODY(fmtmsg_test, tc) +{ + char *result; + struct testcase *t; + int i; + + for (i = 0; i < nitems(testcases); i++) { + t = &testcases[i]; + if (t->msgverb != NULL) + setenv("MSGVERB", t->msgverb, 1); + else + unsetenv("MSGVERB"); + result = run_test(t->classification, t->label, t->severity, + t->text, t->action, t->tag); + ATF_CHECK_MSG(result != NULL, "testcase %d failed", i + 1); + if (result != NULL) + ATF_CHECK_MSG(strcmp(result, t->result) == 0, + "results for testcase %d didn't match; " + "`%s` != `%s`", i + 1, result, t->result); + free(result); + } +} + +ATF_TP_ADD_TCS(tp) +{ + + ATF_TP_ADD_TC(tp, fmtmsg_test); + + return (atf_no_error()); +} diff --git a/lib/libc/tests/gen/fnmatch_test.c b/lib/libc/tests/gen/fnmatch_test.c new file mode 100644 index 0000000..8d9ead2 --- /dev/null +++ b/lib/libc/tests/gen/fnmatch_test.c @@ -0,0 +1,188 @@ +/*- + * Copyright (c) 2010 Jilles Tjoelker + * 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 <sys/cdefs.h> +__FBSDID("$FreeBSD$"); + +#include <sys/param.h> +#include <errno.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> + +#include <atf-c.h> + +#include "fnmatch_testcases.h" + +static const char * +flags_to_string(int flags) +{ + static const int flagvalues[] = { FNM_NOESCAPE, FNM_PATHNAME, + FNM_PERIOD, FNM_LEADING_DIR, FNM_CASEFOLD, 0 }; + static const char flagnames[] = "FNM_NOESCAPE\0FNM_PATHNAME\0FNM_PERIOD\0FNM_LEADING_DIR\0FNM_CASEFOLD\0"; + static char result[sizeof(flagnames) + 3 * sizeof(int) + 2]; + char *p; + size_t i, len; + const char *fp; + + p = result; + fp = flagnames; + for (i = 0; flagvalues[i] != 0; i++) { + len = strlen(fp); + if (flags & flagvalues[i]) { + if (p != result) + *p++ = '|'; + memcpy(p, fp, len); + p += len; + flags &= ~flagvalues[i]; + } + fp += len + 1; + } + if (p == result) + memcpy(p, "0", 2); + else if (flags != 0) + sprintf(p, "%d", flags); + else + *p = '\0'; + return result; +} + +ATF_TC_WITHOUT_HEAD(fnmatch_test); +ATF_TC_BODY(fnmatch_test, tc) +{ + size_t i; + int flags, result; + struct testcase *t; + + for (i = 0; i < nitems(testcases); i++) { + t = &testcases[i]; + flags = t->flags; + do { + result = fnmatch(t->pattern, t->string, flags); + if (result != t->result) + break; + if (strchr(t->pattern, '\\') == NULL && + !(flags & FNM_NOESCAPE)) { + flags |= FNM_NOESCAPE; + result = fnmatch(t->pattern, t->string, flags); + if (result != t->result) + break; + flags = t->flags; + } + if (strchr(t->pattern, '\\') != NULL && + strchr(t->string, '\\') == NULL && + t->result == FNM_NOMATCH && + !(flags & (FNM_NOESCAPE | FNM_LEADING_DIR))) { + flags |= FNM_NOESCAPE; + result = fnmatch(t->pattern, t->string, flags); + if (result != t->result) + break; + flags = t->flags; + } + if ((t->string[0] != '.' || t->pattern[0] == '.' || + t->result == FNM_NOMATCH) && + !(flags & (FNM_PATHNAME | FNM_PERIOD))) { + flags |= FNM_PERIOD; + result = fnmatch(t->pattern, t->string, flags); + if (result != t->result) + break; + flags = t->flags; + } + if ((strchr(t->string, '/') == NULL || + t->result == FNM_NOMATCH) && + !(flags & FNM_PATHNAME)) { + flags |= FNM_PATHNAME; + result = fnmatch(t->pattern, t->string, flags); + if (result != t->result) + break; + flags = t->flags; + } + if ((((t->string[0] != '.' || t->pattern[0] == '.') && + strstr(t->string, "/.") == NULL) || + t->result == FNM_NOMATCH) && + flags & FNM_PATHNAME && !(flags & FNM_PERIOD)) { + flags |= FNM_PERIOD; + result = fnmatch(t->pattern, t->string, flags); + if (result != t->result) + break; + flags = t->flags; + } + if ((((t->string[0] != '.' || t->pattern[0] == '.') && + strchr(t->string, '/') == NULL) || + t->result == FNM_NOMATCH) && + !(flags & (FNM_PATHNAME | FNM_PERIOD))) { + flags |= FNM_PATHNAME | FNM_PERIOD; + result = fnmatch(t->pattern, t->string, flags); + if (result != t->result) + break; + flags = t->flags; + } + if ((strchr(t->string, '/') == NULL || t->result == 0) + && !(flags & FNM_LEADING_DIR)) { + flags |= FNM_LEADING_DIR; + result = fnmatch(t->pattern, t->string, flags); + if (result != t->result) + break; + flags = t->flags; + } + if (t->result == 0 && !(flags & FNM_CASEFOLD)) { + flags |= FNM_CASEFOLD; + result = fnmatch(t->pattern, t->string, flags); + if (result != t->result) + break; + flags = t->flags; + } + if (strchr(t->pattern, '\\') == NULL && + t->result == 0 && + !(flags & (FNM_NOESCAPE | FNM_CASEFOLD))) { + flags |= FNM_NOESCAPE | FNM_CASEFOLD; + result = fnmatch(t->pattern, t->string, flags); + if (result != t->result) + break; + flags = t->flags; + } + } while (0); + + ATF_CHECK(result == t->result); + if (result == t->result) + printf("fnmatch(\"%s\", \"%s\", %s) == %d\n", + t->pattern, t->string, flags_to_string(flags), result); + else + printf("fnmatch(\"%s\", \"%s\", %s) != %d (was %d)\n", + t->pattern, t->string, flags_to_string(flags), + t->result, result); + } + +} + +ATF_TP_ADD_TCS(tp) +{ + + ATF_TP_ADD_TC(tp, fnmatch_test); + + return (atf_no_error()); +} diff --git a/lib/libc/tests/gen/fnmatch_testcases.h b/lib/libc/tests/gen/fnmatch_testcases.h new file mode 100644 index 0000000..537011f --- /dev/null +++ b/lib/libc/tests/gen/fnmatch_testcases.h @@ -0,0 +1,176 @@ +/*- + * Copyright (c) 2010 Jilles Tjoelker + * 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 <sys/cdefs.h> +__FBSDID("$FreeBSD$"); + +#include <fnmatch.h> + +struct testcase { + const char *pattern; + const char *string; + int flags; + int result; +} testcases[] = { + { "", "", 0, 0 }, + { "a", "a", 0, 0 }, + { "a", "b", 0, FNM_NOMATCH }, + { "a", "A", 0, FNM_NOMATCH }, + { "*", "a", 0, 0 }, + { "*", "aa", 0, 0 }, + { "*a", "a", 0, 0 }, + { "*a", "b", 0, FNM_NOMATCH }, + { "*a*", "b", 0, FNM_NOMATCH }, + { "*a*b*", "ab", 0, 0 }, + { "*a*b*", "qaqbq", 0, 0 }, + { "*a*bb*", "qaqbqbbq", 0, 0 }, + { "*a*bc*", "qaqbqbcq", 0, 0 }, + { "*a*bb*", "qaqbqbb", 0, 0 }, + { "*a*bc*", "qaqbqbc", 0, 0 }, + { "*a*bb", "qaqbqbb", 0, 0 }, + { "*a*bc", "qaqbqbc", 0, 0 }, + { "*a*bb", "qaqbqbbq", 0, FNM_NOMATCH }, + { "*a*bc", "qaqbqbcq", 0, FNM_NOMATCH }, + { "*a*a*a*a*a*a*a*a*a*a*", "aaaaaaaaa", 0, FNM_NOMATCH }, + { "*a*a*a*a*a*a*a*a*a*a*", "aaaaaaaaaa", 0, 0 }, + { "*a*a*a*a*a*a*a*a*a*a*", "aaaaaaaaaaa", 0, 0 }, + { ".*.*.*.*.*.*.*.*.*.*", ".........", 0, FNM_NOMATCH }, + { ".*.*.*.*.*.*.*.*.*.*", "..........", 0, 0 }, + { ".*.*.*.*.*.*.*.*.*.*", "...........", 0, 0 }, + { "*?*?*?*?*?*?*?*?*?*?*", "123456789", 0, FNM_NOMATCH }, + { "??????????*", "123456789", 0, FNM_NOMATCH }, + { "*??????????", "123456789", 0, FNM_NOMATCH }, + { "*?*?*?*?*?*?*?*?*?*?*", "1234567890", 0, 0 }, + { "??????????*", "1234567890", 0, 0 }, + { "*??????????", "1234567890", 0, 0 }, + { "*?*?*?*?*?*?*?*?*?*?*", "12345678901", 0, 0 }, + { "??????????*", "12345678901", 0, 0 }, + { "*??????????", "12345678901", 0, 0 }, + { "[x]", "x", 0, 0 }, + { "[*]", "*", 0, 0 }, + { "[?]", "?", 0, 0 }, + { "[", "[", 0, 0 }, + { "[[]", "[", 0, 0 }, + { "[[]", "x", 0, FNM_NOMATCH }, + { "[*]", "", 0, FNM_NOMATCH }, + { "[*]", "x", 0, FNM_NOMATCH }, + { "[?]", "x", 0, FNM_NOMATCH }, + { "*[*]*", "foo*foo", 0, 0 }, + { "*[*]*", "foo", 0, FNM_NOMATCH }, + { "[0-9]", "0", 0, 0 }, + { "[0-9]", "5", 0, 0 }, + { "[0-9]", "9", 0, 0 }, + { "[0-9]", "/", 0, FNM_NOMATCH }, + { "[0-9]", ":", 0, FNM_NOMATCH }, + { "[0-9]", "*", 0, FNM_NOMATCH }, + { "[!0-9]", "0", 0, FNM_NOMATCH }, + { "[!0-9]", "5", 0, FNM_NOMATCH }, + { "[!0-9]", "9", 0, FNM_NOMATCH }, + { "[!0-9]", "/", 0, 0 }, + { "[!0-9]", ":", 0, 0 }, + { "[!0-9]", "*", 0, 0 }, + { "*[0-9]", "a0", 0, 0 }, + { "*[0-9]", "a5", 0, 0 }, + { "*[0-9]", "a9", 0, 0 }, + { "*[0-9]", "a/", 0, FNM_NOMATCH }, + { "*[0-9]", "a:", 0, FNM_NOMATCH }, + { "*[0-9]", "a*", 0, FNM_NOMATCH }, + { "*[!0-9]", "a0", 0, FNM_NOMATCH }, + { "*[!0-9]", "a5", 0, FNM_NOMATCH }, + { "*[!0-9]", "a9", 0, FNM_NOMATCH }, + { "*[!0-9]", "a/", 0, 0 }, + { "*[!0-9]", "a:", 0, 0 }, + { "*[!0-9]", "a*", 0, 0 }, + { "*[0-9]", "a00", 0, 0 }, + { "*[0-9]", "a55", 0, 0 }, + { "*[0-9]", "a99", 0, 0 }, + { "*[0-9]", "a0a0", 0, 0 }, + { "*[0-9]", "a5a5", 0, 0 }, + { "*[0-9]", "a9a9", 0, 0 }, + { "\\*", "*", 0, 0 }, + { "\\?", "?", 0, 0 }, + { "\\[x]", "[x]", 0, 0 }, + { "\\[", "[", 0, 0 }, + { "\\\\", "\\", 0, 0 }, + { "*\\**", "foo*foo", 0, 0 }, + { "*\\**", "foo", 0, FNM_NOMATCH }, + { "*\\\\*", "foo\\foo", 0, 0 }, + { "*\\\\*", "foo", 0, FNM_NOMATCH }, + { "\\(", "(", 0, 0 }, + { "\\a", "a", 0, 0 }, + { "\\*", "a", 0, FNM_NOMATCH }, + { "\\?", "a", 0, FNM_NOMATCH }, + { "\\*", "\\*", 0, FNM_NOMATCH }, + { "\\?", "\\?", 0, FNM_NOMATCH }, + { "\\[x]", "\\[x]", 0, FNM_NOMATCH }, + { "\\[x]", "\\x", 0, FNM_NOMATCH }, + { "\\[", "\\[", 0, FNM_NOMATCH }, + { "\\(", "\\(", 0, FNM_NOMATCH }, + { "\\a", "\\a", 0, FNM_NOMATCH }, + { "\\", "\\", 0, FNM_NOMATCH }, + { "\\", "", 0, 0 }, + { "\\*", "\\*", FNM_NOESCAPE, 0 }, + { "\\?", "\\?", FNM_NOESCAPE, 0 }, + { "\\", "\\", FNM_NOESCAPE, 0 }, + { "\\\\", "\\", FNM_NOESCAPE, FNM_NOMATCH }, + { "\\\\", "\\\\", FNM_NOESCAPE, 0 }, + { "*\\*", "foo\\foo", FNM_NOESCAPE, 0 }, + { "*\\*", "foo", FNM_NOESCAPE, FNM_NOMATCH }, + { "*", ".", FNM_PERIOD, FNM_NOMATCH }, + { "?", ".", FNM_PERIOD, FNM_NOMATCH }, + { ".*", ".", 0, 0 }, + { ".*", "..", 0, 0 }, + { ".*", ".a", 0, 0 }, + { "[0-9]", ".", FNM_PERIOD, FNM_NOMATCH }, + { "a*", "a.", 0, 0 }, + { "a/a", "a/a", FNM_PATHNAME, 0 }, + { "a/*", "a/a", FNM_PATHNAME, 0 }, + { "*/a", "a/a", FNM_PATHNAME, 0 }, + { "*/*", "a/a", FNM_PATHNAME, 0 }, + { "a*b/*", "abbb/x", FNM_PATHNAME, 0 }, + { "a*b/*", "abbb/.x", FNM_PATHNAME, 0 }, + { "*", "a/a", FNM_PATHNAME, FNM_NOMATCH }, + { "*/*", "a/a/a", FNM_PATHNAME, FNM_NOMATCH }, + { "b/*", "b/.x", FNM_PATHNAME | FNM_PERIOD, FNM_NOMATCH }, + { "b*/*", "a/.x", FNM_PATHNAME | FNM_PERIOD, FNM_NOMATCH }, + { "b/.*", "b/.x", FNM_PATHNAME | FNM_PERIOD, 0 }, + { "b*/.*", "b/.x", FNM_PATHNAME | FNM_PERIOD, 0 }, + { "a", "A", FNM_CASEFOLD, 0 }, + { "A", "a", FNM_CASEFOLD, 0 }, + { "[a]", "A", FNM_CASEFOLD, 0 }, + { "[A]", "a", FNM_CASEFOLD, 0 }, + { "a", "b", FNM_CASEFOLD, FNM_NOMATCH }, + { "a", "a/b", FNM_PATHNAME, FNM_NOMATCH }, + { "*", "a/b", FNM_PATHNAME, FNM_NOMATCH }, + { "*b", "a/b", FNM_PATHNAME, FNM_NOMATCH }, + { "a", "a/b", FNM_PATHNAME | FNM_LEADING_DIR, 0 }, + { "*", "a/b", FNM_PATHNAME | FNM_LEADING_DIR, 0 }, + { "*", ".a/b", FNM_PATHNAME | FNM_LEADING_DIR, 0 }, + { "*a", ".a/b", FNM_PATHNAME | FNM_LEADING_DIR, 0 }, + { "*", ".a/b", FNM_PATHNAME | FNM_PERIOD | FNM_LEADING_DIR, FNM_NOMATCH }, + { "*a", ".a/b", FNM_PATHNAME | FNM_PERIOD | FNM_LEADING_DIR, FNM_NOMATCH }, + { "a*b/*", "abbb/.x", FNM_PATHNAME | FNM_PERIOD, FNM_NOMATCH }, +}; diff --git a/lib/libc/tests/gen/ftw_test.c b/lib/libc/tests/gen/ftw_test.c new file mode 100644 index 0000000..b120f01 --- /dev/null +++ b/lib/libc/tests/gen/ftw_test.c @@ -0,0 +1,127 @@ +/*- + * Copyright (c) 2012 Jilles Tjoelker + * 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. + */ + +/* + * Limited test program for nftw() as specified by IEEE Std. 1003.1-2008. + */ + +#include <sys/cdefs.h> +__FBSDID("$FreeBSD$"); + +#include <sys/wait.h> +#include <err.h> +#include <errno.h> +#include <fcntl.h> +#include <ftw.h> +#include <limits.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <spawn.h> +#include <unistd.h> + +#include <atf-c.h> + +extern char **environ; + +static char template[] = "testftw.XXXXXXXXXX"; +static char dir[PATH_MAX]; +static int ftwflags; + +static int +cb(const char *path, const struct stat *st, int type, struct FTW *f) +{ + + switch (type) { + case FTW_D: + if ((ftwflags & FTW_DEPTH) == 0) + return (0); + break; + case FTW_DP: + if ((ftwflags & FTW_DEPTH) != 0) + return (0); + break; + case FTW_SL: + if ((ftwflags & FTW_PHYS) != 0) + return (0); + break; + } + ATF_CHECK_MSG(false, + "unexpected path=%s type=%d f.level=%d\n", + path, type, f->level); + return (0); +} + +ATF_TC_WITHOUT_HEAD(ftw_test); +ATF_TC_BODY(ftw_test, tc) +{ + int fd; + + ATF_REQUIRE_MSG(mkdtemp(template) != NULL, "mkdtemp failed"); + + /* XXX: the path needs to be absolute for the 0/FTW_DEPTH testcases */ + ATF_REQUIRE_MSG(realpath(template, dir) != NULL, + "realpath failed; errno=%d", errno); + + fd = open(dir, O_DIRECTORY|O_RDONLY); + ATF_REQUIRE_MSG(fd != -1, "open failed; errno=%d", errno); + + ATF_REQUIRE_MSG(mkdirat(fd, "d1", 0777) == 0, + "mkdirat failed; errno=%d", errno); + + ATF_REQUIRE_MSG(symlinkat(dir, fd, "d1/looper") == 0, + "symlinkat failed; errno=%d", errno); + + printf("ftwflags=FTW_PHYS\n"); + ftwflags = FTW_PHYS; + ATF_REQUIRE_MSG(nftw(dir, cb, 10, ftwflags) != -1, + "nftw FTW_PHYS failed; errno=%d", errno); + + printf("ftwflags=FTW_PHYS|FTW_DEPTH\n"); + ftwflags = FTW_PHYS|FTW_DEPTH; + ATF_REQUIRE_MSG(nftw(dir, cb, 10, ftwflags) != -1, + "nftw FTW_PHYS|FTW_DEPTH failed; errno=%d", errno); + + printf("ftwflags=0\n"); + ftwflags = 0; + ATF_REQUIRE_MSG(nftw(dir, cb, 10, ftwflags) != -1, + "nftw 0 failed; errno=%d", errno); + + printf("ftwflags=FTW_DEPTH\n"); + ftwflags = FTW_DEPTH; + ATF_REQUIRE_MSG(nftw(dir, cb, 10, ftwflags) != -1, + "nftw FTW_DEPTH failed; errno=%d", errno); + + close(fd); +} + +ATF_TP_ADD_TCS(tp) +{ + + ATF_TP_ADD_TC(tp, ftw_test); + + return (atf_no_error()); +} diff --git a/lib/libc/tests/gen/popen_test.c b/lib/libc/tests/gen/popen_test.c new file mode 100644 index 0000000..5c615b7 --- /dev/null +++ b/lib/libc/tests/gen/popen_test.c @@ -0,0 +1,251 @@ +/*- + * Copyright (c) 2013 Jilles Tjoelker + * 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. + */ + +/* + * Limited test program for popen() as specified by IEEE Std. 1003.1-2008, + * with BSD extensions. + */ + +#include <sys/cdefs.h> +__FBSDID("$FreeBSD$"); + +#include <sys/param.h> +#include <sys/wait.h> +#include <errno.h> +#include <fcntl.h> +#include <signal.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +#include <atf-c.h> + +static volatile sig_atomic_t got_sigpipe; + +static void +sigpipe_handler(int sig __unused) +{ + got_sigpipe = 1; +} + +static void +check_cloexec(FILE *fp, const char *mode) +{ + int exp_flags, flags; + + flags = fcntl(fileno(fp), F_GETFD); + ATF_CHECK_MSG(flags != -1, "fcntl(F_GETFD) failed; errno=%d", errno); + if (flags == -1) + return; + if (strchr(mode, 'e') != NULL) + exp_flags = FD_CLOEXEC; + else + exp_flags = 0; + ATF_CHECK_MSG((flags & FD_CLOEXEC) == exp_flags, + "bad cloexec flag; %d != %d", flags, exp_flags); +} + +ATF_TC_WITHOUT_HEAD(popen_all_modes_test); +ATF_TC_BODY(popen_all_modes_test, tc) +{ + FILE *fp; + int i, status; + const char *mode; + const char *allmodes[] = { "r", "w", "r+", "re", "we", "r+e", "re+" }; + + for (i = 0; i < nitems(allmodes); i++) { + mode = allmodes[i]; + fp = popen("exit 7", mode); + ATF_CHECK_MSG(fp != NULL, "popen(, \"%s\") failed", mode); + if (fp == NULL) + continue; + check_cloexec(fp, mode); + status = pclose(fp); + ATF_CHECK_MSG(WIFEXITED(status) && WEXITSTATUS(status) == 7, + "bad exit status (no I/O)"); + } +} + +ATF_TC_WITHOUT_HEAD(popen_rmodes_test); +ATF_TC_BODY(popen_rmodes_test, tc) +{ + FILE *fp; + const char *rmodes[] = { "r", "r+", "re", "r+e", "re+" }; + const char *mode; + char buf[80]; + int i, status; + + for (i = 0; i < nitems(rmodes); i++) { + mode = rmodes[i]; + fp = popen("exit 9", mode); + ATF_CHECK_MSG(fp != NULL, "popen(, \"%s\") failed", mode); + if (fp == NULL) + continue; + check_cloexec(fp, mode); + bool input_error_1 = !(fgetc(fp) != EOF || !feof(fp) || !ferror(fp)); + ATF_CHECK_MSG(!input_error_1, "input error 1"); + if (input_error_1) + continue; + status = pclose(fp); + ATF_CHECK_MSG(WIFEXITED(status) && WEXITSTATUS(status) == 9, + "bad exit status (input)"); + } + + for (i = 0; i < nitems(rmodes); i++) { + char *sres; + mode = rmodes[i]; + fp = popen("echo hi there", mode); + ATF_CHECK_MSG(fp != NULL, "popen(, \"%s\") failed", mode); + if (fp == NULL) + continue; + check_cloexec(fp, mode); + ATF_CHECK_MSG((sres = fgets(buf, sizeof(buf), fp)) != NULL, + "Input error 2"); + if (sres != NULL) + ATF_CHECK_MSG(strcmp(buf, "hi there\n") == 0, + "Bad input 1"); + status = pclose(fp); + ATF_CHECK_MSG(WIFEXITED(status) && WEXITSTATUS(status) == 0, + "Bad exit status (input)"); + } +} + +ATF_TC_WITHOUT_HEAD(popen_wmodes_test); +ATF_TC_BODY(popen_wmodes_test, tc) +{ + FILE *fp, *fp2; + const char *wmodes[] = { "w", "r+", "we", "r+e", "re+" }; + const char *mode; + struct sigaction act, oact; + int i, j, status; + + for (i = 0; i < nitems(wmodes); i++) { + mode = wmodes[i]; + fp = popen("read x && [ \"$x\" = abcd ]", mode); + ATF_CHECK_MSG(fp != NULL, "popen(, \"%s\") failed", mode); + if (fp == NULL) + continue; + check_cloexec(fp, mode); + ATF_CHECK_MSG(fputs("abcd\n", fp) != EOF, + "Output error 1"); + status = pclose(fp); + ATF_CHECK_MSG(WIFEXITED(status) && WEXITSTATUS(status) == 0, + "Bad exit status (output)"); + } + + act.sa_handler = sigpipe_handler; + act.sa_flags = SA_RESTART; + sigemptyset(&act.sa_mask); + ATF_CHECK_MSG(sigaction(SIGPIPE, &act, &oact) != -1, + "sigaction() failed"); + for (i = 0; i < nitems(wmodes); i++) { + mode = wmodes[i]; + fp = popen("exit 88", mode); + ATF_CHECK_MSG(fp != NULL, "popen(, \"%s\") failed", mode); + if (fp == NULL) + continue; + check_cloexec(fp, mode); + got_sigpipe = 0; + while (fputs("abcd\n", fp) != EOF) + ; + ATF_CHECK_MSG(ferror(fp) && errno == EPIPE, "Expected EPIPE"); + ATF_CHECK_MSG(got_sigpipe, "Expected SIGPIPE"); + status = pclose(fp); + ATF_CHECK_MSG(WIFEXITED(status) && WEXITSTATUS(status) == 88, + "Bad exit status (EPIPE)"); + } + ATF_CHECK_MSG(sigaction(SIGPIPE, &oact, NULL) != -1, + "sigaction() failed"); + + for (i = 0; i < nitems(wmodes); i++) { + for (j = 0; j < nitems(wmodes); j++) { + mode = wmodes[i]; + fp = popen("read x", mode); + ATF_CHECK_MSG(fp != NULL, + "popen(, \"%s\") failed", mode); + if (fp == NULL) + continue; + mode = wmodes[j]; + fp2 = popen("read x", mode); + ATF_CHECK_MSG(fp2 != NULL, + "popen(, \"%s\") failed", mode); + if (fp2 == NULL) { + pclose(fp); + continue; + } + /* If fp2 inherits fp's pipe, we will deadlock here. */ + status = pclose(fp); + ATF_CHECK_MSG(WIFEXITED(status) && WEXITSTATUS(status) == 1, + "bad exit status (2 pipes)"); + status = pclose(fp2); + ATF_CHECK_MSG(WIFEXITED(status) && WEXITSTATUS(status) == 1, + "bad exit status (2 pipes)"); + } + } +} + +ATF_TC_WITHOUT_HEAD(popen_rwmodes_test); +ATF_TC_BODY(popen_rwmodes_test, tc) +{ + const char *rwmodes[] = { "r+", "r+e", "re+" }; + FILE *fp; + const char *mode; + char *sres; + char buf[80]; + int i, ires, status; + + for (i = 0; i < nitems(rwmodes); i++) { + mode = rwmodes[i]; + fp = popen("read x && printf '%s\\n' \"Q${x#a}\"", mode); + ATF_CHECK_MSG(fp != NULL, "popen(, \"%s\") failed", mode); + if (fp == NULL) + continue; + check_cloexec(fp, mode); + ATF_CHECK_MSG((ires = fputs("abcd\n", fp)) != EOF, + "Output error 2"); + if (ires != EOF) { + sres = fgets(buf, sizeof(buf), fp); + ATF_CHECK_MSG(sres != NULL, "Input error 3"); + if (sres != NULL) + ATF_CHECK_MSG(strcmp(buf, "Qbcd\n") == 0, + "Bad input 2"); + } + status = pclose(fp); + ATF_CHECK_MSG(WIFEXITED(status) && WEXITSTATUS(status) == 0, + "bad exit status (I/O)"); + } +} + +ATF_TP_ADD_TCS(tp) +{ + + ATF_TP_ADD_TC(tp, popen_all_modes_test); + ATF_TP_ADD_TC(tp, popen_rmodes_test); + ATF_TP_ADD_TC(tp, popen_wmodes_test); + ATF_TP_ADD_TC(tp, popen_rwmodes_test); + + return (atf_no_error()); +} diff --git a/lib/libc/tests/gen/posix_spawn_test.c b/lib/libc/tests/gen/posix_spawn_test.c new file mode 100644 index 0000000..e04d103 --- /dev/null +++ b/lib/libc/tests/gen/posix_spawn_test.c @@ -0,0 +1,103 @@ +/*- + * Copyright (c) 2011 Jilles Tjoelker + * 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. + */ + +/* + * Test program for posix_spawn() and posix_spawnp() as specified by + * IEEE Std. 1003.1-2008. + */ + +#include <sys/cdefs.h> +__FBSDID("$FreeBSD$"); + +#include <sys/wait.h> +#include <errno.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <spawn.h> + +#include <atf-c.h> + +char *myenv[2] = { "answer=42", NULL }; + +ATF_TC_WITHOUT_HEAD(posix_spawn_simple_test); +ATF_TC_BODY(posix_spawn_simple_test, tc) +{ + char *myargs[4]; + int error, status; + pid_t pid, waitres; + + /* Make sure we have no child processes. */ + while (waitpid(-1, NULL, 0) != -1) + ; + ATF_REQUIRE_MSG(errno == ECHILD, "errno was not ECHILD: %d", errno); + + /* Simple test. */ + myargs[0] = "sh"; + myargs[1] = "-c"; + myargs[2] = "exit $answer"; + myargs[3] = NULL; + error = posix_spawnp(&pid, myargs[0], NULL, NULL, myargs, myenv); + ATF_REQUIRE(error == 0); + waitres = waitpid(pid, &status, 0); + ATF_REQUIRE(waitres == pid); + ATF_REQUIRE(WIFEXITED(status) && WEXITSTATUS(status) == 42); +} + +ATF_TC_WITHOUT_HEAD(posix_spawn_no_such_command_negative_test); +ATF_TC_BODY(posix_spawn_no_such_command_negative_test, tc) +{ + char *myargs[4]; + int error, status; + pid_t pid, waitres; + + /* + * If the executable does not exist, the function shall either fail + * and not create a child process or succeed and create a child + * process that exits with status 127. + */ + myargs[0] = "/var/empty/nonexistent"; + myargs[1] = NULL; + error = posix_spawn(&pid, myargs[0], NULL, NULL, myargs, myenv); + if (error == 0) { + waitres = waitpid(pid, &status, 0); + ATF_REQUIRE(waitres == pid); + ATF_REQUIRE(WIFEXITED(status) && WEXITSTATUS(status) == 127); + } else { + ATF_REQUIRE(error == ENOENT); + waitres = waitpid(-1, NULL, 0); + ATF_REQUIRE(waitres == -1 && errno == ECHILD); + } +} + +ATF_TP_ADD_TCS(tp) +{ + + ATF_TP_ADD_TC(tp, posix_spawn_simple_test); + ATF_TP_ADD_TC(tp, posix_spawn_no_such_command_negative_test); + + return (atf_no_error()); +} diff --git a/lib/libc/tests/gen/test-fnmatch.c b/lib/libc/tests/gen/test-fnmatch.c new file mode 100644 index 0000000..7771ab3 --- /dev/null +++ b/lib/libc/tests/gen/test-fnmatch.c @@ -0,0 +1,102 @@ +/*- + * Copyright (c) 2010 Jilles Tjoelker + * 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 <sys/cdefs.h> +__FBSDID("$FreeBSD$"); + +#include <sys/param.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> + +#include "fnmatch_testcases.h" + +static int +write_sh_tests(const char *progname, int num) +{ + size_t i; + struct testcase *t; + + printf("# Generated by %s -s %d, do not edit.\n", progname, num); + printf("# $" "FreeBSD$\n"); + printf("failures=\n"); + printf("failed() { printf '%%s\\n' \"Failed: $1 '$2' '$3'\"; failures=x$failures; }\n"); + if (num == 1) { + printf("testmatch() { eval \"case \\$2 in ''$1) ;; *) failed testmatch \\\"\\$@\\\";; esac\"; }\n"); + printf("testnomatch() { eval \"case \\$2 in ''$1) failed testnomatch \\\"\\$@\\\";; esac\"; }\n"); + } else if (num == 2) { + printf("# We do not treat a backslash specially in this case,\n"); + printf("# but this is not the case in all shells.\n"); + printf("netestmatch() { case $2 in $1) ;; *) failed netestmatch \"$@\";; esac; }\n"); + printf("netestnomatch() { case $2 in $1) failed netestnomatch \"$@\";; esac; }\n"); + } + + for (i = 0; i < nitems(testcases); i++) { + t = &testcases[i]; + if (strchr(t->pattern, '\'') != NULL || + strchr(t->string, '\'') != NULL) + continue; + if (t->flags == 0 && strcmp(t->pattern, "\\") == 0) + continue; + if (num == 1 && t->flags == 0) + printf("test%smatch '%s' '%s'\n", + t->result == FNM_NOMATCH ? "no" : "", + t->pattern, t->string); + if (num == 2 && (t->flags == FNM_NOESCAPE || + (t->flags == 0 && strchr(t->pattern, '\\') == NULL))) + printf("netest%smatch '%s' '%s'\n", + t->result == FNM_NOMATCH ? "no" : "", + t->pattern, t->string); + } + printf("[ -z \"$failures\" ]\n"); + return 0; +} + +static void +usage(char *progname) +{ + fprintf(stderr, "usage: %s [-s num]\n", progname); + fprintf(stderr, "-s option writes tests for sh(1), num is 1 or 2\n"); +} + +int +main(int argc, char *argv[]) +{ + int opt; + + while ((opt = getopt(argc, argv, "s:")) != -1) { + switch (opt) { + case 's': + return (write_sh_tests(argv[0], atoi(optarg))); + default: + usage(argv[0]); + exit(1); + } + } + usage(argv[0]); + exit(1); +} diff --git a/lib/libc/tests/gen/wordexp_test.c b/lib/libc/tests/gen/wordexp_test.c new file mode 100644 index 0000000..3ccc677 --- /dev/null +++ b/lib/libc/tests/gen/wordexp_test.c @@ -0,0 +1,360 @@ +/*- + * Copyright (c) 2003 Tim J. Robbins + * 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. + */ + +/* + * Test program for wordexp() and wordfree() as specified by + * IEEE Std. 1003.1-2001. + */ + +#include <sys/cdefs.h> +__FBSDID("$FreeBSD$"); + +#include <sys/wait.h> +#include <errno.h> +#include <signal.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <wordexp.h> + +#include <atf-c.h> + +static void +chld_handler(int x) +{ + int status, serrno; + + (void)x; + serrno = errno; + while (waitpid(-1, &status, WNOHANG) > 0) + ; + errno = serrno; +} + +ATF_TC_WITHOUT_HEAD(simple_test); +ATF_TC_BODY(simple_test, tc) +{ + wordexp_t we; + int r; + + /* Test that the macros are there. */ + (void)(WRDE_APPEND + WRDE_DOOFFS + WRDE_NOCMD + WRDE_REUSE + + WRDE_SHOWERR + WRDE_UNDEF); + (void)(WRDE_BADCHAR + WRDE_BADVAL + WRDE_CMDSUB + WRDE_NOSPACE + + WRDE_SYNTAX); + + /* Simple test. */ + r = wordexp("hello world", &we, 0); + ATF_REQUIRE(r == 0); + ATF_REQUIRE(we.we_wordc == 2); + ATF_REQUIRE(strcmp(we.we_wordv[0], "hello") == 0); + ATF_REQUIRE(strcmp(we.we_wordv[1], "world") == 0); + ATF_REQUIRE(we.we_wordv[2] == NULL); + wordfree(&we); +} + +ATF_TC_WITHOUT_HEAD(long_output_test); +ATF_TC_BODY(long_output_test, tc) +{ + char longdata[6 * 10000 + 1]; + wordexp_t we; + int i, r; + + /* Long output. */ + for (i = 0; i < 10000; i++) + snprintf(longdata + 6 * i, 7, "%05d ", i); + r = wordexp(longdata, &we, 0); + ATF_REQUIRE(r == 0); + ATF_REQUIRE(we.we_wordc == 10000); + ATF_REQUIRE(we.we_wordv[10000] == NULL); + wordfree(&we); +} + +ATF_TC_WITHOUT_HEAD(WRDE_DOOFFS_test); +ATF_TC_BODY(WRDE_DOOFFS_test, tc) +{ + wordexp_t we; + int r; + + we.we_offs = 3; + r = wordexp("hello world", &we, WRDE_DOOFFS); + ATF_REQUIRE(r == 0); + ATF_REQUIRE(we.we_wordc == 2); + ATF_REQUIRE(we.we_wordv[0] == NULL); + ATF_REQUIRE(we.we_wordv[1] == NULL); + ATF_REQUIRE(we.we_wordv[2] == NULL); + ATF_REQUIRE(strcmp(we.we_wordv[3], "hello") == 0); + ATF_REQUIRE(strcmp(we.we_wordv[4], "world") == 0); + ATF_REQUIRE(we.we_wordv[5] == NULL); + wordfree(&we); +} + +ATF_TC_WITHOUT_HEAD(WRDE_REUSE_test); +ATF_TC_BODY(WRDE_REUSE_test, tc) +{ + wordexp_t we; + int r; + + r = wordexp("hello world", &we, 0); + r = wordexp("hello world", &we, WRDE_REUSE); + ATF_REQUIRE(r == 0); + ATF_REQUIRE(we.we_wordc == 2); + ATF_REQUIRE(strcmp(we.we_wordv[0], "hello") == 0); + ATF_REQUIRE(strcmp(we.we_wordv[1], "world") == 0); + ATF_REQUIRE(we.we_wordv[2] == NULL); + wordfree(&we); +} + +ATF_TC_WITHOUT_HEAD(WRDE_APPEND_test); +ATF_TC_BODY(WRDE_APPEND_test, tc) +{ + wordexp_t we; + int r; + + r = wordexp("this is", &we, 0); + ATF_REQUIRE(r == 0); + r = wordexp("a test", &we, WRDE_APPEND); + ATF_REQUIRE(r == 0); + ATF_REQUIRE(we.we_wordc == 4); + ATF_REQUIRE(strcmp(we.we_wordv[0], "this") == 0); + ATF_REQUIRE(strcmp(we.we_wordv[1], "is") == 0); + ATF_REQUIRE(strcmp(we.we_wordv[2], "a") == 0); + ATF_REQUIRE(strcmp(we.we_wordv[3], "test") == 0); + ATF_REQUIRE(we.we_wordv[4] == NULL); + wordfree(&we); +} + +ATF_TC_WITHOUT_HEAD(WRDE_DOOFFS__WRDE_APPEND_test); +ATF_TC_BODY(WRDE_DOOFFS__WRDE_APPEND_test, tc) +{ + wordexp_t we; + int r; + + we.we_offs = 2; + r = wordexp("this is", &we, WRDE_DOOFFS); + ATF_REQUIRE(r == 0); + r = wordexp("a test", &we, WRDE_APPEND|WRDE_DOOFFS); + ATF_REQUIRE(r == 0); + r = wordexp("of wordexp", &we, WRDE_APPEND|WRDE_DOOFFS); + ATF_REQUIRE(r == 0); + ATF_REQUIRE(we.we_wordc == 6); + ATF_REQUIRE(we.we_wordv[0] == NULL); + ATF_REQUIRE(we.we_wordv[1] == NULL); + ATF_REQUIRE(strcmp(we.we_wordv[2], "this") == 0); + ATF_REQUIRE(strcmp(we.we_wordv[3], "is") == 0); + ATF_REQUIRE(strcmp(we.we_wordv[4], "a") == 0); + ATF_REQUIRE(strcmp(we.we_wordv[5], "test") == 0); + ATF_REQUIRE(strcmp(we.we_wordv[6], "of") == 0); + ATF_REQUIRE(strcmp(we.we_wordv[7], "wordexp") == 0); + ATF_REQUIRE(we.we_wordv[8] == NULL); + wordfree(&we); +} + +ATF_TC_WITHOUT_HEAD(WRDE_UNDEF_test); +ATF_TC_BODY(WRDE_UNDEF_test, tc) +{ + wordexp_t we; + int r; + + r = wordexp("${dont_set_me}", &we, WRDE_UNDEF); + ATF_REQUIRE(r == WRDE_BADVAL); +} + +ATF_TC_WITHOUT_HEAD(WRDE_NOCMD_test); +ATF_TC_BODY(WRDE_NOCMD_test, tc) +{ + wordexp_t we; + int r; + + r = wordexp("`date`", &we, WRDE_NOCMD); + ATF_REQUIRE(r == WRDE_CMDSUB); + r = wordexp("\"`date`\"", &we, WRDE_NOCMD); + ATF_REQUIRE(r == WRDE_CMDSUB); + r = wordexp("$(date)", &we, WRDE_NOCMD); + ATF_REQUIRE(r == WRDE_CMDSUB); + r = wordexp("\"$(date)\"", &we, WRDE_NOCMD); + ATF_REQUIRE(r == WRDE_CMDSUB); + r = wordexp("$((3+5))", &we, WRDE_NOCMD); + ATF_REQUIRE(r == 0); + r = wordexp("\\$\\(date\\)", &we, WRDE_NOCMD|WRDE_REUSE); + ATF_REQUIRE(r == 0); + r = wordexp("'`date`'", &we, WRDE_NOCMD|WRDE_REUSE); + ATF_REQUIRE(r == 0); + r = wordexp("'$(date)'", &we, WRDE_NOCMD|WRDE_REUSE); + ATF_REQUIRE(r == 0); + wordfree(&we); +} + +ATF_TC_WITHOUT_HEAD(WRDE_BADCHAR_test); +ATF_TC_BODY(WRDE_BADCHAR_test, tc) +{ + wordexp_t we; + int r; + + r = wordexp("'\n|&;<>(){}'", &we, 0); + ATF_REQUIRE(r == 0); + r = wordexp("\"\n|&;<>(){}\"", &we, WRDE_REUSE); + ATF_REQUIRE(r == 0); + r = wordexp("\\\n\\|\\&\\;\\<\\>\\(\\)\\{\\}", &we, WRDE_REUSE); + ATF_REQUIRE(r == 0); + wordfree(&we); + r = wordexp("test \n test", &we, 0); + ATF_REQUIRE(r == WRDE_BADCHAR); + r = wordexp("test | test", &we, 0); + ATF_REQUIRE(r == WRDE_BADCHAR); + r = wordexp("test & test", &we, 0); + ATF_REQUIRE(r == WRDE_BADCHAR); + r = wordexp("test ; test", &we, 0); + ATF_REQUIRE(r == WRDE_BADCHAR); + r = wordexp("test > test", &we, 0); + ATF_REQUIRE(r == WRDE_BADCHAR); + r = wordexp("test < test", &we, 0); + ATF_REQUIRE(r == WRDE_BADCHAR); + r = wordexp("test ( test", &we, 0); + ATF_REQUIRE(r == WRDE_BADCHAR); + r = wordexp("test ) test", &we, 0); + ATF_REQUIRE(r == WRDE_BADCHAR); + r = wordexp("test { test", &we, 0); + ATF_REQUIRE(r == WRDE_BADCHAR); + r = wordexp("test } test", &we, 0); + ATF_REQUIRE(r == WRDE_BADCHAR); +} + +ATF_TC_WITHOUT_HEAD(WRDE_SYNTAX_test); +ATF_TC_BODY(WRDE_SYNTAX_test, tc) +{ + wordexp_t we; + int r; + + r = wordexp("'", &we, 0); + ATF_REQUIRE(r == WRDE_SYNTAX); + r = wordexp("'", &we, WRDE_UNDEF); + ATF_REQUIRE(r == WRDE_SYNTAX); + r = wordexp("'\\'", &we, 0); + ATF_REQUIRE(r == 0); + ATF_REQUIRE(we.we_wordc == 1); + ATF_REQUIRE(strcmp(we.we_wordv[0], "\\") == 0); + ATF_REQUIRE(we.we_wordv[1] == NULL); + wordfree(&we); + /* Two syntax errors that are not detected by the current we_check(). */ + r = wordexp("${IFS:+'}", &we, 0); + ATF_REQUIRE(r == WRDE_SYNTAX); + r = wordexp("${IFS:+'}", &we, WRDE_UNDEF); + ATF_REQUIRE(r == WRDE_SYNTAX); + r = wordexp("$(case)", &we, 0); + ATF_REQUIRE(r == WRDE_SYNTAX); + r = wordexp("$(case)", &we, WRDE_UNDEF); + ATF_REQUIRE(r == WRDE_SYNTAX); +} + +ATF_TC_WITHOUT_HEAD(with_SIGCHILD_handler_test); +ATF_TC_BODY(with_SIGCHILD_handler_test, tc) +{ + struct sigaction sa; + wordexp_t we; + int r; + + /* With a SIGCHLD handler that reaps all zombies. */ + sa.sa_flags = 0; + sigemptyset(&sa.sa_mask); + sa.sa_handler = chld_handler; + r = sigaction(SIGCHLD, &sa, NULL); + ATF_REQUIRE(r == 0); + r = wordexp("hello world", &we, 0); + ATF_REQUIRE(r == 0); + ATF_REQUIRE(we.we_wordc == 2); + ATF_REQUIRE(strcmp(we.we_wordv[0], "hello") == 0); + ATF_REQUIRE(strcmp(we.we_wordv[1], "world") == 0); + ATF_REQUIRE(we.we_wordv[2] == NULL); + wordfree(&we); + sa.sa_handler = SIG_DFL; + r = sigaction(SIGCHLD, &sa, NULL); + ATF_REQUIRE(r == 0); +} + +ATF_TC_WITHOUT_HEAD(with_unused_non_default_IFS_test); +ATF_TC_BODY(with_unused_non_default_IFS_test, tc) +{ + wordexp_t we; + int r; + + /* + * With IFS set to a non-default value (without depending on whether + * IFS is inherited or not). + */ + r = setenv("IFS", ":", 1); + ATF_REQUIRE(r == 0); + r = wordexp("hello world", &we, 0); + ATF_REQUIRE(r == 0); + ATF_REQUIRE(we.we_wordc == 2); + ATF_REQUIRE(strcmp(we.we_wordv[0], "hello") == 0); + ATF_REQUIRE(strcmp(we.we_wordv[1], "world") == 0); + ATF_REQUIRE(we.we_wordv[2] == NULL); + wordfree(&we); + r = unsetenv("IFS"); + ATF_REQUIRE(r == 0); +} + +ATF_TC_WITHOUT_HEAD(with_used_non_default_IFS_test); +ATF_TC_BODY(with_used_non_default_IFS_test, tc) +{ + wordexp_t we; + int r; + + /* + * With IFS set to a non-default value, and using it. + */ + r = setenv("IFS", ":", 1); + ATF_REQUIRE(r == 0); + r = wordexp("${IFS+hello:world}", &we, 0); + ATF_REQUIRE(r == 0); + ATF_REQUIRE(we.we_wordc == 2); + ATF_REQUIRE(strcmp(we.we_wordv[0], "hello") == 0); + ATF_REQUIRE(strcmp(we.we_wordv[1], "world") == 0); + ATF_REQUIRE(we.we_wordv[2] == NULL); + wordfree(&we); + r = unsetenv("IFS"); + ATF_REQUIRE(r == 0); +} + +ATF_TP_ADD_TCS(tp) +{ + ATF_TP_ADD_TC(tp, simple_test); + ATF_TP_ADD_TC(tp, long_output_test); + ATF_TP_ADD_TC(tp, WRDE_DOOFFS_test); + ATF_TP_ADD_TC(tp, WRDE_REUSE_test); + ATF_TP_ADD_TC(tp, WRDE_APPEND_test); + ATF_TP_ADD_TC(tp, WRDE_DOOFFS__WRDE_APPEND_test); + ATF_TP_ADD_TC(tp, WRDE_UNDEF_test); + ATF_TP_ADD_TC(tp, WRDE_NOCMD_test); + ATF_TP_ADD_TC(tp, WRDE_BADCHAR_test); + ATF_TP_ADD_TC(tp, WRDE_SYNTAX_test); + ATF_TP_ADD_TC(tp, with_SIGCHILD_handler_test); + ATF_TP_ADD_TC(tp, with_unused_non_default_IFS_test); + ATF_TP_ADD_TC(tp, with_used_non_default_IFS_test); + + return (atf_no_error()); +} diff --git a/lib/libc/tests/locale/Makefile b/lib/libc/tests/locale/Makefile index c0e0378..e05cbae 100644 --- a/lib/libc/tests/locale/Makefile +++ b/lib/libc/tests/locale/Makefile @@ -2,6 +2,24 @@ .include <bsd.own.mk> +ATF_TESTS_C+= btowc_test +ATF_TESTS_C+= c16rtomb_test +ATF_TESTS_C+= iswctype_test +ATF_TESTS_C+= mblen_test +ATF_TESTS_C+= mbrlen_test +ATF_TESTS_C+= mbrtoc16_test +ATF_TESTS_C+= mbrtowc_2_test +ATF_TESTS_C+= mbsnrtowcs_2_test +ATF_TESTS_C+= mbsrtowcs_test +ATF_TESTS_C+= mbstowcs_2_test +ATF_TESTS_C+= mbtowc_2_test +ATF_TESTS_C+= towctrans_test +ATF_TESTS_C+= wcrtomb_test +ATF_TESTS_C+= wcsnrtombs_test +ATF_TESTS_C+= wcsrtombs_test +ATF_TESTS_C+= wcstombs_test +ATF_TESTS_C+= wctomb_2_test + NETBSD_ATF_TESTS_C= io_test NETBSD_ATF_TESTS_C+= mbrtowc_test NETBSD_ATF_TESTS_C+= mbstowcs_test @@ -13,7 +31,13 @@ NETBSD_ATF_TESTS_C+= wcsspn_test NETBSD_ATF_TESTS_C+= wcstod_test NETBSD_ATF_TESTS_C+= wctomb_test -CFLAGS.t_wctomb.c+= -Wno-stack-protector +SRCS.mbrtowc_2_test= mbrtowc_test.c +SRCS.mbsnrtowcs_2_test= mbsnrtowcs_test.c +SRCS.mbstowcs_2_test= mbstowcs_test.c +SRCS.mbtowc_2_test= mbtowc_test.c +SRCS.wctomb_2_test= wctomb_test.c + +CFLAGS.t_wctomb.c+= -Wno-stack-protector .include "../Makefile.netbsd-tests" diff --git a/lib/libc/tests/locale/btowc_test.c b/lib/libc/tests/locale/btowc_test.c new file mode 100644 index 0000000..01a1133 --- /dev/null +++ b/lib/libc/tests/locale/btowc_test.c @@ -0,0 +1,71 @@ +/*- + * Copyright (c) 2002 Tim J. Robbins + * 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. + */ + +/* + * Test program for btowc() and wctob() as specified by IEEE Std. 1003.1-2001 + * and ISO/IEC 9899:1999. + * + * The function is tested in the "C" and "ja_JP.eucJP" locales. + */ + +#include <sys/cdefs.h> +__FBSDID("$FreeBSD$"); + +#include <limits.h> +#include <locale.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <wchar.h> + +#include <atf-c.h> + +ATF_TC_WITHOUT_HEAD(btowc_test); +ATF_TC_BODY(btowc_test, tc) +{ + int i; + + /* C/POSIX locale. */ + ATF_REQUIRE(btowc(EOF) == WEOF); + ATF_REQUIRE(wctob(WEOF) == EOF); + for (i = 0; i < UCHAR_MAX; i++) + ATF_REQUIRE(btowc(i) == (wchar_t)i && i == (int)wctob(i)); + + /* Japanese (EUC) locale. */ + ATF_REQUIRE(strcmp(setlocale(LC_CTYPE, "ja_JP.eucJP"), "ja_JP.eucJP") == 0); + ATF_REQUIRE(MB_CUR_MAX > 1); + ATF_REQUIRE(btowc('A') == L'A' && wctob(L'A') == 'A'); + ATF_REQUIRE(btowc(0xa3) == WEOF && wctob(0xa3c1) == EOF); + +} + +ATF_TP_ADD_TCS(tp) +{ + + ATF_TP_ADD_TC(tp, btowc_test); + + return (atf_no_error()); +} diff --git a/lib/libc/tests/locale/c16rtomb_test.c b/lib/libc/tests/locale/c16rtomb_test.c new file mode 100644 index 0000000..ea1f64f --- /dev/null +++ b/lib/libc/tests/locale/c16rtomb_test.c @@ -0,0 +1,166 @@ +/*- + * Copyright (c) 2002 Tim J. Robbins + * All rights reserved. + * + * Copyright (c) 2013 Ed Schouten <ed@FreeBSD.org> + * 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. + */ +/* + * Test program for c16rtomb() as specified by ISO/IEC 9899:2011. + */ + +#include <sys/cdefs.h> +__FBSDID("$FreeBSD$"); + +#include <errno.h> +#include <limits.h> +#include <locale.h> +#include <stdio.h> +#include <string.h> +#include <uchar.h> + +#include <atf-c.h> + +static void +require_lc_ctype(const char *locale_name) +{ + char *lc_ctype_set; + + lc_ctype_set = setlocale(LC_CTYPE, locale_name); + if (lc_ctype_set == NULL) + atf_tc_fail("setlocale(LC_CTYPE, \"%s\") failed; errno=%d", + locale_name, errno); + + ATF_REQUIRE(strcmp(lc_ctype_set, locale_name) == 0); +} + +static mbstate_t s; +static char buf[MB_LEN_MAX + 1]; + +ATF_TC_WITHOUT_HEAD(c16rtomb_c_locale_test); +ATF_TC_BODY(c16rtomb_c_locale_test, tc) +{ + + require_lc_ctype("C"); + + /* + * If the buffer argument is NULL, c16 is implicitly 0, + * c16rtomb() resets its internal state. + */ + ATF_REQUIRE(c16rtomb(NULL, L'\0', NULL) == 1); + ATF_REQUIRE(c16rtomb(NULL, 0xdc00, NULL) == 1); + + /* Null wide character. */ + memset(&s, 0, sizeof(s)); + memset(buf, 0xcc, sizeof(buf)); + ATF_REQUIRE(c16rtomb(buf, 0, &s) == 1); + ATF_REQUIRE((unsigned char)buf[0] == 0 && (unsigned char)buf[1] == 0xcc); + + /* Latin letter A, internal state. */ + ATF_REQUIRE(c16rtomb(NULL, L'\0', NULL) == 1); + ATF_REQUIRE(c16rtomb(NULL, L'A', NULL) == 1); + + /* Latin letter A. */ + memset(&s, 0, sizeof(s)); + memset(buf, 0xcc, sizeof(buf)); + ATF_REQUIRE(c16rtomb(buf, L'A', &s) == 1); + ATF_REQUIRE((unsigned char)buf[0] == 'A' && (unsigned char)buf[1] == 0xcc); + + /* Unicode character 'Pile of poo'. */ + memset(&s, 0, sizeof(s)); + memset(buf, 0xcc, sizeof(buf)); + ATF_REQUIRE(c16rtomb(buf, 0xd83d, &s) == 0); + ATF_REQUIRE(c16rtomb(buf, 0xdca9, &s) == (size_t)-1); + ATF_REQUIRE(errno == EILSEQ); + ATF_REQUIRE((unsigned char)buf[0] == 0xcc); +} + +ATF_TC_WITHOUT_HEAD(c16rtomb_iso_8859_1_test); +ATF_TC_BODY(c16rtomb_iso_8859_1_test, tc) +{ + + require_lc_ctype("en_US.ISO8859-1"); + + /* Unicode character 'Euro sign'. */ + memset(&s, 0, sizeof(s)); + memset(buf, 0xcc, sizeof(buf)); + ATF_REQUIRE(c16rtomb(buf, 0x20ac, &s) == (size_t)-1); + ATF_REQUIRE(errno == EILSEQ); + ATF_REQUIRE((unsigned char)buf[0] == 0xcc); +} + +ATF_TC_WITHOUT_HEAD(c16rtomb_iso_8859_15_test); +ATF_TC_BODY(c16rtomb_iso_8859_15_test, tc) +{ + + require_lc_ctype("en_US.ISO8859-15"); + + /* Unicode character 'Euro sign'. */ + memset(&s, 0, sizeof(s)); + memset(buf, 0xcc, sizeof(buf)); + ATF_REQUIRE(c16rtomb(buf, 0x20ac, &s) == 1); + ATF_REQUIRE((unsigned char)buf[0] == 0xa4 && (unsigned char)buf[1] == 0xcc); +} + +ATF_TC_WITHOUT_HEAD(c16rtomb_utf_8_test); +ATF_TC_BODY(c16rtomb_utf_8_test, tc) +{ + + require_lc_ctype("en_US.UTF-8"); + + /* Unicode character 'Pile of poo'. */ + memset(&s, 0, sizeof(s)); + memset(buf, 0xcc, sizeof(buf)); + ATF_REQUIRE(c16rtomb(buf, 0xd83d, &s) == 0); + ATF_REQUIRE(c16rtomb(buf, 0xdca9, &s) == 4); + ATF_REQUIRE((unsigned char)buf[0] == 0xf0 && (unsigned char)buf[1] == 0x9f && + (unsigned char)buf[2] == 0x92 && (unsigned char)buf[3] == 0xa9 && + (unsigned char)buf[4] == 0xcc); + + /* Invalid code; 'Pile of poo' without the trail surrogate. */ + memset(&s, 0, sizeof(s)); + memset(buf, 0xcc, sizeof(buf)); + ATF_REQUIRE(c16rtomb(buf, 0xd83d, &s) == 0); + ATF_REQUIRE(c16rtomb(buf, L'A', &s) == (size_t)-1); + ATF_REQUIRE(errno == EILSEQ); + ATF_REQUIRE((unsigned char)buf[0] == 0xcc); + + /* Invalid code; 'Pile of poo' without the lead surrogate. */ + memset(&s, 0, sizeof(s)); + memset(buf, 0xcc, sizeof(buf)); + ATF_REQUIRE(c16rtomb(buf, 0xdca9, &s) == (size_t)-1); + ATF_REQUIRE(errno == EILSEQ); + ATF_REQUIRE((unsigned char)buf[0] == 0xcc); +} + +ATF_TP_ADD_TCS(tp) +{ + + ATF_TP_ADD_TC(tp, c16rtomb_c_locale_test); + ATF_TP_ADD_TC(tp, c16rtomb_iso_8859_1_test); + ATF_TP_ADD_TC(tp, c16rtomb_iso_8859_15_test); + ATF_TP_ADD_TC(tp, c16rtomb_utf_8_test); + + return (atf_no_error()); +} diff --git a/lib/libc/tests/locale/iswctype_test.c b/lib/libc/tests/locale/iswctype_test.c new file mode 100644 index 0000000..14e57b4 --- /dev/null +++ b/lib/libc/tests/locale/iswctype_test.c @@ -0,0 +1,122 @@ +/*- + * Copyright (c) 2003 Tim J. Robbins + * 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. + */ + +/* + * Test program for wctype() and iswctype() as specified by + * IEEE Std. 1003.1-2001 and ISO/IEC 9899:1999. + * + * The functions are tested in the "C" and "ja_JP.eucJP" locales. + */ + +#include <sys/cdefs.h> +__FBSDID("$FreeBSD$"); + +#include <sys/param.h> +#include <errno.h> +#include <locale.h> +#include <stdio.h> +#include <string.h> +#include <wchar.h> +#include <wctype.h> + +#include <atf-c.h> + +static void +require_lc_ctype(const char *locale_name) +{ + char *lc_ctype_set; + + lc_ctype_set = setlocale(LC_CTYPE, locale_name); + if (lc_ctype_set == NULL) + atf_tc_fail("setlocale(LC_CTYPE, \"%s\") failed; errno=%d", + locale_name, errno); + + ATF_REQUIRE(strcmp(lc_ctype_set, locale_name) == 0); +} + +static wctype_t t; +static int i, j; +static struct { + const char *name; + int (*func)(wint_t); +} cls[] = { + { "alnum", iswalnum }, + { "alpha", iswalpha }, + { "blank", iswblank }, + { "cntrl", iswcntrl }, + { "digit", iswdigit }, + { "graph", iswgraph }, + { "lower", iswlower }, + { "print", iswprint }, + { "punct", iswpunct }, + { "space", iswspace }, + { "upper", iswupper }, + { "xdigit", iswxdigit } +}; + +ATF_TC_WITHOUT_HEAD(iswctype_c_locale_test); +ATF_TC_BODY(iswctype_c_locale_test, tc) +{ + + require_lc_ctype("C"); + for (i = 0; i < nitems(cls); i++) { + t = wctype(cls[i].name); + ATF_REQUIRE(t != 0); + for (j = 0; j < 256; j++) + ATF_REQUIRE(cls[i].func(j) == iswctype(j, t)); + } + t = wctype("elephant"); + ATF_REQUIRE(t == 0); + for (i = 0; i < 256; i++) + ATF_REQUIRE(iswctype(i, t) == 0); +} + +ATF_TC_WITHOUT_HEAD(iswctype_euc_jp_test); +ATF_TC_BODY(iswctype_euc_jp_test, tc) +{ + + require_lc_ctype("ja_JP.eucJP"); + + for (i = 0; i < nitems(cls); i++) { + t = wctype(cls[i].name); + ATF_REQUIRE(t != 0); + for (j = 0; j < 65536; j++) + ATF_REQUIRE(cls[i].func(j) == iswctype(j, t)); + } + t = wctype("elephant"); + ATF_REQUIRE(t == 0); + for (i = 0; i < 65536; i++) + ATF_REQUIRE(iswctype(i, t) == 0); +} + +ATF_TP_ADD_TCS(tp) +{ + + ATF_TP_ADD_TC(tp, iswctype_c_locale_test); + ATF_TP_ADD_TC(tp, iswctype_euc_jp_test); + + return (atf_no_error()); +} diff --git a/lib/libc/tests/locale/mblen_test.c b/lib/libc/tests/locale/mblen_test.c new file mode 100644 index 0000000..fbb938d --- /dev/null +++ b/lib/libc/tests/locale/mblen_test.c @@ -0,0 +1,116 @@ +/*- + * Copyright (c) 2002-2004 Tim J. Robbins + * 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. + */ + +/* + * Test program for mblen(), as specified by IEEE Std. 1003.1-2001 and + * ISO/IEC 9899:1990. + * + * The function is tested with both the "C" ("POSIX") LC_CTYPE setting and + * "ja_JP.eucJP". Other encodings are not tested. + */ + +#include <sys/cdefs.h> +__FBSDID("$FreeBSD$"); + +#include <limits.h> +#include <locale.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +#include <atf-c.h> + +ATF_TC_WITHOUT_HEAD(mblen_test); +ATF_TC_BODY(mblen_test, tc) +{ + char buf[MB_LEN_MAX + 1]; + + /* + * C/POSIX locale. + */ + + ATF_REQUIRE(MB_CUR_MAX == 1); + + /* No shift states in C locale. */ + ATF_REQUIRE(mblen(NULL, 0) == 0); + + /* Null wide character. */ + memset(buf, 0xcc, sizeof(buf)); + buf[0] = '\0'; + ATF_REQUIRE(mblen(buf, 1) == 0); + + /* Latin letter A. */ + buf[0] = 'A'; + ATF_REQUIRE(mblen(buf, 1) == 1); + + /* Incomplete character sequence. */ + buf[0] = '\0'; + ATF_REQUIRE(mblen(buf, 0) == -1); + ATF_REQUIRE(mblen(NULL, 0) == 0); + + /* + * Japanese (EUC) locale. + */ + + ATF_REQUIRE(strcmp(setlocale(LC_CTYPE, "ja_JP.eucJP"), "ja_JP.eucJP") == 0); + ATF_REQUIRE(MB_CUR_MAX > 1); + + /* No shift states in EUC. */ + ATF_REQUIRE(mblen(NULL, 0) == 0); + + /* Null wide character. */ + memset(buf, 0xcc, sizeof(buf)); + buf[0] = '\0'; + ATF_REQUIRE(mblen(buf, 1) == 0); + + /* Latin letter A. */ + buf[0] = 'A'; + ATF_REQUIRE(mblen(buf, 1) == 1); + + /* Incomplete character sequence. */ + buf[0] = '\0'; + ATF_REQUIRE(mblen(buf, 0) == -1); + ATF_REQUIRE(mblen(NULL, 0) == 0); + + /* Incomplete character sequence (truncated double-byte). */ + memset(buf, 0xcc, sizeof(buf)); + buf[0] = 0xa3; + buf[1] = 0x00; + ATF_REQUIRE(mblen(buf, 1) == -1); + ATF_REQUIRE(mblen(NULL, 0) == 0); + + /* Same as above, but complete. */ + buf[1] = 0xc1; + ATF_REQUIRE(mblen(buf, 2) == 2); +} + +ATF_TP_ADD_TCS(tp) +{ + + ATF_TP_ADD_TC(tp, mblen_test); + + return (atf_no_error()); +} diff --git a/lib/libc/tests/locale/mbrlen_test.c b/lib/libc/tests/locale/mbrlen_test.c new file mode 100644 index 0000000..c2bc548 --- /dev/null +++ b/lib/libc/tests/locale/mbrlen_test.c @@ -0,0 +1,126 @@ +/*- + * Copyright (c) 2002 Tim J. Robbins + * 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. + */ + +/* + * Test program for mbrlen(), as specified by IEEE Std. 1003.1-2001 and + * ISO/IEC 9899:1999. + * + * The function is tested with both the "C" ("POSIX") LC_CTYPE setting and + * "ja_JP.eucJP". Other encodings are not tested. + */ + +#include <sys/cdefs.h> +__FBSDID("$FreeBSD$"); + +#include <errno.h> +#include <limits.h> +#include <locale.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <wchar.h> + +#include <atf-c.h> + +ATF_TC_WITHOUT_HEAD(mbrlen_test); +ATF_TC_BODY(mbrlen_test, tc) +{ + mbstate_t s; + char buf[MB_LEN_MAX + 1]; + + /* C/POSIX locale. */ + ATF_REQUIRE(MB_CUR_MAX == 1); + + /* Null wide character, internal state. */ + memset(buf, 0xcc, sizeof(buf)); + buf[0] = 0; + ATF_REQUIRE(mbrlen(buf, 1, NULL) == 0); + + /* Null wide character. */ + memset(&s, 0, sizeof(s)); + ATF_REQUIRE(mbrlen(buf, 1, &s) == 0); + + /* Latin letter A, internal state. */ + ATF_REQUIRE(mbrlen(NULL, 0, NULL) == 0); + buf[0] = 'A'; + ATF_REQUIRE(mbrlen(buf, 1, NULL) == 1); + + /* Latin letter A. */ + memset(&s, 0, sizeof(s)); + ATF_REQUIRE(mbrlen(buf, 1, &s) == 1); + + /* Incomplete character sequence. */ + memset(&s, 0, sizeof(s)); + ATF_REQUIRE(mbrlen(buf, 0, &s) == (size_t)-2); + + /* Japanese (EUC) locale. */ + + ATF_REQUIRE(strcmp(setlocale(LC_CTYPE, "ja_JP.eucJP"), "ja_JP.eucJP") == 0); + ATF_REQUIRE(MB_CUR_MAX > 1); + + /* Null wide character, internal state. */ + ATF_REQUIRE(mbrlen(NULL, 0, NULL) == 0); + memset(buf, 0xcc, sizeof(buf)); + buf[0] = 0; + ATF_REQUIRE(mbrlen(buf, 1, NULL) == 0); + + /* Null wide character. */ + memset(&s, 0, sizeof(s)); + ATF_REQUIRE(mbrlen(buf, 1, &s) == 0); + + /* Latin letter A, internal state. */ + ATF_REQUIRE(mbrlen(NULL, 0, NULL) == 0); + buf[0] = 'A'; + ATF_REQUIRE(mbrlen(buf, 1, NULL) == 1); + + /* Latin letter A. */ + memset(&s, 0, sizeof(s)); + ATF_REQUIRE(mbrlen(buf, 1, &s) == 1); + + /* Incomplete character sequence (zero length). */ + memset(&s, 0, sizeof(s)); + ATF_REQUIRE(mbrlen(buf, 0, &s) == (size_t)-2); + + /* Incomplete character sequence (truncated double-byte). */ + memset(buf, 0xcc, sizeof(buf)); + buf[0] = 0xa3; + buf[1] = 0x00; + memset(&s, 0, sizeof(s)); + ATF_REQUIRE(mbrlen(buf, 1, &s) == (size_t)-2); + + /* Same as above, but complete. */ + buf[1] = 0xc1; + memset(&s, 0, sizeof(s)); + ATF_REQUIRE(mbrlen(buf, 2, &s) == 2); +} + +ATF_TP_ADD_TCS(tp) +{ + + ATF_TP_ADD_TC(tp, mbrlen_test); + + return (atf_no_error()); +} diff --git a/lib/libc/tests/locale/mbrtoc16_test.c b/lib/libc/tests/locale/mbrtoc16_test.c new file mode 100644 index 0000000..a6289e1 --- /dev/null +++ b/lib/libc/tests/locale/mbrtoc16_test.c @@ -0,0 +1,214 @@ +/*- + * Copyright (c) 2002 Tim J. Robbins + * All rights reserved. + * + * Copyright (c) 2013 Ed Schouten <ed@FreeBSD.org> + * 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. + */ +/* + * Test program for mbrtoc16() as specified by ISO/IEC 9899:2011. + */ + +#include <sys/cdefs.h> +__FBSDID("$FreeBSD$"); + +#include <errno.h> +#include <limits.h> +#include <locale.h> +#include <stdio.h> +#include <string.h> +#include <uchar.h> + +#include <atf-c.h> + +static void +require_lc_ctype(const char *locale_name) +{ + char *lc_ctype_set; + + lc_ctype_set = setlocale(LC_CTYPE, locale_name); + if (lc_ctype_set == NULL) + atf_tc_fail("setlocale(LC_CTYPE, \"%s\") failed; errno=%d", + locale_name, errno); + + ATF_REQUIRE(strcmp(lc_ctype_set, locale_name) == 0); +} + +static mbstate_t s; +static char16_t c16; + +ATF_TC_WITHOUT_HEAD(mbrtoc16_c_locale_test); +ATF_TC_BODY(mbrtoc16_c_locale_test, tc) +{ + + require_lc_ctype("C"); + + /* Null wide character, internal state. */ + ATF_REQUIRE(mbrtoc16(&c16, "", 1, NULL) == 0); + ATF_REQUIRE(c16 == 0); + + /* Null wide character. */ + memset(&s, 0, sizeof(s)); + ATF_REQUIRE(mbrtoc16(&c16, "", 1, &s) == 0); + ATF_REQUIRE(c16 == 0); + + /* Latin letter A, internal state. */ + ATF_REQUIRE(mbrtoc16(NULL, 0, 0, NULL) == 0); + ATF_REQUIRE(mbrtoc16(&c16, "A", 1, NULL) == 1); + ATF_REQUIRE(c16 == L'A'); + + /* Latin letter A. */ + memset(&s, 0, sizeof(s)); + ATF_REQUIRE(mbrtoc16(&c16, "A", 1, &s) == 1); + ATF_REQUIRE(c16 == L'A'); + + /* Incomplete character sequence. */ + c16 = L'z'; + memset(&s, 0, sizeof(s)); + ATF_REQUIRE(mbrtoc16(&c16, "", 0, &s) == (size_t)-2); + ATF_REQUIRE(c16 == L'z'); + + /* Check that mbrtoc16() doesn't access the buffer when n == 0. */ + c16 = L'z'; + memset(&s, 0, sizeof(s)); + ATF_REQUIRE(mbrtoc16(&c16, "", 0, &s) == (size_t)-2); + ATF_REQUIRE(c16 == L'z'); + + /* Check that mbrtoc16() doesn't read ahead too aggressively. */ + memset(&s, 0, sizeof(s)); + ATF_REQUIRE(mbrtoc16(&c16, "AB", 2, &s) == 1); + ATF_REQUIRE(c16 == L'A'); + ATF_REQUIRE(mbrtoc16(&c16, "C", 1, &s) == 1); + ATF_REQUIRE(c16 == L'C'); + +} + +ATF_TC_WITHOUT_HEAD(mbrtoc16_iso_8859_1_test); +ATF_TC_BODY(mbrtoc16_iso_8859_1_test, tc) +{ + + require_lc_ctype("en_US.ISO8859-1"); + + /* Currency sign. */ + memset(&s, 0, sizeof(s)); + ATF_REQUIRE(mbrtoc16(&c16, "\xa4", 1, &s) == 1); + ATF_REQUIRE(c16 == 0xa4); +} + +ATF_TC_WITHOUT_HEAD(mbrtoc16_iso_8859_15_test); +ATF_TC_BODY(mbrtoc16_iso_8859_15_test, tc) +{ + + require_lc_ctype("en_US.ISO8859-15"); + + /* Euro sign. */ + memset(&s, 0, sizeof(s)); + ATF_REQUIRE(mbrtoc16(&c16, "\xa4", 1, &s) == 1); + ATF_REQUIRE(c16 == 0x20ac); +} + +ATF_TC_WITHOUT_HEAD(mbrtoc16_utf_8_test); +ATF_TC_BODY(mbrtoc16_utf_8_test, tc) +{ + + require_lc_ctype("en_US.UTF-8"); + + /* Null wide character, internal state. */ + ATF_REQUIRE(mbrtoc16(NULL, 0, 0, NULL) == 0); + ATF_REQUIRE(mbrtoc16(&c16, "", 1, NULL) == 0); + ATF_REQUIRE(c16 == 0); + + /* Null wide character. */ + memset(&s, 0, sizeof(s)); + ATF_REQUIRE(mbrtoc16(&c16, "", 1, &s) == 0); + ATF_REQUIRE(c16 == 0); + + /* Latin letter A, internal state. */ + ATF_REQUIRE(mbrtoc16(NULL, 0, 0, NULL) == 0); + ATF_REQUIRE(mbrtoc16(&c16, "A", 1, NULL) == 1); + ATF_REQUIRE(c16 == L'A'); + + /* Latin letter A. */ + memset(&s, 0, sizeof(s)); + ATF_REQUIRE(mbrtoc16(&c16, "A", 1, &s) == 1); + ATF_REQUIRE(c16 == L'A'); + + /* Incomplete character sequence (zero length). */ + c16 = L'z'; + memset(&s, 0, sizeof(s)); + ATF_REQUIRE(mbrtoc16(&c16, "", 0, &s) == (size_t)-2); + ATF_REQUIRE(c16 == L'z'); + + /* Incomplete character sequence (truncated double-byte). */ + memset(&s, 0, sizeof(s)); + c16 = 0; + ATF_REQUIRE(mbrtoc16(&c16, "\xc3", 1, &s) == (size_t)-2); + + /* Same as above, but complete. */ + memset(&s, 0, sizeof(s)); + c16 = 0; + ATF_REQUIRE(mbrtoc16(&c16, "\xc3\x84", 2, &s) == 2); + ATF_REQUIRE(c16 == 0xc4); + + /* Test restarting behaviour. */ + memset(&s, 0, sizeof(s)); + c16 = 0; + ATF_REQUIRE(mbrtoc16(&c16, "\xc3", 1, &s) == (size_t)-2); + ATF_REQUIRE(c16 == 0); + ATF_REQUIRE(mbrtoc16(&c16, "\xb7", 1, &s) == 1); + ATF_REQUIRE(c16 == 0xf7); + + /* Surrogate pair. */ + memset(&s, 0, sizeof(s)); + c16 = 0; + ATF_REQUIRE(mbrtoc16(&c16, "\xf0\x9f\x92\xa9", 4, &s) == 4); + ATF_REQUIRE(c16 == 0xd83d); + ATF_REQUIRE(mbrtoc16(&c16, "", 0, &s) == (size_t)-3); + ATF_REQUIRE(c16 == 0xdca9); + + /* Letter e with acute, precomposed. */ + memset(&s, 0, sizeof(s)); + c16 = 0; + ATF_REQUIRE(mbrtoc16(&c16, "\xc3\xa9", 2, &s) == 2); + ATF_REQUIRE(c16 == 0xe9); + + /* Letter e with acute, combined. */ + memset(&s, 0, sizeof(s)); + c16 = 0; + ATF_REQUIRE(mbrtoc16(&c16, "\x65\xcc\x81", 3, &s) == 1); + ATF_REQUIRE(c16 == 0x65); + ATF_REQUIRE(mbrtoc16(&c16, "\xcc\x81", 2, &s) == 2); + ATF_REQUIRE(c16 == 0x301); +} + +ATF_TP_ADD_TCS(tp) +{ + + ATF_TP_ADD_TC(tp, mbrtoc16_c_locale_test); + ATF_TP_ADD_TC(tp, mbrtoc16_iso_8859_1_test); + ATF_TP_ADD_TC(tp, mbrtoc16_iso_8859_15_test); + ATF_TP_ADD_TC(tp, mbrtoc16_utf_8_test); + + return (atf_no_error()); +} diff --git a/lib/libc/tests/locale/mbrtowc_test.c b/lib/libc/tests/locale/mbrtowc_test.c new file mode 100644 index 0000000..37e0bfd --- /dev/null +++ b/lib/libc/tests/locale/mbrtowc_test.c @@ -0,0 +1,165 @@ +/*- + * Copyright (c) 2002 Tim J. Robbins + * 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. + */ + +/* + * Test program for mbrtowc(), as specified by IEEE Std. 1003.1-2001 and + * ISO/IEC 9899:1999. + * + * The function is tested with both the "C" ("POSIX") LC_CTYPE setting and + * "ja_JP.eucJP". Other encodings are not tested. + */ + +#include <sys/cdefs.h> +__FBSDID("$FreeBSD$"); + +#include <errno.h> +#include <limits.h> +#include <locale.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <wchar.h> + +#include <atf-c.h> + +ATF_TC_WITHOUT_HEAD(mbrtowc_test); +ATF_TC_BODY(mbrtowc_test, tc) +{ + mbstate_t s; + wchar_t wc; + char buf[MB_LEN_MAX + 1]; + + /* + * C/POSIX locale. + */ + + ATF_REQUIRE(MB_CUR_MAX == 1); + + /* Null wide character, internal state. */ + memset(buf, 0xcc, sizeof(buf)); + buf[0] = 0; + ATF_REQUIRE(mbrtowc(&wc, buf, 1, NULL) == 0); + ATF_REQUIRE(wc == 0); + + /* Null wide character. */ + memset(&s, 0, sizeof(s)); + ATF_REQUIRE(mbrtowc(&wc, buf, 1, &s) == 0); + ATF_REQUIRE(wc == 0); + + /* Latin letter A, internal state. */ + ATF_REQUIRE(mbrtowc(NULL, 0, 0, NULL) == 0); + buf[0] = 'A'; + ATF_REQUIRE(mbrtowc(&wc, buf, 1, NULL) == 1); + ATF_REQUIRE(wc == L'A'); + + /* Latin letter A. */ + memset(&s, 0, sizeof(s)); + ATF_REQUIRE(mbrtowc(&wc, buf, 1, &s) == 1); + ATF_REQUIRE(wc == L'A'); + + /* Incomplete character sequence. */ + wc = L'z'; + memset(&s, 0, sizeof(s)); + ATF_REQUIRE(mbrtowc(&wc, buf, 0, &s) == (size_t)-2); + ATF_REQUIRE(wc == L'z'); + + /* Check that mbrtowc() doesn't access the buffer when n == 0. */ + wc = L'z'; + memset(&s, 0, sizeof(s)); + buf[0] = '\0'; + ATF_REQUIRE(mbrtowc(&wc, buf, 0, &s) == (size_t)-2); + ATF_REQUIRE(wc == L'z'); + + /* + * Japanese (EUC) locale. + */ + + ATF_REQUIRE(strcmp(setlocale(LC_CTYPE, "ja_JP.eucJP"), "ja_JP.eucJP") == 0); + ATF_REQUIRE(MB_CUR_MAX > 1); + + /* Null wide character, internal state. */ + ATF_REQUIRE(mbrtowc(NULL, 0, 0, NULL) == 0); + memset(buf, 0xcc, sizeof(buf)); + buf[0] = 0; + ATF_REQUIRE(mbrtowc(&wc, buf, 1, NULL) == 0); + ATF_REQUIRE(wc == 0); + + /* Null wide character. */ + memset(&s, 0, sizeof(s)); + ATF_REQUIRE(mbrtowc(&wc, buf, 1, &s) == 0); + ATF_REQUIRE(wc == 0); + + /* Latin letter A, internal state. */ + ATF_REQUIRE(mbrtowc(NULL, 0, 0, NULL) == 0); + buf[0] = 'A'; + ATF_REQUIRE(mbrtowc(&wc, buf, 1, NULL) == 1); + ATF_REQUIRE(wc == L'A'); + + /* Latin letter A. */ + memset(&s, 0, sizeof(s)); + ATF_REQUIRE(mbrtowc(&wc, buf, 1, &s) == 1); + ATF_REQUIRE(wc == L'A'); + + /* Incomplete character sequence (zero length). */ + wc = L'z'; + memset(&s, 0, sizeof(s)); + ATF_REQUIRE(mbrtowc(&wc, buf, 0, &s) == (size_t)-2); + ATF_REQUIRE(wc == L'z'); + + /* Incomplete character sequence (truncated double-byte). */ + memset(buf, 0xcc, sizeof(buf)); + buf[0] = 0xa3; + buf[1] = 0x00; + memset(&s, 0, sizeof(s)); + wc = 0; + ATF_REQUIRE(mbrtowc(&wc, buf, 1, &s) == (size_t)-2); + + /* Same as above, but complete. */ + buf[1] = 0xc1; + memset(&s, 0, sizeof(s)); + wc = 0; + ATF_REQUIRE(mbrtowc(&wc, buf, 2, &s) == 2); + ATF_REQUIRE(wc == 0xa3c1); + + /* Test restarting behaviour. */ + memset(buf, 0xcc, sizeof(buf)); + buf[0] = 0xa3; + memset(&s, 0, sizeof(s)); + wc = 0; + ATF_REQUIRE(mbrtowc(&wc, buf, 1, &s) == (size_t)-2); + ATF_REQUIRE(wc == 0); + buf[0] = 0xc1; + ATF_REQUIRE(mbrtowc(&wc, buf, 1, &s) == 1); + ATF_REQUIRE(wc == 0xa3c1); +} + +ATF_TP_ADD_TCS(tp) +{ + + ATF_TP_ADD_TC(tp, mbrtowc_test); + + return (atf_no_error()); +} diff --git a/lib/libc/tests/locale/mbsnrtowcs_test.c b/lib/libc/tests/locale/mbsnrtowcs_test.c new file mode 100644 index 0000000..4012b7e --- /dev/null +++ b/lib/libc/tests/locale/mbsnrtowcs_test.c @@ -0,0 +1,195 @@ +/*- + * Copyright (c) 2002-2004 Tim J. Robbins + * 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. + */ + +/* + * Test program for mbsnrtowcs(). + * + * The function is tested with both the "C" ("POSIX") LC_CTYPE setting and + * "ja_JP.eucJP". Other encodings are not tested. + */ + +#include <sys/cdefs.h> +__FBSDID("$FreeBSD$"); + +#include <errno.h> +#include <limits.h> +#include <locale.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <wchar.h> + +#include <atf-c.h> + +ATF_TC_WITHOUT_HEAD(mbsnrtowcs_test); +ATF_TC_BODY(mbsnrtowcs_test, tc) +{ + char srcbuf[128]; + wchar_t dstbuf[128]; + char *src; + mbstate_t s; + + /* C/POSIX locale. */ + + /* Simple null terminated string. */ + memset(srcbuf, 0xcc, sizeof(srcbuf)); + strcpy(srcbuf, "hello"); + wmemset(dstbuf, 0xcccc, sizeof(dstbuf) / sizeof(*dstbuf)); + src = srcbuf; + memset(&s, 0, sizeof(s)); + ATF_REQUIRE(mbsnrtowcs(dstbuf, (const char **)&src, 6, sizeof(dstbuf) / + sizeof(*dstbuf), &s) == 5); + ATF_REQUIRE(wcscmp(dstbuf, L"hello") == 0); + ATF_REQUIRE(dstbuf[6] == 0xcccc); + ATF_REQUIRE(src == NULL); + + /* Simple null terminated string, stopping early. */ + memset(srcbuf, 0xcc, sizeof(srcbuf)); + strcpy(srcbuf, "hello"); + wmemset(dstbuf, 0xcccc, sizeof(dstbuf) / sizeof(*dstbuf)); + src = srcbuf; + memset(&s, 0, sizeof(s)); + ATF_REQUIRE(mbsnrtowcs(dstbuf, (const char **)&src, 4, sizeof(dstbuf) / + sizeof(*dstbuf), &s) == 4); + ATF_REQUIRE(wmemcmp(dstbuf, L"hell", 4) == 0); + ATF_REQUIRE(dstbuf[5] == 0xcccc); + ATF_REQUIRE(src == srcbuf + 4); + + /* Not enough space in destination buffer. */ + memset(srcbuf, 0xcc, sizeof(srcbuf)); + strcpy(srcbuf, "hello"); + wmemset(dstbuf, 0xcccc, sizeof(dstbuf) / sizeof(*dstbuf)); + src = srcbuf; + memset(&s, 0, sizeof(s)); + ATF_REQUIRE(mbsnrtowcs(dstbuf, (const char **)&src, 6, 4, &s) == 4); + ATF_REQUIRE(wmemcmp(dstbuf, L"hell", 4) == 0); + ATF_REQUIRE(dstbuf[5] == 0xcccc); + ATF_REQUIRE(src == srcbuf + 4); + + /* Null terminated string, internal dest. buffer */ + memset(srcbuf, 0xcc, sizeof(srcbuf)); + strcpy(srcbuf, "hello"); + src = srcbuf; + memset(&s, 0, sizeof(s)); + ATF_REQUIRE(mbsnrtowcs(NULL, (const char **)&src, 6, 0, &s) == 5); + + /* Null terminated string, internal dest. buffer, stopping early */ + memset(srcbuf, 0xcc, sizeof(srcbuf)); + strcpy(srcbuf, "hello"); + src = srcbuf; + memset(&s, 0, sizeof(s)); + ATF_REQUIRE(mbsnrtowcs(NULL, (const char **)&src, 4, 0, &s) == 4); + + /* Null terminated string, internal state. */ + memset(srcbuf, 0xcc, sizeof(srcbuf)); + strcpy(srcbuf, "hello"); + wmemset(dstbuf, 0xcccc, sizeof(dstbuf) / sizeof(*dstbuf)); + src = srcbuf; + ATF_REQUIRE(mbsnrtowcs(dstbuf, (const char **)&src, 6, sizeof(dstbuf) / + sizeof(*dstbuf), NULL) == 5); + ATF_REQUIRE(wcscmp(dstbuf, L"hello") == 0); + ATF_REQUIRE(dstbuf[6] == 0xcccc); + ATF_REQUIRE(src == NULL); + + /* Null terminated string, internal state, internal dest. buffer. */ + memset(srcbuf, 0xcc, sizeof(srcbuf)); + strcpy(srcbuf, "hello"); + src = srcbuf; + ATF_REQUIRE(mbsnrtowcs(NULL, (const char **)&src, 6, 0, NULL) == 5); + + /* Empty source buffer. */ + memset(srcbuf, 0xcc, sizeof(srcbuf)); + srcbuf[0] = '\0'; + src = srcbuf; + memset(&s, 0, sizeof(s)); + wmemset(dstbuf, 0xcccc, sizeof(dstbuf) / sizeof(*dstbuf)); + ATF_REQUIRE(mbsnrtowcs(dstbuf, (const char **)&src, 1, 1, &s) == 0); + ATF_REQUIRE(dstbuf[0] == 0); + ATF_REQUIRE(dstbuf[1] == 0xcccc); + ATF_REQUIRE(src == NULL); + + /* Zero length destination buffer. */ + memset(srcbuf, 0xcc, sizeof(srcbuf)); + strcpy(srcbuf, "hello"); + src = srcbuf; + memset(&s, 0, sizeof(s)); + wmemset(dstbuf, 0xcccc, sizeof(dstbuf) / sizeof(*dstbuf)); + ATF_REQUIRE(mbsnrtowcs(dstbuf, (const char **)&src, 1, 0, &s) == 0); + ATF_REQUIRE(dstbuf[0] == 0xcccc); + ATF_REQUIRE(src == srcbuf); + + /* Zero length source buffer. */ + memset(srcbuf, 0xcc, sizeof(srcbuf)); + src = srcbuf; + memset(&s, 0, sizeof(s)); + wmemset(dstbuf, 0xcccc, sizeof(dstbuf) / sizeof(*dstbuf)); + ATF_REQUIRE(mbsnrtowcs(dstbuf, (const char **)&src, 0, 1, &s) == 0); + ATF_REQUIRE(dstbuf[0] == 0xcccc); + ATF_REQUIRE(src == srcbuf); + + /* + * Japanese (EUC) locale. + */ + + ATF_REQUIRE(strcmp(setlocale(LC_CTYPE, "ja_JP.eucJP"), "ja_JP.eucJP") == 0); + ATF_REQUIRE(MB_CUR_MAX > 1); + + memset(srcbuf, 0xcc, sizeof(srcbuf)); + strcpy(srcbuf, "\xA3\xC1 B \xA3\xC3"); + src = srcbuf; + memset(&s, 0, sizeof(s)); + wmemset(dstbuf, 0xcccc, sizeof(dstbuf) / sizeof(*dstbuf)); + ATF_REQUIRE(mbsnrtowcs(dstbuf, (const char **)&src, 8, sizeof(dstbuf) / + sizeof(*dstbuf), &s) == 5); + ATF_REQUIRE(dstbuf[0] == 0xA3C1 && dstbuf[1] == 0x20 && dstbuf[2] == 0x42 && + dstbuf[3] == 0x20 && dstbuf[4] == 0xA3C3 && dstbuf[5] == 0); + ATF_REQUIRE(src == NULL); + + /* Partial character. */ + memset(srcbuf, 0xcc, sizeof(srcbuf)); + strcpy(srcbuf, "\xA3\xC1 B \xA3\xC3"); + src = srcbuf; + memset(&s, 0, sizeof(s)); + wmemset(dstbuf, 0xcccc, sizeof(dstbuf) / sizeof(*dstbuf)); + ATF_REQUIRE(mbsnrtowcs(dstbuf, (const char **)&src, 6, sizeof(dstbuf) / + sizeof(*dstbuf), &s) == 4); + ATF_REQUIRE(src == srcbuf + 6); + ATF_REQUIRE(!mbsinit(&s)); + ATF_REQUIRE(mbsnrtowcs(dstbuf, (const char **)&src, 1, sizeof(dstbuf) / + sizeof(*dstbuf), &s) == 1); + ATF_REQUIRE(src == srcbuf + 7); + ATF_REQUIRE(mbsnrtowcs(dstbuf, (const char **)&src, 1, sizeof(dstbuf) / + sizeof(*dstbuf), &s) == 0); + ATF_REQUIRE(src == NULL); +} + +ATF_TP_ADD_TCS(tp) +{ + + ATF_TP_ADD_TC(tp, mbsnrtowcs_test); + + return (atf_no_error()); +} diff --git a/lib/libc/tests/locale/mbsrtowcs_test.c b/lib/libc/tests/locale/mbsrtowcs_test.c new file mode 100644 index 0000000..1b9d5c9 --- /dev/null +++ b/lib/libc/tests/locale/mbsrtowcs_test.c @@ -0,0 +1,153 @@ +/*- + * Copyright (c) 2002 Tim J. Robbins + * 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. + */ + +/* + * Test program for mbsrtowcs(), as specified by IEEE Std. 1003.1-2001 and + * ISO/IEC 9899:1999. + * + * The function is tested with both the "C" ("POSIX") LC_CTYPE setting and + * "ja_JP.eucJP". Other encodings are not tested. + */ + +#include <sys/cdefs.h> +__FBSDID("$FreeBSD$"); + +#include <errno.h> +#include <limits.h> +#include <locale.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <wchar.h> + +#include <atf-c.h> + +ATF_TC_WITHOUT_HEAD(mbsrtowcs_test); +ATF_TC_BODY(mbsrtowcs_test, tc) +{ + char srcbuf[128]; + wchar_t dstbuf[128]; + char *src; + mbstate_t s; + + /* + * C/POSIX locale. + */ + + /* Simple null terminated string. */ + memset(srcbuf, 0xcc, sizeof(srcbuf)); + strcpy(srcbuf, "hello"); + wmemset(dstbuf, 0xcccc, sizeof(dstbuf) / sizeof(*dstbuf)); + src = srcbuf; + memset(&s, 0, sizeof(s)); + ATF_REQUIRE(mbsrtowcs(dstbuf, (const char **)&src, sizeof(dstbuf) / + sizeof(*dstbuf), &s) == 5); + ATF_REQUIRE(wcscmp(dstbuf, L"hello") == 0); + ATF_REQUIRE(dstbuf[6] == 0xcccc); + ATF_REQUIRE(src == NULL); + + /* Not enough space in destination buffer. */ + memset(srcbuf, 0xcc, sizeof(srcbuf)); + strcpy(srcbuf, "hello"); + wmemset(dstbuf, 0xcccc, sizeof(dstbuf) / sizeof(*dstbuf)); + src = srcbuf; + memset(&s, 0, sizeof(s)); + ATF_REQUIRE(mbsrtowcs(dstbuf, (const char **)&src, 4, &s) == 4); + ATF_REQUIRE(wmemcmp(dstbuf, L"hell", 4) == 0); + ATF_REQUIRE(dstbuf[5] == 0xcccc); + ATF_REQUIRE(src == srcbuf + 4); + + /* Null terminated string, internal dest. buffer */ + memset(srcbuf, 0xcc, sizeof(srcbuf)); + strcpy(srcbuf, "hello"); + src = srcbuf; + memset(&s, 0, sizeof(s)); + ATF_REQUIRE(mbsrtowcs(NULL, (const char **)&src, 0, &s) == 5); + + /* Null terminated string, internal state. */ + memset(srcbuf, 0xcc, sizeof(srcbuf)); + strcpy(srcbuf, "hello"); + wmemset(dstbuf, 0xcccc, sizeof(dstbuf) / sizeof(*dstbuf)); + src = srcbuf; + ATF_REQUIRE(mbsrtowcs(dstbuf, (const char **)&src, sizeof(dstbuf) / + sizeof(*dstbuf), NULL) == 5); + ATF_REQUIRE(wcscmp(dstbuf, L"hello") == 0); + ATF_REQUIRE(dstbuf[6] == 0xcccc); + ATF_REQUIRE(src == NULL); + + /* Null terminated string, internal state, internal dest. buffer. */ + memset(srcbuf, 0xcc, sizeof(srcbuf)); + strcpy(srcbuf, "hello"); + src = srcbuf; + ATF_REQUIRE(mbsrtowcs(NULL, (const char **)&src, 0, NULL) == 5); + + /* Empty source buffer. */ + memset(srcbuf, 0xcc, sizeof(srcbuf)); + srcbuf[0] = '\0'; + src = srcbuf; + memset(&s, 0, sizeof(s)); + wmemset(dstbuf, 0xcccc, sizeof(dstbuf) / sizeof(*dstbuf)); + ATF_REQUIRE(mbsrtowcs(dstbuf, (const char **)&src, 1, &s) == 0); + ATF_REQUIRE(dstbuf[0] == 0); + ATF_REQUIRE(dstbuf[1] == 0xcccc); + ATF_REQUIRE(src == NULL); + + /* Zero length destination buffer. */ + memset(srcbuf, 0xcc, sizeof(srcbuf)); + strcpy(srcbuf, "hello"); + src = srcbuf; + memset(&s, 0, sizeof(s)); + wmemset(dstbuf, 0xcccc, sizeof(dstbuf) / sizeof(*dstbuf)); + ATF_REQUIRE(mbsrtowcs(dstbuf, (const char **)&src, 0, &s) == 0); + ATF_REQUIRE(dstbuf[0] == 0xcccc); + ATF_REQUIRE(src == srcbuf); + + /* + * Japanese (EUC) locale. + */ + + ATF_REQUIRE(strcmp(setlocale(LC_CTYPE, "ja_JP.eucJP"), "ja_JP.eucJP") == 0); + ATF_REQUIRE(MB_CUR_MAX > 1); + + memset(srcbuf, 0xcc, sizeof(srcbuf)); + strcpy(srcbuf, "\xA3\xC1 B \xA3\xC3"); + src = srcbuf; + memset(&s, 0, sizeof(s)); + wmemset(dstbuf, 0xcccc, sizeof(dstbuf) / sizeof(*dstbuf)); + ATF_REQUIRE(mbsrtowcs(dstbuf, (const char **)&src, sizeof(dstbuf) / + sizeof(*dstbuf), &s) == 5); + ATF_REQUIRE(dstbuf[0] == 0xA3C1 && dstbuf[1] == 0x20 && dstbuf[2] == 0x42 && + dstbuf[3] == 0x20 && dstbuf[4] == 0xA3C3 && dstbuf[5] == 0); + ATF_REQUIRE(src == NULL); +} + +ATF_TP_ADD_TCS(tp) +{ + + ATF_TP_ADD_TC(tp, mbsrtowcs_test); + + return (atf_no_error()); +} diff --git a/lib/libc/tests/locale/mbstowcs_test.c b/lib/libc/tests/locale/mbstowcs_test.c new file mode 100644 index 0000000..77b0e9e --- /dev/null +++ b/lib/libc/tests/locale/mbstowcs_test.c @@ -0,0 +1,111 @@ +/*- + * Copyright (c) 2002 Tim J. Robbins + * 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. + */ + +/* + * Test program for mbstowcs(), as specified by IEEE Std. 1003.1-2001 and + * ISO/IEC 9899:1999. + * + * The function is tested with both the "C" ("POSIX") LC_CTYPE setting and + * "ja_JP.eucJP". Other encodings are not tested. + */ + +#include <sys/cdefs.h> +__FBSDID("$FreeBSD$"); + +#include <errno.h> +#include <limits.h> +#include <locale.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <wchar.h> + +#include <atf-c.h> + +ATF_TC_WITHOUT_HEAD(mbstowcs_test); +ATF_TC_BODY(mbstowcs_test, tc) +{ + char srcbuf[128]; + wchar_t dstbuf[128]; + + /* C/POSIX locale. */ + + /* Simple null terminated string. */ + memset(srcbuf, 0xcc, sizeof(srcbuf)); + strcpy(srcbuf, "hello"); + wmemset(dstbuf, 0xcccc, sizeof(dstbuf) / sizeof(*dstbuf)); + ATF_REQUIRE(mbstowcs(dstbuf, srcbuf, sizeof(dstbuf) / sizeof(*dstbuf)) == 5); + ATF_REQUIRE(wcscmp(dstbuf, L"hello") == 0); + ATF_REQUIRE(dstbuf[6] == 0xcccc); + + /* Not enough space in destination buffer. */ + memset(srcbuf, 0xcc, sizeof(srcbuf)); + strcpy(srcbuf, "hello"); + wmemset(dstbuf, 0xcccc, sizeof(dstbuf) / sizeof(*dstbuf)); + ATF_REQUIRE(mbstowcs(dstbuf, srcbuf, 4) == 4); + ATF_REQUIRE(wmemcmp(dstbuf, L"hell", 4) == 0); + ATF_REQUIRE(dstbuf[5] == 0xcccc); + + /* Null terminated string, internal dest. buffer (XSI extension) */ + memset(srcbuf, 0xcc, sizeof(srcbuf)); + strcpy(srcbuf, "hello"); + ATF_REQUIRE(mbstowcs(NULL, srcbuf, 0) == 5); + + /* Empty source buffer. */ + memset(srcbuf, 0xcc, sizeof(srcbuf)); + srcbuf[0] = '\0'; + wmemset(dstbuf, 0xcccc, sizeof(dstbuf) / sizeof(*dstbuf)); + ATF_REQUIRE(mbstowcs(dstbuf, srcbuf, 1) == 0); + ATF_REQUIRE(dstbuf[0] == 0); + ATF_REQUIRE(dstbuf[1] == 0xcccc); + + /* Zero length destination buffer. */ + memset(srcbuf, 0xcc, sizeof(srcbuf)); + strcpy(srcbuf, "hello"); + wmemset(dstbuf, 0xcccc, sizeof(dstbuf) / sizeof(*dstbuf)); + ATF_REQUIRE(mbstowcs(dstbuf, srcbuf, 0) == 0); + ATF_REQUIRE(dstbuf[0] == 0xcccc); + + /* Japanese (EUC) locale. */ + + ATF_REQUIRE(strcmp(setlocale(LC_CTYPE, "ja_JP.eucJP"), "ja_JP.eucJP") == 0); + ATF_REQUIRE(MB_CUR_MAX > 1); + + memset(srcbuf, 0xcc, sizeof(srcbuf)); + strcpy(srcbuf, "\xA3\xC1 B \xA3\xC3"); + wmemset(dstbuf, 0xcccc, sizeof(dstbuf) / sizeof(*dstbuf)); + ATF_REQUIRE(mbstowcs(dstbuf, srcbuf, sizeof(dstbuf) / sizeof(*dstbuf)) == 5); + ATF_REQUIRE(dstbuf[0] == 0xA3C1 && dstbuf[1] == 0x20 && dstbuf[2] == 0x42 && + dstbuf[3] == 0x20 && dstbuf[4] == 0xA3C3 && dstbuf[5] == 0); +} + +ATF_TP_ADD_TCS(tp) +{ + + ATF_TP_ADD_TC(tp, mbstowcs_test); + + return (atf_no_error()); +} diff --git a/lib/libc/tests/locale/mbtowc_test.c b/lib/libc/tests/locale/mbtowc_test.c new file mode 100644 index 0000000..7c7f80e --- /dev/null +++ b/lib/libc/tests/locale/mbtowc_test.c @@ -0,0 +1,122 @@ +/*- + * Copyright (c) 2002-2004 Tim J. Robbins + * 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. + */ + +/* + * Test program for mbtowc(), as specified by IEEE Std. 1003.1-2001 and + * ISO/IEC 9899:1990. + * + * The function is tested with both the "C" ("POSIX") LC_CTYPE setting and + * "ja_JP.eucJP". Other encodings are not tested. + */ + +#include <sys/cdefs.h> +__FBSDID("$FreeBSD$"); + +#include <limits.h> +#include <locale.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +#include <atf-c.h> + +ATF_TC_WITHOUT_HEAD(mbtowc_test); +ATF_TC_BODY(mbtowc_test, tc) +{ + char buf[MB_LEN_MAX + 1]; + wchar_t wc; + + /* C/POSIX locale. */ + + ATF_REQUIRE(MB_CUR_MAX == 1); + + /* No shift states in C locale. */ + ATF_REQUIRE(mbtowc(NULL, NULL, 0) == 0); + + /* Null wide character. */ + wc = 0xcccc; + memset(buf, 0, sizeof(buf)); + ATF_REQUIRE(mbtowc(&wc, buf, 1) == 0); + ATF_REQUIRE(wc == 0); + + /* Latin letter A. */ + buf[0] = 'A'; + ATF_REQUIRE(mbtowc(&wc, buf, 1) == 1); + ATF_REQUIRE(wc == L'A'); + + /* Incomplete character sequence. */ + wc = L'z'; + buf[0] = '\0'; + ATF_REQUIRE(mbtowc(&wc, buf, 0) == -1); + ATF_REQUIRE(wc == L'z'); + ATF_REQUIRE(mbtowc(NULL, NULL, 0) == 0); + + /* Japanese (EUC) locale. */ + + ATF_REQUIRE(strcmp(setlocale(LC_CTYPE, "ja_JP.eucJP"), "ja_JP.eucJP") == 0); + ATF_REQUIRE(MB_CUR_MAX > 1); + + /* Null wide character */ + memset(buf, 0xcc, sizeof(buf)); + buf[0] = 0; + wc = 0xcccc; + ATF_REQUIRE(mbtowc(&wc, buf, 1) == 0); + ATF_REQUIRE(wc == 0); + + /* Latin letter A. */ + buf[0] = 'A'; + ATF_REQUIRE(mbtowc(&wc, buf, 1) == 1); + ATF_REQUIRE(wc == L'A'); + + /* Incomplete character sequence (zero length). */ + wc = L'z'; + buf[0] = '\0'; + ATF_REQUIRE(mbtowc(&wc, buf, 0) == -1); + ATF_REQUIRE(wc == L'z'); + ATF_REQUIRE(mbtowc(NULL, NULL, 0) == 0); + + /* Incomplete character sequence (truncated double-byte). */ + memset(buf, 0xcc, sizeof(buf)); + buf[0] = 0xa3; + buf[1] = 0x00; + wc = L'z'; + ATF_REQUIRE(mbtowc(&wc, buf, 1) == -1); + ATF_REQUIRE(wc == L'z'); + ATF_REQUIRE(mbtowc(NULL, NULL, 0) == 0); + + /* Same as above, but complete. */ + buf[1] = 0xc1; + ATF_REQUIRE(mbtowc(&wc, buf, 2) == 2); + ATF_REQUIRE(wc == 0xa3c1); +} + +ATF_TP_ADD_TCS(tp) +{ + + ATF_TP_ADD_TC(tp, mbtowc_test); + + return (atf_no_error()); +} diff --git a/lib/libc/tests/locale/towctrans_test.c b/lib/libc/tests/locale/towctrans_test.c new file mode 100644 index 0000000..bb9d97c --- /dev/null +++ b/lib/libc/tests/locale/towctrans_test.c @@ -0,0 +1,90 @@ +/*- + * Copyright (c) 2003 Tim J. Robbins + * 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. + */ + +/* + * Test program for wctrans() and towctrans() as specified by + * IEEE Std. 1003.1-2001 and ISO/IEC 9899:1999. + * + * The functions are tested in the "C" and "ja_JP.eucJP" locales. + */ + +#include <sys/cdefs.h> +__FBSDID("$FreeBSD$"); + +#include <locale.h> +#include <stdio.h> +#include <string.h> +#include <wchar.h> +#include <wctype.h> + +#include <atf-c.h> + +ATF_TC_WITHOUT_HEAD(towctrans_test); +ATF_TC_BODY(towctrans_test, tc) +{ + wctype_t t; + int i, j; + struct { + const char *name; + wint_t (*func)(wint_t); + } tran[] = { + { "tolower", towlower }, + { "toupper", towupper }, + }; + + /* C/POSIX locale. */ + for (i = 0; i < sizeof(tran) / sizeof(*tran); i++) { + t = wctrans(tran[i].name); + ATF_REQUIRE(t != 0); + for (j = 0; j < 256; j++) + ATF_REQUIRE(tran[i].func(j) == towctrans(j, t)); + } + t = wctrans("elephant"); + ATF_REQUIRE(t == 0); + for (i = 0; i < 256; i++) + ATF_REQUIRE(towctrans(i, t) == i); + + /* Japanese (EUC) locale. */ + ATF_REQUIRE(strcmp(setlocale(LC_CTYPE, "ja_JP.eucJP"), "ja_JP.eucJP") == 0); + for (i = 0; i < sizeof(tran) / sizeof(*tran); i++) { + t = wctrans(tran[i].name); + ATF_REQUIRE(t != 0); + for (j = 0; j < 65536; j++) + ATF_REQUIRE(tran[i].func(j) == towctrans(j, t)); + } + t = wctrans("elephant"); + ATF_REQUIRE(t == 0); + for (i = 0; i < 65536; i++) + ATF_REQUIRE(towctrans(i, t) == i); +} + +ATF_TP_ADD_TCS(tp) +{ + + ATF_TP_ADD_TC(tp, towctrans_test); + + return (atf_no_error()); +} diff --git a/lib/libc/tests/locale/wcrtomb_test.c b/lib/libc/tests/locale/wcrtomb_test.c new file mode 100644 index 0000000..09199ba --- /dev/null +++ b/lib/libc/tests/locale/wcrtomb_test.c @@ -0,0 +1,135 @@ +/*- + * Copyright (c) 2002 Tim J. Robbins + * 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. + */ + +/* + * Test program for wcrtomb(), as specified by IEEE Std. 1003.1-2001 and + * ISO/IEC 9899:1999. + * + * The function is tested with both the "C" ("POSIX") LC_CTYPE setting and + * "ja_JP.eucJP". Other encodings are not tested. + */ + +#include <sys/cdefs.h> +__FBSDID("$FreeBSD$"); + +#include <errno.h> +#include <limits.h> +#include <locale.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <wchar.h> + +#include <atf-c.h> + +ATF_TC_WITHOUT_HEAD(wcrtomb_test); +ATF_TC_BODY(wcrtomb_test, tc) +{ + mbstate_t s; + size_t len; + char buf[MB_LEN_MAX + 1]; + + /* C/POSIX locale. */ + + ATF_REQUIRE(MB_CUR_MAX == 1); + + /* + * If the buffer argument is NULL, wc is implicitly L'\0', + * wcrtomb() resets its internal state. + */ + ATF_REQUIRE(wcrtomb(NULL, L'\0', NULL) == 1); + ATF_REQUIRE(wcrtomb(NULL, UCHAR_MAX + 1, NULL) == 1); + + /* Null wide character. */ + memset(&s, 0, sizeof(s)); + memset(buf, 0xcc, sizeof(buf)); + len = wcrtomb(buf, L'\0', &s); + ATF_REQUIRE(len == 1); + ATF_REQUIRE((unsigned char)buf[0] == 0 && (unsigned char)buf[1] == 0xcc); + + /* Latin letter A, internal state. */ + ATF_REQUIRE(wcrtomb(NULL, L'\0', NULL) == 1); + ATF_REQUIRE(wcrtomb(NULL, L'A', NULL) == 1); + + /* Latin letter A. */ + memset(&s, 0, sizeof(s)); + memset(buf, 0xcc, sizeof(buf)); + len = wcrtomb(buf, L'A', &s); + ATF_REQUIRE(len == 1); + ATF_REQUIRE((unsigned char)buf[0] == 'A' && (unsigned char)buf[1] == 0xcc); + + /* Invalid code. */ + ATF_REQUIRE(wcrtomb(buf, UCHAR_MAX + 1, NULL) == (size_t)-1); + ATF_REQUIRE(errno == EILSEQ); + + /* + * Japanese (EUC) locale. + */ + + ATF_REQUIRE(strcmp(setlocale(LC_CTYPE, "ja_JP.eucJP"), "ja_JP.eucJP") == 0); + ATF_REQUIRE(MB_CUR_MAX == 3); + + /* + * If the buffer argument is NULL, wc is implicitly L'\0', + * wcrtomb() resets its internal state. + */ + ATF_REQUIRE(wcrtomb(NULL, L'\0', NULL) == 1); + + /* Null wide character. */ + memset(&s, 0, sizeof(s)); + memset(buf, 0xcc, sizeof(buf)); + len = wcrtomb(buf, L'\0', &s); + ATF_REQUIRE(len == 1); + ATF_REQUIRE((unsigned char)buf[0] == 0 && (unsigned char)buf[1] == 0xcc); + + /* Latin letter A, internal state. */ + ATF_REQUIRE(wcrtomb(NULL, L'\0', NULL) == 1); + ATF_REQUIRE(wcrtomb(NULL, L'A', NULL) == 1); + + /* Latin letter A. */ + memset(&s, 0, sizeof(s)); + memset(buf, 0xcc, sizeof(buf)); + len = wcrtomb(buf, L'A', &s); + ATF_REQUIRE(len == 1); + ATF_REQUIRE((unsigned char)buf[0] == 'A' && (unsigned char)buf[1] == 0xcc); + + /* Full width letter A. */ + memset(&s, 0, sizeof(s)); + memset(buf, 0xcc, sizeof(buf)); + len = wcrtomb(buf, 0xa3c1, &s); + ATF_REQUIRE(len == 2); + ATF_REQUIRE((unsigned char)buf[0] == 0xa3 && + (unsigned char)buf[1] == 0xc1 && + (unsigned char)buf[2] == 0xcc); +} + +ATF_TP_ADD_TCS(tp) +{ + + ATF_TP_ADD_TC(tp, wcrtomb_test); + + return (atf_no_error()); +} diff --git a/lib/libc/tests/locale/wcsnrtombs_test.c b/lib/libc/tests/locale/wcsnrtombs_test.c new file mode 100644 index 0000000..2e330a1 --- /dev/null +++ b/lib/libc/tests/locale/wcsnrtombs_test.c @@ -0,0 +1,195 @@ +/*- + * Copyright (c) 2002-2004 Tim J. Robbins + * 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. + */ + +/* + * Test program for wcsnrtombs(). + * + * The function is tested with both the "C" ("POSIX") LC_CTYPE setting and + * "ja_JP.eucJP". Other encodings are not tested. + */ + +#include <sys/cdefs.h> +__FBSDID("$FreeBSD$"); + +#include <errno.h> +#include <limits.h> +#include <locale.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <wchar.h> + +#include <atf-c.h> + +ATF_TC_WITHOUT_HEAD(wcsnrtombs_test); +ATF_TC_BODY(wcsnrtombs_test, tc) +{ + wchar_t srcbuf[128]; + char dstbuf[128]; + wchar_t *src; + mbstate_t s; + + /* C/POSIX locale. */ + + /* Simple null terminated string. */ + wmemset(srcbuf, 0xcc, sizeof(srcbuf) / sizeof(*srcbuf)); + wcscpy(srcbuf, L"hello"); + memset(dstbuf, 0xcc, sizeof(dstbuf)); + src = srcbuf; + memset(&s, 0, sizeof(s)); + ATF_REQUIRE(wcsnrtombs(dstbuf, (const wchar_t **)&src, 6, sizeof(dstbuf), + &s) == 5); + ATF_REQUIRE(strcmp(dstbuf, "hello") == 0); + ATF_REQUIRE((unsigned char)dstbuf[6] == 0xcc); + ATF_REQUIRE(src == NULL); + + /* Simple null terminated string, stopping early. */ + wmemset(srcbuf, 0xcc, sizeof(srcbuf) / sizeof(*srcbuf)); + wcscpy(srcbuf, L"hello"); + memset(dstbuf, 0xcc, sizeof(dstbuf)); + src = srcbuf; + memset(&s, 0, sizeof(s)); + ATF_REQUIRE(wcsnrtombs(dstbuf, (const wchar_t **)&src, 4, sizeof(dstbuf), + &s) == 4); + ATF_REQUIRE(memcmp(dstbuf, "hell", 4) == 0); + ATF_REQUIRE((unsigned char)dstbuf[5] == 0xcc); + ATF_REQUIRE(src == srcbuf + 4); + + /* Not enough space in destination buffer. */ + wmemset(srcbuf, 0xcc, sizeof(srcbuf) / sizeof(*srcbuf)); + wcscpy(srcbuf, L"hello"); + memset(dstbuf, 0xcc, sizeof(dstbuf)); + src = srcbuf; + memset(&s, 0, sizeof(s)); + ATF_REQUIRE(wcsnrtombs(dstbuf, (const wchar_t **)&src, 6, 4, + &s) == 4); + ATF_REQUIRE(memcmp(dstbuf, "hell", 4) == 0); + ATF_REQUIRE((unsigned char)dstbuf[5] == 0xcc); + ATF_REQUIRE(src == srcbuf + 4); + + /* Null terminated string, internal dest. buffer */ + wmemset(srcbuf, 0xcc, sizeof(srcbuf) / sizeof(*srcbuf)); + wcscpy(srcbuf, L"hello"); + src = srcbuf; + memset(&s, 0, sizeof(s)); + ATF_REQUIRE(wcsnrtombs(NULL, (const wchar_t **)&src, 6, sizeof(dstbuf), + &s) == 5); + + /* Null terminated string, internal dest. buffer, stopping early. */ + wmemset(srcbuf, 0xcc, sizeof(srcbuf) / sizeof(*srcbuf)); + wcscpy(srcbuf, L"hello"); + src = srcbuf; + memset(&s, 0, sizeof(s)); + ATF_REQUIRE(wcsnrtombs(NULL, (const wchar_t **)&src, 4, sizeof(dstbuf), + &s) == 4); + + /* Null terminated string, internal state. */ + wmemset(srcbuf, 0xcc, sizeof(srcbuf) / sizeof(*srcbuf)); + wcscpy(srcbuf, L"hello"); + memset(dstbuf, 0xcc, sizeof(dstbuf)); + src = srcbuf; + ATF_REQUIRE(wcsnrtombs(dstbuf, (const wchar_t **)&src, 6, sizeof(dstbuf), + NULL) == 5); + ATF_REQUIRE(strcmp(dstbuf, "hello") == 0); + ATF_REQUIRE((unsigned char)dstbuf[6] == 0xcc); + ATF_REQUIRE(src == NULL); + + /* Null terminated string, internal state, internal dest. buffer. */ + wmemset(srcbuf, 0xcc, sizeof(srcbuf) / sizeof(*srcbuf)); + wcscpy(srcbuf, L"hello"); + src = srcbuf; + ATF_REQUIRE(wcsnrtombs(NULL, (const wchar_t **)&src, 6, 0, NULL) == 5); + + /* Empty source buffer. */ + wmemset(srcbuf, 0xcc, sizeof(srcbuf) / sizeof(*srcbuf)); + srcbuf[0] = L'\0'; + memset(dstbuf, 0xcc, sizeof(dstbuf)); + src = srcbuf; + memset(&s, 0, sizeof(s)); + ATF_REQUIRE(wcsnrtombs(dstbuf, (const wchar_t **)&src, 1, sizeof(dstbuf), + &s) == 0); + ATF_REQUIRE(dstbuf[0] == L'\0'); + + /* Zero length destination buffer. */ + wmemset(srcbuf, 0xcc, sizeof(srcbuf) / sizeof(*srcbuf)); + wcscpy(srcbuf, L"hello"); + memset(dstbuf, 0xcc, sizeof(dstbuf)); + src = srcbuf; + memset(&s, 0, sizeof(s)); + ATF_REQUIRE(wcsnrtombs(dstbuf, (const wchar_t **)&src, 6, 0, &s) == 0); + ATF_REQUIRE((unsigned char)dstbuf[0] == 0xcc); + + /* Zero length source buffer. */ + wmemset(srcbuf, 0xcc, sizeof(srcbuf) / sizeof(*srcbuf)); + memset(dstbuf, 0xcc, sizeof(dstbuf)); + src = srcbuf; + memset(&s, 0, sizeof(s)); + ATF_REQUIRE(wcsnrtombs(dstbuf, (const wchar_t **)&src, 0, sizeof(dstbuf), + &s) == 0); + ATF_REQUIRE((unsigned char)dstbuf[0] == 0xcc); + ATF_REQUIRE(src == srcbuf); + + /* + * Japanese (EUC) locale. + */ + + ATF_REQUIRE(strcmp(setlocale(LC_CTYPE, "ja_JP.eucJP"), "ja_JP.eucJP") == 0); + ATF_REQUIRE(MB_CUR_MAX > 1); + + wmemset(srcbuf, 0xcc, sizeof(srcbuf) / sizeof(*srcbuf)); + srcbuf[0] = 0xA3C1; + srcbuf[1] = 0x0020; + srcbuf[2] = 0x0042; + srcbuf[3] = 0x0020; + srcbuf[4] = 0xA3C3; + srcbuf[5] = 0x0000; + memset(dstbuf, 0xcc, sizeof(dstbuf)); + src = srcbuf; + memset(&s, 0, sizeof(s)); + ATF_REQUIRE(wcsnrtombs(dstbuf, (const wchar_t **)&src, 6, sizeof(dstbuf), + &s) == 7); + ATF_REQUIRE(strcmp(dstbuf, "\xA3\xC1 B \xA3\xC3") == 0); + ATF_REQUIRE((unsigned char)dstbuf[8] == 0xcc); + ATF_REQUIRE(src == NULL); + + /* Stopping early. */ + memset(dstbuf, 0xcc, sizeof(dstbuf)); + src = srcbuf; + memset(&s, 0, sizeof(s)); + ATF_REQUIRE(wcsnrtombs(dstbuf, (const wchar_t **)&src, 6, 6, + &s) == 5); + ATF_REQUIRE(memcmp(dstbuf, "\xA3\xC1 B ", 5) == 0); + ATF_REQUIRE((unsigned char)dstbuf[5] == 0xcc); + ATF_REQUIRE(src == srcbuf + 4); +} + +ATF_TP_ADD_TCS(tp) +{ + + ATF_TP_ADD_TC(tp, wcsnrtombs_test); + + return (atf_no_error()); +} diff --git a/lib/libc/tests/locale/wcsrtombs_test.c b/lib/libc/tests/locale/wcsrtombs_test.c new file mode 100644 index 0000000..4c3455a8 --- /dev/null +++ b/lib/libc/tests/locale/wcsrtombs_test.c @@ -0,0 +1,156 @@ +/*- + * Copyright (c) 2002 Tim J. Robbins + * 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. + */ + +/* + * Test program for wcsrtombs(), as specified by IEEE Std. 1003.1-2001 and + * ISO/IEC 9899:1999. + * + * The function is tested with both the "C" ("POSIX") LC_CTYPE setting and + * "ja_JP.eucJP". Other encodings are not tested. + */ + +#include <sys/cdefs.h> +__FBSDID("$FreeBSD$"); + +#include <errno.h> +#include <limits.h> +#include <locale.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <wchar.h> + +#include <atf-c.h> + +ATF_TC_WITHOUT_HEAD(wcsrtombs_test); +ATF_TC_BODY(wcsrtombs_test, tc) +{ + wchar_t srcbuf[128]; + char dstbuf[128]; + wchar_t *src; + mbstate_t s; + + /* C/POSIX locale. */ + + /* Simple null terminated string. */ + wmemset(srcbuf, 0xcc, sizeof(srcbuf) / sizeof(*srcbuf)); + wcscpy(srcbuf, L"hello"); + memset(dstbuf, 0xcc, sizeof(dstbuf)); + src = srcbuf; + memset(&s, 0, sizeof(s)); + ATF_REQUIRE(wcsrtombs(dstbuf, (const wchar_t **)&src, sizeof(dstbuf), + &s) == 5); + ATF_REQUIRE(strcmp(dstbuf, "hello") == 0); + ATF_REQUIRE((unsigned char)dstbuf[6] == 0xcc); + ATF_REQUIRE(src == NULL); + + /* Not enough space in destination buffer. */ + wmemset(srcbuf, 0xcc, sizeof(srcbuf) / sizeof(*srcbuf)); + wcscpy(srcbuf, L"hello"); + memset(dstbuf, 0xcc, sizeof(dstbuf)); + src = srcbuf; + memset(&s, 0, sizeof(s)); + ATF_REQUIRE(wcsrtombs(dstbuf, (const wchar_t **)&src, 4, + &s) == 4); + ATF_REQUIRE(memcmp(dstbuf, "hell", 4) == 0); + ATF_REQUIRE((unsigned char)dstbuf[5] == 0xcc); + ATF_REQUIRE(src == srcbuf + 4); + + /* Null terminated string, internal dest. buffer */ + wmemset(srcbuf, 0xcc, sizeof(srcbuf) / sizeof(*srcbuf)); + wcscpy(srcbuf, L"hello"); + src = srcbuf; + memset(&s, 0, sizeof(s)); + ATF_REQUIRE(wcsrtombs(NULL, (const wchar_t **)&src, sizeof(dstbuf), + &s) == 5); + + /* Null terminated string, internal state. */ + wmemset(srcbuf, 0xcc, sizeof(srcbuf) / sizeof(*srcbuf)); + wcscpy(srcbuf, L"hello"); + memset(dstbuf, 0xcc, sizeof(dstbuf)); + src = srcbuf; + ATF_REQUIRE(wcsrtombs(dstbuf, (const wchar_t **)&src, sizeof(dstbuf), + NULL) == 5); + ATF_REQUIRE(strcmp(dstbuf, "hello") == 0); + ATF_REQUIRE((unsigned char)dstbuf[6] == 0xcc); + ATF_REQUIRE(src == NULL); + + /* Null terminated string, internal state, internal dest. buffer. */ + wmemset(srcbuf, 0xcc, sizeof(srcbuf) / sizeof(*srcbuf)); + wcscpy(srcbuf, L"hello"); + src = srcbuf; + ATF_REQUIRE(wcsrtombs(NULL, (const wchar_t **)&src, 0, NULL) == 5); + + /* Empty source buffer. */ + wmemset(srcbuf, 0xcc, sizeof(srcbuf) / sizeof(*srcbuf)); + srcbuf[0] = L'\0'; + memset(dstbuf, 0xcc, sizeof(dstbuf)); + src = srcbuf; + memset(&s, 0, sizeof(s)); + ATF_REQUIRE(wcsrtombs(dstbuf, (const wchar_t **)&src, sizeof(dstbuf), + &s) == 0); + ATF_REQUIRE(dstbuf[0] == L'\0'); + + /* Zero length destination buffer. */ + wmemset(srcbuf, 0xcc, sizeof(srcbuf) / sizeof(*srcbuf)); + wcscpy(srcbuf, L"hello"); + memset(dstbuf, 0xcc, sizeof(dstbuf)); + src = srcbuf; + memset(&s, 0, sizeof(s)); + ATF_REQUIRE(wcsrtombs(dstbuf, (const wchar_t **)&src, 0, &s) == 0); + ATF_REQUIRE((unsigned char)dstbuf[0] == 0xcc); + + /* + * Japanese (EUC) locale. + */ + + ATF_REQUIRE(strcmp(setlocale(LC_CTYPE, "ja_JP.eucJP"), "ja_JP.eucJP") == 0); + ATF_REQUIRE(MB_CUR_MAX > 1); + + wmemset(srcbuf, 0xcc, sizeof(srcbuf) / sizeof(*srcbuf)); + srcbuf[0] = 0xA3C1; + srcbuf[1] = 0x0020; + srcbuf[2] = 0x0042; + srcbuf[3] = 0x0020; + srcbuf[4] = 0xA3C3; + srcbuf[5] = 0x0000; + memset(dstbuf, 0xcc, sizeof(dstbuf)); + src = srcbuf; + memset(&s, 0, sizeof(s)); + ATF_REQUIRE(wcsrtombs(dstbuf, (const wchar_t **)&src, sizeof(dstbuf), + &s) == 7); + ATF_REQUIRE(strcmp(dstbuf, "\xA3\xC1 B \xA3\xC3") == 0); + ATF_REQUIRE((unsigned char)dstbuf[8] == 0xcc); + ATF_REQUIRE(src == NULL); +} + +ATF_TP_ADD_TCS(tp) +{ + + ATF_TP_ADD_TC(tp, wcsrtombs_test); + + return (atf_no_error()); +} diff --git a/lib/libc/tests/locale/wcstombs_test.c b/lib/libc/tests/locale/wcstombs_test.c new file mode 100644 index 0000000..f3fcd81 --- /dev/null +++ b/lib/libc/tests/locale/wcstombs_test.c @@ -0,0 +1,130 @@ +/*- + * Copyright (c) 2002 Tim J. Robbins + * 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. + */ + +/* + * Test program for wcstombs(), as specified by IEEE Std. 1003.1-2001 and + * ISO/IEC 9899:1999. + * + * The function is tested with both the "C" ("POSIX") LC_CTYPE setting and + * "ja_JP.eucJP". Other encodings are not tested. + */ + +#include <sys/cdefs.h> +__FBSDID("$FreeBSD$"); + +#include <errno.h> +#include <limits.h> +#include <locale.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <wchar.h> + +#include <atf-c.h> + +ATF_TC_WITHOUT_HEAD(wcstombs_test); +ATF_TC_BODY(wcstombs_test, tc) +{ + wchar_t srcbuf[128]; + char dstbuf[128]; + + /* C/POSIX locale. */ + + /* Simple null terminated string. */ + wmemset(srcbuf, 0xcc, sizeof(srcbuf) / sizeof(*srcbuf)); + wcscpy(srcbuf, L"hello"); + memset(dstbuf, 0xcc, sizeof(dstbuf)); + ATF_REQUIRE(wcstombs(dstbuf, srcbuf, sizeof(dstbuf)) == 5); + ATF_REQUIRE(strcmp(dstbuf, "hello") == 0); + ATF_REQUIRE((unsigned char)dstbuf[6] == 0xcc); + + /* Not enough space in destination buffer. */ + wmemset(srcbuf, 0xcc, sizeof(srcbuf) / sizeof(*srcbuf)); + wcscpy(srcbuf, L"hello"); + memset(dstbuf, 0xcc, sizeof(dstbuf)); + ATF_REQUIRE(wcstombs(dstbuf, srcbuf, 4) == 4); + ATF_REQUIRE(memcmp(dstbuf, "hell", 4) == 0); + ATF_REQUIRE((unsigned char)dstbuf[5] == 0xcc); + + /* Null terminated string, internal dest. buffer */ + wmemset(srcbuf, 0xcc, sizeof(srcbuf) / sizeof(*srcbuf)); + wcscpy(srcbuf, L"hello"); + ATF_REQUIRE(wcstombs(NULL, srcbuf, sizeof(dstbuf)) == 5); + + /* Null terminated string, internal state. */ + wmemset(srcbuf, 0xcc, sizeof(srcbuf) / sizeof(*srcbuf)); + wcscpy(srcbuf, L"hello"); + memset(dstbuf, 0xcc, sizeof(dstbuf)); + ATF_REQUIRE(wcstombs(dstbuf, srcbuf, sizeof(dstbuf)) == 5); + ATF_REQUIRE(strcmp(dstbuf, "hello") == 0); + ATF_REQUIRE((unsigned char)dstbuf[6] == 0xcc); + + /* Null terminated string, internal state, internal dest. buffer. */ + wmemset(srcbuf, 0xcc, sizeof(srcbuf) / sizeof(*srcbuf)); + wcscpy(srcbuf, L"hello"); + ATF_REQUIRE(wcstombs(NULL, srcbuf, 0) == 5); + + /* Empty source buffer. */ + wmemset(srcbuf, 0xcc, sizeof(srcbuf) / sizeof(*srcbuf)); + srcbuf[0] = L'\0'; + memset(dstbuf, 0xcc, sizeof(dstbuf)); + ATF_REQUIRE(wcstombs(dstbuf, srcbuf, sizeof(dstbuf)) == 0); + ATF_REQUIRE(dstbuf[0] == L'\0'); + + /* Zero length destination buffer. */ + wmemset(srcbuf, 0xcc, sizeof(srcbuf) / sizeof(*srcbuf)); + wcscpy(srcbuf, L"hello"); + memset(dstbuf, 0xcc, sizeof(dstbuf)); + ATF_REQUIRE(wcstombs(dstbuf, srcbuf, 0) == 0); + ATF_REQUIRE((unsigned char)dstbuf[0] == 0xcc); + + /* + * Japanese (EUC) locale. + */ + + ATF_REQUIRE(strcmp(setlocale(LC_CTYPE, "ja_JP.eucJP"), "ja_JP.eucJP") == 0); + ATF_REQUIRE(MB_CUR_MAX > 1); + + wmemset(srcbuf, 0xcc, sizeof(srcbuf) / sizeof(*srcbuf)); + srcbuf[0] = 0xA3C1; + srcbuf[1] = 0x0020; + srcbuf[2] = 0x0042; + srcbuf[3] = 0x0020; + srcbuf[4] = 0xA3C3; + srcbuf[5] = 0x0000; + memset(dstbuf, 0xcc, sizeof(dstbuf)); + ATF_REQUIRE(wcstombs(dstbuf, srcbuf, sizeof(dstbuf)) == 7); + ATF_REQUIRE(strcmp(dstbuf, "\xA3\xC1 B \xA3\xC3") == 0); + ATF_REQUIRE((unsigned char)dstbuf[8] == 0xcc); +} + +ATF_TP_ADD_TCS(tp) +{ + + ATF_TP_ADD_TC(tp, wcstombs_test); + + return (atf_no_error()); +} diff --git a/lib/libc/tests/locale/wctomb_test.c b/lib/libc/tests/locale/wctomb_test.c new file mode 100644 index 0000000..255cda4 --- /dev/null +++ b/lib/libc/tests/locale/wctomb_test.c @@ -0,0 +1,113 @@ +/*- + * Copyright (c) 2002-2004 Tim J. Robbins + * 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. + */ + +/* + * Test program for wctomb(), as specified by IEEE Std. 1003.1-2001 and + * ISO/IEC 9899:1999. + * + * The function is tested with both the "C" ("POSIX") LC_CTYPE setting and + * "ja_JP.eucJP". Other encodings are not tested. + */ + +#include <sys/cdefs.h> +__FBSDID("$FreeBSD$"); + +#include <errno.h> +#include <limits.h> +#include <locale.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +#include <atf-c.h> + +ATF_TC_WITHOUT_HEAD(wctomb_test); +ATF_TC_BODY(wctomb_test, tc) +{ + size_t len; + char buf[MB_LEN_MAX + 1]; + + /* C/POSIX locale. */ + + ATF_REQUIRE(MB_CUR_MAX == 1); + + /* No shift states in C locale. */ + ATF_REQUIRE(wctomb(NULL, L'\0') == 0); + + /* Null wide character. */ + memset(buf, 0xcc, sizeof(buf)); + len = wctomb(buf, L'\0'); + ATF_REQUIRE(len == 1); + ATF_REQUIRE((unsigned char)buf[0] == 0 && (unsigned char)buf[1] == 0xcc); + + /* Latin letter A. */ + memset(buf, 0xcc, sizeof(buf)); + len = wctomb(buf, L'A'); + ATF_REQUIRE(len == 1); + ATF_REQUIRE((unsigned char)buf[0] == 'A' && (unsigned char)buf[1] == 0xcc); + + /* Invalid code. */ + ATF_REQUIRE(wctomb(buf, UCHAR_MAX + 1) == -1); + ATF_REQUIRE(wctomb(NULL, 0) == 0); + + /* + * Japanese (EUC) locale. + */ + + ATF_REQUIRE(strcmp(setlocale(LC_CTYPE, "ja_JP.eucJP"), "ja_JP.eucJP") == 0); + ATF_REQUIRE(MB_CUR_MAX == 3); + + /* No shift states in EUC encoding. */ + ATF_REQUIRE(wctomb(NULL, L'\0') == 0); + + /* Null wide character. */ + memset(buf, 0xcc, sizeof(buf)); + len = wctomb(buf, L'\0'); + ATF_REQUIRE(len == 1); + ATF_REQUIRE((unsigned char)buf[0] == 0 && (unsigned char)buf[1] == 0xcc); + + /* Latin letter A. */ + memset(buf, 0xcc, sizeof(buf)); + len = wctomb(buf, L'A'); + ATF_REQUIRE(len == 1); + ATF_REQUIRE((unsigned char)buf[0] == 'A' && (unsigned char)buf[1] == 0xcc); + + /* Full width letter A. */ + memset(buf, 0xcc, sizeof(buf)); + len = wctomb(buf, 0xa3c1); + ATF_REQUIRE(len == 2); + ATF_REQUIRE((unsigned char)buf[0] == 0xa3 && + (unsigned char)buf[1] == 0xc1 && + (unsigned char)buf[2] == 0xcc); +} + +ATF_TP_ADD_TCS(tp) +{ + + ATF_TP_ADD_TC(tp, wctomb_test); + + return (atf_no_error()); +} diff --git a/lib/libc/tests/net/Makefile b/lib/libc/tests/net/Makefile index 5a0d775..8a4e932 100644 --- a/lib/libc/tests/net/Makefile +++ b/lib/libc/tests/net/Makefile @@ -1,22 +1,23 @@ # $FreeBSD$ -.include <bsd.own.mk> +ATF_TESTS_C+= ether_test +ATF_TESTS_C+= eui64_aton_test +ATF_TESTS_C+= eui64_ntoa_test -BINDIR= ${TESTSDIR} +CFLAGS+= -I${.CURDIR} -NETBSD_ATF_TESTS_C= getprotoent_test +NETBSD_ATF_TESTS_C+= getprotoent_test NETBSD_ATF_TESTS_C+= ether_aton_test -SRCS.t_ether_aton= aton_ether_subr.c t_ether_aton.c - -aton_ether_subr.c: gen_ether_subr ${.CURDIR:H:H:H:H}/sys/net/if_ethersubr.c - ${HOST_SH} ${.ALLSRC} ${.TARGET} +SRCS.ether_aton_test= aton_ether_subr.c t_ether_aton.c # TODO: hostent_test NETBSD_ATF_TESTS_SH= nsdispatch_test NETBSD_ATF_TESTS_SH+= protoent_test NETBSD_ATF_TESTS_SH+= servent_test +BINDIR= ${TESTSDIR} + PROGS= h_nsd_recurse PROGS+= h_protoent PROGS+= h_servent @@ -26,12 +27,14 @@ DPADD.h_nsd_recurse+= ${LIBPTHREAD} LDADD.h_nsd_recurse+= -lpthread CLEANFILES+= aton_ether_subr.c +aton_ether_subr.c: gen_ether_subr ${SRCTOP}/sys/net/if_ethersubr.c + ${HOST_SH} ${.ALLSRC} ${.TARGET} .include "../Makefile.netbsd-tests" # TODO: the testcases needs to be ported to FreeBSD #TESTS_SUBDIRS= getaddrinfo -FILES= hosts +FILES+= hosts FILES+= resolv.conf .include <bsd.test.mk> diff --git a/lib/libc/tests/net/ether_test.c b/lib/libc/tests/net/ether_test.c new file mode 100644 index 0000000..fa8e484 --- /dev/null +++ b/lib/libc/tests/net/ether_test.c @@ -0,0 +1,192 @@ +/*- + * Copyright (c) 2007 Robert N. M. Watson + * 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$ + */ + +#include <sys/types.h> + +#include <net/ethernet.h> + +#include <errno.h> +#include <stdio.h> +#include <string.h> + +#include <atf-c.h> + +static const char *ether_line_string = "01:23:45:67:89:ab ether_line_hostname"; +static const char *ether_line_hostname = "ether_line_hostname"; +static const struct ether_addr ether_line_addr = { + { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab } +}; + +ATF_TC_WITHOUT_HEAD(ether_line); +ATF_TC_BODY(ether_line, tc) +{ + struct ether_addr e; + char hostname[256]; + + ATF_REQUIRE_MSG(ether_line(ether_line_string, &e, hostname) == 0, + "ether_line failed; errno=%d", errno); + ATF_REQUIRE_MSG(bcmp(&e, ðer_line_addr, ETHER_ADDR_LEN) == 0, + "bad address"); + ATF_REQUIRE_MSG(strcmp(hostname, ether_line_hostname) == 0, + "bad hostname"); +} + +static const char *ether_line_bad_1_string = "x"; + +ATF_TC_WITHOUT_HEAD(ether_line_bad_1); +ATF_TC_BODY(ether_line_bad_1, tc) +{ + struct ether_addr e; + char hostname[256]; + + ATF_REQUIRE_MSG(ether_line(ether_line_bad_1_string, &e, hostname) != 0, + "ether_line succeeded unexpectedly; errno=%d", errno); +} + +static const char *ether_line_bad_2_string = "x x"; + +ATF_TC_WITHOUT_HEAD(ether_line_bad_2); +ATF_TC_BODY(ether_line_bad_2, tc) +{ + struct ether_addr e; + char hostname[256]; + + ATF_REQUIRE_MSG(ether_line(ether_line_bad_2_string, &e, hostname) != 0, + "ether_line succeeded unexpectedly; errno=%d", errno); +} + +static const char *ether_aton_string = "01:23:45:67:89:ab"; +static const struct ether_addr ether_aton_addr = { + { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab } +}; + +ATF_TC_WITHOUT_HEAD(ether_aton_r); +ATF_TC_BODY(ether_aton_r, tc) +{ + struct ether_addr e, *ep; + + ep = ether_aton_r(ether_aton_string, &e); + + ATF_REQUIRE_MSG(ep != NULL, "ether_aton_r failed; errno=%d", errno); + ATF_REQUIRE_MSG(ep == &e, + "ether_aton_r returned different pointers; %p != %p", ep, &e); +} + +static const char *ether_aton_bad_string = "x"; + +ATF_TC_WITHOUT_HEAD(ether_aton_r_bad); +ATF_TC_BODY(ether_aton_r_bad, tc) +{ + struct ether_addr e, *ep; + + ep = ether_aton_r(ether_aton_bad_string, &e); + ATF_REQUIRE_MSG(ep == NULL, "ether_aton_r succeeded unexpectedly"); +} + +ATF_TC_WITHOUT_HEAD(ether_aton); +ATF_TC_BODY(ether_aton, tc) +{ + struct ether_addr *ep; + + ep = ether_aton(ether_aton_string); + ATF_REQUIRE_MSG(ep != NULL, "ether_aton failed"); + ATF_REQUIRE_MSG(bcmp(ep, ðer_aton_addr, ETHER_ADDR_LEN) == 0, + "bad address"); +} + +ATF_TC_WITHOUT_HEAD(ether_aton_bad); +ATF_TC_BODY(ether_aton_bad, tc) +{ + struct ether_addr *ep; + + ep = ether_aton(ether_aton_bad_string); + ATF_REQUIRE_MSG(ep == NULL, "ether_aton succeeded unexpectedly"); +} + +static const char *ether_ntoa_string = "01:23:45:67:89:ab"; +static const struct ether_addr ether_ntoa_addr = { + { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab } +}; + +ATF_TC_WITHOUT_HEAD(ether_ntoa_r); +ATF_TC_BODY(ether_ntoa_r, tc) +{ + char buf[256], *cp; + + cp = ether_ntoa_r(ðer_ntoa_addr, buf); + ATF_REQUIRE_MSG(cp != NULL, "ether_ntoa_r failed"); + ATF_REQUIRE_MSG(cp == buf, + "ether_ntoa_r returned a different pointer; %p != %p", cp, buf); + ATF_REQUIRE_MSG(strcmp(cp, ether_ntoa_string) == 0, + "strings did not match (`%s` != `%s`)", cp, ether_ntoa_string); +} + +ATF_TC_WITHOUT_HEAD(ether_ntoa); +ATF_TC_BODY(ether_ntoa, tc) +{ + char *cp; + + cp = ether_ntoa(ðer_ntoa_addr); + ATF_REQUIRE_MSG(cp != NULL, "ether_ntoa failed"); + ATF_REQUIRE_MSG(strcmp(cp, ether_ntoa_string) == 0, + "strings did not match (`%s` != `%s`)", cp, ether_ntoa_string); +} + +#if 0 +ATF_TC_WITHOUT_HEAD(ether_ntohost); +ATF_TC_BODY(ether_ntohost, tc) +{ + +} + +ATF_TC_WITHOUT_HEAD(ether_hostton); +ATF_TC_BODY(ether_hostton, tc) +{ + +} +#endif + +ATF_TP_ADD_TCS(tp) +{ + + ATF_TP_ADD_TC(tp, ether_line); + ATF_TP_ADD_TC(tp, ether_line_bad_1); + ATF_TP_ADD_TC(tp, ether_line_bad_2); + ATF_TP_ADD_TC(tp, ether_aton_r); + ATF_TP_ADD_TC(tp, ether_aton_r_bad); + ATF_TP_ADD_TC(tp, ether_aton); + ATF_TP_ADD_TC(tp, ether_aton_bad); + ATF_TP_ADD_TC(tp, ether_ntoa_r); + ATF_TP_ADD_TC(tp, ether_ntoa); +#if 0 + ATF_TP_ADD_TC(tp, ether_ntohost); + ATF_TP_ADD_TC(tp, ether_hostton); +#endif + + return (atf_no_error()); +} diff --git a/lib/libc/tests/net/eui64_aton_test.c b/lib/libc/tests/net/eui64_aton_test.c new file mode 100644 index 0000000..7b97d7f --- /dev/null +++ b/lib/libc/tests/net/eui64_aton_test.c @@ -0,0 +1,104 @@ +/* + * Copyright 2004 The Aerospace Corporation. 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. + * 3. The name of The Aerospace Corporation may not be used to endorse or + * promote products derived from this software. + * + * THIS SOFTWARE IS PROVIDED BY THE AEROSPACE CORPORATION "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 AEROSPACE CORPORATION 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$ + */ + +#include <sys/types.h> +#include <sys/eui64.h> +#include <locale.h> +#include <stdio.h> +#include <string.h> + +#include <atf-c.h> + +#include "test-eui64.h" + +static void +test_str(const char *str, const struct eui64 *eui) +{ + struct eui64 e; + char buf[EUI64_SIZ]; + int rc; + + ATF_REQUIRE_MSG(eui64_aton(str, &e) == 0, "eui64_aton failed"); + rc = memcmp(&e, eui, sizeof(e)); + if (rc != 0) { + eui64_ntoa(&e, buf, sizeof(buf)); + atf_tc_fail( + "eui64_aton(\"%s\", ..) failed; memcmp returned %d. " + "String obtained form eui64_ntoa was: `%s`", + str, rc, buf); + } +} + +ATF_TC_WITHOUT_HEAD(id_ascii); +ATF_TC_BODY(id_ascii, tc) +{ + + test_str(test_eui64_id_ascii, &test_eui64_id); +} + +ATF_TC_WITHOUT_HEAD(id_colon_ascii); +ATF_TC_BODY(id_colon_ascii, tc) +{ + + test_str(test_eui64_id_colon_ascii, &test_eui64_id); +} + +ATF_TC_WITHOUT_HEAD(mac_ascii); +ATF_TC_BODY(mac_ascii, tc) +{ + + test_str(test_eui64_mac_ascii, &test_eui64_eui48); +} + +ATF_TC_WITHOUT_HEAD(mac_colon_ascii); +ATF_TC_BODY(mac_colon_ascii, tc) +{ + + test_str(test_eui64_mac_colon_ascii, &test_eui64_eui48); +} + +ATF_TC_WITHOUT_HEAD(hex_ascii); +ATF_TC_BODY(hex_ascii, tc) +{ + + test_str(test_eui64_hex_ascii, &test_eui64_id); +} + +ATF_TP_ADD_TCS(tp) +{ + + ATF_TP_ADD_TC(tp, id_ascii); + ATF_TP_ADD_TC(tp, id_colon_ascii); + ATF_TP_ADD_TC(tp, mac_ascii); + ATF_TP_ADD_TC(tp, mac_colon_ascii); + ATF_TP_ADD_TC(tp, hex_ascii); + + return (atf_no_error()); +} diff --git a/lib/libc/tests/net/eui64_ntoa_test.c b/lib/libc/tests/net/eui64_ntoa_test.c new file mode 100644 index 0000000..4158e7a --- /dev/null +++ b/lib/libc/tests/net/eui64_ntoa_test.c @@ -0,0 +1,64 @@ +/* + * Copyright 2004 The Aerospace Corporation. 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. + * 3. The name of The Aerospace Corporation may not be used to endorse or + * promote products derived from this software. + * + * THIS SOFTWARE IS PROVIDED BY THE AEROSPACE CORPORATION "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 AEROSPACE CORPORATION 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$ + */ + +#include <sys/types.h> +#include <sys/eui64.h> +#include <stdio.h> +#include <string.h> + +#include <atf-c.h> + +#include "test-eui64.h" + +static void +test_str(const char *str, const struct eui64 *eui) +{ + char a[EUI64_SIZ]; + + ATF_REQUIRE_MSG(eui64_ntoa(&test_eui64_id, a, sizeof(a)) == 0, + "eui64_ntoa failed"); + ATF_REQUIRE_MSG(strcmp(a, test_eui64_id_ascii) == 0, + "the strings mismatched: `%s` != `%s`", a, test_eui64_id_ascii); +} + +ATF_TC_WITHOUT_HEAD(id_ascii); +ATF_TC_BODY(id_ascii, tc) +{ + + test_str(test_eui64_id_ascii, &test_eui64_id); +} + +ATF_TP_ADD_TCS(tp) +{ + + ATF_TP_ADD_TC(tp, id_ascii); + + return (atf_no_error()); +} diff --git a/lib/libc/tests/net/test-eui64.h b/lib/libc/tests/net/test-eui64.h new file mode 100644 index 0000000..ea82a10 --- /dev/null +++ b/lib/libc/tests/net/test-eui64.h @@ -0,0 +1,55 @@ +/* + * Copyright 2004 The Aerospace Corporation. 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. + * 3. The name of The Aerospace Corporation may not be used to endorse or + * promote products derived from this software. + * + * THIS SOFTWARE IS PROVIDED BY THE AEROSPACE CORPORATION "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 AEROSPACE CORPORATION 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 _TEST_EUI64_H +#define _TEST_EUI64_H + +struct eui64 test_eui64_id = {{0x00,0x11,0x22,0x33,0x44,0x55,0x66,0x77}}; +struct eui64 test_eui64_eui48 = {{0x00,0x11,0x22,0xFF,0xFE,0x33,0x44,0x55}}; +struct eui64 test_eui64_mac48 = {{0x00,0x11,0x22,0xFF,0xFF,0x33,0x44,0x55}}; + +#define test_eui64_id_ascii "00-11-22-33-44-55-66-77" +#define test_eui64_id_colon_ascii "00:11:22:33:44:55:66:77" +#define test_eui64_hex_ascii "0x0011223344556677" +#define test_eui64_eui48_ascii "00-11-22-ff-fe-33-44-55" +#define test_eui64_mac48_ascii "00-11-22-ff-fe-33-44-55" +#define test_eui64_mac_ascii "00-11-22-33-44-55" +#define test_eui64_mac_colon_ascii "00:11:22:33:44:55" +#define test_eui64_id_host "id" +#define test_eui64_eui48_host "eui-48" +#define test_eui64_mac48_host "mac-48" + +#define test_eui64_line_id "00-11-22-33-44-55-66-77 id" +#define test_eui64_line_id_colon "00:11:22:33:44:55:66:77 id" +#define test_eui64_line_eui48 "00-11-22-FF-fe-33-44-55 eui-48" +#define test_eui64_line_mac48 "00-11-22-FF-ff-33-44-55 mac-48" +#define test_eui64_line_eui48_6byte "00-11-22-33-44-55 eui-48" +#define test_eui64_line_eui48_6byte_c "00:11:22:33:44:55 eui-48" + +#endif /* !_TEST_EUI64_H */ diff --git a/lib/libc/tests/setjmp/Makefile b/lib/libc/tests/setjmp/Makefile index 0ca2577..ac962c2 100644 --- a/lib/libc/tests/setjmp/Makefile +++ b/lib/libc/tests/setjmp/Makefile @@ -1,10 +1,10 @@ # $FreeBSD$ -NETBSD_ATF_TESTS_C= t_setjmp -NETBSD_ATF_TESTS_C+= t_threadjmp +NETBSD_ATF_TESTS_C= setjmp_test +NETBSD_ATF_TESTS_C+= threadjmp_test -DPADD.t_threadjmp+= ${LIBPTHREAD} -LDADD.t_threadjmp+= -lpthread +DPADD.threadjmp_test+= ${LIBPTHREAD} +LDADD.threadjmp_test+= -lpthread WARNS?= 4 diff --git a/lib/libc/tests/ssp/Makefile b/lib/libc/tests/ssp/Makefile index ec7a82a..dff1578 100644 --- a/lib/libc/tests/ssp/Makefile +++ b/lib/libc/tests/ssp/Makefile @@ -26,9 +26,19 @@ PROGS+= h_memmove PROGS+= h_memset # This testcase doesn't run properly when not compiled with -fsantize=bounds # with clang, which is currently contingent on a compiler_rt update -.if ${COMPILER_TYPE} == "clang" && ${COMPILER_VERSION} < 30500 +# +# XXX: the h_raw/h_read testcases don't cause a SIGABRT with in-tree gcc right +# now on amd64 when it trips the stack bounds specified in t_ssp.sh . This +# probably needs to be fixed as it's currently hardcoded. +# +# sanitizer is not tested or supported for ARM right now. sbruno +.if ${MACHINE_CPUARCH} == "i386" || ${MACHINE_CPUARCH} == "amd64" +.if ${COMPILER_TYPE} == "clang" +.if ${COMPILER_VERSION} < 30500 || 30700 <= ${COMPILER_VERSION} PROGS+= h_raw .endif +.endif +.endif PROGS+= h_read PROGS+= h_readlink PROGS+= h_snprintf diff --git a/lib/libc/tests/stdio/Makefile b/lib/libc/tests/stdio/Makefile index f2d686b..7896422 100644 --- a/lib/libc/tests/stdio/Makefile +++ b/lib/libc/tests/stdio/Makefile @@ -1,6 +1,22 @@ # $FreeBSD$ -ATF_TESTS_C= fmemopen2_test +.include <bsd.own.mk> + +ATF_TESTS_C+= fdopen_test +ATF_TESTS_C+= fmemopen2_test +ATF_TESTS_C+= fopen2_test +ATF_TESTS_C+= freopen_test +ATF_TESTS_C+= getdelim_test +ATF_TESTS_C+= mkostemp_test +ATF_TESTS_C+= open_memstream_test +ATF_TESTS_C+= open_wmemstream_test +ATF_TESTS_C+= perror_test +ATF_TESTS_C+= print_positional_test +ATF_TESTS_C+= printbasic_test +ATF_TESTS_C+= printfloat_test +ATF_TESTS_C+= scanfloat_test + +SRCS.fopen2_test= fopen_test.c NETBSD_ATF_TESTS_C= clearerr_test NETBSD_ATF_TESTS_C+= fflush_test @@ -12,6 +28,18 @@ NETBSD_ATF_TESTS_C+= popen_test NETBSD_ATF_TESTS_C+= printf_test NETBSD_ATF_TESTS_C+= scanf_test +DPADD.printfloat_test+= ${LIBM} +LDADD.printfloat_test+= -lm + +DPADD.scanfloat_test+= ${LIBM} +LDADD.scanfloat_test+= -lm + +.if ${COMPILER_TYPE} == "gcc" +# 90: use of assignment suppression and length modifier together in scanf format +PROG_OVERRIDE_VARS+= NO_WFORMAT +NO_WFORMAT.scanfloat_test= +.endif + .include "../Makefile.netbsd-tests" .include <bsd.test.mk> diff --git a/lib/libc/tests/stdio/fdopen_test.c b/lib/libc/tests/stdio/fdopen_test.c new file mode 100644 index 0000000..060635a --- /dev/null +++ b/lib/libc/tests/stdio/fdopen_test.c @@ -0,0 +1,225 @@ +/*- + * Copyright (c) 2014 Jilles Tjoelker + * 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 <sys/cdefs.h> +__FBSDID("$FreeBSD$"); + +#include <errno.h> +#include <fcntl.h> +#include <paths.h> +#include <stdbool.h> +#include <stdio.h> +#include <string.h> +#include <unistd.h> + +#include <atf-c.h> + +static void +runtest(const char *fname, int intmode, const char *strmode, bool success) +{ + FILE *fp; + int fd; + + fd = open(fname, intmode); + ATF_REQUIRE_MSG(fd != -1, + "open(\"%s\", %#x) failed; errno=%d", fname, intmode, errno); + + fp = fdopen(fd, strmode); + if (fp == NULL) { + close(fd); + ATF_REQUIRE_MSG(success == false, + "fdopen(open(\"%s\", %#x), \"%s\") succeeded unexpectedly", + fname, intmode, strmode); + return; + } + ATF_REQUIRE_MSG(success == true, + "fdopen(open(\"%s\", %#x), \"%s\") failed; errno=%d", + fname, intmode, strmode, errno); + fclose(fp); +} + +ATF_TC_WITHOUT_HEAD(null__O_RDONLY__r_test); +ATF_TC_BODY(null__O_RDONLY__r_test, tc) +{ + + runtest(_PATH_DEVNULL, O_RDONLY, "r", true); +} + +ATF_TC_WITHOUT_HEAD(null__O_WRONLY__r_test); +ATF_TC_BODY(null__O_WRONLY__r_test, tc) +{ + + runtest(_PATH_DEVNULL, O_WRONLY, "r", false); +} + +ATF_TC_WITHOUT_HEAD(null__O_RDWR__r_test); +ATF_TC_BODY(null__O_RDWR__r_test, tc) +{ + + runtest(_PATH_DEVNULL, O_RDWR, "r", true); +} + +ATF_TC_WITHOUT_HEAD(null__O_RDONLY__w_test); +ATF_TC_BODY(null__O_RDONLY__w_test, tc) +{ + + runtest(_PATH_DEVNULL, O_RDONLY, "w", false); +} + +ATF_TC_WITHOUT_HEAD(null__O_WRONLY__w_test); +ATF_TC_BODY(null__O_WRONLY__w_test, tc) +{ + + runtest(_PATH_DEVNULL, O_WRONLY, "w", true); +} + +ATF_TC_WITHOUT_HEAD(null__O_RDWR__w_test); +ATF_TC_BODY(null__O_RDWR__w_test, tc) +{ + + runtest(_PATH_DEVNULL, O_RDWR, "w", true); +} + +ATF_TC_WITHOUT_HEAD(null__O_RDONLY__a_test); +ATF_TC_BODY(null__O_RDONLY__a_test, tc) +{ + + runtest(_PATH_DEVNULL, O_RDONLY, "a", false); +} + +ATF_TC_WITHOUT_HEAD(null__O_WRONLY__a_test); +ATF_TC_BODY(null__O_WRONLY__a_test, tc) +{ + + runtest(_PATH_DEVNULL, O_WRONLY, "a", true); +} + +ATF_TC_WITHOUT_HEAD(null__O_RDWR__test); +ATF_TC_BODY(null__O_RDWR__test, tc) +{ + + runtest(_PATH_DEVNULL, O_RDWR, "a", true); +} + +ATF_TC_WITHOUT_HEAD(null__O_RDONLY__r_append); +ATF_TC_BODY(null__O_RDONLY__r_append, tc) +{ + + runtest(_PATH_DEVNULL, O_RDONLY, "r+", false); +} + +ATF_TC_WITHOUT_HEAD(null__O_WRONLY__r_append); +ATF_TC_BODY(null__O_WRONLY__r_append, tc) +{ + + runtest(_PATH_DEVNULL, O_WRONLY, "r+", false); +} + +ATF_TC_WITHOUT_HEAD(null__O_RDWR__r_append); +ATF_TC_BODY(null__O_RDWR__r_append, tc) +{ + + runtest(_PATH_DEVNULL, O_RDWR, "r+", true); +} + +ATF_TC_WITHOUT_HEAD(null__O_RDONLY__w_append); +ATF_TC_BODY(null__O_RDONLY__w_append, tc) +{ + + runtest(_PATH_DEVNULL, O_RDONLY, "w+", false); +} + +ATF_TC_WITHOUT_HEAD(null__O_WRONLY__w_append); +ATF_TC_BODY(null__O_WRONLY__w_append, tc) +{ + + runtest(_PATH_DEVNULL, O_WRONLY, "w+", false); +} + +ATF_TC_WITHOUT_HEAD(null__O_RDWR__w_append); +ATF_TC_BODY(null__O_RDWR__w_append, tc) +{ + + runtest(_PATH_DEVNULL, O_RDWR, "w+", true); +} + +ATF_TC_WITHOUT_HEAD(sh__O_EXEC__r); +ATF_TC_BODY(sh__O_EXEC__r, tc) +{ + + runtest("/bin/sh", O_EXEC, "r", false); +} + +ATF_TC_WITHOUT_HEAD(sh__O_EXEC__w); +ATF_TC_BODY(sh__O_EXEC__w, tc) +{ + + runtest("/bin/sh", O_EXEC, "w", false); +} + +ATF_TC_WITHOUT_HEAD(sh__O_EXEC__r_append); +ATF_TC_BODY(sh__O_EXEC__r_append, tc) +{ + + runtest("/bin/sh", O_EXEC, "r+", false); +} + +ATF_TC_WITHOUT_HEAD(sh__O_EXEC__w_append); +ATF_TC_BODY(sh__O_EXEC__w_append, tc) +{ + + runtest("/bin/sh", O_EXEC, "w+", false); +} + +ATF_TP_ADD_TCS(tp) +{ + + ATF_TP_ADD_TC(tp, null__O_RDONLY__r_test); + ATF_TP_ADD_TC(tp, null__O_WRONLY__r_test); + ATF_TP_ADD_TC(tp, null__O_RDWR__r_test); + ATF_TP_ADD_TC(tp, null__O_RDONLY__w_test); + ATF_TP_ADD_TC(tp, null__O_WRONLY__w_test); + ATF_TP_ADD_TC(tp, null__O_RDWR__w_test); + ATF_TP_ADD_TC(tp, null__O_RDONLY__a_test); + ATF_TP_ADD_TC(tp, null__O_WRONLY__a_test); + ATF_TP_ADD_TC(tp, null__O_RDWR__test); + ATF_TP_ADD_TC(tp, null__O_RDONLY__r_append); + ATF_TP_ADD_TC(tp, null__O_WRONLY__r_append); + ATF_TP_ADD_TC(tp, null__O_RDWR__r_append); + ATF_TP_ADD_TC(tp, null__O_RDONLY__w_append); + ATF_TP_ADD_TC(tp, null__O_WRONLY__w_append); + ATF_TP_ADD_TC(tp, null__O_RDWR__w_append); + ATF_TP_ADD_TC(tp, sh__O_EXEC__r); + ATF_TP_ADD_TC(tp, sh__O_EXEC__w); + ATF_TP_ADD_TC(tp, sh__O_EXEC__r_append); + ATF_TP_ADD_TC(tp, sh__O_EXEC__w_append); + + return (atf_no_error()); +} + +/* + vim:ts=8:cin:sw=8 + */ diff --git a/lib/libc/tests/stdio/fmemopen2_test.c b/lib/libc/tests/stdio/fmemopen2_test.c index 9555173..c3aa6c5 100644 --- a/lib/libc/tests/stdio/fmemopen2_test.c +++ b/lib/libc/tests/stdio/fmemopen2_test.c @@ -35,15 +35,13 @@ __FBSDID("$FreeBSD$"); #include <stdio.h> #include <string.h> #include <strings.h> + #include <atf-c.h> ATF_TC_WITHOUT_HEAD(test_preexisting); ATF_TC_BODY(test_preexisting, tc) { - /* - * Use a pre-existing buffer. - */ - + /* Use a pre-existing buffer. */ char buf[512]; char buf2[512]; char str[] = "Test writing some stuff"; @@ -74,7 +72,7 @@ ATF_TC_BODY(test_preexisting, tc) nofr = fread(buf2, 1, sizeof(buf2), fp); ATF_REQUIRE(nofr == sizeof(buf2)); - /* + /* * Since a write on a FILE * retrieved by fmemopen * will add a '\0' (if there's space), we can check * the strings for equality. @@ -106,14 +104,10 @@ ATF_TC_BODY(test_preexisting, tc) ATF_TC_WITHOUT_HEAD(test_autoalloc); ATF_TC_BODY(test_autoalloc, tc) { - /* - * Let fmemopen allocate the buffer. - */ - - char str[] = "A quick test"; + /* Let fmemopen allocate the buffer. */ FILE *fp; long pos; - size_t nofw, nofr, i; + size_t nofw, i; int rc; /* Open a FILE * using fmemopen. */ @@ -130,9 +124,7 @@ ATF_TC_BODY(test_autoalloc, tc) pos = ftell(fp); ATF_REQUIRE(pos == 512); - /* - * Try to write past the end, we should get a short object count (0) - */ + /* Try to write past the end, we should get a short object count (0) */ nofw = fwrite("a", 1, 1, fp); ATF_REQUIRE(nofw == 0); @@ -173,10 +165,7 @@ ATF_TC_BODY(test_data_length, tc) nofw = fwrite(str, 1, sizeof(str), fp); ATF_REQUIRE(nofw == sizeof(str)); - /* - * Now seek to the end and check that ftell - * gives us sizeof(str). - */ + /* Now seek to the end and check that ftell gives us sizeof(str). */ rc = fseek(fp, 0, SEEK_END); ATF_REQUIRE(rc == 0); pos = ftell(fp); @@ -264,9 +253,7 @@ ATF_TC_BODY(test_append_binary_pos, tc) ATF_REQUIRE(ftell(fp) == 0L); fclose(fp); - /* - * Make sure that a pre-allocated buffer behaves correctly. - */ + /* Make sure that a pre-allocated buffer behaves correctly. */ char buf[] = "Hello"; fp = fmemopen(buf, sizeof(buf), "ab+"); ATF_REQUIRE(ftell(fp) == strlen(buf)); @@ -276,9 +263,7 @@ ATF_TC_BODY(test_append_binary_pos, tc) ATF_TC_WITHOUT_HEAD(test_size_0); ATF_TC_BODY(test_size_0, tc) { - /* - * POSIX mandates that we return EINVAL if size is 0. - */ + /* POSIX mandates that we return EINVAL if size is 0. */ FILE *fp; diff --git a/lib/libc/tests/stdio/fopen_test.c b/lib/libc/tests/stdio/fopen_test.c new file mode 100644 index 0000000..962e7fd --- /dev/null +++ b/lib/libc/tests/stdio/fopen_test.c @@ -0,0 +1,205 @@ +/*- + * Copyright (c) 2013 Jilles Tjoelker + * 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 <sys/cdefs.h> +__FBSDID("$FreeBSD$"); + +#include <fcntl.h> +#include <paths.h> +#include <stdio.h> +#include <string.h> + +#include <atf-c.h> + +/* + * O_ACCMODE is currently defined incorrectly. This is what it should be. + * Various code depends on the incorrect value. + */ +#define CORRECT_O_ACCMODE (O_ACCMODE | O_EXEC) + +static void +runtest(const char *fname, const char *mode) +{ + FILE *fp; + int exp_fget_ret, fget_ret, fd, flags, wantedflags; + + fp = fopen(fname, mode); + ATF_REQUIRE_MSG(fp != NULL, + "fopen(\"%s\", \"%s\") failed", fname, mode); + fd = fileno(fp); + ATF_REQUIRE_MSG(fd >= 0, "fileno() failed for fopen"); + exp_fget_ret = strchr(mode, 'e') != NULL ? FD_CLOEXEC : 0; + ATF_REQUIRE_MSG((fget_ret = fcntl(fd, F_GETFD)) == exp_fget_ret, + "fcntl(.., F_GETFD) didn't FD_CLOEXEC as expected %d != %d", + exp_fget_ret, fget_ret); + flags = fcntl(fd, F_GETFL); + if (strchr(mode, '+')) + wantedflags = O_RDWR | (*mode == 'a' ? O_APPEND : 0); + else if (*mode == 'r') + wantedflags = O_RDONLY; + else if (*mode == 'w') + wantedflags = O_WRONLY; + else if (*mode == 'a') + wantedflags = O_WRONLY | O_APPEND; + else + wantedflags = -1; + fclose(fp); + if (wantedflags == -1) + atf_tc_fail("unrecognized mode: %s", mode); + else if ((flags & (CORRECT_O_ACCMODE | O_APPEND)) != wantedflags) + atf_tc_fail("incorrect access mode: %s", mode); +} + +ATF_TC_WITHOUT_HEAD(fopen_r_test); +ATF_TC_BODY(fopen_r_test, tc) +{ + + runtest(_PATH_DEVNULL, "r"); +} + +ATF_TC_WITHOUT_HEAD(fopen_r_append_test); +ATF_TC_BODY(fopen_r_append_test, tc) +{ + + runtest(_PATH_DEVNULL, "r+"); +} + +ATF_TC_WITHOUT_HEAD(fopen_w_test); +ATF_TC_BODY(fopen_w_test, tc) +{ + + runtest(_PATH_DEVNULL, "w"); +} + +ATF_TC_WITHOUT_HEAD(fopen_w_append_test); +ATF_TC_BODY(fopen_w_append_test, tc) +{ + + runtest(_PATH_DEVNULL, "w+"); +} + +ATF_TC_WITHOUT_HEAD(fopen_a_test); +ATF_TC_BODY(fopen_a_test, tc) +{ + + runtest(_PATH_DEVNULL, "a"); +} + +ATF_TC_WITHOUT_HEAD(fopen_a_append_test); +ATF_TC_BODY(fopen_a_append_test, tc) +{ + + runtest(_PATH_DEVNULL, "a+"); +} + +ATF_TC_WITHOUT_HEAD(fopen_re_test); +ATF_TC_BODY(fopen_re_test, tc) +{ + + runtest(_PATH_DEVNULL, "re"); +} + +ATF_TC_WITHOUT_HEAD(fopen_r_append_e_test); +ATF_TC_BODY(fopen_r_append_e_test, tc) +{ + + runtest(_PATH_DEVNULL, "r+e"); +} + +ATF_TC_WITHOUT_HEAD(fopen_we_test); +ATF_TC_BODY(fopen_we_test, tc) +{ + + runtest(_PATH_DEVNULL, "we"); +} + +ATF_TC_WITHOUT_HEAD(fopen_w_append_e_test); +ATF_TC_BODY(fopen_w_append_e_test, tc) +{ + + runtest(_PATH_DEVNULL, "w+e"); +} + +ATF_TC_WITHOUT_HEAD(fopen_ae_test); +ATF_TC_BODY(fopen_ae_test, tc) +{ + + runtest(_PATH_DEVNULL, "ae"); +} + +ATF_TC_WITHOUT_HEAD(fopen_a_append_e_test); +ATF_TC_BODY(fopen_a_append_e_test, tc) +{ + + runtest(_PATH_DEVNULL, "a+e"); +} + +ATF_TC_WITHOUT_HEAD(fopen_re_append_test); +ATF_TC_BODY(fopen_re_append_test, tc) +{ + + runtest(_PATH_DEVNULL, "re+"); +} + +ATF_TC_WITHOUT_HEAD(fopen_we_append_test); +ATF_TC_BODY(fopen_we_append_test, tc) +{ + + runtest(_PATH_DEVNULL, "we+"); +} + +ATF_TC_WITHOUT_HEAD(fopen_ae_append_test); +ATF_TC_BODY(fopen_ae_append_test, tc) +{ + + runtest(_PATH_DEVNULL, "ae+"); +} + +ATF_TP_ADD_TCS(tp) +{ + + ATF_TP_ADD_TC(tp, fopen_r_test); + ATF_TP_ADD_TC(tp, fopen_r_append_test); + ATF_TP_ADD_TC(tp, fopen_w_test); + ATF_TP_ADD_TC(tp, fopen_w_append_test); + ATF_TP_ADD_TC(tp, fopen_a_test); + ATF_TP_ADD_TC(tp, fopen_a_append_test); + ATF_TP_ADD_TC(tp, fopen_re_test); + ATF_TP_ADD_TC(tp, fopen_r_append_e_test); + ATF_TP_ADD_TC(tp, fopen_we_test); + ATF_TP_ADD_TC(tp, fopen_w_append_e_test); + ATF_TP_ADD_TC(tp, fopen_ae_test); + ATF_TP_ADD_TC(tp, fopen_a_append_e_test); + ATF_TP_ADD_TC(tp, fopen_re_append_test); + ATF_TP_ADD_TC(tp, fopen_we_append_test); + ATF_TP_ADD_TC(tp, fopen_ae_append_test); + + return (atf_no_error()); +} + +/* + vim:ts=8:cin:sw=8 + */ diff --git a/lib/libc/tests/stdio/freopen_test.c b/lib/libc/tests/stdio/freopen_test.c new file mode 100644 index 0000000..1719927 --- /dev/null +++ b/lib/libc/tests/stdio/freopen_test.c @@ -0,0 +1,224 @@ +/*- + * Copyright (c) 2014 Jilles Tjoelker + * 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 <sys/cdefs.h> +__FBSDID("$FreeBSD$"); + +#include <errno.h> +#include <paths.h> +#include <stdbool.h> +#include <stdio.h> +#include <string.h> + +#include <atf-c.h> + +static void +runtest(const char *fname1, const char *mode1, const char *fname2, + const char *mode2, bool success) +{ + FILE *fp1, *fp2; + const char *fname2_print; + + fname2_print = fname2 != NULL ? fname2 : "<NULL>"; + fp1 = fopen(fname1, mode1); + ATF_REQUIRE_MSG(fp1 != NULL, + "fopen(\"%s\", \"%s\") failed; errno=%d", fname1, mode1, errno); + fp2 = freopen(fname2, mode2, fp1); + if (fp2 == NULL) { + fclose(fp1); + ATF_REQUIRE_MSG(success == false, + "freopen(\"%s\", \"%s\", fopen(\"%s\", \"%s\")) succeeded " + "unexpectedly", fname2_print, mode2, fname1, mode1); + return; + } + ATF_REQUIRE_MSG(success == true, + "freopen(\"%s\", \"%s\", fopen(\"%s\", \"%s\")) failed: %d", + fname2_print, mode2, fname1, mode1, errno); + fclose(fp2); +} + +ATF_TC_WITHOUT_HEAD(null__r__r__test); +ATF_TC_BODY(null__r__r__test, tc) +{ + + runtest(_PATH_DEVNULL, "r", NULL, "r", true); +} + +ATF_TC_WITHOUT_HEAD(null__w__r__test); +ATF_TC_BODY(null__w__r__test, tc) +{ + + runtest(_PATH_DEVNULL, "w", NULL, "r", false); +} + +ATF_TC_WITHOUT_HEAD(null__r_append__r__test); +ATF_TC_BODY(null__r_append__r__test, tc) +{ + + runtest(_PATH_DEVNULL, "r+", NULL, "r", true); +} + +ATF_TC_WITHOUT_HEAD(null__r__w__test); +ATF_TC_BODY(null__r__w__test, tc) +{ + + runtest(_PATH_DEVNULL, "r", NULL, "w", false); +} + +ATF_TC_WITHOUT_HEAD(null__w__w__test); +ATF_TC_BODY(null__w__w__test, tc) +{ + + runtest(_PATH_DEVNULL, "w", NULL, "w", true); +} + +ATF_TC_WITHOUT_HEAD(null__r_append__w__test); +ATF_TC_BODY(null__r_append__w__test, tc) +{ + + runtest(_PATH_DEVNULL, "r+", NULL, "w", true); +} + +ATF_TC_WITHOUT_HEAD(null__r__a__test); +ATF_TC_BODY(null__r__a__test, tc) +{ + + runtest(_PATH_DEVNULL, "r", NULL, "a", false); +} + +ATF_TC_WITHOUT_HEAD(null__w__a__test); +ATF_TC_BODY(null__w__a__test, tc) +{ + + runtest(_PATH_DEVNULL, "w", NULL, "a", true); +} + +ATF_TC_WITHOUT_HEAD(null__r_append__a__test); +ATF_TC_BODY(null__r_append__a__test, tc) +{ + + runtest(_PATH_DEVNULL, "r+", NULL, "a", true); +} + +ATF_TC_WITHOUT_HEAD(null__r__r_append__test); +ATF_TC_BODY(null__r__r_append__test, tc) +{ + + runtest(_PATH_DEVNULL, "r", NULL, "r+", false); +} + +ATF_TC_WITHOUT_HEAD(null__w__r_append__test); +ATF_TC_BODY(null__w__r_append__test, tc) +{ + + runtest(_PATH_DEVNULL, "w", NULL, "r+", false); +} + +ATF_TC_WITHOUT_HEAD(null__r_append__r_append__test); +ATF_TC_BODY(null__r_append__r_append__test, tc) +{ + + runtest(_PATH_DEVNULL, "r+", NULL, "r+", true); +} + +ATF_TC_WITHOUT_HEAD(null__r__w_append__test); +ATF_TC_BODY(null__r__w_append__test, tc) +{ + + runtest(_PATH_DEVNULL, "r", NULL, "w+", false); +} + +ATF_TC_WITHOUT_HEAD(null__w__w_append__test); +ATF_TC_BODY(null__w__w_append__test, tc) +{ + + runtest(_PATH_DEVNULL, "w", NULL, "w+", false); +} + +ATF_TC_WITHOUT_HEAD(null__r_append__w_append__test); +ATF_TC_BODY(null__r_append__w_append__test, tc) +{ + + runtest(_PATH_DEVNULL, "r+", NULL, "w+", true); +} + +ATF_TC_WITHOUT_HEAD(sh__r__r__test); +ATF_TC_BODY(sh__r__r__test, tc) +{ + + runtest("/bin/sh", "r", NULL, "r", true); +} + +ATF_TC_WITHOUT_HEAD(sh__sh__r__r__test); +ATF_TC_BODY(sh__sh__r__r__test, tc) +{ + + runtest("/bin/sh", "r", "/bin/sh", "r", true); +} + +ATF_TC_WITHOUT_HEAD(sh__null__r__r__test); +ATF_TC_BODY(sh__null__r__r__test, tc) +{ + + runtest("/bin/sh", "r", _PATH_DEVNULL, "r", true); +} + +ATF_TC_WITHOUT_HEAD(sh__null__r__w__test); +ATF_TC_BODY(sh__null__r__w__test, tc) +{ + + runtest("/bin/sh", "r", _PATH_DEVNULL, "w", true); +} + +ATF_TP_ADD_TCS(tp) +{ + + ATF_TP_ADD_TC(tp, null__r__r__test); + ATF_TP_ADD_TC(tp, null__w__r__test); + ATF_TP_ADD_TC(tp, null__r_append__r__test); + ATF_TP_ADD_TC(tp, null__r__w__test); + ATF_TP_ADD_TC(tp, null__w__w__test); + ATF_TP_ADD_TC(tp, null__r_append__w__test); + ATF_TP_ADD_TC(tp, null__r__a__test); + ATF_TP_ADD_TC(tp, null__w__a__test); + ATF_TP_ADD_TC(tp, null__r_append__a__test); + ATF_TP_ADD_TC(tp, null__r__r_append__test); + ATF_TP_ADD_TC(tp, null__w__r_append__test); + ATF_TP_ADD_TC(tp, null__r_append__r_append__test); + ATF_TP_ADD_TC(tp, null__r__w_append__test); + ATF_TP_ADD_TC(tp, null__w__w_append__test); + ATF_TP_ADD_TC(tp, null__r_append__w_append__test); + ATF_TP_ADD_TC(tp, sh__r__r__test); + ATF_TP_ADD_TC(tp, sh__sh__r__r__test); + ATF_TP_ADD_TC(tp, sh__null__r__r__test); + ATF_TP_ADD_TC(tp, sh__null__r__w__test); + + return (atf_no_error()); +} + +/* + vim:ts=8:cin:sw=8 + */ diff --git a/lib/libc/tests/stdio/getdelim_test.c b/lib/libc/tests/stdio/getdelim_test.c new file mode 100644 index 0000000..ffc6810 --- /dev/null +++ b/lib/libc/tests/stdio/getdelim_test.c @@ -0,0 +1,236 @@ +/*- + * Copyright (c) 2009 David Schultz <das@FreeBSD.org> + * 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 <sys/cdefs.h> +__FBSDID("$FreeBSD$"); + +#define _WITH_GETLINE +#include <errno.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +#include <atf-c.h> + +#define CHUNK_MAX 10 + +/* The assertions depend on this string. */ +char apothegm[] = "All work and no play\0 makes Jack a dull boy.\n"; + +/* + * This is a neurotic reader function designed to give getdelim() a + * hard time. It reads through the string `apothegm' and returns a + * random number of bytes up to the requested length. + */ +static int +_reader(void *cookie, char *buf, int len) +{ + size_t *offp = cookie; + size_t r; + + r = random() % CHUNK_MAX + 1; + if (len > r) + len = r; + if (len > sizeof(apothegm) - *offp) + len = sizeof(apothegm) - *offp; + memcpy(buf, apothegm + *offp, len); + *offp += len; + return (len); +} + +static FILE * +mkfilebuf(void) +{ + size_t *offp; + + offp = malloc(sizeof(*offp)); /* XXX leak */ + *offp = 0; + return (fropen(offp, _reader)); +} + +ATF_TC_WITHOUT_HEAD(getline_basic); +ATF_TC_BODY(getline_basic, tc) +{ + FILE *fp; + char *line; + size_t linecap; + int i; + + srandom(0); + + /* + * Test multiple times with different buffer sizes + * and different _reader() return values. + */ + errno = 0; + for (i = 0; i < 8; i++) { + fp = mkfilebuf(); + linecap = i; + line = malloc(i); + /* First line: the full apothegm */ + ATF_REQUIRE(getline(&line, &linecap, fp) == sizeof(apothegm) - 1); + ATF_REQUIRE(memcmp(line, apothegm, sizeof(apothegm)) == 0); + ATF_REQUIRE(linecap >= sizeof(apothegm)); + /* Second line: the NUL terminator following the newline */ + ATF_REQUIRE(getline(&line, &linecap, fp) == 1); + ATF_REQUIRE(line[0] == '\0' && line[1] == '\0'); + /* Third line: EOF */ + line[0] = 'X'; + ATF_REQUIRE(getline(&line, &linecap, fp) == -1); + ATF_REQUIRE(line[0] == '\0'); + free(line); + line = NULL; + ATF_REQUIRE(feof(fp)); + ATF_REQUIRE(!ferror(fp)); + fclose(fp); + } + ATF_REQUIRE(errno == 0); +} + +ATF_TC_WITHOUT_HEAD(stream_error); +ATF_TC_BODY(stream_error, tc) +{ + char *line; + size_t linecap; + + /* Make sure read errors are handled properly. */ + line = NULL; + linecap = 0; + errno = 0; + ATF_REQUIRE(getline(&line, &linecap, stdout) == -1); + ATF_REQUIRE(errno == EBADF); + errno = 0; + ATF_REQUIRE(getdelim(&line, &linecap, 'X', stdout) == -1); + ATF_REQUIRE(errno == EBADF); + ATF_REQUIRE(ferror(stdout)); +} + +ATF_TC_WITHOUT_HEAD(invalid_params); +ATF_TC_BODY(invalid_params, tc) +{ + FILE *fp; + char *line; + size_t linecap; + + /* Make sure NULL linep or linecapp pointers are handled. */ + fp = mkfilebuf(); + ATF_REQUIRE(getline(NULL, &linecap, fp) == -1); + ATF_REQUIRE(errno == EINVAL); + ATF_REQUIRE(getline(&line, NULL, fp) == -1); + ATF_REQUIRE(errno == EINVAL); + ATF_REQUIRE(ferror(fp)); + fclose(fp); +} + +ATF_TC_WITHOUT_HEAD(eof); +ATF_TC_BODY(eof, tc) +{ + FILE *fp; + char *line; + size_t linecap; + + /* Make sure getline() allocates memory as needed if fp is at EOF. */ + errno = 0; + fp = mkfilebuf(); + while (!feof(fp)) /* advance to EOF; can't fseek this stream */ + getc(fp); + line = NULL; + linecap = 0; + printf("getline\n"); + ATF_REQUIRE(getline(&line, &linecap, fp) == -1); + ATF_REQUIRE(line[0] == '\0'); + ATF_REQUIRE(linecap > 0); + ATF_REQUIRE(errno == 0); + printf("feof\n"); + ATF_REQUIRE(feof(fp)); + ATF_REQUIRE(!ferror(fp)); + fclose(fp); +} + +ATF_TC_WITHOUT_HEAD(nul); +ATF_TC_BODY(nul, tc) +{ + FILE *fp; + char *line; + size_t linecap, n; + + line = NULL; + linecap = 0; + /* Make sure a NUL delimiter works. */ + fp = mkfilebuf(); + n = strlen(apothegm); + printf("getdelim\n"); + ATF_REQUIRE(getdelim(&line, &linecap, '\0', fp) == n + 1); + ATF_REQUIRE(strcmp(line, apothegm) == 0); + ATF_REQUIRE(line[n + 1] == '\0'); + ATF_REQUIRE(linecap > n + 1); + n = strlen(apothegm + n + 1); + printf("getdelim 2\n"); + ATF_REQUIRE(getdelim(&line, &linecap, '\0', fp) == n + 1); + ATF_REQUIRE(line[n + 1] == '\0'); + ATF_REQUIRE(linecap > n + 1); + ATF_REQUIRE(errno == 0); + ATF_REQUIRE(!ferror(fp)); + fclose(fp); +} + +ATF_TC_WITHOUT_HEAD(empty_NULL_buffer); +ATF_TC_BODY(empty_NULL_buffer, tc) +{ + FILE *fp; + char *line; + size_t linecap; + + /* Make sure NULL *linep and zero *linecapp are handled. */ + fp = mkfilebuf(); + free(line); + line = NULL; + linecap = 42; + ATF_REQUIRE(getline(&line, &linecap, fp) == sizeof(apothegm) - 1); + ATF_REQUIRE(memcmp(line, apothegm, sizeof(apothegm)) == 0); + fp = mkfilebuf(); + free(line); + line = malloc(100); + linecap = 0; + ATF_REQUIRE(getline(&line, &linecap, fp) == sizeof(apothegm) - 1); + ATF_REQUIRE(memcmp(line, apothegm, sizeof(apothegm)) == 0); + free(line); + ATF_REQUIRE(!ferror(fp)); + fclose(fp); +} + +ATF_TP_ADD_TCS(tp) +{ + + ATF_TP_ADD_TC(tp, getline_basic); + ATF_TP_ADD_TC(tp, stream_error); + ATF_TP_ADD_TC(tp, eof); + ATF_TP_ADD_TC(tp, invalid_params); + ATF_TP_ADD_TC(tp, nul); + ATF_TP_ADD_TC(tp, empty_NULL_buffer); + + return (atf_no_error()); +} diff --git a/lib/libc/tests/stdio/mkostemp_test.c b/lib/libc/tests/stdio/mkostemp_test.c new file mode 100644 index 0000000..0dd475b --- /dev/null +++ b/lib/libc/tests/stdio/mkostemp_test.c @@ -0,0 +1,185 @@ +/*- + * Copyright (c) 2013 Jilles Tjoelker + * 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. + */ + +/* + * Test program for mkostemp(). + */ + +#include <sys/cdefs.h> +__FBSDID("$FreeBSD$"); + +#include <sys/stat.h> + +#include <errno.h> +#include <fcntl.h> +#include <paths.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> + +#include <atf-c.h> + +static const char template[] = "mkostemp.XXXXXXXX"; +static int testnum; + +#define MISCFLAGS (O_APPEND | O_DIRECT | O_SHLOCK | O_EXLOCK | O_SYNC) + +static void +test_one(int oflags) +{ + char tmpf[sizeof(template)]; + struct stat st1, st2; + int fd; + + memcpy(tmpf, template, sizeof(tmpf)); + fd = mkostemp(tmpf, oflags); + if (fd < 0) { + printf("not ok %d - oflags=%#x " + "mkostemp() reported failure: %s\n", + testnum++, oflags, strerror(errno)); + return; + } + if (memcmp(tmpf, template, sizeof(tmpf) - 8 - 1) != 0) { + printf("not ok %d - oflags=%#x " + "returned pathname does not match template: %s\n", + testnum++, oflags, tmpf); + return; + } + do { + if (fcntl(fd, F_GETFD) != + (oflags & O_CLOEXEC ? FD_CLOEXEC : 0)) { + printf("not ok %d - oflags=%#x " + "close-on-exec flag incorrect\n", + testnum++, oflags); + break; + } + if ((fcntl(fd, F_GETFL) & MISCFLAGS) != (oflags & MISCFLAGS)) { + printf("not ok %d - oflags=%#x " + "open flags incorrect\n", + testnum++, oflags); + break; + } + if (stat(tmpf, &st1) == -1) { + printf("not ok %d - oflags=%#x " + "cannot stat returned pathname %s: %s\n", + testnum++, oflags, tmpf, strerror(errno)); + break; + } + if (fstat(fd, &st2) == -1) { + printf("not ok %d - oflags=%#x " + "cannot fstat returned fd %d: %s\n", + testnum++, oflags, fd, strerror(errno)); + break; + } + if (!S_ISREG(st1.st_mode) || (st1.st_mode & 0777) != 0600 || + st1.st_nlink != 1 || st1.st_size != 0) { + printf("not ok %d - oflags=%#x " + "named file attributes incorrect\n", + testnum++, oflags); + break; + } + if (!S_ISREG(st2.st_mode) || (st2.st_mode & 0777) != 0600 || + st2.st_nlink != 1 || st2.st_size != 0) { + printf("not ok %d - oflags=%#x " + "opened file attributes incorrect\n", + testnum++, oflags); + break; + } + if (st1.st_dev != st2.st_dev || st1.st_ino != st2.st_ino) { + printf("not ok %d - oflags=%#x " + "named and opened file do not match\n", + testnum++, oflags); + break; + } + (void)unlink(tmpf); + if (fstat(fd, &st2) == -1) + printf("not ok %d - oflags=%#x " + "cannot fstat returned fd %d again: %s\n", + testnum++, oflags, fd, strerror(errno)); + else if (st2.st_nlink != 0) + printf("not ok %d - oflags=%#x " + "st_nlink is not 0 after unlink\n", + testnum++, oflags); + else + printf("ok %d - oflags=%#x\n", testnum++, oflags); + (void)close(fd); + return; + } while (0); + (void)close(fd); + (void)unlink(tmpf); +} + +ATF_TC_WITHOUT_HEAD(zero); +ATF_TC_BODY(zero, tc) +{ + + test_one(0); +} + +ATF_TC_WITHOUT_HEAD(O_CLOEXEC); +ATF_TC_BODY(O_CLOEXEC, tc) +{ + + test_one(O_CLOEXEC); +} + +ATF_TC_WITHOUT_HEAD(O_APPEND); +ATF_TC_BODY(O_APPEND, tc) +{ + + test_one(O_APPEND); +} + +ATF_TC_WITHOUT_HEAD(O_APPEND__O_CLOEXEC); +ATF_TC_BODY(O_APPEND__O_CLOEXEC, tc) +{ + + test_one(O_APPEND|O_CLOEXEC); +} + +ATF_TC_WITHOUT_HEAD(bad_flags); +ATF_TC_BODY(bad_flags, tc) +{ + + char tmpf[sizeof(template)]; + + memcpy(tmpf, template, sizeof(tmpf)); + ATF_REQUIRE_MSG(mkostemp(tmpf, O_CREAT) == -1, + "mkostemp(O_CREAT) succeeded unexpectedly"); +} + +ATF_TP_ADD_TCS(tp) +{ + + ATF_TP_ADD_TC(tp, zero); + ATF_TP_ADD_TC(tp, O_CLOEXEC); + ATF_TP_ADD_TC(tp, O_APPEND); + ATF_TP_ADD_TC(tp, O_APPEND__O_CLOEXEC); + ATF_TP_ADD_TC(tp, bad_flags); + + return (atf_no_error()); +} diff --git a/lib/libc/tests/stdio/open_memstream_test.c b/lib/libc/tests/stdio/open_memstream_test.c new file mode 100644 index 0000000..3c9e3ec --- /dev/null +++ b/lib/libc/tests/stdio/open_memstream_test.c @@ -0,0 +1,201 @@ +/*- + * Copyright (c) 2013 Hudson River Trading LLC + * Written by: John H. Baldwin <jhb@FreeBSD.org> + * 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 <sys/cdefs.h> +__FBSDID("$FreeBSD$"); + +#include <err.h> +#include <errno.h> +#include <limits.h> +#include <stdint.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <wchar.h> + +#include <atf-c.h> + +static char *buf; +static size_t len; + +static void +assert_stream(const char *contents) +{ + if (strlen(contents) != len) + printf("bad length %zd for \"%s\"\n", len, contents); + else if (strncmp(buf, contents, strlen(contents)) != 0) + printf("bad buffer \"%s\" for \"%s\"\n", buf, contents); +} + +ATF_TC_WITHOUT_HEAD(open_group_test); +ATF_TC_BODY(open_group_test, tc) +{ + FILE *fp; + off_t eob; + + fp = open_memstream(&buf, &len); + ATF_REQUIRE_MSG(fp != NULL, "open_memstream failed"); + + fprintf(fp, "hello my world"); + fflush(fp); + assert_stream("hello my world"); + eob = ftello(fp); + rewind(fp); + fprintf(fp, "good-bye"); + fseeko(fp, eob, SEEK_SET); + fclose(fp); + assert_stream("good-bye world"); + free(buf); +} + +ATF_TC_WITHOUT_HEAD(simple_tests); +ATF_TC_BODY(simple_tests, tc) +{ + static const char zerobuf[] = + { 'f', 'o', 'o', 0, 0, 0, 0, 'b', 'a', 'r', 0 }; + char c; + FILE *fp; + + fp = open_memstream(&buf, NULL); + ATF_REQUIRE_MSG(fp == NULL, "open_memstream did not fail"); + ATF_REQUIRE_MSG(errno == EINVAL, + "open_memstream didn't fail with EINVAL"); + fp = open_memstream(NULL, &len); + ATF_REQUIRE_MSG(fp == NULL, "open_memstream did not fail"); + ATF_REQUIRE_MSG(errno == EINVAL, + "open_memstream didn't fail with EINVAL"); + fp = open_memstream(&buf, &len); + ATF_REQUIRE_MSG(fp != NULL, "open_memstream failed; errno=%d", errno); + fflush(fp); + assert_stream(""); + if (fwide(fp, 0) >= 0) + printf("stream is not byte-oriented\n"); + + fprintf(fp, "fo"); + fflush(fp); + assert_stream("fo"); + fputc('o', fp); + fflush(fp); + assert_stream("foo"); + rewind(fp); + fflush(fp); + assert_stream(""); + fseek(fp, 0, SEEK_END); + fflush(fp); + assert_stream("foo"); + + /* + * Test seeking out past the current end. Should zero-fill the + * intermediate area. + */ + fseek(fp, 4, SEEK_END); + fprintf(fp, "bar"); + fflush(fp); + + /* + * Can't use assert_stream() here since this should contain + * embedded null characters. + */ + if (len != 10) + printf("bad length %zd for zero-fill test\n", len); + else if (memcmp(buf, zerobuf, sizeof(zerobuf)) != 0) + printf("bad buffer for zero-fill test\n"); + + fseek(fp, 3, SEEK_SET); + fprintf(fp, " in "); + fflush(fp); + assert_stream("foo in "); + fseek(fp, 0, SEEK_END); + fflush(fp); + assert_stream("foo in bar"); + + rewind(fp); + if (fread(&c, sizeof(c), 1, fp) != 0) + printf("fread did not fail\n"); + else if (!ferror(fp)) + printf("error indicator not set after fread\n"); + else + clearerr(fp); + + fseek(fp, 4, SEEK_SET); + fprintf(fp, "bar baz"); + fclose(fp); + assert_stream("foo bar baz"); + free(buf); +} + +ATF_TC_WITHOUT_HEAD(seek_tests); +ATF_TC_BODY(seek_tests, tc) +{ + FILE *fp; + + fp = open_memstream(&buf, &len); + ATF_REQUIRE_MSG(fp != NULL, "open_memstream failed: %d", errno); + +#define SEEK_FAIL(offset, whence, error) do { \ + errno = 0; \ + ATF_REQUIRE_MSG(fseeko(fp, (offset), (whence)) != 0, \ + "fseeko(%s, %s) did not fail, set pos to %jd\n", \ + __STRING(offset), __STRING(whence), \ + (intmax_t)ftello(fp)); \ + ATF_REQUIRE_MSG(errno == (error), \ + "fseeko(%s, %s) failed with %d rather than %s\n", \ + __STRING(offset), __STRING(whence), errno, \ + __STRING(error)); \ +} while (0) + +#define SEEK_OK(offset, whence, result) do { \ + ATF_REQUIRE_MSG(fseeko(fp, (offset), (whence)) == 0, \ + "fseeko(%s, %s) failed: %s", \ + __STRING(offset), __STRING(whence), strerror(errno)); \ + ATF_REQUIRE_MSG(ftello(fp) == (result), \ + "fseeko(%s, %s) seeked to %jd rather than %s\n", \ + __STRING(offset), __STRING(whence), \ + (intmax_t)ftello(fp), __STRING(result)); \ +} while (0) + + SEEK_FAIL(-1, SEEK_SET, EINVAL); + SEEK_FAIL(-1, SEEK_CUR, EINVAL); + SEEK_FAIL(-1, SEEK_END, EINVAL); + fprintf(fp, "foo"); + SEEK_OK(-1, SEEK_CUR, 2); + SEEK_OK(0, SEEK_SET, 0); + SEEK_OK(-1, SEEK_END, 2); + SEEK_OK(OFF_MAX - 1, SEEK_SET, OFF_MAX - 1); + SEEK_FAIL(2, SEEK_CUR, EOVERFLOW); + fclose(fp); +} + +ATF_TP_ADD_TCS(tp) +{ + + ATF_TP_ADD_TC(tp, open_group_test); + ATF_TP_ADD_TC(tp, simple_tests); + ATF_TP_ADD_TC(tp, seek_tests); + + return (atf_no_error()); +} diff --git a/lib/libc/tests/stdio/open_wmemstream_test.c b/lib/libc/tests/stdio/open_wmemstream_test.c new file mode 100644 index 0000000..d6ae2ea --- /dev/null +++ b/lib/libc/tests/stdio/open_wmemstream_test.c @@ -0,0 +1,201 @@ +/*- + * Copyright (c) 2013 Hudson River Trading LLC + * Written by: John H. Baldwin <jhb@FreeBSD.org> + * 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 <sys/cdefs.h> +__FBSDID("$FreeBSD$"); + +#include <err.h> +#include <errno.h> +#include <limits.h> +#include <stdint.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <wchar.h> + +#include <atf-c.h> + +static wchar_t *buf; +static size_t len; + +static void +assert_stream(const wchar_t *contents) +{ + if (wcslen(contents) != len) + printf("bad length %zd for \"%ls\"\n", len, contents); + else if (wcsncmp(buf, contents, wcslen(contents)) != 0) + printf("bad buffer \"%ls\" for \"%ls\"\n", buf, contents); +} + +ATF_TC_WITHOUT_HEAD(open_group_test); +ATF_TC_BODY(open_group_test, tc) +{ + FILE *fp; + off_t eob; + + fp = open_wmemstream(&buf, &len); + ATF_REQUIRE_MSG(fp != NULL, "open_wmemstream failed"); + + fwprintf(fp, L"hello my world"); + fflush(fp); + assert_stream(L"hello my world"); + eob = ftello(fp); + rewind(fp); + fwprintf(fp, L"good-bye"); + fseeko(fp, eob, SEEK_SET); + fclose(fp); + assert_stream(L"good-bye world"); + free(buf); +} + +ATF_TC_WITHOUT_HEAD(simple_tests); +ATF_TC_BODY(simple_tests, tc) +{ + static const wchar_t zerobuf[] = + { L'f', L'o', L'o', 0, 0, 0, 0, L'b', L'a', L'r', 0 }; + wchar_t c; + FILE *fp; + + fp = open_wmemstream(&buf, NULL); + ATF_REQUIRE_MSG(fp == NULL, "open_wmemstream did not fail"); + ATF_REQUIRE_MSG(errno == EINVAL, + "open_wmemstream didn't fail with EINVAL"); + fp = open_wmemstream(NULL, &len); + ATF_REQUIRE_MSG(fp == NULL, "open_wmemstream did not fail"); + ATF_REQUIRE_MSG(errno == EINVAL, + "open_wmemstream didn't fail with EINVAL"); + fp = open_wmemstream(&buf, &len); + ATF_REQUIRE_MSG(fp != NULL, "open_memstream failed; errno=%d", errno); + fflush(fp); + assert_stream(L""); + if (fwide(fp, 0) <= 0) + printf("stream is not wide-oriented\n"); + + fwprintf(fp, L"fo"); + fflush(fp); + assert_stream(L"fo"); + fputwc(L'o', fp); + fflush(fp); + assert_stream(L"foo"); + rewind(fp); + fflush(fp); + assert_stream(L""); + fseek(fp, 0, SEEK_END); + fflush(fp); + assert_stream(L"foo"); + + /* + * Test seeking out past the current end. Should zero-fill the + * intermediate area. + */ + fseek(fp, 4, SEEK_END); + fwprintf(fp, L"bar"); + fflush(fp); + + /* + * Can't use assert_stream() here since this should contain + * embedded null characters. + */ + if (len != 10) + printf("bad length %zd for zero-fill test\n", len); + else if (memcmp(buf, zerobuf, sizeof(zerobuf)) != 0) + printf("bad buffer for zero-fill test\n"); + + fseek(fp, 3, SEEK_SET); + fwprintf(fp, L" in "); + fflush(fp); + assert_stream(L"foo in "); + fseek(fp, 0, SEEK_END); + fflush(fp); + assert_stream(L"foo in bar"); + + rewind(fp); + if (fread(&c, sizeof(c), 1, fp) != 0) + printf("fread did not fail\n"); + else if (!ferror(fp)) + printf("error indicator not set after fread\n"); + else + clearerr(fp); + + fseek(fp, 4, SEEK_SET); + fwprintf(fp, L"bar baz"); + fclose(fp); + assert_stream(L"foo bar baz"); + free(buf); +} + +ATF_TC_WITHOUT_HEAD(seek_tests); +ATF_TC_BODY(seek_tests, tc) +{ + FILE *fp; + + fp = open_wmemstream(&buf, &len); + ATF_REQUIRE_MSG(fp != NULL, "open_wmemstream failed; errno=%d", errno); + +#define SEEK_FAIL(offset, whence, error) do { \ + errno = 0; \ + ATF_REQUIRE_MSG(fseeko(fp, (offset), (whence)) != 0, \ + "fseeko(%s, %s) did not fail, set pos to %jd\n", \ + __STRING(offset), __STRING(whence), \ + (intmax_t)ftello(fp)); \ + ATF_REQUIRE_MSG(errno == (error), \ + "fseeko(%s, %s) failed with %d rather than %s\n", \ + __STRING(offset), __STRING(whence), errno, \ + __STRING(error)); \ +} while (0) + +#define SEEK_OK(offset, whence, result) do { \ + ATF_REQUIRE_MSG(fseeko(fp, (offset), (whence)) == 0, \ + "fseeko(%s, %s) failed: %s", \ + __STRING(offset), __STRING(whence), strerror(errno)); \ + ATF_REQUIRE_MSG(ftello(fp) == (result), \ + "fseeko(%s, %s) seeked to %jd rather than %s\n", \ + __STRING(offset), __STRING(whence), \ + (intmax_t)ftello(fp), __STRING(result)); \ +} while (0) + + SEEK_FAIL(-1, SEEK_SET, EINVAL); + SEEK_FAIL(-1, SEEK_CUR, EINVAL); + SEEK_FAIL(-1, SEEK_END, EINVAL); + fwprintf(fp, L"foo"); + SEEK_OK(-1, SEEK_CUR, 2); + SEEK_OK(0, SEEK_SET, 0); + SEEK_OK(-1, SEEK_END, 2); + SEEK_OK(OFF_MAX - 1, SEEK_SET, OFF_MAX - 1); + SEEK_FAIL(2, SEEK_CUR, EOVERFLOW); + fclose(fp); +} + +ATF_TP_ADD_TCS(tp) +{ + + ATF_TP_ADD_TC(tp, open_group_test); + ATF_TP_ADD_TC(tp, simple_tests); + ATF_TP_ADD_TC(tp, seek_tests); + + return (atf_no_error()); +} diff --git a/lib/libc/tests/stdio/perror_test.c b/lib/libc/tests/stdio/perror_test.c new file mode 100644 index 0000000..989f1ff --- /dev/null +++ b/lib/libc/tests/stdio/perror_test.c @@ -0,0 +1,107 @@ +/*- + * Copyright (c) 2002 Tim J. Robbins + * 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. + */ + +/* + * Test program for perror() as specified by IEEE Std. 1003.1-2001 and + * ISO/IEC 9899:1999. + */ + +#include <sys/cdefs.h> +__FBSDID("$FreeBSD$"); + +#include <err.h> +#include <errno.h> +#include <limits.h> +#include <paths.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> + +#include <atf-c.h> + +static char tmpfil[PATH_MAX]; + +ATF_TC_WITHOUT_HEAD(perror_test); +ATF_TC_BODY(perror_test, tc) +{ + char lbuf[512]; + int i; + char *s; + + strcpy(tmpfil, "perror.XXXXXXXX"); + ATF_REQUIRE(mkstemp(tmpfil) >= 0); + /* Reopen stderr on a file descriptor other than 2. */ + fclose(stderr); + for (i = 0; i < 3; i++) + dup(0); + ATF_REQUIRE(freopen(tmpfil, "r+", stderr) != NULL); + + /* + * Test that perror() doesn't call strerror() (4.4BSD bug), + * the two ways of omitting a program name, and the formatting when + * a program name is specified. + */ + s = strerror(ENOENT); + ATF_REQUIRE_MSG(strcmp(s, "No such file or directory") == 0, + "message obtained was: %s", s); + errno = EPERM; + perror(NULL); + perror(""); + perror("perror_test"); + ATF_REQUIRE_MSG(strcmp(s, "No such file or directory") == 0, + "message obtained was: %s", s); + + /* + * Read it back to check... + */ + rewind(stderr); + s = fgets(lbuf, sizeof(lbuf), stderr); + ATF_REQUIRE(s != NULL); + ATF_REQUIRE_MSG(strcmp(s, "Operation not permitted\n") == 0, + "message obtained was: %s", s); + s = fgets(lbuf, sizeof(lbuf), stderr); + ATF_REQUIRE(s != NULL); + ATF_REQUIRE_MSG(strcmp(s, "Operation not permitted\n") == 0, + "message obtained was: %s", s); + s = fgets(lbuf, sizeof(lbuf), stderr); + ATF_REQUIRE(s != NULL); + ATF_REQUIRE_MSG( + strcmp(s, "perror_test: Operation not permitted\n") == 0, + "message obtained was: %s", s); + s = fgets(lbuf, sizeof(lbuf), stderr); + ATF_REQUIRE(s == NULL); + fclose(stderr); + +} + +ATF_TP_ADD_TCS(tp) +{ + + ATF_TP_ADD_TC(tp, perror_test); + + return (atf_no_error()); +} diff --git a/lib/libc/tests/stdio/print_positional_test.c b/lib/libc/tests/stdio/print_positional_test.c new file mode 100644 index 0000000..1de43a1 --- /dev/null +++ b/lib/libc/tests/stdio/print_positional_test.c @@ -0,0 +1,156 @@ +/* $OpenBSD: sprintf_test.c,v 1.3 2004/09/16 20:22:26 otto Exp $ */ + +/* + * Copyright (c) 2003 Theo de Raadt + * 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. + * + * 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 HOLDERS 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 <sys/cdefs.h> +__FBSDID("$FreeBSD$"); + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <wchar.h> + +#include <atf-c.h> + +const char correct[] = + "|xx 01 02 03 04\n" + "|xx 05 06 07 08\n" + "|xx 09 10 11 12\n" + "|xx 13 14 15 16\n" + "|xx 17 18 19 20\n" + "|xx 21 22 23 24\n" + "|xx 25 26 27 28\n" + "|xx 29 30 31 32\n" + "|xx 33 34 35 36\n" + "|xx 37 38 39 40\n" + "|xx 41 42 43 44\n" + "|xx 45 -1 1 -1 1\n"; + +const char correct2[] = + "b bs BSD"; +static char buf[1024]; +static wchar_t wbuf1[1024], wbuf2[1024]; +static const char *temp; + +ATF_TC_WITHOUT_HEAD(positional_normal); +ATF_TC_BODY(positional_normal, tc) +{ + + /* Test positional arguments */ + snprintf(buf, sizeof buf, + "|xx %1$s %2$s %3$s %4$s\n" + "|xx %5$s %6$s %7$s %8$s\n" + "|xx %9$s %10$s %11$s %12$s\n" + "|xx %13$s %14$s %15$s %16$s\n" + "|xx %17$s %18$s %19$s %20$s\n" + "|xx %21$s %22$s %23$s %24$s\n" + "|xx %25$s %26$s %27$s %28$s\n" + "|xx %29$s %30$s %31$s %32$s\n" + "|xx %33$s %34$s %35$s %36$s\n" + "|xx %37$s %38$s %39$s %40$s\n" + "|xx %41$s %42$s %43$s %44$s\n" + "|xx %45$d %46$ld %47$lld %48$d %49$lld\n", + "01", "02", "03", "04", "05", "06", + "07", "08", "09", "10", "11", "12", + "13", "14", "15", "16", "17", "18", + "19", "20", "21", "22", "23", "24", + "25", "26", "27", "28", "29", "30", + "31", "32", "33", "34", "35", "36", + "37", "38", "39", "40", "41", "42", + "43", "44", 45, -1L, 1LL, -1, 1LL + ); + ATF_REQUIRE_MSG(wcscmp(wbuf1, wbuf2) == 0, + "buffers didn't match"); +} + +ATF_TC_WITHOUT_HEAD(positional_wide); +ATF_TC_BODY(positional_wide, tc) +{ + + swprintf(wbuf1, sizeof wbuf1, + L"|xx %1$s %2$s %3$s %4$s\n" + "|xx %5$s %6$s %7$s %8$s\n" + "|xx %9$s %10$s %11$s %12$s\n" + "|xx %13$s %14$s %15$s %16$s\n" + "|xx %17$s %18$s %19$s %20$s\n" + "|xx %21$s %22$s %23$s %24$s\n" + "|xx %25$s %26$s %27$s %28$s\n" + "|xx %29$s %30$s %31$s %32$s\n" + "|xx %33$s %34$s %35$s %36$s\n" + "|xx %37$s %38$s %39$s %40$s\n" + "|xx %41$s %42$s %43$s %44$s\n" + "|xx %45$d %46$ld %47$lld %48$d %49$lld\n", + "01", "02", "03", "04", "05", "06", + "07", "08", "09", "10", "11", "12", + "13", "14", "15", "16", "17", "18", + "19", "20", "21", "22", "23", "24", + "25", "26", "27", "28", "29", "30", + "31", "32", "33", "34", "35", "36", + "37", "38", "39", "40", "41", "42", + "43", "44", 45, -1L, 1LL, -1, 1LL + ); + temp = correct; + mbsrtowcs(wbuf2, &temp, sizeof wbuf2, NULL); + ATF_REQUIRE_MSG(wcscmp(wbuf1, wbuf2) == 0, + "buffers didn't match"); +} + +ATF_TC_WITHOUT_HEAD(positional_precision); +ATF_TC_BODY(positional_precision, tc) +{ + + snprintf(buf, sizeof buf, "%2$.*4$s %2$.*3$s %1$s", + "BSD", "bsd", 2, 1); + ATF_REQUIRE_MSG(strcmp(buf, correct2) == 0, + "buffers didn't match"); +} + +ATF_TC_WITHOUT_HEAD(positional_precision_wide); +ATF_TC_BODY(positional_precision_wide, tc) +{ + + swprintf(wbuf1, sizeof buf, L"%2$.*4$s %2$.*3$s %1$s", + "BSD", "bsd", 2, 1); + temp = correct2; + mbsrtowcs(wbuf2, &temp, sizeof wbuf2, NULL); + ATF_REQUIRE_MSG(wcscmp(wbuf1, wbuf2) == 0, + "buffers didn't match"); +} + +ATF_TP_ADD_TCS(tp) +{ + + ATF_TP_ADD_TC(tp, positional_normal); + ATF_TP_ADD_TC(tp, positional_wide); + ATF_TP_ADD_TC(tp, positional_precision); + ATF_TP_ADD_TC(tp, positional_precision_wide); + + return (atf_no_error()); +} diff --git a/lib/libc/tests/stdio/printbasic_test.c b/lib/libc/tests/stdio/printbasic_test.c new file mode 100644 index 0000000..d1fab29 --- /dev/null +++ b/lib/libc/tests/stdio/printbasic_test.c @@ -0,0 +1,158 @@ +/*- + * Copyright (c) 2009 David Schultz <das@FreeBSD.org> + * 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. + */ + +/* + * Tests for basic and miscellaneous printf() formats. + */ + +#include <sys/cdefs.h> +__FBSDID("$FreeBSD$"); + +#include <err.h> +#include <limits.h> +#include <locale.h> +#include <stdio.h> +#include <stdarg.h> +#include <stddef.h> +#include <stdint.h> +#include <stdlib.h> +#include <string.h> +#include <wchar.h> + +#include <atf-c.h> + +#define S_UINT64MAX "18446744073709551615" +#define S_UINT32MAX "4294967295" +#define S_INT64MIN "-9223372036854775808" +#define S_INT32MIN "-2147483648" + +#define S_SIZEMAX (SIZE_MAX == UINT64_MAX ? S_UINT64MAX : S_UINT32MAX) +#define S_ULONGMAX (ULONG_MAX == UINT64_MAX ? S_UINT64MAX : S_UINT32MAX) +#define S_ULLONGMAX (ULLONG_MAX == UINT64_MAX ? S_UINT64MAX : S_UINT32MAX) + +static void +smash_stack(void) +{ + static uint32_t junk = 0xdeadbeef; + uint32_t buf[512]; + int i; + + for (i = 0; i < sizeof(buf) / sizeof(buf[0]); i++) + buf[i] = junk; +} + +#define testfmt(result, fmt, ...) \ + _testfmt((result), #__VA_ARGS__, fmt, __VA_ARGS__) +static void +_testfmt(const char *result, const char *argstr, const char *fmt,...) +{ +#define BUF 100 + wchar_t ws[BUF], wfmt[BUF], wresult[BUF]; + char s[BUF]; + va_list ap, ap2; + + va_start(ap, fmt); + va_copy(ap2, ap); + smash_stack(); + vsnprintf(s, sizeof(s), fmt, ap); + if (strcmp(result, s) != 0) { + atf_tc_fail( + "printf(\"%s\", %s) ==> [%s], expected [%s]\n", + fmt, argstr, s, result); + } + + smash_stack(); + mbstowcs(ws, s, BUF - 1); + mbstowcs(wfmt, fmt, BUF - 1); + mbstowcs(wresult, result, BUF - 1); + vswprintf(ws, sizeof(ws) / sizeof(ws[0]), wfmt, ap2); + if (wcscmp(wresult, ws) != 0) { + atf_tc_fail( + "wprintf(\"%ls\", %s) ==> [%ls], expected [%ls]\n", + wfmt, argstr, ws, wresult); + } +} + +ATF_TC_WITHOUT_HEAD(int_within_limits); +ATF_TC_BODY(int_within_limits, tc) +{ + + ATF_REQUIRE(setlocale(LC_NUMERIC, "C")); + + /* The test requires these to be true. */ + ATF_REQUIRE(UINTMAX_MAX == UINT64_MAX); + ATF_REQUIRE(UINT_MAX == UINT32_MAX); + ATF_REQUIRE(USHRT_MAX == 0xffff); + ATF_REQUIRE(UCHAR_MAX == 0xff); + + /* Make sure we handle signed vs. unsigned args correctly. */ + testfmt("-1", "%jd", (intmax_t)-1); + testfmt(S_UINT64MAX, "%ju", UINT64_MAX); + + testfmt("-1", "%td", (ptrdiff_t)-1); + testfmt(S_SIZEMAX, "%tu", (size_t)-1); + + testfmt("-1", "%zd", (ssize_t)-1); + testfmt(S_SIZEMAX, "%zu", (ssize_t)-1); + + testfmt("-1", "%ld", (long)-1); + testfmt(S_ULONGMAX, "%lu", ULONG_MAX); + + testfmt("-1", "%lld", (long long)-1); + testfmt(S_ULONGMAX, "%lu", ULLONG_MAX); + + testfmt("-1", "%d", -1); + testfmt(S_UINT32MAX, "%lu", UINT32_MAX); + + testfmt("-1", "%hd", -1); + testfmt("65535", "%hu", USHRT_MAX); + + testfmt("-1", "%hhd", -1); + testfmt("255", "%hhu", UCHAR_MAX); +} + +ATF_TC_WITHOUT_HEAD(int_limits); +ATF_TC_BODY(int_limits, tc) +{ + + ATF_REQUIRE(setlocale(LC_NUMERIC, "C")); + + /* + * Check that printing the largest negative number does not cause + * overflow when it is negated. + */ + testfmt(S_INT32MIN, "%d", INT_MIN); + testfmt(S_INT64MIN, "%jd", INTMAX_MIN); +} + +ATF_TP_ADD_TCS(tp) +{ + + ATF_TP_ADD_TC(tp, int_within_limits); + ATF_TP_ADD_TC(tp, int_limits); + + return (atf_no_error()); +} diff --git a/lib/libc/tests/stdio/printfloat_test.c b/lib/libc/tests/stdio/printfloat_test.c new file mode 100644 index 0000000..6b4e455 --- /dev/null +++ b/lib/libc/tests/stdio/printfloat_test.c @@ -0,0 +1,390 @@ +/*- + * Copyright (c) 2002-2009 David Schultz <das@FreeBSD.org> + * 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. + */ + +/* + * Test for printf() floating point formats. + */ + +#include <sys/cdefs.h> +__FBSDID("$FreeBSD$"); + +#include <err.h> +#include <fenv.h> +#include <float.h> +#include <locale.h> +#include <math.h> +#include <stdio.h> +#include <stdarg.h> +#include <stdint.h> +#include <stdlib.h> +#include <string.h> +#include <wchar.h> + +#include <atf-c.h> + +static void +smash_stack(void) +{ + static uint32_t junk = 0xdeadbeef; + uint32_t buf[512]; + int i; + + for (i = 0; i < sizeof(buf) / sizeof(buf[0]); i++) + buf[i] = junk; +} + +#define testfmt(result, fmt, ...) \ + _testfmt((result), #__VA_ARGS__, fmt, __VA_ARGS__) +static void +_testfmt(const char *result, const char *argstr, const char *fmt,...) +{ +#define BUF 100 + wchar_t ws[BUF], wfmt[BUF], wresult[BUF]; + char s[BUF]; + va_list ap, ap2; + + va_start(ap, fmt); + va_copy(ap2, ap); + smash_stack(); + vsnprintf(s, sizeof(s), fmt, ap); + if (strcmp(result, s) != 0) { + atf_tc_fail( + "printf(\"%s\", %s) ==> [%s], expected [%s]\n", + fmt, argstr, s, result); + } + + smash_stack(); + mbstowcs(ws, s, BUF - 1); + mbstowcs(wfmt, fmt, BUF - 1); + mbstowcs(wresult, result, BUF - 1); + vswprintf(ws, sizeof(ws) / sizeof(ws[0]), wfmt, ap2); + if (wcscmp(wresult, ws) != 0) { + atf_tc_fail( + "wprintf(\"%ls\", %s) ==> [%ls], expected [%ls]\n", + wfmt, argstr, ws, wresult); + } +} + +ATF_TC_WITHOUT_HEAD(float_within_limits); +ATF_TC_BODY(float_within_limits, tc) +{ + + ATF_REQUIRE(setlocale(LC_NUMERIC, "C")); + + /* Basic tests of decimal output functionality. */ + testfmt(" 1.000000E+00", "%13E", 1.0); + testfmt(" 1.000000", "%13f", 1.0); + testfmt(" 1", "%13G", 1.0); + testfmt(" 1.000000E+00", "%13LE", 1.0L); + testfmt(" 1.000000", "%13Lf", 1.0L); + testfmt(" 1", "%13LG", 1.0L); + + testfmt("2.718282", "%.*f", -2, 2.7182818); + + testfmt("1.234568e+06", "%e", 1234567.8); + testfmt("1234567.800000", "%f", 1234567.8); + testfmt("1.23457E+06", "%G", 1234567.8); + testfmt("1.234568e+06", "%Le", 1234567.8L); + testfmt("1234567.800000", "%Lf", 1234567.8L); + testfmt("1.23457E+06", "%LG", 1234567.8L); + +#if (LDBL_MANT_DIG > DBL_MANT_DIG) && !defined(__i386__) + testfmt("123456789.864210", "%Lf", 123456789.8642097531L); + testfmt("-1.23457E+08", "%LG", -123456789.8642097531L); + testfmt("123456789.8642097531", "%.10Lf", 123456789.8642097531L); + testfmt(" 3.141592653589793238e-4000", "%L27.18Le", + 3.14159265358979323846e-4000L); +#endif +} + +ATF_TC_WITHOUT_HEAD(infinities_and_nans); +ATF_TC_BODY(infinities_and_nans, tc) +{ + + ATF_REQUIRE(setlocale(LC_NUMERIC, "C")); + + testfmt("nan", "%e", NAN); + testfmt("NAN", "%F", NAN); + testfmt("nan", "%g", NAN); + testfmt("NAN", "%LE", (long double)NAN); + testfmt(" nan", "%05e", NAN); + + testfmt("INF", "%E", HUGE_VAL); + testfmt("-inf", "%f", -HUGE_VAL); + testfmt("+inf", "%+g", HUGE_VAL); + testfmt(" inf", "%4.2Le", HUGE_VALL); + testfmt("-inf", "%Lf", -HUGE_VALL); + testfmt(" inf", "%05e", HUGE_VAL); + testfmt(" -inf", "%05e", -HUGE_VAL); +} + +ATF_TC_WITHOUT_HEAD(padding); +ATF_TC_BODY(padding, tc) +{ + + ATF_REQUIRE(setlocale(LC_NUMERIC, "C")); + + testfmt("0.000000e+00", "%e", 0.0); + testfmt("0.000000", "%F", (double)0.0); + testfmt("0", "%G", 0.0); + testfmt(" 0", "%3.0Lg", 0.0L); + testfmt(" 0", "%5.0f", 0.001); +} + +ATF_TC_WITHOUT_HEAD(precision_specifiers); +ATF_TC_BODY(precision_specifiers, tc) +{ + + ATF_REQUIRE(setlocale(LC_NUMERIC, "C")); + + testfmt("1.0123e+00", "%.4e", 1.0123456789); + testfmt("1.0123", "%.4f", 1.0123456789); + testfmt("1.012", "%.4g", 1.0123456789); + testfmt("1.2346e-02", "%.4e", 0.0123456789); + testfmt("0.0123", "%.4f", 0.0123456789); + testfmt("0.01235", "%.4g", 0.0123456789); +} + +ATF_TC_WITHOUT_HEAD(thousands_separator_and_other_locale_tests); +ATF_TC_BODY(thousands_separator_and_other_locale_tests, tc) +{ + + ATF_REQUIRE(setlocale(LC_NUMERIC, "C")); + + testfmt("12345678.0625", "%'.04f", 12345678.0625); + testfmt("0012345678.0625", "%'015.4F", 12345678.0625); + + ATF_REQUIRE(setlocale(LC_NUMERIC, "hi_IN.ISCII-DEV")); /* grouping == 2;3 */ + testfmt("1,23,45,678.0625", "%'.4f", 12345678.0625); + testfmt("01,23,45,678.0625", "%'017.4F", 12345678.0625); + testfmt(" 9,000", "%'6.0f", 9000.0); + testfmt("9,000.0", "%'.1f", 9000.0); + + ATF_REQUIRE(setlocale(LC_NUMERIC, "ru_RU.ISO8859-5")); /* decimalpoint==, */ + testfmt("3,1415", "%g", 3.1415); + + /* thousands=. decimalpoint=, grouping=3;3 */ + ATF_REQUIRE(setlocale(LC_NUMERIC, "el_GR.ISO8859-7")); /* decimalpoint==, */ + testfmt("1.234,00", "%'.2f", 1234.00); + testfmt("123.456,789", "%'.3f", 123456.789); + + ATF_REQUIRE(setlocale(LC_NUMERIC, "C")); + testfmt("12345678.062500", "%'f", 12345678.0625); + testfmt("9000.000000", "%'f", 9000.0); +} + +ATF_TC_WITHOUT_HEAD(signed_conversions); +ATF_TC_BODY(signed_conversions, tc) +{ + + ATF_REQUIRE(setlocale(LC_NUMERIC, "C")); + + testfmt("+2.500000e-01", "%+e", 0.25); + testfmt("+0.000000", "%+F", 0.0); + testfmt("-1", "%+g", -1.0); + + testfmt("-1.000000e+00", "% e", -1.0); + testfmt("+1.000000", "% +f", 1.0); + testfmt(" 1", "% g", 1.0); + testfmt(" 0", "% g", 0.0); +} + +ATF_TC_WITHOUT_HEAD(alternate_form); +ATF_TC_BODY(alternate_form, tc) +{ + + ATF_REQUIRE(setlocale(LC_NUMERIC, "C")); + + testfmt("1.250e+00", "%#.3e", 1.25); + testfmt("123.000000", "%#f", 123.0); + testfmt(" 12345.", "%#7.5g", 12345.0); + testfmt(" 1.00000", "%#8g", 1.0); + testfmt("0.0", "%#.2g", 0.0); +} + +ATF_TC_WITHOUT_HEAD(padding_and_decimal_point_placement); +ATF_TC_BODY(padding_and_decimal_point_placement, tc) +{ + + ATF_REQUIRE(setlocale(LC_NUMERIC, "C")); + + testfmt("03.2E+00", "%08.1E", 3.25); + testfmt("003.25", "%06.2F", 3.25); + testfmt("0003.25", "%07.4G", 3.25); + + testfmt("3.14159e-05", "%g", 3.14159e-5); + testfmt("0.000314159", "%g", 3.14159e-4); + testfmt("3.14159e+06", "%g", 3.14159e6); + testfmt("314159", "%g", 3.14159e5); + testfmt("314159.", "%#g", 3.14159e5); + + testfmt(" 9.000000e+03", "%13e", 9000.0); + testfmt(" 9000.000000", "%12f", 9000.0); + testfmt(" 9000", "%5g", 9000.0); + testfmt(" 900000.", "%#8g", 900000.0); + testfmt(" 9e+06", "%6g", 9000000.0); + testfmt(" 9.000000e-04", "%13e", 0.0009); + testfmt(" 0.000900", "%9f", 0.0009); + testfmt(" 0.0009", "%7g", 0.0009); + testfmt(" 9e-05", "%6g", 0.00009); + testfmt(" 9.00000e-05", "%#12g", 0.00009); + testfmt(" 9.e-05", "%#7.1g", 0.00009); + + testfmt(" 0.0", "%4.1f", 0.0); + testfmt("90.0", "%4.1f", 90.0); + testfmt(" 100", "%4.0f", 100.0); + testfmt("9.0e+01", "%4.1e", 90.0); + testfmt("1e+02", "%4.0e", 100.0); +} + +ATF_TC_WITHOUT_HEAD(decimal_rounding); +ATF_TC_BODY(decimal_rounding, tc) +{ + + ATF_REQUIRE(setlocale(LC_NUMERIC, "C")); + + fesetround(FE_DOWNWARD); + testfmt("4.437", "%.3f", 4.4375); + testfmt("-4.438", "%.3f", -4.4375); + testfmt("4.437", "%.3Lf", 4.4375L); + testfmt("-4.438", "%.3Lf", -4.4375L); + + fesetround(FE_UPWARD); + testfmt("4.438", "%.3f", 4.4375); + testfmt("-4.437", "%.3f", -4.4375); + testfmt("4.438", "%.3Lf", 4.4375L); + testfmt("-4.437", "%.3Lf", -4.4375L); + + fesetround(FE_TOWARDZERO); + testfmt("4.437", "%.3f", 4.4375); + testfmt("-4.437", "%.3f", -4.4375); + testfmt("4.437", "%.3Lf", 4.4375L); + testfmt("-4.437", "%.3Lf", -4.4375L); + + fesetround(FE_TONEAREST); + testfmt("4.438", "%.3f", 4.4375); + testfmt("-4.438", "%.3f", -4.4375); + testfmt("4.438", "%.3Lf", 4.4375L); + testfmt("-4.438", "%.3Lf", -4.4375L); +} + +ATF_TC_WITHOUT_HEAD(hexadecimal_floating_point); +ATF_TC_BODY(hexadecimal_floating_point, tc) +{ + + ATF_REQUIRE(setlocale(LC_NUMERIC, "C")); + + /* + * Hexadecimal floating point (%a, %A) tests. Some of these + * are only valid if the implementation converts to hex digits + * on nibble boundaries. + */ + testfmt("0x0p+0", "%a", 0x0.0p0); + testfmt("0X0.P+0", "%#LA", 0x0.0p0L); + testfmt("inf", "%La", (long double)INFINITY); + testfmt("+INF", "%+A", INFINITY); + testfmt("nan", "%La", (long double)NAN); + testfmt("NAN", "%A", NAN); + + testfmt(" 0x1.23p+0", "%10a", 0x1.23p0); + testfmt(" 0x1.23p-500", "%12a", 0x1.23p-500); + testfmt(" 0x1.2p+40", "%10.1a", 0x1.23p40); + testfmt(" 0X1.230000000000000000000000P-4", "%32.24A", 0x1.23p-4); + testfmt("0x1p-1074", "%a", 0x1p-1074); + testfmt("0x1.2345p-1024", "%a", 0x1.2345p-1024); + +#if (LDBL_MANT_DIG == 64) && !defined(__i386__) + testfmt("0x1.921fb54442d18468p+1", "%La", 0x3.243f6a8885a308dp0L); + testfmt("0x1p-16445", "%La", 0x1p-16445L); + testfmt("0x1.30ecap-16381", "%La", 0x9.8765p-16384L); +#elif (LDBL_MANT_DIG == 113) + testfmt("0x1.921fb54442d18469898cc51701b8p+1", "%La", + 0x3.243f6a8885a308d313198a2e037p0L); + testfmt("0x1p-16494", "%La", 0x1p-16494L); + testfmt("0x1.2345p-16384", "%La", 0x1.2345p-16384L); +#else + testfmt("0x1.921fb54442d18p+1", "%La", 0x3.243f6a8885a31p0L); + testfmt("0x1p-1074", "%La", 0x1p-1074L); + testfmt("0x1.30ecap-1021", "%La", 0x9.8765p-1024L); +#endif +} + +ATF_TC_WITHOUT_HEAD(hexadecimal_rounding); +ATF_TC_BODY(hexadecimal_rounding, tc) +{ + + ATF_REQUIRE(setlocale(LC_NUMERIC, "C")); + + fesetround(FE_TOWARDZERO); + testfmt("0X1.23456789ABCP+0", "%.11A", 0x1.23456789abcdep0); + testfmt("-0x1.23456p+0", "%.5a", -0x1.23456789abcdep0); + testfmt("0x1.23456p+0", "%.5a", 0x1.23456789abcdep0); + testfmt("0x1.234567p+0", "%.6a", 0x1.23456789abcdep0); + testfmt("-0x1.234566p+0", "%.6a", -0x1.23456689abcdep0); + + fesetround(FE_DOWNWARD); + testfmt("0X1.23456789ABCP+0", "%.11A", 0x1.23456789abcdep0); + testfmt("-0x1.23457p+0", "%.5a", -0x1.23456789abcdep0); + testfmt("0x1.23456p+0", "%.5a", 0x1.23456789abcdep0); + testfmt("0x1.234567p+0", "%.6a", 0x1.23456789abcdep0); + testfmt("-0x1.234567p+0", "%.6a", -0x1.23456689abcdep0); + + fesetround(FE_UPWARD); + testfmt("0X1.23456789ABDP+0", "%.11A", 0x1.23456789abcdep0); + testfmt("-0x1.23456p+0", "%.5a", -0x1.23456789abcdep0); + testfmt("0x1.23457p+0", "%.5a", 0x1.23456789abcdep0); + testfmt("0x1.234568p+0", "%.6a", 0x1.23456789abcdep0); + testfmt("-0x1.234566p+0", "%.6a", -0x1.23456689abcdep0); + + fesetround(FE_TONEAREST); + testfmt("0x1.23456789abcdep+4", "%a", 0x1.23456789abcdep4); + testfmt("0X1.23456789ABDP+0", "%.11A", 0x1.23456789abcdep0); + testfmt("-0x1.23456p+0", "%.5a", -0x1.23456789abcdep0); + testfmt("0x1.23456p+0", "%.5a", 0x1.23456789abcdep0); + testfmt("0x1.234568p+0", "%.6a", 0x1.23456789abcdep0); + testfmt("-0x1.234567p+0", "%.6a", -0x1.23456689abcdep0); + testfmt("0x1.00p-1029", "%.2a", 0x1.fffp-1030); + testfmt("0x1.00p-1026", "%.2a", 0xf.fffp-1030); + testfmt("0x1.83p+0", "%.2a", 1.51); +} + +ATF_TP_ADD_TCS(tp) +{ + + ATF_TP_ADD_TC(tp, float_within_limits); + ATF_TP_ADD_TC(tp, infinities_and_nans); + ATF_TP_ADD_TC(tp, padding); + ATF_TP_ADD_TC(tp, precision_specifiers); + ATF_TP_ADD_TC(tp, thousands_separator_and_other_locale_tests); + ATF_TP_ADD_TC(tp, signed_conversions); + ATF_TP_ADD_TC(tp, alternate_form); + ATF_TP_ADD_TC(tp, padding_and_decimal_point_placement); + ATF_TP_ADD_TC(tp, decimal_rounding); + ATF_TP_ADD_TC(tp, hexadecimal_floating_point); + ATF_TP_ADD_TC(tp, hexadecimal_rounding); + + return (atf_no_error()); +} diff --git a/lib/libc/tests/stdio/scanfloat_test.c b/lib/libc/tests/stdio/scanfloat_test.c new file mode 100644 index 0000000..7e27e69 --- /dev/null +++ b/lib/libc/tests/stdio/scanfloat_test.c @@ -0,0 +1,316 @@ +/*- + * Copyright (C) 2003, 2005 David Schultz <das@FreeBSD.org> + * 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. + */ + +/* + * Test for scanf() floating point formats. + */ + +#include <sys/cdefs.h> +__FBSDID("$FreeBSD$"); + +#include <fenv.h> +#include <float.h> +#include <locale.h> +#include <math.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +#include <atf-c.h> + +#define eq(type, a, b) _eq(type##_EPSILON, (a), (b)) +static int +_eq(long double epsilon, long double a, long double b) +{ + long double delta; + + delta = fabsl(a - b); + return (delta <= epsilon); +} + +ATF_TC_WITHOUT_HEAD(normalized_numbers); +ATF_TC_BODY(normalized_numbers, tc) +{ + char buf[128]; + long double ld = 0.0; + double d = 0.0; + float f = 0.0; + + buf[0] = '\0'; + ATF_REQUIRE(setlocale(LC_NUMERIC, "")); + + sscanf("3.141592", "%e", &f); + ATF_REQUIRE(eq(FLT, f, 3.141592)); + + sscanf("3.141592653589793", "%lf", &d); + ATF_REQUIRE(eq(DBL, d, 3.141592653589793)); + + sscanf("1.234568e+06", "%E", &f); + ATF_REQUIRE(eq(FLT, f, 1.234568e+06)); + + sscanf("-1.234568e6", "%lF", &d); + ATF_REQUIRE(eq(DBL, d, -1.234568e6)); + + sscanf("+1.234568e-52", "%LG", &ld); + ATF_REQUIRE(eq(LDBL, ld, 1.234568e-52L)); + + sscanf("0.1", "%la", &d); + ATF_REQUIRE(eq(DBL, d, 0.1)); + + sscanf("00.2", "%lA", &d); + ATF_REQUIRE(eq(DBL, d, 0.2)); + + sscanf("123456", "%5le%s", &d, buf); + ATF_REQUIRE(eq(DBL, d, 12345.)); + ATF_REQUIRE(strcmp(buf, "6") == 0); + + sscanf("1.0Q", "%*5le%s", buf); + ATF_REQUIRE(strcmp(buf, "Q") == 0); + + sscanf("-1.23e", "%e%s", &f, buf); + ATF_REQUIRE(eq(FLT, f, -1.23)); + ATF_REQUIRE(strcmp(buf, "e") == 0); + + sscanf("1.25e+", "%le%s", &d, buf); + ATF_REQUIRE(eq(DBL, d, 1.25)); + ATF_REQUIRE(strcmp(buf, "e+") == 0); + + sscanf("1.23E4E5", "%le%s", &d, buf); + ATF_REQUIRE(eq(DBL, d, 1.23e4)); + ATF_REQUIRE(strcmp(buf, "E5") == 0); + + sscanf("12e6", "%le", &d); + ATF_REQUIRE(eq(DBL, d, 12e6)); + + sscanf("1.a", "%le%s", &d, buf); + ATF_REQUIRE(eq(DBL, d, 1.0)); + ATF_REQUIRE(strcmp(buf, "a") == 0); + + sscanf(".0p4", "%le%s", &d, buf); + ATF_REQUIRE(eq(DBL, d, 0.0)); + ATF_REQUIRE(strcmp(buf, "p4") == 0); + + d = 0.25; + ATF_REQUIRE(sscanf(".", "%le", &d) == 0); + ATF_REQUIRE(d == 0.25); + + sscanf("0x08", "%le", &d); + ATF_REQUIRE(d == 0x8p0); + + sscanf("0x90a.bcdefP+09a", "%le%s", &d, buf); + ATF_REQUIRE(d == 0x90a.bcdefp+09); + ATF_REQUIRE(strcmp(buf, "a") == 0); + +#if (LDBL_MANT_DIG > DBL_MANT_DIG) && !defined(__i386__) + sscanf("3.14159265358979323846", "%Lg", &ld); + ATF_REQUIRE(eq(LDBL, ld, 3.14159265358979323846L)); + + sscanf(" 0X.0123456789abcdefffp-3g", "%Le%s", &ld, buf); + ATF_REQUIRE(ld == 0x0.0123456789abcdefffp-3L); + ATF_REQUIRE(strcmp(buf, "g") == 0); +#endif + + sscanf("0xg", "%le%s", &d, buf); + ATF_REQUIRE(d == 0.0); + ATF_REQUIRE(strcmp(buf, "xg") == 0); + + ATF_REQUIRE(setlocale(LC_NUMERIC, "ru_RU.ISO8859-5")); /* decimalpoint==, */ + + sscanf("1.23", "%le%s", &d, buf); + ATF_REQUIRE(d == 1.0); + ATF_REQUIRE(strcmp(buf, ".23") == 0); + + sscanf("1,23", "%le", &d); + ATF_REQUIRE(d == 1.23); + + ATF_REQUIRE(setlocale(LC_NUMERIC, "")); +} + +ATF_TC_WITHOUT_HEAD(infinities_and_nans); +ATF_TC_BODY(infinities_and_nans, tc) +{ + char buf[128]; + long double ld = 0.0; + double d = 0.0; + float f = 0.0; + + ATF_REQUIRE(setlocale(LC_NUMERIC, "C")); + + sscanf("-Inf", "%le", &d); + ATF_REQUIRE(d < 0.0 && isinf(d)); + + sscanf("iNfInItY and beyond", "%le%s", &d, buf); + ATF_REQUIRE(d > 0.0 && isinf(d)); + ATF_REQUIRE(strcmp(buf, " and beyond")); + + sscanf("NaN", "%le", &d); + ATF_REQUIRE(isnan(d)); + + sscanf("NAN(123Y", "%le%s", &d, buf); + ATF_REQUIRE(isnan(d)); + ATF_REQUIRE(strcmp(buf, "(123Y") == 0); + + sscanf("nan(f00f)plugh", "%le%s", &d, buf); + ATF_REQUIRE(isnan(d)); + ATF_REQUIRE(strcmp(buf, "plugh") == 0); + + sscanf("-nan", "%le", &d); + ATF_REQUIRE(isnan(d)); + + /* Only quiet NaNs should be returned. */ + sscanf("NaN", "%e", &f); + sscanf("nan", "%le", &d); + sscanf("nan", "%Le", &ld); + feclearexcept(FE_ALL_EXCEPT); + ATF_REQUIRE(f != f); + ATF_REQUIRE(d != d); + ATF_REQUIRE(ld != ld); + ATF_REQUIRE(fetestexcept(FE_INVALID) == 0); + sscanf("nan(1234)", "%e", &f); + sscanf("nan(1234)", "%le", &d); + sscanf("nan(1234)", "%Le", &ld); + feclearexcept(FE_ALL_EXCEPT); + ATF_REQUIRE(f != f); + ATF_REQUIRE(d != d); + ATF_REQUIRE(ld != ld); + /* POSIX says we should only generate quiet NaNs. */ + ATF_REQUIRE(fetestexcept(FE_INVALID) == 0); +} + +ATF_TC_WITHOUT_HEAD(rounding_tests); +ATF_TC_BODY(rounding_tests, tc) +{ + long double ld = 0.0; + double d = 0.0; + + ATF_REQUIRE(setlocale(LC_NUMERIC, "C")); + + fesetround(FE_DOWNWARD); + + sscanf("1.999999999999999999999999999999999", "%le", &d); + ATF_REQUIRE(d < 2.0); + sscanf("0x1.ffffffffffffffp0", "%le", &d); + ATF_REQUIRE(d < 2.0); + sscanf("1.999999999999999999999999999999999", "%Le", &ld); + ATF_REQUIRE(ld < 2.0); + + sscanf("1.0571892669084007", "%le", &d); + ATF_REQUIRE(d == 0x1.0ea3f4af0dc59p0); + sscanf("-1.0571892669084007", "%le", &d); + ATF_REQUIRE(d == -0x1.0ea3f4af0dc5ap0); + sscanf("1.0571892669084010", "%le", &d); + ATF_REQUIRE(d == 0x1.0ea3f4af0dc5ap0); + + sscanf("0x1.23p-5000", "%le", &d); + ATF_REQUIRE(d == 0.0); + + sscanf("0x1.2345678p-1050", "%le", &d); + ATF_REQUIRE(d == 0x1.234567p-1050); + + fesetround(FE_UPWARD); + + sscanf("1.0571892669084007", "%le", &d); + ATF_REQUIRE(d == 0x1.0ea3f4af0dc5ap0); + sscanf("-1.0571892669084007", "%le", &d); + ATF_REQUIRE(d == -0x1.0ea3f4af0dc59p0); + sscanf("1.0571892669084010", "%le", &d); + ATF_REQUIRE(d == 0x1.0ea3f4af0dc5bp0); + + sscanf("0x1.23p-5000", "%le", &d); + ATF_REQUIRE(d == 0x1p-1074); + + sscanf("0x1.2345678p-1050", "%le", &d); + ATF_REQUIRE(d == 0x1.234568p-1050); + + fesetround(FE_TOWARDZERO); + + sscanf("1.0571892669084007", "%le", &d); + ATF_REQUIRE(d == 0x1.0ea3f4af0dc59p0); + sscanf("-1.0571892669084007", "%le", &d); + ATF_REQUIRE(d == -0x1.0ea3f4af0dc59p0); + sscanf("1.0571892669084010", "%le", &d); + ATF_REQUIRE(d == 0x1.0ea3f4af0dc5ap0); + + sscanf("0x1.23p-5000", "%le", &d); + ATF_REQUIRE(d == 0.0); + + sscanf("0x1.2345678p-1050", "%le", &d); + ATF_REQUIRE(d == 0x1.234567p-1050); + + fesetround(FE_TONEAREST); + + /* 1.0571892669084007 is slightly closer to 0x1.0ea3f4af0dc59p0 */ + sscanf("1.0571892669084007", "%le", &d); + ATF_REQUIRE(d == 0x1.0ea3f4af0dc59p0); + sscanf("-1.0571892669084007", "%le", &d); + ATF_REQUIRE(d == -0x1.0ea3f4af0dc59p0); + sscanf("1.0571892669084010", "%le", &d); + ATF_REQUIRE(d == 0x1.0ea3f4af0dc5bp0); + + /* strtod() should round small numbers to 0. */ + sscanf("0x1.23p-5000", "%le", &d); + ATF_REQUIRE(d == 0.0); + + /* Extra digits in a denormal shouldn't break anything. */ + sscanf("0x1.2345678p-1050", "%le", &d); + ATF_REQUIRE(d == 0x1.234568p-1050); +} + +ATF_TC_WITHOUT_HEAD(strtod); +ATF_TC_BODY(strtod, tc) +{ + char *endp; + + ATF_REQUIRE(setlocale(LC_NUMERIC, "C")); + + ATF_REQUIRE(strtod("0xy", &endp) == 0); + ATF_REQUIRE(strcmp("xy", endp) == 0); + + /* This used to cause an infinite loop and round the wrong way. */ + fesetround(FE_DOWNWARD); + ATF_REQUIRE(strtof("3.5e38", &endp) == FLT_MAX); + ATF_REQUIRE(strtod("2e308", &endp) == DBL_MAX); + fesetround(FE_UPWARD); + ATF_REQUIRE(strtof("3.5e38", &endp) == INFINITY); + ATF_REQUIRE(strtod("2e308", &endp) == INFINITY); + fesetround(FE_TOWARDZERO); + ATF_REQUIRE(strtof("3.5e38", &endp) == FLT_MAX); + ATF_REQUIRE(strtod("2e308", &endp) == DBL_MAX); + fesetround(FE_TONEAREST); + ATF_REQUIRE(strtof("3.5e38", &endp) == INFINITY); + ATF_REQUIRE(strtod("2e308", &endp) == INFINITY); +} + +ATF_TP_ADD_TCS(tp) +{ + + ATF_TP_ADD_TC(tp, normalized_numbers); + ATF_TP_ADD_TC(tp, infinities_and_nans); + ATF_TP_ADD_TC(tp, rounding_tests); + ATF_TP_ADD_TC(tp, strtod); + + return (atf_no_error()); +} diff --git a/lib/libc/tests/stdlib/Makefile b/lib/libc/tests/stdlib/Makefile index 187ca5b..cd2c06e 100644 --- a/lib/libc/tests/stdlib/Makefile +++ b/lib/libc/tests/stdlib/Makefile @@ -1,9 +1,11 @@ # $FreeBSD$ -.include <bsd.own.mk> +ATF_TESTS_C+= heapsort_test +ATF_TESTS_C+= mergesort_test +ATF_TESTS_C+= qsort_test # TODO: t_getenv_thread, t_mi_vector_hash -NETBSD_ATF_TESTS_C= abs_test +NETBSD_ATF_TESTS_C+= abs_test NETBSD_ATF_TESTS_C+= atoi_test NETBSD_ATF_TESTS_C+= div_test NETBSD_ATF_TESTS_C+= getenv_test @@ -28,6 +30,8 @@ BINDIR= ${TESTSDIR} #PROGS+= h_atexit PROGS+= h_getopt h_getopt_long +CFLAGS+= -I${.CURDIR} + .for t in h_getopt h_getopt_long CFLAGS.$t+= -I${LIBNETBSD_SRCDIR} -I${SRCTOP}/contrib/netbsd-tests LDFLAGS.$t+= -L${LIBNETBSD_OBJDIR} diff --git a/lib/libc/tests/stdlib/heapsort_test.c b/lib/libc/tests/stdlib/heapsort_test.c new file mode 100644 index 0000000..a83786d --- /dev/null +++ b/lib/libc/tests/stdlib/heapsort_test.c @@ -0,0 +1,71 @@ +/*- + * Copyright (C) 2004 Maxim Sobolev <sobomax@FreeBSD.org> + * 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. + */ + +/* + * Test for heapsort() routine. + */ + +#include <sys/cdefs.h> +__FBSDID("$FreeBSD$"); + +#include <assert.h> +#include <stdio.h> +#include <stdlib.h> + +#include "test-sort.h" + +ATF_TC_WITHOUT_HEAD(heapsort_test); +ATF_TC_BODY(heapsort_test, tc) +{ + int sresvector[IVEC_LEN]; + int testvector[IVEC_LEN]; + int i, j; + + for (j = 2; j < IVEC_LEN; j++) { + /* Populate test vectors */ + for (i = 0; i < j; i++) + testvector[i] = sresvector[i] = initvector[i]; + + /* Sort using heapsort(3) */ + heapsort(testvector, j, sizeof(testvector[0]), sorthelp); + /* Sort using reference slow sorting routine */ + ssort(sresvector, j); + + /* Compare results */ + for (i = 0; i < j; i++) + ATF_CHECK_MSG(testvector[i] == sresvector[i], + "item at index %d didn't match: %d != %d", + i, testvector[i], sresvector[i]); + } +} + +ATF_TP_ADD_TCS(tp) +{ + + ATF_TP_ADD_TC(tp, heapsort_test); + + return (atf_no_error()); +} diff --git a/lib/libc/tests/stdlib/mergesort_test.c b/lib/libc/tests/stdlib/mergesort_test.c new file mode 100644 index 0000000..4334b92 --- /dev/null +++ b/lib/libc/tests/stdlib/mergesort_test.c @@ -0,0 +1,71 @@ +/*- + * Copyright (C) 2004 Maxim Sobolev <sobomax@FreeBSD.org> + * 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. + */ + +/* + * Test for mergesort() routine. + */ + +#include <sys/cdefs.h> +__FBSDID("$FreeBSD$"); + +#include <assert.h> +#include <stdio.h> +#include <stdlib.h> + +#include "test-sort.h" + +ATF_TC_WITHOUT_HEAD(mergesort_test); +ATF_TC_BODY(mergesort_test, tc) +{ + int sresvector[IVEC_LEN]; + int testvector[IVEC_LEN]; + int i, j; + + for (j = 2; j < IVEC_LEN; j++) { + /* Populate test vectors */ + for (i = 0; i < j; i++) + testvector[i] = sresvector[i] = initvector[i]; + + /* Sort using mergesort(3) */ + mergesort(testvector, j, sizeof(testvector[0]), sorthelp); + /* Sort using reference slow sorting routine */ + ssort(sresvector, j); + + /* Compare results */ + for (i = 0; i < j; i++) + ATF_CHECK_MSG(testvector[i] == sresvector[i], + "item at index %d didn't match: %d != %d", + i, testvector[i], sresvector[i]); + } +} + +ATF_TP_ADD_TCS(tp) +{ + + ATF_TP_ADD_TC(tp, mergesort_test); + + return (atf_no_error()); +} diff --git a/lib/libc/tests/stdlib/qsort_test.c b/lib/libc/tests/stdlib/qsort_test.c new file mode 100644 index 0000000..14e0292 --- /dev/null +++ b/lib/libc/tests/stdlib/qsort_test.c @@ -0,0 +1,71 @@ +/*- + * Copyright (C) 2004 Maxim Sobolev <sobomax@FreeBSD.org> + * 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. + */ + +/* + * Test for qsort() routine. + */ + +#include <sys/cdefs.h> +__FBSDID("$FreeBSD$"); + +#include <assert.h> +#include <stdio.h> +#include <stdlib.h> + +#include "test-sort.h" + +ATF_TC_WITHOUT_HEAD(qsort_test); +ATF_TC_BODY(qsort_test, tc) +{ + int testvector[IVEC_LEN]; + int sresvector[IVEC_LEN]; + int i, j; + + for (j = 2; j < IVEC_LEN; j++) { + /* Populate test vectors */ + for (i = 0; i < j; i++) + testvector[i] = sresvector[i] = initvector[i]; + + /* Sort using qsort(3) */ + qsort(testvector, j, sizeof(testvector[0]), sorthelp); + /* Sort using reference slow sorting routine */ + ssort(sresvector, j); + + /* Compare results */ + for (i = 0; i < j; i++) + ATF_CHECK_MSG(testvector[i] == sresvector[i], + "item at index %d didn't match: %d != %d", + i, testvector[i], sresvector[i]); + } +} + +ATF_TP_ADD_TCS(tp) +{ + + ATF_TP_ADD_TC(tp, qsort_test); + + return (atf_no_error()); +} diff --git a/lib/libc/tests/stdlib/test-sort.h b/lib/libc/tests/stdlib/test-sort.h new file mode 100644 index 0000000..f038acd --- /dev/null +++ b/lib/libc/tests/stdlib/test-sort.h @@ -0,0 +1,273 @@ +/*- + * Copyright (C) 2004 Maxim Sobolev <sobomax@FreeBSD.org> + * 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$ + */ + +#ifndef _TEST_SORT_H +#define _TEST_SORT_H + +#include <sys/param.h> + +#include <atf-c.h> + +static int +sorthelp(const void *a, const void *b) +{ + const int *oa, *ob; + + oa = a; + ob = b; + /* Don't use "return *oa - *ob" since it's easy to cause overflow! */ + if (*oa > *ob) + return (1); + if (*oa < *ob) + return (-1); + return (0); +} + +/* Reference sorting routine (slooow!) */ +static void +ssort(int v[], int nmemb) +{ + int i, j, k; + + for (i = 0; i < nmemb; i++) { + for (j = i + 1; j < nmemb; j++) { + if (v[j] < v[i]) { + k = v[i]; + v[i] = v[j]; + v[j] = k; + } + } + } +} + +/* Some random data */ +static int initvector[1024] = { + 599853225, 371951333, -428880425, 1450668530, 85530178, -460170550, + -270680269, 717137591, 106244401, -1138072905, -113532586, + 599690958, 464993720, 107690177, 24249019, -1151018550, 794225588, + 1494905642, -62951716, -734531757, 1197251494, 1020063925, + -634536734, -216634704, 617366508, -18840190, 481010395, + -1555785724, 128221950, -1747743676, 1119012320, -252160437, + 617137855, 1159833073, -106647920, -1570719046, -769400990, + -130308848, 1186546396, 215253591, 445832488, 160263176, 777264170, + -274636650, -696134447, 1057957088, -626175254, 188632134, + -98941793, -1602334908, -373717125, 885013862, 571258221, + -399572192, 407761463, -733249776, 12094800, -367046815, 178974501, + -452638559, -516580143, -94282073, 1411115180, -1151792797, + 1442815268, 1106583674, 515269284, -74019972, 598818901, 696848474, + -657910766, -287309335, 1538095746, 143543003, 851444033, + -947573348, 296222973, 1339592140, -947505360, 872027891, + -418844714, -583075597, -324758197, -964531573, 1016795914, + -866842580, -304084402, -286930819, 338975583, 803597943, + -452483372, 1525283506, -1185830826, -596405894, 905191340, + -1638026278, 106749913, 582771197, -730713796, 56052422, + 1498040174, 644967266, 182541575, 280483468, -1932835017, + -435546874, 940106007, 1753388509, -340355019, -231577358, + -714879035, 1051182949, 204261785, 1321346243, -895289878, + -240369893, 566608506, -350777580, -1384849829, -876816409, + 1013787299, -1408035937, -222626650, 1708168486, -645148461, + 1854654, -393012507, 179327030, -1607975548, -715202732, 730588290, + 246968517, -550975254, -101136772, -174103176, 1188941016, + 2004650834, -1501389866, -2021225998, 1219042515, -464113898, + 268565342, 126451123, -1045877126, -198918003, 310177444, + 1578314812, 1828867082, 453336898, -908485523, 749777130, + -1028565802, 61360571, 241484853, -175693399, 1816211059, + 533940889, -1496933703, 385185125, -821132413, -8923391, + -1429546239, 46190992, 449247332, -20432494, 778761611, -178782699, + -811194695, -632276211, 70196094, 890817525, -1447776908, + -323783741, -62333222, 954929503, 247668507, -1394420605, + 367913886, 1364926759, 1298781924, 357923028, -73644747, + -319744305, 61718202, -1454549286, 387493522, 2018321449, + 861026653, 289973298, 1755939093, -84772204, 43425266, -1325753781, + -679938775, 1228500370, -763816405, 548903035, 1765563727, + 425183052, 1424621863, -188287424, 554385654, 751831998, + 1377088085, 66622090, 139224450, -1305816167, 650140724, 593988868, + -444913321, 589045097, 1261428989, 101292769, -780376786, + 559307348, 1644593236, -1838606833, 53570301, -680576100, + -44969538, 268718267, -632104125, 276904628, 626299449, -11761453, + 545899086, -1027343598, -432251872, 539353494, -399575006, + -568383580, -677802882, 1296513472, 801202048, 806425805, 1983363, + 850487421, 38046173, 1535399484, 1998285544, -1301751898, + -46561973, 56545408, -1107662676, 456041145, -452923904, + -262219453, -371849200, 392524281, 1650231392, 1185585356, + 126610511, -1125389657, 1015981177, -1318481342, -213835789, + 1263484054, -654361441, 1408272041, -231555284, -1121778152, + -395512897, 332277674, -349703586, 1809474399, -223731607, + -1342224737, 736165236, 67535587, 89879082, 471445838, 423788300, + -384354470, 907475706, 154886390, -1406736539, -8558766, + -203405718, -422127884, 1048520863, 747418501, 87438975, 727668160, + -914936981, 428266976, -455742009, -949014605, 487159058, + -262526850, -309451504, -76928461, 1072951428, -1370953830, + 238231681, -1831047244, -405735199, -35941848, 469048670, + 505307987, -660553590, 876537439, -314195871, 999234339, + -1405846240, -579885695, 629067031, 863481510, -742301385, + -1723403128, -153070386, 782682839, -343111818, -877101810, + 1438467302, -319951459, -1585702508, -338381888, 484108815, + -1726935191, -749923706, 1657932127, -816151395, -566321865, + -133542331, 84961164, 598275578, 1302065347, -533098653, + -1766383037, 53169714, -464201288, 617735133, 862536123, + -141730724, -1967377125, -1023736305, -1012511106, 64484992, + -1250856831, 426409332, -355670055, -298251663, -867634978, + -776124819, 74018333, -425385214, -108004251, -1192766130, + 1294193867, -109867195, -78667637, 1164855393, -826007552, + -522528066, 1160283046, -1095276403, -1218917472, -396475366, + -77394733, -425603169, 251928357, -393559355, 1488845184, + 898455978, -773338691, -37627855, -345014717, 204298578, 209084274, + 1047080643, -414348222, 26496664, 705759824, 575149152, 604904761, + 624988690, 1446041250, 1000757225, -1354896151, 1422958189, + -1607165311, -832757521, 365074225, 1171764999, 1200795217, + -203957828, 23166236, -846818698, -547439867, -790192498, + -122123561, 914298013, 66225525, -36163174, -480698856, + -1269421818, 624641703, 254923102, 1564329013, -583609221, + -649433551, -743396069, 1182455435, 102658744, 285599336, + 692480463, -852737563, -660090184, 1374350065, 72300985, 690541659, + -1194212957, -1151816525, 157415641, 487398246, 1030153072, + 933723020, 1359181027, -1303457764, -1543773272, 774306017, + -854382652, 755485667, -864943584, -63242545, -1271480354, + 157720215, -205001173, 889984130, -581583822, -473779111, + -932136577, 735326252, 428638717, 1888884222, 561493709, + -1966427364, -1710208603, 340121869, 918894036, 927172509, + 904178436, 1476687667, 90796414, 651591731, -550913123, -42218158, + 637756529, 1091478400, 124976584, -48739309, -798898083, 393581349, + -1078624722, -789291577, 1010582542, -512317005, 1222773656, + 466454593, 1183558811, 822782663, -851624703, -850404012, + 1473672600, 852527073, 1073953362, 137635828, 936104739, -86567759, + -882563252, 1845232980, -737978404, -104703380, 149802989, + -349118325, 1479797538, 1966007488, 1254228842, 414304661, + -790805785, 31583329, -76864151, 558202855, -1447047313, 716720607, + -404224238, -54107627, 1747385914, -657407390, 202940208, + 1083067056, -532861378, 163426933, -130289277, 1301785258, + -302920320, -637947485, -644895903, -1668027530, 391890467, + -126586485, -536836984, -1154536413, -339505118, -1187229462, + -670985870, -601310813, -1350055158, -482479784, 139847714, + -253955849, 5190414, -542857077, 1175835684, -584165057, + 1132775766, -592091269, -891445655, -340995936, 736395810, + 779967964, 515095845, -1138437307, -259226729, -167820100, + -801611617, -282451622, -1313679283, -1436126694, 1258773990, + -717601098, -583559645, -1307478759, 1238647247, 1589011223, + -1029216445, -107030650, 400152690, -1349079913, 1428582247, + 21546946, 208807686, -169450574, -1086213374, -1242715198, + 669098277, 416626722, -1122525014, -1389466669, -391843085, + -56318357, 421040094, 212303518, 738666684, -1185364904, + -506192760, 646735912, -1424722633, 745226976, 1019191717, + -190891744, -310320868, -373655022, -665117060, 830760000, + 583906512, -330536027, 611092636, -321344259, -1255008904, + -777959046, -523043472, 88896910, 346062204, -163734816, 336635665, + 906060268, -128891583, 740952564, 916767203, 296514859, 198670559, + 358136672, -152253676, 12038867, -1469916749, -1020980597, + -897143313, 354240970, -97959800, 814172811, 1983363241, 264990663, + 105154676, 1060463014, 430172143, 375111946, -824526943, + -708877751, -1377442616, -236559551, 684724584, 1602131358, + -42140186, -763499840, -605167, 98575879, -376577598, 1689746083, + -777973879, -1396984691, -187780326, 281040966, 1858859521, + 158395760, 1022807978, -218458812, 811779708, 1495113833, + 1192561226, 629539535, -1365196683, -1120253162, 1091681956, + 134286445, 1172218369, -34093658, -137087343, -27869226, + -180889478, 55705436, 52362743, -1745516232, -926564477, + -513701675, -1666272054, 1457952810, 843953275, -478275722, + -1240291080, 101859661, -1606687523, 916365333, 314713310, + -22002688, 1019022641, -1171741314, -129050627, -211955813, + -1020176299, 1357865293, -609819628, 724533854, -1141449545, + 22285231, -97731145, -302329687, 191910894, -1300709885, + -644951895, 640448036, -1289009824, 1445456129, 846416471, + 1821291740, -1639640821, -712724532, -447475807, 132156847, + 258067455, 324301319, 278586969, -1544082357, 636007277, 977122066, + 127462480, 365126129, 1086276825, -432124148, 896598926, + -388550179, 273357331, -845018695, -1089465389, 384439820, + -558419772, 1476422025, 730712769, 190665059, -764968927, + -789708218, 637873581, 348429858, 1386000168, -638123594, + -842010345, -607926448, 19535163, -742771490, -18323344, 246155488, + 350409468, 1290907730, -492566468, 300358636, 501876267, 252441807, + 1233551975, -1431067042, 517177374, -1540299707, -948380761, + 1253997663, 693795998, 148707823, 152894502, 98729538, -30042824, + -563057441, 723726409, 367338961, 1395435261, 217868876, + 1220652431, 953572083, -1134905155, -734486813, -587470130, + -864647866, 1030737023, 781798521, -321076732, -460548153, + 122681678, -873728847, -1286304399, -75472885, 113390881, + -1556849198, -1070802176, 924389470, 957478910, 5974049, 709413506, + 476334647, 572869787, 776298405, -8822420, -99326499, -707855342, + -1187216303, 668038414, 262454769, -1120293198, -32011040, + 249812104, -101835410, 1082281087, -570183855, -954535179, + 1384361473, -983199686, 2017611313, 328926483, -878162849, + -1202254181, -225604951, 966898955, 247213529, -1257544612, + -197005970, -1039902730, -1947925142, 1752780907, -313410699, + -464474556, 416580338, -1063356643, -292212702, 57509168, + 1034124629, 1059212593, 468522867, 845369497, 1872717306, + -1216544764, -1419907623, 1376869956, -66585488, -1590974467, + -367070705, -1456529060, 791844031, 336217635, -1106832215, + 1476739427, -751018210, -1411671555, -1880387375, -1714242595, + 1169006474, -479442380, -892267555, -1471250266, -267888858, + 808634418, 1324777189, -585449929, 1127186951, 468768901, + -2002989138, -52352849, 186493053, 1258464606, 117157186, + 445919258, 908401949, -1112221136, 863904453, -942718649, + 796754809, -38943966, -781978872, -56814078, 1273857459, + -1781920832, 209979504, 811828269, -1150814437, 850061883, + -532968763, 252506408, -885025629, 391567580, -1295702482, + 574894420, 1462248349, 1622584325, -88443443, -1122006092, + -169758578, 456282338, -443233309, 436693483, -956563815, + -480221349, 435252860, -1114099391, 1060053979, -470893945, + -1273682879, -734596176, 639950927, -1278648701, 306274747, + -410562146, 1137869228, -1970746553, 1313830798, 1248071822, + -247297704, 1015218053, -1607348116, -261817613, -821413148, + -782942639, -628711083, 240953091, -629550668, -1584736319, + 856616893, -186759752, 197905373, 541638393, 603407919, -278480495, + 410077039, 544065371, -1509627427, 402918436, -450463799, + -131169308, 249920630, 1079548609, -927911828, 1444577689, + -353002528, -224292462, 1247795279, -790844631, -40427503, + 59829765, -332587567, 1319862109, -1261340753, 121711726, + 1342756342, -643495787, 100326201, -934436714, -69134888, + -898880561, -379524737, -577234570, -805827092, -1575493557, + -289920678, -476605057, 1235714994, -317239591, 418553949, + 410053338, -204985448, 1206503615, 202610372, -932244873, + 782207875, -288661931, -806814809, 1270953679, 2060991595, + -311412846, 327279979, 1148562672, 55239149, -610114433, + -1511688434, 87619740, -433503545, 326150519, -581293393, + -97417688, -289736140, -1543886029, -1251976119, 1585774446, + 1570011421, 432602745, 486343696, -834680922, 265004849, + -1132107706, 502627197, -815873818, 249635389, 1985714127, + -1095817653, -130743522, -645266828, -334621094, 199921747, + 1059256177, 378031303, 1519740920, 925540689, 1405957844, + 1387748290, -56138046, -770637828, -187984510, -1361735163, + 1294823206, -608941238, 451860688, -510549867, 1143516283, + -779090703, 1459305047, -600335915, -1684168049, 1516622316, + -631733335, -4360068, 499778796, 587600402, -1296000335, -37959743, + -1084203927, 1162902556, 246374600, -515103645, 341724568, + -702303954, 452229900, 485108287, 1170048553, -1510148355, + 611133912, 1997927484, -142022671, -724776653, -336090522, + 708283514, -1409637378, -2052637687, 376055110, 226628105, + -1714452033, -1776158002, 369167930, 1800807012, 710680889, + -69951947, -1223849766, -1862239787, 218536127, -656411794, + -1202269188, 609634805, -224425858, 519797951, 284223080, + 869408930, 270750206, -544967439, 2097168510, 31650971, -600985417, + -165303097, -257809088, -1043223971, 1827891621, -156827355, + 499719603 +}; + +#define IVEC_LEN (nitems(initvector)) + +#endif diff --git a/lib/libc/tests/string/Makefile b/lib/libc/tests/string/Makefile index d91af08..14044f4 100644 --- a/lib/libc/tests/string/Makefile +++ b/lib/libc/tests/string/Makefile @@ -1,31 +1,36 @@ # $FreeBSD$ -.include <bsd.own.mk> +ATF_TESTS_C+= stpncpy_test +ATF_TESTS_C+= strerror2_test +ATF_TESTS_C+= wcscasecmp_test +ATF_TESTS_C+= wcsnlen_test # TODO: popcount, stresep -NETBSD_ATF_TESTS_C+= memchr -NETBSD_ATF_TESTS_C+= memcpy -NETBSD_ATF_TESTS_C+= memmem -NETBSD_ATF_TESTS_C+= memset -NETBSD_ATF_TESTS_C+= strcat -NETBSD_ATF_TESTS_C+= strchr -NETBSD_ATF_TESTS_C+= strcmp -NETBSD_ATF_TESTS_C+= strcpy -NETBSD_ATF_TESTS_C+= strcspn -NETBSD_ATF_TESTS_C+= strerror -NETBSD_ATF_TESTS_C+= strlen -NETBSD_ATF_TESTS_C+= strpbrk -NETBSD_ATF_TESTS_C+= strrchr -NETBSD_ATF_TESTS_C+= strspn -NETBSD_ATF_TESTS_C+= swab +NETBSD_ATF_TESTS_C+= memchr_test +NETBSD_ATF_TESTS_C+= memcpy_test +NETBSD_ATF_TESTS_C+= memmem_test +NETBSD_ATF_TESTS_C+= memset_test +NETBSD_ATF_TESTS_C+= strcat_test +NETBSD_ATF_TESTS_C+= strchr_test +NETBSD_ATF_TESTS_C+= strcmp_test +NETBSD_ATF_TESTS_C+= strcpy_test +NETBSD_ATF_TESTS_C+= strcspn_test +NETBSD_ATF_TESTS_C+= strerror_test +NETBSD_ATF_TESTS_C+= strlen_test +NETBSD_ATF_TESTS_C+= strpbrk_test +NETBSD_ATF_TESTS_C+= strrchr_test +NETBSD_ATF_TESTS_C+= strspn_test +NETBSD_ATF_TESTS_C+= swab_test + +SRCS.strerror2_test= strerror_test.c .include "../Makefile.netbsd-tests" -LDADD.memchr+= -lmd -DPADD.memchr+= ${LIBMD} +LDADD.memchr_test+= -lmd +DPADD.memchr_test+= ${LIBMD} -LDADD.memcpy+= -lmd -DPADD.memcpy+= ${LIBMD} +LDADD.memcpy_test+= -lmd +DPADD.memcpy_test+= ${LIBMD} .include <bsd.test.mk> diff --git a/lib/libc/tests/string/stpncpy_test.c b/lib/libc/tests/string/stpncpy_test.c new file mode 100644 index 0000000..0a7b1d2 --- /dev/null +++ b/lib/libc/tests/string/stpncpy_test.c @@ -0,0 +1,110 @@ +/*- + * Copyright (c) 2009 David Schultz <das@FreeBSD.org> + * 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 <sys/cdefs.h> +__FBSDID("$FreeBSD$"); + +#include <sys/param.h> +#include <sys/mman.h> +#include <assert.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +#include <atf-c.h> + +static char * +makebuf(size_t len, int guard_at_end) +{ + char *buf; + size_t alloc_size = roundup2(len, PAGE_SIZE) + PAGE_SIZE; + + buf = mmap(NULL, alloc_size, PROT_READ | PROT_WRITE, MAP_ANON, -1, 0); + assert(buf); + if (guard_at_end) { + assert(munmap(buf + alloc_size - PAGE_SIZE, PAGE_SIZE) == 0); + return (buf + alloc_size - PAGE_SIZE - len); + } else { + assert(munmap(buf, PAGE_SIZE) == 0); + return (buf + PAGE_SIZE); + } +} + +static void +test_stpncpy(const char *s) +{ + char *src, *dst; + size_t size, len, bufsize, x; + int i, j; + + size = strlen(s) + 1; + for (i = 0; i <= 1; i++) { + for (j = 0; j <= 1; j++) { + for (bufsize = 0; bufsize <= size + 10; bufsize++) { + src = makebuf(size, i); + memcpy(src, s, size); + dst = makebuf(bufsize, j); + memset(dst, 'X', bufsize); + len = (bufsize < size) ? bufsize : size - 1; + assert(stpncpy(dst, src, bufsize) == dst+len); + assert(memcmp(src, dst, len) == 0); + for (x = len; x < bufsize; x++) + assert(dst[x] == '\0'); + } + } + } +} + +ATF_TC_WITHOUT_HEAD(nul); +ATF_TC_BODY(nul, tc) +{ + + test_stpncpy(""); +} + +ATF_TC_WITHOUT_HEAD(foo); +ATF_TC_BODY(foo, tc) +{ + + test_stpncpy("foo"); +} + +ATF_TC_WITHOUT_HEAD(glorp); +ATF_TC_BODY(glorp, tc) +{ + + test_stpncpy("glorp"); +} + +ATF_TP_ADD_TCS(tp) +{ + + ATF_TP_ADD_TC(tp, nul); + ATF_TP_ADD_TC(tp, foo); + ATF_TP_ADD_TC(tp, glorp); + + return (atf_no_error()); +} diff --git a/lib/libc/tests/string/strerror_test.c b/lib/libc/tests/string/strerror_test.c new file mode 100644 index 0000000..51bbf17 --- /dev/null +++ b/lib/libc/tests/string/strerror_test.c @@ -0,0 +1,206 @@ +/*- + * Copyright (c) 2001 Wes Peters <wes@FreeBSD.org> + * 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$ + */ + +#include <assert.h> +#include <errno.h> +#include <limits.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +#include <atf-c.h> + +static char buf[64]; +static char *sret; +static int iret; + +ATF_TC_WITHOUT_HEAD(strerror_unknown_error); +ATF_TC_BODY(strerror_unknown_error, tc) +{ + + errno = 0; + sret = strerror(INT_MAX); + snprintf(buf, sizeof(buf), "Unknown error: %d", INT_MAX); + ATF_CHECK(strcmp(sret, buf) == 0); + ATF_CHECK(errno == EINVAL); +} + +ATF_TC_WITHOUT_HEAD(strerror_no_error); +ATF_TC_BODY(strerror_no_error, tc) +{ + + errno = 0; + sret = strerror(0); + ATF_CHECK(strcmp(sret, "No error: 0") == 0); + ATF_CHECK(errno == 0); +} + +ATF_TC_WITHOUT_HEAD(strerror_EPERM_test); +ATF_TC_BODY(strerror_EPERM_test, tc) +{ + + errno = 0; + sret = strerror(EPERM); + ATF_CHECK(strcmp(sret, "Operation not permitted") == 0); + ATF_CHECK(errno == 0); +} + +ATF_TC_WITHOUT_HEAD(strerror_EPFNOSUPPORT_test); +ATF_TC_BODY(strerror_EPFNOSUPPORT_test, tc) +{ + + errno = 0; + sret = strerror(EPFNOSUPPORT); + ATF_CHECK(strcmp(sret, "Protocol family not supported") == 0); + ATF_CHECK(errno == 0); +} + +ATF_TC_WITHOUT_HEAD(strerror_ELAST_test); +ATF_TC_BODY(strerror_ELAST_test, tc) +{ + + errno = 0; + sret = strerror(ELAST); + ATF_CHECK(errno == 0); +} + +ATF_TC_WITHOUT_HEAD(strerror_r__unknown_error); +ATF_TC_BODY(strerror_r__unknown_error, tc) +{ + + memset(buf, '*', sizeof(buf)); + iret = strerror_r(-1, buf, sizeof(buf)); + ATF_CHECK(strcmp(buf, "Unknown error: -1") == 0); + ATF_CHECK(iret == EINVAL); +} + +ATF_TC_WITHOUT_HEAD(strerror_r__EPERM_one_byte_short); +ATF_TC_BODY(strerror_r__EPERM_one_byte_short, tc) +{ + + memset(buf, '*', sizeof(buf)); + /* One byte too short. */ + iret = strerror_r(EPERM, buf, strlen("Operation not permitted")); + ATF_CHECK(strcmp(buf, "Operation not permitte") == 0); + ATF_CHECK(iret == ERANGE); +} + +ATF_TC_WITHOUT_HEAD(strerror_r__EPERM_unknown_error_one_byte_short); +ATF_TC_BODY(strerror_r__EPERM_unknown_error_one_byte_short, tc) +{ + + memset(buf, '*', sizeof(buf)); + /* One byte too short. */ + iret = strerror_r(-1, buf, strlen("Unknown error: -1")); + ATF_CHECK(strcmp(buf, "Unknown error: -") == 0); + ATF_CHECK(iret == EINVAL); +} + +ATF_TC_WITHOUT_HEAD(strerror_r__EPERM_unknown_error_two_bytes_short); +ATF_TC_BODY(strerror_r__EPERM_unknown_error_two_bytes_short, tc) +{ + + memset(buf, '*', sizeof(buf)); + /* Two bytes too short. */ + iret = strerror_r(-2, buf, strlen("Unknown error: -2") - 1); + ATF_CHECK(strcmp(buf, "Unknown error: ") == 0); + ATF_CHECK(iret == EINVAL); +} + +ATF_TC_WITHOUT_HEAD(strerror_r__EPERM_unknown_error_three_bytes_short); +ATF_TC_BODY(strerror_r__EPERM_unknown_error_three_bytes_short, tc) +{ + + memset(buf, '*', sizeof(buf)); + /* Three bytes too short. */ + iret = strerror_r(-2, buf, strlen("Unknown error: -2") - 2); + ATF_CHECK(strcmp(buf, "Unknown error:") == 0); + ATF_CHECK(iret == EINVAL); +} + +ATF_TC_WITHOUT_HEAD(strerror_r__EPERM_unknown_error_12345_one_byte_short); +ATF_TC_BODY(strerror_r__EPERM_unknown_error_12345_one_byte_short, tc) +{ + + memset(buf, '*', sizeof(buf)); + /* One byte too short. */ + iret = strerror_r(12345, buf, strlen("Unknown error: 12345")); + ATF_CHECK(strcmp(buf, "Unknown error: 1234") == 0); + ATF_CHECK(iret == EINVAL); +} + +ATF_TC_WITHOUT_HEAD(strerror_r__no_error); +ATF_TC_BODY(strerror_r__no_error, tc) +{ + + memset(buf, '*', sizeof(buf)); + iret = strerror_r(0, buf, sizeof(buf)); + ATF_CHECK(strcmp(buf, "No error: 0") == 0); + ATF_CHECK(iret == 0); +} + +ATF_TC_WITHOUT_HEAD(strerror_r__EDEADLK); +ATF_TC_BODY(strerror_r__EDEADLK, tc) +{ + + memset(buf, '*', sizeof(buf)); + iret = strerror_r(EDEADLK, buf, sizeof(buf)); + ATF_CHECK(strcmp(buf, "Resource deadlock avoided") == 0); + ATF_CHECK(iret == 0); +} + +ATF_TC_WITHOUT_HEAD(strerror_r__EPROCLIM); +ATF_TC_BODY(strerror_r__EPROCLIM, tc) +{ + + memset(buf, '*', sizeof(buf)); + iret = strerror_r(EPROCLIM, buf, sizeof(buf)); + ATF_CHECK(strcmp(buf, "Too many processes") == 0); + ATF_CHECK(iret == 0); +} + +ATF_TP_ADD_TCS(tp) +{ + + ATF_TP_ADD_TC(tp, strerror_unknown_error); + ATF_TP_ADD_TC(tp, strerror_no_error); + ATF_TP_ADD_TC(tp, strerror_EPERM_test); + ATF_TP_ADD_TC(tp, strerror_EPFNOSUPPORT_test); + ATF_TP_ADD_TC(tp, strerror_ELAST_test); + ATF_TP_ADD_TC(tp, strerror_r__unknown_error); + ATF_TP_ADD_TC(tp, strerror_r__EPERM_one_byte_short); + ATF_TP_ADD_TC(tp, strerror_r__EPERM_unknown_error_one_byte_short); + ATF_TP_ADD_TC(tp, strerror_r__EPERM_unknown_error_two_bytes_short); + ATF_TP_ADD_TC(tp, strerror_r__EPERM_unknown_error_three_bytes_short); + ATF_TP_ADD_TC(tp, strerror_r__EPERM_unknown_error_12345_one_byte_short); + ATF_TP_ADD_TC(tp, strerror_r__no_error); + ATF_TP_ADD_TC(tp, strerror_r__EDEADLK); + ATF_TP_ADD_TC(tp, strerror_r__EPROCLIM); + + return (atf_no_error()); +} diff --git a/lib/libc/tests/string/wcscasecmp_test.c b/lib/libc/tests/string/wcscasecmp_test.c new file mode 100644 index 0000000..4385f3a --- /dev/null +++ b/lib/libc/tests/string/wcscasecmp_test.c @@ -0,0 +1,128 @@ +/*- + * Copyright (c) 2009 David Schultz <das@FreeBSD.org> + * 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 <sys/cdefs.h> +__FBSDID("$FreeBSD$"); + +#include <assert.h> +#include <locale.h> +#include <stdio.h> +#include <stdlib.h> +#include <wchar.h> +#include <wctype.h> + +#include <atf-c.h> + +ATF_TC_WITHOUT_HEAD(nul); +ATF_TC_BODY(nul, tc) +{ + + ATF_REQUIRE(setlocale(LC_CTYPE, "C") != NULL); + + ATF_CHECK(wcscasecmp(L"", L"") == 0); + ATF_CHECK(wcsncasecmp(L"", L"", 50) == 0); + ATF_CHECK(wcsncasecmp(L"", L"", 0) == 0); +} + +ATF_TC_WITHOUT_HEAD(wcscasecmp_equal); +ATF_TC_BODY(wcscasecmp_equal, tc) +{ + + ATF_REQUIRE(setlocale(LC_CTYPE, "C") != NULL); + + ATF_CHECK(wcscasecmp(L"abc", L"abc") == 0); + ATF_CHECK(wcscasecmp(L"ABC", L"ABC") == 0); + ATF_CHECK(wcscasecmp(L"abc", L"ABC") == 0); + ATF_CHECK(wcscasecmp(L"ABC", L"abc") == 0); +} + +ATF_TC_WITHOUT_HEAD(wcscasecmp_same_len_buffers); +ATF_TC_BODY(wcscasecmp_same_len_buffers, tc) +{ + + ATF_REQUIRE(setlocale(LC_CTYPE, "C") != NULL); + + ATF_CHECK(wcscasecmp(L"abc", L"xyz") < 0); + ATF_CHECK(wcscasecmp(L"ABC", L"xyz") < 0); + ATF_CHECK(wcscasecmp(L"abc", L"XYZ") < 0); + ATF_CHECK(wcscasecmp(L"ABC", L"XYZ") < 0); + ATF_CHECK(wcscasecmp(L"xyz", L"abc") > 0); + ATF_CHECK(wcscasecmp(L"XYZ", L"abc") > 0); + ATF_CHECK(wcscasecmp(L"xyz", L"ABC") > 0); + ATF_CHECK(wcscasecmp(L"XYZ", L"ABC") > 0); +} + +ATF_TC_WITHOUT_HEAD(wcscasecmp_mismatched_len_buffers); +ATF_TC_BODY(wcscasecmp_mismatched_len_buffers, tc) +{ + + ATF_REQUIRE(setlocale(LC_CTYPE, "C") != NULL); + + ATF_CHECK(wcscasecmp(L"abc", L"ABCD") < 0); + ATF_CHECK(wcscasecmp(L"ABC", L"abcd") < 0); + ATF_CHECK(wcscasecmp(L"abcd", L"ABC") > 0); + ATF_CHECK(wcscasecmp(L"ABCD", L"abc") > 0); +} + +ATF_TC_WITHOUT_HEAD(wcsncasecmp); +ATF_TC_BODY(wcsncasecmp, tc) +{ + + ATF_REQUIRE(setlocale(LC_CTYPE, "C") != NULL); + + ATF_CHECK(wcsncasecmp(L"abc", L"ABCD", 4) < 0); + ATF_CHECK(wcsncasecmp(L"ABC", L"abcd", 4) < 0); + ATF_CHECK(wcsncasecmp(L"abcd", L"ABC", 4) > 0); + ATF_CHECK(wcsncasecmp(L"ABCD", L"abc", 4) > 0); + ATF_CHECK(wcsncasecmp(L"abc", L"ABCD", 3) == 0); + ATF_CHECK(wcsncasecmp(L"ABC", L"abcd", 3) == 0); +} + +ATF_TC_WITHOUT_HEAD(wcscasecmp_greek); +ATF_TC_BODY(wcscasecmp_greek, tc) +{ + + ATF_REQUIRE(setlocale(LC_CTYPE, "C") != NULL); + + ATF_CHECK(wcscasecmp(L"λ", L"Λ") != 0); + ATF_REQUIRE(setlocale(LC_CTYPE, "el_GR.UTF-8") != NULL); + ATF_CHECK(wcscasecmp(L"λ", L"Λ") == 0); + ATF_CHECK(wcscasecmp(L"λ", L"Ω") < 0); + ATF_CHECK(wcscasecmp(L"Ω", L"λ") > 0); +} + +ATF_TP_ADD_TCS(tp) +{ + + ATF_TP_ADD_TC(tp, nul); + ATF_TP_ADD_TC(tp, wcscasecmp_equal); + ATF_TP_ADD_TC(tp, wcscasecmp_same_len_buffers); + ATF_TP_ADD_TC(tp, wcscasecmp_mismatched_len_buffers); + ATF_TP_ADD_TC(tp, wcsncasecmp); + ATF_TP_ADD_TC(tp, wcscasecmp_greek); + + return (atf_no_error()); +} diff --git a/lib/libc/tests/string/wcsnlen_test.c b/lib/libc/tests/string/wcsnlen_test.c new file mode 100644 index 0000000..ec11938 --- /dev/null +++ b/lib/libc/tests/string/wcsnlen_test.c @@ -0,0 +1,104 @@ +/*- + * Copyright (c) 2009 David Schultz <das@FreeBSD.org> + * 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 <sys/cdefs.h> +__FBSDID("$FreeBSD$"); + +#include <sys/param.h> +#include <sys/mman.h> +#include <assert.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <wchar.h> + +#include <atf-c.h> + +static void * +makebuf(size_t len, int guard_at_end) +{ + char *buf; + size_t alloc_size = roundup2(len, PAGE_SIZE) + PAGE_SIZE; + + buf = mmap(NULL, alloc_size, PROT_READ | PROT_WRITE, MAP_ANON, -1, 0); + ATF_CHECK(buf); + if (guard_at_end) { + ATF_CHECK(munmap(buf + alloc_size - PAGE_SIZE, PAGE_SIZE) == 0); + return (buf + alloc_size - PAGE_SIZE - len); + } else { + ATF_CHECK(munmap(buf, PAGE_SIZE) == 0); + return (buf + PAGE_SIZE); + } +} + +static void +test_wcsnlen(const wchar_t *s) +{ + wchar_t *s1; + size_t size, len, bufsize; + int i; + + size = wcslen(s) + 1; + for (i = 0; i <= 1; i++) { + for (bufsize = 0; bufsize <= size + 10; bufsize++) { + s1 = makebuf(bufsize * sizeof(wchar_t), i); + wmemcpy(s1, s, bufsize); + len = (size > bufsize) ? bufsize : size - 1; + ATF_CHECK(wcsnlen(s1, bufsize) == len); + } + } +} + +ATF_TC_WITHOUT_HEAD(nul); +ATF_TC_BODY(nul, tc) +{ + + test_wcsnlen(L""); +} + +ATF_TC_WITHOUT_HEAD(foo); +ATF_TC_BODY(foo, tc) +{ + + test_wcsnlen(L"foo"); +} + +ATF_TC_WITHOUT_HEAD(glorp); +ATF_TC_BODY(glorp, tc) +{ + + test_wcsnlen(L"glorp"); +} + +ATF_TP_ADD_TCS(tp) +{ + + ATF_TP_ADD_TC(tp, nul); + ATF_TP_ADD_TC(tp, foo); + ATF_TP_ADD_TC(tp, glorp); + + return (atf_no_error()); +} diff --git a/lib/libc/tests/tls_dso/Makefile b/lib/libc/tests/tls_dso/Makefile index b37ffec..5449799 100644 --- a/lib/libc/tests/tls_dso/Makefile +++ b/lib/libc/tests/tls_dso/Makefile @@ -1,7 +1,5 @@ # $FreeBSD$ -SRCDIR= ${SRCTOP}/contrib/netbsd/ - .include <bsd.own.mk> LIB= h_tls_dynamic |