diff --git a/configure.ac b/configure.ac index b63ed690..c3ea7366 100644 --- a/configure.ac +++ b/configure.ac @@ -120,6 +120,11 @@ AC_CHECK_DECL([poll], [Whether poll() is defined])],, [#include ]) +AC_CHECK_DECL([strlcpy], + [AC_DEFINE([HAVE_STRLCPY],, + [Whether strlcpy() is defined])],, + [#include ]) + # Typedefs AC_TYPE_SIZE_T AC_TYPE_SSIZE_T diff --git a/src/libguac/Makefile.am b/src/libguac/Makefile.am index 876eb298..ffcfffc8 100644 --- a/src/libguac/Makefile.am +++ b/src/libguac/Makefile.am @@ -61,6 +61,7 @@ libguacinc_HEADERS = \ guacamole/socket-types.h \ guacamole/stream.h \ guacamole/stream-types.h \ + guacamole/string.h \ guacamole/timestamp.h \ guacamole/timestamp-types.h \ guacamole/unicode.h \ @@ -96,6 +97,7 @@ libguac_la_SOURCES = \ socket-fd.c \ socket-nest.c \ socket-tee.c \ + string.c \ timestamp.c \ unicode.c \ user.c \ diff --git a/src/libguac/guacamole/string.h b/src/libguac/guacamole/string.h new file mode 100644 index 00000000..89561ab0 --- /dev/null +++ b/src/libguac/guacamole/string.h @@ -0,0 +1,68 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +#ifndef GUAC_STRING_H +#define GUAC_STRING_H + +/** + * Provides convenience functions for manipulating strings. + * + * @file string.h + */ + +#include +#include + +/** + * Copies a limited number of bytes from the given source string to the given + * destination buffer. The resulting buffer will always be null-terminated, + * even if doing so means that the intended string is truncated, unless the + * destination buffer has no space available at all. As this function always + * returns the length of the string it tried to create (the length of the + * source string), whether truncation has occurred can be detected by comparing + * the return value against the size of the destination buffer. If the value + * returned is greater than or equal to the size of the destination buffer, then + * the string has been truncated. + * + * The source and destination buffers MAY NOT overlap. + * + * @param dest + * The buffer which should receive the contents of the source string. This + * buffer will always be null terminated unless zero bytes are available + * within the buffer. + * + * @param src + * The source string to copy into the destination buffer. This string MUST + * be null terminated. + * + * @param n + * The number of bytes available within the destination buffer. If this + * value is zero, no bytes will be written to the destination buffer, and + * the destination buffer may not be null terminated. In all other cases, + * the destination buffer will always be null terminated, even if doing + * so means that the copied data from the source string will be truncated. + * + * @return + * The length of the copied string (the source string) in bytes, excluding + * the null terminator. + */ +size_t guac_strlcpy(char* restrict dest, const char* restrict src, size_t n); + +#endif + diff --git a/src/libguac/string.c b/src/libguac/string.c new file mode 100644 index 00000000..fbcbcf59 --- /dev/null +++ b/src/libguac/string.c @@ -0,0 +1,52 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +#include "config.h" + +#include +#include + +size_t guac_strlcpy(char* restrict dest, const char* restrict src, size_t n) { + +#ifdef HAVE_STRLCPY + return strlcpy(dest, src, n); +#else + /* Calculate actual length of desired string */ + size_t length = strlen(src); + + /* Copy nothing if there is no space */ + if (n <= 0) + return length; + + /* Calculate length of the string which will be copied */ + size_t copy_length = length; + if (copy_length >= n) + copy_length = n - 1; + + /* Copy only as much of string as possible, manually adding a null + * terminator */ + memcpy(dest, src, copy_length); + dest[copy_length] = '\0'; + + /* Return the overall length of the desired string */ + return length; +#endif + +} +