1 // SPDX-License-Identifier: BSD-3-Clause
2 /*
3  * Copyright (c) 1994-2009  Red Hat, Inc.
4  * All rights reserved.
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions are met:
8  *
9  * 1. Redistributions of source code must retain the above copyright notice,
10  * this list of conditions and the following disclaimer.
11  *
12  * 2. Redistributions in binary form must reproduce the above copyright notice,
13  * this list of conditions and the following disclaimer in the documentation
14  * and/or other materials provided with the distribution.
15  *
16  * 3. Neither the name of the copyright holder nor the names of its
17  * contributors may be used to endorse or promote products derived from this
18  * software without specific prior written permission.
19  *
20  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
21  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
24  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
25  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
26  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
27  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
28  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
29  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
30  * POSSIBILITY OF SUCH DAMAGE.
31  */
32 
33 /*
34 FUNCTION
35 	<<strncpy>>---counted copy string
36 
37 INDEX
38 	strncpy
39 
40 ANSI_SYNOPSIS
41 	#include <string.h>
42 	char *strncpy(char *restrict <[dst]>, const char *restrict <[src]>,
43                       size_t <[length]>);
44 
45 TRAD_SYNOPSIS
46 	#include <string.h>
47 	char *strncpy(<[dst]>, <[src]>, <[length]>)
48 	char *<[dst]>;
49 	char *<[src]>;
50 	size_t <[length]>;
51 
52 DESCRIPTION
53 	<<strncpy>> copies not more than <[length]> characters from the
54 	the string pointed to by <[src]> (including the terminating
55 	null character) to the array pointed to by <[dst]>.  If the
56 	string pointed to by <[src]> is shorter than <[length]>
57 	characters, null characters are appended to the destination
58 	array until a total of <[length]> characters have been
59 	written.
60 
61 RETURNS
62 	This function returns the initial value of <[dst]>.
63 
64 PORTABILITY
65 <<strncpy>> is ANSI C.
66 
67 <<strncpy>> requires no supporting OS subroutines.
68 
69 QUICKREF
70 	strncpy ansi pure
71 */
72 
73 #include "_ansi.h"
74 #include <string.h>
75 #include <limits.h>
76 
77 /*SUPPRESS 560*/
78 /*SUPPRESS 530*/
79 
80 /* Nonzero if either X or Y is not aligned on a "long" boundary.  */
81 #define UNALIGNED(X, Y) \
82   (((long)X & (sizeof (long) - 1)) | ((long)Y & (sizeof (long) - 1)))
83 
84 #if LONG_MAX == 2147483647L
85 #define DETECTNULL(X) (((X) - 0x01010101) & ~(X) & 0x80808080)
86 #else
87 #if LONG_MAX == 9223372036854775807L
88 /* Nonzero if X (a long int) contains a NULL byte. */
89 #define DETECTNULL(X) (((X) - 0x0101010101010101) & ~(X) & 0x8080808080808080)
90 #else
91 #error long int is not a 32bit or 64bit type.
92 #endif
93 #endif
94 
95 #ifndef DETECTNULL
96 #error long int is not a 32bit or 64bit byte
97 #endif
98 
99 #define TOO_SMALL(LEN) ((LEN) < sizeof (long))
100 
101 char *
102 _DEFUN (strncpy, (dst0, src0),
103 	char *__restrict dst0 _AND
104 	_CONST char *__restrict src0 _AND
105 	size_t count)
106 {
107 #if defined(PREFER_SIZE_OVER_SPEED) || defined(__OPTIMIZE_SIZE__)
108   char *dscan;
109   _CONST char *sscan;
110 
111   dscan = dst0;
112   sscan = src0;
113   while (count > 0)
114     {
115       --count;
116       if ((*dscan++ = *sscan++) == '\0')
117 	break;
118     }
119   while (count-- > 0)
120     *dscan++ = '\0';
121 
122   return dst0;
123 #else
124   char *dst = dst0;
125   _CONST char *src = src0;
126   long *aligned_dst;
127   _CONST long *aligned_src;
128 
129   /* If SRC and DEST is aligned and count large enough, then copy words.  */
130   if (!UNALIGNED (src, dst) && !TOO_SMALL (count))
131     {
132       aligned_dst = (long*)dst;
133       aligned_src = (long*)src;
134 
135       /* SRC and DEST are both "long int" aligned, try to do "long int"
136 	 sized copies.  */
137       while (count >= sizeof (long int) && !DETECTNULL(*aligned_src))
138 	{
139 	  count -= sizeof (long int);
140 	  *aligned_dst++ = *aligned_src++;
141 	}
142 
143       dst = (char*)aligned_dst;
144       src = (char*)aligned_src;
145     }
146 
147   while (count > 0)
148     {
149       --count;
150       if ((*dst++ = *src++) == '\0')
151 	break;
152     }
153 
154   while (count-- > 0)
155     *dst++ = '\0';
156 
157   return dst0;
158 #endif /* not PREFER_SIZE_OVER_SPEED */
159 }
160