(root)/
strace-6.5/
tests-mx32/
xgetdents.c
       1  /*
       2   * Check decoding of getdents and getdents64 syscalls.
       3   *
       4   * Copyright (c) 2015-2020 Dmitry V. Levin <ldv@strace.io>
       5   * All rights reserved.
       6   *
       7   * SPDX-License-Identifier: GPL-2.0-or-later
       8   */
       9  
      10  #include <dirent.h>
      11  #include <fcntl.h>
      12  #include <stdio.h>
      13  #include <unistd.h>
      14  #include <sys/stat.h>
      15  #include "kernel_dirent.h"
      16  #include "print_fields.h"
      17  
      18  #if VERBOSE
      19  static const char *
      20  str_d_type(const unsigned char d_type)
      21  {
      22  	switch (d_type) {
      23  		case DT_DIR:
      24  			return "DT_DIR";
      25  		case DT_REG:
      26  			return "DT_REG";
      27  		default:
      28  			return "DT_UNKNOWN";
      29  	}
      30  }
      31  
      32  static void
      33  print_dirent(const kernel_dirent_type *d);
      34  #endif
      35  
      36  static const char *errstr;
      37  
      38  static long
      39  k_getdents(const unsigned int fd,
      40  	   const void *dirp,
      41  	   const unsigned int count)
      42  {
      43  	const kernel_ulong_t fill = (kernel_ulong_t) 0xdefaced00000000ULL;
      44  	const kernel_ulong_t bad = (kernel_ulong_t) 0xbadc0dedbadc0dedULL;
      45  	const kernel_ulong_t arg1 = fill | fd;
      46  	const kernel_ulong_t arg2 = (uintptr_t) dirp;
      47  	const kernel_ulong_t arg3 = fill | count;
      48  	const long rc = syscall(NR_getdents, arg1, arg2, arg3, bad, bad, bad);
      49  	errstr = sprintrc(rc);
      50  	return rc;
      51  }
      52  
      53  static void
      54  ls(int fd, char *buf, unsigned int size)
      55  {
      56  	long rc;
      57  	while ((rc = k_getdents(fd, buf, size))) {
      58  		if (rc < 0)
      59  			perror_msg_and_skip(STR_getdents);
      60  		printf("%s(%d, ", STR_getdents, fd);
      61  #if VERBOSE
      62  		printf("[");
      63  #else
      64  		unsigned long entries = 0;
      65  #endif
      66  		kernel_dirent_type *d;
      67  		for (long i = 0; i < rc; i += d->d_reclen) {
      68  			d = (kernel_dirent_type *) &buf[i];
      69  #if VERBOSE
      70  			if (i)
      71  				printf(", ");
      72  			print_dirent(d);
      73  #else
      74  			++entries;
      75  #endif
      76  		}
      77  #if VERBOSE
      78  		printf("]");
      79  #else
      80  		printf("%p /* %lu entries */", buf, entries);
      81  #endif
      82  		printf(", %u) = %ld\n", size, rc);
      83  	}
      84  #if VERBOSE
      85  	printf("%s(%d, [], %u) = 0\n", STR_getdents, fd, size);
      86  #else
      87  	printf("%s(%d, %p /* 0 entries */, %u) = 0\n",
      88  	       STR_getdents, fd, buf, size);
      89  #endif
      90  }
      91  
      92  int
      93  main(void)
      94  {
      95  	static const char dot[] = ".";
      96  	static const char dot_dot[] = "..";
      97  	static const char dname[] = STR_getdents
      98  #if VERBOSE
      99  		"-v"
     100  #endif
     101  		".test.tmp.dir";
     102  	static const char fname[] =
     103  		"A\nA\nA\nA\nA\nA\nA\nA\nA\nA\nA\nA\nA\nA\nA\nA\n"
     104  		"A\nA\nA\nA\nA\nA\nA\nA\nA\nA\nA\nA\nA\nA\nA\nA\n"
     105  		"A\nA\nA\nA\nA\nA\nA\nA\nA\nA\nA\nA\nA\nA\nA\nA\n"
     106  		"A\nA\nA\nA\nA\nA\nA\nA\nA\nA\nA\nA\nA\nA\nA\nA\n"
     107  		"A\nA\nA\nA\nA\nA\nA\nA\nA\nA\nA\nA\nA\nA\nA\nA\n"
     108  		"A\nA\nA\nA\nA\nA\nA\nA\nA\nA\nA\nA\nA\nA\nA\nA\n"
     109  		"A\nA\nA\nA\nA\nA\nA\nA\nA\nA\nA\nA\nA\nA\nA\nA\n"
     110  		"A\nA\nA\nA\nA\nA\nA\nA\nA\nA\nA\nA\nA\nA\nA\nZ";
     111  
     112  	if (mkdir(dname, 0700))
     113  		perror_msg_and_fail("mkdir: %s", dname);
     114  	if (chdir(dname))
     115  		perror_msg_and_fail("chdir: %s", dname);
     116  	int fd = creat(fname, 0600);
     117  	if (fd < 0)
     118  		perror_msg_and_fail("creat: %s", fname);
     119  	if (close(fd))
     120  		perror_msg_and_fail("close: %s", fname);
     121  	fd = open(dot, O_RDONLY | O_DIRECTORY);
     122  	if (fd < 0)
     123  		perror_msg_and_fail("open: %s", dot);
     124  
     125  	unsigned int count = 0xdeadbeefU;
     126  	k_getdents(-1U, NULL, count);
     127  	printf("%s(-1, NULL, %u) = %s\n", STR_getdents, count, errstr);
     128  
     129  	static char buf[8192];
     130  	ls(fd, buf, sizeof(buf));
     131  
     132  	if (unlink(fname))
     133  		perror_msg_and_fail("unlink: %s", fname);
     134  	if (chdir(dot_dot))
     135  		perror_msg_and_fail("chdir: %s", dot_dot);
     136  	if (rmdir(dname))
     137  		perror_msg_and_fail("rmdir: %s", dname);
     138  
     139  	puts("+++ exited with 0 +++");
     140  	return 0;
     141  }