dbus-sysdeps-unix.c

00001 /* -*- mode: C; c-file-style: "gnu" -*- */
00002 /* dbus-sysdeps-unix.c Wrappers around UNIX system/libc features (internal to D-Bus implementation)
00003  * 
00004  * Copyright (C) 2002, 2003, 2006  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-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 <fcntl.h>
00037 #include <sys/socket.h>
00038 #include <dirent.h>
00039 #include <sys/un.h>
00040 #include <pwd.h>
00041 #include <time.h>
00042 #include <locale.h>
00043 #include <sys/time.h>
00044 #include <sys/stat.h>
00045 #include <sys/wait.h>
00046 #include <netinet/in.h>
00047 #include <netdb.h>
00048 #include <grp.h>
00049 
00050 #ifdef HAVE_ERRNO_H
00051 #include <errno.h>
00052 #endif
00053 #ifdef HAVE_WRITEV
00054 #include <sys/uio.h>
00055 #endif
00056 #ifdef HAVE_POLL
00057 #include <sys/poll.h>
00058 #endif
00059 #ifdef HAVE_BACKTRACE
00060 #include <execinfo.h>
00061 #endif
00062 #ifdef HAVE_GETPEERUCRED
00063 #include <ucred.h>
00064 #endif
00065 
00066 #ifndef O_BINARY
00067 #define O_BINARY 0
00068 #endif
00069 
00070 #ifndef HAVE_SOCKLEN_T
00071 #define socklen_t int
00072 #endif
00073 
00092 int
00093 _dbus_read (int               fd,
00094             DBusString       *buffer,
00095             int               count)
00096 {
00097   int bytes_read;
00098   int start;
00099   char *data;
00100 
00101   _dbus_assert (count >= 0);
00102   
00103   start = _dbus_string_get_length (buffer);
00104 
00105   if (!_dbus_string_lengthen (buffer, count))
00106     {
00107       errno = ENOMEM;
00108       return -1;
00109     }
00110 
00111   data = _dbus_string_get_data_len (buffer, start, count);
00112 
00113  again:
00114   
00115   bytes_read = read (fd, data, count);
00116 
00117   if (bytes_read < 0)
00118     {
00119       if (errno == EINTR)
00120         goto again;
00121       else
00122         {
00123           /* put length back (note that this doesn't actually realloc anything) */
00124           _dbus_string_set_length (buffer, start);
00125           return -1;
00126         }
00127     }
00128   else
00129     {
00130       /* put length back (doesn't actually realloc) */
00131       _dbus_string_set_length (buffer, start + bytes_read);
00132 
00133 #if 0
00134       if (bytes_read > 0)
00135         _dbus_verbose_bytes_of_string (buffer, start, bytes_read);
00136 #endif
00137       
00138       return bytes_read;
00139     }
00140 }
00141 
00152 int
00153 _dbus_write (int               fd,
00154              const DBusString *buffer,
00155              int               start,
00156              int               len)
00157 {
00158   const char *data;
00159   int bytes_written;
00160   
00161   data = _dbus_string_get_const_data_len (buffer, start, len);
00162   
00163  again:
00164 
00165   bytes_written = write (fd, data, len);
00166 
00167   if (bytes_written < 0 && errno == EINTR)
00168     goto again;
00169 
00170 #if 0
00171   if (bytes_written > 0)
00172     _dbus_verbose_bytes_of_string (buffer, start, bytes_written);
00173 #endif
00174   
00175   return bytes_written;
00176 }
00177 
00198 int
00199 _dbus_write_two (int               fd,
00200                  const DBusString *buffer1,
00201                  int               start1,
00202                  int               len1,
00203                  const DBusString *buffer2,
00204                  int               start2,
00205                  int               len2)
00206 {
00207   _dbus_assert (buffer1 != NULL);
00208   _dbus_assert (start1 >= 0);
00209   _dbus_assert (start2 >= 0);
00210   _dbus_assert (len1 >= 0);
00211   _dbus_assert (len2 >= 0);
00212   
00213 #ifdef HAVE_WRITEV
00214   {
00215     struct iovec vectors[2];
00216     const char *data1;
00217     const char *data2;
00218     int bytes_written;
00219 
00220     data1 = _dbus_string_get_const_data_len (buffer1, start1, len1);
00221 
00222     if (buffer2 != NULL)
00223       data2 = _dbus_string_get_const_data_len (buffer2, start2, len2);
00224     else
00225       {
00226         data2 = NULL;
00227         start2 = 0;
00228         len2 = 0;
00229       }
00230    
00231     vectors[0].iov_base = (char*) data1;
00232     vectors[0].iov_len = len1;
00233     vectors[1].iov_base = (char*) data2;
00234     vectors[1].iov_len = len2;
00235 
00236   again:
00237    
00238     bytes_written = writev (fd,
00239                             vectors,
00240                             data2 ? 2 : 1);
00241 
00242     if (bytes_written < 0 && errno == EINTR)
00243       goto again;
00244    
00245     return bytes_written;
00246   }
00247 #else /* HAVE_WRITEV */
00248   {
00249     int ret1;
00250     
00251     ret1 = _dbus_write (fd, buffer1, start1, len1);
00252     if (ret1 == len1 && buffer2 != NULL)
00253       {
00254         ret2 = _dbus_write (fd, buffer2, start2, len2);
00255         if (ret2 < 0)
00256           ret2 = 0; /* we can't report an error as the first write was OK */
00257        
00258         return ret1 + ret2;
00259       }
00260     else
00261       return ret1;
00262   }
00263 #endif /* !HAVE_WRITEV */   
00264 }
00265 
00266 #define _DBUS_MAX_SUN_PATH_LENGTH 99
00267 
00295 int
00296 _dbus_connect_unix_socket (const char     *path,
00297                            dbus_bool_t     abstract,
00298                            DBusError      *error)
00299 {
00300   int fd;
00301   size_t path_len;
00302   struct sockaddr_un addr;  
00303 
00304   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
00305 
00306   _dbus_verbose ("connecting to unix socket %s abstract=%d\n",
00307                  path, abstract);
00308   
00309   fd = socket (PF_UNIX, SOCK_STREAM, 0);
00310   
00311   if (fd < 0)
00312     {
00313       dbus_set_error (error,
00314                       _dbus_error_from_errno (errno),
00315                       "Failed to create socket: %s",
00316                       _dbus_strerror (errno)); 
00317       
00318       return -1;
00319     }
00320 
00321   _DBUS_ZERO (addr);
00322   addr.sun_family = AF_UNIX;
00323   path_len = strlen (path);
00324 
00325   if (abstract)
00326     {
00327 #ifdef HAVE_ABSTRACT_SOCKETS
00328       addr.sun_path[0] = '\0'; /* this is what says "use abstract" */
00329       path_len++; /* Account for the extra nul byte added to the start of sun_path */
00330 
00331       if (path_len > _DBUS_MAX_SUN_PATH_LENGTH)
00332         {
00333           dbus_set_error (error, DBUS_ERROR_BAD_ADDRESS,
00334                       "Abstract socket name too long\n");
00335           _dbus_close (fd, NULL);
00336           return -1;
00337         }
00338         
00339       strncpy (&addr.sun_path[1], path, path_len);
00340       /* _dbus_verbose_bytes (addr.sun_path, sizeof (addr.sun_path)); */
00341 #else /* HAVE_ABSTRACT_SOCKETS */
00342       dbus_set_error (error, DBUS_ERROR_NOT_SUPPORTED,
00343                       "Operating system does not support abstract socket namespace\n");
00344       _dbus_close (fd, NULL);
00345       return -1;
00346 #endif /* ! HAVE_ABSTRACT_SOCKETS */
00347     }
00348   else
00349     {
00350       if (path_len > _DBUS_MAX_SUN_PATH_LENGTH)
00351         {
00352           dbus_set_error (error, DBUS_ERROR_BAD_ADDRESS,
00353                       "Socket name too long\n");
00354           _dbus_close (fd, NULL);
00355           return -1;
00356         }
00357 
00358       strncpy (addr.sun_path, path, path_len);
00359     }
00360   
00361   if (connect (fd, (struct sockaddr*) &addr, _DBUS_STRUCT_OFFSET (struct sockaddr_un, sun_path) + path_len) < 0)
00362     {      
00363       dbus_set_error (error,
00364                       _dbus_error_from_errno (errno),
00365                       "Failed to connect to socket %s: %s",
00366                       path, _dbus_strerror (errno));
00367 
00368       _dbus_close (fd, NULL);
00369       fd = -1;
00370       
00371       return -1;
00372     }
00373 
00374   if (!_dbus_set_fd_nonblocking (fd, error))
00375     {
00376       _DBUS_ASSERT_ERROR_IS_SET (error);
00377       
00378       _dbus_close (fd, NULL);
00379       fd = -1;
00380 
00381       return -1;
00382     }
00383 
00384   return fd;
00385 }
00386 
00396 static dbus_bool_t
00397 _dbus_set_local_creds (int fd, dbus_bool_t on)
00398 {
00399   dbus_bool_t retval = TRUE;
00400 
00401 #if defined(LOCAL_CREDS) && !defined(HAVE_CMSGCRED)
00402   int val = on ? 1 : 0;
00403   if (setsockopt (fd, 0, LOCAL_CREDS, &val, sizeof (val)) < 0)
00404     {
00405       _dbus_verbose ("Unable to set LOCAL_CREDS socket option on fd %d\n", fd);
00406       retval = FALSE;
00407     }
00408   else
00409     _dbus_verbose ("LOCAL_CREDS %s for further messages on fd %d\n",
00410                    on ? "enabled" : "disabled", fd);
00411 #endif
00412 
00413   return retval;
00414 }
00415 
00431 int
00432 _dbus_listen_unix_socket (const char     *path,
00433                           dbus_bool_t     abstract,
00434                           DBusError      *error)
00435 {
00436   int listen_fd;
00437   struct sockaddr_un addr;
00438   size_t path_len;
00439 
00440   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
00441 
00442   _dbus_verbose ("listening on unix socket %s abstract=%d\n",
00443                  path, abstract);
00444   
00445   listen_fd = socket (PF_UNIX, SOCK_STREAM, 0);
00446   
00447   if (listen_fd < 0)
00448     {
00449       dbus_set_error (error, _dbus_error_from_errno (errno),
00450                       "Failed to create socket \"%s\": %s",
00451                       path, _dbus_strerror (errno));
00452       return -1;
00453     }
00454 
00455   _DBUS_ZERO (addr);
00456   addr.sun_family = AF_UNIX;
00457   path_len = strlen (path);
00458   
00459   if (abstract)
00460     {
00461 #ifdef HAVE_ABSTRACT_SOCKETS
00462       /* remember that abstract names aren't nul-terminated so we rely
00463        * on sun_path being filled in with zeroes above.
00464        */
00465       addr.sun_path[0] = '\0'; /* this is what says "use abstract" */
00466       path_len++; /* Account for the extra nul byte added to the start of sun_path */
00467 
00468       if (path_len > _DBUS_MAX_SUN_PATH_LENGTH)
00469         {
00470           dbus_set_error (error, DBUS_ERROR_BAD_ADDRESS,
00471                       "Abstract socket name too long\n");
00472           _dbus_close (listen_fd, NULL);
00473           return -1;
00474         }
00475       
00476       strncpy (&addr.sun_path[1], path, path_len);
00477       /* _dbus_verbose_bytes (addr.sun_path, sizeof (addr.sun_path)); */
00478 #else /* HAVE_ABSTRACT_SOCKETS */
00479       dbus_set_error (error, DBUS_ERROR_NOT_SUPPORTED,
00480                       "Operating system does not support abstract socket namespace\n");
00481       _dbus_close (listen_fd, NULL);
00482       return -1;
00483 #endif /* ! HAVE_ABSTRACT_SOCKETS */
00484     }
00485   else
00486     {
00487       /* Discussed security implications of this with Nalin,
00488        * and we couldn't think of where it would kick our ass, but
00489        * it still seems a bit sucky. It also has non-security suckage;
00490        * really we'd prefer to exit if the socket is already in use.
00491        * But there doesn't seem to be a good way to do this.
00492        *
00493        * Just to be extra careful, I threw in the stat() - clearly
00494        * the stat() can't *fix* any security issue, but it at least
00495        * avoids inadvertent/accidental data loss.
00496        */
00497       {
00498         struct stat sb;
00499 
00500         if (stat (path, &sb) == 0 &&
00501             S_ISSOCK (sb.st_mode))
00502           unlink (path);
00503       }
00504 
00505       if (path_len > _DBUS_MAX_SUN_PATH_LENGTH)
00506         {
00507           dbus_set_error (error, DBUS_ERROR_BAD_ADDRESS,
00508                       "Abstract socket name too long\n");
00509           _dbus_close (listen_fd, NULL);
00510           return -1;
00511         }
00512         
00513       strncpy (addr.sun_path, path, path_len);
00514     }
00515   
00516   if (bind (listen_fd, (struct sockaddr*) &addr, _DBUS_STRUCT_OFFSET (struct sockaddr_un, sun_path) + path_len) < 0)
00517     {
00518       dbus_set_error (error, _dbus_error_from_errno (errno),
00519                       "Failed to bind socket \"%s\": %s",
00520                       path, _dbus_strerror (errno));
00521       _dbus_close (listen_fd, NULL);
00522       return -1;
00523     }
00524 
00525   if (listen (listen_fd, 30 /* backlog */) < 0)
00526     {
00527       dbus_set_error (error, _dbus_error_from_errno (errno),
00528                       "Failed to listen on socket \"%s\": %s",
00529                       path, _dbus_strerror (errno));
00530       _dbus_close (listen_fd, NULL);
00531       return -1;
00532     }
00533 
00534   if (!_dbus_set_local_creds (listen_fd, TRUE))
00535     {
00536       dbus_set_error (error, _dbus_error_from_errno (errno),
00537                       "Failed to enable LOCAL_CREDS on socket \"%s\": %s",
00538                       path, _dbus_strerror (errno));
00539       close (listen_fd);
00540       return -1;
00541     }
00542 
00543   if (!_dbus_set_fd_nonblocking (listen_fd, error))
00544     {
00545       _DBUS_ASSERT_ERROR_IS_SET (error);
00546       _dbus_close (listen_fd, NULL);
00547       return -1;
00548     }
00549   
00550   /* Try opening up the permissions, but if we can't, just go ahead
00551    * and continue, maybe it will be good enough.
00552    */
00553   if (!abstract && chmod (path, 0777) < 0)
00554     _dbus_warn ("Could not set mode 0777 on socket %s\n",
00555                 path);
00556   
00557   return listen_fd;
00558 }
00559 
00570 int
00571 _dbus_connect_tcp_socket (const char     *host,
00572                           dbus_uint32_t   port,
00573                           DBusError      *error)
00574 {
00575   int fd;
00576   struct sockaddr_in addr;
00577   struct hostent *he;
00578   struct in_addr *haddr;
00579 
00580   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
00581   
00582   fd = socket (AF_INET, SOCK_STREAM, 0);
00583   
00584   if (fd < 0)
00585     {
00586       dbus_set_error (error,
00587                       _dbus_error_from_errno (errno),
00588                       "Failed to create socket: %s",
00589                       _dbus_strerror (errno)); 
00590       
00591       return -1;
00592     }
00593 
00594   if (host == NULL)
00595     host = "localhost";
00596 
00597   he = gethostbyname (host);
00598   if (he == NULL) 
00599     {
00600       dbus_set_error (error,
00601                       _dbus_error_from_errno (errno),
00602                       "Failed to lookup hostname: %s",
00603                       host);
00604       _dbus_close (fd, NULL);
00605       return -1;
00606     }
00607   
00608   haddr = ((struct in_addr *) (he->h_addr_list)[0]);
00609 
00610   _DBUS_ZERO (addr);
00611   memcpy (&addr.sin_addr, haddr, sizeof(struct in_addr));
00612   addr.sin_family = AF_INET;
00613   addr.sin_port = htons (port);
00614   
00615   if (connect (fd, (struct sockaddr*) &addr, sizeof (addr)) < 0)
00616     {      
00617       dbus_set_error (error,
00618                        _dbus_error_from_errno (errno),
00619                       "Failed to connect to socket %s:%d %s",
00620                       host, port, _dbus_strerror (errno));
00621 
00622       _dbus_close (fd, NULL);
00623       fd = -1;
00624       
00625       return -1;
00626     }
00627 
00628   if (!_dbus_set_fd_nonblocking (fd, error))
00629     {
00630       _dbus_close (fd, NULL);
00631       fd = -1;
00632 
00633       return -1;
00634     }
00635 
00636   return fd;
00637 }
00638 
00649 int
00650 _dbus_listen_tcp_socket (const char     *host,
00651                          dbus_uint32_t   port,
00652                          DBusError      *error)
00653 {
00654   int listen_fd;
00655   struct sockaddr_in addr;
00656   struct hostent *he;
00657   struct in_addr *haddr;
00658 
00659   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
00660   
00661   listen_fd = socket (AF_INET, SOCK_STREAM, 0);
00662   
00663   if (listen_fd < 0)
00664     {
00665       dbus_set_error (error, _dbus_error_from_errno (errno),
00666                       "Failed to create socket \"%s:%d\": %s",
00667                       host, port, _dbus_strerror (errno));
00668       return -1;
00669     }
00670 
00671   he = gethostbyname (host);
00672   if (he == NULL) 
00673     {
00674       dbus_set_error (error,
00675                       _dbus_error_from_errno (errno),
00676                       "Failed to lookup hostname: %s",
00677                       host);
00678       _dbus_close (listen_fd, NULL);
00679       return -1;
00680     }
00681   
00682   haddr = ((struct in_addr *) (he->h_addr_list)[0]);
00683 
00684   _DBUS_ZERO (addr);
00685   memcpy (&addr.sin_addr, haddr, sizeof (struct in_addr));
00686   addr.sin_family = AF_INET;
00687   addr.sin_port = htons (port);
00688 
00689   if (bind (listen_fd, (struct sockaddr*) &addr, sizeof (struct sockaddr)))
00690     {
00691       dbus_set_error (error, _dbus_error_from_errno (errno),
00692                       "Failed to bind socket \"%s:%d\": %s",
00693                       host, port, _dbus_strerror (errno));
00694       _dbus_close (listen_fd, NULL);
00695       return -1;
00696     }
00697 
00698   if (listen (listen_fd, 30 /* backlog */) < 0)
00699     {
00700       dbus_set_error (error, _dbus_error_from_errno (errno),  
00701                       "Failed to listen on socket \"%s:%d\": %s",
00702                       host, port, _dbus_strerror (errno));
00703       _dbus_close (listen_fd, NULL);
00704       return -1;
00705     }
00706 
00707   if (!_dbus_set_fd_nonblocking (listen_fd, error))
00708     {
00709       _dbus_close (listen_fd, NULL);
00710       return -1;
00711     }
00712   
00713   return listen_fd;
00714 }
00715 
00716 static dbus_bool_t
00717 write_credentials_byte (int             server_fd,
00718                         DBusError      *error)
00719 {
00720   int bytes_written;
00721   char buf[1] = { '\0' };
00722 #if defined(HAVE_CMSGCRED) && !defined(LOCAL_CREDS)
00723   struct {
00724           struct cmsghdr hdr;
00725           struct cmsgcred cred;
00726   } cmsg;
00727   struct iovec iov;
00728   struct msghdr msg;
00729 #endif
00730 
00731 #if defined(HAVE_CMSGCRED) && !defined(LOCAL_CREDS)
00732   iov.iov_base = buf;
00733   iov.iov_len = 1;
00734 
00735   memset (&msg, 0, sizeof (msg));
00736   msg.msg_iov = &iov;
00737   msg.msg_iovlen = 1;
00738 
00739   msg.msg_control = &cmsg;
00740   msg.msg_controllen = sizeof (cmsg);
00741   memset (&cmsg, 0, sizeof (cmsg));
00742   cmsg.hdr.cmsg_len = sizeof (cmsg);
00743   cmsg.hdr.cmsg_level = SOL_SOCKET;
00744   cmsg.hdr.cmsg_type = SCM_CREDS;
00745 #endif
00746 
00747   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
00748   
00749  again:
00750 
00751 #if defined(HAVE_CMSGCRED) && !defined(LOCAL_CREDS)
00752   bytes_written = sendmsg (server_fd, &msg, 0);
00753 #else
00754   bytes_written = write (server_fd, buf, 1);
00755 #endif
00756 
00757   if (bytes_written < 0 && errno == EINTR)
00758     goto again;
00759 
00760   if (bytes_written < 0)
00761     {
00762       dbus_set_error (error, _dbus_error_from_errno (errno),
00763                       "Failed to write credentials byte: %s",
00764                      _dbus_strerror (errno));
00765       return FALSE;
00766     }
00767   else if (bytes_written == 0)
00768     {
00769       dbus_set_error (error, DBUS_ERROR_IO_ERROR,
00770                       "wrote zero bytes writing credentials byte");
00771       return FALSE;
00772     }
00773   else
00774     {
00775       _dbus_assert (bytes_written == 1);
00776       _dbus_verbose ("wrote credentials byte\n");
00777       return TRUE;
00778     }
00779 }
00780 
00799 dbus_bool_t
00800 _dbus_read_credentials_unix_socket  (int              client_fd,
00801                                      DBusCredentials *credentials,
00802                                      DBusError       *error)
00803 {
00804   struct msghdr msg;
00805   struct iovec iov;
00806   char buf;
00807 
00808 #ifdef HAVE_CMSGCRED 
00809   struct {
00810           struct cmsghdr hdr;
00811           struct cmsgcred cred;
00812   } cmsg;
00813 
00814 #elif defined(LOCAL_CREDS)
00815   struct {
00816           struct cmsghdr hdr;
00817           struct sockcred cred;
00818   } cmsg;
00819 #endif
00820 
00821   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
00822   
00823   /* The POSIX spec certainly doesn't promise this, but
00824    * we need these assertions to fail as soon as we're wrong about
00825    * it so we can do the porting fixups
00826    */
00827   _dbus_assert (sizeof (pid_t) <= sizeof (credentials->pid));
00828   _dbus_assert (sizeof (uid_t) <= sizeof (credentials->uid));
00829   _dbus_assert (sizeof (gid_t) <= sizeof (credentials->gid));
00830 
00831   _dbus_credentials_clear (credentials);
00832 
00833   /* Systems supporting LOCAL_CREDS are configured to have this feature
00834    * enabled (if it does not conflict with HAVE_CMSGCRED) prior accepting
00835    * the connection.  Therefore, the received message must carry the
00836    * credentials information without doing anything special.
00837    */
00838 
00839   iov.iov_base = &buf;
00840   iov.iov_len = 1;
00841 
00842   memset (&msg, 0, sizeof (msg));
00843   msg.msg_iov = &iov;
00844   msg.msg_iovlen = 1;
00845 
00846 #if defined(HAVE_CMSGCRED) || defined(LOCAL_CREDS)
00847   memset (&cmsg, 0, sizeof (cmsg));
00848   msg.msg_control = &cmsg;
00849   msg.msg_controllen = sizeof (cmsg);
00850 #endif
00851 
00852  again:
00853   if (recvmsg (client_fd, &msg, 0) < 0)
00854     {
00855       if (errno == EINTR)
00856         goto again;
00857 
00858       dbus_set_error (error, _dbus_error_from_errno (errno),
00859                       "Failed to read credentials byte: %s",
00860                       _dbus_strerror (errno));
00861       return FALSE;
00862     }
00863 
00864   if (buf != '\0')
00865     {
00866       dbus_set_error (error, DBUS_ERROR_FAILED,
00867                       "Credentials byte was not nul");
00868       return FALSE;
00869     }
00870 
00871 #if defined(HAVE_CMSGCRED) || defined(LOCAL_CREDS)
00872   if (cmsg.hdr.cmsg_len < sizeof (cmsg) || cmsg.hdr.cmsg_type != SCM_CREDS)
00873     {
00874       dbus_set_error (error, DBUS_ERROR_FAILED,
00875                       "Message from recvmsg() was not SCM_CREDS");
00876       return FALSE;
00877     }
00878 #endif
00879 
00880   _dbus_verbose ("read credentials byte\n");
00881 
00882   {
00883 #ifdef SO_PEERCRED
00884     struct ucred cr;   
00885     int cr_len = sizeof (cr);
00886    
00887     if (getsockopt (client_fd, SOL_SOCKET, SO_PEERCRED, &cr, &cr_len) == 0 &&
00888         cr_len == sizeof (cr))
00889       {
00890         credentials->pid = cr.pid;
00891         credentials->uid = cr.uid;
00892         credentials->gid = cr.gid;
00893       }
00894     else
00895       {
00896         _dbus_verbose ("Failed to getsockopt() credentials, returned len %d/%d: %s\n",
00897                        cr_len, (int) sizeof (cr), _dbus_strerror (errno));
00898       }
00899 #elif defined(HAVE_CMSGCRED)
00900     credentials->pid = cmsg.cred.cmcred_pid;
00901     credentials->uid = cmsg.cred.cmcred_euid;
00902     credentials->gid = cmsg.cred.cmcred_groups[0];
00903 #elif defined(LOCAL_CREDS)
00904     credentials->pid = DBUS_PID_UNSET;
00905     credentials->uid = cmsg.cred.sc_uid;
00906     credentials->gid = cmsg.cred.sc_gid;
00907     /* Since we have already got the credentials from this socket, we can
00908      * disable its LOCAL_CREDS flag if it was ever set. */
00909     _dbus_set_local_creds (client_fd, FALSE);
00910 #elif defined(HAVE_GETPEEREID)
00911     uid_t euid;
00912     gid_t egid;
00913     if (getpeereid (client_fd, &euid, &egid) == 0)
00914       {
00915         credentials->uid = euid;
00916         credentials->gid = egid;
00917       }
00918     else
00919       {
00920         _dbus_verbose ("Failed to getpeereid() credentials: %s\n", _dbus_strerror (errno));
00921       }
00922 #elif defined(HAVE_GETPEERUCRED)
00923     ucred_t * ucred = NULL;
00924     if (getpeerucred (client_fd, &ucred) == 0)
00925       {
00926         credentials->pid = ucred_getpid (ucred);
00927         credentials->uid = ucred_geteuid (ucred);
00928         credentials->gid = ucred_getegid (ucred);
00929       }
00930     else
00931       {
00932         _dbus_verbose ("Failed to getpeerucred() credentials: %s\n", _dbus_strerror (errno));
00933       }
00934     if (ucred != NULL)
00935       ucred_free (ucred);
00936 #else /* !SO_PEERCRED && !HAVE_CMSGCRED && !HAVE_GETPEEREID && !HAVE_GETPEERUCRED */
00937     _dbus_verbose ("Socket credentials not supported on this OS\n");
00938 #endif
00939   }
00940 
00941   _dbus_verbose ("Credentials:"
00942                  "  pid "DBUS_PID_FORMAT
00943                  "  uid "DBUS_UID_FORMAT
00944                  "  gid "DBUS_GID_FORMAT"\n",
00945                  credentials->pid,
00946                  credentials->uid,
00947                  credentials->gid);
00948     
00949   return TRUE;
00950 }
00951 
00969 dbus_bool_t
00970 _dbus_send_credentials_unix_socket  (int              server_fd,
00971                                      DBusError       *error)
00972 {
00973   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
00974   
00975   if (write_credentials_byte (server_fd, error))
00976     return TRUE;
00977   else
00978     return FALSE;
00979 }
00980 
00988 int
00989 _dbus_accept  (int listen_fd)
00990 {
00991   int client_fd;
00992   struct sockaddr addr;
00993   socklen_t addrlen;
00994 
00995   addrlen = sizeof (addr);
00996   
00997  retry:
00998   client_fd = accept (listen_fd, &addr, &addrlen);
00999   
01000   if (client_fd < 0)
01001     {
01002       if (errno == EINTR)
01003         goto retry;
01004     }
01005   
01006   return client_fd;
01007 }
01008 
01017 dbus_bool_t
01018 _dbus_check_dir_is_private_to_user (DBusString *dir, DBusError *error)
01019 {
01020   const char *directory;
01021   struct stat sb;
01022         
01023   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
01024     
01025   directory = _dbus_string_get_const_data (dir);
01026         
01027   if (stat (directory, &sb) < 0)
01028     {
01029       dbus_set_error (error, _dbus_error_from_errno (errno),
01030                       "%s", _dbus_strerror (errno));
01031    
01032       return FALSE;
01033     }
01034     
01035   if ((S_IROTH & sb.st_mode) || (S_IWOTH & sb.st_mode) ||
01036       (S_IRGRP & sb.st_mode) || (S_IWGRP & sb.st_mode))
01037     {
01038       dbus_set_error (error, DBUS_ERROR_FAILED,
01039                      "%s directory is not private to the user", directory);
01040       return FALSE;
01041     }
01042     
01043   return TRUE;
01044 }
01045 
01046 static dbus_bool_t
01047 fill_user_info_from_passwd (struct passwd *p,
01048                             DBusUserInfo  *info,
01049                             DBusError     *error)
01050 {
01051   _dbus_assert (p->pw_name != NULL);
01052   _dbus_assert (p->pw_dir != NULL);
01053   
01054   info->uid = p->pw_uid;
01055   info->primary_gid = p->pw_gid;
01056   info->username = _dbus_strdup (p->pw_name);
01057   info->homedir = _dbus_strdup (p->pw_dir);
01058   
01059   if (info->username == NULL ||
01060       info->homedir == NULL)
01061     {
01062       dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
01063       return FALSE;
01064     }
01065 
01066   return TRUE;
01067 }
01068 
01069 static dbus_bool_t
01070 fill_user_info (DBusUserInfo       *info,
01071                 dbus_uid_t          uid,
01072                 const DBusString   *username,
01073                 DBusError          *error)
01074 {
01075   const char *username_c;
01076   
01077   /* exactly one of username/uid provided */
01078   _dbus_assert (username != NULL || uid != DBUS_UID_UNSET);
01079   _dbus_assert (username == NULL || uid == DBUS_UID_UNSET);
01080 
01081   info->uid = DBUS_UID_UNSET;
01082   info->primary_gid = DBUS_GID_UNSET;
01083   info->group_ids = NULL;
01084   info->n_group_ids = 0;
01085   info->username = NULL;
01086   info->homedir = NULL;
01087   
01088   if (username != NULL)
01089     username_c = _dbus_string_get_const_data (username);
01090   else
01091     username_c = NULL;
01092 
01093   /* For now assuming that the getpwnam() and getpwuid() flavors
01094    * are always symmetrical, if not we have to add more configure
01095    * checks
01096    */
01097   
01098 #if defined (HAVE_POSIX_GETPWNAM_R) || defined (HAVE_NONPOSIX_GETPWNAM_R)
01099   {
01100     struct passwd *p;
01101     int result;
01102     char buf[1024];
01103     struct passwd p_str;
01104 
01105     p = NULL;
01106 #ifdef HAVE_POSIX_GETPWNAM_R
01107     if (uid != DBUS_UID_UNSET)
01108       result = getpwuid_r (uid, &p_str, buf, sizeof (buf),
01109                            &p);
01110     else
01111       result = getpwnam_r (username_c, &p_str, buf, sizeof (buf),
01112                            &p);
01113 #else
01114     if (uid != DBUS_UID_UNSET)
01115       p = getpwuid_r (uid, &p_str, buf, sizeof (buf));
01116     else
01117       p = getpwnam_r (username_c, &p_str, buf, sizeof (buf));
01118     result = 0;
01119 #endif /* !HAVE_POSIX_GETPWNAM_R */
01120     if (result == 0 && p == &p_str)
01121       {
01122         if (!fill_user_info_from_passwd (p, info, error))
01123           return FALSE;
01124       }
01125     else
01126       {
01127         dbus_set_error (error, _dbus_error_from_errno (errno),
01128                         "User \"%s\" unknown or no memory to allocate password entry\n",
01129                         username_c ? username_c : "???");
01130         _dbus_verbose ("User %s unknown\n", username_c ? username_c : "???");
01131         return FALSE;
01132       }
01133   }
01134 #else /* ! HAVE_GETPWNAM_R */
01135   {
01136     /* I guess we're screwed on thread safety here */
01137     struct passwd *p;
01138 
01139     if (uid != DBUS_UID_UNSET)
01140       p = getpwuid (uid);
01141     else
01142       p = getpwnam (username_c);
01143 
01144     if (p != NULL)
01145       {
01146         if (!fill_user_info_from_passwd (p, info, error))
01147           return FALSE;
01148       }
01149     else
01150       {
01151         dbus_set_error (error, _dbus_error_from_errno (errno),
01152                         "User \"%s\" unknown or no memory to allocate password entry\n",
01153                         username_c ? username_c : "???");
01154         _dbus_verbose ("User %s unknown\n", username_c ? username_c : "???");
01155         return FALSE;
01156       }
01157   }
01158 #endif  /* ! HAVE_GETPWNAM_R */
01159 
01160   /* Fill this in so we can use it to get groups */
01161   username_c = info->username;
01162   
01163 #ifdef HAVE_GETGROUPLIST
01164   {
01165     gid_t *buf;
01166     int buf_count;
01167     int i;
01168     
01169     buf_count = 17;
01170     buf = dbus_new (gid_t, buf_count);
01171     if (buf == NULL)
01172       {
01173         dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
01174         goto failed;
01175       }
01176     
01177     if (getgrouplist (username_c,
01178                       info->primary_gid,
01179                       buf, &buf_count) < 0)
01180       {
01181         gid_t *new = dbus_realloc (buf, buf_count * sizeof (buf[0]));
01182         if (new == NULL)
01183           {
01184             dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
01185             dbus_free (buf);
01186             goto failed;
01187           }
01188         
01189         buf = new;
01190 
01191         errno = 0;
01192         if (getgrouplist (username_c, info->primary_gid, buf, &buf_count) < 0)
01193           {
01194             dbus_set_error (error,
01195                             _dbus_error_from_errno (errno),
01196                             "Failed to get groups for username \"%s\" primary GID "
01197                             DBUS_GID_FORMAT ": %s\n",
01198                             username_c, info->primary_gid,
01199                             _dbus_strerror (errno));
01200             dbus_free (buf);
01201             goto failed;
01202           }
01203       }
01204 
01205     info->group_ids = dbus_new (dbus_gid_t, buf_count);
01206     if (info->group_ids == NULL)
01207       {
01208         dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
01209         dbus_free (buf);
01210         goto failed;
01211       }
01212     
01213     for (i = 0; i < buf_count; ++i)
01214       info->group_ids[i] = buf[i];
01215 
01216     info->n_group_ids = buf_count;
01217     
01218     dbus_free (buf);
01219   }
01220 #else  /* HAVE_GETGROUPLIST */
01221   {
01222     /* We just get the one group ID */
01223     info->group_ids = dbus_new (dbus_gid_t, 1);
01224     if (info->group_ids == NULL)
01225       {
01226         dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
01227         goto failed;
01228       }
01229 
01230     info->n_group_ids = 1;
01231 
01232     (info->group_ids)[0] = info->primary_gid;
01233   }
01234 #endif /* HAVE_GETGROUPLIST */
01235 
01236   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
01237   
01238   return TRUE;
01239   
01240  failed:
01241   _DBUS_ASSERT_ERROR_IS_SET (error);
01242   return FALSE;
01243 }
01244 
01253 dbus_bool_t
01254 _dbus_user_info_fill (DBusUserInfo     *info,
01255                       const DBusString *username,
01256                       DBusError        *error)
01257 {
01258   return fill_user_info (info, DBUS_UID_UNSET,
01259                          username, error);
01260 }
01261 
01270 dbus_bool_t
01271 _dbus_user_info_fill_uid (DBusUserInfo *info,
01272                           dbus_uid_t    uid,
01273                           DBusError    *error)
01274 {
01275   return fill_user_info (info, uid,
01276                          NULL, error);
01277 }
01278 
01284 void
01285 _dbus_credentials_from_current_process (DBusCredentials *credentials)
01286 {
01287   /* The POSIX spec certainly doesn't promise this, but
01288    * we need these assertions to fail as soon as we're wrong about
01289    * it so we can do the porting fixups
01290    */
01291   _dbus_assert (sizeof (pid_t) <= sizeof (credentials->pid));
01292   _dbus_assert (sizeof (uid_t) <= sizeof (credentials->uid));
01293   _dbus_assert (sizeof (gid_t) <= sizeof (credentials->gid));
01294   
01295   credentials->pid = getpid ();
01296   credentials->uid = getuid ();
01297   credentials->gid = getgid ();
01298 }
01299 
01304 unsigned long
01305 _dbus_getpid (void)
01306 {
01307   return getpid ();
01308 }
01309 
01313 dbus_uid_t
01314 _dbus_getuid (void)
01315 {
01316   return getuid ();
01317 }
01318 
01319 #ifdef DBUS_BUILD_TESTS
01320 
01323 dbus_gid_t
01324 _dbus_getgid (void)
01325 {
01326   return getgid ();
01327 }
01328 #endif
01329 
01338 int
01339 _dbus_poll (DBusPollFD *fds,
01340             int         n_fds,
01341             int         timeout_milliseconds)
01342 {
01343 #ifdef HAVE_POLL
01344   /* This big thing is a constant expression and should get optimized
01345    * out of existence. So it's more robust than a configure check at
01346    * no cost.
01347    */
01348   if (_DBUS_POLLIN == POLLIN &&
01349       _DBUS_POLLPRI == POLLPRI &&
01350       _DBUS_POLLOUT == POLLOUT &&
01351       _DBUS_POLLERR == POLLERR &&
01352       _DBUS_POLLHUP == POLLHUP &&
01353       _DBUS_POLLNVAL == POLLNVAL &&
01354       sizeof (DBusPollFD) == sizeof (struct pollfd) &&
01355       _DBUS_STRUCT_OFFSET (DBusPollFD, fd) ==
01356       _DBUS_STRUCT_OFFSET (struct pollfd, fd) &&
01357       _DBUS_STRUCT_OFFSET (DBusPollFD, events) ==
01358       _DBUS_STRUCT_OFFSET (struct pollfd, events) &&
01359       _DBUS_STRUCT_OFFSET (DBusPollFD, revents) ==
01360       _DBUS_STRUCT_OFFSET (struct pollfd, revents))
01361     {
01362       return poll ((struct pollfd*) fds,
01363                    n_fds, 
01364                    timeout_milliseconds);
01365     }
01366   else
01367     {
01368       /* We have to convert the DBusPollFD to an array of
01369        * struct pollfd, poll, and convert back.
01370        */
01371       _dbus_warn ("didn't implement poll() properly for this system yet\n");
01372       return -1;
01373     }
01374 #else /* ! HAVE_POLL */
01375 
01376   fd_set read_set, write_set, err_set;
01377   int max_fd = 0;
01378   int i;
01379   struct timeval tv;
01380   int ready;
01381   
01382   FD_ZERO (&read_set);
01383   FD_ZERO (&write_set);
01384   FD_ZERO (&err_set);
01385 
01386   for (i = 0; i < n_fds; i++)
01387     {
01388       DBusPollFD *fdp = &fds[i];
01389 
01390       if (fdp->events & _DBUS_POLLIN)
01391         FD_SET (fdp->fd, &read_set);
01392 
01393       if (fdp->events & _DBUS_POLLOUT)
01394         FD_SET (fdp->fd, &write_set);
01395 
01396       FD_SET (fdp->fd, &err_set);
01397 
01398       max_fd = MAX (max_fd, fdp->fd);
01399     }
01400     
01401   tv.tv_sec = timeout_milliseconds / 1000;
01402   tv.tv_usec = (timeout_milliseconds % 1000) * 1000;
01403 
01404   ready = select (max_fd + 1, &read_set, &write_set, &err_set,
01405                   timeout_milliseconds < 0 ? NULL : &tv);
01406 
01407   if (ready > 0)
01408     {
01409       for (i = 0; i < n_fds; i++)
01410         {
01411           DBusPollFD *fdp = &fds[i];
01412 
01413           fdp->revents = 0;
01414 
01415           if (FD_ISSET (fdp->fd, &read_set))
01416             fdp->revents |= _DBUS_POLLIN;
01417 
01418           if (FD_ISSET (fdp->fd, &write_set))
01419             fdp->revents |= _DBUS_POLLOUT;
01420 
01421           if (FD_ISSET (fdp->fd, &err_set))
01422             fdp->revents |= _DBUS_POLLERR;
01423         }
01424     }
01425 
01426   return ready;
01427 #endif
01428 }
01429 
01436 void
01437 _dbus_get_current_time (long *tv_sec,
01438                         long *tv_usec)
01439 {
01440   struct timeval t;
01441 
01442   gettimeofday (&t, NULL);
01443 
01444   if (tv_sec)
01445     *tv_sec = t.tv_sec;
01446   if (tv_usec)
01447     *tv_usec = t.tv_usec;
01448 }
01449 
01460 dbus_bool_t
01461 _dbus_file_get_contents (DBusString       *str,
01462                          const DBusString *filename,
01463                          DBusError        *error)
01464 {
01465   int fd;
01466   struct stat sb;
01467   int orig_len;
01468   int total;
01469   const char *filename_c;
01470 
01471   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
01472   
01473   filename_c = _dbus_string_get_const_data (filename);
01474   
01475   /* O_BINARY useful on Cygwin */
01476   fd = open (filename_c, O_RDONLY | O_BINARY);
01477   if (fd < 0)
01478     {
01479       dbus_set_error (error, _dbus_error_from_errno (errno),
01480                       "Failed to open \"%s\": %s",
01481                       filename_c,
01482                       _dbus_strerror (errno));
01483       return FALSE;
01484     }
01485 
01486   if (fstat (fd, &sb) < 0)
01487     {
01488       dbus_set_error (error, _dbus_error_from_errno (errno),
01489                       "Failed to stat \"%s\": %s",
01490                       filename_c,
01491                       _dbus_strerror (errno));
01492 
01493       _dbus_verbose ("fstat() failed: %s",
01494                      _dbus_strerror (errno));
01495       
01496       _dbus_close (fd, NULL);
01497       
01498       return FALSE;
01499     }
01500 
01501   if (sb.st_size > _DBUS_ONE_MEGABYTE)
01502     {
01503       dbus_set_error (error, DBUS_ERROR_FAILED,
01504                       "File size %lu of \"%s\" is too large.",
01505                       (unsigned long) sb.st_size, filename_c);
01506       _dbus_close (fd, NULL);
01507       return FALSE;
01508     }
01509   
01510   total = 0;
01511   orig_len = _dbus_string_get_length (str);
01512   if (sb.st_size > 0 && S_ISREG (sb.st_mode))
01513     {
01514       int bytes_read;
01515 
01516       while (total < (int) sb.st_size)
01517         {
01518           bytes_read = _dbus_read (fd, str,
01519                                    sb.st_size - total);
01520           if (bytes_read <= 0)
01521             {
01522               dbus_set_error (error, _dbus_error_from_errno (errno),
01523                               "Error reading \"%s\": %s",
01524                               filename_c,
01525                               _dbus_strerror (errno));
01526 
01527               _dbus_verbose ("read() failed: %s",
01528                              _dbus_strerror (errno));
01529               
01530               _dbus_close (fd, NULL);
01531               _dbus_string_set_length (str, orig_len);
01532               return FALSE;
01533             }
01534           else
01535             total += bytes_read;
01536         }
01537 
01538       _dbus_close (fd, NULL);
01539       return TRUE;
01540     }
01541   else if (sb.st_size != 0)
01542     {
01543       _dbus_verbose ("Can only open regular files at the moment.\n");
01544       dbus_set_error (error, DBUS_ERROR_FAILED,
01545                       "\"%s\" is not a regular file",
01546                       filename_c);
01547       _dbus_close (fd, NULL);
01548       return FALSE;
01549     }
01550   else
01551     {
01552       _dbus_close (fd, NULL);
01553       return TRUE;
01554     }
01555 }
01556 
01566 dbus_bool_t
01567 _dbus_string_save_to_file (const DBusString *str,
01568                            const DBusString *filename,
01569                            DBusError        *error)
01570 {
01571   int fd;
01572   int bytes_to_write;
01573   const char *filename_c;
01574   DBusString tmp_filename;
01575   const char *tmp_filename_c;
01576   int total;
01577   dbus_bool_t need_unlink;
01578   dbus_bool_t retval;
01579 
01580   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
01581   
01582   fd = -1;
01583   retval = FALSE;
01584   need_unlink = FALSE;
01585   
01586   if (!_dbus_string_init (&tmp_filename))
01587     {
01588       dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
01589       return FALSE;
01590     }
01591 
01592   if (!_dbus_string_copy (filename, 0, &tmp_filename, 0))
01593     {
01594       dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
01595       _dbus_string_free (&tmp_filename);
01596       return FALSE;
01597     }
01598   
01599   if (!_dbus_string_append (&tmp_filename, "."))
01600     {
01601       dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
01602       _dbus_string_free (&tmp_filename);
01603       return FALSE;
01604     }
01605 
01606 #define N_TMP_FILENAME_RANDOM_BYTES 8
01607   if (!_dbus_generate_random_ascii (&tmp_filename, N_TMP_FILENAME_RANDOM_BYTES))
01608     {
01609       dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
01610       _dbus_string_free (&tmp_filename);
01611       return FALSE;
01612     }
01613     
01614   filename_c = _dbus_string_get_const_data (filename);
01615   tmp_filename_c = _dbus_string_get_const_data (&tmp_filename);
01616 
01617   fd = open (tmp_filename_c, O_WRONLY | O_BINARY | O_EXCL | O_CREAT,
01618              0600);
01619   if (fd < 0)
01620     {
01621       dbus_set_error (error, _dbus_error_from_errno (errno),
01622                       "Could not create %s: %s", tmp_filename_c,
01623                       _dbus_strerror (errno));
01624       goto out;
01625     }
01626 
01627   need_unlink = TRUE;
01628   
01629   total = 0;
01630   bytes_to_write = _dbus_string_get_length (str);
01631 
01632   while (total < bytes_to_write)
01633     {
01634       int bytes_written;
01635 
01636       bytes_written = _dbus_write (fd, str, total,
01637                                    bytes_to_write - total);
01638 
01639       if (bytes_written <= 0)
01640         {
01641           dbus_set_error (error, _dbus_error_from_errno (errno),
01642                           "Could not write to %s: %s", tmp_filename_c,
01643                           _dbus_strerror (errno));
01644           
01645           goto out;
01646         }
01647 
01648       total += bytes_written;
01649     }
01650 
01651   if (!_dbus_close (fd, NULL))
01652     {
01653       dbus_set_error (error, _dbus_error_from_errno (errno),
01654                       "Could not close file %s: %s",
01655                       tmp_filename_c, _dbus_strerror (errno));
01656 
01657       goto out;
01658     }
01659 
01660   fd = -1;
01661   
01662   if (rename (tmp_filename_c, filename_c) < 0)
01663     {
01664       dbus_set_error (error, _dbus_error_from_errno (errno),
01665                       "Could not rename %s to %s: %s",
01666                       tmp_filename_c, filename_c,
01667                       _dbus_strerror (errno));
01668 
01669       goto out;
01670     }
01671 
01672   need_unlink = FALSE;
01673   
01674   retval = TRUE;
01675   
01676  out:
01677   /* close first, then unlink, to prevent ".nfs34234235" garbage
01678    * files
01679    */
01680 
01681   if (fd >= 0)
01682     _dbus_close (fd, NULL);
01683         
01684   if (need_unlink && unlink (tmp_filename_c) < 0)
01685     _dbus_verbose ("Failed to unlink temp file %s: %s\n",
01686                    tmp_filename_c, _dbus_strerror (errno));
01687 
01688   _dbus_string_free (&tmp_filename);
01689 
01690   if (!retval)
01691     _DBUS_ASSERT_ERROR_IS_SET (error);
01692   
01693   return retval;
01694 }
01695 
01702 dbus_bool_t
01703 _dbus_create_file_exclusively (const DBusString *filename,
01704                                DBusError        *error)
01705 {
01706   int fd;
01707   const char *filename_c;
01708 
01709   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
01710   
01711   filename_c = _dbus_string_get_const_data (filename);
01712   
01713   fd = open (filename_c, O_WRONLY | O_BINARY | O_EXCL | O_CREAT,
01714              0600);
01715   if (fd < 0)
01716     {
01717       dbus_set_error (error,
01718                       DBUS_ERROR_FAILED,
01719                       "Could not create file %s: %s\n",
01720                       filename_c,
01721                       _dbus_strerror (errno));
01722       return FALSE;
01723     }
01724 
01725   if (!_dbus_close (fd, NULL))
01726     {
01727       dbus_set_error (error,
01728                       DBUS_ERROR_FAILED,
01729                       "Could not close file %s: %s\n",
01730                       filename_c,
01731                       _dbus_strerror (errno));
01732       return FALSE;
01733     }
01734   
01735   return TRUE;
01736 }
01737 
01746 dbus_bool_t
01747 _dbus_delete_file (const DBusString *filename,
01748                    DBusError        *error)
01749 {
01750   const char *filename_c;
01751 
01752   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
01753   
01754   filename_c = _dbus_string_get_const_data (filename);
01755 
01756   if (unlink (filename_c) < 0)
01757     {
01758       dbus_set_error (error, DBUS_ERROR_FAILED,
01759                       "Failed to delete file %s: %s\n",
01760                       filename_c, _dbus_strerror (errno));
01761       return FALSE;
01762     }
01763   else
01764     return TRUE;
01765 }
01766 
01775 dbus_bool_t
01776 _dbus_create_directory (const DBusString *filename,
01777                         DBusError        *error)
01778 {
01779   const char *filename_c;
01780 
01781   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
01782   
01783   filename_c = _dbus_string_get_const_data (filename);
01784 
01785   if (mkdir (filename_c, 0700) < 0)
01786     {
01787       if (errno == EEXIST)
01788         return TRUE;
01789       
01790       dbus_set_error (error, DBUS_ERROR_FAILED,
01791                       "Failed to create directory %s: %s\n",
01792                       filename_c, _dbus_strerror (errno));
01793       return FALSE;
01794     }
01795   else
01796     return TRUE;
01797 }
01798 
01809 dbus_bool_t
01810 _dbus_concat_dir_and_file (DBusString       *dir,
01811                            const DBusString *next_component)
01812 {
01813   dbus_bool_t dir_ends_in_slash;
01814   dbus_bool_t file_starts_with_slash;
01815 
01816   if (_dbus_string_get_length (dir) == 0 ||
01817       _dbus_string_get_length (next_component) == 0)
01818     return TRUE;
01819   
01820   dir_ends_in_slash = '/' == _dbus_string_get_byte (dir,
01821                                                     _dbus_string_get_length (dir) - 1);
01822 
01823   file_starts_with_slash = '/' == _dbus_string_get_byte (next_component, 0);
01824 
01825   if (dir_ends_in_slash && file_starts_with_slash)
01826     {
01827       _dbus_string_shorten (dir, 1);
01828     }
01829   else if (!(dir_ends_in_slash || file_starts_with_slash))
01830     {
01831       if (!_dbus_string_append_byte (dir, '/'))
01832         return FALSE;
01833     }
01834 
01835   return _dbus_string_copy (next_component, 0, dir,
01836                             _dbus_string_get_length (dir));
01837 }
01838 
01840 #define NANOSECONDS_PER_SECOND       1000000000
01841 
01842 #define MICROSECONDS_PER_SECOND      1000000
01843 
01844 #define MILLISECONDS_PER_SECOND      1000
01845 
01846 #define NANOSECONDS_PER_MILLISECOND  1000000
01847 
01848 #define MICROSECONDS_PER_MILLISECOND 1000
01849 
01854 void
01855 _dbus_sleep_milliseconds (int milliseconds)
01856 {
01857 #ifdef HAVE_NANOSLEEP
01858   struct timespec req;
01859   struct timespec rem;
01860 
01861   req.tv_sec = milliseconds / MILLISECONDS_PER_SECOND;
01862   req.tv_nsec = (milliseconds % MILLISECONDS_PER_SECOND) * NANOSECONDS_PER_MILLISECOND;
01863   rem.tv_sec = 0;
01864   rem.tv_nsec = 0;
01865 
01866   while (nanosleep (&req, &rem) < 0 && errno == EINTR)
01867     req = rem;
01868 #elif defined (HAVE_USLEEP)
01869   usleep (milliseconds * MICROSECONDS_PER_MILLISECOND);
01870 #else /* ! HAVE_USLEEP */
01871   sleep (MAX (milliseconds / 1000, 1));
01872 #endif
01873 }
01874 
01875 static dbus_bool_t
01876 _dbus_generate_pseudorandom_bytes (DBusString *str,
01877                                    int         n_bytes)
01878 {
01879   int old_len;
01880   char *p;
01881   
01882   old_len = _dbus_string_get_length (str);
01883 
01884   if (!_dbus_string_lengthen (str, n_bytes))
01885     return FALSE;
01886 
01887   p = _dbus_string_get_data_len (str, old_len, n_bytes);
01888 
01889   _dbus_generate_pseudorandom_bytes_buffer (p, n_bytes);
01890 
01891   return TRUE;
01892 }
01893 
01902 dbus_bool_t
01903 _dbus_generate_random_bytes (DBusString *str,
01904                              int         n_bytes)
01905 {
01906   int old_len;
01907   int fd;
01908 
01909   /* FALSE return means "no memory", if it could
01910    * mean something else then we'd need to return
01911    * a DBusError. So we always fall back to pseudorandom
01912    * if the I/O fails.
01913    */
01914   
01915   old_len = _dbus_string_get_length (str);
01916   fd = -1;
01917 
01918   /* note, urandom on linux will fall back to pseudorandom */
01919   fd = open ("/dev/urandom", O_RDONLY);
01920   if (fd < 0)
01921     return _dbus_generate_pseudorandom_bytes (str, n_bytes);
01922 
01923   if (_dbus_read (fd, str, n_bytes) != n_bytes)
01924     {
01925       _dbus_close (fd, NULL);
01926       _dbus_string_set_length (str, old_len);
01927       return _dbus_generate_pseudorandom_bytes (str, n_bytes);
01928     }
01929 
01930   _dbus_verbose ("Read %d bytes from /dev/urandom\n",
01931                  n_bytes);
01932   
01933   _dbus_close (fd, NULL);
01934   
01935   return TRUE;
01936 }
01937 
01943 void
01944 _dbus_exit (int code)
01945 {
01946   _exit (code);
01947 }
01948 
01956 const char*
01957 _dbus_strerror (int error_number)
01958 {
01959   const char *msg;
01960   
01961   msg = strerror (error_number);
01962   if (msg == NULL)
01963     msg = "unknown";
01964 
01965   return msg;
01966 }
01967 
01971 void
01972 _dbus_disable_sigpipe (void)
01973 {
01974   signal (SIGPIPE, SIG_IGN);
01975 }
01976 
01984 void
01985 _dbus_fd_set_close_on_exec (int fd)
01986 {
01987   int val;
01988   
01989   val = fcntl (fd, F_GETFD, 0);
01990   
01991   if (val < 0)
01992     return;
01993 
01994   val |= FD_CLOEXEC;
01995   
01996   fcntl (fd, F_SETFD, val);
01997 }
01998 
02006 dbus_bool_t
02007 _dbus_close (int        fd,
02008              DBusError *error)
02009 {
02010   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
02011   
02012  again:
02013   if (close (fd) < 0)
02014     {
02015       if (errno == EINTR)
02016         goto again;
02017 
02018       dbus_set_error (error, _dbus_error_from_errno (errno),
02019                       "Could not close fd %d", fd);
02020       return FALSE;
02021     }
02022 
02023   return TRUE;
02024 }
02025 
02033 dbus_bool_t
02034 _dbus_set_fd_nonblocking (int             fd,
02035                           DBusError      *error)
02036 {
02037   int val;
02038 
02039   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
02040   
02041   val = fcntl (fd, F_GETFL, 0);
02042   if (val < 0)
02043     {
02044       dbus_set_error (error, _dbus_error_from_errno (errno),
02045                       "Failed to get flags from file descriptor %d: %s",
02046                       fd, _dbus_strerror (errno));
02047       _dbus_verbose ("Failed to get flags for fd %d: %s\n", fd,
02048                      _dbus_strerror (errno));
02049       return FALSE;
02050     }
02051 
02052   if (fcntl (fd, F_SETFL, val | O_NONBLOCK) < 0)
02053     {
02054       dbus_set_error (error, _dbus_error_from_errno (errno),
02055                       "Failed to set nonblocking flag of file descriptor %d: %s",
02056                       fd, _dbus_strerror (errno));
02057       _dbus_verbose ("Failed to set fd %d nonblocking: %s\n",
02058                      fd, _dbus_strerror (errno));
02059 
02060       return FALSE;
02061     }
02062 
02063   return TRUE;
02064 }
02065 
02066 #if !defined (DBUS_DISABLE_ASSERT) || defined(DBUS_BUILD_TESTS)
02067 
02072 void
02073 _dbus_print_backtrace (void)
02074 {
02075 #if defined (HAVE_BACKTRACE) && defined (DBUS_ENABLE_VERBOSE_MODE)
02076   void *bt[500];
02077   int bt_size;
02078   int i;
02079   char **syms;
02080   
02081   bt_size = backtrace (bt, 500);
02082 
02083   syms = backtrace_symbols (bt, bt_size);
02084   
02085   i = 0;
02086   while (i < bt_size)
02087     {
02088       _dbus_verbose ("  %s\n", syms[i]);
02089       ++i;
02090     }
02091 
02092   free (syms);
02093 #else
02094   _dbus_verbose ("  D-Bus not compiled with backtrace support\n");
02095 #endif
02096 }
02097 #endif /* asserts or tests enabled */
02098 
02114 dbus_bool_t
02115 _dbus_full_duplex_pipe (int        *fd1,
02116                         int        *fd2,
02117                         dbus_bool_t blocking,
02118                         DBusError  *error)
02119 {
02120 #ifdef HAVE_SOCKETPAIR
02121   int fds[2];
02122 
02123   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
02124   
02125   if (socketpair (AF_UNIX, SOCK_STREAM, 0, fds) < 0)
02126     {
02127       dbus_set_error (error, _dbus_error_from_errno (errno),
02128                       "Could not create full-duplex pipe");
02129       return FALSE;
02130     }
02131 
02132   if (!blocking &&
02133       (!_dbus_set_fd_nonblocking (fds[0], NULL) ||
02134        !_dbus_set_fd_nonblocking (fds[1], NULL)))
02135     {
02136       dbus_set_error (error, _dbus_error_from_errno (errno),
02137                       "Could not set full-duplex pipe nonblocking");
02138       
02139       _dbus_close (fds[0], NULL);
02140       _dbus_close (fds[1], NULL);
02141       
02142       return FALSE;
02143     }
02144   
02145   *fd1 = fds[0];
02146   *fd2 = fds[1];
02147 
02148   _dbus_verbose ("full-duplex pipe %d <-> %d\n",
02149                  *fd1, *fd2);
02150   
02151   return TRUE;  
02152 #else
02153   _dbus_warn ("_dbus_full_duplex_pipe() not implemented on this OS\n");
02154   dbus_set_error (error, DBUS_ERROR_FAILED,
02155                   "_dbus_full_duplex_pipe() not implemented on this OS");
02156   return FALSE;
02157 #endif
02158 }
02159 
02160 
02169 int
02170 _dbus_printf_string_upper_bound (const char *format,
02171                                  va_list     args)
02172 {
02173   char c;
02174   return vsnprintf (&c, 1, format, args);
02175 }
02176 
02183 const char*
02184 _dbus_get_tmpdir(void)
02185 {
02186   static const char* tmpdir = NULL;
02187 
02188   if (tmpdir == NULL)
02189     {
02190       /* TMPDIR is what glibc uses, then
02191        * glibc falls back to the P_tmpdir macro which
02192        * just expands to "/tmp"
02193        */
02194       if (tmpdir == NULL)
02195         tmpdir = getenv("TMPDIR");
02196 
02197       /* These two env variables are probably
02198        * broken, but maybe some OS uses them?
02199        */
02200       if (tmpdir == NULL)
02201         tmpdir = getenv("TMP");
02202       if (tmpdir == NULL)
02203         tmpdir = getenv("TEMP");
02204 
02205       /* And this is the sane fallback. */
02206       if (tmpdir == NULL)
02207         tmpdir = "/tmp";
02208     }
02209   
02210   _dbus_assert(tmpdir != NULL);
02211   
02212   return tmpdir;
02213 }
02214 
02217 /* tests in dbus-sysdeps-util.c */

Generated on Wed Jan 3 04:58:29 2007 for D-Bus by  doxygen 1.4.7