From 1ffe1ccb6ec5771765f1f6f0c439ed07bf345d67 Mon Sep 17 00:00:00 2001 From: Florian Weimer Date: Sun, 12 Nov 2017 09:53:06 +0100 Subject: support: Add xstrndup, xunlink, xreadlink, support_create_temp_directory --- support/Makefile | 6 +++- support/support.h | 1 + support/support_chroot.c | 9 +++--- support/temp_file.c | 13 +++++++++ support/temp_file.h | 5 ++++ support/tst-xreadlink.c | 72 ++++++++++++++++++++++++++++++++++++++++++++++++ support/xreadlink.c | 44 +++++++++++++++++++++++++++++ support/xstrndup.c | 30 ++++++++++++++++++++ support/xunistd.h | 5 ++++ support/xunlink.c | 27 ++++++++++++++++++ 10 files changed, 207 insertions(+), 5 deletions(-) create mode 100644 support/tst-xreadlink.c create mode 100644 support/xreadlink.c create mode 100644 support/xstrndup.c create mode 100644 support/xunlink.c (limited to 'support') diff --git a/support/Makefile b/support/Makefile index 027a663000..dafb1737a4 100644 --- a/support/Makefile +++ b/support/Makefile @@ -109,19 +109,22 @@ libsupport-routines = \ xpthread_once \ xpthread_rwlock_init \ xpthread_rwlock_rdlock \ - xpthread_rwlock_wrlock \ xpthread_rwlock_unlock \ + xpthread_rwlock_wrlock \ xpthread_rwlockattr_init \ xpthread_rwlockattr_setkind_np \ xpthread_sigmask \ xpthread_spin_lock \ xpthread_spin_unlock \ + xreadlink \ xrealloc \ xrecvfrom \ xsendto \ xsetsockopt \ xsocket \ xstrdup \ + xstrndup \ + xunlink \ xwaitpid \ xwrite \ @@ -138,6 +141,7 @@ tests = \ tst-support_capture_subprocess \ tst-support_format_dns_packet \ tst-support_record_failure \ + tst-xreadlink \ ifeq ($(run-built-tests),yes) tests-special = \ diff --git a/support/support.h b/support/support.h index 4b5f04c2cc..bbba803ba1 100644 --- a/support/support.h +++ b/support/support.h @@ -68,6 +68,7 @@ void *xrealloc (void *p, size_t n); char *xasprintf (const char *format, ...) __attribute__ ((format (printf, 1, 2), malloc)); char *xstrdup (const char *); +char *xstrndup (const char *, size_t); __END_DECLS diff --git a/support/support_chroot.c b/support/support_chroot.c index f3ef551b05..f6fad18f33 100644 --- a/support/support_chroot.c +++ b/support/support_chroot.c @@ -46,10 +46,11 @@ support_chroot_create (struct support_chroot_configuration conf) { struct support_chroot *chroot = xmalloc (sizeof (*chroot)); - chroot->path_chroot = xasprintf ("%s/tst-resolv-res_init-XXXXXX", test_dir); - if (mkdtemp (chroot->path_chroot) == NULL) - FAIL_EXIT1 ("mkdtemp (\"%s\"): %m", chroot->path_chroot); - add_temp_file (chroot->path_chroot); + { + char *template = xasprintf ("%s/tst-resolv-res_init-XXXXXX", test_dir); + chroot->path_chroot = support_create_temp_directory (template); + free (template); + } /* Create the /etc directory in the chroot environment. */ char *path_etc = xasprintf ("%s/etc", chroot->path_chroot); diff --git a/support/temp_file.c b/support/temp_file.c index fdb2477ab9..cbd54e2e17 100644 --- a/support/temp_file.c +++ b/support/temp_file.c @@ -86,6 +86,19 @@ create_temp_file (const char *base, char **filename) return fd; } +char * +support_create_temp_directory (const char *base) +{ + char *base_copy = xstrdup (base); + if (mkdtemp (base_copy) == NULL) + { + printf ("error: mkdtemp (\"%s\"): %m", base); + exit (1); + } + add_temp_file (base_copy); + return base_copy; +} + /* Helper functions called by the test skeleton follow. */ void diff --git a/support/temp_file.h b/support/temp_file.h index 6fed8df1ea..dfefe585de 100644 --- a/support/temp_file.h +++ b/support/temp_file.h @@ -32,6 +32,11 @@ void add_temp_file (const char *name); *FILENAME. */ int create_temp_file (const char *base, char **filename); +/* Create a temporary directory and schedule it for deletion. BASE + must end with the six characters "XXXXXX". Return the name of the + temporary directory. The caller should free the string. */ +char *support_create_temp_directory (const char *base); + __END_DECLS #endif /* SUPPORT_TEMP_FILE_H */ diff --git a/support/tst-xreadlink.c b/support/tst-xreadlink.c new file mode 100644 index 0000000000..cb2c12a888 --- /dev/null +++ b/support/tst-xreadlink.c @@ -0,0 +1,72 @@ +/* Test the xreadlink function. + Copyright (C) 2017 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + . */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +static int +do_test (void) +{ + char *dir = support_create_temp_directory ("/tmp/tst-xreadlink-XXXXXX"); + char *symlink_name = xasprintf ("%s/symlink", dir); + add_temp_file (symlink_name); + + /* The limit 10000 is arbitrary and simply there to prevent an + attempt to exhaust all available disk space. */ + for (int size = 1; size < 10000; ++size) + { + char *contents = xmalloc (size + 1); + for (int i = 0; i < size; ++i) + contents[i] = 'a' + (rand () % 26); + contents[size] = '\0'; + if (symlink (contents, symlink_name) != 0) + { + if (errno == ENAMETOOLONG) + { + printf ("info: ENAMETOOLONG failure at %d bytes\n", size); + free (contents); + break; + } + FAIL_EXIT1 ("symlink (%d bytes): %m", size); + } + + char *readlink_result = xreadlink (symlink_name); + TEST_VERIFY (strcmp (readlink_result, contents) == 0); + free (readlink_result); + xunlink (symlink_name); + free (contents); + } + + /* Create an empty file to suppress the temporary file deletion + warning. */ + xclose (xopen (symlink_name, O_WRONLY | O_CREAT, 0)); + + free (symlink_name); + free (dir); + + return 0; +} + +#include diff --git a/support/xreadlink.c b/support/xreadlink.c new file mode 100644 index 0000000000..aec58a2aa6 --- /dev/null +++ b/support/xreadlink.c @@ -0,0 +1,44 @@ +/* Error-checking, allocating wrapper for readlink. + Copyright (C) 2017 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + . */ + +#include +#include +#include +#include + +char * +xreadlink (const char *path) +{ + struct scratch_buffer buf; + scratch_buffer_init (&buf); + + while (true) + { + ssize_t count = readlink (path, buf.data, buf.length); + if (count < 0) + FAIL_EXIT1 ("readlink (\"%s\"): %m", path); + if (count < buf.length) + { + char *result = xstrndup (buf.data, count); + scratch_buffer_free (&buf); + return result; + } + if (!scratch_buffer_grow (&buf)) + FAIL_EXIT1 ("scratch_buffer_grow in xreadlink"); + } +} diff --git a/support/xstrndup.c b/support/xstrndup.c new file mode 100644 index 0000000000..d59a283d25 --- /dev/null +++ b/support/xstrndup.c @@ -0,0 +1,30 @@ +/* strndup with error checking. + Copyright (C) 2016-2017 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + . */ + +#include + +#include + +char * +xstrndup (const char *s, size_t length) +{ + char *p = strndup (s, length); + if (p == NULL) + oom_error ("strndup", length); + return p; +} diff --git a/support/xunistd.h b/support/xunistd.h index c947bfd8fb..05c2626a7b 100644 --- a/support/xunistd.h +++ b/support/xunistd.h @@ -38,6 +38,11 @@ int xopen (const char *path, int flags, mode_t); void xstat (const char *path, struct stat64 *); void xmkdir (const char *path, mode_t); void xchroot (const char *path); +void xunlink (const char *path); + +/* Read the link at PATH. The caller should free the returned string + with free. */ +char *xreadlink (const char *path); /* Close the file descriptor. Ignore EINTR errors, but terminate the process on other errors. */ diff --git a/support/xunlink.c b/support/xunlink.c new file mode 100644 index 0000000000..f94ee118cf --- /dev/null +++ b/support/xunlink.c @@ -0,0 +1,27 @@ +/* Error-checking wrapper for unlink. + Copyright (C) 2017 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + . */ + +#include +#include + +void +xunlink (const char *path) +{ + if (unlink (path) != 0) + FAIL_EXIT1 ("unlink (\"%s\"): %m", path); +} -- cgit v1.2.3