00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025 #include "dbus-internals.h"
00026 #include "dbus-sysdeps.h"
00027 #include "dbus-threads.h"
00028 #include "dbus-protocol.h"
00029 #include "dbus-test.h"
00030 #include <sys/types.h>
00031 #include <stdlib.h>
00032 #include <string.h>
00033 #include <signal.h>
00034 #include <unistd.h>
00035 #include <stdio.h>
00036 #include <errno.h>
00037 #include <fcntl.h>
00038 #include <sys/socket.h>
00039 #include <dirent.h>
00040 #include <sys/un.h>
00041 #include <pwd.h>
00042 #include <time.h>
00043 #include <locale.h>
00044 #include <sys/time.h>
00045 #include <sys/stat.h>
00046 #include <sys/wait.h>
00047 #include <netinet/in.h>
00048 #include <netdb.h>
00049 #include <grp.h>
00050
00051 #ifdef HAVE_WRITEV
00052 #include <sys/uio.h>
00053 #endif
00054 #ifdef HAVE_POLL
00055 #include <sys/poll.h>
00056 #endif
00057 #ifdef HAVE_BACKTRACE
00058 #include <execinfo.h>
00059 #endif
00060
00061
00062 #ifndef O_BINARY
00063 #define O_BINARY 0
00064 #endif
00065
00066 #ifndef HAVE_SOCKLEN_T
00067 #define socklen_t int
00068 #endif
00069
00077 void
00078 _dbus_abort (void)
00079 {
00080 #ifdef DBUS_ENABLE_VERBOSE_MODE
00081 const char *s;
00082 s = _dbus_getenv ("DBUS_PRINT_BACKTRACE");
00083 if (s && *s)
00084 _dbus_print_backtrace ();
00085 #endif
00086 abort ();
00087 _exit (1);
00088 }
00089
00101 dbus_bool_t
00102 _dbus_setenv (const char *varname,
00103 const char *value)
00104 {
00105 _dbus_assert (varname != NULL);
00106
00107 if (value == NULL)
00108 {
00109 #ifdef HAVE_UNSETENV
00110 unsetenv (varname);
00111 return TRUE;
00112 #else
00113 char *putenv_value;
00114 size_t len;
00115
00116 len = strlen (varname);
00117
00118
00119
00120
00121
00122 putenv_value = malloc (len + 1);
00123 if (putenv_value == NULL)
00124 return FALSE;
00125
00126 strcpy (putenv_value, varname);
00127
00128 return (putenv (putenv_value) == 0);
00129 #endif
00130 }
00131 else
00132 {
00133 #ifdef HAVE_SETENV
00134 return (setenv (varname, value, TRUE) == 0);
00135 #else
00136 char *putenv_value;
00137 size_t len;
00138 size_t varname_len;
00139 size_t value_len;
00140
00141 varname_len = strlen (varname);
00142 value_len = strlen (value);
00143
00144 len = varname_len + value_len + 1 ;
00145
00146
00147
00148
00149
00150 putenv_value = malloc (len + 1);
00151 if (putenv_value == NULL)
00152 return FALSE;
00153
00154 strcpy (putenv_value, varname);
00155 strcpy (putenv_value + varname_len, "=");
00156 strcpy (putenv_value + varname_len + 1, value);
00157
00158 return (putenv (putenv_value) == 0);
00159 #endif
00160 }
00161 }
00162
00169 const char*
00170 _dbus_getenv (const char *varname)
00171 {
00172 return getenv (varname);
00173 }
00174
00188 int
00189 _dbus_read (int fd,
00190 DBusString *buffer,
00191 int count)
00192 {
00193 int bytes_read;
00194 int start;
00195 char *data;
00196
00197 _dbus_assert (count >= 0);
00198
00199 start = _dbus_string_get_length (buffer);
00200
00201 if (!_dbus_string_lengthen (buffer, count))
00202 {
00203 errno = ENOMEM;
00204 return -1;
00205 }
00206
00207 data = _dbus_string_get_data_len (buffer, start, count);
00208
00209 again:
00210
00211 bytes_read = read (fd, data, count);
00212
00213 if (bytes_read < 0)
00214 {
00215 if (errno == EINTR)
00216 goto again;
00217 else
00218 {
00219
00220 _dbus_string_set_length (buffer, start);
00221 return -1;
00222 }
00223 }
00224 else
00225 {
00226
00227 _dbus_string_set_length (buffer, start + bytes_read);
00228
00229 #if 0
00230 if (bytes_read > 0)
00231 _dbus_verbose_bytes_of_string (buffer, start, bytes_read);
00232 #endif
00233
00234 return bytes_read;
00235 }
00236 }
00237
00248 int
00249 _dbus_write (int fd,
00250 const DBusString *buffer,
00251 int start,
00252 int len)
00253 {
00254 const char *data;
00255 int bytes_written;
00256
00257 data = _dbus_string_get_const_data_len (buffer, start, len);
00258
00259 again:
00260
00261 bytes_written = write (fd, data, len);
00262
00263 if (bytes_written < 0 && errno == EINTR)
00264 goto again;
00265
00266 #if 0
00267 if (bytes_written > 0)
00268 _dbus_verbose_bytes_of_string (buffer, start, bytes_written);
00269 #endif
00270
00271 return bytes_written;
00272 }
00273
00294 int
00295 _dbus_write_two (int fd,
00296 const DBusString *buffer1,
00297 int start1,
00298 int len1,
00299 const DBusString *buffer2,
00300 int start2,
00301 int len2)
00302 {
00303 _dbus_assert (buffer1 != NULL);
00304 _dbus_assert (start1 >= 0);
00305 _dbus_assert (start2 >= 0);
00306 _dbus_assert (len1 >= 0);
00307 _dbus_assert (len2 >= 0);
00308
00309 #ifdef HAVE_WRITEV
00310 {
00311 struct iovec vectors[2];
00312 const char *data1;
00313 const char *data2;
00314 int bytes_written;
00315
00316 data1 = _dbus_string_get_const_data_len (buffer1, start1, len1);
00317
00318 if (buffer2 != NULL)
00319 data2 = _dbus_string_get_const_data_len (buffer2, start2, len2);
00320 else
00321 {
00322 data2 = NULL;
00323 start2 = 0;
00324 len2 = 0;
00325 }
00326
00327 vectors[0].iov_base = (char*) data1;
00328 vectors[0].iov_len = len1;
00329 vectors[1].iov_base = (char*) data2;
00330 vectors[1].iov_len = len2;
00331
00332 again:
00333
00334 bytes_written = writev (fd,
00335 vectors,
00336 data2 ? 2 : 1);
00337
00338 if (bytes_written < 0 && errno == EINTR)
00339 goto again;
00340
00341 return bytes_written;
00342 }
00343 #else
00344 {
00345 int ret1;
00346
00347 ret1 = _dbus_write (fd, buffer1, start1, len1);
00348 if (ret1 == len1 && buffer2 != NULL)
00349 {
00350 ret2 = _dbus_write (fd, buffer2, start2, len2);
00351 if (ret2 < 0)
00352 ret2 = 0;
00353
00354 return ret1 + ret2;
00355 }
00356 else
00357 return ret1;
00358 }
00359 #endif
00360 }
00361
00362 #define _DBUS_MAX_SUN_PATH_LENGTH 99
00363
00391 int
00392 _dbus_connect_unix_socket (const char *path,
00393 dbus_bool_t abstract,
00394 DBusError *error)
00395 {
00396 int fd;
00397 struct sockaddr_un addr;
00398
00399 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
00400
00401 _dbus_verbose ("connecting to unix socket %s abstract=%d\n",
00402 path, abstract);
00403
00404 fd = socket (PF_UNIX, SOCK_STREAM, 0);
00405
00406 if (fd < 0)
00407 {
00408 dbus_set_error (error,
00409 _dbus_error_from_errno (errno),
00410 "Failed to create socket: %s",
00411 _dbus_strerror (errno));
00412
00413 return -1;
00414 }
00415
00416 _DBUS_ZERO (addr);
00417 addr.sun_family = AF_UNIX;
00418
00419 if (abstract)
00420 {
00421 #ifdef HAVE_ABSTRACT_SOCKETS
00422
00423
00424
00425 addr.sun_path[0] = '\0';
00426 strncpy (&addr.sun_path[1], path, _DBUS_MAX_SUN_PATH_LENGTH - 2);
00427
00428 #else
00429 dbus_set_error (error, DBUS_ERROR_NOT_SUPPORTED,
00430 "Operating system does not support abstract socket namespace\n");
00431 close (fd);
00432 return -1;
00433 #endif
00434 }
00435 else
00436 {
00437 strncpy (addr.sun_path, path, _DBUS_MAX_SUN_PATH_LENGTH - 1);
00438 }
00439
00440 if (connect (fd, (struct sockaddr*) &addr, sizeof (addr)) < 0)
00441 {
00442 dbus_set_error (error,
00443 _dbus_error_from_errno (errno),
00444 "Failed to connect to socket %s: %s",
00445 path, _dbus_strerror (errno));
00446
00447 close (fd);
00448 fd = -1;
00449
00450 return -1;
00451 }
00452
00453 if (!_dbus_set_fd_nonblocking (fd, error))
00454 {
00455 _DBUS_ASSERT_ERROR_IS_SET (error);
00456
00457 close (fd);
00458 fd = -1;
00459
00460 return -1;
00461 }
00462
00463 return fd;
00464 }
00465
00481 int
00482 _dbus_listen_unix_socket (const char *path,
00483 dbus_bool_t abstract,
00484 DBusError *error)
00485 {
00486 int listen_fd;
00487 struct sockaddr_un addr;
00488
00489 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
00490
00491 _dbus_verbose ("listening on unix socket %s abstract=%d\n",
00492 path, abstract);
00493
00494 listen_fd = socket (PF_UNIX, SOCK_STREAM, 0);
00495
00496 if (listen_fd < 0)
00497 {
00498 dbus_set_error (error, _dbus_error_from_errno (errno),
00499 "Failed to create socket \"%s\": %s",
00500 path, _dbus_strerror (errno));
00501 return -1;
00502 }
00503
00504 _DBUS_ZERO (addr);
00505 addr.sun_family = AF_UNIX;
00506
00507 if (abstract)
00508 {
00509 #ifdef HAVE_ABSTRACT_SOCKETS
00510
00511
00512
00513 addr.sun_path[0] = '\0';
00514 strncpy (&addr.sun_path[1], path, _DBUS_MAX_SUN_PATH_LENGTH - 2);
00515
00516 #else
00517 dbus_set_error (error, DBUS_ERROR_NOT_SUPPORTED,
00518 "Operating system does not support abstract socket namespace\n");
00519 close (listen_fd);
00520 return -1;
00521 #endif
00522 }
00523 else
00524 {
00525
00526
00527
00528
00529
00530
00531
00532
00533
00534
00535 {
00536 struct stat sb;
00537
00538 if (stat (path, &sb) == 0 &&
00539 S_ISSOCK (sb.st_mode))
00540 unlink (path);
00541 }
00542
00543 strncpy (addr.sun_path, path, _DBUS_MAX_SUN_PATH_LENGTH - 1);
00544 }
00545
00546 if (bind (listen_fd, (struct sockaddr*) &addr, sizeof (addr)) < 0)
00547 {
00548 dbus_set_error (error, _dbus_error_from_errno (errno),
00549 "Failed to bind socket \"%s\": %s",
00550 path, _dbus_strerror (errno));
00551 close (listen_fd);
00552 return -1;
00553 }
00554
00555 if (listen (listen_fd, 30 ) < 0)
00556 {
00557 dbus_set_error (error, _dbus_error_from_errno (errno),
00558 "Failed to listen on socket \"%s\": %s",
00559 path, _dbus_strerror (errno));
00560 close (listen_fd);
00561 return -1;
00562 }
00563
00564 if (!_dbus_set_fd_nonblocking (listen_fd, error))
00565 {
00566 _DBUS_ASSERT_ERROR_IS_SET (error);
00567 close (listen_fd);
00568 return -1;
00569 }
00570
00571
00572
00573
00574 if (!abstract && chmod (path, 0777) < 0)
00575 _dbus_warn ("Could not set mode 0777 on socket %s\n",
00576 path);
00577
00578 return listen_fd;
00579 }
00580
00591 int
00592 _dbus_connect_tcp_socket (const char *host,
00593 dbus_uint32_t port,
00594 DBusError *error)
00595 {
00596 int fd;
00597 struct sockaddr_in addr;
00598 struct hostent *he;
00599 struct in_addr *haddr;
00600
00601 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
00602
00603 fd = socket (AF_INET, SOCK_STREAM, 0);
00604
00605 if (fd < 0)
00606 {
00607 dbus_set_error (error,
00608 _dbus_error_from_errno (errno),
00609 "Failed to create socket: %s",
00610 _dbus_strerror (errno));
00611
00612 return -1;
00613 }
00614
00615 if (host == NULL)
00616 host = "localhost";
00617
00618 he = gethostbyname (host);
00619 if (he == NULL)
00620 {
00621 dbus_set_error (error,
00622 _dbus_error_from_errno (errno),
00623 "Failed to lookup hostname: %s",
00624 host);
00625 close (fd);
00626 return -1;
00627 }
00628
00629 haddr = ((struct in_addr *) (he->h_addr_list)[0]);
00630
00631 _DBUS_ZERO (addr);
00632 memcpy (&addr.sin_addr, haddr, sizeof(struct in_addr));
00633 addr.sin_family = AF_INET;
00634 addr.sin_port = htons (port);
00635
00636 if (connect (fd, (struct sockaddr*) &addr, sizeof (addr)) < 0)
00637 {
00638 dbus_set_error (error,
00639 _dbus_error_from_errno (errno),
00640 "Failed to connect to socket %s: %s:%d",
00641 host, _dbus_strerror (errno), port);
00642
00643 close (fd);
00644 fd = -1;
00645
00646 return -1;
00647 }
00648
00649 if (!_dbus_set_fd_nonblocking (fd, error))
00650 {
00651 close (fd);
00652 fd = -1;
00653
00654 return -1;
00655 }
00656
00657 return fd;
00658 }
00659
00670 int
00671 _dbus_listen_tcp_socket (const char *host,
00672 dbus_uint32_t port,
00673 DBusError *error)
00674 {
00675 int listen_fd;
00676 struct sockaddr_in addr;
00677 struct hostent *he;
00678 struct in_addr *haddr;
00679
00680 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
00681
00682 listen_fd = socket (AF_INET, SOCK_STREAM, 0);
00683
00684 if (listen_fd < 0)
00685 {
00686 dbus_set_error (error, _dbus_error_from_errno (errno),
00687 "Failed to create socket \"%s:%d\": %s",
00688 host, port, _dbus_strerror (errno));
00689 return -1;
00690 }
00691
00692 he = gethostbyname (host);
00693 if (he == NULL)
00694 {
00695 dbus_set_error (error,
00696 _dbus_error_from_errno (errno),
00697 "Failed to lookup hostname: %s",
00698 host);
00699 close (listen_fd);
00700 return -1;
00701 }
00702
00703 haddr = ((struct in_addr *) (he->h_addr_list)[0]);
00704
00705 _DBUS_ZERO (addr);
00706 memcpy (&addr.sin_addr, haddr, sizeof (struct in_addr));
00707 addr.sin_family = AF_INET;
00708 addr.sin_port = htons (port);
00709
00710 if (bind (listen_fd, (struct sockaddr*) &addr, sizeof (struct sockaddr)))
00711 {
00712 dbus_set_error (error, _dbus_error_from_errno (errno),
00713 "Failed to bind socket \"%s:%d\": %s",
00714 host, port, _dbus_strerror (errno));
00715 close (listen_fd);
00716 return -1;
00717 }
00718
00719 if (listen (listen_fd, 30 ) < 0)
00720 {
00721 dbus_set_error (error, _dbus_error_from_errno (errno),
00722 "Failed to listen on socket \"%s:%d\": %s",
00723 host, port, _dbus_strerror (errno));
00724 close (listen_fd);
00725 return -1;
00726 }
00727
00728 if (!_dbus_set_fd_nonblocking (listen_fd, error))
00729 {
00730 close (listen_fd);
00731 return -1;
00732 }
00733
00734 return listen_fd;
00735 }
00736
00737 static dbus_bool_t
00738 write_credentials_byte (int server_fd,
00739 DBusError *error)
00740 {
00741 int bytes_written;
00742 char buf[1] = { '\0' };
00743
00744 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
00745
00746 again:
00747
00748 bytes_written = write (server_fd, buf, 1);
00749
00750 if (bytes_written < 0 && errno == EINTR)
00751 goto again;
00752
00753 if (bytes_written < 0)
00754 {
00755 dbus_set_error (error, _dbus_error_from_errno (errno),
00756 "Failed to write credentials byte: %s",
00757 _dbus_strerror (errno));
00758 return FALSE;
00759 }
00760 else if (bytes_written == 0)
00761 {
00762 dbus_set_error (error, DBUS_ERROR_IO_ERROR,
00763 "wrote zero bytes writing credentials byte");
00764 return FALSE;
00765 }
00766 else
00767 {
00768 _dbus_assert (bytes_written == 1);
00769 _dbus_verbose ("wrote credentials byte\n");
00770 return TRUE;
00771 }
00772 }
00773
00792 dbus_bool_t
00793 _dbus_read_credentials_unix_socket (int client_fd,
00794 DBusCredentials *credentials,
00795 DBusError *error)
00796 {
00797 struct msghdr msg;
00798 struct iovec iov;
00799 char buf;
00800
00801 #ifdef HAVE_CMSGCRED
00802 char cmsgmem[CMSG_SPACE (sizeof (struct cmsgcred))];
00803 struct cmsghdr *cmsg = (struct cmsghdr *) cmsgmem;
00804 #endif
00805
00806 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
00807
00808
00809
00810
00811
00812 _dbus_assert (sizeof (pid_t) <= sizeof (credentials->pid));
00813 _dbus_assert (sizeof (uid_t) <= sizeof (credentials->uid));
00814 _dbus_assert (sizeof (gid_t) <= sizeof (credentials->gid));
00815
00816 _dbus_credentials_clear (credentials);
00817
00818 #if defined(LOCAL_CREDS) && defined(HAVE_CMSGCRED)
00819
00820 {
00821 int on = 1;
00822 if (setsockopt (client_fd, 0, LOCAL_CREDS, &on, sizeof (on)) < 0)
00823 {
00824 _dbus_verbose ("Unable to set LOCAL_CREDS socket option\n");
00825 return FALSE;
00826 }
00827 }
00828 #endif
00829
00830 iov.iov_base = &buf;
00831 iov.iov_len = 1;
00832
00833 memset (&msg, 0, sizeof (msg));
00834 msg.msg_iov = &iov;
00835 msg.msg_iovlen = 1;
00836
00837 #ifdef HAVE_CMSGCRED
00838 memset (cmsgmem, 0, sizeof (cmsgmem));
00839 msg.msg_control = cmsgmem;
00840 msg.msg_controllen = sizeof (cmsgmem);
00841 #endif
00842
00843 again:
00844 if (recvmsg (client_fd, &msg, 0) < 0)
00845 {
00846 if (errno == EINTR)
00847 goto again;
00848
00849 dbus_set_error (error, _dbus_error_from_errno (errno),
00850 "Failed to read credentials byte: %s",
00851 _dbus_strerror (errno));
00852 return FALSE;
00853 }
00854
00855 if (buf != '\0')
00856 {
00857 dbus_set_error (error, DBUS_ERROR_FAILED,
00858 "Credentials byte was not nul");
00859 return FALSE;
00860 }
00861
00862 #ifdef HAVE_CMSGCRED
00863 if (cmsg->cmsg_len < sizeof (cmsgmem) || cmsg->cmsg_type != SCM_CREDS)
00864 {
00865 dbus_set_error (error, DBUS_ERROR_FAILED,
00866 "Message from recvmsg() was not SCM_CREDS");
00867 return FALSE;
00868 }
00869 #endif
00870
00871 _dbus_verbose ("read credentials byte\n");
00872
00873 {
00874 #ifdef SO_PEERCRED
00875 struct ucred cr;
00876 int cr_len = sizeof (cr);
00877
00878 if (getsockopt (client_fd, SOL_SOCKET, SO_PEERCRED, &cr, &cr_len) == 0 &&
00879 cr_len == sizeof (cr))
00880 {
00881 credentials->pid = cr.pid;
00882 credentials->uid = cr.uid;
00883 credentials->gid = cr.gid;
00884 }
00885 else
00886 {
00887 _dbus_verbose ("Failed to getsockopt() credentials, returned len %d/%d: %s\n",
00888 cr_len, (int) sizeof (cr), _dbus_strerror (errno));
00889 }
00890 #elif defined(HAVE_CMSGCRED)
00891 struct cmsgcred *cred;
00892
00893 cred = (struct cmsgcred *) CMSG_DATA (cmsg);
00894
00895 credentials->pid = cred->cmcred_pid;
00896 credentials->uid = cred->cmcred_euid;
00897 credentials->gid = cred->cmcred_groups[0];
00898 #else
00899 _dbus_verbose ("Socket credentials not supported on this OS\n");
00900 #endif
00901 }
00902
00903 _dbus_verbose ("Credentials:"
00904 " pid "DBUS_PID_FORMAT
00905 " uid "DBUS_UID_FORMAT
00906 " gid "DBUS_GID_FORMAT"\n",
00907 credentials->pid,
00908 credentials->uid,
00909 credentials->gid);
00910
00911 return TRUE;
00912 }
00913
00931 dbus_bool_t
00932 _dbus_send_credentials_unix_socket (int server_fd,
00933 DBusError *error)
00934 {
00935 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
00936
00937 if (write_credentials_byte (server_fd, error))
00938 return TRUE;
00939 else
00940 return FALSE;
00941 }
00942
00950 int
00951 _dbus_accept (int listen_fd)
00952 {
00953 int client_fd;
00954 struct sockaddr addr;
00955 socklen_t addrlen;
00956
00957 addrlen = sizeof (addr);
00958
00959 retry:
00960 client_fd = accept (listen_fd, &addr, &addrlen);
00961
00962 if (client_fd < 0)
00963 {
00964 if (errno == EINTR)
00965 goto retry;
00966 }
00967
00968 return client_fd;
00969 }
00970
00985 dbus_bool_t
00986 _dbus_string_append_int (DBusString *str,
00987 long value)
00988 {
00989
00990 #define MAX_LONG_LEN ((sizeof (long) * 8 + 2) / 3 + 1)
00991 int orig_len;
00992 int i;
00993 char *buf;
00994
00995 orig_len = _dbus_string_get_length (str);
00996
00997 if (!_dbus_string_lengthen (str, MAX_LONG_LEN))
00998 return FALSE;
00999
01000 buf = _dbus_string_get_data_len (str, orig_len, MAX_LONG_LEN);
01001
01002 snprintf (buf, MAX_LONG_LEN, "%ld", value);
01003
01004 i = 0;
01005 while (*buf)
01006 {
01007 ++buf;
01008 ++i;
01009 }
01010
01011 _dbus_string_shorten (str, MAX_LONG_LEN - i);
01012
01013 return TRUE;
01014 }
01015
01023 dbus_bool_t
01024 _dbus_string_append_uint (DBusString *str,
01025 unsigned long value)
01026 {
01027
01028 #define MAX_ULONG_LEN (MAX_LONG_LEN * 2)
01029 int orig_len;
01030 int i;
01031 char *buf;
01032
01033 orig_len = _dbus_string_get_length (str);
01034
01035 if (!_dbus_string_lengthen (str, MAX_ULONG_LEN))
01036 return FALSE;
01037
01038 buf = _dbus_string_get_data_len (str, orig_len, MAX_ULONG_LEN);
01039
01040 snprintf (buf, MAX_ULONG_LEN, "%lu", value);
01041
01042 i = 0;
01043 while (*buf)
01044 {
01045 ++buf;
01046 ++i;
01047 }
01048
01049 _dbus_string_shorten (str, MAX_ULONG_LEN - i);
01050
01051 return TRUE;
01052 }
01053
01061 dbus_bool_t
01062 _dbus_string_append_double (DBusString *str,
01063 double value)
01064 {
01065 #define MAX_DOUBLE_LEN 64
01066 int orig_len;
01067 char *buf;
01068 int i;
01069
01070 orig_len = _dbus_string_get_length (str);
01071
01072 if (!_dbus_string_lengthen (str, MAX_DOUBLE_LEN))
01073 return FALSE;
01074
01075 buf = _dbus_string_get_data_len (str, orig_len, MAX_DOUBLE_LEN);
01076
01077 snprintf (buf, MAX_LONG_LEN, "%g", value);
01078
01079 i = 0;
01080 while (*buf)
01081 {
01082 ++buf;
01083 ++i;
01084 }
01085
01086 _dbus_string_shorten (str, MAX_DOUBLE_LEN - i);
01087
01088 return TRUE;
01089 }
01090
01103 dbus_bool_t
01104 _dbus_string_parse_int (const DBusString *str,
01105 int start,
01106 long *value_return,
01107 int *end_return)
01108 {
01109 long v;
01110 const char *p;
01111 char *end;
01112
01113 p = _dbus_string_get_const_data_len (str, start,
01114 _dbus_string_get_length (str) - start);
01115
01116 end = NULL;
01117 errno = 0;
01118 v = strtol (p, &end, 0);
01119 if (end == NULL || end == p || errno != 0)
01120 return FALSE;
01121
01122 if (value_return)
01123 *value_return = v;
01124 if (end_return)
01125 *end_return = start + (end - p);
01126
01127 return TRUE;
01128 }
01129
01130 #ifdef DBUS_BUILD_TESTS
01131
01144 dbus_bool_t
01145 _dbus_string_parse_uint (const DBusString *str,
01146 int start,
01147 unsigned long *value_return,
01148 int *end_return)
01149 {
01150 unsigned long v;
01151 const char *p;
01152 char *end;
01153
01154 p = _dbus_string_get_const_data_len (str, start,
01155 _dbus_string_get_length (str) - start);
01156
01157 end = NULL;
01158 errno = 0;
01159 v = strtoul (p, &end, 0);
01160 if (end == NULL || end == p || errno != 0)
01161 return FALSE;
01162
01163 if (value_return)
01164 *value_return = v;
01165 if (end_return)
01166 *end_return = start + (end - p);
01167
01168 return TRUE;
01169 }
01170 #endif
01171
01172 static dbus_bool_t
01173 ascii_isspace (char c)
01174 {
01175 return (c == ' ' ||
01176 c == '\f' ||
01177 c == '\n' ||
01178 c == '\r' ||
01179 c == '\t' ||
01180 c == '\v');
01181 }
01182
01183 static dbus_bool_t
01184 ascii_isdigit (char c)
01185 {
01186 return c >= '0' && c <= '9';
01187 }
01188
01189 static dbus_bool_t
01190 ascii_isxdigit (char c)
01191 {
01192 return (ascii_isdigit (c) ||
01193 (c >= 'a' && c <= 'f') ||
01194 (c >= 'A' && c <= 'F'));
01195 }
01196
01197
01198
01199
01200
01201
01202
01203 static double
01204 ascii_strtod (const char *nptr,
01205 char **endptr)
01206 {
01207 char *fail_pos;
01208 double val;
01209 struct lconv *locale_data;
01210 const char *decimal_point;
01211 int decimal_point_len;
01212 const char *p, *decimal_point_pos;
01213 const char *end = NULL;
01214
01215 fail_pos = NULL;
01216
01217 locale_data = localeconv ();
01218 decimal_point = locale_data->decimal_point;
01219 decimal_point_len = strlen (decimal_point);
01220
01221 _dbus_assert (decimal_point_len != 0);
01222
01223 decimal_point_pos = NULL;
01224 if (decimal_point[0] != '.' ||
01225 decimal_point[1] != 0)
01226 {
01227 p = nptr;
01228
01229 while (ascii_isspace (*p))
01230 p++;
01231
01232
01233 if (*p == '+' || *p == '-')
01234 p++;
01235
01236 if (p[0] == '0' &&
01237 (p[1] == 'x' || p[1] == 'X'))
01238 {
01239 p += 2;
01240
01241
01242 while (ascii_isxdigit (*p))
01243 p++;
01244
01245 if (*p == '.')
01246 {
01247 decimal_point_pos = p++;
01248
01249 while (ascii_isxdigit (*p))
01250 p++;
01251
01252 if (*p == 'p' || *p == 'P')
01253 p++;
01254 if (*p == '+' || *p == '-')
01255 p++;
01256 while (ascii_isdigit (*p))
01257 p++;
01258 end = p;
01259 }
01260 }
01261 else
01262 {
01263 while (ascii_isdigit (*p))
01264 p++;
01265
01266 if (*p == '.')
01267 {
01268 decimal_point_pos = p++;
01269
01270 while (ascii_isdigit (*p))
01271 p++;
01272
01273 if (*p == 'e' || *p == 'E')
01274 p++;
01275 if (*p == '+' || *p == '-')
01276 p++;
01277 while (ascii_isdigit (*p))
01278 p++;
01279 end = p;
01280 }
01281 }
01282
01283 }
01284
01285
01286
01287 errno = 0;
01288
01289 if (decimal_point_pos)
01290 {
01291 char *copy, *c;
01292
01293
01294 copy = dbus_malloc (end - nptr + 1 + decimal_point_len);
01295
01296 c = copy;
01297 memcpy (c, nptr, decimal_point_pos - nptr);
01298 c += decimal_point_pos - nptr;
01299 memcpy (c, decimal_point, decimal_point_len);
01300 c += decimal_point_len;
01301 memcpy (c, decimal_point_pos + 1, end - (decimal_point_pos + 1));
01302 c += end - (decimal_point_pos + 1);
01303 *c = 0;
01304
01305 val = strtod (copy, &fail_pos);
01306
01307 if (fail_pos)
01308 {
01309 if (fail_pos > decimal_point_pos)
01310 fail_pos = (char *)nptr + (fail_pos - copy) - (decimal_point_len - 1);
01311 else
01312 fail_pos = (char *)nptr + (fail_pos - copy);
01313 }
01314
01315 dbus_free (copy);
01316
01317 }
01318 else
01319 val = strtod (nptr, &fail_pos);
01320
01321 if (endptr)
01322 *endptr = fail_pos;
01323
01324 return val;
01325 }
01326
01327
01340 dbus_bool_t
01341 _dbus_string_parse_double (const DBusString *str,
01342 int start,
01343 double *value_return,
01344 int *end_return)
01345 {
01346 double v;
01347 const char *p;
01348 char *end;
01349
01350 p = _dbus_string_get_const_data_len (str, start,
01351 _dbus_string_get_length (str) - start);
01352
01353 end = NULL;
01354 errno = 0;
01355 v = ascii_strtod (p, &end);
01356 if (end == NULL || end == p || errno != 0)
01357 return FALSE;
01358
01359 if (value_return)
01360 *value_return = v;
01361 if (end_return)
01362 *end_return = start + (end - p);
01363
01364 return TRUE;
01365 }
01366
01368
01373 static dbus_bool_t
01374 fill_user_info_from_passwd (struct passwd *p,
01375 DBusUserInfo *info,
01376 DBusError *error)
01377 {
01378 _dbus_assert (p->pw_name != NULL);
01379 _dbus_assert (p->pw_dir != NULL);
01380
01381 info->uid = p->pw_uid;
01382 info->primary_gid = p->pw_gid;
01383 info->username = _dbus_strdup (p->pw_name);
01384 info->homedir = _dbus_strdup (p->pw_dir);
01385
01386 if (info->username == NULL ||
01387 info->homedir == NULL)
01388 {
01389 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
01390 return FALSE;
01391 }
01392
01393 return TRUE;
01394 }
01395
01396 static dbus_bool_t
01397 fill_user_info (DBusUserInfo *info,
01398 dbus_uid_t uid,
01399 const DBusString *username,
01400 DBusError *error)
01401 {
01402 const char *username_c;
01403
01404
01405 _dbus_assert (username != NULL || uid != DBUS_UID_UNSET);
01406 _dbus_assert (username == NULL || uid == DBUS_UID_UNSET);
01407
01408 info->uid = DBUS_UID_UNSET;
01409 info->primary_gid = DBUS_GID_UNSET;
01410 info->group_ids = NULL;
01411 info->n_group_ids = 0;
01412 info->username = NULL;
01413 info->homedir = NULL;
01414
01415 if (username != NULL)
01416 username_c = _dbus_string_get_const_data (username);
01417 else
01418 username_c = NULL;
01419
01420
01421
01422
01423
01424
01425 #if defined (HAVE_POSIX_GETPWNAM_R) || defined (HAVE_NONPOSIX_GETPWNAM_R)
01426 {
01427 struct passwd *p;
01428 int result;
01429 char buf[1024];
01430 struct passwd p_str;
01431
01432 p = NULL;
01433 #ifdef HAVE_POSIX_GETPWNAM_R
01434 if (uid != DBUS_UID_UNSET)
01435 result = getpwuid_r (uid, &p_str, buf, sizeof (buf),
01436 &p);
01437 else
01438 result = getpwnam_r (username_c, &p_str, buf, sizeof (buf),
01439 &p);
01440 #else
01441 if (uid != DBUS_UID_UNSET)
01442 p = getpwuid_r (uid, &p_str, buf, sizeof (buf));
01443 else
01444 p = getpwnam_r (username_c, &p_str, buf, sizeof (buf));
01445 result = 0;
01446 #endif
01447 if (result == 0 && p == &p_str)
01448 {
01449 if (!fill_user_info_from_passwd (p, info, error))
01450 return FALSE;
01451 }
01452 else
01453 {
01454 dbus_set_error (error, _dbus_error_from_errno (errno),
01455 "User \"%s\" unknown or no memory to allocate password entry\n",
01456 username_c ? username_c : "???");
01457 _dbus_verbose ("User %s unknown\n", username_c ? username_c : "???");
01458 return FALSE;
01459 }
01460 }
01461 #else
01462 {
01463
01464 struct passwd *p;
01465
01466 if (uid != DBUS_UID_UNSET)
01467 p = getpwuid (uid);
01468 else
01469 p = getpwnam (username_c);
01470
01471 if (p != NULL)
01472 {
01473 if (!fill_user_info_from_passwd (p, info, error))
01474 return FALSE;
01475 }
01476 else
01477 {
01478 dbus_set_error (error, _dbus_error_from_errno (errno),
01479 "User \"%s\" unknown or no memory to allocate password entry\n",
01480 username_c ? username_c : "???");
01481 _dbus_verbose ("User %s unknown\n", username_c ? username_c : "???");
01482 return FALSE;
01483 }
01484 }
01485 #endif
01486
01487
01488 username_c = info->username;
01489
01490 #ifdef HAVE_GETGROUPLIST
01491 {
01492 gid_t *buf;
01493 int buf_count;
01494 int i;
01495
01496 buf_count = 17;
01497 buf = dbus_new (gid_t, buf_count);
01498 if (buf == NULL)
01499 {
01500 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
01501 goto failed;
01502 }
01503
01504 if (getgrouplist (username_c,
01505 info->primary_gid,
01506 buf, &buf_count) < 0)
01507 {
01508 gid_t *new = dbus_realloc (buf, buf_count * sizeof (buf[0]));
01509 if (new == NULL)
01510 {
01511 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
01512 dbus_free (buf);
01513 goto failed;
01514 }
01515
01516 buf = new;
01517
01518 errno = 0;
01519 if (getgrouplist (username_c, info->primary_gid, buf, &buf_count) < 0)
01520 {
01521 dbus_set_error (error,
01522 _dbus_error_from_errno (errno),
01523 "Failed to get groups for username \"%s\" primary GID "
01524 DBUS_GID_FORMAT ": %s\n",
01525 username_c, info->primary_gid,
01526 _dbus_strerror (errno));
01527 dbus_free (buf);
01528 goto failed;
01529 }
01530 }
01531
01532 info->group_ids = dbus_new (dbus_gid_t, buf_count);
01533 if (info->group_ids == NULL)
01534 {
01535 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
01536 dbus_free (buf);
01537 goto failed;
01538 }
01539
01540 for (i = 0; i < buf_count; ++i)
01541 info->group_ids[i] = buf[i];
01542
01543 info->n_group_ids = buf_count;
01544
01545 dbus_free (buf);
01546 }
01547 #else
01548 {
01549
01550 info->group_ids = dbus_new (dbus_gid_t, 1);
01551 if (info->group_ids == NULL)
01552 {
01553 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
01554 goto failed;
01555 }
01556
01557 info->n_group_ids = 1;
01558
01559 (info->group_ids)[0] = info->primary_gid;
01560 }
01561 #endif
01562
01563 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
01564
01565 return TRUE;
01566
01567 failed:
01568 _DBUS_ASSERT_ERROR_IS_SET (error);
01569 return FALSE;
01570 }
01571
01580 dbus_bool_t
01581 _dbus_user_info_fill (DBusUserInfo *info,
01582 const DBusString *username,
01583 DBusError *error)
01584 {
01585 return fill_user_info (info, DBUS_UID_UNSET,
01586 username, error);
01587 }
01588
01597 dbus_bool_t
01598 _dbus_user_info_fill_uid (DBusUserInfo *info,
01599 dbus_uid_t uid,
01600 DBusError *error)
01601 {
01602 return fill_user_info (info, uid,
01603 NULL, error);
01604 }
01605
01611 void
01612 _dbus_user_info_free (DBusUserInfo *info)
01613 {
01614 dbus_free (info->group_ids);
01615 dbus_free (info->username);
01616 dbus_free (info->homedir);
01617 }
01618
01619 static dbus_bool_t
01620 fill_user_info_from_group (struct group *g,
01621 DBusGroupInfo *info,
01622 DBusError *error)
01623 {
01624 _dbus_assert (g->gr_name != NULL);
01625
01626 info->gid = g->gr_gid;
01627 info->groupname = _dbus_strdup (g->gr_name);
01628
01629
01630
01631 if (info->groupname == NULL)
01632 {
01633 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
01634 return FALSE;
01635 }
01636
01637 return TRUE;
01638 }
01639
01640 static dbus_bool_t
01641 fill_group_info (DBusGroupInfo *info,
01642 dbus_gid_t gid,
01643 const DBusString *groupname,
01644 DBusError *error)
01645 {
01646 const char *group_c_str;
01647
01648 _dbus_assert (groupname != NULL || gid != DBUS_GID_UNSET);
01649 _dbus_assert (groupname == NULL || gid == DBUS_GID_UNSET);
01650
01651 if (groupname)
01652 group_c_str = _dbus_string_get_const_data (groupname);
01653 else
01654 group_c_str = NULL;
01655
01656
01657
01658
01659
01660
01661 #if defined (HAVE_POSIX_GETPWNAM_R) || defined (HAVE_NONPOSIX_GETPWNAM_R)
01662 {
01663 struct group *g;
01664 int result;
01665 char buf[1024];
01666 struct group g_str;
01667
01668 g = NULL;
01669 #ifdef HAVE_POSIX_GETPWNAM_R
01670
01671 if (group_c_str)
01672 result = getgrnam_r (group_c_str, &g_str, buf, sizeof (buf),
01673 &g);
01674 else
01675 result = getgrgid_r (gid, &g_str, buf, sizeof (buf),
01676 &g);
01677 #else
01678 p = getgrnam_r (group_c_str, &g_str, buf, sizeof (buf));
01679 result = 0;
01680 #endif
01681 if (result == 0 && g == &g_str)
01682 {
01683 return fill_user_info_from_group (g, info, error);
01684 }
01685 else
01686 {
01687 dbus_set_error (error, _dbus_error_from_errno (errno),
01688 "Group %s unknown or failed to look it up\n",
01689 group_c_str ? group_c_str : "???");
01690 return FALSE;
01691 }
01692 }
01693 #else
01694 {
01695
01696 struct group *g;
01697
01698 g = getgrnam (group_c_str);
01699
01700 if (g != NULL)
01701 {
01702 return fill_user_info_from_group (g, info, error);
01703 }
01704 else
01705 {
01706 dbus_set_error (error, _dbus_error_from_errno (errno),
01707 "Group %s unknown or failed to look it up\n",
01708 group_c_str ? group_c_str : "???");
01709 return FALSE;
01710 }
01711 }
01712 #endif
01713 }
01714
01724 dbus_bool_t
01725 _dbus_group_info_fill (DBusGroupInfo *info,
01726 const DBusString *groupname,
01727 DBusError *error)
01728 {
01729 return fill_group_info (info, DBUS_GID_UNSET,
01730 groupname, error);
01731
01732 }
01733
01743 dbus_bool_t
01744 _dbus_group_info_fill_gid (DBusGroupInfo *info,
01745 dbus_gid_t gid,
01746 DBusError *error)
01747 {
01748 return fill_group_info (info, gid, NULL, error);
01749 }
01750
01756 void
01757 _dbus_group_info_free (DBusGroupInfo *info)
01758 {
01759 dbus_free (info->groupname);
01760 }
01761
01768 void
01769 _dbus_credentials_clear (DBusCredentials *credentials)
01770 {
01771 credentials->pid = DBUS_PID_UNSET;
01772 credentials->uid = DBUS_UID_UNSET;
01773 credentials->gid = DBUS_GID_UNSET;
01774 }
01775
01781 void
01782 _dbus_credentials_from_current_process (DBusCredentials *credentials)
01783 {
01784
01785
01786
01787
01788 _dbus_assert (sizeof (pid_t) <= sizeof (credentials->pid));
01789 _dbus_assert (sizeof (uid_t) <= sizeof (credentials->uid));
01790 _dbus_assert (sizeof (gid_t) <= sizeof (credentials->gid));
01791
01792 credentials->pid = getpid ();
01793 credentials->uid = getuid ();
01794 credentials->gid = getgid ();
01795 }
01796
01805 dbus_bool_t
01806 _dbus_credentials_match (const DBusCredentials *expected_credentials,
01807 const DBusCredentials *provided_credentials)
01808 {
01809 if (provided_credentials->uid == DBUS_UID_UNSET)
01810 return FALSE;
01811 else if (expected_credentials->uid == DBUS_UID_UNSET)
01812 return FALSE;
01813 else if (provided_credentials->uid == 0)
01814 return TRUE;
01815 else if (provided_credentials->uid == expected_credentials->uid)
01816 return TRUE;
01817 else
01818 return FALSE;
01819 }
01820
01825 unsigned long
01826 _dbus_getpid (void)
01827 {
01828 return getpid ();
01829 }
01830
01834 dbus_uid_t
01835 _dbus_getuid (void)
01836 {
01837 return getuid ();
01838 }
01839
01843 dbus_gid_t
01844 _dbus_getgid (void)
01845 {
01846 return getgid ();
01847 }
01848
01849 _DBUS_DEFINE_GLOBAL_LOCK (atomic);
01850
01851 #ifdef DBUS_USE_ATOMIC_INT_486
01852
01853
01854 static inline dbus_int32_t
01855 atomic_exchange_and_add (DBusAtomic *atomic,
01856 volatile dbus_int32_t val)
01857 {
01858 register dbus_int32_t result;
01859
01860 __asm__ __volatile__ ("lock; xaddl %0,%1"
01861 : "=r" (result), "=m" (atomic->value)
01862 : "0" (val), "m" (atomic->value));
01863 return result;
01864 }
01865 #endif
01866
01875 dbus_int32_t
01876 _dbus_atomic_inc (DBusAtomic *atomic)
01877 {
01878 #ifdef DBUS_USE_ATOMIC_INT_486
01879 return atomic_exchange_and_add (atomic, 1);
01880 #else
01881 dbus_int32_t res;
01882 _DBUS_LOCK (atomic);
01883 res = atomic->value;
01884 atomic->value += 1;
01885 _DBUS_UNLOCK (atomic);
01886 return res;
01887 #endif
01888 }
01889
01898 dbus_int32_t
01899 _dbus_atomic_dec (DBusAtomic *atomic)
01900 {
01901 #ifdef DBUS_USE_ATOMIC_INT_486
01902 return atomic_exchange_and_add (atomic, -1);
01903 #else
01904 dbus_int32_t res;
01905
01906 _DBUS_LOCK (atomic);
01907 res = atomic->value;
01908 atomic->value -= 1;
01909 _DBUS_UNLOCK (atomic);
01910 return res;
01911 #endif
01912 }
01913
01922 int
01923 _dbus_poll (DBusPollFD *fds,
01924 int n_fds,
01925 int timeout_milliseconds)
01926 {
01927 #ifdef HAVE_POLL
01928
01929
01930
01931
01932 if (_DBUS_POLLIN == POLLIN &&
01933 _DBUS_POLLPRI == POLLPRI &&
01934 _DBUS_POLLOUT == POLLOUT &&
01935 _DBUS_POLLERR == POLLERR &&
01936 _DBUS_POLLHUP == POLLHUP &&
01937 _DBUS_POLLNVAL == POLLNVAL &&
01938 sizeof (DBusPollFD) == sizeof (struct pollfd) &&
01939 _DBUS_STRUCT_OFFSET (DBusPollFD, fd) ==
01940 _DBUS_STRUCT_OFFSET (struct pollfd, fd) &&
01941 _DBUS_STRUCT_OFFSET (DBusPollFD, events) ==
01942 _DBUS_STRUCT_OFFSET (struct pollfd, events) &&
01943 _DBUS_STRUCT_OFFSET (DBusPollFD, revents) ==
01944 _DBUS_STRUCT_OFFSET (struct pollfd, revents))
01945 {
01946 return poll ((struct pollfd*) fds,
01947 n_fds,
01948 timeout_milliseconds);
01949 }
01950 else
01951 {
01952
01953
01954
01955 _dbus_warn ("didn't implement poll() properly for this system yet\n");
01956 return -1;
01957 }
01958 #else
01959
01960 fd_set read_set, write_set, err_set;
01961 int max_fd = 0;
01962 int i;
01963 struct timeval tv;
01964 int ready;
01965
01966 FD_ZERO (&read_set);
01967 FD_ZERO (&write_set);
01968 FD_ZERO (&err_set);
01969
01970 for (i = 0; i < n_fds; i++)
01971 {
01972 DBusPollFD f = fds[i];
01973
01974 if (f.events & _DBUS_POLLIN)
01975 FD_SET (f.fd, &read_set);
01976
01977 if (f.events & _DBUS_POLLOUT)
01978 FD_SET (f.fd, &write_set);
01979
01980 FD_SET (f.fd, &err_set);
01981
01982 max_fd = MAX (max_fd, f.fd);
01983 }
01984
01985 tv.tv_sec = timeout_milliseconds / 1000;
01986 tv.tv_usec = (timeout_milliseconds % 1000) * 1000;
01987
01988 ready = select (max_fd + 1, &read_set, &write_set, &err_set, &tv);
01989
01990 if (ready > 0)
01991 {
01992 for (i = 0; i < n_fds; i++)
01993 {
01994 DBusPollFD f = fds[i];
01995
01996 f.revents = 0;
01997
01998 if (FD_ISSET (f.fd, &read_set))
01999 f.revents |= _DBUS_POLLIN;
02000
02001 if (FD_ISSET (f.fd, &write_set))
02002 f.revents |= _DBUS_POLLOUT;
02003
02004 if (FD_ISSET (f.fd, &err_set))
02005 f.revents |= _DBUS_POLLERR;
02006 }
02007 }
02008
02009 return ready;
02010 #endif
02011 }
02012
02014 #define NANOSECONDS_PER_SECOND 1000000000
02015
02016 #define MICROSECONDS_PER_SECOND 1000000
02017
02018 #define MILLISECONDS_PER_SECOND 1000
02019
02020 #define NANOSECONDS_PER_MILLISECOND 1000000
02021
02022 #define MICROSECONDS_PER_MILLISECOND 1000
02023
02028 void
02029 _dbus_sleep_milliseconds (int milliseconds)
02030 {
02031 #ifdef HAVE_NANOSLEEP
02032 struct timespec req;
02033 struct timespec rem;
02034
02035 req.tv_sec = milliseconds / MILLISECONDS_PER_SECOND;
02036 req.tv_nsec = (milliseconds % MILLISECONDS_PER_SECOND) * NANOSECONDS_PER_MILLISECOND;
02037 rem.tv_sec = 0;
02038 rem.tv_nsec = 0;
02039
02040 while (nanosleep (&req, &rem) < 0 && errno == EINTR)
02041 req = rem;
02042 #elif defined (HAVE_USLEEP)
02043 usleep (milliseconds * MICROSECONDS_PER_MILLISECOND);
02044 #else
02045 sleep (MAX (milliseconds / 1000, 1));
02046 #endif
02047 }
02048
02055 void
02056 _dbus_get_current_time (long *tv_sec,
02057 long *tv_usec)
02058 {
02059 struct timeval t;
02060
02061 gettimeofday (&t, NULL);
02062
02063 if (tv_sec)
02064 *tv_sec = t.tv_sec;
02065 if (tv_usec)
02066 *tv_usec = t.tv_usec;
02067 }
02068
02079 dbus_bool_t
02080 _dbus_file_get_contents (DBusString *str,
02081 const DBusString *filename,
02082 DBusError *error)
02083 {
02084 int fd;
02085 struct stat sb;
02086 int orig_len;
02087 int total;
02088 const char *filename_c;
02089
02090 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
02091
02092 filename_c = _dbus_string_get_const_data (filename);
02093
02094
02095 fd = open (filename_c, O_RDONLY | O_BINARY);
02096 if (fd < 0)
02097 {
02098 dbus_set_error (error, _dbus_error_from_errno (errno),
02099 "Failed to open \"%s\": %s",
02100 filename_c,
02101 _dbus_strerror (errno));
02102 return FALSE;
02103 }
02104
02105 if (fstat (fd, &sb) < 0)
02106 {
02107 dbus_set_error (error, _dbus_error_from_errno (errno),
02108 "Failed to stat \"%s\": %s",
02109 filename_c,
02110 _dbus_strerror (errno));
02111
02112 _dbus_verbose ("fstat() failed: %s",
02113 _dbus_strerror (errno));
02114
02115 close (fd);
02116
02117 return FALSE;
02118 }
02119
02120 if (sb.st_size > _DBUS_ONE_MEGABYTE)
02121 {
02122 dbus_set_error (error, DBUS_ERROR_FAILED,
02123 "File size %lu of \"%s\" is too large.",
02124 (unsigned long) sb.st_size, filename_c);
02125 close (fd);
02126 return FALSE;
02127 }
02128
02129 total = 0;
02130 orig_len = _dbus_string_get_length (str);
02131 if (sb.st_size > 0 && S_ISREG (sb.st_mode))
02132 {
02133 int bytes_read;
02134
02135 while (total < (int) sb.st_size)
02136 {
02137 bytes_read = _dbus_read (fd, str,
02138 sb.st_size - total);
02139 if (bytes_read <= 0)
02140 {
02141 dbus_set_error (error, _dbus_error_from_errno (errno),
02142 "Error reading \"%s\": %s",
02143 filename_c,
02144 _dbus_strerror (errno));
02145
02146 _dbus_verbose ("read() failed: %s",
02147 _dbus_strerror (errno));
02148
02149 close (fd);
02150 _dbus_string_set_length (str, orig_len);
02151 return FALSE;
02152 }
02153 else
02154 total += bytes_read;
02155 }
02156
02157 close (fd);
02158 return TRUE;
02159 }
02160 else if (sb.st_size != 0)
02161 {
02162 _dbus_verbose ("Can only open regular files at the moment.\n");
02163 dbus_set_error (error, DBUS_ERROR_FAILED,
02164 "\"%s\" is not a regular file",
02165 filename_c);
02166 close (fd);
02167 return FALSE;
02168 }
02169 else
02170 {
02171 close (fd);
02172 return TRUE;
02173 }
02174 }
02175
02185 dbus_bool_t
02186 _dbus_string_save_to_file (const DBusString *str,
02187 const DBusString *filename,
02188 DBusError *error)
02189 {
02190 int fd;
02191 int bytes_to_write;
02192 const char *filename_c;
02193 DBusString tmp_filename;
02194 const char *tmp_filename_c;
02195 int total;
02196 dbus_bool_t need_unlink;
02197 dbus_bool_t retval;
02198
02199 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
02200
02201 fd = -1;
02202 retval = FALSE;
02203 need_unlink = FALSE;
02204
02205 if (!_dbus_string_init (&tmp_filename))
02206 {
02207 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
02208 return FALSE;
02209 }
02210
02211 if (!_dbus_string_copy (filename, 0, &tmp_filename, 0))
02212 {
02213 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
02214 _dbus_string_free (&tmp_filename);
02215 return FALSE;
02216 }
02217
02218 if (!_dbus_string_append (&tmp_filename, "."))
02219 {
02220 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
02221 _dbus_string_free (&tmp_filename);
02222 return FALSE;
02223 }
02224
02225 #define N_TMP_FILENAME_RANDOM_BYTES 8
02226 if (!_dbus_generate_random_ascii (&tmp_filename, N_TMP_FILENAME_RANDOM_BYTES))
02227 {
02228 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
02229 _dbus_string_free (&tmp_filename);
02230 return FALSE;
02231 }
02232
02233 filename_c = _dbus_string_get_const_data (filename);
02234 tmp_filename_c = _dbus_string_get_const_data (&tmp_filename);
02235
02236 fd = open (tmp_filename_c, O_WRONLY | O_BINARY | O_EXCL | O_CREAT,
02237 0600);
02238 if (fd < 0)
02239 {
02240 dbus_set_error (error, _dbus_error_from_errno (errno),
02241 "Could not create %s: %s", tmp_filename_c,
02242 _dbus_strerror (errno));
02243 goto out;
02244 }
02245
02246 need_unlink = TRUE;
02247
02248 total = 0;
02249 bytes_to_write = _dbus_string_get_length (str);
02250
02251 while (total < bytes_to_write)
02252 {
02253 int bytes_written;
02254
02255 bytes_written = _dbus_write (fd, str, total,
02256 bytes_to_write - total);
02257
02258 if (bytes_written <= 0)
02259 {
02260 dbus_set_error (error, _dbus_error_from_errno (errno),
02261 "Could not write to %s: %s", tmp_filename_c,
02262 _dbus_strerror (errno));
02263
02264 goto out;
02265 }
02266
02267 total += bytes_written;
02268 }
02269
02270 if (close (fd) < 0)
02271 {
02272 dbus_set_error (error, _dbus_error_from_errno (errno),
02273 "Could not close file %s: %s",
02274 tmp_filename_c, _dbus_strerror (errno));
02275
02276 goto out;
02277 }
02278
02279 fd = -1;
02280
02281 if (rename (tmp_filename_c, filename_c) < 0)
02282 {
02283 dbus_set_error (error, _dbus_error_from_errno (errno),
02284 "Could not rename %s to %s: %s",
02285 tmp_filename_c, filename_c,
02286 _dbus_strerror (errno));
02287
02288 goto out;
02289 }
02290
02291 need_unlink = FALSE;
02292
02293 retval = TRUE;
02294
02295 out:
02296
02297
02298
02299
02300 if (fd >= 0)
02301 close (fd);
02302
02303 if (need_unlink && unlink (tmp_filename_c) < 0)
02304 _dbus_verbose ("Failed to unlink temp file %s: %s\n",
02305 tmp_filename_c, _dbus_strerror (errno));
02306
02307 _dbus_string_free (&tmp_filename);
02308
02309 if (!retval)
02310 _DBUS_ASSERT_ERROR_IS_SET (error);
02311
02312 return retval;
02313 }
02314
02321 dbus_bool_t
02322 _dbus_create_file_exclusively (const DBusString *filename,
02323 DBusError *error)
02324 {
02325 int fd;
02326 const char *filename_c;
02327
02328 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
02329
02330 filename_c = _dbus_string_get_const_data (filename);
02331
02332 fd = open (filename_c, O_WRONLY | O_BINARY | O_EXCL | O_CREAT,
02333 0600);
02334 if (fd < 0)
02335 {
02336 dbus_set_error (error,
02337 DBUS_ERROR_FAILED,
02338 "Could not create file %s: %s\n",
02339 filename_c,
02340 _dbus_strerror (errno));
02341 return FALSE;
02342 }
02343
02344 if (close (fd) < 0)
02345 {
02346 dbus_set_error (error,
02347 DBUS_ERROR_FAILED,
02348 "Could not close file %s: %s\n",
02349 filename_c,
02350 _dbus_strerror (errno));
02351 return FALSE;
02352 }
02353
02354 return TRUE;
02355 }
02356
02365 dbus_bool_t
02366 _dbus_delete_file (const DBusString *filename,
02367 DBusError *error)
02368 {
02369 const char *filename_c;
02370
02371 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
02372
02373 filename_c = _dbus_string_get_const_data (filename);
02374
02375 if (unlink (filename_c) < 0)
02376 {
02377 dbus_set_error (error, DBUS_ERROR_FAILED,
02378 "Failed to delete file %s: %s\n",
02379 filename_c, _dbus_strerror (errno));
02380 return FALSE;
02381 }
02382 else
02383 return TRUE;
02384 }
02385
02394 dbus_bool_t
02395 _dbus_create_directory (const DBusString *filename,
02396 DBusError *error)
02397 {
02398 const char *filename_c;
02399
02400 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
02401
02402 filename_c = _dbus_string_get_const_data (filename);
02403
02404 if (mkdir (filename_c, 0700) < 0)
02405 {
02406 if (errno == EEXIST)
02407 return TRUE;
02408
02409 dbus_set_error (error, DBUS_ERROR_FAILED,
02410 "Failed to create directory %s: %s\n",
02411 filename_c, _dbus_strerror (errno));
02412 return FALSE;
02413 }
02414 else
02415 return TRUE;
02416 }
02417
02425 dbus_bool_t
02426 _dbus_delete_directory (const DBusString *filename,
02427 DBusError *error)
02428 {
02429 const char *filename_c;
02430
02431 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
02432
02433 filename_c = _dbus_string_get_const_data (filename);
02434
02435 if (rmdir (filename_c) != 0)
02436 {
02437 dbus_set_error (error, DBUS_ERROR_FAILED,
02438 "Failed to remove directory %s: %s\n",
02439 filename_c, _dbus_strerror (errno));
02440 return FALSE;
02441 }
02442
02443 return TRUE;
02444 }
02445
02456 dbus_bool_t
02457 _dbus_concat_dir_and_file (DBusString *dir,
02458 const DBusString *next_component)
02459 {
02460 dbus_bool_t dir_ends_in_slash;
02461 dbus_bool_t file_starts_with_slash;
02462
02463 if (_dbus_string_get_length (dir) == 0 ||
02464 _dbus_string_get_length (next_component) == 0)
02465 return TRUE;
02466
02467 dir_ends_in_slash = '/' == _dbus_string_get_byte (dir,
02468 _dbus_string_get_length (dir) - 1);
02469
02470 file_starts_with_slash = '/' == _dbus_string_get_byte (next_component, 0);
02471
02472 if (dir_ends_in_slash && file_starts_with_slash)
02473 {
02474 _dbus_string_shorten (dir, 1);
02475 }
02476 else if (!(dir_ends_in_slash || file_starts_with_slash))
02477 {
02478 if (!_dbus_string_append_byte (dir, '/'))
02479 return FALSE;
02480 }
02481
02482 return _dbus_string_copy (next_component, 0, dir,
02483 _dbus_string_get_length (dir));
02484 }
02485
02492 dbus_bool_t
02493 _dbus_string_get_dirname (const DBusString *filename,
02494 DBusString *dirname)
02495 {
02496 int sep;
02497
02498 _dbus_assert (filename != dirname);
02499 _dbus_assert (filename != NULL);
02500 _dbus_assert (dirname != NULL);
02501
02502
02503 sep = _dbus_string_get_length (filename);
02504 if (sep == 0)
02505 return _dbus_string_append (dirname, ".");
02506
02507 while (sep > 0 && _dbus_string_get_byte (filename, sep - 1) == '/')
02508 --sep;
02509
02510 _dbus_assert (sep >= 0);
02511
02512 if (sep == 0)
02513 return _dbus_string_append (dirname, "/");
02514
02515
02516 _dbus_string_find_byte_backward (filename, sep, '/', &sep);
02517 if (sep < 0)
02518 return _dbus_string_append (dirname, ".");
02519
02520
02521 while (sep > 0 && _dbus_string_get_byte (filename, sep - 1) == '/')
02522 --sep;
02523
02524 _dbus_assert (sep >= 0);
02525
02526 if (sep == 0 &&
02527 _dbus_string_get_byte (filename, 0) == '/')
02528 return _dbus_string_append (dirname, "/");
02529 else
02530 return _dbus_string_copy_len (filename, 0, sep - 0,
02531 dirname, _dbus_string_get_length (dirname));
02532 }
02533
02540 dbus_bool_t
02541 _dbus_path_is_absolute (const DBusString *filename)
02542 {
02543 if (_dbus_string_get_length (filename) > 0)
02544 return _dbus_string_get_byte (filename, 0) == '/';
02545 else
02546 return FALSE;
02547 }
02548
02552 struct DBusDirIter
02553 {
02554 DIR *d;
02556 };
02557
02565 DBusDirIter*
02566 _dbus_directory_open (const DBusString *filename,
02567 DBusError *error)
02568 {
02569 DIR *d;
02570 DBusDirIter *iter;
02571 const char *filename_c;
02572
02573 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
02574
02575 filename_c = _dbus_string_get_const_data (filename);
02576
02577 d = opendir (filename_c);
02578 if (d == NULL)
02579 {
02580 dbus_set_error (error, _dbus_error_from_errno (errno),
02581 "Failed to read directory \"%s\": %s",
02582 filename_c,
02583 _dbus_strerror (errno));
02584 return NULL;
02585 }
02586 iter = dbus_new0 (DBusDirIter, 1);
02587 if (iter == NULL)
02588 {
02589 closedir (d);
02590 dbus_set_error (error, DBUS_ERROR_NO_MEMORY,
02591 "Could not allocate memory for directory iterator");
02592 return NULL;
02593 }
02594
02595 iter->d = d;
02596
02597 return iter;
02598 }
02599
02613 dbus_bool_t
02614 _dbus_directory_get_next_file (DBusDirIter *iter,
02615 DBusString *filename,
02616 DBusError *error)
02617 {
02618 struct dirent *ent;
02619
02620 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
02621
02622 again:
02623 errno = 0;
02624 ent = readdir (iter->d);
02625 if (ent == NULL)
02626 {
02627 if (errno != 0)
02628 dbus_set_error (error,
02629 _dbus_error_from_errno (errno),
02630 "%s", _dbus_strerror (errno));
02631 return FALSE;
02632 }
02633 else if (ent->d_name[0] == '.' &&
02634 (ent->d_name[1] == '\0' ||
02635 (ent->d_name[1] == '.' && ent->d_name[2] == '\0')))
02636 goto again;
02637 else
02638 {
02639 _dbus_string_set_length (filename, 0);
02640 if (!_dbus_string_append (filename, ent->d_name))
02641 {
02642 dbus_set_error (error, DBUS_ERROR_NO_MEMORY,
02643 "No memory to read directory entry");
02644 return FALSE;
02645 }
02646 else
02647 return TRUE;
02648 }
02649 }
02650
02654 void
02655 _dbus_directory_close (DBusDirIter *iter)
02656 {
02657 closedir (iter->d);
02658 dbus_free (iter);
02659 }
02660
02661 static dbus_bool_t
02662 pseudorandom_generate_random_bytes (DBusString *str,
02663 int n_bytes)
02664 {
02665 int old_len;
02666 unsigned long tv_usec;
02667 int i;
02668
02669 old_len = _dbus_string_get_length (str);
02670
02671
02672 _dbus_verbose ("Falling back to pseudorandom for %d bytes\n",
02673 n_bytes);
02674
02675 _dbus_get_current_time (NULL, &tv_usec);
02676 srand (tv_usec);
02677
02678 i = 0;
02679 while (i < n_bytes)
02680 {
02681 double r;
02682 unsigned int b;
02683
02684 r = rand ();
02685 b = (r / (double) RAND_MAX) * 255.0;
02686
02687 if (!_dbus_string_append_byte (str, b))
02688 goto failed;
02689
02690 ++i;
02691 }
02692
02693 return TRUE;
02694
02695 failed:
02696 _dbus_string_set_length (str, old_len);
02697 return FALSE;
02698 }
02699
02708 dbus_bool_t
02709 _dbus_generate_random_bytes (DBusString *str,
02710 int n_bytes)
02711 {
02712 int old_len;
02713 int fd;
02714
02715
02716
02717
02718
02719
02720
02721 old_len = _dbus_string_get_length (str);
02722 fd = -1;
02723
02724
02725 fd = open ("/dev/urandom", O_RDONLY);
02726 if (fd < 0)
02727 return pseudorandom_generate_random_bytes (str, n_bytes);
02728
02729 if (_dbus_read (fd, str, n_bytes) != n_bytes)
02730 {
02731 close (fd);
02732 _dbus_string_set_length (str, old_len);
02733 return pseudorandom_generate_random_bytes (str, n_bytes);
02734 }
02735
02736 _dbus_verbose ("Read %d bytes from /dev/urandom\n",
02737 n_bytes);
02738
02739 close (fd);
02740
02741 return TRUE;
02742 }
02743
02752 dbus_bool_t
02753 _dbus_generate_random_ascii (DBusString *str,
02754 int n_bytes)
02755 {
02756 static const char letters[] =
02757 "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789abcdefghijklmnopqrstuvwxyz";
02758 int i;
02759 int len;
02760
02761 if (!_dbus_generate_random_bytes (str, n_bytes))
02762 return FALSE;
02763
02764 len = _dbus_string_get_length (str);
02765 i = len - n_bytes;
02766 while (i < len)
02767 {
02768 _dbus_string_set_byte (str, i,
02769 letters[_dbus_string_get_byte (str, i) %
02770 (sizeof (letters) - 1)]);
02771
02772 ++i;
02773 }
02774
02775 _dbus_assert (_dbus_string_validate_ascii (str, len - n_bytes,
02776 n_bytes));
02777
02778 return TRUE;
02779 }
02780
02788 const char*
02789 _dbus_strerror (int error_number)
02790 {
02791 const char *msg;
02792
02793 msg = strerror (error_number);
02794 if (msg == NULL)
02795 msg = "unknown";
02796
02797 return msg;
02798 }
02799
02803 void
02804 _dbus_disable_sigpipe (void)
02805 {
02806 signal (SIGPIPE, SIG_IGN);
02807 }
02808
02816 void
02817 _dbus_fd_set_close_on_exec (int fd)
02818 {
02819 int val;
02820
02821 val = fcntl (fd, F_GETFD, 0);
02822
02823 if (val < 0)
02824 return;
02825
02826 val |= FD_CLOEXEC;
02827
02828 fcntl (fd, F_SETFD, val);
02829 }
02830
02840 const char*
02841 _dbus_error_from_errno (int error_number)
02842 {
02843 switch (error_number)
02844 {
02845 case 0:
02846 return DBUS_ERROR_FAILED;
02847
02848 #ifdef EPROTONOSUPPORT
02849 case EPROTONOSUPPORT:
02850 return DBUS_ERROR_NOT_SUPPORTED;
02851 #endif
02852 #ifdef EAFNOSUPPORT
02853 case EAFNOSUPPORT:
02854 return DBUS_ERROR_NOT_SUPPORTED;
02855 #endif
02856 #ifdef ENFILE
02857 case ENFILE:
02858 return DBUS_ERROR_LIMITS_EXCEEDED;
02859 #endif
02860 #ifdef EMFILE
02861 case EMFILE:
02862 return DBUS_ERROR_LIMITS_EXCEEDED;
02863 #endif
02864 #ifdef EACCES
02865 case EACCES:
02866 return DBUS_ERROR_ACCESS_DENIED;
02867 #endif
02868 #ifdef EPERM
02869 case EPERM:
02870 return DBUS_ERROR_ACCESS_DENIED;
02871 #endif
02872 #ifdef ENOBUFS
02873 case ENOBUFS:
02874 return DBUS_ERROR_NO_MEMORY;
02875 #endif
02876 #ifdef ENOMEM
02877 case ENOMEM:
02878 return DBUS_ERROR_NO_MEMORY;
02879 #endif
02880 #ifdef EINVAL
02881 case EINVAL:
02882 return DBUS_ERROR_FAILED;
02883 #endif
02884 #ifdef EBADF
02885 case EBADF:
02886 return DBUS_ERROR_FAILED;
02887 #endif
02888 #ifdef EFAULT
02889 case EFAULT:
02890 return DBUS_ERROR_FAILED;
02891 #endif
02892 #ifdef ENOTSOCK
02893 case ENOTSOCK:
02894 return DBUS_ERROR_FAILED;
02895 #endif
02896 #ifdef EISCONN
02897 case EISCONN:
02898 return DBUS_ERROR_FAILED;
02899 #endif
02900 #ifdef ECONNREFUSED
02901 case ECONNREFUSED:
02902 return DBUS_ERROR_NO_SERVER;
02903 #endif
02904 #ifdef ETIMEDOUT
02905 case ETIMEDOUT:
02906 return DBUS_ERROR_TIMEOUT;
02907 #endif
02908 #ifdef ENETUNREACH
02909 case ENETUNREACH:
02910 return DBUS_ERROR_NO_NETWORK;
02911 #endif
02912 #ifdef EADDRINUSE
02913 case EADDRINUSE:
02914 return DBUS_ERROR_ADDRESS_IN_USE;
02915 #endif
02916 #ifdef EEXIST
02917 case EEXIST:
02918 return DBUS_ERROR_FILE_NOT_FOUND;
02919 #endif
02920 #ifdef ENOENT
02921 case ENOENT:
02922 return DBUS_ERROR_FILE_NOT_FOUND;
02923 #endif
02924 }
02925
02926 return DBUS_ERROR_FAILED;
02927 }
02928
02934 void
02935 _dbus_exit (int code)
02936 {
02937 _exit (code);
02938 }
02939
02948 dbus_bool_t
02949 _dbus_stat (const DBusString *filename,
02950 DBusStat *statbuf,
02951 DBusError *error)
02952 {
02953 const char *filename_c;
02954 struct stat sb;
02955
02956 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
02957
02958 filename_c = _dbus_string_get_const_data (filename);
02959
02960 if (stat (filename_c, &sb) < 0)
02961 {
02962 dbus_set_error (error, _dbus_error_from_errno (errno),
02963 "%s", _dbus_strerror (errno));
02964 return FALSE;
02965 }
02966
02967 statbuf->mode = sb.st_mode;
02968 statbuf->nlink = sb.st_nlink;
02969 statbuf->uid = sb.st_uid;
02970 statbuf->gid = sb.st_gid;
02971 statbuf->size = sb.st_size;
02972 statbuf->atime = sb.st_atime;
02973 statbuf->mtime = sb.st_mtime;
02974 statbuf->ctime = sb.st_ctime;
02975
02976 return TRUE;
02977 }
02978
02989 dbus_bool_t
02990 _dbus_full_duplex_pipe (int *fd1,
02991 int *fd2,
02992 dbus_bool_t blocking,
02993 DBusError *error)
02994 {
02995 #ifdef HAVE_SOCKETPAIR
02996 int fds[2];
02997
02998 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
02999
03000 if (socketpair (AF_UNIX, SOCK_STREAM, 0, fds) < 0)
03001 {
03002 dbus_set_error (error, _dbus_error_from_errno (errno),
03003 "Could not create full-duplex pipe");
03004 return FALSE;
03005 }
03006
03007 if (!blocking &&
03008 (!_dbus_set_fd_nonblocking (fds[0], NULL) ||
03009 !_dbus_set_fd_nonblocking (fds[1], NULL)))
03010 {
03011 dbus_set_error (error, _dbus_error_from_errno (errno),
03012 "Could not set full-duplex pipe nonblocking");
03013
03014 close (fds[0]);
03015 close (fds[1]);
03016
03017 return FALSE;
03018 }
03019
03020 *fd1 = fds[0];
03021 *fd2 = fds[1];
03022
03023 _dbus_verbose ("full-duplex pipe %d <-> %d\n",
03024 *fd1, *fd2);
03025
03026 return TRUE;
03027 #else
03028 _dbus_warn ("_dbus_full_duplex_pipe() not implemented on this OS\n");
03029 dbus_set_error (error, DBUS_ERROR_FAILED,
03030 "_dbus_full_duplex_pipe() not implemented on this OS");
03031 return FALSE;
03032 #endif
03033 }
03034
03042 dbus_bool_t
03043 _dbus_close (int fd,
03044 DBusError *error)
03045 {
03046 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
03047
03048 again:
03049 if (close (fd) < 0)
03050 {
03051 if (errno == EINTR)
03052 goto again;
03053
03054 dbus_set_error (error, _dbus_error_from_errno (errno),
03055 "Could not close fd %d", fd);
03056 return FALSE;
03057 }
03058
03059 return TRUE;
03060 }
03061
03069 dbus_bool_t
03070 _dbus_set_fd_nonblocking (int fd,
03071 DBusError *error)
03072 {
03073 int val;
03074
03075 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
03076
03077 val = fcntl (fd, F_GETFL, 0);
03078 if (val < 0)
03079 {
03080 dbus_set_error (error, _dbus_error_from_errno (errno),
03081 "Failed to get flags from file descriptor %d: %s",
03082 fd, _dbus_strerror (errno));
03083 _dbus_verbose ("Failed to get flags for fd %d: %s\n", fd,
03084 _dbus_strerror (errno));
03085 return FALSE;
03086 }
03087
03088 if (fcntl (fd, F_SETFL, val | O_NONBLOCK) < 0)
03089 {
03090 dbus_set_error (error, _dbus_error_from_errno (errno),
03091 "Failed to set nonblocking flag of file descriptor %d: %s",
03092 fd, _dbus_strerror (errno));
03093 _dbus_verbose ("Failed to set fd %d nonblocking: %s\n",
03094 fd, _dbus_strerror (errno));
03095
03096 return FALSE;
03097 }
03098
03099 return TRUE;
03100 }
03101
03107 void
03108 _dbus_print_backtrace (void)
03109 {
03110 #if defined (HAVE_BACKTRACE) && defined (DBUS_ENABLE_VERBOSE_MODE)
03111 void *bt[500];
03112 int bt_size;
03113 int i;
03114 char **syms;
03115
03116 bt_size = backtrace (bt, 500);
03117
03118 syms = backtrace_symbols (bt, bt_size);
03119
03120 i = 0;
03121 while (i < bt_size)
03122 {
03123 _dbus_verbose (" %s\n", syms[i]);
03124 ++i;
03125 }
03126
03127 free (syms);
03128 #else
03129 _dbus_verbose (" D-BUS not compiled with backtrace support\n");
03130 #endif
03131 }
03132
03141 dbus_bool_t
03142 _dbus_become_daemon (const DBusString *pidfile,
03143 int print_pid_fd,
03144 DBusError *error)
03145 {
03146 const char *s;
03147 pid_t child_pid;
03148 int dev_null_fd;
03149
03150 _dbus_verbose ("Becoming a daemon...\n");
03151
03152 _dbus_verbose ("chdir to /\n");
03153 if (chdir ("/") < 0)
03154 {
03155 dbus_set_error (error, DBUS_ERROR_FAILED,
03156 "Could not chdir() to root directory");
03157 return FALSE;
03158 }
03159
03160 _dbus_verbose ("forking...\n");
03161 switch ((child_pid = fork ()))
03162 {
03163 case -1:
03164 _dbus_verbose ("fork failed\n");
03165 dbus_set_error (error, _dbus_error_from_errno (errno),
03166 "Failed to fork daemon: %s", _dbus_strerror (errno));
03167 return FALSE;
03168 break;
03169
03170 case 0:
03171 _dbus_verbose ("in child, closing std file descriptors\n");
03172
03173
03174
03175
03176
03177
03178 dev_null_fd = open ("/dev/null", O_RDWR);
03179 if (dev_null_fd >= 0)
03180 {
03181 dup2 (dev_null_fd, 0);
03182 dup2 (dev_null_fd, 1);
03183
03184 s = _dbus_getenv ("DBUS_DEBUG_OUTPUT");
03185 if (s == NULL || *s == '\0')
03186 dup2 (dev_null_fd, 2);
03187 else
03188 _dbus_verbose ("keeping stderr open due to DBUS_DEBUG_OUTPUT\n");
03189 }
03190
03191
03192 _dbus_verbose ("setting umask\n");
03193 umask (022);
03194 break;
03195
03196 default:
03197 if (pidfile)
03198 {
03199 _dbus_verbose ("parent writing pid file\n");
03200 if (!_dbus_write_pid_file (pidfile,
03201 child_pid,
03202 error))
03203 {
03204 _dbus_verbose ("pid file write failed, killing child\n");
03205 kill (child_pid, SIGTERM);
03206 return FALSE;
03207 }
03208 }
03209
03210
03211 if (print_pid_fd >= 0)
03212 {
03213 DBusString pid;
03214 int bytes;
03215
03216 if (!_dbus_string_init (&pid))
03217 {
03218 _DBUS_SET_OOM (error);
03219 kill (child_pid, SIGTERM);
03220 return FALSE;
03221 }
03222
03223 if (!_dbus_string_append_int (&pid, _dbus_getpid ()) ||
03224 !_dbus_string_append (&pid, "\n"))
03225 {
03226 _dbus_string_free (&pid);
03227 _DBUS_SET_OOM (error);
03228 kill (child_pid, SIGTERM);
03229 return FALSE;
03230 }
03231
03232 bytes = _dbus_string_get_length (&pid);
03233 if (_dbus_write (print_pid_fd, &pid, 0, bytes) != bytes)
03234 {
03235 dbus_set_error (error, DBUS_ERROR_FAILED,
03236 "Printing message bus PID: %s\n",
03237 _dbus_strerror (errno));
03238 _dbus_string_free (&pid);
03239 kill (child_pid, SIGTERM);
03240 return FALSE;
03241 }
03242
03243 _dbus_string_free (&pid);
03244 }
03245 _dbus_verbose ("parent exiting\n");
03246 _exit (0);
03247 break;
03248 }
03249
03250 _dbus_verbose ("calling setsid()\n");
03251 if (setsid () == -1)
03252 _dbus_assert_not_reached ("setsid() failed");
03253
03254 return TRUE;
03255 }
03256
03265 dbus_bool_t
03266 _dbus_write_pid_file (const DBusString *filename,
03267 unsigned long pid,
03268 DBusError *error)
03269 {
03270 const char *cfilename;
03271 int fd;
03272 FILE *f;
03273
03274 cfilename = _dbus_string_get_const_data (filename);
03275
03276 fd = open (cfilename, O_WRONLY|O_CREAT|O_EXCL|O_BINARY, 0644);
03277
03278 if (fd < 0)
03279 {
03280 dbus_set_error (error, _dbus_error_from_errno (errno),
03281 "Failed to open \"%s\": %s", cfilename,
03282 _dbus_strerror (errno));
03283 return FALSE;
03284 }
03285
03286 if ((f = fdopen (fd, "w")) == NULL)
03287 {
03288 dbus_set_error (error, _dbus_error_from_errno (errno),
03289 "Failed to fdopen fd %d: %s", fd, _dbus_strerror (errno));
03290 close (fd);
03291 return FALSE;
03292 }
03293
03294 if (fprintf (f, "%lu\n", pid) < 0)
03295 {
03296 dbus_set_error (error, _dbus_error_from_errno (errno),
03297 "Failed to write to \"%s\": %s", cfilename,
03298 _dbus_strerror (errno));
03299 return FALSE;
03300 }
03301
03302 if (fclose (f) == EOF)
03303 {
03304 dbus_set_error (error, _dbus_error_from_errno (errno),
03305 "Failed to close \"%s\": %s", cfilename,
03306 _dbus_strerror (errno));
03307 return FALSE;
03308 }
03309
03310 return TRUE;
03311 }
03312
03321 dbus_bool_t
03322 _dbus_change_identity (dbus_uid_t uid,
03323 dbus_gid_t gid,
03324 DBusError *error)
03325 {
03326
03327
03328
03329
03330
03331
03332 if (setgroups (0, NULL) < 0)
03333 _dbus_warn ("Failed to drop supplementary groups: %s\n",
03334 _dbus_strerror (errno));
03335
03336
03337
03338
03339 if (setgid (gid) < 0)
03340 {
03341 dbus_set_error (error, _dbus_error_from_errno (errno),
03342 "Failed to set GID to %lu: %s", gid,
03343 _dbus_strerror (errno));
03344 return FALSE;
03345 }
03346
03347 if (setuid (uid) < 0)
03348 {
03349 dbus_set_error (error, _dbus_error_from_errno (errno),
03350 "Failed to set UID to %lu: %s", uid,
03351 _dbus_strerror (errno));
03352 return FALSE;
03353 }
03354
03355 return TRUE;
03356 }
03357
03363 void
03364 _dbus_set_signal_handler (int sig,
03365 DBusSignalHandler handler)
03366 {
03367 struct sigaction act;
03368 sigset_t empty_mask;
03369
03370 sigemptyset (&empty_mask);
03371 act.sa_handler = handler;
03372 act.sa_mask = empty_mask;
03373 act.sa_flags = 0;
03374 sigaction (sig, &act, 0);
03375 }
03376
03382 dbus_bool_t
03383 _dbus_file_exists (const char *file)
03384 {
03385 return (access (file, F_OK) == 0);
03386 }
03387
03394 dbus_bool_t
03395 _dbus_user_at_console (const char *username,
03396 DBusError *error)
03397 {
03398
03399 DBusString f;
03400 dbus_bool_t result;
03401
03402 result = FALSE;
03403 if (!_dbus_string_init (&f))
03404 {
03405 _DBUS_SET_OOM (error);
03406 return FALSE;
03407 }
03408
03409 if (!_dbus_string_append (&f, DBUS_CONSOLE_DIR))
03410 {
03411 _DBUS_SET_OOM (error);
03412 goto out;
03413 }
03414
03415
03416 if (!_dbus_string_append (&f, username))
03417 {
03418 _DBUS_SET_OOM (error);
03419 goto out;
03420 }
03421
03422 result = _dbus_file_exists (_dbus_string_get_const_data (&f));
03423
03424 out:
03425 _dbus_string_free (&f);
03426
03427 return result;
03428 }
03429
03430 #ifdef DBUS_BUILD_TESTS
03431 #include <stdlib.h>
03432 static void
03433 check_dirname (const char *filename,
03434 const char *dirname)
03435 {
03436 DBusString f, d;
03437
03438 _dbus_string_init_const (&f, filename);
03439
03440 if (!_dbus_string_init (&d))
03441 _dbus_assert_not_reached ("no memory");
03442
03443 if (!_dbus_string_get_dirname (&f, &d))
03444 _dbus_assert_not_reached ("no memory");
03445
03446 if (!_dbus_string_equal_c_str (&d, dirname))
03447 {
03448 _dbus_warn ("For filename \"%s\" got dirname \"%s\" and expected \"%s\"\n",
03449 filename,
03450 _dbus_string_get_const_data (&d),
03451 dirname);
03452 exit (1);
03453 }
03454
03455 _dbus_string_free (&d);
03456 }
03457
03458 static void
03459 check_path_absolute (const char *path,
03460 dbus_bool_t expected)
03461 {
03462 DBusString p;
03463
03464 _dbus_string_init_const (&p, path);
03465
03466 if (_dbus_path_is_absolute (&p) != expected)
03467 {
03468 _dbus_warn ("For path \"%s\" expected absolute = %d got %d\n",
03469 path, expected, _dbus_path_is_absolute (&p));
03470 exit (1);
03471 }
03472 }
03473
03479 dbus_bool_t
03480 _dbus_sysdeps_test (void)
03481 {
03482 DBusString str;
03483 double val;
03484 int pos;
03485
03486 check_dirname ("foo", ".");
03487 check_dirname ("foo/bar", "foo");
03488 check_dirname ("foo//bar", "foo");
03489 check_dirname ("foo///bar", "foo");
03490 check_dirname ("foo/bar/", "foo");
03491 check_dirname ("foo//bar/", "foo");
03492 check_dirname ("foo///bar/", "foo");
03493 check_dirname ("foo/bar//", "foo");
03494 check_dirname ("foo//bar////", "foo");
03495 check_dirname ("foo///bar///////", "foo");
03496 check_dirname ("/foo", "/");
03497 check_dirname ("
03498 check_dirname ("/foo/bar", "/foo");
03499 check_dirname ("/foo
03500 check_dirname ("/foo///bar", "/foo");
03501 check_dirname ("/", "/");
03502 check_dirname ("
03503 check_dirname ("", ".");
03504
03505
03506 _dbus_string_init_const (&str, "3.5");
03507 if (!_dbus_string_parse_double (&str,
03508 0, &val, &pos))
03509 {
03510 _dbus_warn ("Failed to parse double");
03511 exit (1);
03512 }
03513 if (ABS(3.5 - val) > 1e-6)
03514 {
03515 _dbus_warn ("Failed to parse 3.5 correctly, got: %f", val);
03516 exit (1);
03517 }
03518 if (pos != 3)
03519 {
03520 _dbus_warn ("_dbus_string_parse_double of \"3.5\" returned wrong position %d", pos);
03521 exit (1);
03522 }
03523
03524 _dbus_string_init_const (&str, "0xff");
03525 if (!_dbus_string_parse_double (&str,
03526 0, &val, &pos))
03527 {
03528 _dbus_warn ("Failed to parse double");
03529 exit (1);
03530 }
03531 if (ABS (0xff - val) > 1e-6)
03532 {
03533 _dbus_warn ("Failed to parse 0xff correctly, got: %f\n", val);
03534 exit (1);
03535 }
03536 if (pos != 4)
03537 {
03538 _dbus_warn ("_dbus_string_parse_double of \"0xff\" returned wrong position %d", pos);
03539 exit (1);
03540 }
03541
03542 check_path_absolute ("/", TRUE);
03543 check_path_absolute ("/foo", TRUE);
03544 check_path_absolute ("", FALSE);
03545 check_path_absolute ("foo", FALSE);
03546 check_path_absolute ("foo/bar", FALSE);
03547
03548 return TRUE;
03549 }
03550 #endif
03551