1 /* Test for /proc/self/fd (or /dev/fd) pathname construction.
2    Copyright (C) 2020-2022 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 <fcntl.h>
20 #include <fd_to_filename.h>
21 #include <stdio.h>
22 #include <support/check.h>
23 #include <support/xunistd.h>
24 
25 /* Run a check on one value.  */
26 static void
check(int value)27 check (int value)
28 {
29   if (value < 0)
30     /* Negative descriptor values violate the precondition.  */
31     return;
32 
33   struct fd_to_filename storage;
34   char *actual = __fd_to_filename (value, &storage);
35   char expected[100];
36   snprintf (expected, sizeof (expected), FD_TO_FILENAME_PREFIX "%d", value);
37   TEST_COMPARE_STRING (actual, expected);
38 }
39 
40 /* Check various ranges constructed around powers.  */
41 static void
check_ranges(int base)42 check_ranges (int base)
43 {
44   unsigned int power = 1;
45   do
46     {
47       for (int factor = 1; factor < base; ++factor)
48         for (int shift = -1000; shift <= 1000; ++shift)
49           check (factor * power + shift);
50     }
51   while (!__builtin_mul_overflow (power, base, &power));
52 }
53 
54 /* Check that it is actually possible to use a the constructed
55    name.  */
56 static void
check_open(void)57 check_open (void)
58 {
59   int pipes[2];
60   xpipe (pipes);
61 
62   struct fd_to_filename storage;
63   int read_alias = xopen (__fd_to_filename (pipes[0], &storage), O_RDONLY, 0);
64   int write_alias = xopen (__fd_to_filename (pipes[1], &storage), O_WRONLY, 0);
65 
66   /* Ensure that all the descriptor numbers are different.  */
67   TEST_VERIFY (pipes[0] < pipes[1]);
68   TEST_VERIFY (pipes[1] < read_alias);
69   TEST_VERIFY (read_alias < write_alias);
70 
71   xwrite (write_alias, "1", 1);
72   char buf[16];
73   TEST_COMPARE_BLOB ("1", 1, buf, read (pipes[0], buf, sizeof (buf)));
74 
75   xwrite (pipes[1], "2", 1);
76   TEST_COMPARE_BLOB ("2", 1, buf, read (read_alias, buf, sizeof (buf)));
77 
78   xwrite (write_alias, "3", 1);
79   TEST_COMPARE_BLOB ("3", 1, buf, read (read_alias, buf, sizeof (buf)));
80 
81   xwrite (pipes[1], "4", 1);
82   TEST_COMPARE_BLOB ("4", 1, buf, read (pipes[0], buf, sizeof (buf)));
83 
84   xclose (write_alias);
85   xclose (read_alias);
86   xclose (pipes[1]);
87   xclose (pipes[0]);
88 }
89 
90 static int
do_test(void)91 do_test (void)
92 {
93   check_ranges (2);
94   check_ranges (10);
95 
96   check_open ();
97 
98   return 0;
99 }
100 
101 #include <support/test-driver.c>
102