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 if (host == NULL)
00691 host = "localhost";
00692
00693 he = gethostbyname (host);
00694 if (he == NULL)
00695 {
00696 dbus_set_error (error,
00697 _dbus_error_from_errno (errno),
00698 "Failed to lookup hostname: %s",
00699 host);
00700 return -1;
00701 }
00702
00703 haddr = ((struct in_addr *) (he->h_addr_list)[0]);
00704
00705 _DBUS_ZERO (addr);
00706 memcpy (&addr.sin_addr, haddr, sizeof (struct in_addr));
00707 addr.sin_family = AF_INET;
00708 addr.sin_port = htons (port);
00709
00710 if (bind (listen_fd, (struct sockaddr*) &addr, sizeof (struct sockaddr)))
00711 {
00712 dbus_set_error (error, _dbus_error_from_errno (errno),
00713 "Failed to bind socket \"%s:%d\": %s",
00714 host, port, _dbus_strerror (errno));
00715 close (listen_fd);
00716 return -1;
00717 }
00718
00719 if (listen (listen_fd, 30 ) < 0)
00720 {
00721 dbus_set_error (error, _dbus_error_from_errno (errno),
00722 "Failed to listen on socket \"%s:%d\": %s",
00723 host, port, _dbus_strerror (errno));
00724 close (listen_fd);
00725 return -1;
00726 }
00727
00728 if (!_dbus_set_fd_nonblocking (listen_fd, error))
00729 {
00730 close (listen_fd);
00731 return -1;
00732 }
00733
00734 return listen_fd;
00735 }
00736
00737 static dbus_bool_t
00738 write_credentials_byte (int server_fd,
00739 DBusError *error)
00740 {
00741 int bytes_written;
00742 char buf[1] = { '\0' };
00743
00744 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
00745
00746 again:
00747
00748 bytes_written = write (server_fd, buf, 1);
00749
00750 if (bytes_written < 0 && errno == EINTR)
00751 goto again;
00752
00753 if (bytes_written < 0)
00754 {
00755 dbus_set_error (error, _dbus_error_from_errno (errno),
00756 "Failed to write credentials byte: %s",
00757 _dbus_strerror (errno));
00758 return FALSE;
00759 }
00760 else if (bytes_written == 0)
00761 {
00762 dbus_set_error (error, DBUS_ERROR_IO_ERROR,
00763 "wrote zero bytes writing credentials byte");
00764 return FALSE;
00765 }
00766 else
00767 {
00768 _dbus_assert (bytes_written == 1);
00769 _dbus_verbose ("wrote credentials byte\n");
00770 return TRUE;
00771 }
00772 }
00773
00792 dbus_bool_t
00793 _dbus_read_credentials_unix_socket (int client_fd,
00794 DBusCredentials *credentials,
00795 DBusError *error)
00796 {
00797 struct msghdr msg;
00798 struct iovec iov;
00799 char buf;
00800
00801 #ifdef HAVE_CMSGCRED
00802 char cmsgmem[CMSG_SPACE (sizeof (struct cmsgcred))];
00803 struct cmsghdr *cmsg = (struct cmsghdr *) cmsgmem;
00804 #endif
00805
00806 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
00807
00808
00809
00810
00811
00812 _dbus_assert (sizeof (pid_t) <= sizeof (credentials->pid));
00813 _dbus_assert (sizeof (uid_t) <= sizeof (credentials->uid));
00814 _dbus_assert (sizeof (gid_t) <= sizeof (credentials->gid));
00815
00816 _dbus_credentials_clear (credentials);
00817
00818 #if defined(LOCAL_CREDS) && defined(HAVE_CMSGCRED)
00819
00820 {
00821 int on = 1;
00822 if (setsockopt (client_fd, 0, LOCAL_CREDS, &on, sizeof (on)) < 0)
00823 {
00824 _dbus_verbose ("Unable to set LOCAL_CREDS socket option\n");
00825 return FALSE;
00826 }
00827 }
00828 #endif
00829
00830 iov.iov_base = &buf;
00831 iov.iov_len = 1;
00832
00833 memset (&msg, 0, sizeof (msg));
00834 msg.msg_iov = &iov;
00835 msg.msg_iovlen = 1;
00836
00837 #ifdef HAVE_CMSGCRED
00838 memset (cmsgmem, 0, sizeof (cmsgmem));
00839 msg.msg_control = cmsgmem;
00840 msg.msg_controllen = sizeof (cmsgmem);
00841 #endif
00842
00843 again:
00844 if (recvmsg (client_fd, &msg, 0) < 0)
00845 {
00846 if (errno == EINTR)
00847 goto again;
00848
00849 dbus_set_error (error, _dbus_error_from_errno (errno),
00850 "Failed to read credentials byte: %s",
00851 _dbus_strerror (errno));
00852 return FALSE;
00853 }
00854
00855 if (buf != '\0')
00856 {
00857 dbus_set_error (error, DBUS_ERROR_FAILED,
00858 "Credentials byte was not nul");
00859 return FALSE;
00860 }
00861
00862 #ifdef HAVE_CMSGCRED
00863 if (cmsg->cmsg_len < sizeof (cmsgmem) || cmsg->cmsg_type != SCM_CREDS)
00864 {
00865 dbus_set_error (error, DBUS_ERROR_FAILED);
00866 _dbus_verbose ("Message from recvmsg() was not SCM_CREDS\n");
00867 return FALSE;
00868 }
00869 #endif
00870
00871 _dbus_verbose ("read credentials byte\n");
00872
00873 {
00874 #ifdef SO_PEERCRED
00875 struct ucred cr;
00876 int cr_len = sizeof (cr);
00877
00878 if (getsockopt (client_fd, SOL_SOCKET, SO_PEERCRED, &cr, &cr_len) == 0 &&
00879 cr_len == sizeof (cr))
00880 {
00881 credentials->pid = cr.pid;
00882 credentials->uid = cr.uid;
00883 credentials->gid = cr.gid;
00884 }
00885 else
00886 {
00887 _dbus_verbose ("Failed to getsockopt() credentials, returned len %d/%d: %s\n",
00888 cr_len, (int) sizeof (cr), _dbus_strerror (errno));
00889 }
00890 #elif defined(HAVE_CMSGCRED)
00891 struct cmsgcred *cred;
00892
00893 cred = (struct cmsgcred *) CMSG_DATA (cmsg);
00894
00895 credentials->pid = cred->cmcred_pid;
00896 credentials->uid = cred->cmcred_euid;
00897 credentials->gid = cred->cmcred_groups[0];
00898 #else
00899 _dbus_verbose ("Socket credentials not supported on this OS\n");
00900 #endif
00901 }
00902
00903 _dbus_verbose ("Credentials:"
00904 " pid "DBUS_PID_FORMAT
00905 " uid "DBUS_UID_FORMAT
00906 " gid "DBUS_GID_FORMAT"\n",
00907 credentials->pid,
00908 credentials->uid,
00909 credentials->gid);
00910
00911 return TRUE;
00912 }
00913
00931 dbus_bool_t
00932 _dbus_send_credentials_unix_socket (int server_fd,
00933 DBusError *error)
00934 {
00935 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
00936
00937 if (write_credentials_byte (server_fd, error))
00938 return TRUE;
00939 else
00940 return FALSE;
00941 }
00942
00950 int
00951 _dbus_accept (int listen_fd)
00952 {
00953 int client_fd;
00954 struct sockaddr addr;
00955 socklen_t addrlen;
00956
00957 addrlen = sizeof (addr);
00958
00959 retry:
00960 client_fd = accept (listen_fd, &addr, &addrlen);
00961
00962 if (client_fd < 0)
00963 {
00964 if (errno == EINTR)
00965 goto retry;
00966 }
00967
00968 return client_fd;
00969 }
00970
00985 dbus_bool_t
00986 _dbus_string_append_int (DBusString *str,
00987 long value)
00988 {
00989
00990 #define MAX_LONG_LEN ((sizeof (long) * 8 + 2) / 3 + 1)
00991 int orig_len;
00992 int i;
00993 char *buf;
00994
00995 orig_len = _dbus_string_get_length (str);
00996
00997 if (!_dbus_string_lengthen (str, MAX_LONG_LEN))
00998 return FALSE;
00999
01000 buf = _dbus_string_get_data_len (str, orig_len, MAX_LONG_LEN);
01001
01002 snprintf (buf, MAX_LONG_LEN, "%ld", value);
01003
01004 i = 0;
01005 while (*buf)
01006 {
01007 ++buf;
01008 ++i;
01009 }
01010
01011 _dbus_string_shorten (str, MAX_LONG_LEN - i);
01012
01013 return TRUE;
01014 }
01015
01023 dbus_bool_t
01024 _dbus_string_append_uint (DBusString *str,
01025 unsigned long value)
01026 {
01027
01028 #define MAX_ULONG_LEN (MAX_LONG_LEN * 2)
01029 int orig_len;
01030 int i;
01031 char *buf;
01032
01033 orig_len = _dbus_string_get_length (str);
01034
01035 if (!_dbus_string_lengthen (str, MAX_ULONG_LEN))
01036 return FALSE;
01037
01038 buf = _dbus_string_get_data_len (str, orig_len, MAX_ULONG_LEN);
01039
01040 snprintf (buf, MAX_ULONG_LEN, "%lu", value);
01041
01042 i = 0;
01043 while (*buf)
01044 {
01045 ++buf;
01046 ++i;
01047 }
01048
01049 _dbus_string_shorten (str, MAX_ULONG_LEN - i);
01050
01051 return TRUE;
01052 }
01053
01061 dbus_bool_t
01062 _dbus_string_append_double (DBusString *str,
01063 double value)
01064 {
01065 #define MAX_DOUBLE_LEN 64
01066 int orig_len;
01067 char *buf;
01068 int i;
01069
01070 orig_len = _dbus_string_get_length (str);
01071
01072 if (!_dbus_string_lengthen (str, MAX_DOUBLE_LEN))
01073 return FALSE;
01074
01075 buf = _dbus_string_get_data_len (str, orig_len, MAX_DOUBLE_LEN);
01076
01077 snprintf (buf, MAX_LONG_LEN, "%g", value);
01078
01079 i = 0;
01080 while (*buf)
01081 {
01082 ++buf;
01083 ++i;
01084 }
01085
01086 _dbus_string_shorten (str, MAX_DOUBLE_LEN - i);
01087
01088 return TRUE;
01089 }
01090
01103 dbus_bool_t
01104 _dbus_string_parse_int (const DBusString *str,
01105 int start,
01106 long *value_return,
01107 int *end_return)
01108 {
01109 long v;
01110 const char *p;
01111 char *end;
01112
01113 p = _dbus_string_get_const_data_len (str, start,
01114 _dbus_string_get_length (str) - start);
01115
01116 end = NULL;
01117 errno = 0;
01118 v = strtol (p, &end, 0);
01119 if (end == NULL || end == p || errno != 0)
01120 return FALSE;
01121
01122 if (value_return)
01123 *value_return = v;
01124 if (end_return)
01125 *end_return = start + (end - p);
01126
01127 return TRUE;
01128 }
01129
01130 #ifdef DBUS_BUILD_TESTS
01131
01144 dbus_bool_t
01145 _dbus_string_parse_uint (const DBusString *str,
01146 int start,
01147 unsigned long *value_return,
01148 int *end_return)
01149 {
01150 unsigned long v;
01151 const char *p;
01152 char *end;
01153
01154 p = _dbus_string_get_const_data_len (str, start,
01155 _dbus_string_get_length (str) - start);
01156
01157 end = NULL;
01158 errno = 0;
01159 v = strtoul (p, &end, 0);
01160 if (end == NULL || end == p || errno != 0)
01161 return FALSE;
01162
01163 if (value_return)
01164 *value_return = v;
01165 if (end_return)
01166 *end_return = start + (end - p);
01167
01168 return TRUE;
01169 }
01170 #endif
01171
01172 static dbus_bool_t
01173 ascii_isspace (char c)
01174 {
01175 return (c == ' ' ||
01176 c == '\f' ||
01177 c == '\n' ||
01178 c == '\r' ||
01179 c == '\t' ||
01180 c == '\v');
01181 }
01182
01183 static dbus_bool_t
01184 ascii_isdigit (char c)
01185 {
01186 return c >= '0' && c <= '9';
01187 }
01188
01189 static dbus_bool_t
01190 ascii_isxdigit (char c)
01191 {
01192 return (ascii_isdigit (c) ||
01193 (c >= 'a' && c <= 'f') ||
01194 (c >= 'A' && c <= 'F'));
01195 }
01196
01197
01198
01199
01200
01201
01202
01203 static double
01204 ascii_strtod (const char *nptr,
01205 char **endptr)
01206 {
01207 char *fail_pos;
01208 double val;
01209 struct lconv *locale_data;
01210 const char *decimal_point;
01211 int decimal_point_len;
01212 const char *p, *decimal_point_pos;
01213 const char *end = NULL;
01214
01215 fail_pos = NULL;
01216
01217 locale_data = localeconv ();
01218 decimal_point = locale_data->decimal_point;
01219 decimal_point_len = strlen (decimal_point);
01220
01221 _dbus_assert (decimal_point_len != 0);
01222
01223 decimal_point_pos = NULL;
01224 if (decimal_point[0] != '.' ||
01225 decimal_point[1] != 0)
01226 {
01227 p = nptr;
01228
01229 while (ascii_isspace (*p))
01230 p++;
01231
01232
01233 if (*p == '+' || *p == '-')
01234 p++;
01235
01236 if (p[0] == '0' &&
01237 (p[1] == 'x' || p[1] == 'X'))
01238 {
01239 p += 2;
01240
01241
01242 while (ascii_isxdigit (*p))
01243 p++;
01244
01245 if (*p == '.')
01246 {
01247 decimal_point_pos = p++;
01248
01249 while (ascii_isxdigit (*p))
01250 p++;
01251
01252 if (*p == 'p' || *p == 'P')
01253 p++;
01254 if (*p == '+' || *p == '-')
01255 p++;
01256 while (ascii_isdigit (*p))
01257 p++;
01258 end = p;
01259 }
01260 }
01261 else
01262 {
01263 while (ascii_isdigit (*p))
01264 p++;
01265
01266 if (*p == '.')
01267 {
01268 decimal_point_pos = p++;
01269
01270 while (ascii_isdigit (*p))
01271 p++;
01272
01273 if (*p == 'e' || *p == 'E')
01274 p++;
01275 if (*p == '+' || *p == '-')
01276 p++;
01277 while (ascii_isdigit (*p))
01278 p++;
01279 end = p;
01280 }
01281 }
01282
01283 }
01284
01285
01286
01287 errno = 0;
01288
01289 if (decimal_point_pos)
01290 {
01291 char *copy, *c;
01292
01293
01294 copy = dbus_malloc (end - nptr + 1 + decimal_point_len);
01295
01296 c = copy;
01297 memcpy (c, nptr, decimal_point_pos - nptr);
01298 c += decimal_point_pos - nptr;
01299 memcpy (c, decimal_point, decimal_point_len);
01300 c += decimal_point_len;
01301 memcpy (c, decimal_point_pos + 1, end - (decimal_point_pos + 1));
01302 c += end - (decimal_point_pos + 1);
01303 *c = 0;
01304
01305 val = strtod (copy, &fail_pos);
01306
01307 if (fail_pos)
01308 {
01309 if (fail_pos > decimal_point_pos)
01310 fail_pos = (char *)nptr + (fail_pos - copy) - (decimal_point_len - 1);
01311 else
01312 fail_pos = (char *)nptr + (fail_pos - copy);
01313 }
01314
01315 dbus_free (copy);
01316
01317 }
01318 else
01319 val = strtod (nptr, &fail_pos);
01320
01321 if (endptr)
01322 *endptr = fail_pos;
01323
01324 return val;
01325 }
01326
01327
01340 dbus_bool_t
01341 _dbus_string_parse_double (const DBusString *str,
01342 int start,
01343 double *value_return,
01344 int *end_return)
01345 {
01346 double v;
01347 const char *p;
01348 char *end;
01349
01350 p = _dbus_string_get_const_data_len (str, start,
01351 _dbus_string_get_length (str) - start);
01352
01353 end = NULL;
01354 errno = 0;
01355 v = ascii_strtod (p, &end);
01356 if (end == NULL || end == p || errno != 0)
01357 return FALSE;
01358
01359 if (value_return)
01360 *value_return = v;
01361 if (end_return)
01362 *end_return = start + (end - p);
01363
01364 return TRUE;
01365 }
01366
01368
01373 static dbus_bool_t
01374 fill_user_info_from_passwd (struct passwd *p,
01375 DBusUserInfo *info,
01376 DBusError *error)
01377 {
01378 _dbus_assert (p->pw_name != NULL);
01379 _dbus_assert (p->pw_dir != NULL);
01380
01381 info->uid = p->pw_uid;
01382 info->primary_gid = p->pw_gid;
01383 info->username = _dbus_strdup (p->pw_name);
01384 info->homedir = _dbus_strdup (p->pw_dir);
01385
01386 if (info->username == NULL ||
01387 info->homedir == NULL)
01388 {
01389 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
01390 return FALSE;
01391 }
01392
01393 return TRUE;
01394 }
01395
01396 static dbus_bool_t
01397 fill_user_info (DBusUserInfo *info,
01398 dbus_uid_t uid,
01399 const DBusString *username,
01400 DBusError *error)
01401 {
01402 const char *username_c;
01403
01404
01405 _dbus_assert (username != NULL || uid != DBUS_UID_UNSET);
01406 _dbus_assert (username == NULL || uid == DBUS_UID_UNSET);
01407
01408 info->uid = DBUS_UID_UNSET;
01409 info->primary_gid = DBUS_GID_UNSET;
01410 info->group_ids = NULL;
01411 info->n_group_ids = 0;
01412 info->username = NULL;
01413 info->homedir = NULL;
01414
01415 if (username != NULL)
01416 username_c = _dbus_string_get_const_data (username);
01417 else
01418 username_c = NULL;
01419
01420
01421
01422
01423
01424
01425 #if defined (HAVE_POSIX_GETPWNAME_R) || defined (HAVE_NONPOSIX_GETPWNAME_R)
01426 {
01427 struct passwd *p;
01428 int result;
01429 char buf[1024];
01430 struct passwd p_str;
01431
01432 p = NULL;
01433 #ifdef HAVE_POSIX_GETPWNAME_R
01434 if (uid >= 0)
01435 result = getpwuid_r (uid, &p_str, buf, sizeof (buf),
01436 &p);
01437 else
01438 result = getpwnam_r (username_c, &p_str, buf, sizeof (buf),
01439 &p);
01440 #else
01441 if (uid != DBUS_UID_UNSET)
01442 p = getpwuid_r (uid, &p_str, buf, sizeof (buf));
01443 else
01444 p = getpwnam_r (username_c, &p_str, buf, sizeof (buf));
01445 result = 0;
01446 #endif
01447 if (result == 0 && p == &p_str)
01448 {
01449 if (!fill_user_info_from_passwd (p, info, error))
01450 return FALSE;
01451 }
01452 else
01453 {
01454 dbus_set_error (error, _dbus_error_from_errno (errno),
01455 "User \"%s\" unknown or no memory to allocate password entry\n",
01456 username_c ? username_c : "???");
01457 _dbus_verbose ("User %s unknown\n", username_c ? username_c : "???");
01458 return FALSE;
01459 }
01460 }
01461 #else
01462 {
01463
01464 struct passwd *p;
01465
01466 if (uid != DBUS_UID_UNSET)
01467 p = getpwuid (uid);
01468 else
01469 p = getpwnam (username_c);
01470
01471 if (p != NULL)
01472 {
01473 if (!fill_user_info_from_passwd (p, info, error))
01474 return FALSE;
01475 }
01476 else
01477 {
01478 dbus_set_error (error, _dbus_error_from_errno (errno),
01479 "User \"%s\" unknown or no memory to allocate password entry\n",
01480 username_c ? username_c : "???");
01481 _dbus_verbose ("User %s unknown\n", username_c ? username_c : "???");
01482 return FALSE;
01483 }
01484 }
01485 #endif
01486
01487
01488 username_c = info->username;
01489
01490 #ifdef HAVE_GETGROUPLIST
01491 {
01492 gid_t *buf;
01493 int buf_count;
01494 int i;
01495
01496 buf_count = 17;
01497 buf = dbus_new (gid_t, buf_count);
01498 if (buf == NULL)
01499 {
01500 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
01501 goto failed;
01502 }
01503
01504 if (getgrouplist (username_c,
01505 info->primary_gid,
01506 buf, &buf_count) < 0)
01507 {
01508 gid_t *new = dbus_realloc (buf, buf_count * sizeof (buf[0]));
01509 if (new == NULL)
01510 {
01511 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
01512 dbus_free (buf);
01513 goto failed;
01514 }
01515
01516 buf = new;
01517
01518 errno = 0;
01519 if (getgrouplist (username_c, info->primary_gid, buf, &buf_count) < 0)
01520 {
01521 dbus_set_error (error,
01522 _dbus_error_from_errno (errno),
01523 "Failed to get groups for username \"%s\" primary GID "
01524 DBUS_GID_FORMAT ": %s\n",
01525 username_c, info->primary_gid,
01526 _dbus_strerror (errno));
01527 dbus_free (buf);
01528 goto failed;
01529 }
01530 }
01531
01532 info->group_ids = dbus_new (dbus_gid_t, buf_count);
01533 if (info->group_ids == NULL)
01534 {
01535 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
01536 dbus_free (buf);
01537 goto failed;
01538 }
01539
01540 for (i = 0; i < buf_count; ++i)
01541 info->group_ids[i] = buf[i];
01542
01543 info->n_group_ids = buf_count;
01544
01545 dbus_free (buf);
01546 }
01547 #else
01548 {
01549
01550 info->group_ids = dbus_new (dbus_gid_t, 1);
01551 if (info->group_ids == NULL)
01552 {
01553 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
01554 goto out;
01555 }
01556
01557 info->n_group_ids = 1;
01558
01559 (info->group_ids)[0] = info->primary_gid;
01560 }
01561 #endif
01562
01563 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
01564
01565 return TRUE;
01566
01567 failed:
01568 _DBUS_ASSERT_ERROR_IS_SET (error);
01569 _dbus_user_info_free (info);
01570 return FALSE;
01571 }
01572
01581 dbus_bool_t
01582 _dbus_user_info_fill (DBusUserInfo *info,
01583 const DBusString *username,
01584 DBusError *error)
01585 {
01586 return fill_user_info (info, DBUS_UID_UNSET,
01587 username, error);
01588 }
01589
01598 dbus_bool_t
01599 _dbus_user_info_fill_uid (DBusUserInfo *info,
01600 dbus_uid_t uid,
01601 DBusError *error)
01602 {
01603 return fill_user_info (info, uid,
01604 NULL, error);
01605 }
01606
01612 void
01613 _dbus_user_info_free (DBusUserInfo *info)
01614 {
01615 dbus_free (info->group_ids);
01616 dbus_free (info->username);
01617 dbus_free (info->homedir);
01618 }
01619
01620 static dbus_bool_t
01621 fill_user_info_from_group (struct group *g,
01622 DBusGroupInfo *info,
01623 DBusError *error)
01624 {
01625 _dbus_assert (g->gr_name != NULL);
01626
01627 info->gid = g->gr_gid;
01628 info->groupname = _dbus_strdup (g->gr_name);
01629
01630
01631
01632 if (info->groupname == NULL)
01633 {
01634 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
01635 return FALSE;
01636 }
01637
01638 return TRUE;
01639 }
01640
01641 static dbus_bool_t
01642 fill_group_info (DBusGroupInfo *info,
01643 dbus_gid_t gid,
01644 const DBusString *groupname,
01645 DBusError *error)
01646 {
01647 const char *group_c_str;
01648
01649 _dbus_assert (groupname != NULL || gid != DBUS_GID_UNSET);
01650 _dbus_assert (groupname == NULL || gid == DBUS_GID_UNSET);
01651
01652 if (groupname)
01653 group_c_str = _dbus_string_get_const_data (groupname);
01654 else
01655 group_c_str = NULL;
01656
01657
01658
01659
01660
01661
01662 #if defined (HAVE_POSIX_GETPWNAME_R) || defined (HAVE_NONPOSIX_GETPWNAME_R)
01663 {
01664 struct group *g;
01665 int result;
01666 char buf[1024];
01667 struct group g_str;
01668
01669 g = NULL;
01670 #ifdef HAVE_POSIX_GETPWNAME_R
01671
01672 if (group_c_str)
01673 result = getgrnam_r (group_c_str, &g_str, buf, sizeof (buf),
01674 &g);
01675 else
01676 result = getgrgid_r (gid, &g_str, buf, sizeof (buf),
01677 &g);
01678 #else
01679 p = getgrnam_r (group_c_str, &g_str, buf, sizeof (buf));
01680 result = 0;
01681 #endif
01682 if (result == 0 && g == &g_str)
01683 {
01684 return fill_user_info_from_group (g, info, error);
01685 }
01686 else
01687 {
01688 dbus_set_error (error, _dbus_error_from_errno (errno),
01689 "Group %s unknown or failed to look it up\n",
01690 group_c_str ? group_c_str : "???");
01691 return FALSE;
01692 }
01693 }
01694 #else
01695 {
01696
01697 struct group *g;
01698
01699 g = getgrnam (group_c_str);
01700
01701 if (g != NULL)
01702 {
01703 return fill_user_info_from_group (g, info, error);
01704 }
01705 else
01706 {
01707 dbus_set_error (error, _dbus_error_from_errno (errno),
01708 "Group %s unknown or failed to look it up\n",
01709 group_c_str ? group_c_str : "???");
01710 return FALSE;
01711 }
01712 }
01713 #endif
01714 }
01715
01725 dbus_bool_t
01726 _dbus_group_info_fill (DBusGroupInfo *info,
01727 const DBusString *groupname,
01728 DBusError *error)
01729 {
01730 return fill_group_info (info, DBUS_GID_UNSET,
01731 groupname, error);
01732
01733 }
01734
01744 dbus_bool_t
01745 _dbus_group_info_fill_gid (DBusGroupInfo *info,
01746 dbus_gid_t gid,
01747 DBusError *error)
01748 {
01749 return fill_group_info (info, gid, NULL, error);
01750 }
01751
01757 void
01758 _dbus_group_info_free (DBusGroupInfo *info)
01759 {
01760 dbus_free (info->groupname);
01761 }
01762
01769 void
01770 _dbus_credentials_clear (DBusCredentials *credentials)
01771 {
01772 credentials->pid = DBUS_PID_UNSET;
01773 credentials->uid = DBUS_UID_UNSET;
01774 credentials->gid = DBUS_GID_UNSET;
01775 }
01776
01782 void
01783 _dbus_credentials_from_current_process (DBusCredentials *credentials)
01784 {
01785
01786
01787
01788
01789 _dbus_assert (sizeof (pid_t) <= sizeof (credentials->pid));
01790 _dbus_assert (sizeof (uid_t) <= sizeof (credentials->uid));
01791 _dbus_assert (sizeof (gid_t) <= sizeof (credentials->gid));
01792
01793 credentials->pid = getpid ();
01794 credentials->uid = getuid ();
01795 credentials->gid = getgid ();
01796 }
01797
01806 dbus_bool_t
01807 _dbus_credentials_match (const DBusCredentials *expected_credentials,
01808 const DBusCredentials *provided_credentials)
01809 {
01810 if (provided_credentials->uid == DBUS_UID_UNSET)
01811 return FALSE;
01812 else if (expected_credentials->uid == DBUS_UID_UNSET)
01813 return FALSE;
01814 else if (provided_credentials->uid == 0)
01815 return TRUE;
01816 else if (provided_credentials->uid == expected_credentials->uid)
01817 return TRUE;
01818 else
01819 return FALSE;
01820 }
01821
01826 unsigned long
01827 _dbus_getpid (void)
01828 {
01829 return getpid ();
01830 }
01831
01835 dbus_uid_t
01836 _dbus_getuid (void)
01837 {
01838 return getuid ();
01839 }
01840
01844 dbus_gid_t
01845 _dbus_getgid (void)
01846 {
01847 return getgid ();
01848 }
01849
01850 _DBUS_DEFINE_GLOBAL_LOCK (atomic);
01851
01852 #ifdef DBUS_USE_ATOMIC_INT_486
01853
01854
01855 static inline dbus_int32_t
01856 atomic_exchange_and_add (DBusAtomic *atomic,
01857 volatile dbus_int32_t val)
01858 {
01859 register dbus_int32_t result;
01860
01861 __asm__ __volatile__ ("lock; xaddl %0,%1"
01862 : "=r" (result), "=m" (atomic->value)
01863 : "0" (val), "m" (atomic->value));
01864 return result;
01865 }
01866 #endif
01867
01876 dbus_int32_t
01877 _dbus_atomic_inc (DBusAtomic *atomic)
01878 {
01879 #ifdef DBUS_USE_ATOMIC_INT_486
01880 return atomic_exchange_and_add (atomic, 1);
01881 #else
01882 dbus_int32_t res;
01883 _DBUS_LOCK (atomic);
01884 res = atomic->value;
01885 atomic->value += 1;
01886 _DBUS_UNLOCK (atomic);
01887 return res;
01888 #endif
01889 }
01890
01899 dbus_int32_t
01900 _dbus_atomic_dec (DBusAtomic *atomic)
01901 {
01902 #ifdef DBUS_USE_ATOMIC_INT_486
01903 return atomic_exchange_and_add (atomic, -1);
01904 #else
01905 dbus_int32_t res;
01906
01907 _DBUS_LOCK (atomic);
01908 res = atomic->value;
01909 atomic->value -= 1;
01910 _DBUS_UNLOCK (atomic);
01911 return res;
01912 #endif
01913 }
01914
01925 int
01926 _dbus_poll (DBusPollFD *fds,
01927 int n_fds,
01928 int timeout_milliseconds)
01929 {
01930 #ifdef HAVE_POLL
01931
01932
01933
01934
01935 if (_DBUS_POLLIN == POLLIN &&
01936 _DBUS_POLLPRI == POLLPRI &&
01937 _DBUS_POLLOUT == POLLOUT &&
01938 _DBUS_POLLERR == POLLERR &&
01939 _DBUS_POLLHUP == POLLHUP &&
01940 _DBUS_POLLNVAL == POLLNVAL &&
01941 sizeof (DBusPollFD) == sizeof (struct pollfd) &&
01942 _DBUS_STRUCT_OFFSET (DBusPollFD, fd) ==
01943 _DBUS_STRUCT_OFFSET (struct pollfd, fd) &&
01944 _DBUS_STRUCT_OFFSET (DBusPollFD, events) ==
01945 _DBUS_STRUCT_OFFSET (struct pollfd, events) &&
01946 _DBUS_STRUCT_OFFSET (DBusPollFD, revents) ==
01947 _DBUS_STRUCT_OFFSET (struct pollfd, revents))
01948 {
01949 return poll ((struct pollfd*) fds,
01950 n_fds,
01951 timeout_milliseconds);
01952 }
01953 else
01954 {
01955
01956
01957
01958 _dbus_warn ("didn't implement poll() properly for this system yet\n");
01959 return -1;
01960 }
01961 #else
01962
01963 fd_set read_set, write_set, err_set;
01964 int max_fd = 0;
01965 int i;
01966 struct timeval tv;
01967 int ready;
01968
01969 FD_ZERO (&read_set);
01970 FD_ZERO (&write_set);
01971 FD_ZERO (&err_set);
01972
01973 for (i = 0; i < n_fds; i++)
01974 {
01975 DBusPollFD f = fds[i];
01976
01977 if (f.events & _DBUS_POLLIN)
01978 FD_SET (f.fd, &read_set);
01979
01980 if (f.events & _DBUS_POLLOUT)
01981 FD_SET (f.fd, &write_set);
01982
01983 FD_SET (f.fd, &err_set);
01984
01985 max_fd = MAX (max_fd, f.fd);
01986 }
01987
01988 tv.tv_sec = timeout_milliseconds / 1000;
01989 tv.tv_usec = (timeout_milliseconds % 1000) * 1000;
01990
01991 ready = select (max_fd + 1, &read_set, &write_set, &err_set, &tv);
01992
01993 if (ready > 0)
01994 {
01995 for (i = 0; i < n_fds; i++)
01996 {
01997 DBusPollFD f = fds[i];
01998
01999 f.revents = 0;
02000
02001 if (FD_ISSET (f.fd, &read_set))
02002 f.revents |= _DBUS_POLLIN;
02003
02004 if (FD_ISSET (f.fd, &write_set))
02005 f.revents |= _DBUS_POLLOUT;
02006
02007 if (FD_ISSET (f.fd, &err_set))
02008 f.revents |= _DBUS_POLLERR;
02009 }
02010 }
02011
02012 return ready;
02013 #endif
02014 }
02015
02017 #define NANOSECONDS_PER_SECOND 1000000000
02018
02019 #define MICROSECONDS_PER_SECOND 1000000
02020
02021 #define MILLISECONDS_PER_SECOND 1000
02022
02023 #define NANOSECONDS_PER_MILLISECOND 1000000
02024
02025 #define MICROSECONDS_PER_MILLISECOND 1000
02026
02031 void
02032 _dbus_sleep_milliseconds (int milliseconds)
02033 {
02034 #ifdef HAVE_NANOSLEEP
02035 struct timespec req;
02036 struct timespec rem;
02037
02038 req.tv_sec = milliseconds / MILLISECONDS_PER_SECOND;
02039 req.tv_nsec = (milliseconds % MILLISECONDS_PER_SECOND) * NANOSECONDS_PER_MILLISECOND;
02040 rem.tv_sec = 0;
02041 rem.tv_nsec = 0;
02042
02043 while (nanosleep (&req, &rem) < 0 && errno == EINTR)
02044 req = rem;
02045 #elif defined (HAVE_USLEEP)
02046 usleep (milliseconds * MICROSECONDS_PER_MILLISECOND);
02047 #else
02048 sleep (MAX (milliseconds / 1000, 1));
02049 #endif
02050 }
02051
02058 void
02059 _dbus_get_current_time (long *tv_sec,
02060 long *tv_usec)
02061 {
02062 struct timeval t;
02063
02064 gettimeofday (&t, NULL);
02065
02066 if (tv_sec)
02067 *tv_sec = t.tv_sec;
02068 if (tv_usec)
02069 *tv_usec = t.tv_usec;
02070 }
02071
02082 dbus_bool_t
02083 _dbus_file_get_contents (DBusString *str,
02084 const DBusString *filename,
02085 DBusError *error)
02086 {
02087 int fd;
02088 struct stat sb;
02089 int orig_len;
02090 int total;
02091 const char *filename_c;
02092
02093 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
02094
02095 filename_c = _dbus_string_get_const_data (filename);
02096
02097
02098 fd = open (filename_c, O_RDONLY | O_BINARY);
02099 if (fd < 0)
02100 {
02101 dbus_set_error (error, _dbus_error_from_errno (errno),
02102 "Failed to open \"%s\": %s",
02103 filename_c,
02104 _dbus_strerror (errno));
02105 return FALSE;
02106 }
02107
02108 if (fstat (fd, &sb) < 0)
02109 {
02110 dbus_set_error (error, _dbus_error_from_errno (errno),
02111 "Failed to stat \"%s\": %s",
02112 filename_c,
02113 _dbus_strerror (errno));
02114
02115 _dbus_verbose ("fstat() failed: %s",
02116 _dbus_strerror (errno));
02117
02118 close (fd);
02119
02120 return FALSE;
02121 }
02122
02123 if (sb.st_size > _DBUS_ONE_MEGABYTE)
02124 {
02125 dbus_set_error (error, DBUS_ERROR_FAILED,
02126 "File size %lu of \"%s\" is too large.",
02127 filename_c, (unsigned long) sb.st_size);
02128 close (fd);
02129 return FALSE;
02130 }
02131
02132 total = 0;
02133 orig_len = _dbus_string_get_length (str);
02134 if (sb.st_size > 0 && S_ISREG (sb.st_mode))
02135 {
02136 int bytes_read;
02137
02138 while (total < (int) sb.st_size)
02139 {
02140 bytes_read = _dbus_read (fd, str,
02141 sb.st_size - total);
02142 if (bytes_read <= 0)
02143 {
02144 dbus_set_error (error, _dbus_error_from_errno (errno),
02145 "Error reading \"%s\": %s",
02146 filename_c,
02147 _dbus_strerror (errno));
02148
02149 _dbus_verbose ("read() failed: %s",
02150 _dbus_strerror (errno));
02151
02152 close (fd);
02153 _dbus_string_set_length (str, orig_len);
02154 return FALSE;
02155 }
02156 else
02157 total += bytes_read;
02158 }
02159
02160 close (fd);
02161 return TRUE;
02162 }
02163 else if (sb.st_size != 0)
02164 {
02165 _dbus_verbose ("Can only open regular files at the moment.\n");
02166 dbus_set_error (error, DBUS_ERROR_FAILED,
02167 "\"%s\" is not a regular file",
02168 filename_c);
02169 close (fd);
02170 return FALSE;
02171 }
02172 else
02173 {
02174 close (fd);
02175 return TRUE;
02176 }
02177 }
02178
02188 dbus_bool_t
02189 _dbus_string_save_to_file (const DBusString *str,
02190 const DBusString *filename,
02191 DBusError *error)
02192 {
02193 int fd;
02194 int bytes_to_write;
02195 const char *filename_c;
02196 DBusString tmp_filename;
02197 const char *tmp_filename_c;
02198 int total;
02199 dbus_bool_t need_unlink;
02200 dbus_bool_t retval;
02201
02202 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
02203
02204 fd = -1;
02205 retval = FALSE;
02206 need_unlink = FALSE;
02207
02208 if (!_dbus_string_init (&tmp_filename))
02209 {
02210 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
02211 return FALSE;
02212 }
02213
02214 if (!_dbus_string_copy (filename, 0, &tmp_filename, 0))
02215 {
02216 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
02217 _dbus_string_free (&tmp_filename);
02218 return FALSE;
02219 }
02220
02221 if (!_dbus_string_append (&tmp_filename, "."))
02222 {
02223 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
02224 _dbus_string_free (&tmp_filename);
02225 return FALSE;
02226 }
02227
02228 #define N_TMP_FILENAME_RANDOM_BYTES 8
02229 if (!_dbus_generate_random_ascii (&tmp_filename, N_TMP_FILENAME_RANDOM_BYTES))
02230 {
02231 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
02232 _dbus_string_free (&tmp_filename);
02233 return FALSE;
02234 }
02235
02236 filename_c = _dbus_string_get_const_data (filename);
02237 tmp_filename_c = _dbus_string_get_const_data (&tmp_filename);
02238
02239 fd = open (tmp_filename_c, O_WRONLY | O_BINARY | O_EXCL | O_CREAT,
02240 0600);
02241 if (fd < 0)
02242 {
02243 dbus_set_error (error, _dbus_error_from_errno (errno),
02244 "Could not create %s: %s", tmp_filename_c,
02245 _dbus_strerror (errno));
02246 goto out;
02247 }
02248
02249 need_unlink = TRUE;
02250
02251 total = 0;
02252 bytes_to_write = _dbus_string_get_length (str);
02253
02254 while (total < bytes_to_write)
02255 {
02256 int bytes_written;
02257
02258 bytes_written = _dbus_write (fd, str, total,
02259 bytes_to_write - total);
02260
02261 if (bytes_written <= 0)
02262 {
02263 dbus_set_error (error, _dbus_error_from_errno (errno),
02264 "Could not write to %s: %s", tmp_filename_c,
02265 _dbus_strerror (errno));
02266
02267 goto out;
02268 }
02269
02270 total += bytes_written;
02271 }
02272
02273 if (close (fd) < 0)
02274 {
02275 dbus_set_error (error, _dbus_error_from_errno (errno),
02276 "Could not close file %s: %s",
02277 tmp_filename_c, _dbus_strerror (errno));
02278
02279 goto out;
02280 }
02281
02282 fd = -1;
02283
02284 if (rename (tmp_filename_c, filename_c) < 0)
02285 {
02286 dbus_set_error (error, _dbus_error_from_errno (errno),
02287 "Could not rename %s to %s: %s",
02288 tmp_filename_c, filename_c,
02289 _dbus_strerror (errno));
02290
02291 goto out;
02292 }
02293
02294 need_unlink = FALSE;
02295
02296 retval = TRUE;
02297
02298 out:
02299
02300
02301
02302
02303 if (fd >= 0)
02304 close (fd);
02305
02306 if (need_unlink && unlink (tmp_filename_c) < 0)
02307 _dbus_verbose ("Failed to unlink temp file %s: %s\n",
02308 tmp_filename_c, _dbus_strerror (errno));
02309
02310 _dbus_string_free (&tmp_filename);
02311
02312 if (!retval)
02313 _DBUS_ASSERT_ERROR_IS_SET (error);
02314
02315 return retval;
02316 }
02317
02324 dbus_bool_t
02325 _dbus_create_file_exclusively (const DBusString *filename,
02326 DBusError *error)
02327 {
02328 int fd;
02329 const char *filename_c;
02330
02331 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
02332
02333 filename_c = _dbus_string_get_const_data (filename);
02334
02335 fd = open (filename_c, O_WRONLY | O_BINARY | O_EXCL | O_CREAT,
02336 0600);
02337 if (fd < 0)
02338 {
02339 dbus_set_error (error,
02340 DBUS_ERROR_FAILED,
02341 "Could not create file %s: %s\n",
02342 filename_c,
02343 _dbus_strerror (errno));
02344 return FALSE;
02345 }
02346
02347 if (close (fd) < 0)
02348 {
02349 dbus_set_error (error,
02350 DBUS_ERROR_FAILED,
02351 "Could not close file %s: %s\n",
02352 filename_c,
02353 _dbus_strerror (errno));
02354 return FALSE;
02355 }
02356
02357 return TRUE;
02358 }
02359
02368 dbus_bool_t
02369 _dbus_delete_file (const DBusString *filename,
02370 DBusError *error)
02371 {
02372 const char *filename_c;
02373
02374 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
02375
02376 filename_c = _dbus_string_get_const_data (filename);
02377
02378 if (unlink (filename_c) < 0)
02379 {
02380 dbus_set_error (error, DBUS_ERROR_FAILED,
02381 "Failed to delete file %s: %s\n",
02382 filename_c, _dbus_strerror (errno));
02383 return FALSE;
02384 }
02385 else
02386 return TRUE;
02387 }
02388
02397 dbus_bool_t
02398 _dbus_create_directory (const DBusString *filename,
02399 DBusError *error)
02400 {
02401 const char *filename_c;
02402
02403 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
02404
02405 filename_c = _dbus_string_get_const_data (filename);
02406
02407 if (mkdir (filename_c, 0700) < 0)
02408 {
02409 if (errno == EEXIST)
02410 return TRUE;
02411
02412 dbus_set_error (error, DBUS_ERROR_FAILED,
02413 "Failed to create directory %s: %s\n",
02414 filename_c, _dbus_strerror (errno));
02415 return FALSE;
02416 }
02417 else
02418 return TRUE;
02419 }
02420
02431 dbus_bool_t
02432 _dbus_concat_dir_and_file (DBusString *dir,
02433 const DBusString *next_component)
02434 {
02435 dbus_bool_t dir_ends_in_slash;
02436 dbus_bool_t file_starts_with_slash;
02437
02438 if (_dbus_string_get_length (dir) == 0 ||
02439 _dbus_string_get_length (next_component) == 0)
02440 return TRUE;
02441
02442 dir_ends_in_slash = '/' == _dbus_string_get_byte (dir,
02443 _dbus_string_get_length (dir) - 1);
02444
02445 file_starts_with_slash = '/' == _dbus_string_get_byte (next_component, 0);
02446
02447 if (dir_ends_in_slash && file_starts_with_slash)
02448 {
02449 _dbus_string_shorten (dir, 1);
02450 }
02451 else if (!(dir_ends_in_slash || file_starts_with_slash))
02452 {
02453 if (!_dbus_string_append_byte (dir, '/'))
02454 return FALSE;
02455 }
02456
02457 return _dbus_string_copy (next_component, 0, dir,
02458 _dbus_string_get_length (dir));
02459 }
02460
02467 dbus_bool_t
02468 _dbus_string_get_dirname (const DBusString *filename,
02469 DBusString *dirname)
02470 {
02471 int sep;
02472
02473 _dbus_assert (filename != dirname);
02474 _dbus_assert (filename != NULL);
02475 _dbus_assert (dirname != NULL);
02476
02477
02478 sep = _dbus_string_get_length (filename);
02479 if (sep == 0)
02480 return _dbus_string_append (dirname, ".");
02481
02482 while (sep > 0 && _dbus_string_get_byte (filename, sep - 1) == '/')
02483 --sep;
02484
02485 _dbus_assert (sep >= 0);
02486
02487 if (sep == 0)
02488 return _dbus_string_append (dirname, "/");
02489
02490
02491 _dbus_string_find_byte_backward (filename, sep, '/', &sep);
02492 if (sep < 0)
02493 return _dbus_string_append (dirname, ".");
02494
02495
02496 while (sep > 0 && _dbus_string_get_byte (filename, sep - 1) == '/')
02497 --sep;
02498
02499 _dbus_assert (sep >= 0);
02500
02501 if (sep == 0 &&
02502 _dbus_string_get_byte (filename, 0) == '/')
02503 return _dbus_string_append (dirname, "/");
02504 else
02505 return _dbus_string_copy_len (filename, 0, sep - 0,
02506 dirname, _dbus_string_get_length (dirname));
02507 }
02508
02515 dbus_bool_t
02516 _dbus_path_is_absolute (const DBusString *filename)
02517 {
02518 if (_dbus_string_get_length (filename) > 0)
02519 return _dbus_string_get_byte (filename, 0) == '/';
02520 else
02521 return FALSE;
02522 }
02523
02527 struct DBusDirIter
02528 {
02529 DIR *d;
02531 };
02532
02540 DBusDirIter*
02541 _dbus_directory_open (const DBusString *filename,
02542 DBusError *error)
02543 {
02544 DIR *d;
02545 DBusDirIter *iter;
02546 const char *filename_c;
02547
02548 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
02549
02550 filename_c = _dbus_string_get_const_data (filename);
02551
02552 d = opendir (filename_c);
02553 if (d == NULL)
02554 {
02555 dbus_set_error (error, _dbus_error_from_errno (errno),
02556 "Failed to read directory \"%s\": %s",
02557 filename_c,
02558 _dbus_strerror (errno));
02559 return NULL;
02560 }
02561 iter = dbus_new0 (DBusDirIter, 1);
02562 if (iter == NULL)
02563 {
02564 closedir (d);
02565 dbus_set_error (error, DBUS_ERROR_NO_MEMORY,
02566 "Could not allocate memory for directory iterator");
02567 return NULL;
02568 }
02569
02570 iter->d = d;
02571
02572 return iter;
02573 }
02574
02588 dbus_bool_t
02589 _dbus_directory_get_next_file (DBusDirIter *iter,
02590 DBusString *filename,
02591 DBusError *error)
02592 {
02593 struct dirent *ent;
02594
02595 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
02596
02597 again:
02598 errno = 0;
02599 ent = readdir (iter->d);
02600 if (ent == NULL)
02601 {
02602 if (errno != 0)
02603 dbus_set_error (error,
02604 _dbus_error_from_errno (errno),
02605 "%s", _dbus_strerror (errno));
02606 return FALSE;
02607 }
02608 else if (ent->d_name[0] == '.' &&
02609 (ent->d_name[1] == '\0' ||
02610 (ent->d_name[1] == '.' && ent->d_name[2] == '\0')))
02611 goto again;
02612 else
02613 {
02614 _dbus_string_set_length (filename, 0);
02615 if (!_dbus_string_append (filename, ent->d_name))
02616 {
02617 dbus_set_error (error, DBUS_ERROR_NO_MEMORY,
02618 "No memory to read directory entry");
02619 return FALSE;
02620 }
02621 else
02622 return TRUE;
02623 }
02624 }
02625
02629 void
02630 _dbus_directory_close (DBusDirIter *iter)
02631 {
02632 closedir (iter->d);
02633 dbus_free (iter);
02634 }
02635
02636 static dbus_bool_t
02637 pseudorandom_generate_random_bytes (DBusString *str,
02638 int n_bytes)
02639 {
02640 int old_len;
02641 unsigned long tv_usec;
02642 int i;
02643
02644 old_len = _dbus_string_get_length (str);
02645
02646
02647 _dbus_verbose ("Falling back to pseudorandom for %d bytes\n",
02648 n_bytes);
02649
02650 _dbus_get_current_time (NULL, &tv_usec);
02651 srand (tv_usec);
02652
02653 i = 0;
02654 while (i < n_bytes)
02655 {
02656 double r;
02657 unsigned int b;
02658
02659 r = rand ();
02660 b = (r / (double) RAND_MAX) * 255.0;
02661
02662 if (!_dbus_string_append_byte (str, b))
02663 goto failed;
02664
02665 ++i;
02666 }
02667
02668 return TRUE;
02669
02670 failed:
02671 _dbus_string_set_length (str, old_len);
02672 return FALSE;
02673 }
02674
02683 dbus_bool_t
02684 _dbus_generate_random_bytes (DBusString *str,
02685 int n_bytes)
02686 {
02687 int old_len;
02688 int fd;
02689
02690
02691
02692
02693
02694
02695
02696 old_len = _dbus_string_get_length (str);
02697 fd = -1;
02698
02699
02700 fd = open ("/dev/urandom", O_RDONLY);
02701 if (fd < 0)
02702 return pseudorandom_generate_random_bytes (str, n_bytes);
02703
02704 if (_dbus_read (fd, str, n_bytes) != n_bytes)
02705 {
02706 close (fd);
02707 _dbus_string_set_length (str, old_len);
02708 return pseudorandom_generate_random_bytes (str, n_bytes);
02709 }
02710
02711 _dbus_verbose ("Read %d bytes from /dev/urandom\n",
02712 n_bytes);
02713
02714 close (fd);
02715
02716 return TRUE;
02717 }
02718
02727 dbus_bool_t
02728 _dbus_generate_random_ascii (DBusString *str,
02729 int n_bytes)
02730 {
02731 static const char letters[] =
02732 "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789abcdefghijklmnopqrstuvwxyz";
02733 int i;
02734 int len;
02735
02736 if (!_dbus_generate_random_bytes (str, n_bytes))
02737 return FALSE;
02738
02739 len = _dbus_string_get_length (str);
02740 i = len - n_bytes;
02741 while (i < len)
02742 {
02743 _dbus_string_set_byte (str, i,
02744 letters[_dbus_string_get_byte (str, i) %
02745 (sizeof (letters) - 1)]);
02746
02747 ++i;
02748 }
02749
02750 _dbus_assert (_dbus_string_validate_ascii (str, len - n_bytes,
02751 n_bytes));
02752
02753 return TRUE;
02754 }
02755
02763 const char*
02764 _dbus_strerror (int error_number)
02765 {
02766 const char *msg;
02767
02768 msg = strerror (error_number);
02769 if (msg == NULL)
02770 msg = "unknown";
02771
02772 return msg;
02773 }
02774
02778 void
02779 _dbus_disable_sigpipe (void)
02780 {
02781 signal (SIGPIPE, SIG_IGN);
02782 }
02783
02791 void
02792 _dbus_fd_set_close_on_exec (int fd)
02793 {
02794 int val;
02795
02796 val = fcntl (fd, F_GETFD, 0);
02797
02798 if (val < 0)
02799 return;
02800
02801 val |= FD_CLOEXEC;
02802
02803 fcntl (fd, F_SETFD, val);
02804 }
02805
02815 const char*
02816 _dbus_error_from_errno (int error_number)
02817 {
02818 switch (error_number)
02819 {
02820 case 0:
02821 return DBUS_ERROR_FAILED;
02822
02823 #ifdef EPROTONOSUPPORT
02824 case EPROTONOSUPPORT:
02825 return DBUS_ERROR_NOT_SUPPORTED;
02826 #endif
02827 #ifdef EAFNOSUPPORT
02828 case EAFNOSUPPORT:
02829 return DBUS_ERROR_NOT_SUPPORTED;
02830 #endif
02831 #ifdef ENFILE
02832 case ENFILE:
02833 return DBUS_ERROR_LIMITS_EXCEEDED;
02834 #endif
02835 #ifdef EMFILE
02836 case EMFILE:
02837 return DBUS_ERROR_LIMITS_EXCEEDED;
02838 #endif
02839 #ifdef EACCES
02840 case EACCES:
02841 return DBUS_ERROR_ACCESS_DENIED;
02842 #endif
02843 #ifdef EPERM
02844 case EPERM:
02845 return DBUS_ERROR_ACCESS_DENIED;
02846 #endif
02847 #ifdef ENOBUFS
02848 case ENOBUFS:
02849 return DBUS_ERROR_NO_MEMORY;
02850 #endif
02851 #ifdef ENOMEM
02852 case ENOMEM:
02853 return DBUS_ERROR_NO_MEMORY;
02854 #endif
02855 #ifdef EINVAL
02856 case EINVAL:
02857 return DBUS_ERROR_FAILED;
02858 #endif
02859 #ifdef EBADF
02860 case EBADF:
02861 return DBUS_ERROR_FAILED;
02862 #endif
02863 #ifdef EFAULT
02864 case EFAULT:
02865 return DBUS_ERROR_FAILED;
02866 #endif
02867 #ifdef ENOTSOCK
02868 case ENOTSOCK:
02869 return DBUS_ERROR_FAILED;
02870 #endif
02871 #ifdef EISCONN
02872 case EISCONN:
02873 return DBUS_ERROR_FAILED;
02874 #endif
02875 #ifdef ECONNREFUSED
02876 case ECONNREFUSED:
02877 return DBUS_ERROR_NO_SERVER;
02878 #endif
02879 #ifdef ETIMEDOUT
02880 case ETIMEDOUT:
02881 return DBUS_ERROR_TIMEOUT;
02882 #endif
02883 #ifdef ENETUNREACH
02884 case ENETUNREACH:
02885 return DBUS_ERROR_NO_NETWORK;
02886 #endif
02887 #ifdef EADDRINUSE
02888 case EADDRINUSE:
02889 return DBUS_ERROR_ADDRESS_IN_USE;
02890 #endif
02891 #ifdef EEXIST
02892 case EEXIST:
02893 return DBUS_ERROR_FILE_NOT_FOUND;
02894 #endif
02895 #ifdef ENOENT
02896 case ENOENT:
02897 return DBUS_ERROR_FILE_NOT_FOUND;
02898 #endif
02899 }
02900
02901 return DBUS_ERROR_FAILED;
02902 }
02903
02909 void
02910 _dbus_exit (int code)
02911 {
02912 _exit (code);
02913 }
02914
02923 dbus_bool_t
02924 _dbus_stat (const DBusString *filename,
02925 DBusStat *statbuf,
02926 DBusError *error)
02927 {
02928 const char *filename_c;
02929 struct stat sb;
02930
02931 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
02932
02933 filename_c = _dbus_string_get_const_data (filename);
02934
02935 if (stat (filename_c, &sb) < 0)
02936 {
02937 dbus_set_error (error, _dbus_error_from_errno (errno),
02938 "%s", _dbus_strerror (errno));
02939 return FALSE;
02940 }
02941
02942 statbuf->mode = sb.st_mode;
02943 statbuf->nlink = sb.st_nlink;
02944 statbuf->uid = sb.st_uid;
02945 statbuf->gid = sb.st_gid;
02946 statbuf->size = sb.st_size;
02947 statbuf->atime = sb.st_atime;
02948 statbuf->mtime = sb.st_mtime;
02949 statbuf->ctime = sb.st_ctime;
02950
02951 return TRUE;
02952 }
02953
02964 dbus_bool_t
02965 _dbus_full_duplex_pipe (int *fd1,
02966 int *fd2,
02967 dbus_bool_t blocking,
02968 DBusError *error)
02969 {
02970 #ifdef HAVE_SOCKETPAIR
02971 int fds[2];
02972
02973 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
02974
02975 if (socketpair (AF_UNIX, SOCK_STREAM, 0, fds) < 0)
02976 {
02977 dbus_set_error (error, _dbus_error_from_errno (errno),
02978 "Could not create full-duplex pipe");
02979 return FALSE;
02980 }
02981
02982 if (!blocking &&
02983 (!_dbus_set_fd_nonblocking (fds[0], NULL) ||
02984 !_dbus_set_fd_nonblocking (fds[1], NULL)))
02985 {
02986 dbus_set_error (error, _dbus_error_from_errno (errno),
02987 "Could not set full-duplex pipe nonblocking");
02988
02989 close (fds[0]);
02990 close (fds[1]);
02991
02992 return FALSE;
02993 }
02994
02995 *fd1 = fds[0];
02996 *fd2 = fds[1];
02997
02998 return TRUE;
02999 #else
03000 _dbus_warn ("_dbus_full_duplex_pipe() not implemented on this OS\n");
03001 dbus_set_error (error, DBUS_ERROR_FAILED,
03002 "_dbus_full_duplex_pipe() not implemented on this OS");
03003 return FALSE;
03004 #endif
03005 }
03006
03014 dbus_bool_t
03015 _dbus_close (int fd,
03016 DBusError *error)
03017 {
03018 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
03019
03020 again:
03021 if (close (fd) < 0)
03022 {
03023 if (errno == EINTR)
03024 goto again;
03025
03026 dbus_set_error (error, _dbus_error_from_errno (errno),
03027 "Could not close fd %d", fd);
03028 return FALSE;
03029 }
03030
03031 return TRUE;
03032 }
03033
03041 dbus_bool_t
03042 _dbus_set_fd_nonblocking (int fd,
03043 DBusError *error)
03044 {
03045 int val;
03046
03047 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
03048
03049 val = fcntl (fd, F_GETFL, 0);
03050 if (val < 0)
03051 {
03052 dbus_set_error (error, _dbus_error_from_errno (errno),
03053 "Failed to get flags from file descriptor %d: %s",
03054 fd, _dbus_strerror (errno));
03055 _dbus_verbose ("Failed to get flags for fd %d: %s\n", fd,
03056 _dbus_strerror (errno));
03057 return FALSE;
03058 }
03059
03060 if (fcntl (fd, F_SETFL, val | O_NONBLOCK) < 0)
03061 {
03062 dbus_set_error (error, _dbus_error_from_errno (errno),
03063 "Failed to set nonblocking flag of file descriptor %d: %s",
03064 fd, _dbus_strerror (errno));
03065 _dbus_verbose ("Failed to set fd %d nonblocking: %s\n",
03066 fd, _dbus_strerror (errno));
03067
03068 return FALSE;
03069 }
03070
03071 return TRUE;
03072 }
03073
03079 void
03080 _dbus_print_backtrace (void)
03081 {
03082 #if defined (HAVE_BACKTRACE) && defined (DBUS_ENABLE_VERBOSE_MODE)
03083 void *bt[500];
03084 int bt_size;
03085 int i;
03086 char **syms;
03087
03088 bt_size = backtrace (bt, 500);
03089
03090 syms = backtrace_symbols (bt, bt_size);
03091
03092 i = 0;
03093 while (i < bt_size)
03094 {
03095 _dbus_verbose (" %s\n", syms[i]);
03096 ++i;
03097 }
03098
03099 free (syms);
03100 #else
03101 _dbus_verbose (" D-BUS not compiled with backtrace support\n");
03102 #endif
03103 }
03104
03112 dbus_bool_t
03113 _dbus_become_daemon (const DBusString *pidfile,
03114 DBusError *error)
03115 {
03116 const char *s;
03117 pid_t child_pid;
03118 int dev_null_fd;
03119
03120 _dbus_verbose ("Becoming a daemon...\n");
03121
03122 _dbus_verbose ("chdir to /\n");
03123 if (chdir ("/") < 0)
03124 {
03125 dbus_set_error (error, DBUS_ERROR_FAILED,
03126 "Could not chdir() to root directory");
03127 return FALSE;
03128 }
03129
03130 _dbus_verbose ("forking...\n");
03131 switch ((child_pid = fork ()))
03132 {
03133 case -1:
03134 _dbus_verbose ("fork failed\n");
03135 dbus_set_error (error, _dbus_error_from_errno (errno),
03136 "Failed to fork daemon: %s", _dbus_strerror (errno));
03137 return FALSE;
03138 break;
03139
03140 case 0:
03141 _dbus_verbose ("in child, closing std file descriptors\n");
03142
03143
03144
03145
03146
03147
03148 dev_null_fd = open ("/dev/null", O_RDWR);
03149 if (dev_null_fd >= 0)
03150 {
03151 dup2 (dev_null_fd, 0);
03152 dup2 (dev_null_fd, 1);
03153
03154 s = _dbus_getenv ("DBUS_DEBUG_OUTPUT");
03155 if (s == NULL || *s == '\0')
03156 dup2 (dev_null_fd, 2);
03157 else
03158 _dbus_verbose ("keeping stderr open due to DBUS_DEBUG_OUTPUT\n");
03159 }
03160
03161
03162 _dbus_verbose ("setting umask\n");
03163 umask (022);
03164 break;
03165
03166 default:
03167 if (pidfile)
03168 {
03169 _dbus_verbose ("parent writing pid file\n");
03170 if (!_dbus_write_pid_file (pidfile,
03171 child_pid,
03172 error))
03173 {
03174 _dbus_verbose ("pid file write failed, killing child\n");
03175 kill (child_pid, SIGTERM);
03176 return FALSE;
03177 }
03178 }
03179 _dbus_verbose ("parent exiting\n");
03180 _exit (0);
03181 break;
03182 }
03183
03184 _dbus_verbose ("calling setsid()\n");
03185 if (setsid () == -1)
03186 _dbus_assert_not_reached ("setsid() failed");
03187
03188 return TRUE;
03189 }
03190
03199 dbus_bool_t
03200 _dbus_write_pid_file (const DBusString *filename,
03201 unsigned long pid,
03202 DBusError *error)
03203 {
03204 const char *cfilename;
03205 int fd;
03206 FILE *f;
03207
03208 cfilename = _dbus_string_get_const_data (filename);
03209
03210 fd = open (cfilename, O_WRONLY|O_CREAT|O_EXCL|O_BINARY, 0644);
03211
03212 if (fd < 0)
03213 {
03214 dbus_set_error (error, _dbus_error_from_errno (errno),
03215 "Failed to open \"%s\": %s", cfilename,
03216 _dbus_strerror (errno));
03217 return FALSE;
03218 }
03219
03220 if ((f = fdopen (fd, "w")) == NULL)
03221 {
03222 dbus_set_error (error, _dbus_error_from_errno (errno),
03223 "Failed to fdopen fd %d: %s", fd, _dbus_strerror (errno));
03224 close (fd);
03225 return FALSE;
03226 }
03227
03228 if (fprintf (f, "%lu\n", pid) < 0)
03229 {
03230 dbus_set_error (error, _dbus_error_from_errno (errno),
03231 "Failed to write to \"%s\": %s", cfilename,
03232 _dbus_strerror (errno));
03233 return FALSE;
03234 }
03235
03236 if (fclose (f) == EOF)
03237 {
03238 dbus_set_error (error, _dbus_error_from_errno (errno),
03239 "Failed to close \"%s\": %s", cfilename,
03240 _dbus_strerror (errno));
03241 return FALSE;
03242 }
03243
03244 return TRUE;
03245 }
03246
03255 dbus_bool_t
03256 _dbus_change_identity (dbus_uid_t uid,
03257 dbus_gid_t gid,
03258 DBusError *error)
03259 {
03260
03261
03262
03263 if (setgid (gid) < 0)
03264 {
03265 dbus_set_error (error, _dbus_error_from_errno (errno),
03266 "Failed to set GID to %lu: %s", gid,
03267 _dbus_strerror (errno));
03268 return FALSE;
03269 }
03270
03271 if (setuid (uid) < 0)
03272 {
03273 dbus_set_error (error, _dbus_error_from_errno (errno),
03274 "Failed to set UID to %lu: %s", uid,
03275 _dbus_strerror (errno));
03276 return FALSE;
03277 }
03278
03279 return TRUE;
03280 }
03281
03287 void
03288 _dbus_set_signal_handler (int sig,
03289 DBusSignalHandler handler)
03290 {
03291 struct sigaction act;
03292 sigset_t empty_mask;
03293
03294 sigemptyset (&empty_mask);
03295 act.sa_handler = handler;
03296 act.sa_mask = empty_mask;
03297 act.sa_flags = 0;
03298 sigaction (sig, &act, 0);
03299 }
03300
03301
03302 #ifdef DBUS_BUILD_TESTS
03303 #include <stdlib.h>
03304 static void
03305 check_dirname (const char *filename,
03306 const char *dirname)
03307 {
03308 DBusString f, d;
03309
03310 _dbus_string_init_const (&f, filename);
03311
03312 if (!_dbus_string_init (&d))
03313 _dbus_assert_not_reached ("no memory");
03314
03315 if (!_dbus_string_get_dirname (&f, &d))
03316 _dbus_assert_not_reached ("no memory");
03317
03318 if (!_dbus_string_equal_c_str (&d, dirname))
03319 {
03320 _dbus_warn ("For filename \"%s\" got dirname \"%s\" and expected \"%s\"\n",
03321 filename,
03322 _dbus_string_get_const_data (&d),
03323 dirname);
03324 exit (1);
03325 }
03326
03327 _dbus_string_free (&d);
03328 }
03329
03330 static void
03331 check_path_absolute (const char *path,
03332 dbus_bool_t expected)
03333 {
03334 DBusString p;
03335
03336 _dbus_string_init_const (&p, path);
03337
03338 if (_dbus_path_is_absolute (&p) != expected)
03339 {
03340 _dbus_warn ("For path \"%s\" expected absolute = %d got %d\n",
03341 path, expected, _dbus_path_is_absolute (&p));
03342 exit (1);
03343 }
03344 }
03345
03351 dbus_bool_t
03352 _dbus_sysdeps_test (void)
03353 {
03354 DBusString str;
03355 double val;
03356 int pos;
03357
03358 check_dirname ("foo", ".");
03359 check_dirname ("foo/bar", "foo");
03360 check_dirname ("foo//bar", "foo");
03361 check_dirname ("foo///bar", "foo");
03362 check_dirname ("foo/bar/", "foo");
03363 check_dirname ("foo//bar/", "foo");
03364 check_dirname ("foo///bar/", "foo");
03365 check_dirname ("foo/bar//", "foo");
03366 check_dirname ("foo//bar////", "foo");
03367 check_dirname ("foo///bar///////", "foo");
03368 check_dirname ("/foo", "/");
03369 check_dirname ("
03370 check_dirname ("/foo/bar", "/foo");
03371 check_dirname ("/foo
03372 check_dirname ("/foo///bar", "/foo");
03373 check_dirname ("/", "/");
03374 check_dirname ("
03375 check_dirname ("", ".");
03376
03377
03378 _dbus_string_init_const (&str, "3.5");
03379 if (!_dbus_string_parse_double (&str,
03380 0, &val, &pos))
03381 {
03382 _dbus_warn ("Failed to parse double");
03383 exit (1);
03384 }
03385 if (val != 3.5)
03386 {
03387 _dbus_warn ("Failed to parse 3.5 correctly, got: %f", val);
03388 exit (1);
03389 }
03390 if (pos != 3)
03391 {
03392 _dbus_warn ("_dbus_string_parse_double of \"3.5\" returned wrong position %d", pos);
03393 exit (1);
03394 }
03395
03396 _dbus_string_init_const (&str, "0xff");
03397 if (!_dbus_string_parse_double (&str,
03398 0, &val, &pos))
03399 {
03400 _dbus_warn ("Failed to parse double");
03401 exit (1);
03402 }
03403 if (val != 0xff)
03404 {
03405 _dbus_warn ("Failed to parse 0xff correctly, got: %f", val);
03406 exit (1);
03407 }
03408 if (pos != 4)
03409 {
03410 _dbus_warn ("_dbus_string_parse_double of \"0xff\" returned wrong position %d", pos);
03411 exit (1);
03412 }
03413
03414 check_path_absolute ("/", TRUE);
03415 check_path_absolute ("/foo", TRUE);
03416 check_path_absolute ("", FALSE);
03417 check_path_absolute ("foo", FALSE);
03418 check_path_absolute ("foo/bar", FALSE);
03419
03420 return TRUE;
03421 }
03422 #endif
03423