### be underscore-prefixed)
set (DBUS_SHARED_SOURCES
${DBUS_DIR}/dbus-dataslot.c
+ ${DBUS_DIR}/dbus-file.c
${DBUS_DIR}/dbus-hash.c
${DBUS_DIR}/dbus-internals.c
${DBUS_DIR}/dbus-list.c
set (DBUS_SHARED_HEADERS
${DBUS_DIR}/dbus-dataslot.h
+ ${DBUS_DIR}/dbus-file.h
${DBUS_DIR}/dbus-hash.h
${DBUS_DIR}/dbus-internals.h
${DBUS_DIR}/dbus-list.h
### platform specific settings
if (WIN32)
set (DBUS_SHARED_SOURCES ${DBUS_SHARED_SOURCES}
+ ${DBUS_DIR}/dbus-file-win.c
${DBUS_DIR}/dbus-sysdeps-win.c
${DBUS_DIR}/dbus-pipe-win.c
${DBUS_DIR}/dbus-sysdeps-thread-win.c
set (LIBS ${LIBS} ws2_32 advapi32 netapi32)
else (WIN32)
set (DBUS_SHARED_SOURCES ${DBUS_SHARED_SOURCES}
+ ${DBUS_DIR}/dbus-file-unix.c
${DBUS_DIR}/dbus-pipe-unix.c
${DBUS_DIR}/dbus-sysdeps-unix.c
${DBUS_DIR}/dbus-sysdeps-pthread.c
dbus-server-win.h
DBUS_SHARED_arch_sources = \
+ dbus-file-win.c \
dbus-pipe-win.c \
dbus-sysdeps-win.c \
dbus-sysdeps-win.h \
dbus-server-unix.h
DBUS_SHARED_arch_sources = \
+ dbus-file-unix.c \
dbus-pipe-unix.c \
dbus-sysdeps-unix.c \
dbus-sysdeps-unix.h \
DBUS_SHARED_SOURCES= \
dbus-dataslot.c \
dbus-dataslot.h \
+ dbus-file.c \
+ dbus-file.h \
dbus-hash.c \
dbus-hash.h \
dbus-internals.c \
--- /dev/null
+/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
+/* dbus-file-unix.c unix related file implementation (internal to D-Bus implementation)
+ *
+ * Copyright (C) 2002, 2003, 2006 Red Hat, Inc.
+ * Copyright (C) 2003 CodeFactory AB
+ *
+ * Licensed under the Academic Free License version 2.1
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ */
+
+#include <config.h>
+#include "dbus-file.h"
+
+/**
+ * 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;
+ }
+
+ _dbus_verbose ("file fd %d opened\n", fd);
+
+ 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));
+
+ _dbus_close (fd, NULL);
+
+ 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);
+ _dbus_close (fd, NULL);
+ 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));
+
+ _dbus_close (fd, NULL);
+ _dbus_string_set_length (str, orig_len);
+ return FALSE;
+ }
+ else
+ total += bytes_read;
+ }
+
+ _dbus_close (fd, NULL);
+ 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);
+ _dbus_close (fd, NULL);
+ return FALSE;
+ }
+ else
+ {
+ _dbus_close (fd, NULL);
+ 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;
+ }
+
+ _dbus_verbose ("tmp file fd %d opened\n", fd);
+
+ 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 (fsync(fd))
+ {
+ dbus_set_error (error, _dbus_error_from_errno (errno),
+ "Could not synchronize file %s: %s",
+ tmp_filename_c, _dbus_strerror (errno));
+
+ goto out;
+ }
+
+ if (!_dbus_close (fd, NULL))
+ {
+ 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)
+ _dbus_close (fd, NULL);
+
+ 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;
+}
+
+/** Makes the file readable by every user in the system.
+ *
+ * @param filename the filename
+ * @param error error location
+ * @returns #TRUE if the file's permissions could be changed.
+ */
+dbus_bool_t
+_dbus_make_file_world_readable(const DBusString *filename,
+ DBusError *error)
+{
+ const char *filename_c;
+
+ _DBUS_ASSERT_ERROR_IS_CLEAR (error);
+
+ filename_c = _dbus_string_get_const_data (filename);
+ if (chmod (filename_c, 0644) == -1)
+ {
+ dbus_set_error (error,
+ DBUS_ERROR_FAILED,
+ "Could not change permissions of file %s: %s\n",
+ filename_c,
+ _dbus_strerror (errno));
+ return FALSE;
+ }
+ return TRUE;
+}
+
+/** 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;
+ }
+
+ _dbus_verbose ("exclusive file fd %d opened\n", fd);
+
+ if (!_dbus_close (fd, NULL))
+ {
+ 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;
+}
--- /dev/null
+/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
+/* dbus-file-win.c windows related file implementation (internal to D-Bus implementation)
+ *
+ * Copyright (C) 2002, 2003, 2006 Red Hat, Inc.
+ * Copyright (C) 2003 CodeFactory AB
+ *
+ * Licensed under the Academic Free License version 2.1
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ */
+
+#include "dbus-protocol.h"
+#include "dbus-string.h"
+#include "dbus-internals.h"
+#include "dbus-sysdeps-win.h"
+#include "dbus-pipe.h"
+
+#include <errno.h>
+#include <fcntl.h>
+#include <io.h>
+#include <sys/stat.h>
+
+#include <windows.h>
+/**
+ * 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 _stati64 sb;
+ int orig_len;
+ int total;
+ const char *filename_c;
+
+ _DBUS_ASSERT_ERROR_IS_CLEAR (error);
+
+ filename_c = _dbus_string_get_const_data (filename);
+
+ 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,
+ strerror (errno));
+ return FALSE;
+ }
+
+ _dbus_verbose ("file %s fd %d opened\n", filename_c, fd);
+
+ if (_fstati64 (fd, &sb) < 0)
+ {
+ dbus_set_error (error, _dbus_error_from_errno (errno),
+ "Failed to stat \"%s\": %s",
+ filename_c,
+ strerror (errno));
+
+ _dbus_verbose ("fstat() failed: %s",
+ 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_file_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,
+ strerror (errno));
+
+ _dbus_verbose ("read() failed: %s",
+ 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;
+ const char *str_c;
+ 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,
+ strerror (errno));
+ goto out;
+ }
+
+ _dbus_verbose ("tmp file %s fd %d opened\n", tmp_filename_c, fd);
+
+ need_unlink = TRUE;
+
+ total = 0;
+ bytes_to_write = _dbus_string_get_length (str);
+ str_c = _dbus_string_get_const_data (str);
+
+ while (total < bytes_to_write)
+ {
+ int bytes_written;
+
+ bytes_written = _write (fd, str_c + 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,
+ 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, strerror (errno));
+
+ goto out;
+ }
+
+ fd = -1;
+
+ /* Unlike rename(), MoveFileEx() can replace existing files */
+ if (MoveFileExA (tmp_filename_c, filename_c, MOVEFILE_REPLACE_EXISTING) < 0)
+ {
+ char *emsg = _dbus_win_error_string (GetLastError ());
+ dbus_set_error (error, DBUS_ERROR_FAILED,
+ "Could not rename %s to %s: %s",
+ tmp_filename_c, filename_c,
+ emsg);
+ _dbus_win_free_error_string (emsg);
+
+ goto out;
+ }
+
+ need_unlink = FALSE;
+
+ retval = TRUE;
+
+ out:
+ /* close first, then unlink */
+
+ 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, 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,
+ strerror (errno));
+ return FALSE;
+ }
+
+ _dbus_verbose ("exclusive file %s fd %d opened\n", filename_c, fd);
+
+ if (_close (fd) < 0)
+ {
+ dbus_set_error (error,
+ DBUS_ERROR_FAILED,
+ "Could not close file %s: %s\n",
+ filename_c,
+ strerror (errno));
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+/**
+ * Thin wrapper around the read() system call that appends
+ * the data it reads to the DBusString buffer. It appends
+ * up to the given count, and returns the same value
+ * and same errno as read(). The only exception is that
+ * _dbus_file_read() handles EINTR for you. Also,
+ * _dbus_file_read() can return ENOMEM.
+ *
+ * @param fd the file descriptor to read from
+ * @param buffer the buffer to append data to
+ * @param count the amount of data to read
+ * @returns the number of bytes read or -1
+ */
+int
+_dbus_file_read (int fd,
+ DBusString *buffer,
+ int count)
+{
+ int bytes_read;
+ int start;
+ char *data;
+
+ _dbus_assert (count >= 0);
+
+ start = _dbus_string_get_length (buffer);
+
+ if (!_dbus_string_lengthen (buffer, count))
+ {
+ errno = ENOMEM;
+ return -1;
+ }
+
+ data = _dbus_string_get_data_len (buffer, start, count);
+
+ again:
+
+ bytes_read = _read (fd, data, count);
+
+ if (bytes_read < 0)
+ {
+ if (errno == EINTR)
+ goto again;
+ else
+ {
+ /* put length back (note that this doesn't actually realloc anything) */
+ _dbus_string_set_length (buffer, start);
+ return -1;
+ }
+ }
+ else
+ {
+ /* put length back (doesn't actually realloc) */
+ _dbus_string_set_length (buffer, start + bytes_read);
+
+#if 0
+ if (bytes_read > 0)
+ _dbus_verbose_bytes_of_string (buffer, start, bytes_read);
+#endif
+
+ return bytes_read;
+ }
+}
--- /dev/null
+/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
+/* dbus-sysdeps-unix.c Wrappers around UNIX system/libc features (internal to D-Bus implementation)
+ *
+ * Copyright (C) 2002, 2003, 2006 Red Hat, Inc.
+ * Copyright (C) 2003 CodeFactory AB
+ *
+ * Licensed under the Academic Free License version 2.1
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ */
+
+#include <config.h>
+
+#include "dbus-file.h"
+
--- /dev/null
+/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
+/* dbus-file.h dbus file related stuff (internal to D-Bus implementation)
+ *
+ * Copyright (C) 2002, 2003 Red Hat, Inc.
+ * Copyright (C) 2003 CodeFactory AB
+ *
+ * Licensed under the Academic Free License version 2.1
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ */
+
+#ifndef DBUS_FILE_H
+#define DBUS_FILE_H
+
+//#include <dbus/dbus-types.h>
+#include <dbus/dbus-string.h>
+#include <dbus/dbus-errors.h>
+
+DBUS_BEGIN_DECLS
+
+/**
+ * @addtogroup DBusFile
+ * @{
+ */
+
+/**
+ * File interface
+ */
+dbus_bool_t _dbus_file_exists (const char *file);
+dbus_bool_t _dbus_file_get_contents (DBusString *str,
+ const DBusString *filename,
+ DBusError *error);
+dbus_bool_t _dbus_string_save_to_file (const DBusString *str,
+ const DBusString *filename,
+ DBusError *error);
+
+dbus_bool_t _dbus_make_file_world_readable (const DBusString *filename,
+ DBusError *error);
+
+dbus_bool_t _dbus_create_file_exclusively (const DBusString *filename,
+ DBusError *error);
+dbus_bool_t _dbus_delete_file (const DBusString *filename,
+ DBusError *error);
+int _dbus_file_read (int fd,
+ DBusString *buffer,
+ int count);
+
+/** @} */
+
+DBUS_END_DECLS
+
+#endif
typedef int socklen_t;
-static char*
+char*
_dbus_win_error_string (int error_number)
{
char *msg;
return msg;
}
-static void
+void
_dbus_win_free_error_string (char *string)
{
LocalFree (string);
* the data it reads to the DBusString buffer. It appends
* up to the given count, and returns the same value
* and same errno as read(). The only exception is that
- * _dbus_read() handles EINTR for you. _dbus_read() can
- * return ENOMEM, even though regular UNIX read doesn't.
+ * _dbus_read_socket() handles EINTR for you.
+ * _dbus_read_socket() can return ENOMEM, even though
+ * regular UNIX read doesn't.
*
* @param fd the file descriptor to read from
* @param buffer the buffer to append data to
{
}
-
-/* _dbus_read() is static on Windows, only used below in this file.
- */
-static int
-_dbus_read (int fd,
- DBusString *buffer,
- int count)
-{
- int bytes_read;
- int start;
- char *data;
-
- _dbus_assert (count >= 0);
-
- start = _dbus_string_get_length (buffer);
-
- if (!_dbus_string_lengthen (buffer, count))
- {
- errno = ENOMEM;
- return -1;
- }
-
- data = _dbus_string_get_data_len (buffer, start, count);
-
- again:
-
- bytes_read = _read (fd, data, count);
-
- if (bytes_read < 0)
- {
- if (errno == EINTR)
- goto again;
- else
- {
- /* put length back (note that this doesn't actually realloc anything) */
- _dbus_string_set_length (buffer, start);
- return -1;
- }
- }
- else
- {
- /* put length back (doesn't actually realloc) */
- _dbus_string_set_length (buffer, start + bytes_read);
-
-#if 0
- if (bytes_read > 0)
- _dbus_verbose_bytes_of_string (buffer, start, bytes_read);
-#endif
-
- return bytes_read;
- }
-}
-
-/**
- * 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 _stati64 sb;
- int orig_len;
- int total;
- const char *filename_c;
-
- _DBUS_ASSERT_ERROR_IS_CLEAR (error);
-
- filename_c = _dbus_string_get_const_data (filename);
-
- 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,
- strerror (errno));
- return FALSE;
- }
-
- _dbus_verbose ("file %s fd %d opened\n", filename_c, fd);
-
- if (_fstati64 (fd, &sb) < 0)
- {
- dbus_set_error (error, _dbus_error_from_errno (errno),
- "Failed to stat \"%s\": %s",
- filename_c,
- strerror (errno));
-
- _dbus_verbose ("fstat() failed: %s",
- 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,
- strerror (errno));
-
- _dbus_verbose ("read() failed: %s",
- 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;
- const char *str_c;
- 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,
- strerror (errno));
- goto out;
- }
-
- _dbus_verbose ("tmp file %s fd %d opened\n", tmp_filename_c, fd);
-
- need_unlink = TRUE;
-
- total = 0;
- bytes_to_write = _dbus_string_get_length (str);
- str_c = _dbus_string_get_const_data (str);
-
- while (total < bytes_to_write)
- {
- int bytes_written;
-
- bytes_written = _write (fd, str_c + 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,
- 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, strerror (errno));
-
- goto out;
- }
-
- fd = -1;
-
- /* Unlike rename(), MoveFileEx() can replace existing files */
- if (MoveFileExA (tmp_filename_c, filename_c, MOVEFILE_REPLACE_EXISTING) < 0)
- {
- char *emsg = _dbus_win_error_string (GetLastError ());
- dbus_set_error (error, DBUS_ERROR_FAILED,
- "Could not rename %s to %s: %s",
- tmp_filename_c, filename_c,
- emsg);
- _dbus_win_free_error_string (emsg);
-
- goto out;
- }
-
- need_unlink = FALSE;
-
- retval = TRUE;
-
- out:
- /* close first, then unlink */
-
- 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, 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,
- strerror (errno));
- return FALSE;
- }
-
- _dbus_verbose ("exclusive file %s fd %d opened\n", filename_c, fd);
-
- if (_close (fd) < 0)
- {
- dbus_set_error (error,
- DBUS_ERROR_FAILED,
- "Could not close file %s: %s\n",
- filename_c,
- strerror (errno));
- return FALSE;
- }
-
- return TRUE;
-}
-
-
/**
* Creates a directory; succeeds if the directory
* is created or already existed.
void _dbus_win_startup_winsock (void);
void _dbus_win_warn_win_error (const char *message,
int code);
+
+char * _dbus_win_error_string (int error_number);
+void _dbus_win_free_error_string (char *string);
+
extern const char* _dbus_lm_strerror (int error_number);
#include <config.h>
#include <dbus/dbus-errors.h>
+#include <dbus/dbus-file.h>
#include <dbus/dbus-string.h>
#include <dbus/dbus-pipe.h>
long *tv_usec);
/**
- * File/directory interface
+ * directory interface
*/
-dbus_bool_t _dbus_file_exists (const char *file);
-dbus_bool_t _dbus_file_get_contents (DBusString *str,
- const DBusString *filename,
- DBusError *error);
-dbus_bool_t _dbus_string_save_to_file (const DBusString *str,
- const DBusString *filename,
- DBusError *error);
-
-dbus_bool_t _dbus_make_file_world_readable (const DBusString *filename,
- DBusError *error);
-
-dbus_bool_t _dbus_create_file_exclusively (const DBusString *filename,
- DBusError *error);
-dbus_bool_t _dbus_delete_file (const DBusString *filename,
- DBusError *error);
dbus_bool_t _dbus_create_directory (const DBusString *filename,
DBusError *error);
dbus_bool_t _dbus_delete_directory (const DBusString *filename,