(root)/
strace-6.5/
tests-m32/
dev-yy.c
       1  /*
       2   * Check printing of character/block device numbers in -yy mode.
       3   *
       4   * Copyright (c) 2018-2021 The strace developers.
       5   * All rights reserved.
       6   *
       7   * SPDX-License-Identifier: GPL-2.0-or-later
       8   */
       9  
      10  #include "tests.h"
      11  
      12  #include <stdio.h>
      13  #include <unistd.h>
      14  
      15  #include "scno.h"
      16  
      17  #include <linux/fcntl.h>
      18  
      19  #include <sys/sysmacros.h>
      20  
      21  #ifndef PRINT_PATH
      22  # define PRINT_PATH 1
      23  #endif
      24  
      25  #ifndef PRINT_DEVNUM
      26  # if PRINT_PATH
      27  #  define PRINT_DEVNUM 1
      28  # else
      29  #  define PRINT_DEVNUM 0
      30  # endif
      31  #endif
      32  
      33  #ifndef PRINT_AT_FDCWD_PATH
      34  # define PRINT_AT_FDCWD_PATH PRINT_DEVNUM
      35  #endif
      36  
      37  #if PRINT_DEVNUM
      38  # define DEV_FMT "<%s<%s %u:%u>>"
      39  #elif PRINT_PATH
      40  # define DEV_FMT "<%s>"
      41  #else
      42  # define DEV_FMT ""
      43  #endif
      44  
      45  #if defined __NR_openat && defined O_PATH
      46  
      47  int
      48  main(void)
      49  {
      50  	skip_if_unavailable("/proc/self/fd/");
      51  # if PRINT_AT_FDCWD_PATH
      52  	char *cwd = get_fd_path(get_dir_fd("."));
      53  # endif
      54  
      55  	static const struct {
      56  		const char *path;
      57  		unsigned int major;
      58  		unsigned int minor;
      59  		bool blk;
      60  		bool optional;
      61  	} checks[] = {
      62  		{ "/dev/zero", 1, 5, false, false },
      63  		{ "/dev/full", 1, 7, false, false },
      64  		{ "/dev/sda",  8, 0, true,  true  },
      65  	};
      66  
      67  	for (unsigned int i = 0; i < ARRAY_SIZE(checks); i++) {
      68  		/*
      69  		 * We can't have nice things here and call openat() directly as
      70  		 * some libcs (yes, musl, I'm looking at you now) are too
      71  		 * frivolous in passing flags to the kernel.
      72  		 */
      73  		long fd = syscall(__NR_openat, AT_FDCWD, checks[i].path,
      74  				  O_RDONLY|O_PATH);
      75  
      76  		printf("openat(AT_FDCWD"
      77  # if PRINT_AT_FDCWD_PATH
      78  		       "<%s>"
      79  # endif
      80  		       ", \"%s\", O_RDONLY|O_PATH) = %s",
      81  # if PRINT_AT_FDCWD_PATH
      82  		       cwd,
      83  # endif
      84  		       checks[i].path, sprintrc(fd));
      85  # if PRINT_PATH
      86  		if (fd >= 0)
      87  			printf(DEV_FMT,
      88  			       checks[i].path
      89  #  if PRINT_DEVNUM
      90  			       , checks[i].blk ? "block" : "char",
      91  			       checks[i].major, checks[i].minor
      92  #  endif
      93  			       );
      94  # endif
      95  		puts("");
      96  
      97  		if (fd < 0) {
      98  			if (checks[i].optional)
      99  				continue;
     100  			else
     101  				perror_msg_and_fail("openat(\"%s\")",
     102  						    checks[i].path);
     103  		}
     104  
     105  		int rc = fsync(fd);
     106  
     107  		printf("fsync(%ld" DEV_FMT ") = %s\n",
     108  		       fd,
     109  # if PRINT_PATH
     110  		       checks[i].path,
     111  #  if PRINT_DEVNUM
     112  		       checks[i].blk ? "block" : "char",
     113  		       checks[i].major, checks[i].minor,
     114  #  endif
     115  # endif
     116  		       sprintrc(rc));
     117  
     118  		close(fd);
     119  	}
     120  
     121  	puts("+++ exited with 0 +++");
     122  	return 0;
     123  }
     124  
     125  #else
     126  
     127  SKIP_MAIN_UNDEFINED("__NR_openat && O_PATH")
     128  
     129  #endif