(root)/
glibc-2.38/
io/
bug-ftw4.c
       1  /* Test if ftw function doesn't leak fds.
       2     Copyright (C) 2003-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 <fcntl.h>
      20  #include <ftw.h>
      21  #include <stdlib.h>
      22  #include <stdio.h>
      23  #include <string.h>
      24  #include <sys/stat.h>
      25  #include <unistd.h>
      26  
      27  static int cb_called;
      28  
      29  static int
      30  cb (const char *name, const struct stat64 *st, int type)
      31  {
      32    return cb_called++ & 1;
      33  }
      34  
      35  int
      36  main (void)
      37  {
      38    char name[32] = "/tmp/ftwXXXXXX", *p;
      39    int ret, i, result = 0, fd, fd1, fd2;
      40  
      41    if (mkdtemp (name) == NULL)
      42      {
      43        printf ("Couldn't make temporary directory: %m\n");
      44        exit (EXIT_FAILURE);
      45      }
      46    p = strchr (name, '\0');
      47    strcpy (p, "/1");
      48    if (mkdir (name, 0755) < 0)
      49      {
      50        printf ("Couldn't make temporary subdirectory: %m\n");
      51        exit (EXIT_FAILURE);
      52      }
      53    *p = '\0';
      54  
      55    ret = ftw64 (name, cb, 20);
      56    if (ret != 1)
      57      {
      58        printf ("ftw64 returned %d instead of 1", ret);
      59        result = 1;
      60      }
      61  
      62    fd = open (name, O_RDONLY);
      63    if (fd < 0)
      64      {
      65        printf ("open failed: %m\n");
      66        result = 1;
      67      }
      68    fd1 = open (name, O_RDONLY);
      69    if (fd1 < 0)
      70      {
      71        printf ("open failed: %m\n");
      72        result = 1;
      73      }
      74    else
      75      close (fd1);
      76    if (fd >= 0)
      77      close (fd);
      78  
      79    for (i = 0; i < 128; ++i)
      80      {
      81        ret = ftw64 (name, cb, 20);
      82        if (ret != 1)
      83  	{
      84  	  printf ("ftw64 returned %d instead of 1", ret);
      85  	  result = 1;
      86  	}
      87      }
      88  
      89    fd = open (name, O_RDONLY);
      90    if (fd < 0)
      91      {
      92        printf ("open failed: %m\n");
      93        result = 1;
      94      }
      95    fd2 = open (name, O_RDONLY);
      96    if (fd2 < 0)
      97      {
      98        printf ("open failed: %m\n");
      99        result = 1;
     100      }
     101    else
     102      close (fd2);
     103    if (fd >= 0)
     104      close (fd);
     105  
     106    if (fd2 >= fd1 + 128)
     107      {
     108        printf ("ftw64 leaking fds: %d -> %d\n", fd1, fd2);
     109        result = 1;
     110      }
     111  
     112    if (cb_called != 129 * 2)
     113      {
     114        printf ("callback called %d times\n", cb_called);
     115        result = 1;
     116      }
     117  
     118    strcpy (p, "/1");
     119    rmdir (name);
     120    *p = '\0';
     121    rmdir (name);
     122    return result;
     123  }