[615] | 1 | /*
|
---|
| 2 | * linux/lib/string.c
|
---|
| 3 | *
|
---|
| 4 | * Copyright (C) 1991, 1992 Linus Torvalds
|
---|
| 5 | */
|
---|
| 6 |
|
---|
| 7 | #include <string.h>
|
---|
| 8 | #include <types.h>
|
---|
| 9 | #include <asm/errno.h>
|
---|
| 10 |
|
---|
| 11 | #define REPEAT_BYTE(x) ((~0ul / 0xff) * (x))
|
---|
| 12 |
|
---|
| 13 | /*
|
---|
| 14 | * This is largely generic for little-endian machines, but the
|
---|
| 15 | * optimal byte mask counting is probably going to be something
|
---|
| 16 | * that is architecture-specific. If you have a reliably fast
|
---|
| 17 | * bit count instruction, that might be better than the multiply
|
---|
| 18 | * and shift, for example.
|
---|
| 19 | */
|
---|
| 20 | struct word_at_a_time {
|
---|
| 21 | const unsigned long one_bits, high_bits;
|
---|
| 22 | };
|
---|
| 23 |
|
---|
| 24 | /* Carl Chatfield / Jan Achrenius G+ version for 32-bit */
|
---|
| 25 | static inline long count_masked_bytes(long mask)
|
---|
| 26 | {
|
---|
| 27 | /* (000000 0000ff 00ffff ffffff) -> ( 1 1 2 3 ) */
|
---|
| 28 | long a = (0x0ff0001+mask) >> 23;
|
---|
| 29 | /* Fix the 1 for 00 case */
|
---|
| 30 | return a & mask;
|
---|
| 31 | }
|
---|
| 32 |
|
---|
| 33 | #define WORD_AT_A_TIME_CONSTANTS { REPEAT_BYTE(0x01), REPEAT_BYTE(0x80) }
|
---|
| 34 |
|
---|
| 35 | /* Return nonzero if it has a zero */
|
---|
| 36 | static inline unsigned long has_zero(unsigned long a, unsigned long *bits, const struct word_at_a_time *c)
|
---|
| 37 | {
|
---|
| 38 | unsigned long mask = ((a - c->one_bits) & ~a) & c->high_bits;
|
---|
| 39 | *bits = mask;
|
---|
| 40 | return mask;
|
---|
| 41 | }
|
---|
| 42 |
|
---|
| 43 | static inline unsigned long prep_zero_mask(unsigned long a, unsigned long bits, const struct word_at_a_time *c)
|
---|
| 44 | {
|
---|
| 45 | return bits;
|
---|
| 46 | }
|
---|
| 47 |
|
---|
| 48 | static inline unsigned long create_zero_mask(unsigned long bits)
|
---|
| 49 | {
|
---|
| 50 | bits = (bits - 1) & ~bits;
|
---|
| 51 | return bits >> 7;
|
---|
| 52 | }
|
---|
| 53 |
|
---|
| 54 | /* The mask we created is directly usable as a bytemask */
|
---|
| 55 | #define zero_bytemask(mask) (mask)
|
---|
| 56 |
|
---|
| 57 | static inline unsigned long find_zero(unsigned long mask)
|
---|
| 58 | {
|
---|
| 59 | return count_masked_bytes(mask);
|
---|
| 60 | }
|
---|
| 61 |
|
---|
| 62 | /**
|
---|
| 63 | * strscpy - Copy a C-string into a sized buffer
|
---|
| 64 | * @dest: Where to copy the string to
|
---|
| 65 | * @src: Where to copy the string from
|
---|
| 66 | * @count: Size of destination buffer
|
---|
| 67 | *
|
---|
| 68 | * Copy the string, or as much of it as fits, into the dest buffer.
|
---|
| 69 | * The routine returns the number of characters copied (not including
|
---|
| 70 | * the trailing NUL) or -E2BIG if the destination buffer wasn't big enough.
|
---|
| 71 | * The behavior is undefined if the string buffers overlap.
|
---|
| 72 | * The destination buffer is always NUL terminated, unless it's zero-sized.
|
---|
| 73 | *
|
---|
| 74 | * Preferred to strlcpy() since the API doesn't require reading memory
|
---|
| 75 | * from the src string beyond the specified "count" bytes, and since
|
---|
| 76 | * the return value is easier to error-check than strlcpy()'s.
|
---|
| 77 | * In addition, the implementation is robust to the string changing out
|
---|
| 78 | * from underneath it, unlike the current strlcpy() implementation.
|
---|
| 79 | *
|
---|
| 80 | * Preferred to strncpy() since it always returns a valid string, and
|
---|
| 81 | * doesn't unnecessarily force the tail of the destination buffer to be
|
---|
| 82 | * zeroed. If the zeroing is desired, it's likely cleaner to use strscpy()
|
---|
| 83 | * with an overflow test, then just memset() the tail of the dest buffer.
|
---|
| 84 | */
|
---|
| 85 | ssize_t strscpy(char *dest, const char *src, size_t count)
|
---|
| 86 | {
|
---|
| 87 | const struct word_at_a_time constants = WORD_AT_A_TIME_CONSTANTS;
|
---|
| 88 | size_t max = count;
|
---|
| 89 | long res = 0;
|
---|
| 90 |
|
---|
| 91 | if (count == 0)
|
---|
| 92 | return -E2BIG;
|
---|
| 93 |
|
---|
| 94 | /* If src or dest is unaligned, don't do word-at-a-time. */
|
---|
| 95 | if (((long) dest | (long) src) & (sizeof(long) - 1))
|
---|
| 96 | max = 0;
|
---|
| 97 |
|
---|
| 98 | while (max >= sizeof(unsigned long)) {
|
---|
| 99 | unsigned long c, data;
|
---|
| 100 |
|
---|
| 101 | c = *(unsigned long *)(src+res);
|
---|
| 102 | if (has_zero(c, &data, &constants)) {
|
---|
| 103 | data = prep_zero_mask(c, data, &constants);
|
---|
| 104 | data = create_zero_mask(data);
|
---|
| 105 | *(unsigned long *)(dest+res) = c & zero_bytemask(data);
|
---|
| 106 | return res + find_zero(data);
|
---|
| 107 | }
|
---|
| 108 | *(unsigned long *)(dest+res) = c;
|
---|
| 109 | res += sizeof(unsigned long);
|
---|
| 110 | count -= sizeof(unsigned long);
|
---|
| 111 | max -= sizeof(unsigned long);
|
---|
| 112 | }
|
---|
| 113 |
|
---|
| 114 | while (count) {
|
---|
| 115 | char c;
|
---|
| 116 |
|
---|
| 117 | c = src[res];
|
---|
| 118 | dest[res] = c;
|
---|
| 119 | if (!c)
|
---|
| 120 | return res;
|
---|
| 121 | res++;
|
---|
| 122 | count--;
|
---|
| 123 | }
|
---|
| 124 |
|
---|
| 125 | /* Hit buffer length without finding a NUL; force NUL-termination. */
|
---|
| 126 | if (res)
|
---|
| 127 | dest[res-1] = '\0';
|
---|
| 128 |
|
---|
| 129 | return -E2BIG;
|
---|
| 130 | }
|
---|