(root)/
glibc-2.38/
io/
tst-openat.c
       1  #include <dirent.h>
       2  #include <fcntl.h>
       3  #include <stdbool.h>
       4  #include <stdio.h>
       5  #include <stdlib.h>
       6  #include <string.h>
       7  #include <unistd.h>
       8  
       9  #include <support/xunistd.h>
      10  
      11  static void prepare (void);
      12  #define PREPARE(argc, argv) prepare ()
      13  
      14  static int do_test (void);
      15  #define TEST_FUNCTION do_test ()
      16  
      17  #include "../test-skeleton.c"
      18  
      19  static int dir_fd;
      20  
      21  static void
      22  prepare (void)
      23  {
      24    size_t test_dir_len = strlen (test_dir);
      25    static const char dir_name[] = "/tst-openat.XXXXXX";
      26  
      27    size_t dirbuflen = test_dir_len + sizeof (dir_name);
      28    char *dirbuf = malloc (dirbuflen);
      29    if (dirbuf == NULL)
      30      {
      31        puts ("out of memory");
      32        exit (1);
      33      }
      34  
      35    snprintf (dirbuf, dirbuflen, "%s%s", test_dir, dir_name);
      36    if (mkdtemp (dirbuf) == NULL)
      37      {
      38        puts ("cannot create temporary directory");
      39        exit (1);
      40      }
      41  
      42    add_temp_file (dirbuf);
      43  
      44    dir_fd = open (dirbuf, O_RDONLY | O_DIRECTORY);
      45    if (dir_fd == -1)
      46      {
      47        puts ("cannot open directory");
      48        exit (1);
      49      }
      50  }
      51  
      52  
      53  static int
      54  do_test (void)
      55  {
      56    /* fdopendir takes over the descriptor, make a copy.  */
      57    int dupfd = dup (dir_fd);
      58    if (dupfd == -1)
      59      {
      60        puts ("dup failed");
      61        return 1;
      62      }
      63    if (lseek (dupfd, 0, SEEK_SET) != 0)
      64      {
      65        puts ("1st lseek failed");
      66        return 1;
      67      }
      68  
      69    /* The directory should be empty safe the . and .. files.  */
      70    DIR *dir = fdopendir (dupfd);
      71    if (dir == NULL)
      72      {
      73        puts ("fdopendir failed");
      74        return 1;
      75      }
      76    struct dirent64 *d;
      77    while ((d = readdir64 (dir)) != NULL)
      78      if (strcmp (d->d_name, ".") != 0 && strcmp (d->d_name, "..") != 0)
      79        {
      80  	printf ("temp directory contains file \"%s\"\n", d->d_name);
      81  	return 1;
      82        }
      83    closedir (dir);
      84  
      85    /* Try to create a file.  */
      86    int fd = openat (dir_fd, "some-file", O_CREAT|O_RDWR|O_EXCL, 0666);
      87    if (fd == -1)
      88      {
      89        if (errno == ENOSYS)
      90  	{
      91  	  puts ("*at functions not supported");
      92  	  return 0;
      93  	}
      94  
      95        puts ("file creation failed");
      96        return 1;
      97      }
      98    xwrite (fd, "hello", 5);
      99  
     100    /* Before closing the file, try using this file descriptor to open
     101       another file.  This must fail.  */
     102    int fd2 = openat (fd, "should-not-work", O_CREAT|O_RDWR, 0666);
     103    if (fd2 != -1)
     104      {
     105        puts ("openat using descriptor for normal file worked");
     106        return 1;
     107      }
     108    if (errno != ENOTDIR)
     109      {
     110        puts ("error for openat using descriptor for normal file not ENOTDIR ");
     111        return 1;
     112      }
     113  
     114    close (fd);
     115    puts ("file created");
     116  
     117    /* fdopendir takes over the descriptor, make a copy.  */
     118    dupfd = dup (dir_fd);
     119    if (dupfd == -1)
     120      {
     121        puts ("dup failed");
     122        return 1;
     123      }
     124    if (lseek (dupfd, 0, SEEK_SET) != 0)
     125      {
     126        puts ("2nd lseek failed");
     127        return 1;
     128      }
     129  
     130    /* The directory should be empty safe the . and .. files.  */
     131    dir = fdopendir (dupfd);
     132    if (dir == NULL)
     133      {
     134        puts ("fdopendir failed");
     135        return 1;
     136      }
     137    bool seen_file = false;
     138    while ((d = readdir64 (dir)) != NULL)
     139      if (strcmp (d->d_name, ".") != 0 && strcmp (d->d_name, "..") != 0)
     140        {
     141  	if (strcmp (d->d_name, "some-file") != 0)
     142  	  {
     143  	    printf ("temp directory contains file \"%s\"\n", d->d_name);
     144  	    return 1;
     145  	  }
     146  
     147  	seen_file = true;
     148        }
     149    closedir (dir);
     150  
     151    if (!seen_file)
     152      {
     153        puts ("file not created in correct directory");
     154        return 1;
     155      }
     156  
     157    int cwdfd = open (".", O_RDONLY | O_DIRECTORY);
     158    if (cwdfd == -1)
     159      {
     160        puts ("cannot get descriptor for cwd");
     161        return 1;
     162      }
     163  
     164    if (fchdir (dir_fd) != 0)
     165      {
     166        puts ("1st fchdir failed");
     167        return 1;
     168      }
     169  
     170    if (unlink ("some-file") != 0)
     171      {
     172        puts ("unlink failed");
     173        return 1;
     174      }
     175  
     176    if (fchdir (cwdfd) != 0)
     177      {
     178        puts ("2nd fchdir failed");
     179        return 1;
     180      }
     181  
     182    close (dir_fd);
     183    close (cwdfd);
     184  
     185    /* With the file descriptor closed the next call must fail.  */
     186    fd = openat (dir_fd, "some-file", O_CREAT|O_RDWR|O_EXCL, 0666);
     187    if (fd != -1)
     188      {
     189        puts ("openat using closed descriptor succeeded");
     190        return 1;
     191      }
     192    if (errno != EBADF)
     193      {
     194        puts ("openat using closed descriptor did not set EBADF");
     195        return 1;
     196      }
     197  
     198    fd = openat (-1, "some-file", O_CREAT|O_RDWR|O_EXCL, 0666);
     199    if (fd != -1)
     200      {
     201        puts ("openat using -1 descriptor succeeded");
     202        return 1;
     203      }
     204    if (errno != EBADF)
     205      {
     206        puts ("openat using -1 descriptor did not set EBADF");
     207        return 1;
     208      }
     209  
     210    return 0;
     211  }