| 1 |
/*- |
| 2 |
* Copyright (c) 2006, 2008 |
| 3 |
* Thorsten Glaser <tg@mirbsd.org> |
| 4 |
* |
| 5 |
* Provided that these terms and disclaimer and all copyright notices |
| 6 |
* are retained or reproduced in an accompanying document, permission |
| 7 |
* is granted to deal in this work without restriction, including un- |
| 8 |
* limited rights to use, publicly perform, distribute, sell, modify, |
| 9 |
* merge, give away, or sublicence. |
| 10 |
* |
| 11 |
* This work is provided "AS IS" and WITHOUT WARRANTY of any kind, to |
| 12 |
* the utmost extent permitted by applicable law, neither express nor |
| 13 |
* implied; without malicious intent or gross negligence. In no event |
| 14 |
* may a licensor, author or contributor be held liable for indirect, |
| 15 |
* direct, other damage, loss, or other issues arising in any way out |
| 16 |
* of dealing in the work, even if advised of the possibility of such |
| 17 |
* damage or existence of a defect, except proven that it results out |
| 18 |
* of said person's immediate fault when using the work as intended. |
| 19 |
*- |
| 20 |
* The original implementations of strlcpy(3) and strlcat(3) are from |
| 21 |
* Todd C. Miller; the licence is reproduced below. However, this ap- |
| 22 |
* plies only to the strlcpy(3) portion of the code, as Thorsten Gla- |
| 23 |
* ser write the following strlcat(3) implementation according to the |
| 24 |
* spec. Both functions below have been optimised according to sugge- |
| 25 |
* stions from Bodo Eggert. Thorsten Glaser also has merged this code |
| 26 |
* with strxfrm(3) for ISO-10646-only systems and wrote the wide char |
| 27 |
* variants wcslcat(3), wcslcpy(3), and wcsxfrm(3) (see wcslfun.c). |
| 28 |
*/ |
| 29 |
|
| 30 |
#ifdef STRXFRM |
| 31 |
#undef HAVE_STRLCPY |
| 32 |
#undef HAVE_STRLCAT |
| 33 |
#define HAVE_STRLCPY 0 |
| 34 |
#define HAVE_STRLCAT 1 |
| 35 |
#define strlcpy strxfrm |
| 36 |
#endif |
| 37 |
|
| 38 |
#include <sys/types.h> |
| 39 |
#if defined(_KERNEL) || defined(_STANDALONE) |
| 40 |
#include <lib/libkern/libkern.h> |
| 41 |
#undef HAVE_STRLCPY |
| 42 |
#undef HAVE_STRLCAT |
| 43 |
#else |
| 44 |
#include <stddef.h> /* for size_t in user space (SUSv3) */ |
| 45 |
#if defined(HAVE_CONFIG_H) && (HAVE_CONFIG_H != 0) |
| 46 |
/* usually when packaged with third-party software */ |
| 47 |
#ifdef CONFIG_H_FILENAME |
| 48 |
#include CONFIG_H_FILENAME |
| 49 |
#else |
| 50 |
#include "config.h" |
| 51 |
#endif |
| 52 |
#endif |
| 53 |
/* do not include <string.h> to prevent redefinition warnings */ |
| 54 |
extern size_t strlen(const char *); |
| 55 |
#endif |
| 56 |
|
| 57 |
#ifndef __RCSID |
| 58 |
#undef __IDSTRING |
| 59 |
#undef __IDSTRING_CONCAT |
| 60 |
#undef __IDSTRING_EXPAND |
| 61 |
#define __IDSTRING_CONCAT(l,p) __LINTED__ ## l ## _ ## p |
| 62 |
#define __IDSTRING_EXPAND(l,p) __IDSTRING_CONCAT(l,p) |
| 63 |
#define __IDSTRING(prefix, string) \ |
| 64 |
static const char __IDSTRING_EXPAND(__LINE__,prefix) [] \ |
| 65 |
__attribute__((used)) = "@(""#)" #prefix ": " string |
| 66 |
#define __RCSID(x) __IDSTRING(rcsid,x) |
| 67 |
#endif |
| 68 |
|
| 69 |
#ifndef __predict_true |
| 70 |
#define __predict_true(exp) ((exp) != 0) |
| 71 |
#endif |
| 72 |
#ifndef __predict_false |
| 73 |
#define __predict_false(exp) ((exp) != 0) |
| 74 |
#endif |
| 75 |
|
| 76 |
#if !defined(_KERNEL) && !defined(_STANDALONE) |
| 77 |
__RCSID("$MirOS: src/lib/libc/string/strlfun.c,v 1.18 2008/08/01 12:26:17 tg Exp $"); |
| 78 |
#endif |
| 79 |
|
| 80 |
/* (multibyte) string functions */ |
| 81 |
#undef NUL |
| 82 |
#undef char_t |
| 83 |
#define NUL '\0' |
| 84 |
#define char_t char |
| 85 |
|
| 86 |
size_t strlcat(char_t *, const char_t *, size_t); |
| 87 |
size_t strlcpy(char_t *, const char_t *, size_t); |
| 88 |
|
| 89 |
#if !defined(HAVE_STRLCAT) || (HAVE_STRLCAT == 0) |
| 90 |
/* |
| 91 |
* Appends src to string dst of size dlen (unlike strncat, dlen is the |
| 92 |
* full size of dst, not space left). At most dlen-1 characters |
| 93 |
* will be copied. Always NUL terminates (unless dlen <= strlen(dst)). |
| 94 |
* Returns strlen(src) + MIN(dlen, strlen(initial dst)), without the |
| 95 |
* trailing NUL byte counted. If retval >= dlen, truncation occurred. |
| 96 |
*/ |
| 97 |
size_t |
| 98 |
strlcat(char_t *dst, const char_t *src, size_t dlen) |
| 99 |
{ |
| 100 |
size_t n = 0, slen; |
| 101 |
|
| 102 |
slen = strlen(src); |
| 103 |
while (__predict_true(n + 1 < dlen && dst[n] != NUL)) |
| 104 |
++n; |
| 105 |
if (__predict_false(dlen == 0 || dst[n] != NUL)) |
| 106 |
return (dlen + slen); |
| 107 |
while (__predict_true((slen > 0) && (n < (dlen - 1)))) { |
| 108 |
dst[n++] = *src++; |
| 109 |
--slen; |
| 110 |
} |
| 111 |
dst[n] = NUL; |
| 112 |
return (n + slen); |
| 113 |
} |
| 114 |
#endif /* !HAVE_STRLCAT */ |
| 115 |
|
| 116 |
#if !defined(HAVE_STRLCPY) || (HAVE_STRLCPY == 0) |
| 117 |
/* $OpenBSD: strlcpy.c,v 1.11 2006/05/05 15:27:38 millert Exp $ */ |
| 118 |
|
| 119 |
/*- |
| 120 |
* Copyright (c) 1998 Todd C. Miller <Todd.Miller@courtesan.com> |
| 121 |
* |
| 122 |
* Permission to use, copy, modify, and distribute this software for any |
| 123 |
* purpose with or without fee is hereby granted, provided that the above |
| 124 |
* copyright notice and this permission notice appear in all copies. |
| 125 |
* |
| 126 |
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES |
| 127 |
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF |
| 128 |
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR |
| 129 |
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES |
| 130 |
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN |
| 131 |
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF |
| 132 |
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. |
| 133 |
*/ |
| 134 |
|
| 135 |
/* |
| 136 |
* Copy src to string dst of size siz. At most siz-1 characters |
| 137 |
* will be copied. Always NUL terminates (unless siz == 0). |
| 138 |
* Returns strlen(src); if retval >= siz, truncation occurred. |
| 139 |
*/ |
| 140 |
size_t |
| 141 |
strlcpy(char_t *dst, const char_t *src, size_t siz) |
| 142 |
{ |
| 143 |
const char_t *s = src; |
| 144 |
|
| 145 |
if (__predict_false(siz == 0)) |
| 146 |
goto traverse_src; |
| 147 |
|
| 148 |
/* copy as many chars as will fit */ |
| 149 |
while (--siz && (*dst++ = *s++)) |
| 150 |
; |
| 151 |
|
| 152 |
/* not enough room in dst */ |
| 153 |
if (__predict_false(siz == 0)) { |
| 154 |
/* safe to NUL-terminate dst since we copied <= siz-1 chars */ |
| 155 |
*dst = NUL; |
| 156 |
traverse_src: |
| 157 |
/* traverse rest of src */ |
| 158 |
while (*s++) |
| 159 |
; |
| 160 |
} |
| 161 |
|
| 162 |
/* count does not include NUL */ |
| 163 |
return (s - src - 1); |
| 164 |
} |
| 165 |
#endif /* !HAVE_STRLCPY */ |