示例#1
0
/* Close all file descriptors except the one specified.  */
static void
close_all_fds (void)
{
  DIR *dir = __opendir ("/proc/self/fd");
  if (dir != NULL)
    {
      struct dirent64 *d;
      while ((d = __readdir64 (dir)) != NULL)
	if (isdigit (d->d_name[0]))
	  {
	    char *endp;
	    long int fd = strtol (d->d_name, &endp, 10);
	    if (*endp == '\0' && fd != PTY_FILENO && fd != dirfd (dir))
	      __close_nocancel_nostatus (fd);
	  }

      __closedir (dir);

      int nullfd = __open_nocancel (_PATH_DEVNULL, O_RDONLY);
      assert (nullfd == STDIN_FILENO);
      nullfd = __open_nocancel (_PATH_DEVNULL, O_WRONLY);
      assert (nullfd == STDOUT_FILENO);
      __dup2 (STDOUT_FILENO, STDERR_FILENO);
    }
}
示例#2
0
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;
    }

  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;
}
示例#3
0
static int
internal_function attribute_compat_text_section
getttyname_r (char *buf, size_t buflen, dev_t mydev, ino64_t myino,
	      int save, int *dostat)
{
  struct stat64 st;
  DIR *dirstream;
  struct dirent64 *d;
  size_t devlen = strlen (buf);

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

  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"))
      {
	char *cp;
	size_t needed = _D_EXACT_NAMLEN (d) + 1;

	if (needed > buflen)
	  {
	    *dostat = -1;
	    (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;
}
/* On some architectures it is possible to distinguish between configured
   and active cpus.  */
int
__get_nprocs_conf ()
{
  /* XXX Here will come a test for the new system call.  */

  /* Try to use the sysfs filesystem.  It has actual information about
     online processors.  */
  DIR *dir = __opendir ("/sys/devices/system/cpu");
  if (dir != NULL)
    {
      int count = 0;
      struct dirent64 *d;

      while ((d = __readdir64 (dir)) != NULL)
	/* NB: the sysfs has d_type support.  */
	if (d->d_type == DT_DIR && strncmp (d->d_name, "cpu", 3) == 0)
	  {
	    char *endp;
	    unsigned long int nr = strtoul (d->d_name + 3, &endp, 10);
	    if (nr != ULONG_MAX && endp != d->d_name + 3 && *endp == '\0')
	      ++count;
	  }

      __closedir (dir);

      return count;
    }

  int result = 1;

#ifdef GET_NPROCS_CONF_PARSER
  /* If we haven't found an appropriate entry return 1.  */
  FILE *fp = fopen ("/proc/cpuinfo", "rce");
  if (fp != NULL)
    {
      char buffer[8192];

      /* No threads use this stream.  */
      __fsetlocking (fp, FSETLOCKING_BYCALLER);
      GET_NPROCS_CONF_PARSER (fp, buffer, result);
      fclose (fp);
    }
#else
  result = __get_nprocs ();
#endif

  return result;
}
示例#5
0
文件: readdir.c 项目: gf-chen/glibc
/* Read a directory entry from DIRP.  */
struct dirent *
__readdir (DIR *dirp)
{
  struct dirent64 *entry64 = __readdir64 (dirp);

  if (sizeof (struct dirent64) == sizeof (struct dirent))
    /* We should in fact just be an alias to readdir64 on this machine.  */
    return (struct dirent *) entry64;

  /* These are all compile-time constants.  We know that d_ino is the first
     member and that the layout of the following members matches exactly in
     both structures.  */
  assert (offsetof (struct dirent, d_ino) == 0);
  assert (offsetof (struct dirent64, d_ino) == 0);
# define MATCH(memb)							      \
  assert (offsetof (struct dirent64, memb) - sizeof (entry64->d_ino)	      \
	  == offsetof (struct dirent, memb) - sizeof (ino_t))
  MATCH (d_reclen);
  MATCH (d_type);
  MATCH (d_namlen);
# undef MATCH

  if (entry64 == NULL)
    return NULL;

  struct dirent *const entry = ((void *) (&entry64->d_ino + 1)
				- sizeof entry->d_ino);
  const ino_t d_ino = entry64->d_ino;
  if (d_ino != entry64->d_ino)
    {
      __set_errno (EOVERFLOW);
      return NULL;
    }
# if BYTE_ORDER != BIG_ENDIAN	/* We just skipped over the zero high word.  */
  entry->d_ino = d_ino;	/* ... or the nonzero low word, swap it.  */
# endif
  entry->d_reclen -= sizeof entry64->d_ino - sizeof entry->d_ino;
  return entry;
}
示例#6
0
文件: ftw.c 项目: riscv/riscv-glibc
ftw_dir (struct ftw_data *data, struct STAT *st, struct dir_data *old_dir)
{
  struct dir_data dir;
  struct dirent64 *d;
  int previous_base = data->ftw.base;
  int result;
  char *startp;

  /* Open the stream for this directory.  This might require that
     another stream has to be closed.  */
  result = open_dir_stream (old_dir == NULL ? NULL : &old_dir->streamfd,
			    data, &dir);
  if (result != 0)
    {
      if (errno == EACCES)
	/* We cannot read the directory.  Signal this with a special flag.  */
	result = (*data->func) (data->dirbuf, st, FTW_DNR, &data->ftw);

      return result;
    }

  /* First, report the directory (if not depth-first).  */
  if (!(data->flags & FTW_DEPTH))
    {
      result = (*data->func) (data->dirbuf, st, FTW_D, &data->ftw);
      if (result != 0)
	{
	  int save_err;
fail:
	  save_err = errno;
	  __closedir (dir.stream);
	  dir.streamfd = -1;
	  __set_errno (save_err);

	  if (data->actdir-- == 0)
	    data->actdir = data->maxdir - 1;
	  data->dirstreams[data->actdir] = NULL;
	  return result;
	}
    }

  /* If necessary, change to this directory.  */
  if (data->flags & FTW_CHDIR)
    {
      if (__fchdir (__dirfd (dir.stream)) < 0)
	{
	  result = -1;
	  goto fail;
	}
    }

  /* Next, update the `struct FTW' information.  */
  ++data->ftw.level;
  startp = __rawmemchr (data->dirbuf, '\0');
  /* There always must be a directory name.  */
  assert (startp != data->dirbuf);
  if (startp[-1] != '/')
    *startp++ = '/';
  data->ftw.base = startp - data->dirbuf;

  while (dir.stream != NULL && (d = __readdir64 (dir.stream)) != NULL)
    {
      int d_type = DT_UNKNOWN;
#ifdef _DIRENT_HAVE_D_TYPE
      d_type = d->d_type;
#endif
      result = process_entry (data, &dir, d->d_name, NAMLEN (d), d_type);
      if (result != 0)
	break;
    }

  if (dir.stream != NULL)
    {
      /* The stream is still open.  I.e., we did not need more
	 descriptors.  Simply close the stream now.  */
      int save_err = errno;

      assert (dir.content == NULL);

      __closedir (dir.stream);
      dir.streamfd = -1;
      __set_errno (save_err);

      if (data->actdir-- == 0)
	data->actdir = data->maxdir - 1;
      data->dirstreams[data->actdir] = NULL;
    }
  else
    {
      int save_err;
      char *runp = dir.content;

      while (result == 0 && *runp != '\0')
	{
	  char *endp = strchr (runp, '\0');

	  // XXX Should store the d_type values as well?!
	  result = process_entry (data, &dir, runp, endp - runp, DT_UNKNOWN);

	  runp = endp + 1;
	}

      save_err = errno;
      free (dir.content);
      __set_errno (save_err);
    }

  if ((data->flags & FTW_ACTIONRETVAL) && result == FTW_SKIP_SIBLINGS)
    result = 0;

  /* Prepare the return, revert the `struct FTW' information.  */
  data->dirbuf[data->ftw.base - 1] = '\0';
  --data->ftw.level;
  data->ftw.base = previous_base;

  /* Finally, if we process depth-first report the directory.  */
  if (result == 0 && (data->flags & FTW_DEPTH))
    result = (*data->func) (data->dirbuf, st, FTW_DP, &data->ftw);

  if (old_dir
      && (data->flags & FTW_CHDIR)
      && (result == 0
	  || ((data->flags & FTW_ACTIONRETVAL)
	      && (result != -1 && result != FTW_STOP))))
    {
      /* Change back to the parent directory.  */
      int done = 0;
      if (old_dir->stream != NULL)
	if (__fchdir (__dirfd (old_dir->stream)) == 0)
	  done = 1;

      if (!done)
	{
	  if (data->ftw.base == 1)
	    {
	      if (__chdir ("/") < 0)
		result = -1;
	    }
	  else
	    if (__chdir ("..") < 0)
	      result = -1;
	}
    }

  return result;
}
示例#7
0
文件: ftw.c 项目: riscv/riscv-glibc
open_dir_stream (int *dfdp, struct ftw_data *data, struct dir_data *dirp)
{
  int result = 0;

  if (data->dirstreams[data->actdir] != NULL)
    {
      /* Oh, oh.  We must close this stream.  Get all remaining
	 entries and store them as a list in the `content' member of
	 the `struct dir_data' variable.  */
      size_t bufsize = 1024;
      char *buf = malloc (bufsize);

      if (buf == NULL)
	result = -1;
      else
	{
	  DIR *st = data->dirstreams[data->actdir]->stream;
	  struct dirent64 *d;
	  size_t actsize = 0;

	  while ((d = __readdir64 (st)) != NULL)
	    {
	      size_t this_len = NAMLEN (d);
	      if (actsize + this_len + 2 >= bufsize)
		{
		  char *newp;
		  bufsize += MAX (1024, 2 * this_len);
		  newp = (char *) realloc (buf, bufsize);
		  if (newp == NULL)
		    {
		      /* No more memory.  */
		      int save_err = errno;
		      free (buf);
		      __set_errno (save_err);
		      return -1;
		    }
		  buf = newp;
		}

	      *((char *) __mempcpy (buf + actsize, d->d_name, this_len))
		= '\0';
	      actsize += this_len + 1;
	    }

	  /* Terminate the list with an additional NUL byte.  */
	  buf[actsize++] = '\0';

	  /* Shrink the buffer to what we actually need.  */
	  data->dirstreams[data->actdir]->content = realloc (buf, actsize);
	  if (data->dirstreams[data->actdir]->content == NULL)
	    {
	      int save_err = errno;
	      free (buf);
	      __set_errno (save_err);
	      result = -1;
	    }
	  else
	    {
	      __closedir (st);
	      data->dirstreams[data->actdir]->stream = NULL;
	      data->dirstreams[data->actdir]->streamfd = -1;
	      data->dirstreams[data->actdir] = NULL;
	    }
	}
    }

  /* Open the new stream.  */
  if (result == 0)
    {
      assert (data->dirstreams[data->actdir] == NULL);

      if (dfdp != NULL && *dfdp != -1)
	{
	  int fd = __openat64_nocancel (*dfdp, data->dirbuf + data->ftw.base,
					O_RDONLY | O_DIRECTORY | O_NDELAY);
	  dirp->stream = NULL;
	  if (fd != -1 && (dirp->stream = __fdopendir (fd)) == NULL)
	    __close_nocancel_nostatus (fd);
	}
      else
	{
	  const char *name;

	  if (data->flags & FTW_CHDIR)
	    {
	      name = data->dirbuf + data->ftw.base;
	      if (name[0] == '\0')
		name = ".";
	    }
	  else
	    name = data->dirbuf;

	  dirp->stream = __opendir (name);
	}

      if (dirp->stream == NULL)
	result = -1;
      else
	{
	  dirp->streamfd = __dirfd (dirp->stream);
	  dirp->content = NULL;
	  data->dirstreams[data->actdir] = dirp;

	  if (++data->actdir == data->maxdir)
	    data->actdir = 0;
	}
    }

  return result;
}