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