Beispiel #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);
    }
}
Beispiel #2
0
/* Open the database stored in FILE.  If succesful, store either a
   pointer to the mapped file or a file handle for the file in H and
   return NSS_STATUS_SUCCESS.  On failure, return the appropriate
   lookup status.  */
enum nss_status
internal_setent (const char *file, struct nss_db_map *mapping)
{
  enum nss_status status = NSS_STATUS_UNAVAIL;

  int fd = __open_nocancel (file, O_RDONLY | O_LARGEFILE | O_CLOEXEC);
  if (fd != -1)
    {
      struct nss_db_header header;

      if (read (fd, &header, sizeof (header)) == sizeof (header))
	{
	  mapping->header = mmap (NULL, header.allocate, PROT_READ,
				  MAP_PRIVATE, fd, 0);
	  mapping->len = header.allocate;
	  if (mapping->header != MAP_FAILED)
	    status = NSS_STATUS_SUCCESS;
	  else if (errno == ENOMEM)
	    status = NSS_STATUS_TRYAGAIN;
	}

      __close_nocancel_nostatus (fd);
    }

  return status;
}
Beispiel #3
0
static int
setutent_file (void)
{
  if (file_fd < 0)
    {
      const char *file_name;

      file_name = TRANSFORM_UTMP_FILE_NAME (__libc_utmp_file_name);

      file_writable = false;
      file_fd = __open_nocancel
	(file_name, O_RDONLY | O_LARGEFILE | O_CLOEXEC);
      if (file_fd == -1)
	return 0;
    }

  __lseek64 (file_fd, 0, SEEK_SET);
  file_offset = 0;

  /* Make sure the entry won't match.  */
#if _HAVE_UT_TYPE - 0
  last_entry.ut_type = -1;
#else
  last_entry.ut_line[0] = '\177';
# if _HAVE_UT_ID - 0
  last_entry.ut_id[0] = '\0';
# endif
#endif

  return 1;
}
Beispiel #4
0
static int
has_cpuclock (void)
{
  if (__builtin_expect (itc_usable == 0, 0))
    {
      int newval = 1;
      int fd = __open_nocancel ("/proc/sal/itc_drift", O_RDONLY);
      if (__builtin_expect (fd != -1, 1))
	{
	  char buf[16];
	  /* We expect the file to contain a single digit followed by
	     a newline.  If the format changes we better not rely on
	     the file content.  */
	  if (__read_nocancel (fd, buf, sizeof buf) != 2
	      || buf[0] != '0' || buf[1] != '\n')
	    newval = -1;

	  __close_nocancel_nostatus (fd);
	}

      itc_usable = newval;
    }

  return itc_usable;
}
Beispiel #5
0
int
pthread_getname_np (pthread_t th, char *buf, size_t len)
{
  const struct pthread *pd = (const struct pthread *) th;

  /* Unfortunately the kernel headers do not export the TASK_COMM_LEN
     macro.  So we have to define it here.  */
#define TASK_COMM_LEN 16
  if (len < TASK_COMM_LEN)
    return ERANGE;

  if (pd == THREAD_SELF)
    return prctl (PR_GET_NAME, buf) ? errno : 0;

#define FMT "/proc/self/task/%u/comm"
  char fname[sizeof (FMT) + 8];
  sprintf (fname, FMT, (unsigned int) pd->tid);

  int fd = __open_nocancel (fname, O_RDONLY);
  if (fd == -1)
    return errno;

  int res = 0;
  ssize_t n = TEMP_FAILURE_RETRY (__read_nocancel (fd, buf, len));
  if (n < 0)
    res = errno;
  else
    {
      if (buf[n - 1] == '\n')
	buf[n - 1] = '\0';
      else if (n == len)
	res = ERANGE;
      else
	buf[n] = '\0';
    }

  __close_nocancel_nostatus (fd);

  return res;
}
Beispiel #6
0
int
__get_nprocs (void)
{
  static int cached_result = -1;
  static time_t timestamp;

  time_t now = time (NULL);
  time_t prev = timestamp;
  atomic_read_barrier ();
  if (now == prev && cached_result > -1)
    return cached_result;

  /* XXX Here will come a test for the new system call.  */

  const size_t buffer_size = __libc_use_alloca (8192) ? 8192 : 512;
  char *buffer = alloca (buffer_size);
  char *buffer_end = buffer + buffer_size;
  char *cp = buffer_end;
  char *re = buffer_end;

  const int flags = O_RDONLY | O_CLOEXEC;
  int fd = __open_nocancel ("/sys/devices/system/cpu/online", flags);
  char *l;
  int result = 0;
  if (fd != -1)
    {
      l = next_line (fd, buffer, &cp, &re, buffer_end);
      if (l != NULL)
	do
	  {
	    char *endp;
	    unsigned long int n = strtoul (l, &endp, 10);
	    if (l == endp)
	      {
		result = 0;
		break;
	      }

	    unsigned long int m = n;
	    if (*endp == '-')
	      {
		l = endp + 1;
		m = strtoul (l, &endp, 10);
		if (l == endp)
		  {
		    result = 0;
		    break;
		  }
	      }

	    result += m - n + 1;

	    l = endp;
	    while (l < re && isspace (*l))
	      ++l;
	  }
	while (l < re);

      __close_nocancel_nostatus (fd);

      if (result > 0)
	goto out;
    }

  cp = buffer_end;
  re = buffer_end;

  /* Default to an SMP system in case we cannot obtain an accurate
     number.  */
  result = 2;

  /* The /proc/stat format is more uniform, use it by default.  */
  fd = __open_nocancel ("/proc/stat", flags);
  if (fd != -1)
    {
      result = 0;

      while ((l = next_line (fd, buffer, &cp, &re, buffer_end)) != NULL)
	/* The current format of /proc/stat has all the cpu* entries
	   at the front.  We assume here that stays this way.  */
	if (strncmp (l, "cpu", 3) != 0)
	  break;
	else if (isdigit (l[3]))
	  ++result;

      __close_nocancel_nostatus (fd);
    }
  else
    {
      fd = __open_nocancel ("/proc/cpuinfo", flags);
      if (fd != -1)
	{
	  GET_NPROCS_PARSER (fd, buffer, cp, re, buffer_end, result);
	  __close_nocancel_nostatus (fd);
	}
    }

 out:
  cached_result = result;
  atomic_write_barrier ();
  timestamp = now;

  return result;
}
Beispiel #7
0
int
__open_catalog (const char *cat_name, const char *nlspath, const char *env_var,
		__nl_catd catalog)
{
  int fd = -1;
  struct stat64 st;
  int swapping;
  size_t cnt;
  size_t max_offset;
  size_t tab_size;
  const char *lastp;
  int result = -1;
  char *buf = NULL;

  if (strchr (cat_name, '/') != NULL || nlspath == NULL)
    fd = __open_nocancel (cat_name, O_RDONLY);
  else
    {
      const char *run_nlspath = nlspath;
#define ENOUGH(n)							      \
  if (__glibc_unlikely (bufact + (n) >= bufmax))			      \
    {									      \
      char *old_buf = buf;						      \
      bufmax += (bufmax < 256 + (n)) ? 256 + (n) : bufmax;		      \
      buf = realloc (buf, bufmax);					      \
      if (__glibc_unlikely (buf == NULL))				      \
	{								      \
	  free (old_buf);						      \
	  return -1;							      \
	}								      \
    }

      /* The RUN_NLSPATH variable contains a colon separated list of
	 descriptions where we expect to find catalogs.  We have to
	 recognize certain % substitutions and stop when we found the
	 first existing file.  */
      size_t bufact;
      size_t bufmax = 0;
      size_t len;

      fd = -1;
      while (*run_nlspath != '\0')
	{
	  bufact = 0;

	  if (*run_nlspath == ':')
	    {
	      /* Leading colon or adjacent colons - treat same as %N.  */
	      len = strlen (cat_name);
	      ENOUGH (len);
	      memcpy (&buf[bufact], cat_name, len);
	      bufact += len;
	    }
	  else
	    while (*run_nlspath != ':' && *run_nlspath != '\0')
	      if (*run_nlspath == '%')
		{
		  const char *tmp;

		  ++run_nlspath;	/* We have seen the `%'.  */
		  switch (*run_nlspath++)
		    {
		    case 'N':
		      /* Use the catalog name.  */
		      len = strlen (cat_name);
		      ENOUGH (len);
		      memcpy (&buf[bufact], cat_name, len);
		      bufact += len;
		      break;
		    case 'L':
		      /* Use the current locale category value.  */
		      len = strlen (env_var);
		      ENOUGH (len);
		      memcpy (&buf[bufact], env_var, len);
		      bufact += len;
		      break;
		    case 'l':
		      /* Use language element of locale category value.  */
		      tmp = env_var;
		      do
			{
			  ENOUGH (1);
			  buf[bufact++] = *tmp++;
			}
		      while (*tmp != '\0' && *tmp != '_' && *tmp != '.');
		      break;
		    case 't':
		      /* Use territory element of locale category value.  */
		      tmp = env_var;
		      do
			++tmp;
		      while (*tmp != '\0' && *tmp != '_' && *tmp != '.');
		      if (*tmp == '_')
			{
			  ++tmp;
			  do
			    {
			      ENOUGH (1);
			      buf[bufact++] = *tmp++;
			    }
			  while (*tmp != '\0' && *tmp != '.');
			}
		      break;
		    case 'c':
		      /* Use code set element of locale category value.  */
		      tmp = env_var;
		      do
			++tmp;
		      while (*tmp != '\0' && *tmp != '.');
		      if (*tmp == '.')
			{
			  ++tmp;
			  do
			    {
			      ENOUGH (1);
			      buf[bufact++] = *tmp++;
			    }
			  while (*tmp != '\0');
			}
		      break;
		    case '%':
		      ENOUGH (1);
		      buf[bufact++] = '%';
		      break;
		    default:
		      /* Unknown variable: ignore this path element.  */
		      bufact = 0;
		      while (*run_nlspath != '\0' && *run_nlspath != ':')
			++run_nlspath;
		      break;
		    }
		}
	      else
		{
		  ENOUGH (1);
		  buf[bufact++] = *run_nlspath++;
		}

	  ENOUGH (1);
	  buf[bufact] = '\0';

	  if (bufact != 0)
	    {
	      fd = __open_nocancel (buf, O_RDONLY);
	      if (fd >= 0)
		break;
	    }

	  ++run_nlspath;
	}
    }

  /* Avoid dealing with directories and block devices */
  if (__builtin_expect (fd, 0) < 0)
    {
      free (buf);
      return -1;
    }

  if (__builtin_expect (__fxstat64 (_STAT_VER, fd, &st), 0) < 0)
    goto close_unlock_return;

  if (__builtin_expect (!S_ISREG (st.st_mode), 0)
      || (size_t) st.st_size < sizeof (struct catalog_obj))
    {
      /* `errno' is not set correctly but the file is not usable.
	 Use an reasonable error value.  */
      __set_errno (EINVAL);
      goto close_unlock_return;
    }

  catalog->file_size = st.st_size;
#ifdef _POSIX_MAPPED_FILES
# ifndef MAP_COPY
    /* Linux seems to lack read-only copy-on-write.  */
#  define MAP_COPY MAP_PRIVATE
# endif
# ifndef MAP_FILE
    /* Some systems do not have this flag; it is superfluous.  */
#  define MAP_FILE 0
# endif
  catalog->file_ptr =
    (struct catalog_obj *) __mmap (NULL, st.st_size, PROT_READ,
				   MAP_FILE|MAP_COPY, fd, 0);
  if (__builtin_expect (catalog->file_ptr != (struct catalog_obj *) MAP_FAILED,
			1))
    /* Tell the world we managed to mmap the file.  */
    catalog->status = mmapped;
  else
#endif /* _POSIX_MAPPED_FILES */
    {
      /* mmap failed perhaps because the system call is not
	 implemented.  Try to load the file.  */
      size_t todo;
      catalog->file_ptr = malloc (st.st_size);
      if (catalog->file_ptr == NULL)
	goto close_unlock_return;

      todo = st.st_size;
      /* Save read, handle partial reads.  */
      do
	{
	  size_t now = __read_nocancel (fd, (((char *) catalog->file_ptr)
					     + (st.st_size - todo)), todo);
	  if (now == 0 || now == (size_t) -1)
	    {
#ifdef EINTR
	      if (now == (size_t) -1 && errno == EINTR)
		continue;
#endif
	      free ((void *) catalog->file_ptr);
	      goto close_unlock_return;
	    }
	  todo -= now;
	}
      while (todo > 0);
      catalog->status = malloced;
    }

  /* Determine whether the file is a catalog file and if yes whether
     it is written using the correct byte order.  Else we have to swap
     the values.  */
  if (__glibc_likely (catalog->file_ptr->magic == CATGETS_MAGIC))
    swapping = 0;
  else if (catalog->file_ptr->magic == SWAPU32 (CATGETS_MAGIC))
    swapping = 1;
  else
    {
    invalid_file:
      /* Invalid file.  Free the resources and mark catalog as not
	 usable.  */
#ifdef _POSIX_MAPPED_FILES
      if (catalog->status == mmapped)
	__munmap ((void *) catalog->file_ptr, catalog->file_size);
      else
#endif	/* _POSIX_MAPPED_FILES */
	free (catalog->file_ptr);
      goto close_unlock_return;
    }

#define SWAP(x) (swapping ? SWAPU32 (x) : (x))

  /* Get dimensions of the used hashing table.  */
  catalog->plane_size = SWAP (catalog->file_ptr->plane_size);
  catalog->plane_depth = SWAP (catalog->file_ptr->plane_depth);

  /* The file contains two versions of the pointer tables.  Pick the
     right one for the local byte order.  */
#if __BYTE_ORDER == __LITTLE_ENDIAN
  catalog->name_ptr = &catalog->file_ptr->name_ptr[0];
#elif __BYTE_ORDER == __BIG_ENDIAN
  catalog->name_ptr = &catalog->file_ptr->name_ptr[catalog->plane_size
						  * catalog->plane_depth
						  * 3];
#else
# error Cannot handle __BYTE_ORDER byte order
#endif

  /* The rest of the file contains all the strings.  They are
     addressed relative to the position of the first string.  */
  catalog->strings =
    (const char *) &catalog->file_ptr->name_ptr[catalog->plane_size
					       * catalog->plane_depth * 3 * 2];

  /* Determine the largest string offset mentioned in the table.  */
  max_offset = 0;
  tab_size = 3 * catalog->plane_size * catalog->plane_depth;
  for (cnt = 2; cnt < tab_size; cnt += 3)
    if (catalog->name_ptr[cnt] > max_offset)
      max_offset = catalog->name_ptr[cnt];

  /* Now we can check whether the file is large enough to contain the
     tables it says it contains.  */
  if ((size_t) st.st_size
      <= (sizeof (struct catalog_obj) + 2 * tab_size + max_offset))
    /* The last string is not contained in the file.  */
    goto invalid_file;

  lastp = catalog->strings + max_offset;
  max_offset = (st.st_size
		- sizeof (struct catalog_obj) + 2 * tab_size + max_offset);
  while (*lastp != '\0')
    {
      if (--max_offset == 0)
	goto invalid_file;
      ++lastp;
    }

  /* We succeeded.  */
  result = 0;

  /* Release the lock again.  */
 close_unlock_return:
  __close_nocancel_nostatus (fd);
  free (buf);

  return result;
}