Blame sysdeps/wordsize-64/tst-writev.c

Packit Service 82fcde
/* Copyright (C) 2011-2018 Free Software Foundation, Inc.
Packit Service 82fcde
   This file is part of the GNU C Library.
Packit Service 82fcde
   Contributed by Ryan S. Arnold <rsa@us.ibm.com>, 2011.
Packit Service 82fcde
Packit Service 82fcde
   The GNU C Library is free software; you can redistribute it and/or
Packit Service 82fcde
   modify it under the terms of the GNU Lesser General Public
Packit Service 82fcde
   License as published by the Free Software Foundation; either
Packit Service 82fcde
   version 2.1 of the License, or (at your option) any later version.
Packit Service 82fcde
Packit Service 82fcde
   The GNU C Library is distributed in the hope that it will be useful,
Packit Service 82fcde
   but WITHOUT ANY WARRANTY; without even the implied warranty of
Packit Service 82fcde
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
Packit Service 82fcde
   Lesser General Public License for more details.
Packit Service 82fcde
Packit Service 82fcde
   You should have received a copy of the GNU Lesser General Public
Packit Service 82fcde
   License along with the GNU C Library; if not, see
Packit Service 82fcde
   <http://www.gnu.org/licenses/>.  */
Packit Service 82fcde
Packit Service 82fcde
#include <fcntl.h>
Packit Service 82fcde
#include <limits.h>
Packit Service 82fcde
#include <paths.h>
Packit Service 82fcde
#include <stdio.h>
Packit Service 82fcde
#include <stdint.h>
Packit Service 82fcde
#include <stdlib.h>
Packit Service 82fcde
#include <unistd.h>
Packit Service 82fcde
#include <sys/uio.h>
Packit Service 82fcde
Packit Service 82fcde
Packit Service 82fcde
/* The purpose of this test is to verify that the INTERNAL_[V]SYSCALL_NCS
Packit Service 82fcde
   macros on 64-bit platforms don't cast the return type to (int) which would
Packit Service 82fcde
   erroneously sign extend the return value should the high bit of the bottom
Packit Service 82fcde
   half of the word be '1'.  */
Packit Service 82fcde
Packit Service 82fcde
#if 0
Packit Service 82fcde
/* Used to test the non power-of-2 code path.  */
Packit Service 82fcde
#undef IOV_MAX
Packit Service 82fcde
#define IOV_MAX 1000
Packit Service 82fcde
#endif
Packit Service 82fcde
Packit Service 82fcde
/* writev() should report that it has written EXPECTED number of bytes.  */
Packit Service 82fcde
#define EXPECTED ((size_t) INT32_MAX + 1)
Packit Service 82fcde
Packit Service 82fcde
static int
Packit Service 82fcde
do_test (void)
Packit Service 82fcde
{
Packit Service 82fcde
  struct iovec iv[IOV_MAX];
Packit Service 82fcde
  /* POSIX doesn't guarantee that IOV_MAX is pow of 2 but we're optimistic.  */
Packit Service 82fcde
  size_t bufsz = EXPECTED / IOV_MAX;
Packit Service 82fcde
  size_t bufrem = EXPECTED % IOV_MAX;
Packit Service 82fcde
Packit Service 82fcde
  /* If there's a remainder then IOV_MAX probably isn't a power of 2 and we
Packit Service 82fcde
     need to make bufsz bigger so that the last iovec, iv[IOV_MAX-1], is free
Packit Service 82fcde
     for the remainder.  */
Packit Service 82fcde
  if (bufrem)
Packit Service 82fcde
    {
Packit Service 82fcde
      bufsz = bufsz + 1;
Packit Service 82fcde
      bufrem = EXPECTED - (bufsz * (IOV_MAX - 1));
Packit Service 82fcde
    }
Packit Service 82fcde
Packit Service 82fcde
  /* We writev to /dev/null since we're just testing writev's return value.  */
Packit Service 82fcde
  int fd = open (_PATH_DEVNULL, O_WRONLY);
Packit Service 82fcde
  if (fd == -1)
Packit Service 82fcde
    {
Packit Service 82fcde
      printf ("Unable to open /dev/null for writing.\n");
Packit Service 82fcde
      return -1;
Packit Service 82fcde
    }
Packit Service 82fcde
Packit Service 82fcde
  iv[0].iov_base = malloc (bufsz);
Packit Service 82fcde
  if (iv[0].iov_base == NULL)
Packit Service 82fcde
    {
Packit Service 82fcde
      printf ("malloc (%zu) failed.\n", bufsz);
Packit Service 82fcde
      close (fd);
Packit Service 82fcde
      return -1;
Packit Service 82fcde
    }
Packit Service 82fcde
  iv[0].iov_len = bufsz;
Packit Service 82fcde
Packit Service 82fcde
  /* We optimistically presume that there isn't a remainder and set all iovec
Packit Service 82fcde
     instances to the same base and len as the first instance.  */
Packit Service 82fcde
  for (int i = 1; i < IOV_MAX; i++)
Packit Service 82fcde
    {
Packit Service 82fcde
      /* We don't care what the data is so reuse the allocation from iv[0];  */
Packit Service 82fcde
      iv[i].iov_base = iv[0].iov_base;
Packit Service 82fcde
      iv[i].iov_len = iv[0].iov_len;
Packit Service 82fcde
    }
Packit Service 82fcde
Packit Service 82fcde
  /* If there is a remainder then we correct the last iov_len.  */
Packit Service 82fcde
  if (bufrem)
Packit Service 82fcde
    iv[IOV_MAX - 1].iov_len = bufrem;
Packit Service 82fcde
Packit Service 82fcde
  /* Write junk to /dev/null with the writev syscall in order to get a return
Packit Service 82fcde
     of INT32_MAX+1 bytes to verify that the INTERNAL_SYSCALL wrappers aren't
Packit Service 82fcde
     mangling the result if the signbit of a 32-bit number is set.  */
Packit Service 82fcde
  ssize_t ret = writev (fd, iv, IOV_MAX);
Packit Service 82fcde
Packit Service 82fcde
  free (iv[0].iov_base);
Packit Service 82fcde
  close (fd);
Packit Service 82fcde
Packit Service 82fcde
  if (ret != (ssize_t) EXPECTED)
Packit Service 82fcde
    {
Packit Service 82fcde
#ifdef ARTIFICIAL_LIMIT
Packit Service 82fcde
      if (ret != (ssize_t) ARTIFICIAL_LIMIT)
Packit Service 82fcde
#endif
Packit Service 82fcde
	{
Packit Service 82fcde
	  printf ("writev() return value: %zd != EXPECTED: %zd\n",
Packit Service 82fcde
		  ret, EXPECTED);
Packit Service 82fcde
	  return 1;
Packit Service 82fcde
	}
Packit Service 82fcde
    }
Packit Service 82fcde
Packit Service 82fcde
  return 0;
Packit Service 82fcde
}
Packit Service 82fcde
Packit Service 82fcde
/* Time enough for a large writev syscall to complete.  */
Packit Service 82fcde
#define TIMEOUT 20
Packit Service 82fcde
Packit Service 82fcde
#define TEST_FUNCTION do_test ()
Packit Service 82fcde
#include "../test-skeleton.c"