Main Page | Modules | Data Structures | File List | Data Fields | Related Pages

dbus-sysdeps.c

00001 /* -*- mode: C; c-file-style: "gnu" -*- */ 00002 /* dbus-sysdeps.c Wrappers around system/libc features (internal to D-BUS implementation) 00003 * 00004 * Copyright (C) 2002, 2003 Red Hat, Inc. 00005 * Copyright (C) 2003 CodeFactory AB 00006 * 00007 * Licensed under the Academic Free License version 2.1 00008 * 00009 * This program is free software; you can redistribute it and/or modify 00010 * it under the terms of the GNU General Public License as published by 00011 * the Free Software Foundation; either version 2 of the License, or 00012 * (at your option) any later version. 00013 * 00014 * This program is distributed in the hope that it will be useful, 00015 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00016 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00017 * GNU General Public License for more details. 00018 * 00019 * You should have received a copy of the GNU General Public License 00020 * along with this program; if not, write to the Free Software 00021 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 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); /* in case someone manages to ignore SIGABRT */ 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 /* Use system malloc to avoid memleaks that dbus_malloc 00119 * will get upset about. 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 /* Use system malloc to avoid memleaks that dbus_malloc 00147 * will get upset about. 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 /* put length back (note that this doesn't actually realloc anything) */ 00220 _dbus_string_set_length (buffer, start); 00221 return -1; 00222 } 00223 } 00224 else 00225 { 00226 /* put length back (doesn't actually realloc) */ 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 /* HAVE_WRITEV */ 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; /* we can't report an error as the first write was OK */ 00353 00354 return ret1 + ret2; 00355 } 00356 else 00357 return ret1; 00358 } 00359 #endif /* !HAVE_WRITEV */ 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 /* remember that abstract names aren't nul-terminated so we rely 00423 * on sun_path being filled in with zeroes above. 00424 */ 00425 addr.sun_path[0] = '\0'; /* this is what says "use abstract" */ 00426 strncpy (&addr.sun_path[1], path, _DBUS_MAX_SUN_PATH_LENGTH - 2); 00427 /* _dbus_verbose_bytes (addr.sun_path, sizeof (addr.sun_path)); */ 00428 #else /* HAVE_ABSTRACT_SOCKETS */ 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 /* ! HAVE_ABSTRACT_SOCKETS */ 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 /* remember that abstract names aren't nul-terminated so we rely 00511 * on sun_path being filled in with zeroes above. 00512 */ 00513 addr.sun_path[0] = '\0'; /* this is what says "use abstract" */ 00514 strncpy (&addr.sun_path[1], path, _DBUS_MAX_SUN_PATH_LENGTH - 2); 00515 /* _dbus_verbose_bytes (addr.sun_path, sizeof (addr.sun_path)); */ 00516 #else /* HAVE_ABSTRACT_SOCKETS */ 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 /* ! HAVE_ABSTRACT_SOCKETS */ 00522 } 00523 else 00524 { 00525 /* FIXME discussed security implications of this with Nalin, 00526 * and we couldn't think of where it would kick our ass, but 00527 * it still seems a bit sucky. It also has non-security suckage; 00528 * really we'd prefer to exit if the socket is already in use. 00529 * But there doesn't seem to be a good way to do this. 00530 * 00531 * Just to be extra careful, I threw in the stat() - clearly 00532 * the stat() can't *fix* any security issue, but it at least 00533 * avoids inadvertent/accidental data loss. 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 /* backlog */) < 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 /* Try opening up the permissions, but if we can't, just go ahead 00572 * and continue, maybe it will be good enough. 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 /* backlog */) < 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 /* The POSIX spec certainly doesn't promise this, but 00807 * we need these assertions to fail as soon as we're wrong about 00808 * it so we can do the porting fixups 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 /* Set the socket to receive credentials on the next message */ 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 /* !SO_PEERCRED && !HAVE_CMSGCRED */ 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 /* this calculation is from comp.lang.c faq */ 00988 #define MAX_LONG_LEN ((sizeof (long) * 8 + 2) / 3 + 1) /* +1 for '-' */ 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 /* this is wrong, but definitely on the high side. */ 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 /* this is completely made up :-/ */ 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 /* Not currently used, so only built when tests are enabled */ 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 /* DBUS_BUILD_TESTS */ 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 /* Calls strtod in a locale-independent fashion, by looking at 01197 * the locale data and patching the decimal comma to a point. 01198 * 01199 * Relicensed from glib. 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; /* Silence gcc */ 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 /* Skip leading space */ 01227 while (ascii_isspace (*p)) 01228 p++; 01229 01230 /* Skip leading optional sign */ 01231 if (*p == '+' || *p == '-') 01232 p++; 01233 01234 if (p[0] == '0' && 01235 (p[1] == 'x' || p[1] == 'X')) 01236 { 01237 p += 2; 01238 /* HEX - find the (optional) decimal point */ 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 /* For the other cases, we need not convert the decimal point */ 01281 } 01282 01283 /* Set errno to zero, so that we can distinguish zero results 01284 and underflows */ 01285 errno = 0; 01286 01287 if (decimal_point_pos) 01288 { 01289 char *copy, *c; 01290 01291 /* We need to convert the '.' to the locale specific decimal point */ 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 /* DBusString group */ 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 /* exactly one of username/uid provided */ 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 /* For now assuming that the getpwnam() and getpwuid() flavors 01419 * are always symmetrical, if not we have to add more configure 01420 * checks 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 /* !HAVE_POSIX_GETPWNAME_R */ 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 /* ! HAVE_GETPWNAM_R */ 01460 { 01461 /* I guess we're screwed on thread safety here */ 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 /* ! HAVE_GETPWNAM_R */ 01484 01485 /* Fill this in so we can use it to get groups */ 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 /* HAVE_GETGROUPLIST */ 01546 { 01547 /* We just get the one group ID */ 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 /* HAVE_GETGROUPLIST */ 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 /* info->members = dbus_strdupv (g->gr_mem) */ 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 /* For now assuming that the getgrnam() and getgrgid() flavors 01656 * always correspond to the pwnam flavors, if not we have 01657 * to add more configure checks. 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 /* !HAVE_POSIX_GETPWNAME_R */ 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 /* ! HAVE_GETPWNAM_R */ 01693 { 01694 /* I guess we're screwed on thread safety here */ 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 /* ! HAVE_GETPWNAM_R */ 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 /* The POSIX spec certainly doesn't promise this, but 01784 * we need these assertions to fail as soon as we're wrong about 01785 * it so we can do the porting fixups 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 /* Taken from CVS version 1.7 of glibc's sysdeps/i386/i486/atomicity.h */ 01852 /* Since the asm stuff here is gcc-specific we go ahead and use "inline" also */ 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 /* This big thing is a constant expression and should get optimized 01928 * out of existence. So it's more robust than a configure check at 01929 * no cost. 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 /* We have to convert the DBusPollFD to an array of 01952 * struct pollfd, poll, and convert back. 01953 */ 01954 _dbus_warn ("didn't implement poll() properly for this system yet\n"); 01955 return -1; 01956 } 01957 #else /* ! HAVE_POLL */ 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 /* ! HAVE_USLEEP */ 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 /* O_BINARY useful on Cygwin */ 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 /* close first, then unlink, to prevent ".nfs34234235" garbage 02296 * files 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 /* Ignore any separators on the end */ 02502 sep = _dbus_string_get_length (filename); 02503 if (sep == 0) 02504 return _dbus_string_append (dirname, "."); /* empty string passed in */ 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 /* Now find the previous separator */ 02515 _dbus_string_find_byte_backward (filename, sep, '/', &sep); 02516 if (sep < 0) 02517 return _dbus_string_append (dirname, "."); 02518 02519 /* skip multiple separators */ 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 /* fall back to pseudorandom */ 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 /* FALSE return means "no memory", if it could 02715 * mean something else then we'd need to return 02716 * a DBusError. So we always fall back to pseudorandom 02717 * if the I/O fails. 02718 */ 02719 02720 old_len = _dbus_string_get_length (str); 02721 fd = -1; 02722 02723 /* note, urandom on linux will fall back to pseudorandom */ 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; /* kernel out of memory */ 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 /* silently ignore failures here, if someone 03168 * doesn't have /dev/null we may as well try 03169 * to continue anyhow 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 /* Get a predictable umask */ 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 /* Set GID first, or the setuid may remove our permission 03285 * to change the GID 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//bar", "/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 /* DBUS_BUILD_TESTS */ 03447

Generated on Mon Jun 27 07:48:22 2005 for D-BUS by doxygen 1.3.7