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