(root)/
glibc-2.38/
io/
tst-statx.c
       1  /* Basic test of statx system call.
       2     Copyright (C) 2018-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 <errno.h>
      20  #include <stdbool.h>
      21  #include <stdint.h>
      22  #include <stdio.h>
      23  #include <stdlib.h>
      24  #include <support/check.h>
      25  #include <support/support.h>
      26  #include <support/temp_file.h>
      27  #include <support/xunistd.h>
      28  #include <sys/stat.h>
      29  #include <sys/syscall.h>
      30  #include <sys/sysmacros.h>
      31  #include <unistd.h>
      32  
      33  /* Ensure that the types have the kernel-expected layout.  */
      34  _Static_assert (sizeof (struct statx_timestamp) == 16, "statx_timestamp size");
      35  _Static_assert (sizeof (struct statx) == 256, "statx size");
      36  _Static_assert (offsetof (struct statx, stx_nlink) == 16, "statx nlink");
      37  _Static_assert (offsetof (struct statx, stx_ino) == 32, "statx ino");
      38  _Static_assert (offsetof (struct statx, stx_atime) == 64, "statx atime");
      39  _Static_assert (offsetof (struct statx, stx_rdev_major) == 128, "statx rdev");
      40  _Static_assert (offsetof (struct statx, __statx_pad2) == 144, "statx pad2");
      41  
      42  #include "statx_generic.c"
      43  
      44  typedef int (*statx_function) (int, const char *, int, unsigned int,
      45                                 struct statx *);
      46  
      47  /* Return true if we have a real implementation of statx.  */
      48  static bool
      49  kernel_supports_statx (void)
      50  {
      51  #ifdef __NR_statx
      52    struct statx buf;
      53    return syscall (__NR_statx, 0, "", AT_EMPTY_PATH, 0, &buf) == 0
      54      || errno != ENOSYS;
      55  #else
      56    return false;
      57  #endif
      58  }
      59  
      60  /* Tests which apply to both implementations.  */
      61  static void
      62  both_implementations_tests (statx_function impl, const char *path, int fd)
      63  {
      64    uint64_t ino;
      65    {
      66      struct statx buf = { 0, };
      67      TEST_COMPARE (statx (fd, "", AT_EMPTY_PATH, STATX_BASIC_STATS, &buf), 0);
      68      TEST_COMPARE (buf.stx_size, 3);
      69      ino = buf.stx_ino;
      70    }
      71    {
      72      struct statx buf = { 0, };
      73      TEST_COMPARE (statx (AT_FDCWD, path, 0, STATX_BASIC_STATS, &buf), 0);
      74      TEST_COMPARE (buf.stx_size, 3);
      75      TEST_COMPARE (buf.stx_ino, ino);
      76    }
      77    {
      78      struct statx stx = { 0, };
      79      TEST_COMPARE (statx (fd, "", AT_EMPTY_PATH, STATX_BASIC_STATS, &stx), 0);
      80      struct stat64 st;
      81      xfstat (fd, &st);
      82      TEST_COMPARE (stx.stx_mode, st.st_mode);
      83      TEST_COMPARE (stx.stx_dev_major, major (st.st_dev));
      84      TEST_COMPARE (stx.stx_dev_minor, minor (st.st_dev));
      85    }
      86    {
      87      struct statx stx = { 0, };
      88      TEST_COMPARE (statx (AT_FDCWD, "/dev/null", 0, STATX_BASIC_STATS, &stx),
      89                    0);
      90      struct stat64 st;
      91      xstat ("/dev/null", &st);
      92      TEST_COMPARE (stx.stx_mode, st.st_mode);
      93      TEST_COMPARE (stx.stx_dev_major, major (st.st_dev));
      94      TEST_COMPARE (stx.stx_dev_minor, minor (st.st_dev));
      95      TEST_COMPARE (stx.stx_rdev_major, major (st.st_rdev));
      96      TEST_COMPARE (stx.stx_rdev_minor, minor (st.st_rdev));
      97    }
      98  }
      99  
     100  /* Tests which apply only to the non-kernel (generic)
     101     implementation.  */
     102  static void
     103  non_kernel_tests (statx_function impl, int fd)
     104  {
     105    /* The non-kernel implementation must always fail for explicit sync
     106       flags.  */
     107    struct statx buf;
     108    errno = 0;
     109    TEST_COMPARE (impl (fd, "", AT_EMPTY_PATH | AT_STATX_FORCE_SYNC,
     110                        STATX_BASIC_STATS, &buf), -1);
     111    TEST_COMPARE (errno, EINVAL);
     112    errno = 0;
     113    TEST_COMPARE (impl (fd, "", AT_EMPTY_PATH | AT_STATX_DONT_SYNC,
     114                        STATX_BASIC_STATS, &buf), -1);
     115    TEST_COMPARE (errno, EINVAL);
     116  }
     117  
     118  static int
     119  do_test (void)
     120  {
     121    char *path;
     122    int fd = create_temp_file ("tst-statx-", &path);
     123    TEST_VERIFY_EXIT (fd >= 0);
     124    support_write_file_string (path, "abc");
     125  
     126    both_implementations_tests (&statx, path, fd);
     127    both_implementations_tests (&statx_generic, path, fd);
     128  
     129    if (kernel_supports_statx ())
     130      {
     131        puts ("info: kernel supports statx");
     132        struct statx buf;
     133        buf.stx_size = 0;
     134        TEST_COMPARE (statx (fd, "", AT_EMPTY_PATH | AT_STATX_FORCE_SYNC,
     135                             STATX_BASIC_STATS, &buf),
     136                      0);
     137        TEST_COMPARE (buf.stx_size, 3);
     138        buf.stx_size = 0;
     139        TEST_COMPARE (statx (fd, "", AT_EMPTY_PATH | AT_STATX_DONT_SYNC,
     140                             STATX_BASIC_STATS, &buf),
     141                      0);
     142        TEST_COMPARE (buf.stx_size, 3);
     143      }
     144    else
     145      {
     146        puts ("info: kernel does not support statx");
     147        non_kernel_tests (&statx, fd);
     148      }
     149    non_kernel_tests (&statx_generic, fd);
     150  
     151    xclose (fd);
     152    free (path);
     153  
     154    return 0;
     155  }
     156  
     157  #include <support/test-driver.c>