Navigation Menu

Skip to content

Commit

Permalink
string: strpcpy, strpcat
Browse files Browse the repository at this point in the history
alternatives for strlcpy, strlcat
  • Loading branch information
markokr committed Oct 8, 2015
1 parent 85e11db commit c58e1e7
Show file tree
Hide file tree
Showing 4 changed files with 178 additions and 2 deletions.
5 changes: 3 additions & 2 deletions m4/usual.m4
Expand Up @@ -210,8 +210,9 @@ dnl
AC_DEFUN([AC_USUAL_FUNCTION_CHECK], [
### Functions provided if missing
dnl AC_CHECK_FUNCS(basename dirname) # unstable, provide always
AC_CHECK_FUNCS(strlcpy strlcat strsep memmem getpeereid sigaction sigqueue)
AC_CHECK_FUNCS(inet_ntop inet_pton poll getline memrchr regcomp)
AC_CHECK_FUNCS(strlcpy strlcat strsep getpeereid sigaction sigqueue)
AC_CHECK_FUNCS(memmem memrchr mempcpy)
AC_CHECK_FUNCS(inet_ntop inet_pton poll getline regcomp)
AC_CHECK_FUNCS(err errx warn warnx getprogname setprogname)
AC_CHECK_FUNCS(posix_memalign memalign valloc explicit_bzero memset_s reallocarray)
AC_CHECK_FUNCS(getopt getopt_long getopt_long_only)
Expand Down
116 changes: 116 additions & 0 deletions test/test_string.c
Expand Up @@ -142,6 +142,119 @@ static void test_memmem(void *p)
end:;
}

/*
* mempcpy
*/

static void test_mempcpy(void *p)
{
char buf[128];
memset(buf, 0, sizeof buf);
tt_assert(mempcpy(buf, "xx", 0) == buf); str_check(buf, "");
tt_assert(mempcpy(buf, "xx", 1) == buf+1); str_check(buf, "x");
tt_assert(mempcpy(buf, "yy", 2) == buf+2); str_check(buf, "yy");
end:;
}

/*
* strpcpy
*/

static int run_strpcpy(char *dst, const char *src, int size)
{
char *res;
memcpy(dst, "XXX", 4);
res = strpcpy(dst, src, size);
if (res == NULL) {
if (size == 0) {
if (strcmp(dst, "XXX") != 0)
return -10;
} else {
if (memcmp(dst, src, size - 1) != 0)
return -11;
if (dst[size-1] != '\0')
return -12;
}
return -1;
}
if (*res != '\0')
return -13;
if (memcmp(dst, src, res-dst) != 0)
return -14;
if (res < dst)
return -15;
return res - dst;
}

static void test_strpcpy(void *p)
{
char buf[128];
memset(buf, 0, sizeof buf);
int_check(run_strpcpy(buf, "", 0), -1);
int_check(run_strpcpy(buf, "", 1), 0);
int_check(run_strpcpy(buf, "a", 0), -1);
int_check(run_strpcpy(buf, "a", 1), -1);
int_check(run_strpcpy(buf, "a", 2), 1);
int_check(run_strpcpy(buf, "asd", 1), -1);
int_check(run_strpcpy(buf, "asd", 2), -1);
int_check(run_strpcpy(buf, "asd", 3), -1);
int_check(run_strpcpy(buf, "asd", 4), 3);
int_check(run_strpcpy(buf, "asd", 5), 3);
end:;
}

/*
* strpcat
*/

static int run_strpcat(char *dst, const char *src, int size)
{
char *res;
char copydst[1024];
char copy[1024];
strlcpy(copydst, dst, sizeof copy);
strlcpy(copy, dst, sizeof copy);
strlcat(copy, src, sizeof copy);
res = strpcat(dst, src, size);
if (res == NULL) {
if (size == 0) {
if (strcmp(dst, copydst) != 0)
return -10;
} else {
if (memcmp(dst, copy, size - 1) != 0)
return -11;
if (dst[size-1] != '\0')
return -12;
}
return -1;
}
if (*res != '\0')
return -13;
if (memcmp(dst, copy, res-dst) != 0)
return -14;
if (res < dst)
return -15;
return res - dst;
}

static void test_strpcat(void *p)
{
char buf[128];
memset(buf, 0, sizeof buf);
int_check(run_strpcat(buf, "", 0), -1);
int_check(run_strpcat(buf, "", 1), 0);
int_check(run_strpcat(buf, "a", 1), -1);
int_check(run_strpcat(buf, "a", 2), 1);
str_check(buf, "a");

int_check(run_strpcat(buf, "b", 0), -1);
int_check(run_strpcat(buf, "b", 1), -12);
int_check(run_strpcat(buf, "b", 2), -1);
int_check(run_strpcat(buf, "b", 3), 2);
str_check(buf, "ab");
end:;
}

/*
* basename
*/
Expand Down Expand Up @@ -500,7 +613,10 @@ struct testcase_t string_tests[] = {
{ "mempbrk", test_mempbrk },
{ "memcspn", test_memcspn },
{ "memspn", test_memspn},
{ "mempcpy", test_mempcpy },
{ "strsep", test_strsep },
{ "strpcpy", test_strpcpy },
{ "strpcat", test_strpcat },
{ "basename", test_basename },
{ "dirname", test_dirname },
{ "strlist", test_strlist },
Expand Down
28 changes: 28 additions & 0 deletions usual/string.c
Expand Up @@ -216,6 +216,34 @@ size_t strlcat(char *dst, const char *src, size_t n)
}
#endif

char *strpcpy(char *dst, const char *src, size_t n)
{
if (n == 0)
return NULL;
for (; n > 0; n--, dst++, src++) {
if ((*dst = *src) == '\0')
return dst;
}
dst[-1] = '\0';
return NULL;
}

char *strpcat(char *dst, const char *src, size_t n)
{
size_t dstlen = strnlen(dst, n);
if (dstlen < n)
return strpcpy(dst + dstlen, src, n - dstlen);
return NULL;
}

#ifndef HAVE_MEMPCPY
void *mempcpy(void *dst, const void *src, size_t n)
{
memcpy(dst, src, n);
return (char *)(dst) + n;
}
#endif

#ifndef HAVE_MEMRCHR
void *memrchr(const void *s, int c, size_t n)
{
Expand Down
31 changes: 31 additions & 0 deletions usual/string.h
Expand Up @@ -66,6 +66,31 @@ size_t strlcpy(char *dst, const char *src, size_t n);
size_t strlcat(char *dst, const char *src, size_t n);
#endif

#undef strpcpy
#define strpcpy(a,b,c) usual_strpcpy(a,b,c)

/**
* Safe string copy.
*
* Returns pointer to end of string in dst or NULL
* if truncation occured. Destination will be
* zero-terminated unless dstlen is 0.
*/
char *strpcpy(char *dst, const char *src, size_t dstlen);

#undef strpcat
#define strpcat(a,b,c) usual_strpcat(a,b,c)

/**
* Safe string concat.
*
* Returns pointer to end of string in dst or NULL if truncation occured.
* Destination will be zero-terminated, unless dstlen is 0 or existing
* contents were not zero-terminated.
*/
char *strpcat(char *dst, const char *src, size_t dstlen);


#ifndef HAVE_MEMRCHR
#define memrchr(a,b,c) usual_memrchr(a,b,c)
/** Compat: find byte in reverse direction */
Expand All @@ -78,6 +103,12 @@ void *memrchr(const void *s, int c, size_t n);
void *memmem(const void *s, size_t slen, const void *q, size_t qlen);
#endif

#ifndef HAVE_MEMPCPY
#define mempcpy(a,b,c) usual_mempcpy(a,b,c)
/** Copy memory, return pointer to end. */
void *mempcpy(void *dst, const void *src, size_t len);
#endif

/** Return position to first byte that is in 'find'. */
void *mempbrk(const void *data, size_t dlen, const void *find, size_t flen);

Expand Down

0 comments on commit c58e1e7

Please sign in to comment.