1 /* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
2 /* dbus-sysdeps.c Wrappers around system/libc features (internal to D-BUS implementation)
4 * Copyright (C) 2002, 2003 Red Hat, Inc.
5 * Copyright (C) 2003 CodeFactory AB
6 * Copyright (C) 2005 Novell, Inc.
7 * Copyright (C) 2006 Ralf Habacker <ralf.habacker@freenet.de>
8 * Copyright (C) 2006 Peter Kümmel <syntheticpp@gmx.net>
9 * Copyright (C) 2006 Christian Ehrlicher <ch.ehrlicher@gmx.de>
11 * Licensed under the Academic Free License version 2.1
13 * This program is free software; you can redistribute it and/or modify
14 * it under the terms of the GNU General Public License as published by
15 * the Free Software Foundation; either version 2 of the License, or
16 * (at your option) any later version.
18 * This program is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU General Public License for more details.
23 * You should have received a copy of the GNU General Public License
24 * along with this program; if not, write to the Free Software
25 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
31 #define STRSAFE_NO_DEPRECATE
34 #define _WIN32_WINNT 0x0500
37 #include "dbus-internals.h"
38 #include "dbus-sysdeps.h"
39 #include "dbus-threads.h"
40 #include "dbus-protocol.h"
41 #include "dbus-string.h"
42 #include "dbus-sysdeps-win.h"
43 #include "dbus-protocol.h"
44 #include "dbus-hash.h"
45 #include "dbus-sockets-win.h"
46 #include "dbus-list.h"
47 #include "dbus-credentials.h"
54 #include <sys/types.h>
60 #ifndef HAVE_SOCKLEN_T
69 _dbus_file_open (DBusFile *file,
75 file->FDATA = _open (filename, oflag, pmode);
77 file->FDATA = _open (filename, oflag);
88 _dbus_file_close (DBusFile *file,
91 const int fd = file->FDATA;
93 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
95 _dbus_assert (fd >= 0);
97 if (_close (fd) == -1)
99 dbus_set_error (error, _dbus_error_from_errno (errno),
100 "Could not close fd %d: %s", fd,
101 _dbus_strerror (errno));
106 _dbus_verbose ("closed C file descriptor %d:\n",fd);
112 _dbus_file_read(DBusFile *file,
116 const int fd = file->FDATA;
120 _dbus_assert (count >= 0);
122 start = _dbus_string_get_length (buffer);
124 if (!_dbus_string_lengthen (buffer, count))
130 data = _dbus_string_get_data_len (buffer, start, count);
132 _dbus_assert (fd >= 0);
134 _dbus_verbose ("read: count=%d fd=%d\n", count, fd);
135 bytes_read = read (fd, data, count);
137 if (bytes_read == -1)
138 _dbus_verbose ("read: failed: %s\n", _dbus_strerror (errno));
140 _dbus_verbose ("read: = %d\n", bytes_read);
144 /* put length back (note that this doesn't actually realloc anything) */
145 _dbus_string_set_length (buffer, start);
150 /* put length back (doesn't actually realloc) */
151 _dbus_string_set_length (buffer, start + bytes_read);
156 _dbus_verbose_bytes_of_string (buffer, start, bytes_read);
164 _dbus_file_write (DBusFile *file,
165 const DBusString *buffer,
169 const int fd = file->FDATA;
173 data = _dbus_string_get_const_data_len (buffer, start, len);
175 _dbus_assert (fd >= 0);
177 _dbus_verbose ("write: len=%d fd=%d\n", len, fd);
178 bytes_written = write (fd, data, len);
180 if (bytes_written == -1)
181 _dbus_verbose ("write: failed: %s\n", _dbus_strerror (errno));
183 _dbus_verbose ("write: = %d\n", bytes_written);
187 if (bytes_written > 0)
188 _dbus_verbose_bytes_of_string (buffer, start, bytes_written);
191 return bytes_written;
195 _dbus_is_valid_file (DBusFile* file)
197 return file->FDATA >= 0;
200 dbus_bool_t _dbus_fstat (DBusFile *file,
203 return fstat(file->FDATA, sb) >= 0;
207 * write data to a pipe.
209 * @param pipe the pipe instance
210 * @param buffer the buffer to write data from
211 * @param start the first byte in the buffer to write
212 * @param len the number of bytes to try to write
213 * @param error error return
214 * @returns the number of bytes written or -1 on error
217 _dbus_pipe_write (DBusPipe *pipe,
218 const DBusString *buffer,
225 file.FDATA = pipe->fd_or_handle;
226 written = _dbus_file_write (&file, buffer, start, len);
229 dbus_set_error (error, DBUS_ERROR_FAILED,
230 "Writing to pipe: %s\n",
231 _dbus_strerror (errno));
239 * @param pipe the pipe instance
240 * @param error return location for an error
241 * @returns #FALSE if error is set
244 _dbus_pipe_close (DBusPipe *pipe,
248 file.FDATA = pipe->fd_or_handle;
249 if (_dbus_file_close (&file, error) < 0)
255 _dbus_pipe_invalidate (pipe);
268 * Thin wrapper around the read() system call that appends
269 * the data it reads to the DBusString buffer. It appends
270 * up to the given count, and returns the same value
271 * and same errno as read(). The only exception is that
272 * _dbus_read() handles EINTR for you. _dbus_read() can
273 * return ENOMEM, even though regular UNIX read doesn't.
275 * @param fd the file descriptor to read from
276 * @param buffer the buffer to append data to
277 * @param count the amount of data to read
278 * @returns the number of bytes read or -1
281 _dbus_read_socket (int fd,
289 _dbus_assert (count >= 0);
291 start = _dbus_string_get_length (buffer);
293 if (!_dbus_string_lengthen (buffer, count))
299 data = _dbus_string_get_data_len (buffer, start, count);
303 _dbus_verbose ("recv: count=%d fd=%d\n", count, fd);
304 bytes_read = recv (fd, data, count, 0);
306 if (bytes_read == SOCKET_ERROR)
308 DBUS_SOCKET_SET_ERRNO();
309 _dbus_verbose ("recv: failed: %s\n", _dbus_strerror (errno));
313 _dbus_verbose ("recv: = %d\n", bytes_read);
321 /* put length back (note that this doesn't actually realloc anything) */
322 _dbus_string_set_length (buffer, start);
328 /* put length back (doesn't actually realloc) */
329 _dbus_string_set_length (buffer, start + bytes_read);
333 _dbus_verbose_bytes_of_string (buffer, start, bytes_read);
341 * Thin wrapper around the write() system call that writes a part of a
342 * DBusString and handles EINTR for you.
344 * @param fd the file descriptor to write
345 * @param buffer the buffer to write data from
346 * @param start the first byte in the buffer to write
347 * @param len the number of bytes to try to write
348 * @returns the number of bytes written or -1 on error
351 _dbus_write_socket (int fd,
352 const DBusString *buffer,
359 data = _dbus_string_get_const_data_len (buffer, start, len);
363 _dbus_verbose ("send: len=%d fd=%d\n", len, fd);
364 bytes_written = send (fd, data, len, 0);
366 if (bytes_written == SOCKET_ERROR)
368 DBUS_SOCKET_SET_ERRNO();
369 _dbus_verbose ("send: failed: %s\n", _dbus_strerror (errno));
373 _dbus_verbose ("send: = %d\n", bytes_written);
375 if (bytes_written < 0 && errno == EINTR)
379 if (bytes_written > 0)
380 _dbus_verbose_bytes_of_string (buffer, start, bytes_written);
383 return bytes_written;
388 * Closes a file descriptor.
390 * @param fd the file descriptor
391 * @param error error object
392 * @returns #FALSE if error set
395 _dbus_close_socket (int fd,
398 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
401 if (closesocket (fd) == SOCKET_ERROR)
403 DBUS_SOCKET_SET_ERRNO ();
408 dbus_set_error (error, _dbus_error_from_errno (errno),
409 "Could not close socket: socket=%d, , %s",
410 fd, _dbus_strerror (errno));
413 _dbus_verbose ("_dbus_close_socket: socket=%d, \n", fd);
419 * Sets the file descriptor to be close
420 * on exec. Should be called for all file
421 * descriptors in D-Bus code.
423 * @param fd the file descriptor
426 _dbus_fd_set_close_on_exec (int handle)
428 #ifdef ENABLE_DBUSSOCKET
433 _dbus_lock_sockets();
435 _dbus_handle_to_socket_unlocked (handle, &s);
436 s->close_on_exec = TRUE;
438 _dbus_unlock_sockets();
443 val = fcntl (fd, F_GETFD, 0);
450 fcntl (fd, F_SETFD, val);
456 * Sets a file descriptor to be nonblocking.
458 * @param fd the file descriptor.
459 * @param error address of error location.
460 * @returns #TRUE on success.
463 _dbus_set_fd_nonblocking (int handle,
468 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
470 if (ioctlsocket (handle, FIONBIO, &one) == SOCKET_ERROR)
472 dbus_set_error (error, _dbus_error_from_errno (WSAGetLastError ()),
473 "Failed to set socket %d:%d to nonblocking: %s", handle,
474 _dbus_strerror (WSAGetLastError ()));
483 * Like _dbus_write() but will use writev() if possible
484 * to write both buffers in sequence. The return value
485 * is the number of bytes written in the first buffer,
486 * plus the number written in the second. If the first
487 * buffer is written successfully and an error occurs
488 * writing the second, the number of bytes in the first
489 * is returned (i.e. the error is ignored), on systems that
490 * don't have writev. Handles EINTR for you.
491 * The second buffer may be #NULL.
493 * @param fd the file descriptor
494 * @param buffer1 first buffer
495 * @param start1 first byte to write in first buffer
496 * @param len1 number of bytes to write from first buffer
497 * @param buffer2 second buffer, or #NULL
498 * @param start2 first byte to write in second buffer
499 * @param len2 number of bytes to write in second buffer
500 * @returns total bytes written from both buffers, or -1 on error
503 _dbus_write_socket_two (int fd,
504 const DBusString *buffer1,
507 const DBusString *buffer2,
518 _dbus_assert (buffer1 != NULL);
519 _dbus_assert (start1 >= 0);
520 _dbus_assert (start2 >= 0);
521 _dbus_assert (len1 >= 0);
522 _dbus_assert (len2 >= 0);
525 data1 = _dbus_string_get_const_data_len (buffer1, start1, len1);
528 data2 = _dbus_string_get_const_data_len (buffer2, start2, len2);
536 vectors[0].buf = (char*) data1;
537 vectors[0].len = len1;
538 vectors[1].buf = (char*) data2;
539 vectors[1].len = len2;
543 _dbus_verbose ("WSASend: len1+2=%d+%d fd=%d\n", len1, len2, fd);
554 DBUS_SOCKET_SET_ERRNO ();
555 _dbus_verbose ("WSASend: failed: %s\n", _dbus_strerror (errno));
559 _dbus_verbose ("WSASend: = %ld\n", bytes_written);
561 if (bytes_written < 0 && errno == EINTR)
564 return bytes_written;
570 * Opens the client side of a Windows named pipe. The connection D-BUS
571 * file descriptor index is returned. It is set up as nonblocking.
573 * @param path the path to named pipe socket
574 * @param error return location for error code
575 * @returns connection D-BUS file descriptor or -1 on error
578 _dbus_connect_named_pipe (const char *path,
581 _dbus_assert_not_reached ("not implemented");
589 _dbus_win_startup_winsock (void)
591 /* Straight from MSDN, deuglified */
593 static dbus_bool_t beenhere = FALSE;
595 WORD wVersionRequested;
602 wVersionRequested = MAKEWORD (2, 0);
604 err = WSAStartup (wVersionRequested, &wsaData);
607 _dbus_assert_not_reached ("Could not initialize WinSock");
611 /* Confirm that the WinSock DLL supports 2.0. Note that if the DLL
612 * supports versions greater than 2.0 in addition to 2.0, it will
613 * still return 2.0 in wVersion since that is the version we
616 if (LOBYTE (wsaData.wVersion) != 2 ||
617 HIBYTE (wsaData.wVersion) != 0)
619 _dbus_assert_not_reached ("No usable WinSock found");
634 /************************************************************************
638 ************************************************************************/
641 * Measure the message length without terminating nul
643 int _dbus_printf_string_upper_bound (const char *format,
646 /* MSVCRT's vsnprintf semantics are a bit different */
647 /* The C library source in the Platform SDK indicates that this
648 * would work, but alas, it doesn't. At least not on Windows
649 * 2000. Presumably those sources correspond to the C library on
650 * some newer or even future Windows version.
652 len = _vsnprintf (NULL, _DBUS_INT_MAX, format, args);
656 len = _vsnprintf (p, sizeof(p)-1, format, args);
657 if (len == -1) // try again
660 p = malloc (strlen(format)*3);
661 len = _vsnprintf (p, sizeof(p)-1, format, args);
669 * Returns the UTF-16 form of a UTF-8 string. The result should be
670 * freed with dbus_free() when no longer needed.
672 * @param str the UTF-8 string
673 * @param error return location for error code
676 _dbus_win_utf8_to_utf16 (const char *str,
683 _dbus_string_init_const (&s, str);
685 if (!_dbus_string_validate_utf8 (&s, 0, _dbus_string_get_length (&s)))
687 dbus_set_error_const (error, DBUS_ERROR_FAILED, "Invalid UTF-8");
691 n = MultiByteToWideChar (CP_UTF8, 0, str, -1, NULL, 0);
695 _dbus_win_set_error_from_win_error (error, GetLastError ());
699 retval = dbus_new (wchar_t, n);
703 _DBUS_SET_OOM (error);
707 if (MultiByteToWideChar (CP_UTF8, 0, str, -1, retval, n) != n)
710 dbus_set_error_const (error, DBUS_ERROR_FAILED, "MultiByteToWideChar inconsistency");
718 * Returns the UTF-8 form of a UTF-16 string. The result should be
719 * freed with dbus_free() when no longer needed.
721 * @param str the UTF-16 string
722 * @param error return location for error code
725 _dbus_win_utf16_to_utf8 (const wchar_t *str,
731 n = WideCharToMultiByte (CP_UTF8, 0, str, -1, NULL, 0, NULL, NULL);
735 _dbus_win_set_error_from_win_error (error, GetLastError ());
739 retval = dbus_malloc (n);
743 _DBUS_SET_OOM (error);
747 if (WideCharToMultiByte (CP_UTF8, 0, str, -1, retval, n, NULL, NULL) != n)
750 dbus_set_error_const (error, DBUS_ERROR_FAILED, "WideCharToMultiByte inconsistency");
762 /************************************************************************
765 ************************************************************************/
768 _dbus_win_account_to_sid (const wchar_t *waccount,
772 dbus_bool_t retval = FALSE;
773 DWORD sid_length, wdomain_length;
781 if (!LookupAccountNameW (NULL, waccount, NULL, &sid_length,
782 NULL, &wdomain_length, &use) &&
783 GetLastError () != ERROR_INSUFFICIENT_BUFFER)
785 _dbus_win_set_error_from_win_error (error, GetLastError ());
789 *ppsid = dbus_malloc (sid_length);
792 _DBUS_SET_OOM (error);
796 wdomain = dbus_new (wchar_t, wdomain_length);
799 _DBUS_SET_OOM (error);
803 if (!LookupAccountNameW (NULL, waccount, (PSID) *ppsid, &sid_length,
804 wdomain, &wdomain_length, &use))
806 _dbus_win_set_error_from_win_error (error, GetLastError ());
810 if (!IsValidSid ((PSID) *ppsid))
812 dbus_set_error_const (error, DBUS_ERROR_FAILED, "Invalid SID");
830 /** @} end of sysdeps-win */
834 * @returns process UID
839 return DBUS_UID_UNSET;
842 /** Gets our effective UID
843 * @returns process effective UID
848 return DBUS_UID_UNSET;
852 * The only reason this is separate from _dbus_getpid() is to allow it
853 * on Windows for logging but not for other purposes.
855 * @returns process ID to put in log messages
858 _dbus_pid_for_log (void)
860 return _dbus_getpid ();
864 * @param points to sid buffer, need to be freed with LocalFree()
865 * @returns process sid
868 _dbus_getsid(char **sid)
870 HANDLE process_token = NULL;
871 TOKEN_USER *token_user = NULL;
876 if (!OpenProcessToken (GetCurrentProcess (), TOKEN_QUERY, &process_token))
878 _dbus_win_warn_win_error ("OpenProcessToken failed", GetLastError ());
881 if ((!GetTokenInformation (process_token, TokenUser, NULL, 0, &n)
882 && GetLastError () != ERROR_INSUFFICIENT_BUFFER)
883 || (token_user = alloca (n)) == NULL
884 || !GetTokenInformation (process_token, TokenUser, token_user, n, &n))
886 _dbus_win_warn_win_error ("GetTokenInformation failed", GetLastError ());
889 psid = token_user->User.Sid;
890 if (!IsValidSid (psid))
892 _dbus_verbose("%s invalid sid\n",__FUNCTION__);
895 if (!ConvertSidToStringSidA (psid, sid))
897 _dbus_verbose("%s invalid sid\n",__FUNCTION__);
904 if (process_token != NULL)
905 CloseHandle (process_token);
907 _dbus_verbose("_dbus_getsid() returns %d\n",retval);
912 #ifdef DBUS_BUILD_TESTS
914 * @returns process GID
919 return DBUS_GID_UNSET;
924 _dbus_domain_test (const char *test_data_dir)
926 if (!_dbus_test_oom_handling ("spawn_nonexistent",
927 check_spawn_nonexistent,
934 #endif //DBUS_BUILD_TESTS
936 /************************************************************************
940 ************************************************************************/
943 * Creates a full-duplex pipe (as in socketpair()).
944 * Sets both ends of the pipe nonblocking.
946 * @todo libdbus only uses this for the debug-pipe server, so in
947 * principle it could be in dbus-sysdeps-util.c, except that
948 * dbus-sysdeps-util.c isn't in libdbus when tests are enabled and the
949 * debug-pipe server is used.
951 * @param fd1 return location for one end
952 * @param fd2 return location for the other end
953 * @param blocking #TRUE if pipe should be blocking
954 * @param error error return
955 * @returns #FALSE on failure (if error is set)
958 _dbus_full_duplex_pipe (int *fd1,
960 dbus_bool_t blocking,
963 SOCKET temp, socket1 = -1, socket2 = -1;
964 struct sockaddr_in saddr;
967 fd_set read_set, write_set;
970 _dbus_win_startup_winsock ();
972 temp = socket (AF_INET, SOCK_STREAM, 0);
973 if (temp == INVALID_SOCKET)
975 DBUS_SOCKET_SET_ERRNO ();
980 if (ioctlsocket (temp, FIONBIO, &arg) == SOCKET_ERROR)
982 DBUS_SOCKET_SET_ERRNO ();
987 saddr.sin_family = AF_INET;
989 saddr.sin_addr.s_addr = htonl (INADDR_LOOPBACK);
991 if (bind (temp, (struct sockaddr *)&saddr, sizeof (saddr)))
993 DBUS_SOCKET_SET_ERRNO ();
997 if (listen (temp, 1) == SOCKET_ERROR)
999 DBUS_SOCKET_SET_ERRNO ();
1003 len = sizeof (saddr);
1004 if (getsockname (temp, (struct sockaddr *)&saddr, &len))
1006 DBUS_SOCKET_SET_ERRNO ();
1010 socket1 = socket (AF_INET, SOCK_STREAM, 0);
1011 if (socket1 == INVALID_SOCKET)
1013 DBUS_SOCKET_SET_ERRNO ();
1018 if (ioctlsocket (socket1, FIONBIO, &arg) == SOCKET_ERROR)
1020 DBUS_SOCKET_SET_ERRNO ();
1024 if (connect (socket1, (struct sockaddr *)&saddr, len) != SOCKET_ERROR ||
1025 WSAGetLastError () != WSAEWOULDBLOCK)
1027 DBUS_SOCKET_SET_ERRNO ();
1031 FD_ZERO (&read_set);
1032 FD_SET (temp, &read_set);
1037 if (select (0, &read_set, NULL, NULL, NULL) == SOCKET_ERROR)
1039 DBUS_SOCKET_SET_ERRNO ();
1043 _dbus_assert (FD_ISSET (temp, &read_set));
1045 socket2 = accept (temp, (struct sockaddr *) &saddr, &len);
1046 if (socket2 == INVALID_SOCKET)
1048 DBUS_SOCKET_SET_ERRNO ();
1052 FD_ZERO (&write_set);
1053 FD_SET (socket1, &write_set);
1058 if (select (0, NULL, &write_set, NULL, NULL) == SOCKET_ERROR)
1060 DBUS_SOCKET_SET_ERRNO ();
1064 _dbus_assert (FD_ISSET (socket1, &write_set));
1069 if (ioctlsocket (socket1, FIONBIO, &arg) == SOCKET_ERROR)
1071 DBUS_SOCKET_SET_ERRNO ();
1076 if (ioctlsocket (socket2, FIONBIO, &arg) == SOCKET_ERROR)
1078 DBUS_SOCKET_SET_ERRNO ();
1085 if (ioctlsocket (socket2, FIONBIO, &arg) == SOCKET_ERROR)
1087 DBUS_SOCKET_SET_ERRNO ();
1095 _dbus_verbose ("full-duplex pipe %d:%d <-> %d:%d\n",
1096 *fd1, socket1, *fd2, socket2);
1103 closesocket (socket2);
1105 closesocket (socket1);
1109 dbus_set_error (error, _dbus_error_from_errno (errno),
1110 "Could not setup socket pair: %s",
1111 _dbus_strerror (errno));
1117 * Wrapper for poll().
1119 * @param fds the file descriptors to poll
1120 * @param n_fds number of descriptors in the array
1121 * @param timeout_milliseconds timeout or -1 for infinite
1122 * @returns numbers of fds with revents, or <0 on error
1124 #define USE_CHRIS_IMPL 0
1127 _dbus_poll (DBusPollFD *fds,
1129 int timeout_milliseconds)
1131 #define DBUS_POLL_CHAR_BUFFER_SIZE 2000
1132 char msg[DBUS_POLL_CHAR_BUFFER_SIZE];
1140 #define DBUS_STACK_WSAEVENTS 256
1141 WSAEVENT eventsOnStack[DBUS_STACK_WSAEVENTS];
1142 WSAEVENT *pEvents = NULL;
1143 if (n_fds > DBUS_STACK_WSAEVENTS)
1144 pEvents = calloc(sizeof(WSAEVENT), n_fds);
1146 pEvents = eventsOnStack;
1149 #ifdef DBUS_ENABLE_VERBOSE_MODE
1151 msgp += sprintf (msgp, "WSAEventSelect: to=%d\n\t", timeout_milliseconds);
1152 for (i = 0; i < n_fds; i++)
1154 static dbus_bool_t warned = FALSE;
1155 DBusPollFD *fdp = &fds[i];
1158 if (fdp->events & _DBUS_POLLIN)
1159 msgp += sprintf (msgp, "R:%d ", fdp->fd);
1161 if (fdp->events & _DBUS_POLLOUT)
1162 msgp += sprintf (msgp, "W:%d ", fdp->fd);
1164 msgp += sprintf (msgp, "E:%d\n\t", fdp->fd);
1166 // FIXME: more robust code for long msg
1167 // create on heap when msg[] becomes too small
1168 if (msgp >= msg + DBUS_POLL_CHAR_BUFFER_SIZE)
1170 _dbus_assert_not_reached ("buffer overflow in _dbus_poll");
1174 msgp += sprintf (msgp, "\n");
1175 _dbus_verbose ("%s",msg);
1177 for (i = 0; i < n_fds; i++)
1179 DBusPollFD *fdp = &fds[i];
1181 long lNetworkEvents = FD_OOB;
1183 ev = WSACreateEvent();
1185 if (fdp->events & _DBUS_POLLIN)
1186 lNetworkEvents |= FD_READ | FD_ACCEPT | FD_CLOSE;
1188 if (fdp->events & _DBUS_POLLOUT)
1189 lNetworkEvents |= FD_WRITE | FD_CONNECT;
1191 WSAEventSelect(fdp->fd, ev, lNetworkEvents);
1197 ready = WSAWaitForMultipleEvents (n_fds, pEvents, FALSE, timeout_milliseconds, FALSE);
1199 if (DBUS_SOCKET_API_RETURNS_ERROR (ready))
1201 DBUS_SOCKET_SET_ERRNO ();
1202 if (errno != EWOULDBLOCK)
1203 _dbus_verbose ("WSAWaitForMultipleEvents: failed: %s\n", _dbus_strerror (errno));
1206 else if (ready == WSA_WAIT_TIMEOUT)
1208 _dbus_verbose ("WSAWaitForMultipleEvents: WSA_WAIT_TIMEOUT\n");
1211 else if (ready >= WSA_WAIT_EVENT_0 && ready < (int)(WSA_WAIT_EVENT_0 + n_fds))
1214 msgp += sprintf (msgp, "WSAWaitForMultipleEvents: =%d\n\t", ready);
1216 for (i = 0; i < n_fds; i++)
1218 DBusPollFD *fdp = &fds[i];
1219 WSANETWORKEVENTS ne;
1223 WSAEnumNetworkEvents(fdp->fd, pEvents[i], &ne);
1225 if (ne.lNetworkEvents & (FD_READ | FD_ACCEPT | FD_CLOSE))
1226 fdp->revents |= _DBUS_POLLIN;
1228 if (ne.lNetworkEvents & (FD_WRITE | FD_CONNECT))
1229 fdp->revents |= _DBUS_POLLOUT;
1231 if (ne.lNetworkEvents & (FD_OOB))
1232 fdp->revents |= _DBUS_POLLERR;
1234 if (ne.lNetworkEvents & (FD_READ | FD_ACCEPT | FD_CLOSE))
1235 msgp += sprintf (msgp, "R:%d ", fdp->fd);
1237 if (ne.lNetworkEvents & (FD_WRITE | FD_CONNECT))
1238 msgp += sprintf (msgp, "W:%d ", fdp->fd);
1240 if (ne.lNetworkEvents & (FD_OOB))
1241 msgp += sprintf (msgp, "E:%d ", fdp->fd);
1243 msgp += sprintf (msgp, "lNetworkEvents:%d ", ne.lNetworkEvents);
1245 if(ne.lNetworkEvents)
1248 WSAEventSelect(fdp->fd, pEvents[i], 0);
1251 msgp += sprintf (msgp, "\n");
1252 _dbus_verbose ("%s",msg);
1256 _dbus_verbose ("WSAWaitForMultipleEvents: failed for unknown reason!");
1260 for(i = 0; i < n_fds; i++)
1262 WSACloseEvent(pEvents[i]);
1265 if (n_fds > DBUS_STACK_WSAEVENTS)
1271 #else // USE_CHRIS_IMPL
1274 _dbus_poll (DBusPollFD *fds,
1276 int timeout_milliseconds)
1278 #define DBUS_POLL_CHAR_BUFFER_SIZE 2000
1279 char msg[DBUS_POLL_CHAR_BUFFER_SIZE];
1282 fd_set read_set, write_set, err_set;
1288 FD_ZERO (&read_set);
1289 FD_ZERO (&write_set);
1293 #ifdef DBUS_ENABLE_VERBOSE_MODE
1295 msgp += sprintf (msgp, "select: to=%d\n\t", timeout_milliseconds);
1296 for (i = 0; i < n_fds; i++)
1298 static dbus_bool_t warned = FALSE;
1299 DBusPollFD *fdp = &fds[i];
1302 if (fdp->events & _DBUS_POLLIN)
1303 msgp += sprintf (msgp, "R:%d ", fdp->fd);
1305 if (fdp->events & _DBUS_POLLOUT)
1306 msgp += sprintf (msgp, "W:%d ", fdp->fd);
1308 msgp += sprintf (msgp, "E:%d\n\t", fdp->fd);
1310 // FIXME: more robust code for long msg
1311 // create on heap when msg[] becomes too small
1312 if (msgp >= msg + DBUS_POLL_CHAR_BUFFER_SIZE)
1314 _dbus_assert_not_reached ("buffer overflow in _dbus_poll");
1318 msgp += sprintf (msgp, "\n");
1319 _dbus_verbose ("%s",msg);
1321 for (i = 0; i < n_fds; i++)
1323 DBusPollFD *fdp = &fds[i];
1325 if (fdp->events & _DBUS_POLLIN)
1326 FD_SET (fdp->fd, &read_set);
1328 if (fdp->events & _DBUS_POLLOUT)
1329 FD_SET (fdp->fd, &write_set);
1331 FD_SET (fdp->fd, &err_set);
1333 max_fd = MAX (max_fd, fdp->fd);
1337 tv.tv_sec = timeout_milliseconds / 1000;
1338 tv.tv_usec = (timeout_milliseconds % 1000) * 1000;
1340 ready = select (max_fd + 1, &read_set, &write_set, &err_set,
1341 timeout_milliseconds < 0 ? NULL : &tv);
1343 if (DBUS_SOCKET_API_RETURNS_ERROR (ready))
1345 DBUS_SOCKET_SET_ERRNO ();
1346 if (errno != EWOULDBLOCK)
1347 _dbus_verbose ("select: failed: %s\n", _dbus_strerror (errno));
1349 else if (ready == 0)
1350 _dbus_verbose ("select: = 0\n");
1354 #ifdef DBUS_ENABLE_VERBOSE_MODE
1356 msgp += sprintf (msgp, "select: = %d:\n\t", ready);
1358 for (i = 0; i < n_fds; i++)
1360 DBusPollFD *fdp = &fds[i];
1362 if (FD_ISSET (fdp->fd, &read_set))
1363 msgp += sprintf (msgp, "R:%d ", fdp->fd);
1365 if (FD_ISSET (fdp->fd, &write_set))
1366 msgp += sprintf (msgp, "W:%d ", fdp->fd);
1368 if (FD_ISSET (fdp->fd, &err_set))
1369 msgp += sprintf (msgp, "E:%d\n\t", fdp->fd);
1371 msgp += sprintf (msgp, "\n");
1372 _dbus_verbose ("%s",msg);
1375 for (i = 0; i < n_fds; i++)
1377 DBusPollFD *fdp = &fds[i];
1381 if (FD_ISSET (fdp->fd, &read_set))
1382 fdp->revents |= _DBUS_POLLIN;
1384 if (FD_ISSET (fdp->fd, &write_set))
1385 fdp->revents |= _DBUS_POLLOUT;
1387 if (FD_ISSET (fdp->fd, &err_set))
1388 fdp->revents |= _DBUS_POLLERR;
1394 #endif // USE_CHRIS_IMPL
1399 /******************************************************************************
1401 Original CVS version of dbus-sysdeps.c
1403 ******************************************************************************/
1404 /* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
1405 /* dbus-sysdeps.c Wrappers around system/libc features (internal to D-Bus implementation)
1407 * Copyright (C) 2002, 2003 Red Hat, Inc.
1408 * Copyright (C) 2003 CodeFactory AB
1409 * Copyright (C) 2005 Novell, Inc.
1411 * Licensed under the Academic Free License version 2.1
1413 * This program is free software; you can redistribute it and/or modify
1414 * it under the terms of the GNU General Public License as published by
1415 * the Free Software Foundation; either version 2 of the License, or
1416 * (at your option) any later version.
1418 * This program is distributed in the hope that it will be useful,
1419 * but WITHOUT ANY WARRANTY; without even the implied warranty of
1420 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1421 * GNU General Public License for more details.
1423 * You should have received a copy of the GNU General Public License
1424 * along with this program; if not, write to the Free Software
1425 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
1431 * @addtogroup DBusInternalsUtils
1435 int _dbus_mkdir (const char *path,
1438 return _mkdir(path);
1442 * Exit the process, returning the given value.
1444 * @param code the exit code
1447 _dbus_exit (int code)
1453 * Creates a socket and connects to a socket at the given host
1454 * and port. The connection fd is returned, and is set up as
1457 * @param host the host name to connect to, NULL for loopback
1458 * @param port the prot to connect to
1459 * @param error return location for error code
1460 * @returns connection file descriptor or -1 on error
1463 _dbus_connect_tcp_socket (const char *host,
1468 struct sockaddr_in addr;
1470 struct in_addr *haddr;
1473 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
1475 _dbus_win_startup_winsock ();
1477 fd = socket (AF_INET, SOCK_STREAM, 0);
1479 if (DBUS_SOCKET_IS_INVALID (fd))
1481 DBUS_SOCKET_SET_ERRNO ();
1482 dbus_set_error (error,
1483 _dbus_error_from_errno (errno),
1484 "Failed to create socket: %s",
1485 _dbus_strerror (errno));
1493 ina.s_addr = htonl (INADDR_LOOPBACK);
1497 he = gethostbyname (host);
1500 DBUS_SOCKET_SET_ERRNO ();
1501 dbus_set_error (error,
1502 _dbus_error_from_errno (errno),
1503 "Failed to lookup hostname: %s",
1505 DBUS_CLOSE_SOCKET (fd);
1509 haddr = ((struct in_addr *) (he->h_addr_list)[0]);
1512 memcpy (&addr.sin_addr, haddr, sizeof(struct in_addr));
1513 addr.sin_family = AF_INET;
1514 addr.sin_port = htons (port);
1516 if (DBUS_SOCKET_API_RETURNS_ERROR
1517 (connect (fd, (struct sockaddr*) &addr, sizeof (addr)) < 0))
1519 DBUS_SOCKET_SET_ERRNO ();
1520 dbus_set_error (error,
1521 _dbus_error_from_errno (errno),
1522 "Failed to connect to socket %s:%d %s",
1523 host, port, _dbus_strerror (errno));
1525 DBUS_CLOSE_SOCKET (fd);
1531 if (!_dbus_set_fd_nonblocking (fd, error))
1533 _dbus_close_socket (fd, NULL);
1543 _dbus_daemon_init(const char *host, dbus_uint32_t port);
1545 * Creates a socket and binds it to the given port,
1546 * then listens on the socket. The socket is
1547 * set to be nonblocking.
1548 * In case of port=0 a random free port is used and
1549 * returned in the port parameter.
1551 * @param host the interface to listen on, NULL for loopback, empty for any
1552 * @param port the port to listen on, if zero a free port will be used
1553 * @param error return location for errors
1554 * @returns the listening file descriptor or -1 on error
1558 _dbus_listen_tcp_socket (const char *host,
1559 dbus_uint32_t *port,
1560 dbus_bool_t inaddr_any,
1564 struct sockaddr_in addr;
1566 struct in_addr *haddr;
1567 socklen_t len = (socklen_t) sizeof (struct sockaddr);
1571 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
1573 _dbus_win_startup_winsock ();
1575 fd = socket (AF_INET, SOCK_STREAM, 0);
1577 if (DBUS_SOCKET_IS_INVALID (fd))
1579 DBUS_SOCKET_SET_ERRNO ();
1580 dbus_set_error (error, _dbus_error_from_errno (errno),
1581 "Failed to create socket \"%s:%d\": %s",
1582 host, port, _dbus_strerror (errno));
1588 ina.s_addr = htonl (INADDR_LOOPBACK);
1593 ina.s_addr = htonl (INADDR_ANY);
1598 he = gethostbyname (host);
1601 DBUS_SOCKET_SET_ERRNO ();
1602 dbus_set_error (error,
1603 _dbus_error_from_errno (errno),
1604 "Failed to lookup hostname: %s",
1606 DBUS_CLOSE_SOCKET (fd);
1610 haddr = ((struct in_addr *) (he->h_addr_list)[0]);
1614 memcpy (&addr.sin_addr, haddr, sizeof (struct in_addr));
1615 addr.sin_family = AF_INET;
1616 addr.sin_port = htons (*port);
1618 if (bind (fd, (struct sockaddr*) &addr, sizeof (struct sockaddr)))
1620 DBUS_SOCKET_SET_ERRNO ();
1621 dbus_set_error (error, _dbus_error_from_errno (errno),
1622 "Failed to bind socket \"%s:%d\": %s",
1623 host, *port, _dbus_strerror (errno));
1624 DBUS_CLOSE_SOCKET (fd);
1628 if (DBUS_SOCKET_API_RETURNS_ERROR (listen (fd, 30 /* backlog */)))
1630 DBUS_SOCKET_SET_ERRNO ();
1631 dbus_set_error (error, _dbus_error_from_errno (errno),
1632 "Failed to listen on socket \"%s:%d\": %s",
1633 host, *port, _dbus_strerror (errno));
1634 DBUS_CLOSE_SOCKET (fd);
1638 getsockname(fd, (struct sockaddr*) &addr, &len);
1639 *port = (dbus_uint32_t) ntohs(addr.sin_port);
1641 _dbus_daemon_init(host, ntohs(addr.sin_port));
1643 if (!_dbus_set_fd_nonblocking (fd, error))
1645 _dbus_close_socket (fd, NULL);
1654 * Accepts a connection on a listening socket.
1655 * Handles EINTR for you.
1657 * @param listen_fd the listen file descriptor
1658 * @returns the connection fd of the client, or -1 on error
1661 _dbus_accept (int listen_fd)
1664 struct sockaddr addr;
1667 addrlen = sizeof (addr);
1670 client_fd = accept (listen_fd, &addr, &addrlen);
1672 if (DBUS_SOCKET_IS_INVALID (client_fd))
1674 DBUS_SOCKET_SET_ERRNO ();
1679 _dbus_verbose ("client fd %d accepted\n", client_fd);
1688 _dbus_send_credentials_socket (int handle,
1691 /* FIXME: for the session bus credentials shouldn't matter (?), but
1692 * for the system bus they are presumably essential. A rough outline
1693 * of a way to implement the credential transfer would be this:
1695 * client waits to *read* a byte.
1697 * server creates a named pipe with a random name, sends a byte
1698 * contining its length, and its name.
1700 * client reads the name, connects to it (using Win32 API).
1702 * server waits for connection to the named pipe, then calls
1703 * ImpersonateNamedPipeClient(), notes its now-current credentials,
1704 * calls RevertToSelf(), closes its handles to the named pipe, and
1705 * is done. (Maybe there is some other way to get the SID of a named
1706 * pipe client without having to use impersonation?)
1708 * client closes its handles and is done.
1710 * Ralf: Why not sending credentials over the given this connection ?
1711 * Using named pipes makes it impossible to be connected from a unix client.
1717 _dbus_string_init_const_len (&buf, "\0", 1);
1719 bytes_written = _dbus_write_socket (handle, &buf, 0, 1 );
1721 if (bytes_written < 0 && errno == EINTR)
1724 if (bytes_written < 0)
1726 dbus_set_error (error, _dbus_error_from_errno (errno),
1727 "Failed to write credentials byte: %s",
1728 _dbus_strerror (errno));
1731 else if (bytes_written == 0)
1733 dbus_set_error (error, DBUS_ERROR_IO_ERROR,
1734 "wrote zero bytes writing credentials byte");
1739 _dbus_assert (bytes_written == 1);
1740 _dbus_verbose ("wrote 1 zero byte, credential sending isn't implemented yet\n");
1747 * Reads a single byte which must be nul (an error occurs otherwise),
1748 * and reads unix credentials if available. Fills in pid/uid/gid with
1749 * -1 if no credentials are available. Return value indicates whether
1750 * a byte was read, not whether we got valid credentials. On some
1751 * systems, such as Linux, reading/writing the byte isn't actually
1752 * required, but we do it anyway just to avoid multiple codepaths.
1754 * Fails if no byte is available, so you must select() first.
1756 * The point of the byte is that on some systems we have to
1757 * use sendmsg()/recvmsg() to transmit credentials.
1759 * @param client_fd the client file descriptor
1760 * @param credentials struct to fill with credentials of client
1761 * @param error location to store error code
1762 * @returns #TRUE on success
1765 _dbus_read_credentials_socket (int handle,
1766 DBusCredentials *credentials,
1772 // could fail due too OOM
1773 if (_dbus_string_init(&buf))
1775 bytes_read = _dbus_read_socket(handle, &buf, 1 );
1778 _dbus_verbose("got one zero byte from server");
1780 _dbus_string_free(&buf);
1783 _dbus_credentials_add_from_current_process (credentials);
1784 _dbus_verbose("FIXME: get faked credentials from current process");
1790 * Checks to make sure the given directory is
1791 * private to the user
1793 * @param dir the name of the directory
1794 * @param error error return
1795 * @returns #FALSE on failure
1798 _dbus_check_dir_is_private_to_user (DBusString *dir, DBusError *error)
1800 const char *directory;
1803 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
1810 * Appends the given filename to the given directory.
1812 * @todo it might be cute to collapse multiple '/' such as "foo//"
1815 * @param dir the directory name
1816 * @param next_component the filename
1817 * @returns #TRUE on success
1820 _dbus_concat_dir_and_file (DBusString *dir,
1821 const DBusString *next_component)
1823 dbus_bool_t dir_ends_in_slash;
1824 dbus_bool_t file_starts_with_slash;
1826 if (_dbus_string_get_length (dir) == 0 ||
1827 _dbus_string_get_length (next_component) == 0)
1831 ('/' == _dbus_string_get_byte (dir, _dbus_string_get_length (dir) - 1) ||
1832 '\\' == _dbus_string_get_byte (dir, _dbus_string_get_length (dir) - 1));
1834 file_starts_with_slash =
1835 ('/' == _dbus_string_get_byte (next_component, 0) ||
1836 '\\' == _dbus_string_get_byte (next_component, 0));
1838 if (dir_ends_in_slash && file_starts_with_slash)
1840 _dbus_string_shorten (dir, 1);
1842 else if (!(dir_ends_in_slash || file_starts_with_slash))
1844 if (!_dbus_string_append_byte (dir, '\\'))
1848 return _dbus_string_copy (next_component, 0, dir,
1849 _dbus_string_get_length (dir));
1852 /*---------------- DBusCredentials ----------------------------------
1855 * Adds the credentials corresponding to the given username.
1857 * @param credentials credentials to fill in
1858 * @param username the username
1859 * @returns #TRUE if the username existed and we got some credentials
1862 _dbus_credentials_add_from_user (DBusCredentials *credentials,
1863 const DBusString *username)
1865 return _dbus_credentials_add_windows_sid (credentials,
1866 _dbus_string_get_const_data(username));
1870 * Adds the credentials of the current process to the
1871 * passed-in credentials object.
1873 * @param credentials credentials to add to
1874 * @returns #FALSE if no memory; does not properly roll back on failure, so only some credentials may have been added
1878 _dbus_credentials_add_from_current_process (DBusCredentials *credentials)
1880 dbus_bool_t retval = FALSE;
1883 if (!_dbus_getsid(&sid))
1886 if (!_dbus_credentials_add_unix_pid(credentials, _dbus_getpid()))
1889 if (!_dbus_credentials_add_windows_sid (credentials,sid))
1904 * Append to the string the identity we would like to have when we
1905 * authenticate, on UNIX this is the current process UID and on
1906 * Windows something else, probably a Windows SID string. No escaping
1907 * is required, that is done in dbus-auth.c. The username here
1908 * need not be anything human-readable, it can be the machine-readable
1909 * form i.e. a user id.
1911 * @param str the string to append to
1912 * @returns #FALSE on no memory
1913 * @todo to which class belongs this
1916 _dbus_append_user_from_current_process (DBusString *str)
1918 dbus_bool_t retval = FALSE;
1921 if (!_dbus_getsid(&sid))
1924 retval = _dbus_string_append (str,sid);
1931 * Gets our process ID
1932 * @returns process ID
1937 return GetCurrentProcessId ();
1940 /** nanoseconds in a second */
1941 #define NANOSECONDS_PER_SECOND 1000000000
1942 /** microseconds in a second */
1943 #define MICROSECONDS_PER_SECOND 1000000
1944 /** milliseconds in a second */
1945 #define MILLISECONDS_PER_SECOND 1000
1946 /** nanoseconds in a millisecond */
1947 #define NANOSECONDS_PER_MILLISECOND 1000000
1948 /** microseconds in a millisecond */
1949 #define MICROSECONDS_PER_MILLISECOND 1000
1952 * Sleeps the given number of milliseconds.
1953 * @param milliseconds number of milliseconds
1956 _dbus_sleep_milliseconds (int milliseconds)
1958 Sleep (milliseconds);
1963 * Get current time, as in gettimeofday().
1965 * @param tv_sec return location for number of seconds
1966 * @param tv_usec return location for number of microseconds
1969 _dbus_get_current_time (long *tv_sec,
1973 dbus_uint64_t *time64 = (dbus_uint64_t *) &ft;
1975 GetSystemTimeAsFileTime (&ft);
1977 /* Convert from 100s of nanoseconds since 1601-01-01
1978 * to Unix epoch. Yes, this is Y2038 unsafe.
1980 *time64 -= DBUS_INT64_CONSTANT (116444736000000000);
1984 *tv_sec = *time64 / 1000000;
1987 *tv_usec = *time64 % 1000000;
1992 * signal (SIGPIPE, SIG_IGN);
1995 _dbus_disable_sigpipe (void)
1997 _dbus_verbose("FIXME: implement _dbus_disable_sigpipe (void)\n");
2002 * Appends the contents of the given file to the string,
2003 * returning error code. At the moment, won't open a file
2004 * more than a megabyte in size.
2006 * @param str the string to append to
2007 * @param filename filename to load
2008 * @param error place to set an error
2009 * @returns #FALSE if error was set
2012 _dbus_file_get_contents (DBusString *str,
2013 const DBusString *filename,
2020 const char *filename_c;
2022 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
2024 filename_c = _dbus_string_get_const_data (filename);
2026 /* O_BINARY useful on Cygwin and Win32 */
2027 if (!_dbus_file_open (&file, filename_c, O_RDONLY | O_BINARY, -1))
2029 dbus_set_error (error, _dbus_error_from_errno (errno),
2030 "Failed to open \"%s\": %s",
2032 _dbus_strerror (errno));
2036 if (!_dbus_fstat (&file, &sb))
2038 dbus_set_error (error, _dbus_error_from_errno (errno),
2039 "Failed to stat \"%s\": %s",
2041 _dbus_strerror (errno));
2043 _dbus_verbose ("fstat() failed: %s",
2044 _dbus_strerror (errno));
2046 _dbus_file_close (&file, NULL);
2051 if (sb.st_size > _DBUS_ONE_MEGABYTE)
2053 dbus_set_error (error, DBUS_ERROR_FAILED,
2054 "File size %lu of \"%s\" is too large.",
2055 (unsigned long) sb.st_size, filename_c);
2056 _dbus_file_close (&file, NULL);
2061 orig_len = _dbus_string_get_length (str);
2062 if (sb.st_size > 0 && S_ISREG (sb.st_mode))
2066 while (total < (int) sb.st_size)
2068 bytes_read = _dbus_file_read (&file, str,
2069 sb.st_size - total);
2070 if (bytes_read <= 0)
2072 dbus_set_error (error, _dbus_error_from_errno (errno),
2073 "Error reading \"%s\": %s",
2075 _dbus_strerror (errno));
2077 _dbus_verbose ("read() failed: %s",
2078 _dbus_strerror (errno));
2080 _dbus_file_close (&file, NULL);
2081 _dbus_string_set_length (str, orig_len);
2085 total += bytes_read;
2088 _dbus_file_close (&file, NULL);
2091 else if (sb.st_size != 0)
2093 _dbus_verbose ("Can only open regular files at the moment.\n");
2094 dbus_set_error (error, DBUS_ERROR_FAILED,
2095 "\"%s\" is not a regular file",
2097 _dbus_file_close (&file, NULL);
2102 _dbus_file_close (&file, NULL);
2108 * Writes a string out to a file. If the file exists,
2109 * it will be atomically overwritten by the new data.
2111 * @param str the string to write out
2112 * @param filename the file to save string to
2113 * @param error error to be filled in on failure
2114 * @returns #FALSE on failure
2117 _dbus_string_save_to_file (const DBusString *str,
2118 const DBusString *filename,
2123 const char *filename_c;
2124 DBusString tmp_filename;
2125 const char *tmp_filename_c;
2127 dbus_bool_t need_unlink;
2130 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
2133 need_unlink = FALSE;
2135 if (!_dbus_string_init (&tmp_filename))
2137 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
2141 if (!_dbus_string_copy (filename, 0, &tmp_filename, 0))
2143 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
2144 _dbus_string_free (&tmp_filename);
2148 if (!_dbus_string_append (&tmp_filename, "."))
2150 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
2151 _dbus_string_free (&tmp_filename);
2155 #define N_TMP_FILENAME_RANDOM_BYTES 8
2156 if (!_dbus_generate_random_ascii (&tmp_filename, N_TMP_FILENAME_RANDOM_BYTES))
2158 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
2159 _dbus_string_free (&tmp_filename);
2163 filename_c = _dbus_string_get_const_data (filename);
2164 tmp_filename_c = _dbus_string_get_const_data (&tmp_filename);
2166 if (!_dbus_file_open (&file, tmp_filename_c, O_WRONLY | O_BINARY | O_EXCL | O_CREAT,
2169 dbus_set_error (error, _dbus_error_from_errno (errno),
2170 "Could not create %s: %s", tmp_filename_c,
2171 _dbus_strerror (errno));
2178 bytes_to_write = _dbus_string_get_length (str);
2180 while (total < bytes_to_write)
2184 bytes_written = _dbus_file_write (&file, str, total,
2185 bytes_to_write - total);
2187 if (bytes_written <= 0)
2189 dbus_set_error (error, _dbus_error_from_errno (errno),
2190 "Could not write to %s: %s", tmp_filename_c,
2191 _dbus_strerror (errno));
2196 total += bytes_written;
2199 if (!_dbus_file_close (&file, NULL))
2201 dbus_set_error (error, _dbus_error_from_errno (errno),
2202 "Could not close file %s: %s",
2203 tmp_filename_c, _dbus_strerror (errno));
2209 if ((unlink (filename_c) == -1 && errno != ENOENT) ||
2210 rename (tmp_filename_c, filename_c) < 0)
2212 dbus_set_error (error, _dbus_error_from_errno (errno),
2213 "Could not rename %s to %s: %s",
2214 tmp_filename_c, filename_c,
2215 _dbus_strerror (errno));
2220 need_unlink = FALSE;
2225 /* close first, then unlink, to prevent ".nfs34234235" garbage
2229 if (_dbus_is_valid_file(&file))
2230 _dbus_file_close (&file, NULL);
2232 if (need_unlink && unlink (tmp_filename_c) < 0)
2233 _dbus_verbose ("Failed to unlink temp file %s: %s\n",
2234 tmp_filename_c, _dbus_strerror (errno));
2236 _dbus_string_free (&tmp_filename);
2239 _DBUS_ASSERT_ERROR_IS_SET (error);
2245 /** Creates the given file, failing if the file already exists.
2247 * @param filename the filename
2248 * @param error error location
2249 * @returns #TRUE if we created the file and it didn't exist
2252 _dbus_create_file_exclusively (const DBusString *filename,
2256 const char *filename_c;
2258 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
2260 filename_c = _dbus_string_get_const_data (filename);
2262 if (!_dbus_file_open (&file, filename_c, O_WRONLY | O_BINARY | O_EXCL | O_CREAT,
2265 dbus_set_error (error,
2267 "Could not create file %s: %s\n",
2269 _dbus_strerror (errno));
2273 if (!_dbus_file_close (&file, NULL))
2275 dbus_set_error (error,
2277 "Could not close file %s: %s\n",
2279 _dbus_strerror (errno));
2288 * Creates a directory; succeeds if the directory
2289 * is created or already existed.
2291 * @param filename directory filename
2292 * @param error initialized error object
2293 * @returns #TRUE on success
2296 _dbus_create_directory (const DBusString *filename,
2299 const char *filename_c;
2301 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
2303 filename_c = _dbus_string_get_const_data (filename);
2305 if (_dbus_mkdir (filename_c, 0700) < 0)
2307 if (errno == EEXIST)
2310 dbus_set_error (error, DBUS_ERROR_FAILED,
2311 "Failed to create directory %s: %s\n",
2312 filename_c, _dbus_strerror (errno));
2321 pseudorandom_generate_random_bytes_buffer (char *buffer,
2327 /* fall back to pseudorandom */
2328 _dbus_verbose ("Falling back to pseudorandom for %d bytes\n",
2331 _dbus_get_current_time (NULL, &tv_usec);
2341 b = (r / (double) RAND_MAX) * 255.0;
2350 pseudorandom_generate_random_bytes (DBusString *str,
2356 old_len = _dbus_string_get_length (str);
2358 if (!_dbus_string_lengthen (str, n_bytes))
2361 p = _dbus_string_get_data_len (str, old_len, n_bytes);
2363 pseudorandom_generate_random_bytes_buffer (p, n_bytes);
2369 * Gets the temporary files directory by inspecting the environment variables
2370 * TMPDIR, TMP, and TEMP in that order. If none of those are set "/tmp" is returned
2372 * @returns location of temp directory
2375 _dbus_get_tmpdir(void)
2377 static const char* tmpdir = NULL;
2382 tmpdir = getenv("TMP");
2384 tmpdir = getenv("TEMP");
2386 tmpdir = getenv("TMPDIR");
2388 tmpdir = "C:\\Temp";
2391 _dbus_assert(tmpdir != NULL);
2398 * Deletes the given file.
2400 * @param filename the filename
2401 * @param error error location
2403 * @returns #TRUE if unlink() succeeded
2406 _dbus_delete_file (const DBusString *filename,
2409 const char *filename_c;
2411 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
2413 filename_c = _dbus_string_get_const_data (filename);
2415 if (unlink (filename_c) < 0)
2417 dbus_set_error (error, DBUS_ERROR_FAILED,
2418 "Failed to delete file %s: %s\n",
2419 filename_c, _dbus_strerror (errno));
2427 * Generates the given number of random bytes,
2428 * using the best mechanism we can come up with.
2430 * @param str the string
2431 * @param n_bytes the number of random bytes to append to string
2432 * @returns #TRUE on success, #FALSE if no memory
2435 _dbus_generate_random_bytes (DBusString *str,
2438 return pseudorandom_generate_random_bytes (str, n_bytes);
2441 #if !defined (DBUS_DISABLE_ASSERT) || defined(DBUS_BUILD_TESTS)
2453 * Backtrace Generator
2455 * Copyright 2004 Eric Poech
2456 * Copyright 2004 Robert Shearman
2458 * This library is free software; you can redistribute it and/or
2459 * modify it under the terms of the GNU Lesser General Public
2460 * License as published by the Free Software Foundation; either
2461 * version 2.1 of the License, or (at your option) any later version.
2463 * This library is distributed in the hope that it will be useful,
2464 * but WITHOUT ANY WARRANTY; without even the implied warranty of
2465 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
2466 * Lesser General Public License for more details.
2468 * You should have received a copy of the GNU Lesser General Public
2469 * License along with this library; if not, write to the Free Software
2470 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
2474 #include <imagehlp.h>
2477 #define DPRINTF _dbus_warn
2485 //#define MAKE_FUNCPTR(f) static typeof(f) * p##f
2487 //MAKE_FUNCPTR(StackWalk);
2488 //MAKE_FUNCPTR(SymGetModuleBase);
2489 //MAKE_FUNCPTR(SymFunctionTableAccess);
2490 //MAKE_FUNCPTR(SymInitialize);
2491 //MAKE_FUNCPTR(SymGetSymFromAddr);
2492 //MAKE_FUNCPTR(SymGetModuleInfo);
2493 static BOOL (WINAPI *pStackWalk)(
2497 LPSTACKFRAME StackFrame,
2498 PVOID ContextRecord,
2499 PREAD_PROCESS_MEMORY_ROUTINE ReadMemoryRoutine,
2500 PFUNCTION_TABLE_ACCESS_ROUTINE FunctionTableAccessRoutine,
2501 PGET_MODULE_BASE_ROUTINE GetModuleBaseRoutine,
2502 PTRANSLATE_ADDRESS_ROUTINE TranslateAddress
2504 static DWORD (WINAPI *pSymGetModuleBase)(
2508 static PVOID (WINAPI *pSymFunctionTableAccess)(
2512 static BOOL (WINAPI *pSymInitialize)(
2514 PSTR UserSearchPath,
2517 static BOOL (WINAPI *pSymGetSymFromAddr)(
2520 PDWORD Displacement,
2521 PIMAGEHLP_SYMBOL Symbol
2523 static BOOL (WINAPI *pSymGetModuleInfo)(
2526 PIMAGEHLP_MODULE ModuleInfo
2528 static DWORD (WINAPI *pSymSetOptions)(
2533 static BOOL init_backtrace()
2535 HMODULE hmodDbgHelp = LoadLibraryA("dbghelp");
2537 #define GETFUNC(x) \
2538 p##x = (typeof(x)*)GetProcAddress(hmodDbgHelp, #x); \
2546 // GETFUNC(StackWalk);
2547 // GETFUNC(SymGetModuleBase);
2548 // GETFUNC(SymFunctionTableAccess);
2549 // GETFUNC(SymInitialize);
2550 // GETFUNC(SymGetSymFromAddr);
2551 // GETFUNC(SymGetModuleInfo);
2555 pStackWalk = (BOOL (WINAPI *)(
2559 LPSTACKFRAME StackFrame,
2560 PVOID ContextRecord,
2561 PREAD_PROCESS_MEMORY_ROUTINE ReadMemoryRoutine,
2562 PFUNCTION_TABLE_ACCESS_ROUTINE FunctionTableAccessRoutine,
2563 PGET_MODULE_BASE_ROUTINE GetModuleBaseRoutine,
2564 PTRANSLATE_ADDRESS_ROUTINE TranslateAddress
2565 ))GetProcAddress (hmodDbgHelp, FUNC(StackWalk));
2566 pSymGetModuleBase=(DWORD (WINAPI *)(
2569 ))GetProcAddress (hmodDbgHelp, FUNC(SymGetModuleBase));
2570 pSymFunctionTableAccess=(PVOID (WINAPI *)(
2573 ))GetProcAddress (hmodDbgHelp, FUNC(SymFunctionTableAccess));
2574 pSymInitialize = (BOOL (WINAPI *)(
2576 PSTR UserSearchPath,
2578 ))GetProcAddress (hmodDbgHelp, FUNC(SymInitialize));
2579 pSymGetSymFromAddr = (BOOL (WINAPI *)(
2582 PDWORD Displacement,
2583 PIMAGEHLP_SYMBOL Symbol
2584 ))GetProcAddress (hmodDbgHelp, FUNC(SymGetSymFromAddr));
2585 pSymGetModuleInfo = (BOOL (WINAPI *)(
2588 PIMAGEHLP_MODULE ModuleInfo
2589 ))GetProcAddress (hmodDbgHelp, FUNC(SymGetModuleInfo));
2590 pSymSetOptions = (DWORD (WINAPI *)(
2592 ))GetProcAddress (hmodDbgHelp, FUNC(SymSetOptions));
2595 pSymSetOptions(SYMOPT_UNDNAME);
2597 pSymInitialize(GetCurrentProcess(), NULL, TRUE);
2602 static void dump_backtrace_for_thread(HANDLE hThread)
2609 if (!init_backtrace())
2612 /* can't use this function for current thread as GetThreadContext
2613 * doesn't support getting context from current thread */
2614 if (hThread == GetCurrentThread())
2617 DPRINTF("Backtrace:\n");
2619 memset(&context, 0, sizeof(context));
2620 context.ContextFlags = CONTEXT_FULL;
2622 SuspendThread(hThread);
2624 if (!GetThreadContext(hThread, &context))
2626 DPRINTF("Couldn't get thread context (error %ld)\n", GetLastError());
2627 ResumeThread(hThread);
2631 memset(&sf, 0, sizeof(sf));
2634 sf.AddrFrame.Offset = context.Ebp;
2635 sf.AddrFrame.Mode = AddrModeFlat;
2636 sf.AddrPC.Offset = context.Eip;
2637 sf.AddrPC.Mode = AddrModeFlat;
2638 dwImageType = IMAGE_FILE_MACHINE_I386;
2640 # error You need to fill in the STACKFRAME structure for your architecture
2643 while (pStackWalk(dwImageType, GetCurrentProcess(),
2644 hThread, &sf, &context, NULL, pSymFunctionTableAccess,
2645 pSymGetModuleBase, NULL))
2648 IMAGEHLP_SYMBOL * pSymbol = (IMAGEHLP_SYMBOL *)buffer;
2649 DWORD dwDisplacement;
2651 pSymbol->SizeOfStruct = sizeof(IMAGEHLP_SYMBOL);
2652 pSymbol->MaxNameLength = sizeof(buffer) - sizeof(IMAGEHLP_SYMBOL) + 1;
2654 if (!pSymGetSymFromAddr(GetCurrentProcess(), sf.AddrPC.Offset,
2655 &dwDisplacement, pSymbol))
2657 IMAGEHLP_MODULE ModuleInfo;
2658 ModuleInfo.SizeOfStruct = sizeof(ModuleInfo);
2660 if (!pSymGetModuleInfo(GetCurrentProcess(), sf.AddrPC.Offset,
2662 DPRINTF("1\t%p\n", (void*)sf.AddrPC.Offset);
2664 DPRINTF("2\t%s+0x%lx\n", ModuleInfo.ImageName,
2665 sf.AddrPC.Offset - ModuleInfo.BaseOfImage);
2667 else if (dwDisplacement)
2668 DPRINTF("3\t%s+0x%lx\n", pSymbol->Name, dwDisplacement);
2670 DPRINTF("4\t%s\n", pSymbol->Name);
2673 ResumeThread(hThread);
2676 static DWORD WINAPI dump_thread_proc(LPVOID lpParameter)
2678 dump_backtrace_for_thread((HANDLE)lpParameter);
2682 /* cannot get valid context from current thread, so we have to execute
2683 * backtrace from another thread */
2684 static void dump_backtrace()
2686 HANDLE hCurrentThread;
2689 DuplicateHandle(GetCurrentProcess(), GetCurrentThread(),
2690 GetCurrentProcess(), &hCurrentThread, 0, FALSE, DUPLICATE_SAME_ACCESS);
2691 hThread = CreateThread(NULL, 0, dump_thread_proc, (LPVOID)hCurrentThread,
2693 WaitForSingleObject(hThread, INFINITE);
2694 CloseHandle(hThread);
2695 CloseHandle(hCurrentThread);
2698 void _dbus_print_backtrace(void)
2704 void _dbus_print_backtrace(void)
2706 _dbus_verbose (" D-Bus not compiled with backtrace support\n");
2710 static dbus_uint32_t fromAscii(char ascii)
2712 if(ascii >= '0' && ascii <= '9')
2714 if(ascii >= 'A' && ascii <= 'F')
2715 return ascii - 'A' + 10;
2716 if(ascii >= 'a' && ascii <= 'f')
2717 return ascii - 'a' + 10;
2721 dbus_bool_t _dbus_read_local_machine_uuid (DBusGUID *machine_id,
2722 dbus_bool_t create_if_not_found,
2729 HW_PROFILE_INFOA info;
2730 char *lpc = &info.szHwProfileGuid[0];
2733 // the hw-profile guid lives long enough
2734 if(!GetCurrentHwProfileA(&info))
2736 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL); // FIXME
2740 // Form: {12340001-4980-1920-6788-123456789012}
2743 u = ((fromAscii(lpc[0]) << 0) |
2744 (fromAscii(lpc[1]) << 4) |
2745 (fromAscii(lpc[2]) << 8) |
2746 (fromAscii(lpc[3]) << 12) |
2747 (fromAscii(lpc[4]) << 16) |
2748 (fromAscii(lpc[5]) << 20) |
2749 (fromAscii(lpc[6]) << 24) |
2750 (fromAscii(lpc[7]) << 28));
2751 machine_id->as_uint32s[0] = u;
2755 u = ((fromAscii(lpc[0]) << 0) |
2756 (fromAscii(lpc[1]) << 4) |
2757 (fromAscii(lpc[2]) << 8) |
2758 (fromAscii(lpc[3]) << 12) |
2759 (fromAscii(lpc[5]) << 16) |
2760 (fromAscii(lpc[6]) << 20) |
2761 (fromAscii(lpc[7]) << 24) |
2762 (fromAscii(lpc[8]) << 28));
2763 machine_id->as_uint32s[1] = u;
2767 u = ((fromAscii(lpc[0]) << 0) |
2768 (fromAscii(lpc[1]) << 4) |
2769 (fromAscii(lpc[2]) << 8) |
2770 (fromAscii(lpc[3]) << 12) |
2771 (fromAscii(lpc[5]) << 16) |
2772 (fromAscii(lpc[6]) << 20) |
2773 (fromAscii(lpc[7]) << 24) |
2774 (fromAscii(lpc[8]) << 28));
2775 machine_id->as_uint32s[2] = u;
2779 u = ((fromAscii(lpc[0]) << 0) |
2780 (fromAscii(lpc[1]) << 4) |
2781 (fromAscii(lpc[2]) << 8) |
2782 (fromAscii(lpc[3]) << 12) |
2783 (fromAscii(lpc[4]) << 16) |
2784 (fromAscii(lpc[5]) << 20) |
2785 (fromAscii(lpc[6]) << 24) |
2786 (fromAscii(lpc[7]) << 28));
2787 machine_id->as_uint32s[3] = u;
2793 HANDLE _dbus_global_lock (const char *mutexname)
2798 mutex = CreateMutex( NULL, FALSE, mutexname );
2804 gotMutex = WaitForSingleObject( mutex, INFINITE );
2807 case WAIT_ABANDONED:
2808 ReleaseMutex (mutex);
2809 CloseHandle (mutex);
2820 void _dbus_global_unlock (HANDLE mutex)
2822 ReleaseMutex (mutex);
2823 CloseHandle (mutex);
2826 // for proper cleanup in dbus-daemon
2827 static HANDLE hDBusDaemonMutex = NULL;
2828 static HANDLE hDBusSharedMem = NULL;
2829 // sync _dbus_daemon_init, _dbus_daemon_uninit and _dbus_daemon_already_runs
2830 static const char *cUniqueDBusInitMutex = "UniqueDBusInitMutex";
2831 // sync _dbus_get_autolaunch_address
2832 static const char *cDBusAutolaunchMutex = "DBusAutolaunchMutex";
2833 // mutex to determine if dbus-daemon is already started (per user)
2834 static const char *cDBusDaemonMutex = "DBusDaemonMutex";
2835 // named shm for dbus adress info (per user)
2836 static const char *cDBusDaemonAddressInfo = "DBusDaemonAddressInfo";
2839 _dbus_daemon_init(const char *host, dbus_uint32_t port)
2842 const char *adr = NULL;
2843 char szUserName[64];
2844 DWORD dwUserNameSize = sizeof(szUserName);
2845 char szDBusDaemonMutex[128];
2846 char szDBusDaemonAddressInfo[128];
2847 char szAddress[128];
2852 _snprintf(szAddress, sizeof(szAddress) - 1, "tcp:host=%s,port=%d", host, port);
2854 _dbus_assert( GetUserName(szUserName, &dwUserNameSize) != 0);
2855 _snprintf(szDBusDaemonMutex, sizeof(szDBusDaemonMutex) - 1, "%s:%s",
2856 cDBusDaemonMutex, szUserName);
2857 _snprintf(szDBusDaemonAddressInfo, sizeof(szDBusDaemonAddressInfo) - 1, "%s:%s",
2858 cDBusDaemonAddressInfo, szUserName);
2860 // before _dbus_global_lock to keep correct lock/release order
2861 hDBusDaemonMutex = CreateMutex( NULL, FALSE, szDBusDaemonMutex );
2863 _dbus_assert(WaitForSingleObject( hDBusDaemonMutex, 1000 ) == WAIT_OBJECT_0);
2865 // sync _dbus_daemon_init, _dbus_daemon_uninit and _dbus_daemon_already_runs
2866 lock = _dbus_global_lock( cUniqueDBusInitMutex );
2869 hDBusSharedMem = CreateFileMapping( INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE,
2870 0, strlen( szAddress ) + 1, szDBusDaemonAddressInfo );
2871 _dbus_assert( hDBusSharedMem );
2873 adr = MapViewOfFile( hDBusSharedMem, FILE_MAP_WRITE, 0, 0, 0 );
2875 _dbus_assert( adr );
2877 strcpy( (char*) adr, szAddress);
2880 UnmapViewOfFile( (char*) adr );
2882 _dbus_global_unlock( lock );
2886 _dbus_daemon_release()
2890 // sync _dbus_daemon_init, _dbus_daemon_uninit and _dbus_daemon_already_runs
2891 lock = _dbus_global_lock( cUniqueDBusInitMutex );
2893 CloseHandle( hDBusSharedMem );
2895 hDBusSharedMem = NULL;
2897 ReleaseMutex( hDBusDaemonMutex );
2899 CloseHandle( hDBusDaemonMutex );
2901 hDBusDaemonMutex = NULL;
2903 _dbus_global_unlock( lock );
2907 _dbus_get_autolaunch_shm(DBusString *adress)
2911 char szUserName[64];
2912 DWORD dwUserNameSize = sizeof(szUserName);
2913 char szDBusDaemonAddressInfo[128];
2915 if( !GetUserName(szUserName, &dwUserNameSize) )
2917 _snprintf(szDBusDaemonAddressInfo, sizeof(szDBusDaemonAddressInfo) - 1, "%s:%s",
2918 cDBusDaemonAddressInfo, szUserName);
2922 // we know that dbus-daemon is available, so we wait until shm is available
2923 sharedMem = OpenFileMapping( FILE_MAP_READ, FALSE, szDBusDaemonAddressInfo );
2924 if( sharedMem == 0 )
2926 } while( sharedMem == 0 );
2928 if( sharedMem == 0 )
2931 adr = MapViewOfFile( sharedMem, FILE_MAP_READ, 0, 0, 0 );
2936 _dbus_string_init( adress );
2938 _dbus_string_append( adress, adr );
2941 UnmapViewOfFile( (char*) adr );
2943 CloseHandle( sharedMem );
2949 _dbus_daemon_already_runs (DBusString *adress)
2953 dbus_bool_t bRet = TRUE;
2954 char szUserName[64];
2955 DWORD dwUserNameSize = sizeof(szUserName);
2956 char szDBusDaemonMutex[128];
2958 // sync _dbus_daemon_init, _dbus_daemon_uninit and _dbus_daemon_already_runs
2959 lock = _dbus_global_lock( cUniqueDBusInitMutex );
2961 if( !GetUserName(szUserName, &dwUserNameSize) )
2963 _snprintf(szDBusDaemonMutex, sizeof(szDBusDaemonMutex) - 1, "%s:%s",
2964 cDBusDaemonMutex, szUserName);
2967 daemon = CreateMutex( NULL, FALSE, szDBusDaemonMutex );
2968 if(WaitForSingleObject( daemon, 10 ) != WAIT_TIMEOUT)
2970 ReleaseMutex (daemon);
2971 CloseHandle (daemon);
2973 _dbus_global_unlock( lock );
2978 bRet = _dbus_get_autolaunch_shm( adress );
2981 CloseHandle ( daemon );
2983 _dbus_global_unlock( lock );
2989 _dbus_get_autolaunch_address (DBusString *address,
2994 PROCESS_INFORMATION pi;
2995 dbus_bool_t retval = FALSE;
2997 char dbus_exe_path[MAX_PATH];
2998 char dbus_args[MAX_PATH * 2];
3000 mutex = _dbus_global_lock ( cDBusAutolaunchMutex );
3002 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
3004 if (_dbus_daemon_already_runs(address))
3006 printf("dbus daemon already exists\n");
3011 if (!SearchPathA(NULL, "dbus-daemon.exe", NULL, sizeof(dbus_exe_path), dbus_exe_path, &lpFile))
3013 printf ("could not find dbus-daemon executable\n");
3018 ZeroMemory( &si, sizeof(si) );
3020 ZeroMemory( &pi, sizeof(pi) );
3022 _snprintf(dbus_args, sizeof(dbus_args) - 1, "\"%s\" %s", dbus_exe_path, " --session");
3024 // argv[i] = "--config-file=bus\\session.conf";
3025 printf("create process \"%s\" %s\n", dbus_exe_path, dbus_args);
3026 if(CreateProcessA(dbus_exe_path, dbus_args, NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi))
3030 // Wait until started (see _dbus_get_autolaunch_shm())
3031 WaitForInputIdle(pi.hProcess, INFINITE);
3033 retval = _dbus_get_autolaunch_shm( address );
3040 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
3042 _DBUS_ASSERT_ERROR_IS_SET (error);
3044 _dbus_global_unlock (mutex);
3050 /** Makes the file readable by every user in the system.
3052 * @param filename the filename
3053 * @param error error location
3054 * @returns #TRUE if the file's permissions could be changed.
3057 _dbus_make_file_world_readable(const DBusString *filename,
3065 #define DBUS_STANDARD_SESSION_SERVICEDIR "/dbus-1/services"
3066 #define DBUS_STANDARD_SYSTEM_SERVICEDIR "/dbus-1/system-services"
3069 * Returns the standard directories for a session bus to look for service
3072 * On Windows this should be data directories:
3074 * %CommonProgramFiles%/dbus
3080 * @param dirs the directory list we are returning
3081 * @returns #FALSE on OOM
3085 _dbus_get_standard_session_servicedirs (DBusList **dirs)
3087 const char *common_progs;
3088 DBusString servicedir_path;
3090 if (!_dbus_string_init (&servicedir_path))
3093 if (!_dbus_string_append (&servicedir_path, DBUS_DATADIR _DBUS_PATH_SEPARATOR))
3096 common_progs = _dbus_getenv ("CommonProgramFiles");
3098 if (common_progs != NULL)
3100 if (!_dbus_string_append (&servicedir_path, common_progs))
3103 if (!_dbus_string_append (&servicedir_path, _DBUS_PATH_SEPARATOR))
3107 if (!_dbus_split_paths_and_append (&servicedir_path,
3108 DBUS_STANDARD_SESSION_SERVICEDIR,
3112 _dbus_string_free (&servicedir_path);
3116 _dbus_string_free (&servicedir_path);
3120 _DBUS_DEFINE_GLOBAL_LOCK (atomic);
3123 * Atomically increments an integer
3125 * @param atomic pointer to the integer to increment
3126 * @returns the value before incrementing
3130 _dbus_atomic_inc (DBusAtomic *atomic)
3132 // +/- 1 is needed here!
3133 // no volatile argument with mingw
3134 return InterlockedIncrement (&atomic->value) - 1;
3138 * Atomically decrement an integer
3140 * @param atomic pointer to the integer to decrement
3141 * @returns the value before decrementing
3145 _dbus_atomic_dec (DBusAtomic *atomic)
3147 // +/- 1 is needed here!
3148 // no volatile argument with mingw
3149 return InterlockedDecrement (&atomic->value) + 1;
3152 #endif /* asserts or tests enabled */
3155 * Called when the bus daemon is signaled to reload its configuration; any
3156 * caches should be nuked. Of course any caches that need explicit reload
3157 * are probably broken, but c'est la vie.
3162 _dbus_flush_caches (void)
3167 dbus_bool_t _dbus_windows_user_is_process_owner (const char *windows_sid)
3173 * See if errno is EAGAIN or EWOULDBLOCK (this has to be done differently
3174 * for Winsock so is abstracted)
3176 * @returns #TRUE if errno == EAGAIN or errno == EWOULDBLOCK
3179 _dbus_get_is_errno_eagain_or_ewouldblock (void)
3181 return errno == EAGAIN || errno == EWOULDBLOCK;
3185 * return the absolute path of the dbus installation
3187 * @param s buffer for installation path
3188 * @param len length of buffer
3189 * @returns #FALSE on failure
3192 _dbus_get_install_root(char *s, int len)
3195 int ret = GetModuleFileName(NULL,s,len);
3197 || ret == len && GetLastError() == ERROR_INSUFFICIENT_BUFFER)
3202 else if ((p = strstr(s,"\\bin\\")))
3215 find config file either from installation or build root according to
3216 the following path layout
3218 bin/dbus-daemon[d].exe
3219 etc/<config-file>.conf
3222 bin/dbus-daemon[d].exe
3223 bus/<config-file>.conf
3226 _dbus_get_config_file_name(DBusString *config_file, char *s)
3228 char path[MAX_PATH*2];
3229 int path_size = sizeof(path);
3231 if (!_dbus_get_install_root(path,path_size))
3234 strcat_s(path,path_size,"etc\\");
3235 strcat_s(path,path_size,s);
3236 if (_dbus_file_exists(path))
3238 // find path from executable
3239 if (!_dbus_string_append (config_file, path))
3244 if (!_dbus_get_install_root(path,path_size))
3246 strcat_s(path,path_size,"bus\\");
3247 strcat_s(path,path_size,s);
3249 if (_dbus_file_exists(path))
3251 if (!_dbus_string_append (config_file, path))
3259 * Append the absolute path of the system.conf file
3260 * (there is no system bus on Windows so this can just
3261 * return FALSE and print a warning or something)
3263 * @param str the string to append to
3264 * @returns #FALSE if no memory
3267 _dbus_append_system_config_file (DBusString *str)
3269 return _dbus_get_config_file_name(str, "system.conf");
3273 * Append the absolute path of the session.conf file.
3275 * @param str the string to append to
3276 * @returns #FALSE if no memory
3279 _dbus_append_session_config_file (DBusString *str)
3281 return _dbus_get_config_file_name(str, "session.conf");
3284 /* See comment in dbus-sysdeps-unix.c */
3286 _dbus_lookup_session_address (dbus_bool_t *supported,
3287 DBusString *address,
3290 /* Probably fill this in with something based on COM? */
3296 * Appends the directory in which a keyring for the given credentials
3297 * should be stored. The credentials should have either a Windows or
3298 * UNIX user in them. The directory should be an absolute path.
3300 * On UNIX the directory is ~/.dbus-keyrings while on Windows it should probably
3301 * be something else, since the dotfile convention is not normal on Windows.
3303 * @param directory string to append directory to
3304 * @param credentials credentials the directory should be for
3306 * @returns #FALSE on no memory
3309 _dbus_append_keyring_directory_for_credentials (DBusString *directory,
3310 DBusCredentials *credentials)
3315 const char *homepath;
3317 _dbus_assert (credentials != NULL);
3318 _dbus_assert (!_dbus_credentials_are_anonymous (credentials));
3320 if (!_dbus_string_init (&homedir))
3323 homepath = _dbus_getenv("HOMEPATH");
3324 if (homepath != NULL && *homepath != '\0')
3326 _dbus_string_append(&homedir,homepath);
3329 #ifdef DBUS_BUILD_TESTS
3331 const char *override;
3333 override = _dbus_getenv ("DBUS_TEST_HOMEDIR");
3334 if (override != NULL && *override != '\0')
3336 _dbus_string_set_length (&homedir, 0);
3337 if (!_dbus_string_append (&homedir, override))
3340 _dbus_verbose ("Using fake homedir for testing: %s\n",
3341 _dbus_string_get_const_data (&homedir));
3345 static dbus_bool_t already_warned = FALSE;
3346 if (!already_warned)
3348 _dbus_warn ("Using your real home directory for testing, set DBUS_TEST_HOMEDIR to avoid\n");
3349 already_warned = TRUE;
3355 _dbus_string_init_const (&dotdir, ".dbus-keyrings");
3356 if (!_dbus_concat_dir_and_file (&homedir,
3360 if (!_dbus_string_copy (&homedir, 0,
3361 directory, _dbus_string_get_length (directory))) {
3365 _dbus_string_free (&homedir);
3369 _dbus_string_free (&homedir);
3373 /** @} end of sysdeps-win */
3374 /* tests in dbus-sysdeps-util.c */