예제 #1
0
/* Open a directory stream on NAME.  */
DIR *
__opendir (const char *name)
{
  struct stat64 statbuf;

  if (__builtin_expect (name[0], '\1') == '\0')
    {
      /* POSIX.1-1990 says an empty name gets ENOENT;
	 but `open' might like it fine.  */
      __set_errno (ENOENT);
      return NULL;
    }

#ifdef O_DIRECTORY
  /* Test whether O_DIRECTORY works.  */
  if (o_directory_works == 0)
    tryopen_o_directory ();

  /* We can skip the expensive `stat' call if O_DIRECTORY works.  */
  if (o_directory_works < 0)
#endif
    {
      /* We first have to check whether the name is for a directory.  We
	 cannot do this after the open() call since the open/close operation
	 performed on, say, a tape device might have undesirable effects.  */
      if (__builtin_expect (__xstat64 (_STAT_VER, name, &statbuf), 0) < 0)
	return NULL;
      if (__builtin_expect (! S_ISDIR (statbuf.st_mode), 0))
	{
	  __set_errno (ENOTDIR);
	  return NULL;
	 }
    }

  int fd = open_not_cancel_2 (name, O_RDONLY|O_NDELAY|EXTRA_FLAGS|O_LARGEFILE);
  if (__builtin_expect (fd, 0) < 0)
    return NULL;

  /* Now make sure this really is a directory and nothing changed since
     the `stat' call.  We do not have to perform the test for the
     descriptor being associated with a directory if we know the
     O_DIRECTORY flag is honored by the kernel.  */
  if (__builtin_expect (__fxstat64 (_STAT_VER, fd, &statbuf), 0) < 0)
    goto lose;
#ifdef O_DIRECTORY
  if (o_directory_works <= 0)
#endif
    {
      if (__builtin_expect (! S_ISDIR (statbuf.st_mode), 0))
	{
	  __set_errno (ENOTDIR);
	lose:
	  close_not_cancel_no_status (fd);
	  return NULL;
	}
    }

  return __alloc_dir (fd, true, &statbuf);
}
예제 #2
0
static bool
need_isdir_precheck (void)
{
#ifdef O_DIRECTORY
  /* Test whether O_DIRECTORY works.  */
  if (o_directory_works == 0)
    tryopen_o_directory ();

  /* We can skip the expensive `stat' call if O_DIRECTORY works.  */
  return o_directory_works < 0;
#endif
  return true;
}
예제 #3
0
파일: opendir.c 프로젝트: dreal/tai
internal_function
__opendirat (int dfd, const char *name)
{
  struct stat64 statbuf;
  struct stat64 *statp = NULL;

  if (__builtin_expect (name[0], '\1') == '\0')
    {
      /* POSIX.1-1990 says an empty name gets ENOENT;
	 but `open' might like it fine.  */
      __set_errno (ENOENT);
      return NULL;
    }

#ifdef O_DIRECTORY
  /* Test whether O_DIRECTORY works.  */
  if (o_directory_works == 0)
    tryopen_o_directory ();

  /* We can skip the expensive `stat' call if O_DIRECTORY works.  */
  if (o_directory_works < 0)
#endif
    {
      /* We first have to check whether the name is for a directory.  We
	 cannot do this after the open() call since the open/close operation
	 performed on, say, a tape device might have undesirable effects.  */
      if (__builtin_expect (__xstat64 (_STAT_VER, name, &statbuf), 0) < 0)
	return NULL;
      if (__builtin_expect (! S_ISDIR (statbuf.st_mode), 0))
	{
	  __set_errno (ENOTDIR);
	  return NULL;
	 }
    }

  int flags = O_RDONLY|O_NDELAY|EXTRA_FLAGS|O_LARGEFILE;
#ifdef O_CLOEXEC
  flags |= O_CLOEXEC;
#endif
  int fd;
#ifdef IS_IN_rtld
  assert (dfd == AT_FDCWD);
  fd = open_not_cancel_2 (name, flags);
#else
  fd = openat_not_cancel_3 (dfd, name, flags);
#endif
  if (__builtin_expect (fd, 0) < 0)
    return NULL;

#ifdef O_DIRECTORY
  if (o_directory_works <= 0)
#endif
    {
      /* Now make sure this really is a directory and nothing changed since
	 the `stat' call.  */
      if (__builtin_expect (__fxstat64 (_STAT_VER, fd, &statbuf), 0) < 0)
	goto lose;
      if (__builtin_expect (! S_ISDIR (statbuf.st_mode), 0))
	{
	  __set_errno (ENOTDIR);
	lose:
	  close_not_cancel_no_status (fd);
	  return NULL;
	}
      statp = &statbuf;
    }

  return __alloc_dir (fd, true, 0, statp);
}
예제 #4
0
/* Open a directory stream on NAME.  */
DIR *
__opendir (const char *name)
{
    DIR *dirp;
    struct stat64 statbuf;
    int fd;
    size_t allocation;
    int save_errno;

    if (__builtin_expect (name[0], '\1') == '\0')
    {
        /* POSIX.1-1990 says an empty name gets ENOENT;
        but `open' might like it fine.  */
        __set_errno (ENOENT);
        return NULL;
    }

#ifdef O_DIRECTORY
    /* Test whether O_DIRECTORY works.  */
    if (o_directory_works == 0)
        tryopen_o_directory ();

    /* We can skip the expensive `stat' call if O_DIRECTORY works.  */
    if (o_directory_works < 0)
#endif
    {
        /* We first have to check whether the name is for a directory.  We
        cannot do this after the open() call since the open/close operation
         performed on, say, a tape device might have undesirable effects.  */
        if (__builtin_expect (__xstat64 (_STAT_VER, name, &statbuf), 0) < 0)
            return NULL;
        if (__builtin_expect (! S_ISDIR (statbuf.st_mode), 0))
        {
            __set_errno (ENOTDIR);
            return NULL;
        }
    }

    fd = open_not_cancel_2 (name, O_RDONLY|O_NDELAY|EXTRA_FLAGS|O_LARGEFILE);
    if (__builtin_expect (fd, 0) < 0)
        return NULL;

    /* Now make sure this really is a directory and nothing changed since
       the `stat' call.  We do not have to perform the test for the
       descriptor being associated with a directory if we know the
       O_DIRECTORY flag is honored by the kernel.  */
    if (__builtin_expect (__fxstat64 (_STAT_VER, fd, &statbuf), 0) < 0)
        goto lose;
#ifdef O_DIRECTORY
    if (o_directory_works <= 0)
#endif
    {
        if (__builtin_expect (! S_ISDIR (statbuf.st_mode), 0))
        {
            save_errno = ENOTDIR;
            goto lose;
        }
    }

    if (__builtin_expect (__fcntl (fd, F_SETFD, FD_CLOEXEC), 0) < 0)
        goto lose;

#ifdef _STATBUF_ST_BLKSIZE
    if (__builtin_expect ((size_t) statbuf.st_blksize >= sizeof (struct dirent64),
                          1))
        allocation = statbuf.st_blksize;
    else
#endif
        allocation = (BUFSIZ < sizeof (struct dirent64)
                      ? sizeof (struct dirent64) : BUFSIZ);

    const int pad = -sizeof (DIR) % __alignof__ (struct dirent64);

    dirp = (DIR *) malloc (sizeof (DIR) + allocation + pad);
    if (dirp == NULL)
lose:
    {
        save_errno = errno;
        close_not_cancel_no_status (fd);
        __set_errno (save_errno);
        return NULL;
    }
    memset (dirp, '\0', sizeof (DIR));
    dirp->data = (char *) (dirp + 1) + pad;
    dirp->allocation = allocation;
    dirp->fd = fd;

    __libc_lock_init (dirp->lock);

    return dirp;
}