Provided by: manpages_6.7-2_all bug

NAME

       stpcpy,  strcpy,  strcat, stpecpy, strtcpy, strlcpy, strlcat, stpncpy, strncpy, strncat - copying strings
       and character sequences

SYNOPSIS

   Strings
       // Chain-copy a string.
       char *stpcpy(char *restrict dst, const char *restrict src);

       // Copy/catenate a string.
       char *strcpy(char *restrict dst, const char *restrict src);
       char *strcat(char *restrict dst, const char *restrict src);

       // Chain-copy a string with truncation.
       char *stpecpy(char *dst, char end[0], const char *restrict src);

       // Copy/catenate a string with truncation.
       ssize_t strtcpy(char dst[restrict .dsize], const char *restrict src,
                      size_t dsize);
       size_t strlcpy(char dst[restrict .dsize], const char *restrict src,
                      size_t dsize);
       size_t strlcat(char dst[restrict .dsize], const char *restrict src,
                      size_t dsize);

   Null-padded character sequences
       // Fill a fixed-size buffer with characters from a string
       // and pad with null bytes.
       char *strncpy(char dst[restrict .dsize], const char *restrict src,
                      size_t dsize);
       char *stpncpy(char dst[restrict .dsize], const char *restrict src,
                      size_t dsize);

       // Chain-copy a null-padded character sequence into a character sequence.
       mempcpy(dst, src, strnlen(src, NITEMS(src)));

       // Chain-copy a null-padded character sequence into a string.
       stpcpy(mempcpy(dst, src, strnlen(src, NITEMS(src))), "");

       // Catenate a null-padded character sequence into a string.
       char *strncat(char *restrict dst, const char src[restrict .ssize],
                      size_t ssize);

   Known-length character sequences
       // Chain-copy a known-length character sequence.
       void *mempcpy(void dst[restrict .len], const void src[restrict .len],
                      size_t len);

       // Chain-copy a known-length character sequence into a string.
       stpcpy(mempcpy(dst, src, len), "");

DESCRIPTION

   Terms (and abbreviations)
       string (str)
              is a sequence of zero or more non-null characters followed by a null character.

       character sequence
              is a sequence of zero or more non-null  characters.   A  program  should  never  use  a  character
              sequence  where a string is required.  However, with appropriate care, a string can be used in the
              place of a character sequence.

              null-padded character sequence
                     Character sequences can be contained in fixed-size  buffers,  which  contain  padding  null
                     bytes  after  the  character sequence, to fill the rest of the buffer without affecting the
                     character sequence; however, those padding  null  bytes  are  not  part  of  the  character
                     sequence.   Don't  confuse  null-padded  with  null-terminated: null-padded means 0 or more
                     padding null bytes, while null-terminated means exactly 1 terminating null character.

              known-length character sequence
                     Character sequence delimited by its length.  It may  be  a  slice  of  a  larger  character
                     sequence, or even of a string.

       length (len)
              is the number of non-null characters in a string or character sequence.  It is the return value of
              strlen(str) and of strnlen(buf, size).

       size   refers to the entire buffer where the string or character sequence is contained.

       end    is the name of a pointer to one  past  the  last  element  of  a  buffer.   It  is  equivalent  to
              &str[size].  It is used as a sentinel value, to be able to truncate strings or character sequences
              instead of overrunning the containing buffer.

       copy   This term is used when the writing starts at the first element pointed to by dst.

       catenate
              This term is used when a function first finds the terminating null  character  in  dst,  and  then
              starts writing at that position.

       chain  This  term  is  used  when  it's  the  programmer  who  provides a pointer to the terminating null
              character in the string dst (or one after the last character in a  character  sequence),  and  the
              function  starts  writing at that location.  The function returns a pointer to the new location of
              the terminating null character (or one after the last character in a character sequence) after the
              call, so that the programmer can use it to chain such calls.

   Copy, catenate, and chain-copy
       Originally,  there was a distinction between functions that copy and those that catenate.  However, newer
       functions that copy while allowing chaining cover both use cases  with  a  single  API.   They  are  also
       algorithmically  faster,  since  they  don't  need  to  search  for the terminating null character of the
       existing string.  However, functions that catenate have a much simpler use,  so  if  performance  is  not
       important, it can make sense to use them for improving readability.

       The  pointer returned by functions that allow chaining is a byproduct of the copy operation, so it has no
       performance costs.  Functions that return such a pointer, and thus can be chained, have names of the form
       *stp*(), since it's common to name the pointer just p.

       Chain-copying  functions  that truncate should accept a pointer to the end of the destination buffer, and
       have names of the form *stpe*().  This allows not having to recalculate the  remaining  size  after  each
       call.

   Truncate or not?
       The  first  thing  to  note  is  that programmers should be careful with buffers, so they always have the
       correct size, and truncation is not necessary.

       In most cases, truncation is not desired, and it is simpler to just do the copy.  Simpler code  is  safer
       code.   Programming against programming mistakes by adding more code just adds more points where mistakes
       can be made.

       Nowadays, compilers can detect most programmer  errors  with  features  like  compiler  warnings,  static
       analyzers,  and  _FORTIFY_SOURCE  (see  ftm(7)).   Keeping the code simple helps these overflow-detection
       features be more precise.

       When validating user input, code should normally not truncate, but instead fail and prevent the  copy  at
       all.

       In some cases, however, it makes sense to truncate.

       Functions that truncate:

       •  stpecpy()

       •  strtcpy()

       •  strlcpy(3bsd) and strlcat(3bsd) are similar, but have important performance problems; see BUGS.

       •  stpncpy(3)  and  strncpy(3)  also  truncate,  but  they  don't  write  strings, but rather null-padded
          character sequences.

   Null-padded character sequences
       For historic reasons, some standard APIs and file formats, such as utmpx(5) and tar(1),  use  null-padded
       character  sequences  in  fixed-size  buffers.   To interface with them, specialized functions need to be
       used.

       To copy bytes from strings into these buffers, use strncpy(3) or stpncpy(3).

       To read a null-padded character sequence, use strnlen(src, NITEMS(src)), and then you can treat it  as  a
       known-length character sequence; or use strncat(3) directly.

   Known-length character sequences
       The simplest character sequence copying function is mempcpy(3).  It requires always knowing the length of
       your character sequences, for which structures can be used.  It makes the code  much  faster,  since  you
       always  know  the  length  of  your  character  sequences,  and  can  do  the  minimal  copies and length
       measurements.  mempcpy(3) copies character sequences, so you need to explicitly set the terminating  null
       character if you need a string.

       In  programs that make considerable use of strings or character sequences, and need the best performance,
       using overlapping character sequences can make a big difference.  It allows  holding  subsequences  of  a
       larger character sequence, while not duplicating memory nor using time to do a copy.

       However,  this  is delicate, since it requires using character sequences.  C library APIs use strings, so
       programs that use character sequences will have to take care of differentiating  strings  from  character
       sequences.

       To copy a known-length character sequence, use mempcpy(3).

       To copy a known-length character sequence into a string, use stpcpy(mempcpy(dst, src, len), "").

       A string is also accepted as input, because mempcpy(3) asks for the length, and a string is composed of a
       character sequence of the same length plus a terminating null character.

   String vs character sequence
       Some functions only operate on strings.  Those require that the input src is a string, and  guarantee  an
       output  string  (even  when  truncation  occurs).   Functions that catenate also require that dst holds a
       string before the call.  List of functions:

       •  stpcpy(3)
       •  strcpy(3), strcat(3)
       •  stpecpy()
       •  strtcpy()
       •  strlcpy(3bsd), strlcat(3bsd)

       Other functions require an input string, but create a character sequence as output.  These functions have
       confusing names, and have a long history of misuse.  List of functions:

       •  stpncpy(3)
       •  strncpy(3)

       Other  functions  operate  on  an  input character sequence, and create an output string.  Functions that
       catenate also require that dst holds a string before the call.  strncat(3) has an  even  more  misleading
       name than the functions above.  List of functions:

       •  strncat(3)

       Other  functions  operate on an input character sequence to create an output character sequence.  List of
       functions:

       •  mempcpy(3)

   Functions
       stpcpy(3)
              Copy the input string into a destination string.  The programmer is responsible for  allocating  a
              buffer large enough.  It returns a pointer suitable for chaining.

       strcpy(3)
       strcat(3)
              Copy  and  catenate the input string into a destination string.  The programmer is responsible for
              allocating a buffer large enough.  The return value is useless.

              stpcpy(3) is a faster alternative to these functions.

       stpecpy()
              Chain-copy the input string into a destination string.  If the destination buffer,  limited  by  a
              pointer to its end, isn't large enough to hold the copy, the resulting string is truncated (but it
              is guaranteed to be null-terminated).  It returns a pointer  suitable  for  chaining.   Truncation
              needs to be detected only once after the last chained call.

              This function is not provided by any library; see EXAMPLES for a reference implementation.

       strtcpy()
              Copy  the input string into a destination string.  If the destination buffer isn't large enough to
              hold the copy, the resulting string is truncated (but it is guaranteed to be null-terminated).  It
              returns the length of the string, or -1 if it truncated.

              This function is not provided by any library; see EXAMPLES for a reference implementation.

       strlcpy(3bsd)
       strlcat(3bsd)
              Copy  and catenate the input string into a destination string.  If the destination buffer, limited
              by its size, isn't large enough to hold the copy, the resulting string is  truncated  (but  it  is
              guaranteed  to  be  null-terminated).   They  return  the length of the total string they tried to
              create.

              Check BUGS before using these functions.

              strtcpy() and stpecpy() are better alternatives to these functions.

       stpncpy(3)
              Copy the input string into a destination null-padded character sequence in  a  fixed-size  buffer.
              If the destination buffer, limited by its size, isn't large enough to hold the copy, the resulting
              character sequence is truncated.  Since it creates a character sequence, it doesn't need to  write
              a  terminating  null  character.   It's  impossible to distinguish truncation by the result of the
              call, from a character sequence that just  fits  the  destination  buffer;  truncation  should  be
              detected by comparing the length of the input string with the size of the destination buffer.

       strncpy(3)
              This function is identical to stpncpy(3) except for the useless return value.

              stpncpy(3) is a more useful alternative to this function.

       strncat(3)
              Catenate  the  input  character  sequence,  contained  in  a null-padded fixed-size buffer, into a
              destination string.  The programmer is responsible for allocating  a  buffer  large  enough.   The
              return value is useless.

              Do not confuse this function with strncpy(3); they are not related at all.

              stpcpy(mempcpy(dst, src, strnlen(src, NITEMS(src))), "") is a faster alternative to this function.

       mempcpy(3)
              Copy  the  input character sequence, limited by its length, into a destination character sequence.
              The programmer is responsible for allocating a buffer large enough.  It returns a pointer suitable
              for chaining.

RETURN VALUE

       stpcpy(3)
              A pointer to the terminating null character in the destination string.

       stpecpy()
              A pointer to the terminating null character in the destination string, on success.  On error, NULL
              is returned, and errno is set to indicate the error.

       mempcpy(3)
       stpncpy(3)
              A pointer to one after the last character in the destination character sequence.

       strtcpy()
              The length of the string, on success.  On error, -1 is returned, and errno is set to indicate  the
              error.

       strlcpy(3bsd)
       strlcat(3bsd)
              The length of the total string that they tried to create (as if truncation didn't occur).

       strcpy(3)
       strcat(3)
       strncpy(3)
       strncat(3)
              The dst pointer, which is useless.

ERRORS

       Most of these functions don't set errno.

       stpecpy()
       strtcpy()

              ENOBUFS
                     dsize was 0.

              E2BIG  The string has been truncated.

NOTES

       The  Linux  kernel  has  an  internal  function  for  copying  strings, strscpy(9), which is identical to
       strtcpy(), except that it returns -E2BIG instead of -1 and it doesn't set errno.

CAVEATS

       Don't mix chain calls to truncating and non-truncating functions.  It is conceptually  wrong  unless  you
       know  that the first part of a copy will always fit.  Anyway, the performance difference will probably be
       negligible, so it will probably be more clear if you use consistent semantics: either truncating or  non-
       truncating.  Calling a non-truncating function after a truncating one is necessarily wrong.

BUGS

       All    catenation    functions    share    the   same   performance   problem:   Shlemiel   the   painter
       ⟨https://www.joelonsoftware.com/2001/12/11/back-to-basics/⟩.  As a  mitigation,  compilers  are  able  to
       transform  some  calls to catenation functions into normal copy functions, since strlen(dst) is usually a
       byproduct of the previous copy.

       strlcpy(3) and strlcat(3) need to read the entire src string, even if the destination  buffer  is  small.
       This  makes  them  vulnerable to Denial of Service (DoS) attacks if an attacker can control the length of
       the src string.  And if not, they're still unnecessarily slow.

EXAMPLES

       The following are examples of correct use of each of these functions.

       stpcpy(3)
              p = buf;
              p = stpcpy(p, "Hello ");
              p = stpcpy(p, "world");
              p = stpcpy(p, "!");
              len = p - buf;
              puts(buf);

       strcpy(3)
       strcat(3)
              strcpy(buf, "Hello ");
              strcat(buf, "world");
              strcat(buf, "!");
              len = strlen(buf);
              puts(buf);

       stpecpy()
              end = buf + NITEMS(buf);
              p = buf;
              p = stpecpy(p, end, "Hello ");
              p = stpecpy(p, end, "world");
              p = stpecpy(p, end, "!");
              if (p == NULL) {
                  len = NITEMS(buf) - 1;
                  goto toolong;
              }
              len = p - buf;
              puts(buf);

       strtcpy()
              len = strtcpy(buf, "Hello world!", NITEMS(buf));
              if (len == -1)
                  goto toolong;
              puts(buf);

       strlcpy(3bsd)
       strlcat(3bsd)
              if (strlcpy(buf, "Hello ", NITEMS(buf)) >= NITEMS(buf))
                  goto toolong;
              if (strlcat(buf, "world", NITEMS(buf)) >= NITEMS(buf))
                  goto toolong;
              len = strlcat(buf, "!", NITEMS(buf));
              if (len >= NITEMS(buf))
                  goto toolong;
              puts(buf);

       stpncpy(3)
              p = stpncpy(u->ut_user, "alx", NITEMS(u->ut_user));
              if (NITEMS(u->ut_user) < strlen("alx"))
                  goto toolong;
              len = p - u->ut_user;
              fwrite(u->ut_user, 1, len, stdout);

       strncpy(3)
              strncpy(u->ut_user, "alx", NITEMS(u->ut_user));
              if (NITEMS(u->ut_user) < strlen("alx"))
                  goto toolong;
              len = strnlen(u->ut_user, NITEMS(u->ut_user));
              fwrite(u->ut_user, 1, len, stdout);

       mempcpy(dst, src, strnlen(src, NITEMS(src)))
              char  buf[NITEMS(u->ut_user)];
              p = buf;
              p = mempcpy(p, u->ut_user, strnlen(u->ut_user, NITEMS(u->ut_user)));
              len = p - buf;
              fwrite(buf, 1, len, stdout);

       stpcpy(mempcpy(dst, src, strnlen(src, NITEMS(src))), "")
              char  buf[NITEMS(u->ut_user) + 1];
              p = buf;
              p = mempcpy(p, u->ut_user, strnlen(u->ut_user, NITEMS(u->ut_user)));
              p = stpcpy(p, "");
              len = p - buf;
              puts(buf);

       strncat(3)
              char  buf[NITEMS(u->ut_user) + 1];
              strcpy(buf, "");
              strncat(buf, u->ut_user, NITEMS(u->ut_user));
              len = strlen(buf);
              puts(buf);

       mempcpy(3)
              p = buf;
              p = mempcpy(p, "Hello ", 6);
              p = mempcpy(p, "world", 5);
              p = mempcpy(p, "!", 1);
              len = p - buf;
              fwrite(buf, 1, len, stdout);

       stpcpy(mempcpy(dst, src, len), "")
              p = buf;
              p = mempcpy(p, "Hello ", 6);
              p = mempcpy(p, "world", 5);
              p = mempcpy(p, "!", 1);
              p = stpcpy(p, "");
              len = p - buf;
              puts(buf);

   Implementations
       Here are reference implementations for functions not provided by libc.

           /* This code is in the public domain. */

           char *
           stpecpy(char *dst, char end[0], const char *restrict src)
           {
               size_t  dlen;

               if (dst == NULL)
                   return NULL;

               dlen = strtcpy(dst, src, end - dst);
               return (dlen == -1) ? NULL : dst + dlen;
           }

           ssize_t
           strtcpy(char *restrict dst, const char *restrict src, size_t dsize)
           {
               bool    trunc;
               size_t  dlen, slen;

               if (dsize == 0) {
                   errno = ENOBUFS;
                   return -1;
               }

               slen = strnlen(src, dsize);
               trunc = (slen == dsize);
               dlen = slen - trunc;

               stpcpy(mempcpy(dst, src, dlen), "");
               if (trunc)
                   errno = E2BIG;
               return trunc ? -1 : slen;
           }

SEE ALSO

       bzero(3), memcpy(3), memccpy(3), mempcpy(3), stpcpy(3), strlcpy(3bsd), strncat(3), stpncpy(3), string(3)