/*-1* SPDX-License-Identifier: BSD-2-Clause2*3* Copyright 2010 Nexenta Systems, Inc. All rights reserved.4* Copyright (c) 1995 Alex Tatmanjants <[email protected]>5* at Electronni Visti IA, Kiev, Ukraine.6* All rights reserved.7*8* Copyright (c) 2011 The FreeBSD Foundation9*10* Portions of this software were developed by David Chisnall11* under sponsorship from the FreeBSD Foundation.12*13* Redistribution and use in source and binary forms, with or without14* modification, are permitted provided that the following conditions15* are met:16* 1. Redistributions of source code must retain the above copyright17* notice, this list of conditions and the following disclaimer.18* 2. Redistributions in binary form must reproduce the above copyright19* notice, this list of conditions and the following disclaimer in the20* documentation and/or other materials provided with the distribution.21*22* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND23* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE24* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE25* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE26* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL27* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS28* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)29* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT30* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY31* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF32* SUCH DAMAGE.33*/3435#include <stdlib.h>36#include <string.h>37#include <errno.h>38#include <wchar.h>39#include "collate.h"404142/*43* In order to properly handle multibyte locales, its easiest to just44* convert to wide characters and then use wcscoll. However if an45* error occurs, we gracefully fall back to simple strcmp. Caller46* should check errno.47*/48int49strcoll_l(const char *s, const char *s2, locale_t locale)50{51int ret;52wchar_t *t1 = NULL, *t2 = NULL;53wchar_t *w1 = NULL, *w2 = NULL;54const char *cs1, *cs2;55mbstate_t mbs1;56mbstate_t mbs2;57size_t sz1, sz2;5859memset(&mbs1, 0, sizeof (mbstate_t));60memset(&mbs2, 0, sizeof (mbstate_t));6162/*63* The mbsrtowcs_l function can set the src pointer to null upon64* failure, so it should act on a copy to avoid:65* - sending null pointer to strcmp66* - having strcoll/strcoll_l change *s or *s2 to null67*/68cs1 = s;69cs2 = s2;7071FIX_LOCALE(locale);72struct xlocale_collate *table =73(struct xlocale_collate*)locale->components[XLC_COLLATE];7475if (table->__collate_load_error)76goto error;7778sz1 = strlen(s) + 1;79sz2 = strlen(s2) + 1;8081/*82* Simple assumption: conversion to wide format is strictly83* reducing, i.e. a single byte (or multibyte character)84* cannot result in multiple wide characters.85*/86if ((t1 = malloc(sz1 * sizeof (wchar_t))) == NULL)87goto error;88w1 = t1;89if ((t2 = malloc(sz2 * sizeof (wchar_t))) == NULL)90goto error;91w2 = t2;9293if ((mbsrtowcs_l(w1, &cs1, sz1, &mbs1, locale)) == (size_t)-1)94goto error;9596if ((mbsrtowcs_l(w2, &cs2, sz2, &mbs2, locale)) == (size_t)-1)97goto error;9899ret = wcscoll_l(w1, w2, locale);100free(t1);101free(t2);102103return (ret);104105error:106free(t1);107free(t2);108return (strcmp(s, s2));109}110111int112strcoll(const char *s, const char *s2)113{114return strcoll_l(s, s2, __get_locale());115}116117118119