(root)/
glibc-2.38/
io/
test-lfs.c
       1  /* Some basic tests for LFS.
       2     Copyright (C) 2000-2023 Free Software Foundation, Inc.
       3     This file is part of the GNU C Library.
       4  
       5     The GNU C Library is free software; you can redistribute it and/or
       6     modify it under the terms of the GNU Lesser General Public
       7     License as published by the Free Software Foundation; either
       8     version 2.1 of the License, or (at your option) any later version.
       9  
      10     The GNU C Library is distributed in the hope that it will be useful,
      11     but WITHOUT ANY WARRANTY; without even the implied warranty of
      12     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
      13     Lesser General Public License for more details.
      14  
      15     You should have received a copy of the GNU Lesser General Public
      16     License along with the GNU C Library; if not, see
      17     <https://www.gnu.org/licenses/>.  */
      18  
      19  #include <unistd.h>
      20  #include <stdlib.h>
      21  #include <sys/types.h>
      22  #include <sys/stat.h>
      23  #include <fcntl.h>
      24  #include <error.h>
      25  #include <errno.h>
      26  #include <sys/resource.h>
      27  #include <support/check.h>
      28  
      29  /* Prototype for our test function.  */
      30  extern void do_prepare (int argc, char *argv[]);
      31  extern int do_test (int argc, char *argv[]);
      32  
      33  /* We have a preparation function.  */
      34  #define PREPARE do_prepare
      35  
      36  /* This defines the `main' function and some more.  */
      37  #include <test-skeleton.c>
      38  
      39  /* These are for the temporary file we generate.  */
      40  char *name;
      41  int fd;
      42  
      43  /* 2^31 = 2GB.  */
      44  #define TWO_GB 2147483648LL
      45  
      46  void
      47  do_prepare (int argc, char *argv[])
      48  {
      49    size_t name_len;
      50    struct rlimit64 rlim;
      51  
      52    name_len = strlen (test_dir);
      53    name = xmalloc (name_len + sizeof ("/lfsXXXXXX"));
      54    mempcpy (mempcpy (name, test_dir, name_len),
      55             "/lfsXXXXXX", sizeof ("/lfsXXXXXX"));
      56  
      57    /* Open our test file.   */
      58    fd = mkstemp64 (name);
      59    if (fd == -1)
      60      {
      61        if (errno == ENOSYS)
      62  	{
      63  	  /* Fail silently.  */
      64  	  error (0, 0, "open64 is not supported");
      65  	  exit (EXIT_SUCCESS);
      66  	}
      67        else
      68  	error (EXIT_FAILURE, errno, "cannot create temporary file");
      69      }
      70    if (!support_descriptor_supports_holes (fd))
      71      FAIL_UNSUPPORTED ("File %s does not support holes", name);
      72    add_temp_file (name);
      73  
      74    if (getrlimit64 (RLIMIT_FSIZE, &rlim) != 0)
      75      {
      76        error (0, errno, "cannot get resource limit");
      77        exit (0);
      78      }
      79    if (rlim.rlim_cur < TWO_GB + 200)
      80      {
      81        rlim.rlim_cur = TWO_GB + 200;
      82        if (setrlimit64 (RLIMIT_FSIZE, &rlim) != 0)
      83  	{
      84  	  error (0, errno, "cannot reset file size limits");
      85  	  exit (0);
      86  	}
      87      }
      88  }
      89  
      90  static void
      91  test_ftello (void)
      92  {
      93    FILE *f;
      94    int ret;
      95    off64_t pos;
      96  
      97    f = fopen64 (name, "w");
      98  
      99    ret = fseeko64 (f, TWO_GB+100, SEEK_SET);
     100    if (ret == -1 && errno == ENOSYS)
     101      {
     102        error (0, 0, "fseeko64 is not supported.");
     103        exit (EXIT_SUCCESS);
     104      }
     105    if (ret == -1 && errno == EINVAL)
     106      {
     107        error (0, 0, "LFS seems not to be supported");
     108        exit (EXIT_SUCCESS);
     109      }
     110    if (ret == -1)
     111      {
     112        error (0, errno, "fseeko64 failed with error");
     113        exit (EXIT_FAILURE);
     114      }
     115  
     116    ret = fwrite ("Hello", 1, 5, f);
     117    if (ret == -1 && errno == EFBIG)
     118      {
     119        error (0, errno, "LFS seems not to be supported");
     120        exit (EXIT_SUCCESS);
     121      }
     122  
     123    if (ret == -1 && errno == ENOSPC)
     124      {
     125        error (0, 0, "Not enough space to write file.");
     126        exit (EXIT_SUCCESS);
     127      }
     128  
     129    if (ret != 5)
     130      error (EXIT_FAILURE, errno, "Cannot write test string to large file");
     131  
     132    pos = ftello64 (f);
     133  
     134    if (pos != TWO_GB+105)
     135      {
     136        error (0, 0, "ftello64 gives wrong result.");
     137        exit (EXIT_FAILURE);
     138      }
     139  
     140    fclose (f);
     141  }
     142  
     143  int
     144  do_test (int argc, char *argv[])
     145  {
     146    int ret, fd2;
     147    struct stat64 statbuf;
     148  
     149    ret = lseek64 (fd, TWO_GB+100, SEEK_SET);
     150    if (ret == -1 && errno == ENOSYS)
     151      {
     152        error (0, 0, "lseek64 is not supported.");
     153        exit (EXIT_SUCCESS);
     154      }
     155    if (ret == -1 && errno == EINVAL)
     156      {
     157        error (0, 0, "LFS seems not to be supported.");
     158        exit (EXIT_SUCCESS);
     159      }
     160    if (ret == -1)
     161      {
     162        error (0, errno, "lseek64 failed with error");
     163        exit (EXIT_FAILURE);
     164      }
     165    off64_t offset64 = lseek64 (fd, 0, SEEK_CUR);
     166    if (offset64 != TWO_GB + 100)
     167      {
     168        error (0, 0, "lseek64 did not return expected offset");
     169        exit (EXIT_FAILURE);
     170      }
     171    off_t offset = lseek (fd, 0, SEEK_CUR);
     172    if (sizeof (off_t) < sizeof (off64_t))
     173      {
     174        if (offset != -1 || errno != EOVERFLOW)
     175  	{
     176  	  error (0, 0, "lseek did not fail with EOVERFLOW");
     177  	  exit (EXIT_FAILURE);
     178  	}
     179      }
     180    else
     181      if (offset != TWO_GB + 100)
     182        {
     183  	error (0, 0, "lseek did not return expected offset");
     184  	exit (EXIT_FAILURE);
     185        }
     186  
     187    ret = write (fd, "Hello", 5);
     188    if (ret == -1 && errno == EFBIG)
     189      {
     190        error (0, 0, "LFS seems not to be supported.");
     191        exit (EXIT_SUCCESS);
     192      }
     193  
     194    if (ret == -1 && errno == ENOSPC)
     195      {
     196        error (0, 0, "Not enough space to write file.");
     197        exit (EXIT_SUCCESS);
     198      }
     199  
     200    if (ret != 5)
     201      error (EXIT_FAILURE, errno, "cannot write test string to large file");
     202  
     203    ret = close (fd);
     204  
     205    if (ret == -1)
     206      error (EXIT_FAILURE, errno, "error closing file");
     207  
     208    ret = stat64 (name, &statbuf);
     209  
     210    if (ret == -1 && (errno == ENOSYS || errno == EOVERFLOW))
     211      error (0, 0, "stat64 is not supported.");
     212    else if (ret == -1)
     213      error (EXIT_FAILURE, errno, "cannot stat file `%s'", name);
     214    else if (statbuf.st_size != (TWO_GB + 100 + 5))
     215      error (EXIT_FAILURE, 0, "stat reported size %lld instead of %lld.",
     216  	   (long long int) statbuf.st_size, (TWO_GB + 100 + 5));
     217  
     218    fd2 = openat64 (AT_FDCWD, name, O_RDWR);
     219    if (fd2 == -1)
     220      {
     221        if (errno == ENOSYS)
     222  	{
     223  	  /* Silently ignore this test.  */
     224  	  error (0, 0, "openat64 is not supported");
     225  	}
     226        else
     227  	error (EXIT_FAILURE, errno, "openat64 failed to open big file");
     228      }
     229    else
     230      {
     231        ret = close (fd2);
     232  
     233        if (ret == -1)
     234  	error (EXIT_FAILURE, errno, "error closing file");
     235      }
     236  
     237    test_ftello ();
     238  
     239    return 0;
     240  }