D-Bus  1.12.20
dbus-file-unix.c
1 /* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
2 /* dbus-file-unix.c unix related file implementation (internal to D-Bus implementation)
3  *
4  * Copyright (C) 2002, 2003, 2006 Red Hat, Inc.
5  * Copyright (C) 2003 CodeFactory AB
6  *
7  * Licensed under the Academic Free License version 2.1
8  *
9  * This program is free software; you can redistribute it and/or modify
10  * it under the terms of the GNU General Public License as published by
11  * the Free Software Foundation; either version 2 of the License, or
12  * (at your option) any later version.
13  *
14  * This program is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17  * GNU General Public License for more details.
18  *
19  * You should have received a copy of the GNU General Public License
20  * along with this program; if not, write to the Free Software
21  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
22  *
23  */
24 
25 #include <config.h>
26 
27 #include "dbus-protocol.h"
28 #include "dbus-errors.h"
29 #include "dbus-file.h"
30 #include "dbus-internals.h"
31 #include "dbus-sysdeps.h"
32 #include "dbus-sysdeps-unix.h"
33 
34 #include <sys/stat.h>
35 #include <stdio.h>
36 #include <fcntl.h>
37 #include <unistd.h>
38 #include <errno.h>
39 
40 #ifndef O_BINARY
41 #define O_BINARY 0
42 #endif
43 
56  const DBusString *filename,
57  DBusError *error)
58 {
59  int fd;
60  struct stat sb;
61  int orig_len;
62  int total;
63  const char *filename_c;
64 
65  _DBUS_ASSERT_ERROR_IS_CLEAR (error);
66 
67  filename_c = _dbus_string_get_const_data (filename);
68 
69  /* O_BINARY useful on Cygwin */
70  fd = open (filename_c, O_RDONLY | O_BINARY);
71  if (fd < 0)
72  {
73  dbus_set_error (error, _dbus_error_from_errno (errno),
74  "Failed to open \"%s\": %s",
75  filename_c,
76  _dbus_strerror (errno));
77  return FALSE;
78  }
79 
80  _dbus_verbose ("file fd %d opened\n", fd);
81 
82 #if defined HAVE_PDPLINUX && defined DBUS_ENABLE_VERBOSE_MODE
83  _dbus_verbose ("Read file: '%s'\n", filename_c);
84 #endif
85 
86  if (fstat (fd, &sb) < 0)
87  {
88  dbus_set_error (error, _dbus_error_from_errno (errno),
89  "Failed to stat \"%s\": %s",
90  filename_c,
91  _dbus_strerror (errno));
92 
93  _dbus_verbose ("fstat() failed: %s",
94  _dbus_strerror (errno));
95 
96  _dbus_close (fd, NULL);
97 
98  return FALSE;
99  }
100 
101  if (sb.st_size > _DBUS_ONE_MEGABYTE)
102  {
104  "File size %lu of \"%s\" is too large.",
105  (unsigned long) sb.st_size, filename_c);
106  _dbus_close (fd, NULL);
107  return FALSE;
108  }
109 
110  total = 0;
111  orig_len = _dbus_string_get_length (str);
112  if (sb.st_size > 0 && S_ISREG (sb.st_mode))
113  {
114  int bytes_read;
115 
116  while (total < (int) sb.st_size)
117  {
118  bytes_read = _dbus_read (fd, str,
119  sb.st_size - total);
120  if (bytes_read <= 0)
121  {
122  dbus_set_error (error, _dbus_error_from_errno (errno),
123  "Error reading \"%s\": %s",
124  filename_c,
125  _dbus_strerror (errno));
126 
127  _dbus_verbose ("read() failed: %s",
128  _dbus_strerror (errno));
129 
130  _dbus_close (fd, NULL);
131  _dbus_string_set_length (str, orig_len);
132  return FALSE;
133  }
134  else
135  total += bytes_read;
136  }
137 
138  _dbus_close (fd, NULL);
139  return TRUE;
140  }
141  else if (sb.st_size != 0)
142  {
143  _dbus_verbose ("Can only open regular files at the moment.\n");
145  "\"%s\" is not a regular file",
146  filename_c);
147  _dbus_close (fd, NULL);
148  return FALSE;
149  }
150  else
151  {
152  _dbus_close (fd, NULL);
153  return TRUE;
154  }
155 }
156 
169  const DBusString *filename,
170  dbus_bool_t world_readable,
171  DBusError *error)
172 {
173  int fd;
174  int bytes_to_write;
175  const char *filename_c;
176  DBusString tmp_filename;
177  const char *tmp_filename_c;
178  int total;
179  dbus_bool_t need_unlink;
180  dbus_bool_t retval;
181 
182  _DBUS_ASSERT_ERROR_IS_CLEAR (error);
183 
184  fd = -1;
185  retval = FALSE;
186  need_unlink = FALSE;
187 
188  if (!_dbus_string_init (&tmp_filename))
189  {
191  return FALSE;
192  }
193 
194  if (!_dbus_string_copy (filename, 0, &tmp_filename, 0))
195  {
197  _dbus_string_free (&tmp_filename);
198  return FALSE;
199  }
200 
201  if (!_dbus_string_append (&tmp_filename, "."))
202  {
204  _dbus_string_free (&tmp_filename);
205  return FALSE;
206  }
207 
208 #define N_TMP_FILENAME_RANDOM_BYTES 8
209  if (!_dbus_generate_random_ascii (&tmp_filename, N_TMP_FILENAME_RANDOM_BYTES,
210  error))
211  {
212  _dbus_string_free (&tmp_filename);
213  return FALSE;
214  }
215 
216  filename_c = _dbus_string_get_const_data (filename);
217  tmp_filename_c = _dbus_string_get_const_data (&tmp_filename);
218 
219  fd = open (tmp_filename_c, O_WRONLY | O_BINARY | O_EXCL | O_CREAT,
220  world_readable ? 0644 : 0600);
221  if (fd < 0)
222  {
223  dbus_set_error (error, _dbus_error_from_errno (errno),
224  "Could not create %s: %s", tmp_filename_c,
225  _dbus_strerror (errno));
226  goto out;
227  }
228  if (world_readable)
229  {
230  /* Ensure the file is world readable even in the presence of
231  * possibly restrictive umasks;
232  * see http://lists.freedesktop.org/archives/dbus/2010-September/013367.html
233  */
234  if (fchmod (fd, 0644) < 0)
235  {
236  dbus_set_error (error, _dbus_error_from_errno (errno),
237  "Could not chmod %s: %s", tmp_filename_c,
238  _dbus_strerror (errno));
239  goto out;
240  }
241  }
242 
243  _dbus_verbose ("tmp file fd %d opened\n", fd);
244 
245  need_unlink = TRUE;
246 
247  total = 0;
248  bytes_to_write = _dbus_string_get_length (str);
249 
250  while (total < bytes_to_write)
251  {
252  int bytes_written;
253 
254  bytes_written = _dbus_write (fd, str, total,
255  bytes_to_write - total);
256 
257  if (bytes_written <= 0)
258  {
259  dbus_set_error (error, _dbus_error_from_errno (errno),
260  "Could not write to %s: %s", tmp_filename_c,
261  _dbus_strerror (errno));
262 
263  goto out;
264  }
265 
266  total += bytes_written;
267  }
268 
269  if (fsync(fd))
270  {
271  dbus_set_error (error, _dbus_error_from_errno (errno),
272  "Could not synchronize file %s: %s",
273  tmp_filename_c, _dbus_strerror (errno));
274 
275  goto out;
276  }
277 
278  if (!_dbus_close (fd, NULL))
279  {
280  dbus_set_error (error, _dbus_error_from_errno (errno),
281  "Could not close file %s: %s",
282  tmp_filename_c, _dbus_strerror (errno));
283 
284  goto out;
285  }
286 
287  fd = -1;
288 
289  if (rename (tmp_filename_c, filename_c) < 0)
290  {
291  dbus_set_error (error, _dbus_error_from_errno (errno),
292  "Could not rename %s to %s: %s",
293  tmp_filename_c, filename_c,
294  _dbus_strerror (errno));
295 
296  goto out;
297  }
298 
299  need_unlink = FALSE;
300 
301  retval = TRUE;
302 
303  out:
304  /* close first, then unlink, to prevent ".nfs34234235" garbage
305  * files
306  */
307 
308  if (fd >= 0)
309  _dbus_close (fd, NULL);
310 
311  if (need_unlink && unlink (tmp_filename_c) < 0)
312  _dbus_verbose ("Failed to unlink temp file %s: %s\n",
313  tmp_filename_c, _dbus_strerror (errno));
314 
315  _dbus_string_free (&tmp_filename);
316 
317  if (!retval)
318  _DBUS_ASSERT_ERROR_IS_SET (error);
319 
320  return retval;
321 }
322 
331  DBusError *error)
332 {
333  const char *filename_c;
334 
335  _DBUS_ASSERT_ERROR_IS_CLEAR (error);
336 
337  filename_c = _dbus_string_get_const_data (filename);
338  if (chmod (filename_c, 0644) == -1)
339  {
340  dbus_set_error (error,
342  "Could not change permissions of file %s: %s\n",
343  filename_c,
344  _dbus_strerror (errno));
345  return FALSE;
346  }
347  return TRUE;
348 }
349 
358  DBusError *error)
359 {
360  int fd;
361  const char *filename_c;
362 
363  _DBUS_ASSERT_ERROR_IS_CLEAR (error);
364 
365  filename_c = _dbus_string_get_const_data (filename);
366 
367  fd = open (filename_c, O_WRONLY | O_BINARY | O_EXCL | O_CREAT,
368  0600);
369  if (fd < 0)
370  {
371  dbus_set_error (error,
373  "Could not create file %s: %s\n",
374  filename_c,
375  _dbus_strerror (errno));
376  return FALSE;
377  }
378 
379  _dbus_verbose ("exclusive file fd %d opened\n", fd);
380 
381  if (!_dbus_close (fd, NULL))
382  {
383  dbus_set_error (error,
385  "Could not close file %s: %s\n",
386  filename_c,
387  _dbus_strerror (errno));
388  return FALSE;
389  }
390 
391  return TRUE;
392 }
393 
403 _dbus_delete_file (const DBusString *filename,
404  DBusError *error)
405 {
406  const char *filename_c;
407 
408  _DBUS_ASSERT_ERROR_IS_CLEAR (error);
409 
410  filename_c = _dbus_string_get_const_data (filename);
411 
412  if (unlink (filename_c) < 0)
413  {
415  "Failed to delete file %s: %s\n",
416  filename_c, _dbus_strerror (errno));
417  return FALSE;
418  }
419  else
420  return TRUE;
421 }
_dbus_string_free
void _dbus_string_free(DBusString *str)
Frees a string created by _dbus_string_init().
Definition: dbus-string.c:259
_dbus_create_file_exclusively
dbus_bool_t _dbus_create_file_exclusively(const DBusString *filename, DBusError *error)
Creates the given file, failing if the file already exists.
Definition: dbus-file-unix.c:357
_dbus_string_save_to_file
dbus_bool_t _dbus_string_save_to_file(const DBusString *str, const DBusString *filename, dbus_bool_t world_readable, DBusError *error)
Writes a string out to a file.
Definition: dbus-file-unix.c:168
_dbus_error_from_errno
const char * _dbus_error_from_errno(int error_number)
Converts a UNIX errno, or Windows errno or WinSock error value into a DBusError name.
Definition: dbus-sysdeps.c:592
_dbus_write
int _dbus_write(int fd, const DBusString *buffer, int start, int len)
Thin wrapper around the write() system call that writes a part of a DBusString and handles EINTR for ...
Definition: dbus-sysdeps-unix.c:795
_dbus_string_copy
dbus_bool_t _dbus_string_copy(const DBusString *source, int start, DBusString *dest, int insert_at)
Like _dbus_string_move(), but does not delete the section of the source string that's copied to the d...
Definition: dbus-string.c:1283
_dbus_file_get_contents
dbus_bool_t _dbus_file_get_contents(DBusString *str, const DBusString *filename, DBusError *error)
Appends the contents of the given file to the string, returning error code.
Definition: dbus-file-unix.c:55
_dbus_string_init
dbus_bool_t _dbus_string_init(DBusString *str)
Initializes a string.
Definition: dbus-string.c:175
TRUE
#define TRUE
Expands to "1".
DBUS_ERROR_FAILED
#define DBUS_ERROR_FAILED
A generic error; "something went wrong" - see the error message for more.
Definition: dbus-protocol.h:368
_dbus_delete_file
dbus_bool_t _dbus_delete_file(const DBusString *filename, DBusError *error)
Deletes the given file.
Definition: dbus-file-unix.c:403
_dbus_read
int _dbus_read(int fd, DBusString *buffer, int count)
Thin wrapper around the read() system call that appends the data it reads to the DBusString buffer.
Definition: dbus-sysdeps-unix.c:735
_dbus_generate_random_ascii
dbus_bool_t _dbus_generate_random_ascii(DBusString *str, int n_bytes, DBusError *error)
Generates the given number of random bytes, where the bytes are chosen from the alphanumeric ASCII su...
Definition: dbus-sysdeps.c:552
DBusString
Definition: dbus-string.h:43
_dbus_make_file_world_readable
dbus_bool_t _dbus_make_file_world_readable(const DBusString *filename, DBusError *error)
Makes the file readable by every user in the system.
Definition: dbus-file-unix.c:330
FALSE
#define FALSE
Expands to "0".
DBUS_ERROR_NO_MEMORY
#define DBUS_ERROR_NO_MEMORY
There was not enough memory to complete an operation.
Definition: dbus-protocol.h:370
_dbus_string_set_length
dbus_bool_t _dbus_string_set_length(DBusString *str, int length)
Sets the length of a string.
Definition: dbus-string.c:802
_dbus_close
dbus_bool_t _dbus_close(int fd, DBusError *error)
Closes a file descriptor.
Definition: dbus-sysdeps-unix.c:3481
DBusError
Object representing an exception.
Definition: dbus-errors.h:49
dbus_set_error
void dbus_set_error(DBusError *error, const char *name, const char *format,...)
Assigns an error name and message to a DBusError.
Definition: dbus-errors.c:354
_dbus_string_append
dbus_bool_t _dbus_string_append(DBusString *str, const char *buffer)
Appends a nul-terminated C-style string to a DBusString.
Definition: dbus-string.c:935
dbus_bool_t
dbus_uint32_t dbus_bool_t
A boolean, valid values are TRUE and FALSE.
Definition: dbus-types.h:35
NULL
#define NULL
A null pointer, defined appropriately for C or C++.