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
02428 dbus_bool_t
02429 _dbus_delete_directory (const DBusString *filename,
02430 DBusError *error)
02431 {
02432 const char *filename_c;
02433
02434 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
02435
02436 filename_c = _dbus_string_get_const_data (filename);
02437
02438 if (rmdir (filename_c) != 0)
02439 {
02440 dbus_set_error (error, DBUS_ERROR_FAILED,
02441 "Failed to remove directory %s: %s\n",
02442 filename_c, _dbus_strerror (errno));
02443 return FALSE;
02444 }
02445
02446 return TRUE;
02447 }
02448
02459 dbus_bool_t
02460 _dbus_concat_dir_and_file (DBusString *dir,
02461 const DBusString *next_component)
02462 {
02463 dbus_bool_t dir_ends_in_slash;
02464 dbus_bool_t file_starts_with_slash;
02465
02466 if (_dbus_string_get_length (dir) == 0 ||
02467 _dbus_string_get_length (next_component) == 0)
02468 return TRUE;
02469
02470 dir_ends_in_slash = '/' == _dbus_string_get_byte (dir,
02471 _dbus_string_get_length (dir) - 1);
02472
02473 file_starts_with_slash = '/' == _dbus_string_get_byte (next_component, 0);
02474
02475 if (dir_ends_in_slash && file_starts_with_slash)
02476 {
02477 _dbus_string_shorten (dir, 1);
02478 }
02479 else if (!(dir_ends_in_slash || file_starts_with_slash))
02480 {
02481 if (!_dbus_string_append_byte (dir, '/'))
02482 return FALSE;
02483 }
02484
02485 return _dbus_string_copy (next_component, 0, dir,
02486 _dbus_string_get_length (dir));
02487 }
02488
02495 dbus_bool_t
02496 _dbus_string_get_dirname (const DBusString *filename,
02497 DBusString *dirname)
02498 {
02499 int sep;
02500
02501 _dbus_assert (filename != dirname);
02502 _dbus_assert (filename != NULL);
02503 _dbus_assert (dirname != NULL);
02504
02505
02506 sep = _dbus_string_get_length (filename);
02507 if (sep == 0)
02508 return _dbus_string_append (dirname, ".");
02509
02510 while (sep > 0 && _dbus_string_get_byte (filename, sep - 1) == '/')
02511 --sep;
02512
02513 _dbus_assert (sep >= 0);
02514
02515 if (sep == 0)
02516 return _dbus_string_append (dirname, "/");
02517
02518
02519 _dbus_string_find_byte_backward (filename, sep, '/', &sep);
02520 if (sep < 0)
02521 return _dbus_string_append (dirname, ".");
02522
02523
02524 while (sep > 0 && _dbus_string_get_byte (filename, sep - 1) == '/')
02525 --sep;
02526
02527 _dbus_assert (sep >= 0);
02528
02529 if (sep == 0 &&
02530 _dbus_string_get_byte (filename, 0) == '/')
02531 return _dbus_string_append (dirname, "/");
02532 else
02533 return _dbus_string_copy_len (filename, 0, sep - 0,
02534 dirname, _dbus_string_get_length (dirname));
02535 }
02536
02543 dbus_bool_t
02544 _dbus_path_is_absolute (const DBusString *filename)
02545 {
02546 if (_dbus_string_get_length (filename) > 0)
02547 return _dbus_string_get_byte (filename, 0) == '/';
02548 else
02549 return FALSE;
02550 }
02551
02555 struct DBusDirIter
02556 {
02557 DIR *d;
02559 };
02560
02568 DBusDirIter*
02569 _dbus_directory_open (const DBusString *filename,
02570 DBusError *error)
02571 {
02572 DIR *d;
02573 DBusDirIter *iter;
02574 const char *filename_c;
02575
02576 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
02577
02578 filename_c = _dbus_string_get_const_data (filename);
02579
02580 d = opendir (filename_c);
02581 if (d == NULL)
02582 {
02583 dbus_set_error (error, _dbus_error_from_errno (errno),
02584 "Failed to read directory \"%s\": %s",
02585 filename_c,
02586 _dbus_strerror (errno));
02587 return NULL;
02588 }
02589 iter = dbus_new0 (DBusDirIter, 1);
02590 if (iter == NULL)
02591 {
02592 closedir (d);
02593 dbus_set_error (error, DBUS_ERROR_NO_MEMORY,
02594 "Could not allocate memory for directory iterator");
02595 return NULL;
02596 }
02597
02598 iter->d = d;
02599
02600 return iter;
02601 }
02602
02616 dbus_bool_t
02617 _dbus_directory_get_next_file (DBusDirIter *iter,
02618 DBusString *filename,
02619 DBusError *error)
02620 {
02621 struct dirent *ent;
02622
02623 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
02624
02625 again:
02626 errno = 0;
02627 ent = readdir (iter->d);
02628 if (ent == NULL)
02629 {
02630 if (errno != 0)
02631 dbus_set_error (error,
02632 _dbus_error_from_errno (errno),
02633 "%s", _dbus_strerror (errno));
02634 return FALSE;
02635 }
02636 else if (ent->d_name[0] == '.' &&
02637 (ent->d_name[1] == '\0' ||
02638 (ent->d_name[1] == '.' && ent->d_name[2] == '\0')))
02639 goto again;
02640 else
02641 {
02642 _dbus_string_set_length (filename, 0);
02643 if (!_dbus_string_append (filename, ent->d_name))
02644 {
02645 dbus_set_error (error, DBUS_ERROR_NO_MEMORY,
02646 "No memory to read directory entry");
02647 return FALSE;
02648 }
02649 else
02650 return TRUE;
02651 }
02652 }
02653
02657 void
02658 _dbus_directory_close (DBusDirIter *iter)
02659 {
02660 closedir (iter->d);
02661 dbus_free (iter);
02662 }
02663
02664 static dbus_bool_t
02665 pseudorandom_generate_random_bytes (DBusString *str,
02666 int n_bytes)
02667 {
02668 int old_len;
02669 unsigned long tv_usec;
02670 int i;
02671
02672 old_len = _dbus_string_get_length (str);
02673
02674
02675 _dbus_verbose ("Falling back to pseudorandom for %d bytes\n",
02676 n_bytes);
02677
02678 _dbus_get_current_time (NULL, &tv_usec);
02679 srand (tv_usec);
02680
02681 i = 0;
02682 while (i < n_bytes)
02683 {
02684 double r;
02685 unsigned int b;
02686
02687 r = rand ();
02688 b = (r / (double) RAND_MAX) * 255.0;
02689
02690 if (!_dbus_string_append_byte (str, b))
02691 goto failed;
02692
02693 ++i;
02694 }
02695
02696 return TRUE;
02697
02698 failed:
02699 _dbus_string_set_length (str, old_len);
02700 return FALSE;
02701 }
02702
02711 dbus_bool_t
02712 _dbus_generate_random_bytes (DBusString *str,
02713 int n_bytes)
02714 {
02715 int old_len;
02716 int fd;
02717
02718
02719
02720
02721
02722
02723
02724 old_len = _dbus_string_get_length (str);
02725 fd = -1;
02726
02727
02728 fd = open ("/dev/urandom", O_RDONLY);
02729 if (fd < 0)
02730 return pseudorandom_generate_random_bytes (str, n_bytes);
02731
02732 if (_dbus_read (fd, str, n_bytes) != n_bytes)
02733 {
02734 close (fd);
02735 _dbus_string_set_length (str, old_len);
02736 return pseudorandom_generate_random_bytes (str, n_bytes);
02737 }
02738
02739 _dbus_verbose ("Read %d bytes from /dev/urandom\n",
02740 n_bytes);
02741
02742 close (fd);
02743
02744 return TRUE;
02745 }
02746
02755 dbus_bool_t
02756 _dbus_generate_random_ascii (DBusString *str,
02757 int n_bytes)
02758 {
02759 static const char letters[] =
02760 "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789abcdefghijklmnopqrstuvwxyz";
02761 int i;
02762 int len;
02763
02764 if (!_dbus_generate_random_bytes (str, n_bytes))
02765 return FALSE;
02766
02767 len = _dbus_string_get_length (str);
02768 i = len - n_bytes;
02769 while (i < len)
02770 {
02771 _dbus_string_set_byte (str, i,
02772 letters[_dbus_string_get_byte (str, i) %
02773 (sizeof (letters) - 1)]);
02774
02775 ++i;
02776 }
02777
02778 _dbus_assert (_dbus_string_validate_ascii (str, len - n_bytes,
02779 n_bytes));
02780
02781 return TRUE;
02782 }
02783
02791 const char*
02792 _dbus_strerror (int error_number)
02793 {
02794 const char *msg;
02795
02796 msg = strerror (error_number);
02797 if (msg == NULL)
02798 msg = "unknown";
02799
02800 return msg;
02801 }
02802
02806 void
02807 _dbus_disable_sigpipe (void)
02808 {
02809 signal (SIGPIPE, SIG_IGN);
02810 }
02811
02819 void
02820 _dbus_fd_set_close_on_exec (int fd)
02821 {
02822 int val;
02823
02824 val = fcntl (fd, F_GETFD, 0);
02825
02826 if (val < 0)
02827 return;
02828
02829 val |= FD_CLOEXEC;
02830
02831 fcntl (fd, F_SETFD, val);
02832 }
02833
02843 const char*
02844 _dbus_error_from_errno (int error_number)
02845 {
02846 switch (error_number)
02847 {
02848 case 0:
02849 return DBUS_ERROR_FAILED;
02850
02851 #ifdef EPROTONOSUPPORT
02852 case EPROTONOSUPPORT:
02853 return DBUS_ERROR_NOT_SUPPORTED;
02854 #endif
02855 #ifdef EAFNOSUPPORT
02856 case EAFNOSUPPORT:
02857 return DBUS_ERROR_NOT_SUPPORTED;
02858 #endif
02859 #ifdef ENFILE
02860 case ENFILE:
02861 return DBUS_ERROR_LIMITS_EXCEEDED;
02862 #endif
02863 #ifdef EMFILE
02864 case EMFILE:
02865 return DBUS_ERROR_LIMITS_EXCEEDED;
02866 #endif
02867 #ifdef EACCES
02868 case EACCES:
02869 return DBUS_ERROR_ACCESS_DENIED;
02870 #endif
02871 #ifdef EPERM
02872 case EPERM:
02873 return DBUS_ERROR_ACCESS_DENIED;
02874 #endif
02875 #ifdef ENOBUFS
02876 case ENOBUFS:
02877 return DBUS_ERROR_NO_MEMORY;
02878 #endif
02879 #ifdef ENOMEM
02880 case ENOMEM:
02881 return DBUS_ERROR_NO_MEMORY;
02882 #endif
02883 #ifdef EINVAL
02884 case EINVAL:
02885 return DBUS_ERROR_FAILED;
02886 #endif
02887 #ifdef EBADF
02888 case EBADF:
02889 return DBUS_ERROR_FAILED;
02890 #endif
02891 #ifdef EFAULT
02892 case EFAULT:
02893 return DBUS_ERROR_FAILED;
02894 #endif
02895 #ifdef ENOTSOCK
02896 case ENOTSOCK:
02897 return DBUS_ERROR_FAILED;
02898 #endif
02899 #ifdef EISCONN
02900 case EISCONN:
02901 return DBUS_ERROR_FAILED;
02902 #endif
02903 #ifdef ECONNREFUSED
02904 case ECONNREFUSED:
02905 return DBUS_ERROR_NO_SERVER;
02906 #endif
02907 #ifdef ETIMEDOUT
02908 case ETIMEDOUT:
02909 return DBUS_ERROR_TIMEOUT;
02910 #endif
02911 #ifdef ENETUNREACH
02912 case ENETUNREACH:
02913 return DBUS_ERROR_NO_NETWORK;
02914 #endif
02915 #ifdef EADDRINUSE
02916 case EADDRINUSE:
02917 return DBUS_ERROR_ADDRESS_IN_USE;
02918 #endif
02919 #ifdef EEXIST
02920 case EEXIST:
02921 return DBUS_ERROR_FILE_NOT_FOUND;
02922 #endif
02923 #ifdef ENOENT
02924 case ENOENT:
02925 return DBUS_ERROR_FILE_NOT_FOUND;
02926 #endif
02927 }
02928
02929 return DBUS_ERROR_FAILED;
02930 }
02931
02937 void
02938 _dbus_exit (int code)
02939 {
02940 _exit (code);
02941 }
02942
02951 dbus_bool_t
02952 _dbus_stat (const DBusString *filename,
02953 DBusStat *statbuf,
02954 DBusError *error)
02955 {
02956 const char *filename_c;
02957 struct stat sb;
02958
02959 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
02960
02961 filename_c = _dbus_string_get_const_data (filename);
02962
02963 if (stat (filename_c, &sb) < 0)
02964 {
02965 dbus_set_error (error, _dbus_error_from_errno (errno),
02966 "%s", _dbus_strerror (errno));
02967 return FALSE;
02968 }
02969
02970 statbuf->mode = sb.st_mode;
02971 statbuf->nlink = sb.st_nlink;
02972 statbuf->uid = sb.st_uid;
02973 statbuf->gid = sb.st_gid;
02974 statbuf->size = sb.st_size;
02975 statbuf->atime = sb.st_atime;
02976 statbuf->mtime = sb.st_mtime;
02977 statbuf->ctime = sb.st_ctime;
02978
02979 return TRUE;
02980 }
02981
02992 dbus_bool_t
02993 _dbus_full_duplex_pipe (int *fd1,
02994 int *fd2,
02995 dbus_bool_t blocking,
02996 DBusError *error)
02997 {
02998 #ifdef HAVE_SOCKETPAIR
02999 int fds[2];
03000
03001 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
03002
03003 if (socketpair (AF_UNIX, SOCK_STREAM, 0, fds) < 0)
03004 {
03005 dbus_set_error (error, _dbus_error_from_errno (errno),
03006 "Could not create full-duplex pipe");
03007 return FALSE;
03008 }
03009
03010 if (!blocking &&
03011 (!_dbus_set_fd_nonblocking (fds[0], NULL) ||
03012 !_dbus_set_fd_nonblocking (fds[1], NULL)))
03013 {
03014 dbus_set_error (error, _dbus_error_from_errno (errno),
03015 "Could not set full-duplex pipe nonblocking");
03016
03017 close (fds[0]);
03018 close (fds[1]);
03019
03020 return FALSE;
03021 }
03022
03023 *fd1 = fds[0];
03024 *fd2 = fds[1];
03025
03026 return TRUE;
03027 #else
03028 _dbus_warn ("_dbus_full_duplex_pipe() not implemented on this OS\n");
03029 dbus_set_error (error, DBUS_ERROR_FAILED,
03030 "_dbus_full_duplex_pipe() not implemented on this OS");
03031 return FALSE;
03032 #endif
03033 }
03034
03042 dbus_bool_t
03043 _dbus_close (int fd,
03044 DBusError *error)
03045 {
03046 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
03047
03048 again:
03049 if (close (fd) < 0)
03050 {
03051 if (errno == EINTR)
03052 goto again;
03053
03054 dbus_set_error (error, _dbus_error_from_errno (errno),
03055 "Could not close fd %d", fd);
03056 return FALSE;
03057 }
03058
03059 return TRUE;
03060 }
03061
03069 dbus_bool_t
03070 _dbus_set_fd_nonblocking (int fd,
03071 DBusError *error)
03072 {
03073 int val;
03074
03075 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
03076
03077 val = fcntl (fd, F_GETFL, 0);
03078 if (val < 0)
03079 {
03080 dbus_set_error (error, _dbus_error_from_errno (errno),
03081 "Failed to get flags from file descriptor %d: %s",
03082 fd, _dbus_strerror (errno));
03083 _dbus_verbose ("Failed to get flags for fd %d: %s\n", fd,
03084 _dbus_strerror (errno));
03085 return FALSE;
03086 }
03087
03088 if (fcntl (fd, F_SETFL, val | O_NONBLOCK) < 0)
03089 {
03090 dbus_set_error (error, _dbus_error_from_errno (errno),
03091 "Failed to set nonblocking flag of file descriptor %d: %s",
03092 fd, _dbus_strerror (errno));
03093 _dbus_verbose ("Failed to set fd %d nonblocking: %s\n",
03094 fd, _dbus_strerror (errno));
03095
03096 return FALSE;
03097 }
03098
03099 return TRUE;
03100 }
03101
03107 void
03108 _dbus_print_backtrace (void)
03109 {
03110 #if defined (HAVE_BACKTRACE) && defined (DBUS_ENABLE_VERBOSE_MODE)
03111 void *bt[500];
03112 int bt_size;
03113 int i;
03114 char **syms;
03115
03116 bt_size = backtrace (bt, 500);
03117
03118 syms = backtrace_symbols (bt, bt_size);
03119
03120 i = 0;
03121 while (i < bt_size)
03122 {
03123 _dbus_verbose (" %s\n", syms[i]);
03124 ++i;
03125 }
03126
03127 free (syms);
03128 #else
03129 _dbus_verbose (" D-BUS not compiled with backtrace support\n");
03130 #endif
03131 }
03132
03140 dbus_bool_t
03141 _dbus_become_daemon (const DBusString *pidfile,
03142 DBusError *error)
03143 {
03144 const char *s;
03145 pid_t child_pid;
03146 int dev_null_fd;
03147
03148 _dbus_verbose ("Becoming a daemon...\n");
03149
03150 _dbus_verbose ("chdir to /\n");
03151 if (chdir ("/") < 0)
03152 {
03153 dbus_set_error (error, DBUS_ERROR_FAILED,
03154 "Could not chdir() to root directory");
03155 return FALSE;
03156 }
03157
03158 _dbus_verbose ("forking...\n");
03159 switch ((child_pid = fork ()))
03160 {
03161 case -1:
03162 _dbus_verbose ("fork failed\n");
03163 dbus_set_error (error, _dbus_error_from_errno (errno),
03164 "Failed to fork daemon: %s", _dbus_strerror (errno));
03165 return FALSE;
03166 break;
03167
03168 case 0:
03169 _dbus_verbose ("in child, closing std file descriptors\n");
03170
03171
03172
03173
03174
03175
03176 dev_null_fd = open ("/dev/null", O_RDWR);
03177 if (dev_null_fd >= 0)
03178 {
03179 dup2 (dev_null_fd, 0);
03180 dup2 (dev_null_fd, 1);
03181
03182 s = _dbus_getenv ("DBUS_DEBUG_OUTPUT");
03183 if (s == NULL || *s == '\0')
03184 dup2 (dev_null_fd, 2);
03185 else
03186 _dbus_verbose ("keeping stderr open due to DBUS_DEBUG_OUTPUT\n");
03187 }
03188
03189
03190 _dbus_verbose ("setting umask\n");
03191 umask (022);
03192 break;
03193
03194 default:
03195 if (pidfile)
03196 {
03197 _dbus_verbose ("parent writing pid file\n");
03198 if (!_dbus_write_pid_file (pidfile,
03199 child_pid,
03200 error))
03201 {
03202 _dbus_verbose ("pid file write failed, killing child\n");
03203 kill (child_pid, SIGTERM);
03204 return FALSE;
03205 }
03206 }
03207 _dbus_verbose ("parent exiting\n");
03208 _exit (0);
03209 break;
03210 }
03211
03212 _dbus_verbose ("calling setsid()\n");
03213 if (setsid () == -1)
03214 _dbus_assert_not_reached ("setsid() failed");
03215
03216 return TRUE;
03217 }
03218
03227 dbus_bool_t
03228 _dbus_write_pid_file (const DBusString *filename,
03229 unsigned long pid,
03230 DBusError *error)
03231 {
03232 const char *cfilename;
03233 int fd;
03234 FILE *f;
03235
03236 cfilename = _dbus_string_get_const_data (filename);
03237
03238 fd = open (cfilename, O_WRONLY|O_CREAT|O_EXCL|O_BINARY, 0644);
03239
03240 if (fd < 0)
03241 {
03242 dbus_set_error (error, _dbus_error_from_errno (errno),
03243 "Failed to open \"%s\": %s", cfilename,
03244 _dbus_strerror (errno));
03245 return FALSE;
03246 }
03247
03248 if ((f = fdopen (fd, "w")) == NULL)
03249 {
03250 dbus_set_error (error, _dbus_error_from_errno (errno),
03251 "Failed to fdopen fd %d: %s", fd, _dbus_strerror (errno));
03252 close (fd);
03253 return FALSE;
03254 }
03255
03256 if (fprintf (f, "%lu\n", pid) < 0)
03257 {
03258 dbus_set_error (error, _dbus_error_from_errno (errno),
03259 "Failed to write to \"%s\": %s", cfilename,
03260 _dbus_strerror (errno));
03261 return FALSE;
03262 }
03263
03264 if (fclose (f) == EOF)
03265 {
03266 dbus_set_error (error, _dbus_error_from_errno (errno),
03267 "Failed to close \"%s\": %s", cfilename,
03268 _dbus_strerror (errno));
03269 return FALSE;
03270 }
03271
03272 return TRUE;
03273 }
03274
03283 dbus_bool_t
03284 _dbus_change_identity (dbus_uid_t uid,
03285 dbus_gid_t gid,
03286 DBusError *error)
03287 {
03288
03289
03290
03291 if (setgid (gid) < 0)
03292 {
03293 dbus_set_error (error, _dbus_error_from_errno (errno),
03294 "Failed to set GID to %lu: %s", gid,
03295 _dbus_strerror (errno));
03296 return FALSE;
03297 }
03298
03299 if (setuid (uid) < 0)
03300 {
03301 dbus_set_error (error, _dbus_error_from_errno (errno),
03302 "Failed to set UID to %lu: %s", uid,
03303 _dbus_strerror (errno));
03304 return FALSE;
03305 }
03306
03307 return TRUE;
03308 }
03309
03315 void
03316 _dbus_set_signal_handler (int sig,
03317 DBusSignalHandler handler)
03318 {
03319 struct sigaction act;
03320 sigset_t empty_mask;
03321
03322 sigemptyset (&empty_mask);
03323 act.sa_handler = handler;
03324 act.sa_mask = empty_mask;
03325 act.sa_flags = 0;
03326 sigaction (sig, &act, 0);
03327 }
03328
03329
03330 #ifdef DBUS_BUILD_TESTS
03331 #include <stdlib.h>
03332 static void
03333 check_dirname (const char *filename,
03334 const char *dirname)
03335 {
03336 DBusString f, d;
03337
03338 _dbus_string_init_const (&f, filename);
03339
03340 if (!_dbus_string_init (&d))
03341 _dbus_assert_not_reached ("no memory");
03342
03343 if (!_dbus_string_get_dirname (&f, &d))
03344 _dbus_assert_not_reached ("no memory");
03345
03346 if (!_dbus_string_equal_c_str (&d, dirname))
03347 {
03348 _dbus_warn ("For filename \"%s\" got dirname \"%s\" and expected \"%s\"\n",
03349 filename,
03350 _dbus_string_get_const_data (&d),
03351 dirname);
03352 exit (1);
03353 }
03354
03355 _dbus_string_free (&d);
03356 }
03357
03358 static void
03359 check_path_absolute (const char *path,
03360 dbus_bool_t expected)
03361 {
03362 DBusString p;
03363
03364 _dbus_string_init_const (&p, path);
03365
03366 if (_dbus_path_is_absolute (&p) != expected)
03367 {
03368 _dbus_warn ("For path \"%s\" expected absolute = %d got %d\n",
03369 path, expected, _dbus_path_is_absolute (&p));
03370 exit (1);
03371 }
03372 }
03373
03379 dbus_bool_t
03380 _dbus_sysdeps_test (void)
03381 {
03382 DBusString str;
03383 double val;
03384 int pos;
03385
03386 check_dirname ("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//bar/", "foo");
03392 check_dirname ("foo///bar/", "foo");
03393 check_dirname ("foo/bar//", "foo");
03394 check_dirname ("foo//bar////", "foo");
03395 check_dirname ("foo///bar///////", "foo");
03396 check_dirname ("/foo", "/");
03397 check_dirname ("
03398 check_dirname ("/foo/bar", "/foo");
03399 check_dirname ("/foo
03400 check_dirname ("/foo///bar", "/foo");
03401 check_dirname ("/", "/");
03402 check_dirname ("
03403 check_dirname ("", ".");
03404
03405
03406 _dbus_string_init_const (&str, "3.5");
03407 if (!_dbus_string_parse_double (&str,
03408 0, &val, &pos))
03409 {
03410 _dbus_warn ("Failed to parse double");
03411 exit (1);
03412 }
03413 if (val != 3.5)
03414 {
03415 _dbus_warn ("Failed to parse 3.5 correctly, got: %f", val);
03416 exit (1);
03417 }
03418 if (pos != 3)
03419 {
03420 _dbus_warn ("_dbus_string_parse_double of \"3.5\" returned wrong position %d", pos);
03421 exit (1);
03422 }
03423
03424 _dbus_string_init_const (&str, "0xff");
03425 if (!_dbus_string_parse_double (&str,
03426 0, &val, &pos))
03427 {
03428 _dbus_warn ("Failed to parse double");
03429 exit (1);
03430 }
03431 if (val != 0xff)
03432 {
03433 _dbus_warn ("Failed to parse 0xff correctly, got: %f", val);
03434 exit (1);
03435 }
03436 if (pos != 4)
03437 {
03438 _dbus_warn ("_dbus_string_parse_double of \"0xff\" returned wrong position %d", pos);
03439 exit (1);
03440 }
03441
03442 check_path_absolute ("/", TRUE);
03443 check_path_absolute ("/foo", TRUE);
03444 check_path_absolute ("", FALSE);
03445 check_path_absolute ("foo", FALSE);
03446 check_path_absolute ("foo/bar", FALSE);
03447
03448 return TRUE;
03449 }
03450 #endif
03451