Beispiel #1
0
/* Return the pathname of the terminal FD is open on, or NULL on errors.
   The returned storage is good only until the next call to this function.  */
char *
ttyname (int fd)
{
  struct stat64 st, st1;
  int dostat = 0;
  char *name;
  int save = errno;
  struct termios term;

  /* isatty check, tcgetattr is used because it sets the correct
     errno (EBADF resp. ENOTTY) on error.  */
  if (__builtin_expect (__tcgetattr (fd, &term) < 0, 0))
    return NULL;

  if (__fxstat64 (_STAT_VER, fd, &st) < 0)
    return NULL;

  if (__xstat64 (_STAT_VER, "/dev/pts", &st1) == 0 && S_ISDIR (st1.st_mode))
    {
#ifdef _STATBUF_ST_RDEV
      name = getttyname ("/dev/pts", st.st_rdev, st.st_ino, save, &dostat);
#else
      name = getttyname ("/dev/pts", st.st_dev, st.st_ino, save, &dostat);
#endif
    }
  else
    {
      __set_errno (save);
      name = NULL;
    }

  if (!name && dostat != -1)
    {
#ifdef _STATBUF_ST_RDEV
      name = getttyname ("/dev", st.st_rdev, st.st_ino, save, &dostat);
#else
      name = getttyname ("/dev", st.st_dev, st.st_ino, save, &dostat);
#endif
    }

  if (!name && dostat != -1)
    {
      dostat = 1;
#ifdef _STATBUF_ST_RDEV
      name = getttyname ("/dev", st.st_rdev, st.st_ino, save, &dostat);
#else
      name = getttyname ("/dev", st.st_dev, st.st_ino, save, &dostat);
#endif
    }

  return name;
}
Beispiel #2
0
static int
internal_function
getttyname_r (char *buf, size_t buflen, dev_t mydev, ino64_t myino, int save)
{
  struct stat64 st;
  DIR *dirstream;
  struct dirent *d;
  size_t devlen = strlen (buf);

  dirstream = __opendir (buf);
  if (dirstream == NULL)
    {
      return errno;
    }

  while ((d = __readdir (dirstream)) != NULL)
    if (d->d_fileno == myino)
      {
	char *cp;
	size_t needed = _D_EXACT_NAMLEN (d) + 1;

	if (needed > buflen)
	  {
	    (void) __closedir (dirstream);
	    __set_errno (ERANGE);
	    return ERANGE;
	  }

	cp = __stpncpy (buf + devlen, d->d_name, needed);
	cp[0] = '\0';

	if (__xstat64 (_STAT_VER, buf, &st) == 0
#ifdef _STATBUF_ST_RDEV
	    && S_ISCHR (st.st_mode) && st.st_rdev == mydev
#else
	    && d->d_fileno == myino && st.st_dev == mydev
#endif
	   )
	  {
	    (void) __closedir (dirstream);
	    __set_errno (save);
	    return 0;
	  }
      }

  (void) __closedir (dirstream);
  __set_errno (save);
  /* It is not clear what to return in this case.  `isatty' says FD
     refers to a TTY but no entry in /dev has this inode.  */
  return ENOTTY;
}
Beispiel #3
0
static long int
__sysconf_check_spec (const char *spec)
{
  int save_errno = errno;

  const char *getconf_dir = __libc_secure_getenv ("GETCONF_DIR") ?: GETCONF_DIR;
  size_t getconf_dirlen = strlen (getconf_dir);
  size_t speclen = strlen (spec);

  char name[getconf_dirlen + sizeof ("/POSIX_V6_") + speclen];
  memcpy (mempcpy (mempcpy (name, getconf_dir, getconf_dirlen),
		   "/POSIX_V6_", sizeof ("/POSIX_V6_") - 1),
	  spec, speclen + 1);

  struct stat64 st;
  long int ret = __xstat64 (_STAT_VER, name, &st) >= 0 ? 1 : -1;

  __set_errno (save_errno);
  return ret;
}
Beispiel #4
0
/* Open a directory stream on NAME.  */
DIR *
__opendir (const char *name)
{
  if (__glibc_unlikely (invalid_name (name)))
    return NULL;

  if (need_isdir_precheck ())
    {
      /* 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.  */
      struct stat64 statbuf;
      if (__glibc_unlikely (__xstat64 (_STAT_VER, name, &statbuf) < 0))
	return NULL;
      if (__glibc_unlikely (! S_ISDIR (statbuf.st_mode)))
	{
	  __set_errno (ENOTDIR);
	  return NULL;
	}
    }

  return opendir_tail (open_not_cancel_2 (name, opendir_oflags ()));
}
Beispiel #5
0
int
stat64 (const char *file, struct stat64 *buf)
{
  return __xstat64 (_STAT_VER, file, buf);
}
Beispiel #6
0
/* Store at most BUFLEN character of the pathname of the terminal FD is
   open on in BUF.  Return 0 on success,  otherwise an error number.  */
int
__ttyname_r (int fd, char *buf, size_t buflen)
{
  char procname[30];
  struct stat64 st, st1;
  int dostat = 0;
  int save = errno;

  /* Test for the absolute minimal size.  This makes life easier inside
     the loop.  */
  if (!buf)
    {
      __set_errno (EINVAL);
      return EINVAL;
    }

  if (buflen < sizeof ("/dev/pts/"))
    {
      __set_errno (ERANGE);
      return ERANGE;
    }

  /* isatty check, tcgetattr is used because it sets the correct
     errno (EBADF resp. ENOTTY) on error.  */
  struct termios term;
  if (__glibc_unlikely (__tcgetattr (fd, &term) < 0))
    return errno;

  if (__fxstat64 (_STAT_VER, fd, &st) < 0)
    return errno;

  /* We try using the /proc filesystem.  */
  *_fitoa_word (fd, __stpcpy (procname, "/proc/self/fd/"), 10, 0) = '\0';

  ssize_t ret = __readlink (procname, buf, buflen - 1);
  if (__glibc_unlikely (ret == -1 && errno == ENAMETOOLONG))
    {
      __set_errno (ERANGE);
      return ERANGE;
    }

  if (__glibc_likely (ret != -1))
    {
#define UNREACHABLE_LEN strlen ("(unreachable)")
      if (ret > UNREACHABLE_LEN
	  && memcmp (buf, "(unreachable)", UNREACHABLE_LEN) == 0)
	{
	  memmove (buf, buf + UNREACHABLE_LEN, ret - UNREACHABLE_LEN);
	  ret -= UNREACHABLE_LEN;
	}

      /* readlink need not terminate the string.  */
      buf[ret] = '\0';

      /* Verify readlink result, fall back on iterating through devices.  */
      if (buf[0] == '/'
	  && __xstat64 (_STAT_VER, buf, &st1) == 0
#ifdef _STATBUF_ST_RDEV
	  && S_ISCHR (st1.st_mode)
	  && st1.st_rdev == st.st_rdev
#else
	  && st1.st_ino == st.st_ino
	  && st1.st_dev == st.st_dev
#endif
	  )
	return 0;
    }

  /* Prepare the result buffer.  */
  memcpy (buf, "/dev/pts/", sizeof ("/dev/pts/"));
  buflen -= sizeof ("/dev/pts/") - 1;

  if (__xstat64 (_STAT_VER, buf, &st1) == 0 && S_ISDIR (st1.st_mode))
    {
#ifdef _STATBUF_ST_RDEV
      ret = getttyname_r (buf, buflen, st.st_rdev, st.st_ino, save,
			  &dostat);
#else
      ret = getttyname_r (buf, buflen, st.st_dev, st.st_ino, save,
			  &dostat);
#endif
    }
  else
    {
      __set_errno (save);
      ret = ENOENT;
    }

  if (ret && dostat != -1)
    {
      buf[sizeof ("/dev/") - 1] = '\0';
      buflen += sizeof ("pts/") - 1;
#ifdef _STATBUF_ST_RDEV
      ret = getttyname_r (buf, buflen, st.st_rdev, st.st_ino, save,
			  &dostat);
#else
      ret = getttyname_r (buf, buflen, st.st_dev, st.st_ino, save,
			  &dostat);
#endif
    }

  if (ret && dostat != -1)
    {
      buf[sizeof ("/dev/") - 1] = '\0';
      dostat = 1;
#ifdef _STATBUF_ST_RDEV
      ret = getttyname_r (buf, buflen, st.st_rdev, st.st_ino,
			  save, &dostat);
#else
      ret = getttyname_r (buf, buflen, st.st_dev, st.st_ino,
			  save, &dostat);
#endif
    }

  return ret;
}
Beispiel #7
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;
}
Beispiel #8
0
int
attribute_hidden
stat64 (const char *file, struct stat64 *buf)
{
  return __xstat64 (_STAT_VER, file, buf);
}
Beispiel #9
0
__attribute__((weak)) int stat64(const char *path, struct stat64 *buf) { return __xstat64(1, path, buf); }
Beispiel #10
0
/* Get file-specific information about PATH.  */
long int
__pathconf (const char *path, int name)
{
  if (path[0] == '\0')
    {
      __set_errno (ENOENT);
      return -1;
    }

  switch (name)
    {
    default:
      __set_errno (EINVAL);
      return -1;

    case _PC_LINK_MAX:
#ifdef	LINK_MAX
      return LINK_MAX;
#else
      return -1;
#endif

    case _PC_MAX_CANON:
#ifdef	MAX_CANON
      return MAX_CANON;
#else
      return -1;
#endif

    case _PC_MAX_INPUT:
#ifdef	MAX_INPUT
      return MAX_INPUT;
#else
      return -1;
#endif

    case _PC_NAME_MAX:
#ifdef	NAME_MAX
      {
	struct statvfs64 sv;
	int save_errno = errno;

	if (__statvfs64 (path, &sv) < 0)
	  {
	    if (errno == ENOSYS)
	      {
		errno = save_errno;
		return NAME_MAX;
	      }
	    return -1;
	  }
	else
	  {
	    return sv.f_namemax;
	  }
      }
#else
      return -1;
#endif

    case _PC_PATH_MAX:
#ifdef	PATH_MAX
      return PATH_MAX;
#else
      return -1;
#endif

    case _PC_PIPE_BUF:
#ifdef	PIPE_BUF
      return PIPE_BUF;
#else
      return -1;
#endif

    case _PC_CHOWN_RESTRICTED:
#ifdef	_POSIX_CHOWN_RESTRICTED
      return _POSIX_CHOWN_RESTRICTED;
#else
      return -1;
#endif

    case _PC_NO_TRUNC:
#ifdef	_POSIX_NO_TRUNC
      return _POSIX_NO_TRUNC;
#else
      return -1;
#endif

    case _PC_VDISABLE:
#ifdef	_POSIX_VDISABLE
      return _POSIX_VDISABLE;
#else
      return -1;
#endif

    case _PC_SYNC_IO:
#ifdef	_POSIX_SYNC_IO
      return _POSIX_SYNC_IO;
#else
      return -1;
#endif

    case _PC_ASYNC_IO:
#ifdef	_POSIX_ASYNC_IO
      {
	/* AIO is only allowed on regular files and block devices.  */
	struct stat64 st;

	if (__xstat64 (_STAT_VER, path, &st) < 0
	    || (! S_ISREG (st.st_mode) && ! S_ISBLK (st.st_mode)))
	  return -1;
	else
	  return 1;
      }
#else
      return -1;
#endif

    case _PC_PRIO_IO:
#ifdef	_POSIX_PRIO_IO
      return _POSIX_PRIO_IO;
#else
      return -1;
#endif

    case _PC_SOCK_MAXBUF:
#ifdef	SOCK_MAXBUF
      return SOCK_MAXBUF;
#else
      return -1;
#endif

    case _PC_FILESIZEBITS:
#ifdef FILESIZEBITS
      return FILESIZEBITS;
#else
      /* We let platforms with larger file sizes overwrite this value.  */
      return 32;
#endif

    case _PC_REC_INCR_XFER_SIZE:
      /* XXX It is not entirely clear what the limit is supposed to do.
	 What is incremented?  */
      return -1;

    case _PC_REC_MAX_XFER_SIZE:
      /* XXX It is not entirely clear what the limit is supposed to do.
	 In general there is no top limit of the number of bytes which
	 case be transported at once.  */
      return -1;

    case _PC_REC_MIN_XFER_SIZE:
      {
	/* XXX It is not entirely clear what the limit is supposed to do.
	   I assume this is the block size of the filesystem.  */
	struct statvfs64 sv;

	if (__statvfs64 (path, &sv) < 0)
	  return -1;
	return sv.f_bsize;
      }

    case _PC_REC_XFER_ALIGN:
      {
	/* XXX It is not entirely clear what the limit is supposed to do.
	   I assume that the number should reflect the minimal block
	   alignment.  */
	struct statvfs64 sv;

	if (__statvfs64 (path, &sv) < 0)
	  return -1;
	return sv.f_frsize;
      }

    case _PC_ALLOC_SIZE_MIN:
      {
	/* XXX It is not entirely clear what the limit is supposed to do.
	   I assume that the number should reflect the minimal block
	   alignment.  */
	struct statvfs64 sv;

	if (__statvfs64 (path, &sv) < 0)
	  return -1;
	return sv.f_frsize;
      }

    case _PC_SYMLINK_MAX:
      /* In general there are no limits.  If a system has one it should
	 overwrite this case.  */
      return -1;

    case _PC_2_SYMLINKS:
      /* Unix systems generally have symlinks.  */
      return 1;
    }
}
Beispiel #11
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 flags = O_RDONLY|O_NDELAY|EXTRA_FLAGS|O_LARGEFILE;
#ifdef O_CLOEXEC
  flags |= O_CLOEXEC;
#endif
  int fd = open_not_cancel_2 (name, flags);
  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);
}
Beispiel #12
0
/* Return the pathname of the terminal FD is open on, or NULL on errors.
   The returned storage is good only until the next call to this function.  */
char *
ttyname (int fd)
{
  static size_t buflen;
  char procname[30];
  struct stat64 st, st1;
  int dostat = 0;
  char *name;
  int save = errno;
  struct termios term;

  /* isatty check, tcgetattr is used because it sets the correct
     errno (EBADF resp. ENOTTY) on error.  */
  if (__glibc_unlikely (__tcgetattr (fd, &term) < 0))
    return NULL;

  if (__fxstat64 (_STAT_VER, fd, &st) < 0)
    return NULL;

  /* We try using the /proc filesystem.  */
  *_fitoa_word (fd, __stpcpy (procname, "/proc/self/fd/"), 10, 0) = '\0';

  if (buflen == 0)
    {
      buflen = 4095;
      ttyname_buf = (char *) malloc (buflen + 1);
      if (ttyname_buf == NULL)
	{
	  buflen = 0;
	  return NULL;
	}
    }

  ssize_t len = __readlink (procname, ttyname_buf, buflen);
  if (__glibc_likely (len != -1))
    {
      if ((size_t) len >= buflen)
	return NULL;

#define UNREACHABLE_LEN strlen ("(unreachable)")
      if (len > UNREACHABLE_LEN
	  && memcmp (ttyname_buf, "(unreachable)", UNREACHABLE_LEN) == 0)
	{
	  memmove (ttyname_buf, ttyname_buf + UNREACHABLE_LEN,
		   len - UNREACHABLE_LEN);
	  len -= UNREACHABLE_LEN;
	}

      /* readlink need not terminate the string.  */
      ttyname_buf[len] = '\0';

      /* Verify readlink result, fall back on iterating through devices.  */
      if (ttyname_buf[0] == '/'
	  && __xstat64 (_STAT_VER, ttyname_buf, &st1) == 0
#ifdef _STATBUF_ST_RDEV
	  && S_ISCHR (st1.st_mode)
	  && st1.st_rdev == st.st_rdev
#else
	  && st1.st_ino == st.st_ino
	  && st1.st_dev == st.st_dev
#endif
	  )
	return ttyname_buf;
    }

  if (__xstat64 (_STAT_VER, "/dev/pts", &st1) == 0 && S_ISDIR (st1.st_mode))
    {
#ifdef _STATBUF_ST_RDEV
      name = getttyname ("/dev/pts", st.st_rdev, st.st_ino, save, &dostat);
#else
      name = getttyname ("/dev/pts", st.st_dev, st.st_ino, save, &dostat);
#endif
    }
  else
    {
      __set_errno (save);
      name = NULL;
    }

  if (!name && dostat != -1)
    {
#ifdef _STATBUF_ST_RDEV
      name = getttyname ("/dev", st.st_rdev, st.st_ino, save, &dostat);
#else
      name = getttyname ("/dev", st.st_dev, st.st_ino, save, &dostat);
#endif
    }

  if (!name && dostat != -1)
    {
      dostat = 1;
#ifdef _STATBUF_ST_RDEV
      name = getttyname ("/dev", st.st_rdev, st.st_ino, save, &dostat);
#else
      name = getttyname ("/dev", st.st_dev, st.st_ino, save, &dostat);
#endif
    }

  return name;
}
Beispiel #13
0
int
__ptsname_internal (int fd, char *buf, size_t buflen, struct stat64 *stp)
{
  int save_errno = errno;
  unsigned int ptyno;

  if (buf == NULL)
    {
      __set_errno (EINVAL);
      return EINVAL;
    }

  if (!__isatty (fd))
    {
      __set_errno (ENOTTY);
      return ENOTTY;
    }

#ifdef TIOCGPTN
  if (__ioctl (fd, TIOCGPTN, &ptyno) == 0)
    {
      /* Buffer we use to print the number in.  For a maximum size for
	 `int' of 8 bytes we never need more than 20 digits.  */
      char numbuf[21];
      const char *devpts = _PATH_DEVPTS;
      const size_t devptslen = strlen (_PATH_DEVPTS);
      char *p;

      numbuf[sizeof (numbuf) - 1] = '\0';
      p = _itoa_word (ptyno, &numbuf[sizeof (numbuf) - 1], 10, 0);

      if (buflen < devptslen + (&numbuf[sizeof (numbuf)] - p))
	{
	  __set_errno (ERANGE);
	  return ERANGE;
	}

      memcpy (__stpcpy (buf, devpts), p, &numbuf[sizeof (numbuf)] - p);
    }
  else if (errno != EINVAL)
    return errno;
  else
#endif
    {
      char *p;

      if (buflen < strlen (_PATH_TTY) + 3)
	{
	  __set_errno (ERANGE);
	  return ERANGE;
	}

      if (__fxstat64 (_STAT_VER, fd, stp) < 0)
	return errno;

      /* Check if FD really is a master pseudo terminal.  */
      if (! MASTER_P (stp->st_rdev))
	{
	  __set_errno (ENOTTY);
	  return ENOTTY;
	}

      ptyno = minor (stp->st_rdev);

      if (ptyno / 16 >= strlen (__libc_ptyname1))
	{
	  __set_errno (ENOTTY);
	  return ENOTTY;
	}

      p = __stpcpy (buf, _PATH_TTY);
      p[0] = __libc_ptyname1[ptyno / 16];
      p[1] = __libc_ptyname2[ptyno % 16];
      p[2] = '\0';
    }

  if (__xstat64 (_STAT_VER, buf, stp) < 0)
    return errno;

  /* Check if the name we're about to return really corresponds to a
     slave pseudo terminal.  */
  if (! S_ISCHR (stp->st_mode) || ! SLAVE_P (stp->st_rdev))
    {
      /* This really is a configuration problem.  */
      __set_errno (ENOTTY);
      return ENOTTY;
    }

  __set_errno (save_errno);
  return 0;
}
Beispiel #14
0
/* Store at most BUFLEN character of the pathname of the terminal FD is
   open on in BUF.  Return 0 on success,  otherwise an error number.  */
int
__ttyname_r (int fd, char *buf, size_t buflen)
{
  char procname[30];
  struct stat64 st, st1;
  int dostat = 0;
  int save = errno;
  int ret;

  /* Test for the absolute minimal size.  This makes life easier inside
     the loop.  */
  if (!buf)
    {
      __set_errno (EINVAL);
      return EINVAL;
    }

  if (buflen < sizeof ("/dev/pts/"))
    {
      __set_errno (ERANGE);
      return ERANGE;
    }

  /* We try using the /proc filesystem.  */
  *_fitoa_word (fd, __stpcpy (procname, "/proc/self/fd/"), 10, 0) = '\0';

  ret = __readlink (procname, buf, buflen - 1);
  if (ret == -1 && errno == ENOENT)
    {
      __set_errno (EBADF);
      return EBADF;
    }

  if (!__isatty (fd))
    {
      __set_errno (ENOTTY);
      return ENOTTY;
    }

  if (ret == -1 && errno == ENAMETOOLONG)
    {
      __set_errno (ERANGE);
      return ERANGE;
    }

  if (ret != -1 && buf[0] != '[')
    {
      buf[ret] = '\0';
      return 0;
    }

  if (__fxstat64 (_STAT_VER, fd, &st) < 0)
    return errno;

  /* Prepare the result buffer.  */
  memcpy (buf, "/dev/pts/", sizeof ("/dev/pts/"));
  buflen -= sizeof ("/dev/pts/") - 1;

  if (__xstat64 (_STAT_VER, buf, &st1) == 0 && S_ISDIR (st1.st_mode))
    {
#ifdef _STATBUF_ST_RDEV
      ret = getttyname_r (buf, buflen, st.st_rdev, st.st_ino, save,
			  &dostat);
#else
      ret = getttyname_r (buf, buflen, st.st_dev, st.st_ino, save,
			  &dostat);
#endif
    }
  else
    {
      __set_errno (save);
      ret = ENOENT;
    }

  if (ret && dostat != -1)
    {
      buf[sizeof ("/dev/") - 1] = '\0';
      buflen += sizeof ("pts/") - 1;
#ifdef _STATBUF_ST_RDEV
      ret = getttyname_r (buf, buflen, st.st_rdev, st.st_ino, save,
			  &dostat);
#else
      ret = getttyname_r (buf, buflen, st.st_dev, st.st_ino, save,
			  &dostat);
#endif
    }

  if (ret && dostat != -1)
    {
      buf[sizeof ("/dev/") - 1] = '\0';
      dostat = 1;
#ifdef _STATBUF_ST_RDEV
      ret = getttyname_r (buf, buflen, st.st_rdev, st.st_ino,
			  save, &dostat);
#else
      ret = getttyname_r (buf, buflen, st.st_dev, st.st_ino,
			  save, &dostat);
#endif
    }

  return ret;
}
Beispiel #15
0
/* Return the pathname of the terminal FD is open on, or NULL on errors.
   The returned storage is good only until the next call to this function.  */
char *
ttyname (int fd)
{
  static size_t buflen;
  char procname[30];
  struct stat64 st, st1;
  int dostat = 0;
  char *name;
  int save = errno;
  struct termios term;

  /* isatty check, tcgetattr is used because it sets the correct
     errno (EBADF resp. ENOTTY) on error.  */
  if (__builtin_expect (__tcgetattr (fd, &term) < 0, 0))
    return NULL;

  /* We try using the /proc filesystem.  */
  *_fitoa_word (fd, __stpcpy (procname, "/proc/self/fd/"), 10, 0) = '\0';

  if (buflen == 0)
    {
      buflen = 4095;
      ttyname_buf = (char *) malloc (buflen + 1);
      if (ttyname_buf == NULL)
	{
	  buflen = 0;
	  return NULL;
	}
    }

  ssize_t len = __readlink (procname, ttyname_buf, buflen);
  if (__builtin_expect (len == -1 && errno == ENOENT, 0))
    {
      __set_errno (EBADF);
      return NULL;
    }

  if (__builtin_expect (len != -1
#ifndef __ASSUME_PROC_SELF_FD_SYMLINK
			/* This is for Linux 2.0.  */
			&& ttyname_buf[0] != '['
#endif
			, 1))
    {
      if ((size_t) len >= buflen)
	return NULL;
      /* readlink need not terminate the string.  */
      ttyname_buf[len] = '\0';
      return ttyname_buf;
    }

  if (__fxstat64 (_STAT_VER, fd, &st) < 0)
    return NULL;

  if (__xstat64 (_STAT_VER, "/dev/pts", &st1) == 0 && S_ISDIR (st1.st_mode))
    {
#ifdef _STATBUF_ST_RDEV
      name = getttyname ("/dev/pts", st.st_rdev, st.st_ino, save, &dostat);
#else
      name = getttyname ("/dev/pts", st.st_dev, st.st_ino, save, &dostat);
#endif
    }
  else
    {
      __set_errno (save);
      name = NULL;
    }

  if (!name && dostat != -1)
    {
#ifdef _STATBUF_ST_RDEV
      name = getttyname ("/dev", st.st_rdev, st.st_ino, save, &dostat);
#else
      name = getttyname ("/dev", st.st_dev, st.st_ino, save, &dostat);
#endif
    }

  if (!name && dostat != -1)
    {
      dostat = 1;
#ifdef _STATBUF_ST_RDEV
      name = getttyname ("/dev", st.st_rdev, st.st_ino, save, &dostat);
#else
      name = getttyname ("/dev", st.st_dev, st.st_ino, save, &dostat);
#endif
    }

  return name;
}
/* Return nonzero if DIR is an existent directory.  */
static bool
direxists (const char *dir)
{
  struct_stat64 buf;
  return __xstat64 (_STAT_VER, dir, &buf) == 0 && S_ISDIR (buf.st_mode);
}
internal_function attribute_compat_text_section
getttyname (const char *dev, dev_t mydev, ino64_t myino, int save, int *dostat)
{
  static size_t namelen;
  struct stat64 st;
  DIR *dirstream;
  struct dirent64 *d;
  size_t devlen = strlen (dev) + 1;

  dirstream = __opendir (dev);
  if (dirstream == NULL)
    {
      *dostat = -1;
      return NULL;
    }

  /* Prepare for the loop.  If we already have a buffer copy the directory
     name we look at into it.  */
  if (devlen < namelen)
    *((char *) __mempcpy (getttyname_name, dev, devlen - 1)) = '/';

  while ((d = __readdir64 (dirstream)) != NULL)
    if ((d->d_fileno == myino || *dostat)
	&& strcmp (d->d_name, "stdin")
	&& strcmp (d->d_name, "stdout")
	&& strcmp (d->d_name, "stderr"))
      {
	size_t dlen = _D_ALLOC_NAMLEN (d);
	if (devlen + dlen > namelen)
	  {
	    free (getttyname_name);
	    namelen = 2 * (devlen + dlen); /* Big enough.  */
	    getttyname_name = malloc (namelen);
	    if (! getttyname_name)
	      {
		*dostat = -1;
		/* Perhaps it helps to free the directory stream buffer.  */
		(void) __closedir (dirstream);
		return NULL;
	      }
	    *((char *) __mempcpy (getttyname_name, dev, devlen - 1)) = '/';
	  }
	memcpy (&getttyname_name[devlen], d->d_name, dlen);
	if (__xstat64 (_STAT_VER, getttyname_name, &st) == 0
#ifdef _STATBUF_ST_RDEV
	    && S_ISCHR (st.st_mode) && st.st_rdev == mydev
#else
	    && d->d_fileno == myino && st.st_dev == mydev
#endif
	   )
	  {
	    (void) __closedir (dirstream);
#if 0
	    __ttyname = getttyname_name;
#endif
	    __set_errno (save);
	    return getttyname_name;
	  }
      }

  (void) __closedir (dirstream);
  __set_errno (save);
  return NULL;
}
Beispiel #18
0
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);
}
Beispiel #19
0
void
attribute_hidden
__atfct_seterrno_2 (int errval, int fd1, const char *buf1, int fd2,
		    const char *buf2)
{
  if (buf1 != NULL || buf2 != NULL)
    {
      struct stat64 st;

      if (errval == ENOTDIR)
	{
	  /* This can mean either the file descriptor is invalid or
	     /proc is not mounted.  */
	  if (buf1 != NULL)
	    {
	      if (__fxstat64 (_STAT_VER, fd1, &st) != 0)
		/* errno is already set correctly.  */
		return;

	      /* If /proc is not mounted there is nothing we can do.  */
	      if (S_ISDIR (st.st_mode)
		  && (__xstat64 (_STAT_VER, "/proc/self/fd", &st) != 0
		      || !S_ISDIR (st.st_mode)))
		{
		  errval = ENOSYS;
		  goto out;
		}
	    }

	  if (buf2 != NULL)
	    {
	      if (__fxstat64 (_STAT_VER, fd2, &st) != 0)
		/* errno is already set correctly.  */
		return;

	      /* If /proc is not mounted there is nothing we can do.  */
	      if (S_ISDIR (st.st_mode)
		  && (__xstat64 (_STAT_VER, "/proc/self/fd", &st) != 0
		      || !S_ISDIR (st.st_mode)))
		errval = ENOSYS;
	    }
	}
      else if (errval == ENOENT)
	{
	  /* This could mean the file descriptor is not valid.  We
	     reuse BUF for the stat call.  Find the slash after the
	     file descriptor number.  */
	  if (buf1 != NULL)
	    {
	      *(char *) strchr (buf1 + sizeof "/proc/self/fd", '/') = '\0';

	      int e = __lxstat64 (_STAT_VER, buf1, &st);
	      if ((e == -1 && errno == ENOENT)
		  ||(e == 0 && !S_ISLNK (st.st_mode)))
		{
		  errval = EBADF;
		  goto out;
		}
	    }

	  if (buf2 != NULL)
	    {
	      *(char *) strchr (buf2 + sizeof "/proc/self/fd", '/') = '\0';

	      int e = __lxstat64 (_STAT_VER, buf2, &st);
	      if ((e == -1 && errno == ENOENT)
		  ||(e == 0 && !S_ISLNK (st.st_mode)))
		errval = EBADF;
	    }
	}
    }

 out:
  __set_errno (errval);
}