-#ifdef HAVE_POLL
- /* This big thing is a constant expression and should get optimized
- * out of existence. So it's more robust than a configure check at
- * no cost.
- */
- if (_DBUS_POLLIN == POLLIN &&
- _DBUS_POLLPRI == POLLPRI &&
- _DBUS_POLLOUT == POLLOUT &&
- _DBUS_POLLERR == POLLERR &&
- _DBUS_POLLHUP == POLLHUP &&
- _DBUS_POLLNVAL == POLLNVAL &&
- sizeof (DBusPollFD) == sizeof (struct pollfd) &&
- _DBUS_STRUCT_OFFSET (DBusPollFD, fd) ==
- _DBUS_STRUCT_OFFSET (struct pollfd, fd) &&
- _DBUS_STRUCT_OFFSET (DBusPollFD, events) ==
- _DBUS_STRUCT_OFFSET (struct pollfd, events) &&
- _DBUS_STRUCT_OFFSET (DBusPollFD, revents) ==
- _DBUS_STRUCT_OFFSET (struct pollfd, revents))
- {
- return poll ((struct pollfd*) fds,
- n_fds,
- timeout_milliseconds);
- }
- else
- {
- /* We have to convert the DBusPollFD to an array of
- * struct pollfd, poll, and convert back.
- */
- _dbus_warn ("didn't implement poll() properly for this system yet\n");
- return -1;
- }
-#else /* ! HAVE_POLL */
-
- fd_set read_set, write_set, err_set;
- int max_fd = 0;
- int i;
- struct timeval tv;
- int ready;
-
- FD_ZERO (&read_set);
- FD_ZERO (&write_set);
- FD_ZERO (&err_set);
-
- for (i = 0; i < n_fds; i++)
- {
- DBusPollFD *fdp = &fds[i];
-
- if (fdp->events & _DBUS_POLLIN)
- FD_SET (fdp->fd, &read_set);
-
- if (fdp->events & _DBUS_POLLOUT)
- FD_SET (fdp->fd, &write_set);
-
- FD_SET (fdp->fd, &err_set);
-
- max_fd = MAX (max_fd, fdp->fd);
- }
-
- tv.tv_sec = timeout_milliseconds / 1000;
- tv.tv_usec = (timeout_milliseconds % 1000) * 1000;
-
- ready = select (max_fd + 1, &read_set, &write_set, &err_set,
- timeout_milliseconds < 0 ? NULL : &tv);
-
- if (ready > 0)
- {
- for (i = 0; i < n_fds; i++)
- {
- DBusPollFD *fdp = &fds[i];
-
- fdp->revents = 0;
-
- if (FD_ISSET (fdp->fd, &read_set))
- fdp->revents |= _DBUS_POLLIN;
-
- if (FD_ISSET (fdp->fd, &write_set))
- fdp->revents |= _DBUS_POLLOUT;
-
- if (FD_ISSET (fdp->fd, &err_set))
- fdp->revents |= _DBUS_POLLERR;
- }
- }
-
- return ready;
-#endif
-}
-
-/** nanoseconds in a second */
-#define NANOSECONDS_PER_SECOND 1000000000
-/** microseconds in a second */
-#define MICROSECONDS_PER_SECOND 1000000
-/** milliseconds in a second */
-#define MILLISECONDS_PER_SECOND 1000
-/** nanoseconds in a millisecond */
-#define NANOSECONDS_PER_MILLISECOND 1000000
-/** microseconds in a millisecond */
-#define MICROSECONDS_PER_MILLISECOND 1000
-
-/**
- * Sleeps the given number of milliseconds.
- * @param milliseconds number of milliseconds
- */
-void
-_dbus_sleep_milliseconds (int milliseconds)
-{
-#ifdef HAVE_NANOSLEEP
- struct timespec req;
- struct timespec rem;
-
- req.tv_sec = milliseconds / MILLISECONDS_PER_SECOND;
- req.tv_nsec = (milliseconds % MILLISECONDS_PER_SECOND) * NANOSECONDS_PER_MILLISECOND;
- rem.tv_sec = 0;
- rem.tv_nsec = 0;
-
- while (nanosleep (&req, &rem) < 0 && errno == EINTR)
- req = rem;
-#elif defined (HAVE_USLEEP)
- usleep (milliseconds * MICROSECONDS_PER_MILLISECOND);
-#else /* ! HAVE_USLEEP */
- sleep (MAX (milliseconds / 1000, 1));
-#endif
-}
-
-/**
- * Get current time, as in gettimeofday().
- *
- * @param tv_sec return location for number of seconds
- * @param tv_usec return location for number of microseconds (thousandths)
- */
-void
-_dbus_get_current_time (long *tv_sec,
- long *tv_usec)
-{
- struct timeval t;
-
- gettimeofday (&t, NULL);
-
- if (tv_sec)
- *tv_sec = t.tv_sec;
- if (tv_usec)
- *tv_usec = t.tv_usec;
-}
-
-/**
- * Appends the contents of the given file to the string,
- * returning error code. At the moment, won't open a file
- * more than a megabyte in size.
- *
- * @param str the string to append to
- * @param filename filename to load
- * @param error place to set an error
- * @returns #FALSE if error was set
- */
-dbus_bool_t
-_dbus_file_get_contents (DBusString *str,
- const DBusString *filename,
- DBusError *error)
-{
- int fd;
- struct stat sb;
- int orig_len;
- int total;
- const char *filename_c;
-
- _DBUS_ASSERT_ERROR_IS_CLEAR (error);
-
- filename_c = _dbus_string_get_const_data (filename);
-
- /* O_BINARY useful on Cygwin */
- fd = open (filename_c, O_RDONLY | O_BINARY);
- if (fd < 0)
- {
- dbus_set_error (error, _dbus_error_from_errno (errno),
- "Failed to open \"%s\": %s",
- filename_c,
- _dbus_strerror (errno));
- return FALSE;
- }
-
- if (fstat (fd, &sb) < 0)
- {
- dbus_set_error (error, _dbus_error_from_errno (errno),
- "Failed to stat \"%s\": %s",
- filename_c,
- _dbus_strerror (errno));
-
- _dbus_verbose ("fstat() failed: %s",
- _dbus_strerror (errno));
-
- close (fd);
-
- return FALSE;
- }
-
- if (sb.st_size > _DBUS_ONE_MEGABYTE)
- {
- dbus_set_error (error, DBUS_ERROR_FAILED,
- "File size %lu of \"%s\" is too large.",
- (unsigned long) sb.st_size, filename_c);
- close (fd);
- return FALSE;
- }
-
- total = 0;
- orig_len = _dbus_string_get_length (str);
- if (sb.st_size > 0 && S_ISREG (sb.st_mode))
- {
- int bytes_read;
-
- while (total < (int) sb.st_size)
- {
- bytes_read = _dbus_read (fd, str,
- sb.st_size - total);
- if (bytes_read <= 0)
- {
- dbus_set_error (error, _dbus_error_from_errno (errno),
- "Error reading \"%s\": %s",
- filename_c,
- _dbus_strerror (errno));
-
- _dbus_verbose ("read() failed: %s",
- _dbus_strerror (errno));
-
- close (fd);
- _dbus_string_set_length (str, orig_len);
- return FALSE;
- }
- else
- total += bytes_read;
- }
-
- close (fd);
- return TRUE;
- }
- else if (sb.st_size != 0)
- {
- _dbus_verbose ("Can only open regular files at the moment.\n");
- dbus_set_error (error, DBUS_ERROR_FAILED,
- "\"%s\" is not a regular file",
- filename_c);
- close (fd);
- return FALSE;
- }
- else
- {
- close (fd);
- return TRUE;
- }
-}
-
-/**
- * Writes a string out to a file. If the file exists,
- * it will be atomically overwritten by the new data.
- *
- * @param str the string to write out
- * @param filename the file to save string to
- * @param error error to be filled in on failure
- * @returns #FALSE on failure
- */
-dbus_bool_t
-_dbus_string_save_to_file (const DBusString *str,
- const DBusString *filename,
- DBusError *error)
-{
- int fd;
- int bytes_to_write;
- const char *filename_c;
- DBusString tmp_filename;
- const char *tmp_filename_c;
- int total;
- dbus_bool_t need_unlink;
- dbus_bool_t retval;
-
- _DBUS_ASSERT_ERROR_IS_CLEAR (error);
-
- fd = -1;
- retval = FALSE;
- need_unlink = FALSE;
-
- if (!_dbus_string_init (&tmp_filename))
- {
- dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
- return FALSE;
- }
-
- if (!_dbus_string_copy (filename, 0, &tmp_filename, 0))
- {
- dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
- _dbus_string_free (&tmp_filename);
- return FALSE;
- }
-
- if (!_dbus_string_append (&tmp_filename, "."))
- {
- dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
- _dbus_string_free (&tmp_filename);
- return FALSE;
- }
-
-#define N_TMP_FILENAME_RANDOM_BYTES 8
- if (!_dbus_generate_random_ascii (&tmp_filename, N_TMP_FILENAME_RANDOM_BYTES))
- {
- dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
- _dbus_string_free (&tmp_filename);
- return FALSE;
- }
-
- filename_c = _dbus_string_get_const_data (filename);
- tmp_filename_c = _dbus_string_get_const_data (&tmp_filename);
-
- fd = open (tmp_filename_c, O_WRONLY | O_BINARY | O_EXCL | O_CREAT,
- 0600);
- if (fd < 0)
- {
- dbus_set_error (error, _dbus_error_from_errno (errno),
- "Could not create %s: %s", tmp_filename_c,
- _dbus_strerror (errno));
- goto out;
- }
-
- need_unlink = TRUE;
-
- total = 0;
- bytes_to_write = _dbus_string_get_length (str);
-
- while (total < bytes_to_write)
- {
- int bytes_written;
-
- bytes_written = _dbus_write (fd, str, total,
- bytes_to_write - total);
-
- if (bytes_written <= 0)
- {
- dbus_set_error (error, _dbus_error_from_errno (errno),
- "Could not write to %s: %s", tmp_filename_c,
- _dbus_strerror (errno));
-
- goto out;
- }
-
- total += bytes_written;
- }
-
- if (close (fd) < 0)
- {
- dbus_set_error (error, _dbus_error_from_errno (errno),
- "Could not close file %s: %s",
- tmp_filename_c, _dbus_strerror (errno));
-
- goto out;
- }
-
- fd = -1;
-
- if (rename (tmp_filename_c, filename_c) < 0)
- {
- dbus_set_error (error, _dbus_error_from_errno (errno),
- "Could not rename %s to %s: %s",
- tmp_filename_c, filename_c,
- _dbus_strerror (errno));
-
- goto out;
- }
-
- need_unlink = FALSE;
-
- retval = TRUE;
-
- out:
- /* close first, then unlink, to prevent ".nfs34234235" garbage
- * files
- */
-
- if (fd >= 0)
- close (fd);
-
- if (need_unlink && unlink (tmp_filename_c) < 0)
- _dbus_verbose ("Failed to unlink temp file %s: %s\n",
- tmp_filename_c, _dbus_strerror (errno));
-
- _dbus_string_free (&tmp_filename);
-
- if (!retval)
- _DBUS_ASSERT_ERROR_IS_SET (error);
-
- return retval;
-}
-
-/** Creates the given file, failing if the file already exists.
- *
- * @param filename the filename
- * @param error error location
- * @returns #TRUE if we created the file and it didn't exist
- */
-dbus_bool_t
-_dbus_create_file_exclusively (const DBusString *filename,
- DBusError *error)
-{
- int fd;
- const char *filename_c;
-
- _DBUS_ASSERT_ERROR_IS_CLEAR (error);
-
- filename_c = _dbus_string_get_const_data (filename);
-
- fd = open (filename_c, O_WRONLY | O_BINARY | O_EXCL | O_CREAT,
- 0600);
- if (fd < 0)
- {
- dbus_set_error (error,
- DBUS_ERROR_FAILED,
- "Could not create file %s: %s\n",
- filename_c,
- _dbus_strerror (errno));
- return FALSE;
- }
-
- if (close (fd) < 0)
- {
- dbus_set_error (error,
- DBUS_ERROR_FAILED,
- "Could not close file %s: %s\n",
- filename_c,
- _dbus_strerror (errno));
- return FALSE;
- }
-
- return TRUE;
-}
-
-/**
- * Deletes the given file.
- *
- * @param filename the filename
- * @param error error location
- *
- * @returns #TRUE if unlink() succeeded
- */
-dbus_bool_t
-_dbus_delete_file (const DBusString *filename,
- DBusError *error)
-{
- const char *filename_c;
-
- _DBUS_ASSERT_ERROR_IS_CLEAR (error);
-
- filename_c = _dbus_string_get_const_data (filename);
-
- if (unlink (filename_c) < 0)
- {
- dbus_set_error (error, DBUS_ERROR_FAILED,
- "Failed to delete file %s: %s\n",
- filename_c, _dbus_strerror (errno));
- return FALSE;
- }
- else
- return TRUE;
-}
-
-/**
- * Creates a directory; succeeds if the directory
- * is created or already existed.
- *
- * @param filename directory filename
- * @param error initialized error object
- * @returns #TRUE on success
- */
-dbus_bool_t
-_dbus_create_directory (const DBusString *filename,
- DBusError *error)
-{
- const char *filename_c;
-
- _DBUS_ASSERT_ERROR_IS_CLEAR (error);
-
- filename_c = _dbus_string_get_const_data (filename);
-
- if (mkdir (filename_c, 0700) < 0)
- {
- if (errno == EEXIST)
- return TRUE;
-
- dbus_set_error (error, DBUS_ERROR_FAILED,
- "Failed to create directory %s: %s\n",
- filename_c, _dbus_strerror (errno));
- return FALSE;
- }
- else
- return TRUE;
-}
-
-/**
- * Appends the given filename to the given directory.
- *
- * @todo it might be cute to collapse multiple '/' such as "foo//"
- * concat "//bar"
- *
- * @param dir the directory name
- * @param next_component the filename
- * @returns #TRUE on success
- */
-dbus_bool_t
-_dbus_concat_dir_and_file (DBusString *dir,
- const DBusString *next_component)
-{
- dbus_bool_t dir_ends_in_slash;
- dbus_bool_t file_starts_with_slash;
-
- if (_dbus_string_get_length (dir) == 0 ||
- _dbus_string_get_length (next_component) == 0)
- return TRUE;
-
- dir_ends_in_slash = '/' == _dbus_string_get_byte (dir,
- _dbus_string_get_length (dir) - 1);
-
- file_starts_with_slash = '/' == _dbus_string_get_byte (next_component, 0);
-
- if (dir_ends_in_slash && file_starts_with_slash)
- {
- _dbus_string_shorten (dir, 1);
- }
- else if (!(dir_ends_in_slash || file_starts_with_slash))
- {
- if (!_dbus_string_append_byte (dir, '/'))
- return FALSE;
- }
-
- return _dbus_string_copy (next_component, 0, dir,
- _dbus_string_get_length (dir));
-}
-
-static void
-pseudorandom_generate_random_bytes_buffer (char *buffer,
- int n_bytes)
-{
- unsigned long tv_usec;