p The buffers .Fa src and .Fa dst may not overlap.
p The buffer .Fa src is not required to hold a .Tn NUL Ns -terminated string on input; it is only required .Em either to have at least .Fa len bytes allocated and initialized, .Em or to have a .Tn NUL byte if it is shorter than .Fa len bytes.
p The buffer .Fa dst is not guaranteed to hold a .Tn NUL Ns -terminated string on output; .Fn stpncpy and .Fn strncpy write exactly .Fa len bytes to it, which includes nonempty .Tn NUL padding only if a .Tn NUL byte appears in the first .Fa len bytes at .Fa src . .Sh RETURN VALUES The .Fn strncpy function returns .Fa dst .
p The .Fn stpncpy function returns a pointer to the byte after the last .No non- Ns Tn NUL byte of .Fa dst . This does not necessarily point to a .Tn NUL byte; .Fn stpncpy may return .Li \*(Am Ns Fa dst Ns Li "[" Fa len Ns Li "]" Ns , if all .Fa len bytes starting at .Fa src are .No non- Tn NUL . .Sh EXAMPLES The following logic fills a fixed-width field in a record that might appear on disk with the content of a caller-provided string .Dv str , padded to the end of the field with .Tn NUL bytes: d -literal -offset indent struct record { uint16_t id; char name[6]; uint8_t tag; ... }; struct record *rec = ...; strncpy(rec->name, str, sizeof(rec->name)); .Ed
p The following values for .Dv str result in the following corresponding contents of .Dv rec Ns Li "->name" : l -column -offset indent ".Li \*qabcdefghi\e0\*q" ".Li \*qabc\e0\e0\e0\*q" t Dv str Ta Dv rec Ns Li "->name" t Li \*qabc\e0\*q Ta Li \*qabc\e0\e0\e0\*q t Li \*qabc\e0\e0\e0\*q Ta Li \*qabc\e0\e0\e0\*q t Li \*qabcde\e0\*q Ta Li \*qabcde\e0\*q t Li \*qabcdef\e0\*q Ta Li \*qabcdef\*q t Li \*qabcdef\*q Ta Li \*qabcdef\*q t Li \*qabcdefghi\e0\*q Ta Li \*qabcdef\*q t Li \*qabcdefghi\*q Ta Li \*qabcdef\*q .El
p Note that when .Dv str has at least six .No non- Ns Tn NUL bytes, .Dv rec Ns Li "->name" is .Em not .Tn NUL Ns -terminated \(em it is only .Em padded with (possibly zero) .Tn NUL bytes to fill the fixed-width buffer. When .Dv str has .Em more than six .No non- Ns Tn NUL bytes, the additional ones are truncated. If .Dv str has space for .Em fewer than six bytes, and the last one is not .Tn NUL , using .Fn strncpy is undefined.
p Because .Fn strncpy does .Em not guarantee to .Tn NUL Ns -terminate the result, if .Tn NUL Ns -termination is required it must be done explicitly: d -literal -offset indent char buf[1024]; strncpy(buf, input, sizeof(buf) - 1); buf[sizeof(buf) - 1] = '\e0'; .Ed
p If .Va input is guaranteed to be .Tn NUL Ns -terminated , and if .Va buf need only be .Tn NUL Ns -terminated , not fully initialized with .Tn NUL padding, this could be achieved using .Xr strlcpy 3 as follows: d -literal -offset indent strlcpy(buf, input, sizeof(buf)); .Ed
p It is not enough for .Va input to have .Li sizeof(buf) bytes allocated; it MUST be .Tn NUL Ns -terminated for .Xr strlcpy 3 to be used.
p Note that because .Xr strlcpy 3 is not defined in any standards, it should only be used when portability is not a concern.
p .Sy WARNING : Because .Xr strlcpy 3 does not fully initialize .Fa dst , but does read all the way to a .Tn NUL terminator in .Fa src even past .Fa len bytes, .Xr strlcpy 3 is .Em not a safe .Tn NUL Ns -terminating replacement for .Fn strncpy . Naively replacing .Fn strncpy by .Xr strlcpy 3 can lead to crashes, undefined behaviour, and disclosure of secrets from uninitialized memory. .Sh SEE ALSO .Xr bcopy 3 , .Xr memccpy 3 , .Xr memcpy 3 , .Xr memmove 3 , .Xr strcpy 3 , .Xr strlcpy 3 , .Xr wcscpy 3 .Sh STANDARDS The .Fn strncpy function conforms to .St -isoC-99 .
p The .Fn stpncpy function conforms to .St -p1003.1-2008 . .Sh HISTORY The .Fn stpncpy function first appeared in .Nx 6.0 . .Sh SECURITY CONSIDERATIONS The .Fn stpncpy and .Fn strncpy functions are not guaranteed to .Tn NUL Ns -terminate the result.