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-string.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
00074 #ifndef DBUS_DISABLE_ASSERT
00075
00078 void
00079 _dbus_abort (void)
00080 {
00081 #ifdef DBUS_ENABLE_VERBOSE_MODE
00082 const char *s;
00083 s = _dbus_getenv ("DBUS_PRINT_BACKTRACE");
00084 if (s && *s)
00085 _dbus_print_backtrace ();
00086 #endif
00087 abort ();
00088 _exit (1);
00089 }
00090 #endif
00091
00103 dbus_bool_t
00104 _dbus_setenv (const char *varname,
00105 const char *value)
00106 {
00107 _dbus_assert (varname != NULL);
00108
00109 if (value == NULL)
00110 {
00111 #ifdef HAVE_UNSETENV
00112 unsetenv (varname);
00113 return TRUE;
00114 #else
00115 char *putenv_value;
00116 size_t len;
00117
00118 len = strlen (varname);
00119
00120
00121
00122
00123
00124 putenv_value = malloc (len + 1);
00125 if (putenv_value == NULL)
00126 return FALSE;
00127
00128 strcpy (putenv_value, varname);
00129
00130 return (putenv (putenv_value) == 0);
00131 #endif
00132 }
00133 else
00134 {
00135 #ifdef HAVE_SETENV
00136 return (setenv (varname, value, TRUE) == 0);
00137 #else
00138 char *putenv_value;
00139 size_t len;
00140 size_t varname_len;
00141 size_t value_len;
00142
00143 varname_len = strlen (varname);
00144 value_len = strlen (value);
00145
00146 len = varname_len + value_len + 1 ;
00147
00148
00149
00150
00151
00152 putenv_value = malloc (len + 1);
00153 if (putenv_value == NULL)
00154 return FALSE;
00155
00156 strcpy (putenv_value, varname);
00157 strcpy (putenv_value + varname_len, "=");
00158 strcpy (putenv_value + varname_len + 1, value);
00159
00160 return (putenv (putenv_value) == 0);
00161 #endif
00162 }
00163 }
00164
00171 const char*
00172 _dbus_getenv (const char *varname)
00173 {
00174 return getenv (varname);
00175 }
00176
00190 int
00191 _dbus_read (int fd,
00192 DBusString *buffer,
00193 int count)
00194 {
00195 int bytes_read;
00196 int start;
00197 char *data;
00198
00199 _dbus_assert (count >= 0);
00200
00201 start = _dbus_string_get_length (buffer);
00202
00203 if (!_dbus_string_lengthen (buffer, count))
00204 {
00205 errno = ENOMEM;
00206 return -1;
00207 }
00208
00209 data = _dbus_string_get_data_len (buffer, start, count);
00210
00211 again:
00212
00213 bytes_read = read (fd, data, count);
00214
00215 if (bytes_read < 0)
00216 {
00217 if (errno == EINTR)
00218 goto again;
00219 else
00220 {
00221
00222 _dbus_string_set_length (buffer, start);
00223 return -1;
00224 }
00225 }
00226 else
00227 {
00228
00229 _dbus_string_set_length (buffer, start + bytes_read);
00230
00231 #if 0
00232 if (bytes_read > 0)
00233 _dbus_verbose_bytes_of_string (buffer, start, bytes_read);
00234 #endif
00235
00236 return bytes_read;
00237 }
00238 }
00239
00250 int
00251 _dbus_write (int fd,
00252 const DBusString *buffer,
00253 int start,
00254 int len)
00255 {
00256 const char *data;
00257 int bytes_written;
00258
00259 data = _dbus_string_get_const_data_len (buffer, start, len);
00260
00261 again:
00262
00263 bytes_written = write (fd, data, len);
00264
00265 if (bytes_written < 0 && errno == EINTR)
00266 goto again;
00267
00268 #if 0
00269 if (bytes_written > 0)
00270 _dbus_verbose_bytes_of_string (buffer, start, bytes_written);
00271 #endif
00272
00273 return bytes_written;
00274 }
00275
00296 int
00297 _dbus_write_two (int fd,
00298 const DBusString *buffer1,
00299 int start1,
00300 int len1,
00301 const DBusString *buffer2,
00302 int start2,
00303 int len2)
00304 {
00305 _dbus_assert (buffer1 != NULL);
00306 _dbus_assert (start1 >= 0);
00307 _dbus_assert (start2 >= 0);
00308 _dbus_assert (len1 >= 0);
00309 _dbus_assert (len2 >= 0);
00310
00311 #ifdef HAVE_WRITEV
00312 {
00313 struct iovec vectors[2];
00314 const char *data1;
00315 const char *data2;
00316 int bytes_written;
00317
00318 data1 = _dbus_string_get_const_data_len (buffer1, start1, len1);
00319
00320 if (buffer2 != NULL)
00321 data2 = _dbus_string_get_const_data_len (buffer2, start2, len2);
00322 else
00323 {
00324 data2 = NULL;
00325 start2 = 0;
00326 len2 = 0;
00327 }
00328
00329 vectors[0].iov_base = (char*) data1;
00330 vectors[0].iov_len = len1;
00331 vectors[1].iov_base = (char*) data2;
00332 vectors[1].iov_len = len2;
00333
00334 again:
00335
00336 bytes_written = writev (fd,
00337 vectors,
00338 data2 ? 2 : 1);
00339
00340 if (bytes_written < 0 && errno == EINTR)
00341 goto again;
00342
00343 return bytes_written;
00344 }
00345 #else
00346 {
00347 int ret1;
00348
00349 ret1 = _dbus_write (fd, buffer1, start1, len1);
00350 if (ret1 == len1 && buffer2 != NULL)
00351 {
00352 ret2 = _dbus_write (fd, buffer2, start2, len2);
00353 if (ret2 < 0)
00354 ret2 = 0;
00355
00356 return ret1 + ret2;
00357 }
00358 else
00359 return ret1;
00360 }
00361 #endif
00362 }
00363
00364 #define _DBUS_MAX_SUN_PATH_LENGTH 99
00365
00393 int
00394 _dbus_connect_unix_socket (const char *path,
00395 dbus_bool_t abstract,
00396 DBusError *error)
00397 {
00398 int fd;
00399 struct sockaddr_un addr;
00400
00401 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
00402
00403 _dbus_verbose ("connecting to unix socket %s abstract=%d\n",
00404 path, abstract);
00405
00406 fd = socket (PF_UNIX, SOCK_STREAM, 0);
00407
00408 if (fd < 0)
00409 {
00410 dbus_set_error (error,
00411 _dbus_error_from_errno (errno),
00412 "Failed to create socket: %s",
00413 _dbus_strerror (errno));
00414
00415 return -1;
00416 }
00417
00418 _DBUS_ZERO (addr);
00419 addr.sun_family = AF_UNIX;
00420
00421 if (abstract)
00422 {
00423 #ifdef HAVE_ABSTRACT_SOCKETS
00424
00425
00426
00427 addr.sun_path[0] = '\0';
00428 strncpy (&addr.sun_path[1], path, _DBUS_MAX_SUN_PATH_LENGTH - 2);
00429
00430 #else
00431 dbus_set_error (error, DBUS_ERROR_NOT_SUPPORTED,
00432 "Operating system does not support abstract socket namespace\n");
00433 close (fd);
00434 return -1;
00435 #endif
00436 }
00437 else
00438 {
00439 strncpy (addr.sun_path, path, _DBUS_MAX_SUN_PATH_LENGTH - 1);
00440 }
00441
00442 if (connect (fd, (struct sockaddr*) &addr, sizeof (addr)) < 0)
00443 {
00444 dbus_set_error (error,
00445 _dbus_error_from_errno (errno),
00446 "Failed to connect to socket %s: %s",
00447 path, _dbus_strerror (errno));
00448
00449 close (fd);
00450 fd = -1;
00451
00452 return -1;
00453 }
00454
00455 if (!_dbus_set_fd_nonblocking (fd, error))
00456 {
00457 _DBUS_ASSERT_ERROR_IS_SET (error);
00458
00459 close (fd);
00460 fd = -1;
00461
00462 return -1;
00463 }
00464
00465 return fd;
00466 }
00467
00483 int
00484 _dbus_listen_unix_socket (const char *path,
00485 dbus_bool_t abstract,
00486 DBusError *error)
00487 {
00488 int listen_fd;
00489 struct sockaddr_un addr;
00490
00491 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
00492
00493 _dbus_verbose ("listening on unix socket %s abstract=%d\n",
00494 path, abstract);
00495
00496 listen_fd = socket (PF_UNIX, SOCK_STREAM, 0);
00497
00498 if (listen_fd < 0)
00499 {
00500 dbus_set_error (error, _dbus_error_from_errno (errno),
00501 "Failed to create socket \"%s\": %s",
00502 path, _dbus_strerror (errno));
00503 return -1;
00504 }
00505
00506 _DBUS_ZERO (addr);
00507 addr.sun_family = AF_UNIX;
00508
00509 if (abstract)
00510 {
00511 #ifdef HAVE_ABSTRACT_SOCKETS
00512
00513
00514
00515 addr.sun_path[0] = '\0';
00516 strncpy (&addr.sun_path[1], path, _DBUS_MAX_SUN_PATH_LENGTH - 2);
00517
00518 #else
00519 dbus_set_error (error, DBUS_ERROR_NOT_SUPPORTED,
00520 "Operating system does not support abstract socket namespace\n");
00521 close (listen_fd);
00522 return -1;
00523 #endif
00524 }
00525 else
00526 {
00527
00528
00529
00530
00531
00532
00533
00534
00535
00536
00537 {
00538 struct stat sb;
00539
00540 if (stat (path, &sb) == 0 &&
00541 S_ISSOCK (sb.st_mode))
00542 unlink (path);
00543 }
00544
00545 strncpy (addr.sun_path, path, _DBUS_MAX_SUN_PATH_LENGTH - 1);
00546 }
00547
00548 if (bind (listen_fd, (struct sockaddr*) &addr, sizeof (addr)) < 0)
00549 {
00550 dbus_set_error (error, _dbus_error_from_errno (errno),
00551 "Failed to bind socket \"%s\": %s",
00552 path, _dbus_strerror (errno));
00553 close (listen_fd);
00554 return -1;
00555 }
00556
00557 if (listen (listen_fd, 30 ) < 0)
00558 {
00559 dbus_set_error (error, _dbus_error_from_errno (errno),
00560 "Failed to listen on socket \"%s\": %s",
00561 path, _dbus_strerror (errno));
00562 close (listen_fd);
00563 return -1;
00564 }
00565
00566 if (!_dbus_set_fd_nonblocking (listen_fd, error))
00567 {
00568 _DBUS_ASSERT_ERROR_IS_SET (error);
00569 close (listen_fd);
00570 return -1;
00571 }
00572
00573
00574
00575
00576 if (!abstract && chmod (path, 0777) < 0)
00577 _dbus_warn ("Could not set mode 0777 on socket %s\n",
00578 path);
00579
00580 return listen_fd;
00581 }
00582
00593 int
00594 _dbus_connect_tcp_socket (const char *host,
00595 dbus_uint32_t port,
00596 DBusError *error)
00597 {
00598 int fd;
00599 struct sockaddr_in addr;
00600 struct hostent *he;
00601 struct in_addr *haddr;
00602
00603 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
00604
00605 fd = socket (AF_INET, SOCK_STREAM, 0);
00606
00607 if (fd < 0)
00608 {
00609 dbus_set_error (error,
00610 _dbus_error_from_errno (errno),
00611 "Failed to create socket: %s",
00612 _dbus_strerror (errno));
00613
00614 return -1;
00615 }
00616
00617 if (host == NULL)
00618 host = "localhost";
00619
00620 he = gethostbyname (host);
00621 if (he == NULL)
00622 {
00623 dbus_set_error (error,
00624 _dbus_error_from_errno (errno),
00625 "Failed to lookup hostname: %s",
00626 host);
00627 close (fd);
00628 return -1;
00629 }
00630
00631 haddr = ((struct in_addr *) (he->h_addr_list)[0]);
00632
00633 _DBUS_ZERO (addr);
00634 memcpy (&addr.sin_addr, haddr, sizeof(struct in_addr));
00635 addr.sin_family = AF_INET;
00636 addr.sin_port = htons (port);
00637
00638 if (connect (fd, (struct sockaddr*) &addr, sizeof (addr)) < 0)
00639 {
00640 dbus_set_error (error,
00641 _dbus_error_from_errno (errno),
00642 "Failed to connect to socket %s: %s:%d",
00643 host, _dbus_strerror (errno), port);
00644
00645 close (fd);
00646 fd = -1;
00647
00648 return -1;
00649 }
00650
00651 if (!_dbus_set_fd_nonblocking (fd, error))
00652 {
00653 close (fd);
00654 fd = -1;
00655
00656 return -1;
00657 }
00658
00659 return fd;
00660 }
00661
00672 int
00673 _dbus_listen_tcp_socket (const char *host,
00674 dbus_uint32_t port,
00675 DBusError *error)
00676 {
00677 int listen_fd;
00678 struct sockaddr_in addr;
00679 struct hostent *he;
00680 struct in_addr *haddr;
00681
00682 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
00683
00684 listen_fd = socket (AF_INET, SOCK_STREAM, 0);
00685
00686 if (listen_fd < 0)
00687 {
00688 dbus_set_error (error, _dbus_error_from_errno (errno),
00689 "Failed to create socket \"%s:%d\": %s",
00690 host, port, _dbus_strerror (errno));
00691 return -1;
00692 }
00693
00694 he = gethostbyname (host);
00695 if (he == NULL)
00696 {
00697 dbus_set_error (error,
00698 _dbus_error_from_errno (errno),
00699 "Failed to lookup hostname: %s",
00700 host);
00701 close (listen_fd);
00702 return -1;
00703 }
00704
00705 haddr = ((struct in_addr *) (he->h_addr_list)[0]);
00706
00707 _DBUS_ZERO (addr);
00708 memcpy (&addr.sin_addr, haddr, sizeof (struct in_addr));
00709 addr.sin_family = AF_INET;
00710 addr.sin_port = htons (port);
00711
00712 if (bind (listen_fd, (struct sockaddr*) &addr, sizeof (struct sockaddr)))
00713 {
00714 dbus_set_error (error, _dbus_error_from_errno (errno),
00715 "Failed to bind socket \"%s:%d\": %s",
00716 host, port, _dbus_strerror (errno));
00717 close (listen_fd);
00718 return -1;
00719 }
00720
00721 if (listen (listen_fd, 30 ) < 0)
00722 {
00723 dbus_set_error (error, _dbus_error_from_errno (errno),
00724 "Failed to listen on socket \"%s:%d\": %s",
00725 host, port, _dbus_strerror (errno));
00726 close (listen_fd);
00727 return -1;
00728 }
00729
00730 if (!_dbus_set_fd_nonblocking (listen_fd, error))
00731 {
00732 close (listen_fd);
00733 return -1;
00734 }
00735
00736 return listen_fd;
00737 }
00738
00739 static dbus_bool_t
00740 write_credentials_byte (int server_fd,
00741 DBusError *error)
00742 {
00743 int bytes_written;
00744 char buf[1] = { '\0' };
00745 #if defined(HAVE_CMSGCRED) && !defined(LOCAL_CREDS)
00746 struct {
00747 struct cmsghdr hdr;
00748 struct cmsgcred cred;
00749 } cmsg;
00750 struct iovec iov;
00751 struct msghdr msg;
00752 #endif
00753
00754 #if defined(HAVE_CMSGCRED) && !defined(LOCAL_CREDS)
00755 iov.iov_base = buf;
00756 iov.iov_len = 1;
00757
00758 memset (&msg, 0, sizeof (msg));
00759 msg.msg_iov = &iov;
00760 msg.msg_iovlen = 1;
00761
00762 msg.msg_control = &cmsg;
00763 msg.msg_controllen = sizeof (cmsg);
00764 memset (&cmsg, 0, sizeof (cmsg));
00765 cmsg.hdr.cmsg_len = sizeof (cmsg);
00766 cmsg.hdr.cmsg_level = SOL_SOCKET;
00767 cmsg.hdr.cmsg_type = SCM_CREDS;
00768 #endif
00769
00770 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
00771
00772 again:
00773
00774 #if defined(HAVE_CMSGCRED) && !defined(LOCAL_CREDS)
00775 bytes_written = sendmsg (server_fd, &msg, 0);
00776 #else
00777 bytes_written = write (server_fd, buf, 1);
00778 #endif
00779
00780 if (bytes_written < 0 && errno == EINTR)
00781 goto again;
00782
00783 if (bytes_written < 0)
00784 {
00785 dbus_set_error (error, _dbus_error_from_errno (errno),
00786 "Failed to write credentials byte: %s",
00787 _dbus_strerror (errno));
00788 return FALSE;
00789 }
00790 else if (bytes_written == 0)
00791 {
00792 dbus_set_error (error, DBUS_ERROR_IO_ERROR,
00793 "wrote zero bytes writing credentials byte");
00794 return FALSE;
00795 }
00796 else
00797 {
00798 _dbus_assert (bytes_written == 1);
00799 _dbus_verbose ("wrote credentials byte\n");
00800 return TRUE;
00801 }
00802 }
00803
00822 dbus_bool_t
00823 _dbus_read_credentials_unix_socket (int client_fd,
00824 DBusCredentials *credentials,
00825 DBusError *error)
00826 {
00827 struct msghdr msg;
00828 struct iovec iov;
00829 char buf;
00830
00831 #ifdef HAVE_CMSGCRED
00832 struct {
00833 struct cmsghdr hdr;
00834 struct cmsgcred cred;
00835 } cmsg;
00836 #endif
00837
00838 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
00839
00840
00841
00842
00843
00844 _dbus_assert (sizeof (pid_t) <= sizeof (credentials->pid));
00845 _dbus_assert (sizeof (uid_t) <= sizeof (credentials->uid));
00846 _dbus_assert (sizeof (gid_t) <= sizeof (credentials->gid));
00847
00848 _dbus_credentials_clear (credentials);
00849
00850 #if defined(LOCAL_CREDS) && defined(HAVE_CMSGCRED)
00851
00852 {
00853 int on = 1;
00854 if (setsockopt (client_fd, 0, LOCAL_CREDS, &on, sizeof (on)) < 0)
00855 {
00856 _dbus_verbose ("Unable to set LOCAL_CREDS socket option\n");
00857 return FALSE;
00858 }
00859 }
00860 #endif
00861
00862 iov.iov_base = &buf;
00863 iov.iov_len = 1;
00864
00865 memset (&msg, 0, sizeof (msg));
00866 msg.msg_iov = &iov;
00867 msg.msg_iovlen = 1;
00868
00869 #ifdef HAVE_CMSGCRED
00870 memset (&cmsg, 0, sizeof (cmsg));
00871 msg.msg_control = &cmsg;
00872 msg.msg_controllen = sizeof (cmsg);
00873 #endif
00874
00875 again:
00876 if (recvmsg (client_fd, &msg, 0) < 0)
00877 {
00878 if (errno == EINTR)
00879 goto again;
00880
00881 dbus_set_error (error, _dbus_error_from_errno (errno),
00882 "Failed to read credentials byte: %s",
00883 _dbus_strerror (errno));
00884 return FALSE;
00885 }
00886
00887 if (buf != '\0')
00888 {
00889 dbus_set_error (error, DBUS_ERROR_FAILED,
00890 "Credentials byte was not nul");
00891 return FALSE;
00892 }
00893
00894 #ifdef HAVE_CMSGCRED
00895 if (cmsg->hdr.cmsg_len < sizeof (cmsg) || cmsg.hdr.cmsg_type != SCM_CREDS)
00896 {
00897 dbus_set_error (error, DBUS_ERROR_FAILED,
00898 "Message from recvmsg() was not SCM_CREDS");
00899 return FALSE;
00900 }
00901 #endif
00902
00903 _dbus_verbose ("read credentials byte\n");
00904
00905 {
00906 #ifdef SO_PEERCRED
00907 struct ucred cr;
00908 int cr_len = sizeof (cr);
00909
00910 if (getsockopt (client_fd, SOL_SOCKET, SO_PEERCRED, &cr, &cr_len) == 0 &&
00911 cr_len == sizeof (cr))
00912 {
00913 credentials->pid = cr.pid;
00914 credentials->uid = cr.uid;
00915 credentials->gid = cr.gid;
00916 }
00917 else
00918 {
00919 _dbus_verbose ("Failed to getsockopt() credentials, returned len %d/%d: %s\n",
00920 cr_len, (int) sizeof (cr), _dbus_strerror (errno));
00921 }
00922 #elif defined(HAVE_CMSGCRED)
00923 credentials->pid = cmsg.cred.cmcred_pid;
00924 credentials->uid = cmsg.cred.cmcred_euid;
00925 credentials->gid = cmsg.cred.cmcred_groups[0];
00926 #else
00927 _dbus_verbose ("Socket credentials not supported on this OS\n");
00928 #endif
00929 }
00930
00931 _dbus_verbose ("Credentials:"
00932 " pid "DBUS_PID_FORMAT
00933 " uid "DBUS_UID_FORMAT
00934 " gid "DBUS_GID_FORMAT"\n",
00935 credentials->pid,
00936 credentials->uid,
00937 credentials->gid);
00938
00939 return TRUE;
00940 }
00941
00959 dbus_bool_t
00960 _dbus_send_credentials_unix_socket (int server_fd,
00961 DBusError *error)
00962 {
00963 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
00964
00965 if (write_credentials_byte (server_fd, error))
00966 return TRUE;
00967 else
00968 return FALSE;
00969 }
00970
00978 int
00979 _dbus_accept (int listen_fd)
00980 {
00981 int client_fd;
00982 struct sockaddr addr;
00983 socklen_t addrlen;
00984
00985 addrlen = sizeof (addr);
00986
00987 retry:
00988 client_fd = accept (listen_fd, &addr, &addrlen);
00989
00990 if (client_fd < 0)
00991 {
00992 if (errno == EINTR)
00993 goto retry;
00994 }
00995
00996 return client_fd;
00997 }
00998
01013 dbus_bool_t
01014 _dbus_string_append_int (DBusString *str,
01015 long value)
01016 {
01017
01018 #define MAX_LONG_LEN ((sizeof (long) * 8 + 2) / 3 + 1)
01019 int orig_len;
01020 int i;
01021 char *buf;
01022
01023 orig_len = _dbus_string_get_length (str);
01024
01025 if (!_dbus_string_lengthen (str, MAX_LONG_LEN))
01026 return FALSE;
01027
01028 buf = _dbus_string_get_data_len (str, orig_len, MAX_LONG_LEN);
01029
01030 snprintf (buf, MAX_LONG_LEN, "%ld", value);
01031
01032 i = 0;
01033 while (*buf)
01034 {
01035 ++buf;
01036 ++i;
01037 }
01038
01039 _dbus_string_shorten (str, MAX_LONG_LEN - i);
01040
01041 return TRUE;
01042 }
01043
01051 dbus_bool_t
01052 _dbus_string_append_uint (DBusString *str,
01053 unsigned long value)
01054 {
01055
01056 #define MAX_ULONG_LEN (MAX_LONG_LEN * 2)
01057 int orig_len;
01058 int i;
01059 char *buf;
01060
01061 orig_len = _dbus_string_get_length (str);
01062
01063 if (!_dbus_string_lengthen (str, MAX_ULONG_LEN))
01064 return FALSE;
01065
01066 buf = _dbus_string_get_data_len (str, orig_len, MAX_ULONG_LEN);
01067
01068 snprintf (buf, MAX_ULONG_LEN, "%lu", value);
01069
01070 i = 0;
01071 while (*buf)
01072 {
01073 ++buf;
01074 ++i;
01075 }
01076
01077 _dbus_string_shorten (str, MAX_ULONG_LEN - i);
01078
01079 return TRUE;
01080 }
01081
01082 #ifdef DBUS_BUILD_TESTS
01083
01090 dbus_bool_t
01091 _dbus_string_append_double (DBusString *str,
01092 double value)
01093 {
01094 #define MAX_DOUBLE_LEN 64
01095 int orig_len;
01096 char *buf;
01097 int i;
01098
01099 orig_len = _dbus_string_get_length (str);
01100
01101 if (!_dbus_string_lengthen (str, MAX_DOUBLE_LEN))
01102 return FALSE;
01103
01104 buf = _dbus_string_get_data_len (str, orig_len, MAX_DOUBLE_LEN);
01105
01106 snprintf (buf, MAX_LONG_LEN, "%g", value);
01107
01108 i = 0;
01109 while (*buf)
01110 {
01111 ++buf;
01112 ++i;
01113 }
01114
01115 _dbus_string_shorten (str, MAX_DOUBLE_LEN - i);
01116
01117 return TRUE;
01118 }
01119 #endif
01120
01133 dbus_bool_t
01134 _dbus_string_parse_int (const DBusString *str,
01135 int start,
01136 long *value_return,
01137 int *end_return)
01138 {
01139 long v;
01140 const char *p;
01141 char *end;
01142
01143 p = _dbus_string_get_const_data_len (str, start,
01144 _dbus_string_get_length (str) - start);
01145
01146 end = NULL;
01147 errno = 0;
01148 v = strtol (p, &end, 0);
01149 if (end == NULL || end == p || errno != 0)
01150 return FALSE;
01151
01152 if (value_return)
01153 *value_return = v;
01154 if (end_return)
01155 *end_return = start + (end - p);
01156
01157 return TRUE;
01158 }
01159
01167 dbus_bool_t
01168 _dbus_check_dir_is_private_to_user (DBusString *dir, DBusError *error)
01169 {
01170 const char *directory;
01171 struct stat sb;
01172
01173 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
01174
01175 directory = _dbus_string_get_const_data (dir);
01176
01177 if (stat (directory, &sb) < 0)
01178 {
01179 dbus_set_error (error, _dbus_error_from_errno (errno),
01180 "%s", _dbus_strerror (errno));
01181
01182 return FALSE;
01183 }
01184
01185 if ((S_IROTH & sb.st_mode) || (S_IWOTH & sb.st_mode) ||
01186 (S_IRGRP & sb.st_mode) || (S_IWGRP & sb.st_mode))
01187 {
01188 dbus_set_error (error, DBUS_ERROR_FAILED,
01189 "%s directory is not private to the user", directory);
01190 return FALSE;
01191 }
01192
01193 return TRUE;
01194 }
01195
01196 #ifdef DBUS_BUILD_TESTS
01197
01210 dbus_bool_t
01211 _dbus_string_parse_uint (const DBusString *str,
01212 int start,
01213 unsigned long *value_return,
01214 int *end_return)
01215 {
01216 unsigned long v;
01217 const char *p;
01218 char *end;
01219
01220 p = _dbus_string_get_const_data_len (str, start,
01221 _dbus_string_get_length (str) - start);
01222
01223 end = NULL;
01224 errno = 0;
01225 v = strtoul (p, &end, 0);
01226 if (end == NULL || end == p || errno != 0)
01227 return FALSE;
01228
01229 if (value_return)
01230 *value_return = v;
01231 if (end_return)
01232 *end_return = start + (end - p);
01233
01234 return TRUE;
01235 }
01236 #endif
01237
01238 #ifdef DBUS_BUILD_TESTS
01239 static dbus_bool_t
01240 ascii_isspace (char c)
01241 {
01242 return (c == ' ' ||
01243 c == '\f' ||
01244 c == '\n' ||
01245 c == '\r' ||
01246 c == '\t' ||
01247 c == '\v');
01248 }
01249 #endif
01250
01251 #ifdef DBUS_BUILD_TESTS
01252 static dbus_bool_t
01253 ascii_isdigit (char c)
01254 {
01255 return c >= '0' && c <= '9';
01256 }
01257 #endif
01258
01259 #ifdef DBUS_BUILD_TESTS
01260 static dbus_bool_t
01261 ascii_isxdigit (char c)
01262 {
01263 return (ascii_isdigit (c) ||
01264 (c >= 'a' && c <= 'f') ||
01265 (c >= 'A' && c <= 'F'));
01266 }
01267 #endif
01268
01269 #ifdef DBUS_BUILD_TESTS
01270
01271
01272
01273
01274
01275 static double
01276 ascii_strtod (const char *nptr,
01277 char **endptr)
01278 {
01279 char *fail_pos;
01280 double val;
01281 struct lconv *locale_data;
01282 const char *decimal_point;
01283 int decimal_point_len;
01284 const char *p, *decimal_point_pos;
01285 const char *end = NULL;
01286
01287 fail_pos = NULL;
01288
01289 locale_data = localeconv ();
01290 decimal_point = locale_data->decimal_point;
01291 decimal_point_len = strlen (decimal_point);
01292
01293 _dbus_assert (decimal_point_len != 0);
01294
01295 decimal_point_pos = NULL;
01296 if (decimal_point[0] != '.' ||
01297 decimal_point[1] != 0)
01298 {
01299 p = nptr;
01300
01301 while (ascii_isspace (*p))
01302 p++;
01303
01304
01305 if (*p == '+' || *p == '-')
01306 p++;
01307
01308 if (p[0] == '0' &&
01309 (p[1] == 'x' || p[1] == 'X'))
01310 {
01311 p += 2;
01312
01313
01314 while (ascii_isxdigit (*p))
01315 p++;
01316
01317 if (*p == '.')
01318 {
01319 decimal_point_pos = p++;
01320
01321 while (ascii_isxdigit (*p))
01322 p++;
01323
01324 if (*p == 'p' || *p == 'P')
01325 p++;
01326 if (*p == '+' || *p == '-')
01327 p++;
01328 while (ascii_isdigit (*p))
01329 p++;
01330 end = p;
01331 }
01332 }
01333 else
01334 {
01335 while (ascii_isdigit (*p))
01336 p++;
01337
01338 if (*p == '.')
01339 {
01340 decimal_point_pos = p++;
01341
01342 while (ascii_isdigit (*p))
01343 p++;
01344
01345 if (*p == 'e' || *p == 'E')
01346 p++;
01347 if (*p == '+' || *p == '-')
01348 p++;
01349 while (ascii_isdigit (*p))
01350 p++;
01351 end = p;
01352 }
01353 }
01354
01355 }
01356
01357
01358
01359 errno = 0;
01360
01361 if (decimal_point_pos)
01362 {
01363 char *copy, *c;
01364
01365
01366 copy = dbus_malloc (end - nptr + 1 + decimal_point_len);
01367
01368 c = copy;
01369 memcpy (c, nptr, decimal_point_pos - nptr);
01370 c += decimal_point_pos - nptr;
01371 memcpy (c, decimal_point, decimal_point_len);
01372 c += decimal_point_len;
01373 memcpy (c, decimal_point_pos + 1, end - (decimal_point_pos + 1));
01374 c += end - (decimal_point_pos + 1);
01375 *c = 0;
01376
01377 val = strtod (copy, &fail_pos);
01378
01379 if (fail_pos)
01380 {
01381 if (fail_pos > decimal_point_pos)
01382 fail_pos = (char *)nptr + (fail_pos - copy) - (decimal_point_len - 1);
01383 else
01384 fail_pos = (char *)nptr + (fail_pos - copy);
01385 }
01386
01387 dbus_free (copy);
01388
01389 }
01390 else
01391 val = strtod (nptr, &fail_pos);
01392
01393 if (endptr)
01394 *endptr = fail_pos;
01395
01396 return val;
01397 }
01398 #endif
01399
01400 #ifdef DBUS_BUILD_TESTS
01401
01413 dbus_bool_t
01414 _dbus_string_parse_double (const DBusString *str,
01415 int start,
01416 double *value_return,
01417 int *end_return)
01418 {
01419 double v;
01420 const char *p;
01421 char *end;
01422
01423 p = _dbus_string_get_const_data_len (str, start,
01424 _dbus_string_get_length (str) - start);
01425
01426 end = NULL;
01427 errno = 0;
01428 v = ascii_strtod (p, &end);
01429 if (end == NULL || end == p || errno != 0)
01430 return FALSE;
01431
01432 if (value_return)
01433 *value_return = v;
01434 if (end_return)
01435 *end_return = start + (end - p);
01436
01437 return TRUE;
01438 }
01439 #endif
01440
01442
01447 static dbus_bool_t
01448 fill_user_info_from_passwd (struct passwd *p,
01449 DBusUserInfo *info,
01450 DBusError *error)
01451 {
01452 _dbus_assert (p->pw_name != NULL);
01453 _dbus_assert (p->pw_dir != NULL);
01454
01455 info->uid = p->pw_uid;
01456 info->primary_gid = p->pw_gid;
01457 info->username = _dbus_strdup (p->pw_name);
01458 info->homedir = _dbus_strdup (p->pw_dir);
01459
01460 if (info->username == NULL ||
01461 info->homedir == NULL)
01462 {
01463 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
01464 return FALSE;
01465 }
01466
01467 return TRUE;
01468 }
01469
01470 static dbus_bool_t
01471 fill_user_info (DBusUserInfo *info,
01472 dbus_uid_t uid,
01473 const DBusString *username,
01474 DBusError *error)
01475 {
01476 const char *username_c;
01477
01478
01479 _dbus_assert (username != NULL || uid != DBUS_UID_UNSET);
01480 _dbus_assert (username == NULL || uid == DBUS_UID_UNSET);
01481
01482 info->uid = DBUS_UID_UNSET;
01483 info->primary_gid = DBUS_GID_UNSET;
01484 info->group_ids = NULL;
01485 info->n_group_ids = 0;
01486 info->username = NULL;
01487 info->homedir = NULL;
01488
01489 if (username != NULL)
01490 username_c = _dbus_string_get_const_data (username);
01491 else
01492 username_c = NULL;
01493
01494
01495
01496
01497
01498
01499 #if defined (HAVE_POSIX_GETPWNAM_R) || defined (HAVE_NONPOSIX_GETPWNAM_R)
01500 {
01501 struct passwd *p;
01502 int result;
01503 char buf[1024];
01504 struct passwd p_str;
01505
01506 p = NULL;
01507 #ifdef HAVE_POSIX_GETPWNAM_R
01508 if (uid != DBUS_UID_UNSET)
01509 result = getpwuid_r (uid, &p_str, buf, sizeof (buf),
01510 &p);
01511 else
01512 result = getpwnam_r (username_c, &p_str, buf, sizeof (buf),
01513 &p);
01514 #else
01515 if (uid != DBUS_UID_UNSET)
01516 p = getpwuid_r (uid, &p_str, buf, sizeof (buf));
01517 else
01518 p = getpwnam_r (username_c, &p_str, buf, sizeof (buf));
01519 result = 0;
01520 #endif
01521 if (result == 0 && p == &p_str)
01522 {
01523 if (!fill_user_info_from_passwd (p, info, error))
01524 return FALSE;
01525 }
01526 else
01527 {
01528 dbus_set_error (error, _dbus_error_from_errno (errno),
01529 "User \"%s\" unknown or no memory to allocate password entry\n",
01530 username_c ? username_c : "???");
01531 _dbus_verbose ("User %s unknown\n", username_c ? username_c : "???");
01532 return FALSE;
01533 }
01534 }
01535 #else
01536 {
01537
01538 struct passwd *p;
01539
01540 if (uid != DBUS_UID_UNSET)
01541 p = getpwuid (uid);
01542 else
01543 p = getpwnam (username_c);
01544
01545 if (p != NULL)
01546 {
01547 if (!fill_user_info_from_passwd (p, info, error))
01548 return FALSE;
01549 }
01550 else
01551 {
01552 dbus_set_error (error, _dbus_error_from_errno (errno),
01553 "User \"%s\" unknown or no memory to allocate password entry\n",
01554 username_c ? username_c : "???");
01555 _dbus_verbose ("User %s unknown\n", username_c ? username_c : "???");
01556 return FALSE;
01557 }
01558 }
01559 #endif
01560
01561
01562 username_c = info->username;
01563
01564 #ifdef HAVE_GETGROUPLIST
01565 {
01566 gid_t *buf;
01567 int buf_count;
01568 int i;
01569
01570 buf_count = 17;
01571 buf = dbus_new (gid_t, buf_count);
01572 if (buf == NULL)
01573 {
01574 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
01575 goto failed;
01576 }
01577
01578 if (getgrouplist (username_c,
01579 info->primary_gid,
01580 buf, &buf_count) < 0)
01581 {
01582 gid_t *new = dbus_realloc (buf, buf_count * sizeof (buf[0]));
01583 if (new == NULL)
01584 {
01585 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
01586 dbus_free (buf);
01587 goto failed;
01588 }
01589
01590 buf = new;
01591
01592 errno = 0;
01593 if (getgrouplist (username_c, info->primary_gid, buf, &buf_count) < 0)
01594 {
01595 dbus_set_error (error,
01596 _dbus_error_from_errno (errno),
01597 "Failed to get groups for username \"%s\" primary GID "
01598 DBUS_GID_FORMAT ": %s\n",
01599 username_c, info->primary_gid,
01600 _dbus_strerror (errno));
01601 dbus_free (buf);
01602 goto failed;
01603 }
01604 }
01605
01606 info->group_ids = dbus_new (dbus_gid_t, buf_count);
01607 if (info->group_ids == NULL)
01608 {
01609 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
01610 dbus_free (buf);
01611 goto failed;
01612 }
01613
01614 for (i = 0; i < buf_count; ++i)
01615 info->group_ids[i] = buf[i];
01616
01617 info->n_group_ids = buf_count;
01618
01619 dbus_free (buf);
01620 }
01621 #else
01622 {
01623
01624 info->group_ids = dbus_new (dbus_gid_t, 1);
01625 if (info->group_ids == NULL)
01626 {
01627 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
01628 goto failed;
01629 }
01630
01631 info->n_group_ids = 1;
01632
01633 (info->group_ids)[0] = info->primary_gid;
01634 }
01635 #endif
01636
01637 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
01638
01639 return TRUE;
01640
01641 failed:
01642 _DBUS_ASSERT_ERROR_IS_SET (error);
01643 return FALSE;
01644 }
01645
01654 dbus_bool_t
01655 _dbus_user_info_fill (DBusUserInfo *info,
01656 const DBusString *username,
01657 DBusError *error)
01658 {
01659 return fill_user_info (info, DBUS_UID_UNSET,
01660 username, error);
01661 }
01662
01671 dbus_bool_t
01672 _dbus_user_info_fill_uid (DBusUserInfo *info,
01673 dbus_uid_t uid,
01674 DBusError *error)
01675 {
01676 return fill_user_info (info, uid,
01677 NULL, error);
01678 }
01679
01685 void
01686 _dbus_user_info_free (DBusUserInfo *info)
01687 {
01688 dbus_free (info->group_ids);
01689 dbus_free (info->username);
01690 dbus_free (info->homedir);
01691 }
01692
01699 void
01700 _dbus_credentials_clear (DBusCredentials *credentials)
01701 {
01702 credentials->pid = DBUS_PID_UNSET;
01703 credentials->uid = DBUS_UID_UNSET;
01704 credentials->gid = DBUS_GID_UNSET;
01705 }
01706
01712 void
01713 _dbus_credentials_from_current_process (DBusCredentials *credentials)
01714 {
01715
01716
01717
01718
01719 _dbus_assert (sizeof (pid_t) <= sizeof (credentials->pid));
01720 _dbus_assert (sizeof (uid_t) <= sizeof (credentials->uid));
01721 _dbus_assert (sizeof (gid_t) <= sizeof (credentials->gid));
01722
01723 credentials->pid = getpid ();
01724 credentials->uid = getuid ();
01725 credentials->gid = getgid ();
01726 }
01727
01736 dbus_bool_t
01737 _dbus_credentials_match (const DBusCredentials *expected_credentials,
01738 const DBusCredentials *provided_credentials)
01739 {
01740 if (provided_credentials->uid == DBUS_UID_UNSET)
01741 return FALSE;
01742 else if (expected_credentials->uid == DBUS_UID_UNSET)
01743 return FALSE;
01744 else if (provided_credentials->uid == 0)
01745 return TRUE;
01746 else if (provided_credentials->uid == expected_credentials->uid)
01747 return TRUE;
01748 else
01749 return FALSE;
01750 }
01751
01756 unsigned long
01757 _dbus_getpid (void)
01758 {
01759 return getpid ();
01760 }
01761
01765 dbus_uid_t
01766 _dbus_getuid (void)
01767 {
01768 return getuid ();
01769 }
01770
01771 #ifdef DBUS_BUILD_TESTS
01772
01775 dbus_gid_t
01776 _dbus_getgid (void)
01777 {
01778 return getgid ();
01779 }
01780 #endif
01781
01782 _DBUS_DEFINE_GLOBAL_LOCK (atomic);
01783
01784 #ifdef DBUS_USE_ATOMIC_INT_486
01785
01786
01787 static inline dbus_int32_t
01788 atomic_exchange_and_add (DBusAtomic *atomic,
01789 volatile dbus_int32_t val)
01790 {
01791 register dbus_int32_t result;
01792
01793 __asm__ __volatile__ ("lock; xaddl %0,%1"
01794 : "=r" (result), "=m" (atomic->value)
01795 : "0" (val), "m" (atomic->value));
01796 return result;
01797 }
01798 #endif
01799
01808 dbus_int32_t
01809 _dbus_atomic_inc (DBusAtomic *atomic)
01810 {
01811 #ifdef DBUS_USE_ATOMIC_INT_486
01812 return atomic_exchange_and_add (atomic, 1);
01813 #else
01814 dbus_int32_t res;
01815 _DBUS_LOCK (atomic);
01816 res = atomic->value;
01817 atomic->value += 1;
01818 _DBUS_UNLOCK (atomic);
01819 return res;
01820 #endif
01821 }
01822
01831 dbus_int32_t
01832 _dbus_atomic_dec (DBusAtomic *atomic)
01833 {
01834 #ifdef DBUS_USE_ATOMIC_INT_486
01835 return atomic_exchange_and_add (atomic, -1);
01836 #else
01837 dbus_int32_t res;
01838
01839 _DBUS_LOCK (atomic);
01840 res = atomic->value;
01841 atomic->value -= 1;
01842 _DBUS_UNLOCK (atomic);
01843 return res;
01844 #endif
01845 }
01846
01855 int
01856 _dbus_poll (DBusPollFD *fds,
01857 int n_fds,
01858 int timeout_milliseconds)
01859 {
01860 #ifdef HAVE_POLL
01861
01862
01863
01864
01865 if (_DBUS_POLLIN == POLLIN &&
01866 _DBUS_POLLPRI == POLLPRI &&
01867 _DBUS_POLLOUT == POLLOUT &&
01868 _DBUS_POLLERR == POLLERR &&
01869 _DBUS_POLLHUP == POLLHUP &&
01870 _DBUS_POLLNVAL == POLLNVAL &&
01871 sizeof (DBusPollFD) == sizeof (struct pollfd) &&
01872 _DBUS_STRUCT_OFFSET (DBusPollFD, fd) ==
01873 _DBUS_STRUCT_OFFSET (struct pollfd, fd) &&
01874 _DBUS_STRUCT_OFFSET (DBusPollFD, events) ==
01875 _DBUS_STRUCT_OFFSET (struct pollfd, events) &&
01876 _DBUS_STRUCT_OFFSET (DBusPollFD, revents) ==
01877 _DBUS_STRUCT_OFFSET (struct pollfd, revents))
01878 {
01879 return poll ((struct pollfd*) fds,
01880 n_fds,
01881 timeout_milliseconds);
01882 }
01883 else
01884 {
01885
01886
01887
01888 _dbus_warn ("didn't implement poll() properly for this system yet\n");
01889 return -1;
01890 }
01891 #else
01892
01893 fd_set read_set, write_set, err_set;
01894 int max_fd = 0;
01895 int i;
01896 struct timeval tv;
01897 int ready;
01898
01899 FD_ZERO (&read_set);
01900 FD_ZERO (&write_set);
01901 FD_ZERO (&err_set);
01902
01903 for (i = 0; i < n_fds; i++)
01904 {
01905 DBusPollFD *fdp = &fds[i];
01906
01907 if (fdp->events & _DBUS_POLLIN)
01908 FD_SET (fdp->fd, &read_set);
01909
01910 if (fdp->events & _DBUS_POLLOUT)
01911 FD_SET (fdp->fd, &write_set);
01912
01913 FD_SET (fdp->fd, &err_set);
01914
01915 max_fd = MAX (max_fd, fdp->fd);
01916 }
01917
01918 tv.tv_sec = timeout_milliseconds / 1000;
01919 tv.tv_usec = (timeout_milliseconds % 1000) * 1000;
01920
01921 ready = select (max_fd + 1, &read_set, &write_set, &err_set,
01922 timeout_milliseconds < 0 ? NULL : &tv);
01923
01924 if (ready > 0)
01925 {
01926 for (i = 0; i < n_fds; i++)
01927 {
01928 DBusPollFD *fdp = &fds[i];
01929
01930 fdp->revents = 0;
01931
01932 if (FD_ISSET (fdp->fd, &read_set))
01933 fdp->revents |= _DBUS_POLLIN;
01934
01935 if (FD_ISSET (fdp->fd, &write_set))
01936 fdp->revents |= _DBUS_POLLOUT;
01937
01938 if (FD_ISSET (fdp->fd, &err_set))
01939 fdp->revents |= _DBUS_POLLERR;
01940 }
01941 }
01942
01943 return ready;
01944 #endif
01945 }
01946
01948 #define NANOSECONDS_PER_SECOND 1000000000
01949
01950 #define MICROSECONDS_PER_SECOND 1000000
01951
01952 #define MILLISECONDS_PER_SECOND 1000
01953
01954 #define NANOSECONDS_PER_MILLISECOND 1000000
01955
01956 #define MICROSECONDS_PER_MILLISECOND 1000
01957
01962 void
01963 _dbus_sleep_milliseconds (int milliseconds)
01964 {
01965 #ifdef HAVE_NANOSLEEP
01966 struct timespec req;
01967 struct timespec rem;
01968
01969 req.tv_sec = milliseconds / MILLISECONDS_PER_SECOND;
01970 req.tv_nsec = (milliseconds % MILLISECONDS_PER_SECOND) * NANOSECONDS_PER_MILLISECOND;
01971 rem.tv_sec = 0;
01972 rem.tv_nsec = 0;
01973
01974 while (nanosleep (&req, &rem) < 0 && errno == EINTR)
01975 req = rem;
01976 #elif defined (HAVE_USLEEP)
01977 usleep (milliseconds * MICROSECONDS_PER_MILLISECOND);
01978 #else
01979 sleep (MAX (milliseconds / 1000, 1));
01980 #endif
01981 }
01982
01989 void
01990 _dbus_get_current_time (long *tv_sec,
01991 long *tv_usec)
01992 {
01993 struct timeval t;
01994
01995 gettimeofday (&t, NULL);
01996
01997 if (tv_sec)
01998 *tv_sec = t.tv_sec;
01999 if (tv_usec)
02000 *tv_usec = t.tv_usec;
02001 }
02002
02013 dbus_bool_t
02014 _dbus_file_get_contents (DBusString *str,
02015 const DBusString *filename,
02016 DBusError *error)
02017 {
02018 int fd;
02019 struct stat sb;
02020 int orig_len;
02021 int total;
02022 const char *filename_c;
02023
02024 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
02025
02026 filename_c = _dbus_string_get_const_data (filename);
02027
02028
02029 fd = open (filename_c, O_RDONLY | O_BINARY);
02030 if (fd < 0)
02031 {
02032 dbus_set_error (error, _dbus_error_from_errno (errno),
02033 "Failed to open \"%s\": %s",
02034 filename_c,
02035 _dbus_strerror (errno));
02036 return FALSE;
02037 }
02038
02039 if (fstat (fd, &sb) < 0)
02040 {
02041 dbus_set_error (error, _dbus_error_from_errno (errno),
02042 "Failed to stat \"%s\": %s",
02043 filename_c,
02044 _dbus_strerror (errno));
02045
02046 _dbus_verbose ("fstat() failed: %s",
02047 _dbus_strerror (errno));
02048
02049 close (fd);
02050
02051 return FALSE;
02052 }
02053
02054 if (sb.st_size > _DBUS_ONE_MEGABYTE)
02055 {
02056 dbus_set_error (error, DBUS_ERROR_FAILED,
02057 "File size %lu of \"%s\" is too large.",
02058 (unsigned long) sb.st_size, filename_c);
02059 close (fd);
02060 return FALSE;
02061 }
02062
02063 total = 0;
02064 orig_len = _dbus_string_get_length (str);
02065 if (sb.st_size > 0 && S_ISREG (sb.st_mode))
02066 {
02067 int bytes_read;
02068
02069 while (total < (int) sb.st_size)
02070 {
02071 bytes_read = _dbus_read (fd, str,
02072 sb.st_size - total);
02073 if (bytes_read <= 0)
02074 {
02075 dbus_set_error (error, _dbus_error_from_errno (errno),
02076 "Error reading \"%s\": %s",
02077 filename_c,
02078 _dbus_strerror (errno));
02079
02080 _dbus_verbose ("read() failed: %s",
02081 _dbus_strerror (errno));
02082
02083 close (fd);
02084 _dbus_string_set_length (str, orig_len);
02085 return FALSE;
02086 }
02087 else
02088 total += bytes_read;
02089 }
02090
02091 close (fd);
02092 return TRUE;
02093 }
02094 else if (sb.st_size != 0)
02095 {
02096 _dbus_verbose ("Can only open regular files at the moment.\n");
02097 dbus_set_error (error, DBUS_ERROR_FAILED,
02098 "\"%s\" is not a regular file",
02099 filename_c);
02100 close (fd);
02101 return FALSE;
02102 }
02103 else
02104 {
02105 close (fd);
02106 return TRUE;
02107 }
02108 }
02109
02119 dbus_bool_t
02120 _dbus_string_save_to_file (const DBusString *str,
02121 const DBusString *filename,
02122 DBusError *error)
02123 {
02124 int fd;
02125 int bytes_to_write;
02126 const char *filename_c;
02127 DBusString tmp_filename;
02128 const char *tmp_filename_c;
02129 int total;
02130 dbus_bool_t need_unlink;
02131 dbus_bool_t retval;
02132
02133 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
02134
02135 fd = -1;
02136 retval = FALSE;
02137 need_unlink = FALSE;
02138
02139 if (!_dbus_string_init (&tmp_filename))
02140 {
02141 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
02142 return FALSE;
02143 }
02144
02145 if (!_dbus_string_copy (filename, 0, &tmp_filename, 0))
02146 {
02147 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
02148 _dbus_string_free (&tmp_filename);
02149 return FALSE;
02150 }
02151
02152 if (!_dbus_string_append (&tmp_filename, "."))
02153 {
02154 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
02155 _dbus_string_free (&tmp_filename);
02156 return FALSE;
02157 }
02158
02159 #define N_TMP_FILENAME_RANDOM_BYTES 8
02160 if (!_dbus_generate_random_ascii (&tmp_filename, N_TMP_FILENAME_RANDOM_BYTES))
02161 {
02162 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
02163 _dbus_string_free (&tmp_filename);
02164 return FALSE;
02165 }
02166
02167 filename_c = _dbus_string_get_const_data (filename);
02168 tmp_filename_c = _dbus_string_get_const_data (&tmp_filename);
02169
02170 fd = open (tmp_filename_c, O_WRONLY | O_BINARY | O_EXCL | O_CREAT,
02171 0600);
02172 if (fd < 0)
02173 {
02174 dbus_set_error (error, _dbus_error_from_errno (errno),
02175 "Could not create %s: %s", tmp_filename_c,
02176 _dbus_strerror (errno));
02177 goto out;
02178 }
02179
02180 need_unlink = TRUE;
02181
02182 total = 0;
02183 bytes_to_write = _dbus_string_get_length (str);
02184
02185 while (total < bytes_to_write)
02186 {
02187 int bytes_written;
02188
02189 bytes_written = _dbus_write (fd, str, total,
02190 bytes_to_write - total);
02191
02192 if (bytes_written <= 0)
02193 {
02194 dbus_set_error (error, _dbus_error_from_errno (errno),
02195 "Could not write to %s: %s", tmp_filename_c,
02196 _dbus_strerror (errno));
02197
02198 goto out;
02199 }
02200
02201 total += bytes_written;
02202 }
02203
02204 if (close (fd) < 0)
02205 {
02206 dbus_set_error (error, _dbus_error_from_errno (errno),
02207 "Could not close file %s: %s",
02208 tmp_filename_c, _dbus_strerror (errno));
02209
02210 goto out;
02211 }
02212
02213 fd = -1;
02214
02215 if (rename (tmp_filename_c, filename_c) < 0)
02216 {
02217 dbus_set_error (error, _dbus_error_from_errno (errno),
02218 "Could not rename %s to %s: %s",
02219 tmp_filename_c, filename_c,
02220 _dbus_strerror (errno));
02221
02222 goto out;
02223 }
02224
02225 need_unlink = FALSE;
02226
02227 retval = TRUE;
02228
02229 out:
02230
02231
02232
02233
02234 if (fd >= 0)
02235 close (fd);
02236
02237 if (need_unlink && unlink (tmp_filename_c) < 0)
02238 _dbus_verbose ("Failed to unlink temp file %s: %s\n",
02239 tmp_filename_c, _dbus_strerror (errno));
02240
02241 _dbus_string_free (&tmp_filename);
02242
02243 if (!retval)
02244 _DBUS_ASSERT_ERROR_IS_SET (error);
02245
02246 return retval;
02247 }
02248
02255 dbus_bool_t
02256 _dbus_create_file_exclusively (const DBusString *filename,
02257 DBusError *error)
02258 {
02259 int fd;
02260 const char *filename_c;
02261
02262 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
02263
02264 filename_c = _dbus_string_get_const_data (filename);
02265
02266 fd = open (filename_c, O_WRONLY | O_BINARY | O_EXCL | O_CREAT,
02267 0600);
02268 if (fd < 0)
02269 {
02270 dbus_set_error (error,
02271 DBUS_ERROR_FAILED,
02272 "Could not create file %s: %s\n",
02273 filename_c,
02274 _dbus_strerror (errno));
02275 return FALSE;
02276 }
02277
02278 if (close (fd) < 0)
02279 {
02280 dbus_set_error (error,
02281 DBUS_ERROR_FAILED,
02282 "Could not close file %s: %s\n",
02283 filename_c,
02284 _dbus_strerror (errno));
02285 return FALSE;
02286 }
02287
02288 return TRUE;
02289 }
02290
02299 dbus_bool_t
02300 _dbus_delete_file (const DBusString *filename,
02301 DBusError *error)
02302 {
02303 const char *filename_c;
02304
02305 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
02306
02307 filename_c = _dbus_string_get_const_data (filename);
02308
02309 if (unlink (filename_c) < 0)
02310 {
02311 dbus_set_error (error, DBUS_ERROR_FAILED,
02312 "Failed to delete file %s: %s\n",
02313 filename_c, _dbus_strerror (errno));
02314 return FALSE;
02315 }
02316 else
02317 return TRUE;
02318 }
02319
02328 dbus_bool_t
02329 _dbus_create_directory (const DBusString *filename,
02330 DBusError *error)
02331 {
02332 const char *filename_c;
02333
02334 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
02335
02336 filename_c = _dbus_string_get_const_data (filename);
02337
02338 if (mkdir (filename_c, 0700) < 0)
02339 {
02340 if (errno == EEXIST)
02341 return TRUE;
02342
02343 dbus_set_error (error, DBUS_ERROR_FAILED,
02344 "Failed to create directory %s: %s\n",
02345 filename_c, _dbus_strerror (errno));
02346 return FALSE;
02347 }
02348 else
02349 return TRUE;
02350 }
02351
02362 dbus_bool_t
02363 _dbus_concat_dir_and_file (DBusString *dir,
02364 const DBusString *next_component)
02365 {
02366 dbus_bool_t dir_ends_in_slash;
02367 dbus_bool_t file_starts_with_slash;
02368
02369 if (_dbus_string_get_length (dir) == 0 ||
02370 _dbus_string_get_length (next_component) == 0)
02371 return TRUE;
02372
02373 dir_ends_in_slash = '/' == _dbus_string_get_byte (dir,
02374 _dbus_string_get_length (dir) - 1);
02375
02376 file_starts_with_slash = '/' == _dbus_string_get_byte (next_component, 0);
02377
02378 if (dir_ends_in_slash && file_starts_with_slash)
02379 {
02380 _dbus_string_shorten (dir, 1);
02381 }
02382 else if (!(dir_ends_in_slash || file_starts_with_slash))
02383 {
02384 if (!_dbus_string_append_byte (dir, '/'))
02385 return FALSE;
02386 }
02387
02388 return _dbus_string_copy (next_component, 0, dir,
02389 _dbus_string_get_length (dir));
02390 }
02391
02392 static void
02393 pseudorandom_generate_random_bytes_buffer (char *buffer,
02394 int n_bytes)
02395 {
02396 unsigned long tv_usec;
02397 int i;
02398
02399
02400 _dbus_verbose ("Falling back to pseudorandom for %d bytes\n",
02401 n_bytes);
02402
02403 _dbus_get_current_time (NULL, &tv_usec);
02404 srand (tv_usec);
02405
02406 i = 0;
02407 while (i < n_bytes)
02408 {
02409 double r;
02410 unsigned int b;
02411
02412 r = rand ();
02413 b = (r / (double) RAND_MAX) * 255.0;
02414
02415 buffer[i] = b;
02416
02417 ++i;
02418 }
02419 }
02420
02421 static dbus_bool_t
02422 pseudorandom_generate_random_bytes (DBusString *str,
02423 int n_bytes)
02424 {
02425 int old_len;
02426 char *p;
02427
02428 old_len = _dbus_string_get_length (str);
02429
02430 if (!_dbus_string_lengthen (str, n_bytes))
02431 return FALSE;
02432
02433 p = _dbus_string_get_data_len (str, old_len, n_bytes);
02434
02435 pseudorandom_generate_random_bytes_buffer (p, n_bytes);
02436
02437 return TRUE;
02438 }
02439
02446 void
02447 _dbus_generate_random_bytes_buffer (char *buffer,
02448 int n_bytes)
02449 {
02450 DBusString str;
02451
02452 if (!_dbus_string_init (&str))
02453 {
02454 pseudorandom_generate_random_bytes_buffer (buffer, n_bytes);
02455 return;
02456 }
02457
02458 if (!_dbus_generate_random_bytes (&str, n_bytes))
02459 {
02460 _dbus_string_free (&str);
02461 pseudorandom_generate_random_bytes_buffer (buffer, n_bytes);
02462 return;
02463 }
02464
02465 _dbus_string_copy_to_buffer (&str, buffer, n_bytes);
02466
02467 _dbus_string_free (&str);
02468 }
02469
02478 dbus_bool_t
02479 _dbus_generate_random_bytes (DBusString *str,
02480 int n_bytes)
02481 {
02482 int old_len;
02483 int fd;
02484
02485
02486
02487
02488
02489
02490
02491 old_len = _dbus_string_get_length (str);
02492 fd = -1;
02493
02494
02495 fd = open ("/dev/urandom", O_RDONLY);
02496 if (fd < 0)
02497 return pseudorandom_generate_random_bytes (str, n_bytes);
02498
02499 if (_dbus_read (fd, str, n_bytes) != n_bytes)
02500 {
02501 close (fd);
02502 _dbus_string_set_length (str, old_len);
02503 return pseudorandom_generate_random_bytes (str, n_bytes);
02504 }
02505
02506 _dbus_verbose ("Read %d bytes from /dev/urandom\n",
02507 n_bytes);
02508
02509 close (fd);
02510
02511 return TRUE;
02512 }
02513
02522 dbus_bool_t
02523 _dbus_generate_random_ascii (DBusString *str,
02524 int n_bytes)
02525 {
02526 static const char letters[] =
02527 "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789abcdefghijklmnopqrstuvwxyz";
02528 int i;
02529 int len;
02530
02531 if (!_dbus_generate_random_bytes (str, n_bytes))
02532 return FALSE;
02533
02534 len = _dbus_string_get_length (str);
02535 i = len - n_bytes;
02536 while (i < len)
02537 {
02538 _dbus_string_set_byte (str, i,
02539 letters[_dbus_string_get_byte (str, i) %
02540 (sizeof (letters) - 1)]);
02541
02542 ++i;
02543 }
02544
02545 _dbus_assert (_dbus_string_validate_ascii (str, len - n_bytes,
02546 n_bytes));
02547
02548 return TRUE;
02549 }
02550
02558 const char*
02559 _dbus_strerror (int error_number)
02560 {
02561 const char *msg;
02562
02563 msg = strerror (error_number);
02564 if (msg == NULL)
02565 msg = "unknown";
02566
02567 return msg;
02568 }
02569
02573 void
02574 _dbus_disable_sigpipe (void)
02575 {
02576 signal (SIGPIPE, SIG_IGN);
02577 }
02578
02586 void
02587 _dbus_fd_set_close_on_exec (int fd)
02588 {
02589 int val;
02590
02591 val = fcntl (fd, F_GETFD, 0);
02592
02593 if (val < 0)
02594 return;
02595
02596 val |= FD_CLOEXEC;
02597
02598 fcntl (fd, F_SETFD, val);
02599 }
02600
02610 const char*
02611 _dbus_error_from_errno (int error_number)
02612 {
02613 switch (error_number)
02614 {
02615 case 0:
02616 return DBUS_ERROR_FAILED;
02617
02618 #ifdef EPROTONOSUPPORT
02619 case EPROTONOSUPPORT:
02620 return DBUS_ERROR_NOT_SUPPORTED;
02621 #endif
02622 #ifdef EAFNOSUPPORT
02623 case EAFNOSUPPORT:
02624 return DBUS_ERROR_NOT_SUPPORTED;
02625 #endif
02626 #ifdef ENFILE
02627 case ENFILE:
02628 return DBUS_ERROR_LIMITS_EXCEEDED;
02629 #endif
02630 #ifdef EMFILE
02631 case EMFILE:
02632 return DBUS_ERROR_LIMITS_EXCEEDED;
02633 #endif
02634 #ifdef EACCES
02635 case EACCES:
02636 return DBUS_ERROR_ACCESS_DENIED;
02637 #endif
02638 #ifdef EPERM
02639 case EPERM:
02640 return DBUS_ERROR_ACCESS_DENIED;
02641 #endif
02642 #ifdef ENOBUFS
02643 case ENOBUFS:
02644 return DBUS_ERROR_NO_MEMORY;
02645 #endif
02646 #ifdef ENOMEM
02647 case ENOMEM:
02648 return DBUS_ERROR_NO_MEMORY;
02649 #endif
02650 #ifdef EINVAL
02651 case EINVAL:
02652 return DBUS_ERROR_FAILED;
02653 #endif
02654 #ifdef EBADF
02655 case EBADF:
02656 return DBUS_ERROR_FAILED;
02657 #endif
02658 #ifdef EFAULT
02659 case EFAULT:
02660 return DBUS_ERROR_FAILED;
02661 #endif
02662 #ifdef ENOTSOCK
02663 case ENOTSOCK:
02664 return DBUS_ERROR_FAILED;
02665 #endif
02666 #ifdef EISCONN
02667 case EISCONN:
02668 return DBUS_ERROR_FAILED;
02669 #endif
02670 #ifdef ECONNREFUSED
02671 case ECONNREFUSED:
02672 return DBUS_ERROR_NO_SERVER;
02673 #endif
02674 #ifdef ETIMEDOUT
02675 case ETIMEDOUT:
02676 return DBUS_ERROR_TIMEOUT;
02677 #endif
02678 #ifdef ENETUNREACH
02679 case ENETUNREACH:
02680 return DBUS_ERROR_NO_NETWORK;
02681 #endif
02682 #ifdef EADDRINUSE
02683 case EADDRINUSE:
02684 return DBUS_ERROR_ADDRESS_IN_USE;
02685 #endif
02686 #ifdef EEXIST
02687 case EEXIST:
02688 return DBUS_ERROR_FILE_NOT_FOUND;
02689 #endif
02690 #ifdef ENOENT
02691 case ENOENT:
02692 return DBUS_ERROR_FILE_NOT_FOUND;
02693 #endif
02694 }
02695
02696 return DBUS_ERROR_FAILED;
02697 }
02698
02704 void
02705 _dbus_exit (int code)
02706 {
02707 _exit (code);
02708 }
02709
02717 dbus_bool_t
02718 _dbus_close (int fd,
02719 DBusError *error)
02720 {
02721 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
02722
02723 again:
02724 if (close (fd) < 0)
02725 {
02726 if (errno == EINTR)
02727 goto again;
02728
02729 dbus_set_error (error, _dbus_error_from_errno (errno),
02730 "Could not close fd %d", fd);
02731 return FALSE;
02732 }
02733
02734 return TRUE;
02735 }
02736
02744 dbus_bool_t
02745 _dbus_set_fd_nonblocking (int fd,
02746 DBusError *error)
02747 {
02748 int val;
02749
02750 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
02751
02752 val = fcntl (fd, F_GETFL, 0);
02753 if (val < 0)
02754 {
02755 dbus_set_error (error, _dbus_error_from_errno (errno),
02756 "Failed to get flags from file descriptor %d: %s",
02757 fd, _dbus_strerror (errno));
02758 _dbus_verbose ("Failed to get flags for fd %d: %s\n", fd,
02759 _dbus_strerror (errno));
02760 return FALSE;
02761 }
02762
02763 if (fcntl (fd, F_SETFL, val | O_NONBLOCK) < 0)
02764 {
02765 dbus_set_error (error, _dbus_error_from_errno (errno),
02766 "Failed to set nonblocking flag of file descriptor %d: %s",
02767 fd, _dbus_strerror (errno));
02768 _dbus_verbose ("Failed to set fd %d nonblocking: %s\n",
02769 fd, _dbus_strerror (errno));
02770
02771 return FALSE;
02772 }
02773
02774 return TRUE;
02775 }
02776
02777 #if !defined (DBUS_DISABLE_ASSERT) || defined(DBUS_BUILD_TESTS)
02778
02783 void
02784 _dbus_print_backtrace (void)
02785 {
02786 #if defined (HAVE_BACKTRACE) && defined (DBUS_ENABLE_VERBOSE_MODE)
02787 void *bt[500];
02788 int bt_size;
02789 int i;
02790 char **syms;
02791
02792 bt_size = backtrace (bt, 500);
02793
02794 syms = backtrace_symbols (bt, bt_size);
02795
02796 i = 0;
02797 while (i < bt_size)
02798 {
02799 _dbus_verbose (" %s\n", syms[i]);
02800 ++i;
02801 }
02802
02803 free (syms);
02804 #else
02805 _dbus_verbose (" D-BUS not compiled with backtrace support\n");
02806 #endif
02807 }
02808 #endif
02809
02810
02818 dbus_bool_t
02819 _dbus_parse_uid (const DBusString *uid_str,
02820 dbus_uid_t *uid)
02821 {
02822 int end;
02823 long val;
02824
02825 if (_dbus_string_get_length (uid_str) == 0)
02826 {
02827 _dbus_verbose ("UID string was zero length\n");
02828 return FALSE;
02829 }
02830
02831 val = -1;
02832 end = 0;
02833 if (!_dbus_string_parse_int (uid_str, 0, &val,
02834 &end))
02835 {
02836 _dbus_verbose ("could not parse string as a UID\n");
02837 return FALSE;
02838 }
02839
02840 if (end != _dbus_string_get_length (uid_str))
02841 {
02842 _dbus_verbose ("string contained trailing stuff after UID\n");
02843 return FALSE;
02844 }
02845
02846 *uid = val;
02847
02848 return TRUE;
02849 }
02850
02866 dbus_bool_t
02867 _dbus_full_duplex_pipe (int *fd1,
02868 int *fd2,
02869 dbus_bool_t blocking,
02870 DBusError *error)
02871 {
02872 #ifdef HAVE_SOCKETPAIR
02873 int fds[2];
02874
02875 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
02876
02877 if (socketpair (AF_UNIX, SOCK_STREAM, 0, fds) < 0)
02878 {
02879 dbus_set_error (error, _dbus_error_from_errno (errno),
02880 "Could not create full-duplex pipe");
02881 return FALSE;
02882 }
02883
02884 if (!blocking &&
02885 (!_dbus_set_fd_nonblocking (fds[0], NULL) ||
02886 !_dbus_set_fd_nonblocking (fds[1], NULL)))
02887 {
02888 dbus_set_error (error, _dbus_error_from_errno (errno),
02889 "Could not set full-duplex pipe nonblocking");
02890
02891 close (fds[0]);
02892 close (fds[1]);
02893
02894 return FALSE;
02895 }
02896
02897 *fd1 = fds[0];
02898 *fd2 = fds[1];
02899
02900 _dbus_verbose ("full-duplex pipe %d <-> %d\n",
02901 *fd1, *fd2);
02902
02903 return TRUE;
02904 #else
02905 _dbus_warn ("_dbus_full_duplex_pipe() not implemented on this OS\n");
02906 dbus_set_error (error, DBUS_ERROR_FAILED,
02907 "_dbus_full_duplex_pipe() not implemented on this OS");
02908 return FALSE;
02909 #endif
02910 }
02911
02914