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-test.h"
00029 #include <sys/types.h>
00030 #include <stdlib.h>
00031 #include <string.h>
00032 #include <signal.h>
00033 #include <unistd.h>
00034 #include <stdio.h>
00035 #include <errno.h>
00036 #include <fcntl.h>
00037 #include <sys/socket.h>
00038 #include <dirent.h>
00039 #include <sys/un.h>
00040 #include <pwd.h>
00041 #include <time.h>
00042 #include <locale.h>
00043 #include <sys/time.h>
00044 #include <sys/stat.h>
00045 #include <sys/wait.h>
00046 #include <netinet/in.h>
00047 #include <netdb.h>
00048 #include <grp.h>
00049
00050 #ifdef HAVE_WRITEV
00051 #include <sys/uio.h>
00052 #endif
00053 #ifdef HAVE_POLL
00054 #include <sys/poll.h>
00055 #endif
00056 #ifdef HAVE_BACKTRACE
00057 #include <execinfo.h>
00058 #endif
00059
00060
00061 #ifndef O_BINARY
00062 #define O_BINARY 0
00063 #endif
00064
00065 #ifndef HAVE_SOCKLEN_T
00066 #define socklen_t int
00067 #endif
00068
00076 void
00077 _dbus_abort (void)
00078 {
00079 abort ();
00080 _exit (1);
00081 }
00082
00094 dbus_bool_t
00095 _dbus_setenv (const char *varname,
00096 const char *value)
00097 {
00098 _dbus_assert (varname != NULL);
00099
00100 if (value == NULL)
00101 {
00102 #ifdef HAVE_UNSETENV
00103 unsetenv (varname);
00104 return TRUE;
00105 #else
00106 char *putenv_value;
00107 size_t len;
00108
00109 len = strlen (varname);
00110
00111
00112
00113
00114
00115 putenv_value = malloc (len + 1);
00116 if (putenv_value == NULL)
00117 return FALSE;
00118
00119 strcpy (putenv_value, varname);
00120
00121 return (putenv (putenv_value) == 0);
00122 #endif
00123 }
00124 else
00125 {
00126 #ifdef HAVE_SETENV
00127 return (setenv (varname, value, TRUE) == 0);
00128 #else
00129 char *putenv_value;
00130 size_t len;
00131 size_t varname_len;
00132 size_t value_len;
00133
00134 varname_len = strlen (varname);
00135 value_len = strlen (value);
00136
00137 len = varname_len + value_len + 1 ;
00138
00139
00140
00141
00142
00143 putenv_value = malloc (len + 1);
00144 if (putenv_value == NULL)
00145 return FALSE;
00146
00147 strcpy (putenv_value, varname);
00148 strcpy (putenv_value + varname_len, "=");
00149 strcpy (putenv_value + varname_len + 1, value);
00150
00151 return (putenv (putenv_value) == 0);
00152 #endif
00153 }
00154 }
00155
00162 const char*
00163 _dbus_getenv (const char *varname)
00164 {
00165 return getenv (varname);
00166 }
00167
00181 int
00182 _dbus_read (int fd,
00183 DBusString *buffer,
00184 int count)
00185 {
00186 int bytes_read;
00187 int start;
00188 char *data;
00189
00190 _dbus_assert (count >= 0);
00191
00192 start = _dbus_string_get_length (buffer);
00193
00194 if (!_dbus_string_lengthen (buffer, count))
00195 {
00196 errno = ENOMEM;
00197 return -1;
00198 }
00199
00200 data = _dbus_string_get_data_len (buffer, start, count);
00201
00202 again:
00203
00204 bytes_read = read (fd, data, count);
00205
00206 if (bytes_read < 0)
00207 {
00208 if (errno == EINTR)
00209 goto again;
00210 else
00211 {
00212
00213 _dbus_string_set_length (buffer, start);
00214 return -1;
00215 }
00216 }
00217 else
00218 {
00219
00220 _dbus_string_set_length (buffer, start + bytes_read);
00221
00222 #if 0
00223 if (bytes_read > 0)
00224 _dbus_verbose_bytes_of_string (buffer, start, bytes_read);
00225 #endif
00226
00227 return bytes_read;
00228 }
00229 }
00230
00241 int
00242 _dbus_write (int fd,
00243 const DBusString *buffer,
00244 int start,
00245 int len)
00246 {
00247 const char *data;
00248 int bytes_written;
00249
00250 data = _dbus_string_get_const_data_len (buffer, start, len);
00251
00252 again:
00253
00254 bytes_written = write (fd, data, len);
00255
00256 if (bytes_written < 0 && errno == EINTR)
00257 goto again;
00258
00259 #if 0
00260 if (bytes_written > 0)
00261 _dbus_verbose_bytes_of_string (buffer, start, bytes_written);
00262 #endif
00263
00264 return bytes_written;
00265 }
00266
00287 int
00288 _dbus_write_two (int fd,
00289 const DBusString *buffer1,
00290 int start1,
00291 int len1,
00292 const DBusString *buffer2,
00293 int start2,
00294 int len2)
00295 {
00296 _dbus_assert (buffer1 != NULL);
00297 _dbus_assert (start1 >= 0);
00298 _dbus_assert (start2 >= 0);
00299 _dbus_assert (len1 >= 0);
00300 _dbus_assert (len2 >= 0);
00301
00302 #ifdef HAVE_WRITEV
00303 {
00304 struct iovec vectors[2];
00305 const char *data1;
00306 const char *data2;
00307 int bytes_written;
00308
00309 data1 = _dbus_string_get_const_data_len (buffer1, start1, len1);
00310
00311 if (buffer2 != NULL)
00312 data2 = _dbus_string_get_const_data_len (buffer2, start2, len2);
00313 else
00314 {
00315 data2 = NULL;
00316 start2 = 0;
00317 len2 = 0;
00318 }
00319
00320 vectors[0].iov_base = (char*) data1;
00321 vectors[0].iov_len = len1;
00322 vectors[1].iov_base = (char*) data2;
00323 vectors[1].iov_len = len2;
00324
00325 again:
00326
00327 bytes_written = writev (fd,
00328 vectors,
00329 data2 ? 2 : 1);
00330
00331 if (bytes_written < 0 && errno == EINTR)
00332 goto again;
00333
00334 return bytes_written;
00335 }
00336 #else
00337 {
00338 int ret1;
00339
00340 ret1 = _dbus_write (fd, buffer1, start1, len1);
00341 if (ret1 == len1 && buffer2 != NULL)
00342 {
00343 ret2 = _dbus_write (fd, buffer2, start2, len2);
00344 if (ret2 < 0)
00345 ret2 = 0;
00346
00347 return ret1 + ret2;
00348 }
00349 else
00350 return ret1;
00351 }
00352 #endif
00353 }
00354
00355 #define _DBUS_MAX_SUN_PATH_LENGTH 99
00356
00384 int
00385 _dbus_connect_unix_socket (const char *path,
00386 dbus_bool_t abstract,
00387 DBusError *error)
00388 {
00389 int fd;
00390 struct sockaddr_un addr;
00391
00392 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
00393
00394 _dbus_verbose ("connecting to unix socket %s abstract=%d\n",
00395 path, abstract);
00396
00397 fd = socket (PF_UNIX, SOCK_STREAM, 0);
00398
00399 if (fd < 0)
00400 {
00401 dbus_set_error (error,
00402 _dbus_error_from_errno (errno),
00403 "Failed to create socket: %s",
00404 _dbus_strerror (errno));
00405
00406 return -1;
00407 }
00408
00409 _DBUS_ZERO (addr);
00410 addr.sun_family = AF_UNIX;
00411
00412 if (abstract)
00413 {
00414 #ifdef HAVE_ABSTRACT_SOCKETS
00415
00416
00417
00418 addr.sun_path[0] = '\0';
00419 strncpy (&addr.sun_path[1], path, _DBUS_MAX_SUN_PATH_LENGTH - 2);
00420
00421 #else
00422 dbus_set_error (error, DBUS_ERROR_NOT_SUPPORTED,
00423 "Operating system does not support abstract socket namespace\n");
00424 close (fd);
00425 return -1;
00426 #endif
00427 }
00428 else
00429 {
00430 strncpy (addr.sun_path, path, _DBUS_MAX_SUN_PATH_LENGTH - 1);
00431 }
00432
00433 if (connect (fd, (struct sockaddr*) &addr, sizeof (addr)) < 0)
00434 {
00435 dbus_set_error (error,
00436 _dbus_error_from_errno (errno),
00437 "Failed to connect to socket %s: %s",
00438 path, _dbus_strerror (errno));
00439
00440 close (fd);
00441 fd = -1;
00442
00443 return -1;
00444 }
00445
00446 if (!_dbus_set_fd_nonblocking (fd, error))
00447 {
00448 _DBUS_ASSERT_ERROR_IS_SET (error);
00449
00450 close (fd);
00451 fd = -1;
00452
00453 return -1;
00454 }
00455
00456 return fd;
00457 }
00458
00474 int
00475 _dbus_listen_unix_socket (const char *path,
00476 dbus_bool_t abstract,
00477 DBusError *error)
00478 {
00479 int listen_fd;
00480 struct sockaddr_un addr;
00481
00482 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
00483
00484 _dbus_verbose ("listening on unix socket %s abstract=%d\n",
00485 path, abstract);
00486
00487 listen_fd = socket (PF_UNIX, SOCK_STREAM, 0);
00488
00489 if (listen_fd < 0)
00490 {
00491 dbus_set_error (error, _dbus_error_from_errno (errno),
00492 "Failed to create socket \"%s\": %s",
00493 path, _dbus_strerror (errno));
00494 return -1;
00495 }
00496
00497 _DBUS_ZERO (addr);
00498 addr.sun_family = AF_UNIX;
00499
00500 if (abstract)
00501 {
00502 #ifdef HAVE_ABSTRACT_SOCKETS
00503
00504
00505
00506 addr.sun_path[0] = '\0';
00507 strncpy (&addr.sun_path[1], path, _DBUS_MAX_SUN_PATH_LENGTH - 2);
00508
00509 #else
00510 dbus_set_error (error, DBUS_ERROR_NOT_SUPPORTED,
00511 "Operating system does not support abstract socket namespace\n");
00512 close (listen_fd);
00513 return -1;
00514 #endif
00515 }
00516 else
00517 {
00518
00519
00520
00521
00522
00523
00524
00525
00526
00527
00528 {
00529 struct stat sb;
00530
00531 if (stat (path, &sb) == 0 &&
00532 S_ISSOCK (sb.st_mode))
00533 unlink (path);
00534 }
00535
00536 strncpy (addr.sun_path, path, _DBUS_MAX_SUN_PATH_LENGTH - 1);
00537 }
00538
00539 if (bind (listen_fd, (struct sockaddr*) &addr, sizeof (addr)) < 0)
00540 {
00541 dbus_set_error (error, _dbus_error_from_errno (errno),
00542 "Failed to bind socket \"%s\": %s",
00543 path, _dbus_strerror (errno));
00544 close (listen_fd);
00545 return -1;
00546 }
00547
00548 if (listen (listen_fd, 30 ) < 0)
00549 {
00550 dbus_set_error (error, _dbus_error_from_errno (errno),
00551 "Failed to listen on socket \"%s\": %s",
00552 path, _dbus_strerror (errno));
00553 close (listen_fd);
00554 return -1;
00555 }
00556
00557 if (!_dbus_set_fd_nonblocking (listen_fd, error))
00558 {
00559 _DBUS_ASSERT_ERROR_IS_SET (error);
00560 close (listen_fd);
00561 return -1;
00562 }
00563
00564
00565
00566
00567 if (!abstract && chmod (path, 0777) < 0)
00568 _dbus_warn ("Could not set mode 0777 on socket %s\n",
00569 path);
00570
00571 return listen_fd;
00572 }
00573
00584 int
00585 _dbus_connect_tcp_socket (const char *host,
00586 dbus_uint32_t port,
00587 DBusError *error)
00588 {
00589 int fd;
00590 struct sockaddr_in addr;
00591 struct hostent *he;
00592 struct in_addr *haddr;
00593
00594 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
00595
00596 fd = socket (AF_INET, SOCK_STREAM, 0);
00597
00598 if (fd < 0)
00599 {
00600 dbus_set_error (error,
00601 _dbus_error_from_errno (errno),
00602 "Failed to create socket: %s",
00603 _dbus_strerror (errno));
00604
00605 return -1;
00606 }
00607
00608 if (host == NULL)
00609 host = "localhost";
00610
00611 he = gethostbyname (host);
00612 if (he == NULL)
00613 {
00614 dbus_set_error (error,
00615 _dbus_error_from_errno (errno),
00616 "Failed to lookup hostname: %s",
00617 host);
00618 return -1;
00619 }
00620
00621 haddr = ((struct in_addr *) (he->h_addr_list)[0]);
00622
00623 _DBUS_ZERO (addr);
00624 memcpy (&addr.sin_addr, haddr, sizeof(struct in_addr));
00625 addr.sin_family = AF_INET;
00626 addr.sin_port = htons (port);
00627
00628 if (connect (fd, (struct sockaddr*) &addr, sizeof (addr)) < 0)
00629 {
00630 dbus_set_error (error,
00631 _dbus_error_from_errno (errno),
00632 "Failed to connect to socket %s: %s:%d",
00633 host, _dbus_strerror (errno), port);
00634
00635 close (fd);
00636 fd = -1;
00637
00638 return -1;
00639 }
00640
00641 if (!_dbus_set_fd_nonblocking (fd, error))
00642 {
00643 close (fd);
00644 fd = -1;
00645
00646 return -1;
00647 }
00648
00649 return fd;
00650 }
00651
00662 int
00663 _dbus_listen_tcp_socket (const char *host,
00664 dbus_uint32_t port,
00665 DBusError *error)
00666 {
00667 int listen_fd;
00668 struct sockaddr_in addr;
00669 struct hostent *he;
00670 struct in_addr *haddr;
00671
00672 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
00673
00674 listen_fd = socket (AF_INET, SOCK_STREAM, 0);
00675
00676 if (listen_fd < 0)
00677 {
00678 dbus_set_error (error, _dbus_error_from_errno (errno),
00679 "Failed to create socket \"%s:%d\": %s",
00680 host, port, _dbus_strerror (errno));
00681 return -1;
00682 }
00683
00684 if (host == NULL)
00685 host = "localhost";
00686
00687 he = gethostbyname (host);
00688 if (he == NULL)
00689 {
00690 dbus_set_error (error,
00691 _dbus_error_from_errno (errno),
00692 "Failed to lookup hostname: %s",
00693 host);
00694 return -1;
00695 }
00696
00697 haddr = ((struct in_addr *) (he->h_addr_list)[0]);
00698
00699 _DBUS_ZERO (addr);
00700 memcpy (&addr.sin_addr, haddr, sizeof (struct in_addr));
00701 addr.sin_family = AF_INET;
00702 addr.sin_port = htons (port);
00703
00704 if (bind (listen_fd, (struct sockaddr*) &addr, sizeof (struct sockaddr)))
00705 {
00706 dbus_set_error (error, _dbus_error_from_errno (errno),
00707 "Failed to bind socket \"%s:%d\": %s",
00708 host, port, _dbus_strerror (errno));
00709 close (listen_fd);
00710 return -1;
00711 }
00712
00713 if (listen (listen_fd, 30 ) < 0)
00714 {
00715 dbus_set_error (error, _dbus_error_from_errno (errno),
00716 "Failed to listen on socket \"%s:%d\": %s",
00717 host, port, _dbus_strerror (errno));
00718 close (listen_fd);
00719 return -1;
00720 }
00721
00722 if (!_dbus_set_fd_nonblocking (listen_fd, error))
00723 {
00724 close (listen_fd);
00725 return -1;
00726 }
00727
00728 return listen_fd;
00729 }
00730
00731 static dbus_bool_t
00732 write_credentials_byte (int server_fd,
00733 DBusError *error)
00734 {
00735 int bytes_written;
00736 char buf[1] = { '\0' };
00737
00738 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
00739
00740 again:
00741
00742 bytes_written = write (server_fd, buf, 1);
00743
00744 if (bytes_written < 0 && errno == EINTR)
00745 goto again;
00746
00747 if (bytes_written < 0)
00748 {
00749 dbus_set_error (error, _dbus_error_from_errno (errno),
00750 "Failed to write credentials byte: %s",
00751 _dbus_strerror (errno));
00752 return FALSE;
00753 }
00754 else if (bytes_written == 0)
00755 {
00756 dbus_set_error (error, DBUS_ERROR_IO_ERROR,
00757 "wrote zero bytes writing credentials byte");
00758 return FALSE;
00759 }
00760 else
00761 {
00762 _dbus_assert (bytes_written == 1);
00763 _dbus_verbose ("wrote credentials byte\n");
00764 return TRUE;
00765 }
00766 }
00767
00786 dbus_bool_t
00787 _dbus_read_credentials_unix_socket (int client_fd,
00788 DBusCredentials *credentials,
00789 DBusError *error)
00790 {
00791 struct msghdr msg;
00792 struct iovec iov;
00793 char buf;
00794
00795 #ifdef HAVE_CMSGCRED
00796 char cmsgmem[CMSG_SPACE (sizeof (struct cmsgcred))];
00797 struct cmsghdr *cmsg = (struct cmsghdr *) cmsgmem;
00798 #endif
00799
00800 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
00801
00802
00803
00804
00805
00806 _dbus_assert (sizeof (pid_t) <= sizeof (credentials->pid));
00807 _dbus_assert (sizeof (uid_t) <= sizeof (credentials->uid));
00808 _dbus_assert (sizeof (gid_t) <= sizeof (credentials->gid));
00809
00810 _dbus_credentials_clear (credentials);
00811
00812 #if defined(LOCAL_CREDS) && defined(HAVE_CMSGCRED)
00813
00814 {
00815 int on = 1;
00816 if (setsockopt (client_fd, 0, LOCAL_CREDS, &on, sizeof (on)) < 0)
00817 {
00818 _dbus_verbose ("Unable to set LOCAL_CREDS socket option\n");
00819 return FALSE;
00820 }
00821 }
00822 #endif
00823
00824 iov.iov_base = &buf;
00825 iov.iov_len = 1;
00826
00827 memset (&msg, 0, sizeof (msg));
00828 msg.msg_iov = &iov;
00829 msg.msg_iovlen = 1;
00830
00831 #ifdef HAVE_CMSGCRED
00832 memset (cmsgmem, 0, sizeof (cmsgmem));
00833 msg.msg_control = cmsgmem;
00834 msg.msg_controllen = sizeof (cmsgmem);
00835 #endif
00836
00837 again:
00838 if (recvmsg (client_fd, &msg, 0) < 0)
00839 {
00840 if (errno == EINTR)
00841 goto again;
00842
00843 dbus_set_error (error, _dbus_error_from_errno (errno),
00844 "Failed to read credentials byte: %s",
00845 _dbus_strerror (errno));
00846 return FALSE;
00847 }
00848
00849 if (buf != '\0')
00850 {
00851 dbus_set_error (error, DBUS_ERROR_FAILED,
00852 "Credentials byte was not nul");
00853 return FALSE;
00854 }
00855
00856 #ifdef HAVE_CMSGCRED
00857 if (cmsg->cmsg_len < sizeof (cmsgmem) || cmsg->cmsg_type != SCM_CREDS)
00858 {
00859 dbus_set_error (error, DBUS_ERROR_FAILED);
00860 _dbus_verbose ("Message from recvmsg() was not SCM_CREDS\n");
00861 return FALSE;
00862 }
00863 #endif
00864
00865 _dbus_verbose ("read credentials byte\n");
00866
00867 {
00868 #ifdef SO_PEERCRED
00869 struct ucred cr;
00870 int cr_len = sizeof (cr);
00871
00872 if (getsockopt (client_fd, SOL_SOCKET, SO_PEERCRED, &cr, &cr_len) == 0 &&
00873 cr_len == sizeof (cr))
00874 {
00875 credentials->pid = cr.pid;
00876 credentials->uid = cr.uid;
00877 credentials->gid = cr.gid;
00878 }
00879 else
00880 {
00881 _dbus_verbose ("Failed to getsockopt() credentials, returned len %d/%d: %s\n",
00882 cr_len, (int) sizeof (cr), _dbus_strerror (errno));
00883 }
00884 #elif defined(HAVE_CMSGCRED)
00885 struct cmsgcred *cred;
00886
00887 cred = (struct cmsgcred *) CMSG_DATA (cmsg);
00888
00889 credentials->pid = cred->cmcred_pid;
00890 credentials->uid = cred->cmcred_euid;
00891 credentials->gid = cred->cmcred_groups[0];
00892 #else
00893 _dbus_verbose ("Socket credentials not supported on this OS\n");
00894 #endif
00895 }
00896
00897 _dbus_verbose ("Credentials:"
00898 " pid "DBUS_PID_FORMAT
00899 " uid "DBUS_UID_FORMAT
00900 " gid "DBUS_GID_FORMAT"\n",
00901 credentials->pid,
00902 credentials->uid,
00903 credentials->gid);
00904
00905 return TRUE;
00906 }
00907
00925 dbus_bool_t
00926 _dbus_send_credentials_unix_socket (int server_fd,
00927 DBusError *error)
00928 {
00929 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
00930
00931 if (write_credentials_byte (server_fd, error))
00932 return TRUE;
00933 else
00934 return FALSE;
00935 }
00936
00944 int
00945 _dbus_accept (int listen_fd)
00946 {
00947 int client_fd;
00948 struct sockaddr addr;
00949 socklen_t addrlen;
00950
00951 addrlen = sizeof (addr);
00952
00953 retry:
00954 client_fd = accept (listen_fd, &addr, &addrlen);
00955
00956 if (client_fd < 0)
00957 {
00958 if (errno == EINTR)
00959 goto retry;
00960 }
00961
00962 return client_fd;
00963 }
00964
00979 dbus_bool_t
00980 _dbus_string_append_int (DBusString *str,
00981 long value)
00982 {
00983
00984 #define MAX_LONG_LEN ((sizeof (long) * 8 + 2) / 3 + 1)
00985 int orig_len;
00986 int i;
00987 char *buf;
00988
00989 orig_len = _dbus_string_get_length (str);
00990
00991 if (!_dbus_string_lengthen (str, MAX_LONG_LEN))
00992 return FALSE;
00993
00994 buf = _dbus_string_get_data_len (str, orig_len, MAX_LONG_LEN);
00995
00996 snprintf (buf, MAX_LONG_LEN, "%ld", value);
00997
00998 i = 0;
00999 while (*buf)
01000 {
01001 ++buf;
01002 ++i;
01003 }
01004
01005 _dbus_string_shorten (str, MAX_LONG_LEN - i);
01006
01007 return TRUE;
01008 }
01009
01017 dbus_bool_t
01018 _dbus_string_append_uint (DBusString *str,
01019 unsigned long value)
01020 {
01021
01022 #define MAX_ULONG_LEN (MAX_LONG_LEN * 2)
01023 int orig_len;
01024 int i;
01025 char *buf;
01026
01027 orig_len = _dbus_string_get_length (str);
01028
01029 if (!_dbus_string_lengthen (str, MAX_ULONG_LEN))
01030 return FALSE;
01031
01032 buf = _dbus_string_get_data_len (str, orig_len, MAX_ULONG_LEN);
01033
01034 snprintf (buf, MAX_ULONG_LEN, "%lu", value);
01035
01036 i = 0;
01037 while (*buf)
01038 {
01039 ++buf;
01040 ++i;
01041 }
01042
01043 _dbus_string_shorten (str, MAX_ULONG_LEN - i);
01044
01045 return TRUE;
01046 }
01047
01055 dbus_bool_t
01056 _dbus_string_append_double (DBusString *str,
01057 double value)
01058 {
01059 #define MAX_DOUBLE_LEN 64
01060 int orig_len;
01061 char *buf;
01062 int i;
01063
01064 orig_len = _dbus_string_get_length (str);
01065
01066 if (!_dbus_string_lengthen (str, MAX_DOUBLE_LEN))
01067 return FALSE;
01068
01069 buf = _dbus_string_get_data_len (str, orig_len, MAX_DOUBLE_LEN);
01070
01071 snprintf (buf, MAX_LONG_LEN, "%g", value);
01072
01073 i = 0;
01074 while (*buf)
01075 {
01076 ++buf;
01077 ++i;
01078 }
01079
01080 _dbus_string_shorten (str, MAX_DOUBLE_LEN - i);
01081
01082 return TRUE;
01083 }
01084
01097 dbus_bool_t
01098 _dbus_string_parse_int (const DBusString *str,
01099 int start,
01100 long *value_return,
01101 int *end_return)
01102 {
01103 long v;
01104 const char *p;
01105 char *end;
01106
01107 p = _dbus_string_get_const_data_len (str, start,
01108 _dbus_string_get_length (str) - start);
01109
01110 end = NULL;
01111 errno = 0;
01112 v = strtol (p, &end, 0);
01113 if (end == NULL || end == p || errno != 0)
01114 return FALSE;
01115
01116 if (value_return)
01117 *value_return = v;
01118 if (end_return)
01119 *end_return = start + (end - p);
01120
01121 return TRUE;
01122 }
01123
01124 #ifdef DBUS_BUILD_TESTS
01125
01138 dbus_bool_t
01139 _dbus_string_parse_uint (const DBusString *str,
01140 int start,
01141 unsigned long *value_return,
01142 int *end_return)
01143 {
01144 unsigned long v;
01145 const char *p;
01146 char *end;
01147
01148 p = _dbus_string_get_const_data_len (str, start,
01149 _dbus_string_get_length (str) - start);
01150
01151 end = NULL;
01152 errno = 0;
01153 v = strtoul (p, &end, 0);
01154 if (end == NULL || end == p || errno != 0)
01155 return FALSE;
01156
01157 if (value_return)
01158 *value_return = v;
01159 if (end_return)
01160 *end_return = start + (end - p);
01161
01162 return TRUE;
01163 }
01164 #endif
01165
01166 static dbus_bool_t
01167 ascii_isspace (char c)
01168 {
01169 return (c == ' ' ||
01170 c == '\f' ||
01171 c == '\n' ||
01172 c == '\r' ||
01173 c == '\t' ||
01174 c == '\v');
01175 }
01176
01177 static dbus_bool_t
01178 ascii_isdigit (char c)
01179 {
01180 return c >= '0' && c <= '9';
01181 }
01182
01183 static dbus_bool_t
01184 ascii_isxdigit (char c)
01185 {
01186 return (ascii_isdigit (c) ||
01187 (c >= 'a' && c <= 'f') ||
01188 (c >= 'A' && c <= 'F'));
01189 }
01190
01191
01192
01193
01194
01195
01196
01197 static double
01198 ascii_strtod (const char *nptr,
01199 char **endptr)
01200 {
01201 char *fail_pos;
01202 double val;
01203 struct lconv *locale_data;
01204 const char *decimal_point;
01205 int decimal_point_len;
01206 const char *p, *decimal_point_pos;
01207 const char *end = NULL;
01208
01209 fail_pos = NULL;
01210
01211 locale_data = localeconv ();
01212 decimal_point = locale_data->decimal_point;
01213 decimal_point_len = strlen (decimal_point);
01214
01215 _dbus_assert (decimal_point_len != 0);
01216
01217 decimal_point_pos = NULL;
01218 if (decimal_point[0] != '.' ||
01219 decimal_point[1] != 0)
01220 {
01221 p = nptr;
01222
01223 while (ascii_isspace (*p))
01224 p++;
01225
01226
01227 if (*p == '+' || *p == '-')
01228 p++;
01229
01230 if (p[0] == '0' &&
01231 (p[1] == 'x' || p[1] == 'X'))
01232 {
01233 p += 2;
01234
01235
01236 while (ascii_isxdigit (*p))
01237 p++;
01238
01239 if (*p == '.')
01240 {
01241 decimal_point_pos = p++;
01242
01243 while (ascii_isxdigit (*p))
01244 p++;
01245
01246 if (*p == 'p' || *p == 'P')
01247 p++;
01248 if (*p == '+' || *p == '-')
01249 p++;
01250 while (ascii_isdigit (*p))
01251 p++;
01252 end = p;
01253 }
01254 }
01255 else
01256 {
01257 while (ascii_isdigit (*p))
01258 p++;
01259
01260 if (*p == '.')
01261 {
01262 decimal_point_pos = p++;
01263
01264 while (ascii_isdigit (*p))
01265 p++;
01266
01267 if (*p == 'e' || *p == 'E')
01268 p++;
01269 if (*p == '+' || *p == '-')
01270 p++;
01271 while (ascii_isdigit (*p))
01272 p++;
01273 end = p;
01274 }
01275 }
01276
01277 }
01278
01279
01280
01281 errno = 0;
01282
01283 if (decimal_point_pos)
01284 {
01285 char *copy, *c;
01286
01287
01288 copy = dbus_malloc (end - nptr + 1 + decimal_point_len);
01289
01290 c = copy;
01291 memcpy (c, nptr, decimal_point_pos - nptr);
01292 c += decimal_point_pos - nptr;
01293 memcpy (c, decimal_point, decimal_point_len);
01294 c += decimal_point_len;
01295 memcpy (c, decimal_point_pos + 1, end - (decimal_point_pos + 1));
01296 c += end - (decimal_point_pos + 1);
01297 *c = 0;
01298
01299 val = strtod (copy, &fail_pos);
01300
01301 if (fail_pos)
01302 {
01303 if (fail_pos > decimal_point_pos)
01304 fail_pos = (char *)nptr + (fail_pos - copy) - (decimal_point_len - 1);
01305 else
01306 fail_pos = (char *)nptr + (fail_pos - copy);
01307 }
01308
01309 dbus_free (copy);
01310
01311 }
01312 else
01313 val = strtod (nptr, &fail_pos);
01314
01315 if (endptr)
01316 *endptr = fail_pos;
01317
01318 return val;
01319 }
01320
01321
01334 dbus_bool_t
01335 _dbus_string_parse_double (const DBusString *str,
01336 int start,
01337 double *value_return,
01338 int *end_return)
01339 {
01340 double v;
01341 const char *p;
01342 char *end;
01343
01344 p = _dbus_string_get_const_data_len (str, start,
01345 _dbus_string_get_length (str) - start);
01346
01347 end = NULL;
01348 errno = 0;
01349 v = ascii_strtod (p, &end);
01350 if (end == NULL || end == p || errno != 0)
01351 return FALSE;
01352
01353 if (value_return)
01354 *value_return = v;
01355 if (end_return)
01356 *end_return = start + (end - p);
01357
01358 return TRUE;
01359 }
01360
01362
01367 static dbus_bool_t
01368 fill_user_info_from_passwd (struct passwd *p,
01369 DBusUserInfo *info,
01370 DBusError *error)
01371 {
01372 _dbus_assert (p->pw_name != NULL);
01373 _dbus_assert (p->pw_dir != NULL);
01374
01375 info->uid = p->pw_uid;
01376 info->primary_gid = p->pw_gid;
01377 info->username = _dbus_strdup (p->pw_name);
01378 info->homedir = _dbus_strdup (p->pw_dir);
01379
01380 if (info->username == NULL ||
01381 info->homedir == NULL)
01382 {
01383 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
01384 return FALSE;
01385 }
01386
01387 return TRUE;
01388 }
01389
01390 static dbus_bool_t
01391 fill_user_info (DBusUserInfo *info,
01392 dbus_uid_t uid,
01393 const DBusString *username,
01394 DBusError *error)
01395 {
01396 const char *username_c;
01397
01398
01399 _dbus_assert (username != NULL || uid != DBUS_UID_UNSET);
01400 _dbus_assert (username == NULL || uid == DBUS_UID_UNSET);
01401
01402 info->uid = DBUS_UID_UNSET;
01403 info->primary_gid = DBUS_GID_UNSET;
01404 info->group_ids = NULL;
01405 info->n_group_ids = 0;
01406 info->username = NULL;
01407 info->homedir = NULL;
01408
01409 if (username != NULL)
01410 username_c = _dbus_string_get_const_data (username);
01411 else
01412 username_c = NULL;
01413
01414
01415
01416
01417
01418
01419 #if defined (HAVE_POSIX_GETPWNAME_R) || defined (HAVE_NONPOSIX_GETPWNAME_R)
01420 {
01421 struct passwd *p;
01422 int result;
01423 char buf[1024];
01424 struct passwd p_str;
01425
01426 p = NULL;
01427 #ifdef HAVE_POSIX_GETPWNAME_R
01428 if (uid >= 0)
01429 result = getpwuid_r (uid, &p_str, buf, sizeof (buf),
01430 &p);
01431 else
01432 result = getpwnam_r (username_c, &p_str, buf, sizeof (buf),
01433 &p);
01434 #else
01435 if (uid != DBUS_UID_UNSET)
01436 p = getpwuid_r (uid, &p_str, buf, sizeof (buf));
01437 else
01438 p = getpwnam_r (username_c, &p_str, buf, sizeof (buf));
01439 result = 0;
01440 #endif
01441 if (result == 0 && p == &p_str)
01442 {
01443 if (!fill_user_info_from_passwd (p, info, error))
01444 return FALSE;
01445 }
01446 else
01447 {
01448 dbus_set_error (error, _dbus_error_from_errno (errno),
01449 "User \"%s\" unknown or no memory to allocate password entry\n",
01450 username_c ? username_c : "???");
01451 _dbus_verbose ("User %s unknown\n", username_c ? username_c : "???");
01452 return FALSE;
01453 }
01454 }
01455 #else
01456 {
01457
01458 struct passwd *p;
01459
01460 if (uid != DBUS_UID_UNSET)
01461 p = getpwuid (uid);
01462 else
01463 p = getpwnam (username_c);
01464
01465 if (p != NULL)
01466 {
01467 if (!fill_user_info_from_passwd (p, info, error))
01468 return FALSE;
01469 }
01470 else
01471 {
01472 dbus_set_error (error, _dbus_error_from_errno (errno),
01473 "User \"%s\" unknown or no memory to allocate password entry\n",
01474 username_c ? username_c : "???");
01475 _dbus_verbose ("User %s unknown\n", username_c ? username_c : "???");
01476 return FALSE;
01477 }
01478 }
01479 #endif
01480
01481
01482 username_c = info->username;
01483
01484 #ifdef HAVE_GETGROUPLIST
01485 {
01486 gid_t *buf;
01487 int buf_count;
01488 int i;
01489
01490 buf_count = 17;
01491 buf = dbus_new (gid_t, buf_count);
01492 if (buf == NULL)
01493 {
01494 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
01495 goto failed;
01496 }
01497
01498 if (getgrouplist (username_c,
01499 info->primary_gid,
01500 buf, &buf_count) < 0)
01501 {
01502 gid_t *new = dbus_realloc (buf, buf_count * sizeof (buf[0]));
01503 if (new == NULL)
01504 {
01505 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
01506 dbus_free (buf);
01507 goto failed;
01508 }
01509
01510 buf = new;
01511
01512 errno = 0;
01513 if (getgrouplist (username_c, info->primary_gid, buf, &buf_count) < 0)
01514 {
01515 dbus_set_error (error,
01516 _dbus_error_from_errno (errno),
01517 "Failed to get groups for username \"%s\" primary GID "
01518 DBUS_GID_FORMAT ": %s\n",
01519 username_c, info->primary_gid,
01520 _dbus_strerror (errno));
01521 dbus_free (buf);
01522 goto failed;
01523 }
01524 }
01525
01526 info->group_ids = dbus_new (dbus_gid_t, buf_count);
01527 if (info->group_ids == NULL)
01528 {
01529 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
01530 dbus_free (buf);
01531 goto failed;
01532 }
01533
01534 for (i = 0; i < buf_count; ++i)
01535 info->group_ids[i] = buf[i];
01536
01537 info->n_group_ids = buf_count;
01538
01539 dbus_free (buf);
01540 }
01541 #else
01542 {
01543
01544 info->group_ids = dbus_new (dbus_gid_t, 1);
01545 if (info->group_ids == NULL)
01546 {
01547 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
01548 goto out;
01549 }
01550
01551 info->n_group_ids = 1;
01552
01553 (info->group_ids)[0] = info->primary_gid;
01554 }
01555 #endif
01556
01557 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
01558
01559 return TRUE;
01560
01561 failed:
01562 _DBUS_ASSERT_ERROR_IS_SET (error);
01563 _dbus_user_info_free (info);
01564 return FALSE;
01565 }
01566
01575 dbus_bool_t
01576 _dbus_user_info_fill (DBusUserInfo *info,
01577 const DBusString *username,
01578 DBusError *error)
01579 {
01580 return fill_user_info (info, DBUS_UID_UNSET,
01581 username, error);
01582 }
01583
01592 dbus_bool_t
01593 _dbus_user_info_fill_uid (DBusUserInfo *info,
01594 dbus_uid_t uid,
01595 DBusError *error)
01596 {
01597 return fill_user_info (info, uid,
01598 NULL, error);
01599 }
01600
01606 void
01607 _dbus_user_info_free (DBusUserInfo *info)
01608 {
01609 dbus_free (info->group_ids);
01610 dbus_free (info->username);
01611 dbus_free (info->homedir);
01612 }
01613
01614 static dbus_bool_t
01615 fill_user_info_from_group (struct group *g,
01616 DBusGroupInfo *info,
01617 DBusError *error)
01618 {
01619 _dbus_assert (g->gr_name != NULL);
01620
01621 info->gid = g->gr_gid;
01622 info->groupname = _dbus_strdup (g->gr_name);
01623
01624
01625
01626 if (info->groupname == NULL)
01627 {
01628 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
01629 return FALSE;
01630 }
01631
01632 return TRUE;
01633 }
01634
01635 static dbus_bool_t
01636 fill_group_info (DBusGroupInfo *info,
01637 dbus_gid_t gid,
01638 const DBusString *groupname,
01639 DBusError *error)
01640 {
01641 const char *group_c_str;
01642
01643 _dbus_assert (groupname != NULL || gid != DBUS_GID_UNSET);
01644 _dbus_assert (groupname == NULL || gid == DBUS_GID_UNSET);
01645
01646 if (groupname)
01647 group_c_str = _dbus_string_get_const_data (groupname);
01648 else
01649 group_c_str = NULL;
01650
01651
01652
01653
01654
01655
01656 #if defined (HAVE_POSIX_GETPWNAME_R) || defined (HAVE_NONPOSIX_GETPWNAME_R)
01657 {
01658 struct group *g;
01659 int result;
01660 char buf[1024];
01661 struct group g_str;
01662
01663 g = NULL;
01664 #ifdef HAVE_POSIX_GETPWNAME_R
01665
01666 if (group_c_str)
01667 result = getgrnam_r (group_c_str, &g_str, buf, sizeof (buf),
01668 &g);
01669 else
01670 result = getgrgid_r (gid, &g_str, buf, sizeof (buf),
01671 &g);
01672 #else
01673 p = getgrnam_r (group_c_str, &g_str, buf, sizeof (buf));
01674 result = 0;
01675 #endif
01676 if (result == 0 && g == &g_str)
01677 {
01678 return fill_user_info_from_group (g, info, error);
01679 }
01680 else
01681 {
01682 dbus_set_error (error, _dbus_error_from_errno (errno),
01683 "Group %s unknown or failed to look it up\n",
01684 group_c_str ? group_c_str : "???");
01685 return FALSE;
01686 }
01687 }
01688 #else
01689 {
01690
01691 struct group *g;
01692
01693 g = getgrnam (group_c_str);
01694
01695 if (g != NULL)
01696 {
01697 return fill_user_info_from_group (g, info, error);
01698 }
01699 else
01700 {
01701 dbus_set_error (error, _dbus_error_from_errno (errno),
01702 "Group %s unknown or failed to look it up\n",
01703 group_c_str ? group_c_str : "???");
01704 return FALSE;
01705 }
01706 }
01707 #endif
01708 }
01709
01719 dbus_bool_t
01720 _dbus_group_info_fill (DBusGroupInfo *info,
01721 const DBusString *groupname,
01722 DBusError *error)
01723 {
01724 return fill_group_info (info, DBUS_GID_UNSET,
01725 groupname, error);
01726
01727 }
01728
01738 dbus_bool_t
01739 _dbus_group_info_fill_gid (DBusGroupInfo *info,
01740 dbus_gid_t gid,
01741 DBusError *error)
01742 {
01743 return fill_group_info (info, gid, NULL, error);
01744 }
01745
01751 void
01752 _dbus_group_info_free (DBusGroupInfo *info)
01753 {
01754 dbus_free (info->groupname);
01755 }
01756
01763 void
01764 _dbus_credentials_clear (DBusCredentials *credentials)
01765 {
01766 credentials->pid = DBUS_PID_UNSET;
01767 credentials->uid = DBUS_UID_UNSET;
01768 credentials->gid = DBUS_GID_UNSET;
01769 }
01770
01776 void
01777 _dbus_credentials_from_current_process (DBusCredentials *credentials)
01778 {
01779
01780
01781
01782
01783 _dbus_assert (sizeof (pid_t) <= sizeof (credentials->pid));
01784 _dbus_assert (sizeof (uid_t) <= sizeof (credentials->uid));
01785 _dbus_assert (sizeof (gid_t) <= sizeof (credentials->gid));
01786
01787 credentials->pid = getpid ();
01788 credentials->uid = getuid ();
01789 credentials->gid = getgid ();
01790 }
01791
01800 dbus_bool_t
01801 _dbus_credentials_match (const DBusCredentials *expected_credentials,
01802 const DBusCredentials *provided_credentials)
01803 {
01804 if (provided_credentials->uid == DBUS_UID_UNSET)
01805 return FALSE;
01806 else if (expected_credentials->uid == DBUS_UID_UNSET)
01807 return FALSE;
01808 else if (provided_credentials->uid == 0)
01809 return TRUE;
01810 else if (provided_credentials->uid == expected_credentials->uid)
01811 return TRUE;
01812 else
01813 return FALSE;
01814 }
01815
01820 unsigned long
01821 _dbus_getpid (void)
01822 {
01823 return getpid ();
01824 }
01825
01829 dbus_uid_t
01830 _dbus_getuid (void)
01831 {
01832 return getuid ();
01833 }
01834
01838 dbus_gid_t
01839 _dbus_getgid (void)
01840 {
01841 return getgid ();
01842 }
01843
01844 _DBUS_DEFINE_GLOBAL_LOCK (atomic);
01845
01846 #ifdef DBUS_USE_ATOMIC_INT_486
01847
01848
01849 static inline dbus_int32_t
01850 atomic_exchange_and_add (DBusAtomic *atomic,
01851 volatile dbus_int32_t val)
01852 {
01853 register dbus_int32_t result;
01854
01855 __asm__ __volatile__ ("lock; xaddl %0,%1"
01856 : "=r" (result), "=m" (atomic->value)
01857 : "0" (val), "m" (atomic->value));
01858 return result;
01859 }
01860 #endif
01861
01870 dbus_int32_t
01871 _dbus_atomic_inc (DBusAtomic *atomic)
01872 {
01873 #ifdef DBUS_USE_ATOMIC_INT_486
01874 return atomic_exchange_and_add (atomic, 1);
01875 #else
01876 dbus_int32_t res;
01877 _DBUS_LOCK (atomic);
01878 res = atomic->value;
01879 atomic->value += 1;
01880 _DBUS_UNLOCK (atomic);
01881 return res;
01882 #endif
01883 }
01884
01893 dbus_int32_t
01894 _dbus_atomic_dec (DBusAtomic *atomic)
01895 {
01896 #ifdef DBUS_USE_ATOMIC_INT_486
01897 return atomic_exchange_and_add (atomic, -1);
01898 #else
01899 dbus_int32_t res;
01900
01901 _DBUS_LOCK (atomic);
01902 res = atomic->value;
01903 atomic->value -= 1;
01904 _DBUS_UNLOCK (atomic);
01905 return res;
01906 #endif
01907 }
01908
01919 int
01920 _dbus_poll (DBusPollFD *fds,
01921 int n_fds,
01922 int timeout_milliseconds)
01923 {
01924 #ifdef HAVE_POLL
01925
01926
01927
01928
01929 if (_DBUS_POLLIN == POLLIN &&
01930 _DBUS_POLLPRI == POLLPRI &&
01931 _DBUS_POLLOUT == POLLOUT &&
01932 _DBUS_POLLERR == POLLERR &&
01933 _DBUS_POLLHUP == POLLHUP &&
01934 _DBUS_POLLNVAL == POLLNVAL &&
01935 sizeof (DBusPollFD) == sizeof (struct pollfd) &&
01936 _DBUS_STRUCT_OFFSET (DBusPollFD, fd) ==
01937 _DBUS_STRUCT_OFFSET (struct pollfd, fd) &&
01938 _DBUS_STRUCT_OFFSET (DBusPollFD, events) ==
01939 _DBUS_STRUCT_OFFSET (struct pollfd, events) &&
01940 _DBUS_STRUCT_OFFSET (DBusPollFD, revents) ==
01941 _DBUS_STRUCT_OFFSET (struct pollfd, revents))
01942 {
01943 return poll ((struct pollfd*) fds,
01944 n_fds,
01945 timeout_milliseconds);
01946 }
01947 else
01948 {
01949
01950
01951
01952 _dbus_warn ("didn't implement poll() properly for this system yet\n");
01953 return -1;
01954 }
01955 #else
01956
01957 fd_set read_set, write_set, err_set;
01958 int max_fd = 0;
01959 int i;
01960 struct timeval tv;
01961 int ready;
01962
01963 FD_ZERO (&read_set);
01964 FD_ZERO (&write_set);
01965 FD_ZERO (&err_set);
01966
01967 for (i = 0; i < n_fds; i++)
01968 {
01969 DBusPollFD f = fds[i];
01970
01971 if (f.events & _DBUS_POLLIN)
01972 FD_SET (f.fd, &read_set);
01973
01974 if (f.events & _DBUS_POLLOUT)
01975 FD_SET (f.fd, &write_set);
01976
01977 FD_SET (f.fd, &err_set);
01978
01979 max_fd = MAX (max_fd, f.fd);
01980 }
01981
01982 tv.tv_sec = timeout_milliseconds / 1000;
01983 tv.tv_usec = (timeout_milliseconds % 1000) * 1000;
01984
01985 ready = select (max_fd + 1, &read_set, &write_set, &err_set, &tv);
01986
01987 if (ready > 0)
01988 {
01989 for (i = 0; i < n_fds; i++)
01990 {
01991 DBusPollFD f = fds[i];
01992
01993 f.revents = 0;
01994
01995 if (FD_ISSET (f.fd, &read_set))
01996 f.revents |= _DBUS_POLLIN;
01997
01998 if (FD_ISSET (f.fd, &write_set))
01999 f.revents |= _DBUS_POLLOUT;
02000
02001 if (FD_ISSET (f.fd, &err_set))
02002 f.revents |= _DBUS_POLLERR;
02003 }
02004 }
02005
02006 return ready;
02007 #endif
02008 }
02009
02011 #define NANOSECONDS_PER_SECOND 1000000000
02012
02013 #define MICROSECONDS_PER_SECOND 1000000
02014
02015 #define MILLISECONDS_PER_SECOND 1000
02016
02017 #define NANOSECONDS_PER_MILLISECOND 1000000
02018
02019 #define MICROSECONDS_PER_MILLISECOND 1000
02020
02025 void
02026 _dbus_sleep_milliseconds (int milliseconds)
02027 {
02028 #ifdef HAVE_NANOSLEEP
02029 struct timespec req;
02030 struct timespec rem;
02031
02032 req.tv_sec = milliseconds / MILLISECONDS_PER_SECOND;
02033 req.tv_nsec = (milliseconds % MILLISECONDS_PER_SECOND) * NANOSECONDS_PER_MILLISECOND;
02034 rem.tv_sec = 0;
02035 rem.tv_nsec = 0;
02036
02037 while (nanosleep (&req, &rem) < 0 && errno == EINTR)
02038 req = rem;
02039 #elif defined (HAVE_USLEEP)
02040 usleep (milliseconds * MICROSECONDS_PER_MILLISECOND);
02041 #else
02042 sleep (MAX (milliseconds / 1000, 1));
02043 #endif
02044 }
02045
02052 void
02053 _dbus_get_current_time (long *tv_sec,
02054 long *tv_usec)
02055 {
02056 struct timeval t;
02057
02058 gettimeofday (&t, NULL);
02059
02060 if (tv_sec)
02061 *tv_sec = t.tv_sec;
02062 if (tv_usec)
02063 *tv_usec = t.tv_usec;
02064 }
02065
02076 dbus_bool_t
02077 _dbus_file_get_contents (DBusString *str,
02078 const DBusString *filename,
02079 DBusError *error)
02080 {
02081 int fd;
02082 struct stat sb;
02083 int orig_len;
02084 int total;
02085 const char *filename_c;
02086
02087 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
02088
02089 filename_c = _dbus_string_get_const_data (filename);
02090
02091
02092 fd = open (filename_c, O_RDONLY | O_BINARY);
02093 if (fd < 0)
02094 {
02095 dbus_set_error (error, _dbus_error_from_errno (errno),
02096 "Failed to open \"%s\": %s",
02097 filename_c,
02098 _dbus_strerror (errno));
02099 return FALSE;
02100 }
02101
02102 if (fstat (fd, &sb) < 0)
02103 {
02104 dbus_set_error (error, _dbus_error_from_errno (errno),
02105 "Failed to stat \"%s\": %s",
02106 filename_c,
02107 _dbus_strerror (errno));
02108
02109 _dbus_verbose ("fstat() failed: %s",
02110 _dbus_strerror (errno));
02111
02112 close (fd);
02113
02114 return FALSE;
02115 }
02116
02117 if (sb.st_size > _DBUS_ONE_MEGABYTE)
02118 {
02119 dbus_set_error (error, DBUS_ERROR_FAILED,
02120 "File size %lu of \"%s\" is too large.",
02121 filename_c, (unsigned long) sb.st_size);
02122 close (fd);
02123 return FALSE;
02124 }
02125
02126 total = 0;
02127 orig_len = _dbus_string_get_length (str);
02128 if (sb.st_size > 0 && S_ISREG (sb.st_mode))
02129 {
02130 int bytes_read;
02131
02132 while (total < (int) sb.st_size)
02133 {
02134 bytes_read = _dbus_read (fd, str,
02135 sb.st_size - total);
02136 if (bytes_read <= 0)
02137 {
02138 dbus_set_error (error, _dbus_error_from_errno (errno),
02139 "Error reading \"%s\": %s",
02140 filename_c,
02141 _dbus_strerror (errno));
02142
02143 _dbus_verbose ("read() failed: %s",
02144 _dbus_strerror (errno));
02145
02146 close (fd);
02147 _dbus_string_set_length (str, orig_len);
02148 return FALSE;
02149 }
02150 else
02151 total += bytes_read;
02152 }
02153
02154 close (fd);
02155 return TRUE;
02156 }
02157 else if (sb.st_size != 0)
02158 {
02159 _dbus_verbose ("Can only open regular files at the moment.\n");
02160 dbus_set_error (error, DBUS_ERROR_FAILED,
02161 "\"%s\" is not a regular file",
02162 filename_c);
02163 close (fd);
02164 return FALSE;
02165 }
02166 else
02167 {
02168 close (fd);
02169 return TRUE;
02170 }
02171 }
02172
02182 dbus_bool_t
02183 _dbus_string_save_to_file (const DBusString *str,
02184 const DBusString *filename,
02185 DBusError *error)
02186 {
02187 int fd;
02188 int bytes_to_write;
02189 const char *filename_c;
02190 DBusString tmp_filename;
02191 const char *tmp_filename_c;
02192 int total;
02193 dbus_bool_t need_unlink;
02194 dbus_bool_t retval;
02195
02196 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
02197
02198 fd = -1;
02199 retval = FALSE;
02200 need_unlink = FALSE;
02201
02202 if (!_dbus_string_init (&tmp_filename))
02203 {
02204 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
02205 return FALSE;
02206 }
02207
02208 if (!_dbus_string_copy (filename, 0, &tmp_filename, 0))
02209 {
02210 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
02211 _dbus_string_free (&tmp_filename);
02212 return FALSE;
02213 }
02214
02215 if (!_dbus_string_append (&tmp_filename, "."))
02216 {
02217 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
02218 _dbus_string_free (&tmp_filename);
02219 return FALSE;
02220 }
02221
02222 #define N_TMP_FILENAME_RANDOM_BYTES 8
02223 if (!_dbus_generate_random_ascii (&tmp_filename, N_TMP_FILENAME_RANDOM_BYTES))
02224 {
02225 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
02226 _dbus_string_free (&tmp_filename);
02227 return FALSE;
02228 }
02229
02230 filename_c = _dbus_string_get_const_data (filename);
02231 tmp_filename_c = _dbus_string_get_const_data (&tmp_filename);
02232
02233 fd = open (tmp_filename_c, O_WRONLY | O_BINARY | O_EXCL | O_CREAT,
02234 0600);
02235 if (fd < 0)
02236 {
02237 dbus_set_error (error, _dbus_error_from_errno (errno),
02238 "Could not create %s: %s", tmp_filename_c,
02239 _dbus_strerror (errno));
02240 goto out;
02241 }
02242
02243 need_unlink = TRUE;
02244
02245 total = 0;
02246 bytes_to_write = _dbus_string_get_length (str);
02247
02248 while (total < bytes_to_write)
02249 {
02250 int bytes_written;
02251
02252 bytes_written = _dbus_write (fd, str, total,
02253 bytes_to_write - total);
02254
02255 if (bytes_written <= 0)
02256 {
02257 dbus_set_error (error, _dbus_error_from_errno (errno),
02258 "Could not write to %s: %s", tmp_filename_c,
02259 _dbus_strerror (errno));
02260
02261 goto out;
02262 }
02263
02264 total += bytes_written;
02265 }
02266
02267 if (close (fd) < 0)
02268 {
02269 dbus_set_error (error, _dbus_error_from_errno (errno),
02270 "Could not close file %s: %s",
02271 tmp_filename_c, _dbus_strerror (errno));
02272
02273 goto out;
02274 }
02275
02276 fd = -1;
02277
02278 if (rename (tmp_filename_c, filename_c) < 0)
02279 {
02280 dbus_set_error (error, _dbus_error_from_errno (errno),
02281 "Could not rename %s to %s: %s",
02282 tmp_filename_c, filename_c,
02283 _dbus_strerror (errno));
02284
02285 goto out;
02286 }
02287
02288 need_unlink = FALSE;
02289
02290 retval = TRUE;
02291
02292 out:
02293
02294
02295
02296
02297 if (fd >= 0)
02298 close (fd);
02299
02300 if (need_unlink && unlink (tmp_filename_c) < 0)
02301 _dbus_verbose ("Failed to unlink temp file %s: %s\n",
02302 tmp_filename_c, _dbus_strerror (errno));
02303
02304 _dbus_string_free (&tmp_filename);
02305
02306 if (!retval)
02307 _DBUS_ASSERT_ERROR_IS_SET (error);
02308
02309 return retval;
02310 }
02311
02318 dbus_bool_t
02319 _dbus_create_file_exclusively (const DBusString *filename,
02320 DBusError *error)
02321 {
02322 int fd;
02323 const char *filename_c;
02324
02325 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
02326
02327 filename_c = _dbus_string_get_const_data (filename);
02328
02329 fd = open (filename_c, O_WRONLY | O_BINARY | O_EXCL | O_CREAT,
02330 0600);
02331 if (fd < 0)
02332 {
02333 dbus_set_error (error,
02334 DBUS_ERROR_FAILED,
02335 "Could not create file %s: %s\n",
02336 filename_c,
02337 _dbus_strerror (errno));
02338 return FALSE;
02339 }
02340
02341 if (close (fd) < 0)
02342 {
02343 dbus_set_error (error,
02344 DBUS_ERROR_FAILED,
02345 "Could not close file %s: %s\n",
02346 filename_c,
02347 _dbus_strerror (errno));
02348 return FALSE;
02349 }
02350
02351 return TRUE;
02352 }
02353
02362 dbus_bool_t
02363 _dbus_delete_file (const DBusString *filename,
02364 DBusError *error)
02365 {
02366 const char *filename_c;
02367
02368 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
02369
02370 filename_c = _dbus_string_get_const_data (filename);
02371
02372 if (unlink (filename_c) < 0)
02373 {
02374 dbus_set_error (error, DBUS_ERROR_FAILED,
02375 "Failed to delete file %s: %s\n",
02376 filename_c, _dbus_strerror (errno));
02377 return FALSE;
02378 }
02379 else
02380 return TRUE;
02381 }
02382
02391 dbus_bool_t
02392 _dbus_create_directory (const DBusString *filename,
02393 DBusError *error)
02394 {
02395 const char *filename_c;
02396
02397 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
02398
02399 filename_c = _dbus_string_get_const_data (filename);
02400
02401 if (mkdir (filename_c, 0700) < 0)
02402 {
02403 if (errno == EEXIST)
02404 return TRUE;
02405
02406 dbus_set_error (error, DBUS_ERROR_FAILED,
02407 "Failed to create directory %s: %s\n",
02408 filename_c, _dbus_strerror (errno));
02409 return FALSE;
02410 }
02411 else
02412 return TRUE;
02413 }
02414
02425 dbus_bool_t
02426 _dbus_concat_dir_and_file (DBusString *dir,
02427 const DBusString *next_component)
02428 {
02429 dbus_bool_t dir_ends_in_slash;
02430 dbus_bool_t file_starts_with_slash;
02431
02432 if (_dbus_string_get_length (dir) == 0 ||
02433 _dbus_string_get_length (next_component) == 0)
02434 return TRUE;
02435
02436 dir_ends_in_slash = '/' == _dbus_string_get_byte (dir,
02437 _dbus_string_get_length (dir) - 1);
02438
02439 file_starts_with_slash = '/' == _dbus_string_get_byte (next_component, 0);
02440
02441 if (dir_ends_in_slash && file_starts_with_slash)
02442 {
02443 _dbus_string_shorten (dir, 1);
02444 }
02445 else if (!(dir_ends_in_slash || file_starts_with_slash))
02446 {
02447 if (!_dbus_string_append_byte (dir, '/'))
02448 return FALSE;
02449 }
02450
02451 return _dbus_string_copy (next_component, 0, dir,
02452 _dbus_string_get_length (dir));
02453 }
02454
02461 dbus_bool_t
02462 _dbus_string_get_dirname (const DBusString *filename,
02463 DBusString *dirname)
02464 {
02465 int sep;
02466
02467 _dbus_assert (filename != dirname);
02468 _dbus_assert (filename != NULL);
02469 _dbus_assert (dirname != NULL);
02470
02471
02472 sep = _dbus_string_get_length (filename);
02473 if (sep == 0)
02474 return _dbus_string_append (dirname, ".");
02475
02476 while (sep > 0 && _dbus_string_get_byte (filename, sep - 1) == '/')
02477 --sep;
02478
02479 _dbus_assert (sep >= 0);
02480
02481 if (sep == 0)
02482 return _dbus_string_append (dirname, "/");
02483
02484
02485 _dbus_string_find_byte_backward (filename, sep, '/', &sep);
02486 if (sep < 0)
02487 return _dbus_string_append (dirname, ".");
02488
02489
02490 while (sep > 0 && _dbus_string_get_byte (filename, sep - 1) == '/')
02491 --sep;
02492
02493 _dbus_assert (sep >= 0);
02494
02495 if (sep == 0 &&
02496 _dbus_string_get_byte (filename, 0) == '/')
02497 return _dbus_string_append (dirname, "/");
02498 else
02499 return _dbus_string_copy_len (filename, 0, sep - 0,
02500 dirname, _dbus_string_get_length (dirname));
02501 }
02502
02509 dbus_bool_t
02510 _dbus_path_is_absolute (const DBusString *filename)
02511 {
02512 if (_dbus_string_get_length (filename) > 0)
02513 return _dbus_string_get_byte (filename, 0) == '/';
02514 else
02515 return FALSE;
02516 }
02517
02518 struct DBusDirIter
02519 {
02520 DIR *d;
02521
02522 };
02523
02531 DBusDirIter*
02532 _dbus_directory_open (const DBusString *filename,
02533 DBusError *error)
02534 {
02535 DIR *d;
02536 DBusDirIter *iter;
02537 const char *filename_c;
02538
02539 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
02540
02541 filename_c = _dbus_string_get_const_data (filename);
02542
02543 d = opendir (filename_c);
02544 if (d == NULL)
02545 {
02546 dbus_set_error (error, _dbus_error_from_errno (errno),
02547 "Failed to read directory \"%s\": %s",
02548 filename_c,
02549 _dbus_strerror (errno));
02550 return NULL;
02551 }
02552 iter = dbus_new0 (DBusDirIter, 1);
02553 if (iter == NULL)
02554 {
02555 closedir (d);
02556 dbus_set_error (error, DBUS_ERROR_NO_MEMORY,
02557 "Could not allocate memory for directory iterator");
02558 return NULL;
02559 }
02560
02561 iter->d = d;
02562
02563 return iter;
02564 }
02565
02579 dbus_bool_t
02580 _dbus_directory_get_next_file (DBusDirIter *iter,
02581 DBusString *filename,
02582 DBusError *error)
02583 {
02584 struct dirent *ent;
02585
02586 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
02587
02588 again:
02589 errno = 0;
02590 ent = readdir (iter->d);
02591 if (ent == NULL)
02592 {
02593 if (errno != 0)
02594 dbus_set_error (error,
02595 _dbus_error_from_errno (errno),
02596 "%s", _dbus_strerror (errno));
02597 return FALSE;
02598 }
02599 else if (ent->d_name[0] == '.' &&
02600 (ent->d_name[1] == '\0' ||
02601 (ent->d_name[1] == '.' && ent->d_name[2] == '\0')))
02602 goto again;
02603 else
02604 {
02605 _dbus_string_set_length (filename, 0);
02606 if (!_dbus_string_append (filename, ent->d_name))
02607 {
02608 dbus_set_error (error, DBUS_ERROR_NO_MEMORY,
02609 "No memory to read directory entry");
02610 return FALSE;
02611 }
02612 else
02613 return TRUE;
02614 }
02615 }
02616
02620 void
02621 _dbus_directory_close (DBusDirIter *iter)
02622 {
02623 closedir (iter->d);
02624 dbus_free (iter);
02625 }
02626
02627 static dbus_bool_t
02628 pseudorandom_generate_random_bytes (DBusString *str,
02629 int n_bytes)
02630 {
02631 int old_len;
02632 unsigned long tv_usec;
02633 int i;
02634
02635 old_len = _dbus_string_get_length (str);
02636
02637
02638 _dbus_verbose ("Falling back to pseudorandom for %d bytes\n",
02639 n_bytes);
02640
02641 _dbus_get_current_time (NULL, &tv_usec);
02642 srand (tv_usec);
02643
02644 i = 0;
02645 while (i < n_bytes)
02646 {
02647 double r;
02648 unsigned int b;
02649
02650 r = rand ();
02651 b = (r / (double) RAND_MAX) * 255.0;
02652
02653 if (!_dbus_string_append_byte (str, b))
02654 goto failed;
02655
02656 ++i;
02657 }
02658
02659 return TRUE;
02660
02661 failed:
02662 _dbus_string_set_length (str, old_len);
02663 return FALSE;
02664 }
02665
02674 dbus_bool_t
02675 _dbus_generate_random_bytes (DBusString *str,
02676 int n_bytes)
02677 {
02678 int old_len;
02679 int fd;
02680
02681
02682
02683
02684
02685
02686
02687 old_len = _dbus_string_get_length (str);
02688 fd = -1;
02689
02690
02691 fd = open ("/dev/urandom", O_RDONLY);
02692 if (fd < 0)
02693 return pseudorandom_generate_random_bytes (str, n_bytes);
02694
02695 if (_dbus_read (fd, str, n_bytes) != n_bytes)
02696 {
02697 close (fd);
02698 _dbus_string_set_length (str, old_len);
02699 return pseudorandom_generate_random_bytes (str, n_bytes);
02700 }
02701
02702 _dbus_verbose ("Read %d bytes from /dev/urandom\n",
02703 n_bytes);
02704
02705 close (fd);
02706
02707 return TRUE;
02708 }
02709
02718 dbus_bool_t
02719 _dbus_generate_random_ascii (DBusString *str,
02720 int n_bytes)
02721 {
02722 static const char letters[] =
02723 "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789abcdefghijklmnopqrstuvwxyz";
02724 int i;
02725 int len;
02726
02727 if (!_dbus_generate_random_bytes (str, n_bytes))
02728 return FALSE;
02729
02730 len = _dbus_string_get_length (str);
02731 i = len - n_bytes;
02732 while (i < len)
02733 {
02734 _dbus_string_set_byte (str, i,
02735 letters[_dbus_string_get_byte (str, i) %
02736 (sizeof (letters) - 1)]);
02737
02738 ++i;
02739 }
02740
02741 _dbus_assert (_dbus_string_validate_ascii (str, len - n_bytes,
02742 n_bytes));
02743
02744 return TRUE;
02745 }
02746
02754 const char*
02755 _dbus_strerror (int error_number)
02756 {
02757 const char *msg;
02758
02759 msg = strerror (error_number);
02760 if (msg == NULL)
02761 msg = "unknown";
02762
02763 return msg;
02764 }
02765
02769 void
02770 _dbus_disable_sigpipe (void)
02771 {
02772 signal (SIGPIPE, SIG_IGN);
02773 }
02774
02782 void
02783 _dbus_fd_set_close_on_exec (int fd)
02784 {
02785 int val;
02786
02787 val = fcntl (fd, F_GETFD, 0);
02788
02789 if (val < 0)
02790 return;
02791
02792 val |= FD_CLOEXEC;
02793
02794 fcntl (fd, F_SETFD, val);
02795 }
02796
02806 const char*
02807 _dbus_error_from_errno (int error_number)
02808 {
02809 switch (error_number)
02810 {
02811 case 0:
02812 return DBUS_ERROR_FAILED;
02813
02814 #ifdef EPROTONOSUPPORT
02815 case EPROTONOSUPPORT:
02816 return DBUS_ERROR_NOT_SUPPORTED;
02817 #endif
02818 #ifdef EAFNOSUPPORT
02819 case EAFNOSUPPORT:
02820 return DBUS_ERROR_NOT_SUPPORTED;
02821 #endif
02822 #ifdef ENFILE
02823 case ENFILE:
02824 return DBUS_ERROR_LIMITS_EXCEEDED;
02825 #endif
02826 #ifdef EMFILE
02827 case EMFILE:
02828 return DBUS_ERROR_LIMITS_EXCEEDED;
02829 #endif
02830 #ifdef EACCES
02831 case EACCES:
02832 return DBUS_ERROR_ACCESS_DENIED;
02833 #endif
02834 #ifdef EPERM
02835 case EPERM:
02836 return DBUS_ERROR_ACCESS_DENIED;
02837 #endif
02838 #ifdef ENOBUFS
02839 case ENOBUFS:
02840 return DBUS_ERROR_NO_MEMORY;
02841 #endif
02842 #ifdef ENOMEM
02843 case ENOMEM:
02844 return DBUS_ERROR_NO_MEMORY;
02845 #endif
02846 #ifdef EINVAL
02847 case EINVAL:
02848 return DBUS_ERROR_FAILED;
02849 #endif
02850 #ifdef EBADF
02851 case EBADF:
02852 return DBUS_ERROR_FAILED;
02853 #endif
02854 #ifdef EFAULT
02855 case EFAULT:
02856 return DBUS_ERROR_FAILED;
02857 #endif
02858 #ifdef ENOTSOCK
02859 case ENOTSOCK:
02860 return DBUS_ERROR_FAILED;
02861 #endif
02862 #ifdef EISCONN
02863 case EISCONN:
02864 return DBUS_ERROR_FAILED;
02865 #endif
02866 #ifdef ECONNREFUSED
02867 case ECONNREFUSED:
02868 return DBUS_ERROR_NO_SERVER;
02869 #endif
02870 #ifdef ETIMEDOUT
02871 case ETIMEDOUT:
02872 return DBUS_ERROR_TIMEOUT;
02873 #endif
02874 #ifdef ENETUNREACH
02875 case ENETUNREACH:
02876 return DBUS_ERROR_NO_NETWORK;
02877 #endif
02878 #ifdef EADDRINUSE
02879 case EADDRINUSE:
02880 return DBUS_ERROR_ADDRESS_IN_USE;
02881 #endif
02882 #ifdef EEXIST
02883 case EEXIST:
02884 return DBUS_ERROR_FILE_NOT_FOUND;
02885 #endif
02886 #ifdef ENOENT
02887 case ENOENT:
02888 return DBUS_ERROR_FILE_NOT_FOUND;
02889 #endif
02890 }
02891
02892 return DBUS_ERROR_FAILED;
02893 }
02894
02900 void
02901 _dbus_exit (int code)
02902 {
02903 _exit (code);
02904 }
02905
02914 dbus_bool_t
02915 _dbus_stat (const DBusString *filename,
02916 DBusStat *statbuf,
02917 DBusError *error)
02918 {
02919 const char *filename_c;
02920 struct stat sb;
02921
02922 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
02923
02924 filename_c = _dbus_string_get_const_data (filename);
02925
02926 if (stat (filename_c, &sb) < 0)
02927 {
02928 dbus_set_error (error, _dbus_error_from_errno (errno),
02929 "%s", _dbus_strerror (errno));
02930 return FALSE;
02931 }
02932
02933 statbuf->mode = sb.st_mode;
02934 statbuf->nlink = sb.st_nlink;
02935 statbuf->uid = sb.st_uid;
02936 statbuf->gid = sb.st_gid;
02937 statbuf->size = sb.st_size;
02938 statbuf->atime = sb.st_atime;
02939 statbuf->mtime = sb.st_mtime;
02940 statbuf->ctime = sb.st_ctime;
02941
02942 return TRUE;
02943 }
02944
02955 dbus_bool_t
02956 _dbus_full_duplex_pipe (int *fd1,
02957 int *fd2,
02958 dbus_bool_t blocking,
02959 DBusError *error)
02960 {
02961 #ifdef HAVE_SOCKETPAIR
02962 int fds[2];
02963
02964 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
02965
02966 if (socketpair (AF_UNIX, SOCK_STREAM, 0, fds) < 0)
02967 {
02968 dbus_set_error (error, _dbus_error_from_errno (errno),
02969 "Could not create full-duplex pipe");
02970 return FALSE;
02971 }
02972
02973 if (!blocking &&
02974 (!_dbus_set_fd_nonblocking (fds[0], NULL) ||
02975 !_dbus_set_fd_nonblocking (fds[1], NULL)))
02976 {
02977 dbus_set_error (error, _dbus_error_from_errno (errno),
02978 "Could not set full-duplex pipe nonblocking");
02979
02980 close (fds[0]);
02981 close (fds[1]);
02982
02983 return FALSE;
02984 }
02985
02986 *fd1 = fds[0];
02987 *fd2 = fds[1];
02988
02989 return TRUE;
02990 #else
02991 _dbus_warn ("_dbus_full_duplex_pipe() not implemented on this OS\n");
02992 dbus_set_error (error, DBUS_ERROR_FAILED,
02993 "_dbus_full_duplex_pipe() not implemented on this OS");
02994 return FALSE;
02995 #endif
02996 }
02997
03005 dbus_bool_t
03006 _dbus_close (int fd,
03007 DBusError *error)
03008 {
03009 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
03010
03011 again:
03012 if (close (fd) < 0)
03013 {
03014 if (errno == EINTR)
03015 goto again;
03016
03017 dbus_set_error (error, _dbus_error_from_errno (errno),
03018 "Could not close fd %d", fd);
03019 return FALSE;
03020 }
03021
03022 return TRUE;
03023 }
03024
03032 dbus_bool_t
03033 _dbus_set_fd_nonblocking (int fd,
03034 DBusError *error)
03035 {
03036 int val;
03037
03038 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
03039
03040 val = fcntl (fd, F_GETFL, 0);
03041 if (val < 0)
03042 {
03043 dbus_set_error (error, _dbus_error_from_errno (errno),
03044 "Failed to get flags from file descriptor %d: %s",
03045 fd, _dbus_strerror (errno));
03046 _dbus_verbose ("Failed to get flags for fd %d: %s\n", fd,
03047 _dbus_strerror (errno));
03048 return FALSE;
03049 }
03050
03051 if (fcntl (fd, F_SETFL, val | O_NONBLOCK) < 0)
03052 {
03053 dbus_set_error (error, _dbus_error_from_errno (errno),
03054 "Failed to set nonblocking flag of file descriptor %d: %s",
03055 fd, _dbus_strerror (errno));
03056 _dbus_verbose ("Failed to set fd %d nonblocking: %s\n",
03057 fd, _dbus_strerror (errno));
03058
03059 return FALSE;
03060 }
03061
03062 return TRUE;
03063 }
03064
03070 void
03071 _dbus_print_backtrace (void)
03072 {
03073 #if defined (HAVE_BACKTRACE) && defined (DBUS_ENABLE_VERBOSE_MODE)
03074 void *bt[500];
03075 int bt_size;
03076 int i;
03077 char **syms;
03078
03079 bt_size = backtrace (bt, 500);
03080
03081 syms = backtrace_symbols (bt, bt_size);
03082
03083 i = 0;
03084 while (i < bt_size)
03085 {
03086 _dbus_verbose (" %s\n", syms[i]);
03087 ++i;
03088 }
03089
03090 free (syms);
03091 #else
03092 _dbus_verbose (" D-BUS not compiled with backtrace support\n");
03093 #endif
03094 }
03095
03103 dbus_bool_t
03104 _dbus_become_daemon (const DBusString *pidfile,
03105 DBusError *error)
03106 {
03107 const char *s;
03108 pid_t child_pid;
03109
03110 if (chdir ("/") < 0)
03111 {
03112 dbus_set_error (error, DBUS_ERROR_FAILED,
03113 "Could not chdir() to root directory");
03114 return FALSE;
03115 }
03116
03117 switch ((child_pid = fork ()))
03118 {
03119 case -1:
03120 dbus_set_error (error, _dbus_error_from_errno (errno),
03121 "Failed to fork daemon: %s", _dbus_strerror (errno));
03122 return FALSE;
03123 break;
03124
03125 case 0:
03126
03127
03128 s = _dbus_getenv ("DBUS_DEBUG_DAEMONIZE");
03129 if (s != NULL)
03130 kill (_dbus_getpid (), SIGSTOP);
03131
03132 s = _dbus_getenv ("DBUS_DEBUG_OUTPUT");
03133 if (s == NULL || *s == '\0')
03134 {
03135 int dev_null_fd;
03136
03137
03138
03139
03140
03141
03142 dev_null_fd = open ("/dev/null", O_RDWR);
03143 if (dev_null_fd >= 0)
03144 {
03145 dup2 (dev_null_fd, 0);
03146 dup2 (dev_null_fd, 1);
03147 dup2 (dev_null_fd, 2);
03148 }
03149 }
03150
03151
03152 umask (022);
03153 break;
03154
03155 default:
03156 if (pidfile)
03157 {
03158 if (!_dbus_write_pid_file (pidfile,
03159 child_pid,
03160 error))
03161 {
03162 kill (child_pid, SIGTERM);
03163 return FALSE;
03164 }
03165 }
03166 _exit (0);
03167 break;
03168 }
03169
03170 if (setsid () == -1)
03171 _dbus_assert_not_reached ("setsid() failed");
03172
03173 return TRUE;
03174 }
03175
03184 dbus_bool_t
03185 _dbus_write_pid_file (const DBusString *filename,
03186 unsigned long pid,
03187 DBusError *error)
03188 {
03189 const char *cfilename;
03190 int fd;
03191 FILE *f;
03192
03193 cfilename = _dbus_string_get_const_data (filename);
03194
03195 fd = open (cfilename, O_WRONLY|O_CREAT|O_EXCL|O_BINARY, 0644);
03196
03197 if (fd < 0)
03198 {
03199 dbus_set_error (error, _dbus_error_from_errno (errno),
03200 "Failed to open \"%s\": %s", cfilename,
03201 _dbus_strerror (errno));
03202 return FALSE;
03203 }
03204
03205 if ((f = fdopen (fd, "w")) == NULL)
03206 {
03207 dbus_set_error (error, _dbus_error_from_errno (errno),
03208 "Failed to fdopen fd %d: %s", fd, _dbus_strerror (errno));
03209 close (fd);
03210 return FALSE;
03211 }
03212
03213 if (fprintf (f, "%lu\n", pid) < 0)
03214 {
03215 dbus_set_error (error, _dbus_error_from_errno (errno),
03216 "Failed to write to \"%s\": %s", cfilename,
03217 _dbus_strerror (errno));
03218 return FALSE;
03219 }
03220
03221 if (fclose (f) == EOF)
03222 {
03223 dbus_set_error (error, _dbus_error_from_errno (errno),
03224 "Failed to close \"%s\": %s", cfilename,
03225 _dbus_strerror (errno));
03226 return FALSE;
03227 }
03228
03229 return TRUE;
03230 }
03231
03240 dbus_bool_t
03241 _dbus_change_identity (dbus_uid_t uid,
03242 dbus_gid_t gid,
03243 DBusError *error)
03244 {
03245
03246
03247
03248 if (setgid (gid) < 0)
03249 {
03250 dbus_set_error (error, _dbus_error_from_errno (errno),
03251 "Failed to set GID to %lu: %s", gid,
03252 _dbus_strerror (errno));
03253 return FALSE;
03254 }
03255
03256 if (setuid (uid) < 0)
03257 {
03258 dbus_set_error (error, _dbus_error_from_errno (errno),
03259 "Failed to set UID to %lu: %s", uid,
03260 _dbus_strerror (errno));
03261 return FALSE;
03262 }
03263
03264 return TRUE;
03265 }
03266
03272 void
03273 _dbus_set_signal_handler (int sig,
03274 DBusSignalHandler handler)
03275 {
03276 struct sigaction act;
03277 sigset_t empty_mask;
03278
03279 sigemptyset (&empty_mask);
03280 act.sa_handler = handler;
03281 act.sa_mask = empty_mask;
03282 act.sa_flags = 0;
03283 sigaction (sig, &act, 0);
03284 }
03285
03286
03287 #ifdef DBUS_BUILD_TESTS
03288 #include <stdlib.h>
03289 static void
03290 check_dirname (const char *filename,
03291 const char *dirname)
03292 {
03293 DBusString f, d;
03294
03295 _dbus_string_init_const (&f, filename);
03296
03297 if (!_dbus_string_init (&d))
03298 _dbus_assert_not_reached ("no memory");
03299
03300 if (!_dbus_string_get_dirname (&f, &d))
03301 _dbus_assert_not_reached ("no memory");
03302
03303 if (!_dbus_string_equal_c_str (&d, dirname))
03304 {
03305 _dbus_warn ("For filename \"%s\" got dirname \"%s\" and expected \"%s\"\n",
03306 filename,
03307 _dbus_string_get_const_data (&d),
03308 dirname);
03309 exit (1);
03310 }
03311
03312 _dbus_string_free (&d);
03313 }
03314
03315 static void
03316 check_path_absolute (const char *path,
03317 dbus_bool_t expected)
03318 {
03319 DBusString p;
03320
03321 _dbus_string_init_const (&p, path);
03322
03323 if (_dbus_path_is_absolute (&p) != expected)
03324 {
03325 _dbus_warn ("For path \"%s\" expected absolute = %d got %d\n",
03326 path, expected, _dbus_path_is_absolute (&p));
03327 exit (1);
03328 }
03329 }
03330
03336 dbus_bool_t
03337 _dbus_sysdeps_test (void)
03338 {
03339 DBusString str;
03340 double val;
03341 int pos;
03342
03343 check_dirname ("foo", ".");
03344 check_dirname ("foo/bar", "foo");
03345 check_dirname ("foo//bar", "foo");
03346 check_dirname ("foo///bar", "foo");
03347 check_dirname ("foo/bar/", "foo");
03348 check_dirname ("foo//bar/", "foo");
03349 check_dirname ("foo///bar/", "foo");
03350 check_dirname ("foo/bar//", "foo");
03351 check_dirname ("foo//bar////", "foo");
03352 check_dirname ("foo///bar///////", "foo");
03353 check_dirname ("/foo", "/");
03354 check_dirname ("
03355 check_dirname ("/foo/bar", "/foo");
03356 check_dirname ("/foo
03357 check_dirname ("/foo///bar", "/foo");
03358 check_dirname ("/", "/");
03359 check_dirname ("
03360 check_dirname ("", ".");
03361
03362
03363 _dbus_string_init_const (&str, "3.5");
03364 if (!_dbus_string_parse_double (&str,
03365 0, &val, &pos))
03366 {
03367 _dbus_warn ("Failed to parse double");
03368 exit (1);
03369 }
03370 if (val != 3.5)
03371 {
03372 _dbus_warn ("Failed to parse 3.5 correctly, got: %f", val);
03373 exit (1);
03374 }
03375 if (pos != 3)
03376 {
03377 _dbus_warn ("_dbus_string_parse_double of \"3.5\" returned wrong position %d", pos);
03378 exit (1);
03379 }
03380
03381 check_path_absolute ("/", TRUE);
03382 check_path_absolute ("/foo", TRUE);
03383 check_path_absolute ("", FALSE);
03384 check_path_absolute ("foo", FALSE);
03385 check_path_absolute ("foo/bar", FALSE);
03386
03387 return TRUE;
03388 }
03389 #endif
03390