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