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 <config.h>
00026
00027 #include "dbus-protocol.h"
00028 #include "dbus-errors.h"
00029 #include "dbus-file.h"
00030 #include "dbus-internals.h"
00031 #include "dbus-sysdeps.h"
00032 #include "dbus-sysdeps-unix.h"
00033
00034 #include <sys/stat.h>
00035 #include <stdio.h>
00036 #include <fcntl.h>
00037 #include <unistd.h>
00038 #include <errno.h>
00039
00040 #ifndef O_BINARY
00041 #define O_BINARY 0
00042 #endif
00043
00054 dbus_bool_t
00055 _dbus_file_get_contents (DBusString *str,
00056 const DBusString *filename,
00057 DBusError *error)
00058 {
00059 int fd;
00060 struct stat sb;
00061 int orig_len;
00062 int total;
00063 const char *filename_c;
00064
00065 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
00066
00067 filename_c = _dbus_string_get_const_data (filename);
00068
00069
00070 fd = open (filename_c, O_RDONLY | O_BINARY);
00071 if (fd < 0)
00072 {
00073 dbus_set_error (error, _dbus_error_from_errno (errno),
00074 "Failed to open \"%s\": %s",
00075 filename_c,
00076 _dbus_strerror (errno));
00077 return FALSE;
00078 }
00079
00080 _dbus_verbose ("file fd %d opened\n", fd);
00081
00082 if (fstat (fd, &sb) < 0)
00083 {
00084 dbus_set_error (error, _dbus_error_from_errno (errno),
00085 "Failed to stat \"%s\": %s",
00086 filename_c,
00087 _dbus_strerror (errno));
00088
00089 _dbus_verbose ("fstat() failed: %s",
00090 _dbus_strerror (errno));
00091
00092 _dbus_close (fd, NULL);
00093
00094 return FALSE;
00095 }
00096
00097 if (sb.st_size > _DBUS_ONE_MEGABYTE)
00098 {
00099 dbus_set_error (error, DBUS_ERROR_FAILED,
00100 "File size %lu of \"%s\" is too large.",
00101 (unsigned long) sb.st_size, filename_c);
00102 _dbus_close (fd, NULL);
00103 return FALSE;
00104 }
00105
00106 total = 0;
00107 orig_len = _dbus_string_get_length (str);
00108 if (sb.st_size > 0 && S_ISREG (sb.st_mode))
00109 {
00110 int bytes_read;
00111
00112 while (total < (int) sb.st_size)
00113 {
00114 bytes_read = _dbus_read (fd, str,
00115 sb.st_size - total);
00116 if (bytes_read <= 0)
00117 {
00118 dbus_set_error (error, _dbus_error_from_errno (errno),
00119 "Error reading \"%s\": %s",
00120 filename_c,
00121 _dbus_strerror (errno));
00122
00123 _dbus_verbose ("read() failed: %s",
00124 _dbus_strerror (errno));
00125
00126 _dbus_close (fd, NULL);
00127 _dbus_string_set_length (str, orig_len);
00128 return FALSE;
00129 }
00130 else
00131 total += bytes_read;
00132 }
00133
00134 _dbus_close (fd, NULL);
00135 return TRUE;
00136 }
00137 else if (sb.st_size != 0)
00138 {
00139 _dbus_verbose ("Can only open regular files at the moment.\n");
00140 dbus_set_error (error, DBUS_ERROR_FAILED,
00141 "\"%s\" is not a regular file",
00142 filename_c);
00143 _dbus_close (fd, NULL);
00144 return FALSE;
00145 }
00146 else
00147 {
00148 _dbus_close (fd, NULL);
00149 return TRUE;
00150 }
00151 }
00152
00163 dbus_bool_t
00164 _dbus_string_save_to_file (const DBusString *str,
00165 const DBusString *filename,
00166 dbus_bool_t world_readable,
00167 DBusError *error)
00168 {
00169 int fd;
00170 int bytes_to_write;
00171 const char *filename_c;
00172 DBusString tmp_filename;
00173 const char *tmp_filename_c;
00174 int total;
00175 dbus_bool_t need_unlink;
00176 dbus_bool_t retval;
00177
00178 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
00179
00180 fd = -1;
00181 retval = FALSE;
00182 need_unlink = FALSE;
00183
00184 if (!_dbus_string_init (&tmp_filename))
00185 {
00186 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
00187 return FALSE;
00188 }
00189
00190 if (!_dbus_string_copy (filename, 0, &tmp_filename, 0))
00191 {
00192 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
00193 _dbus_string_free (&tmp_filename);
00194 return FALSE;
00195 }
00196
00197 if (!_dbus_string_append (&tmp_filename, "."))
00198 {
00199 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
00200 _dbus_string_free (&tmp_filename);
00201 return FALSE;
00202 }
00203
00204 #define N_TMP_FILENAME_RANDOM_BYTES 8
00205 if (!_dbus_generate_random_ascii (&tmp_filename, N_TMP_FILENAME_RANDOM_BYTES))
00206 {
00207 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
00208 _dbus_string_free (&tmp_filename);
00209 return FALSE;
00210 }
00211
00212 filename_c = _dbus_string_get_const_data (filename);
00213 tmp_filename_c = _dbus_string_get_const_data (&tmp_filename);
00214
00215 fd = open (tmp_filename_c, O_WRONLY | O_BINARY | O_EXCL | O_CREAT,
00216 world_readable ? 0644 : 0600);
00217 if (fd < 0)
00218 {
00219 dbus_set_error (error, _dbus_error_from_errno (errno),
00220 "Could not create %s: %s", tmp_filename_c,
00221 _dbus_strerror (errno));
00222 goto out;
00223 }
00224 if (world_readable)
00225 {
00226
00227
00228
00229
00230 if (fchmod (fd, 0644) < 0)
00231 {
00232 dbus_set_error (error, _dbus_error_from_errno (errno),
00233 "Could not chmod %s: %s", tmp_filename_c,
00234 _dbus_strerror (errno));
00235 goto out;
00236 }
00237 }
00238
00239 _dbus_verbose ("tmp file fd %d opened\n", fd);
00240
00241 need_unlink = TRUE;
00242
00243 total = 0;
00244 bytes_to_write = _dbus_string_get_length (str);
00245
00246 while (total < bytes_to_write)
00247 {
00248 int bytes_written;
00249
00250 bytes_written = _dbus_write (fd, str, total,
00251 bytes_to_write - total);
00252
00253 if (bytes_written <= 0)
00254 {
00255 dbus_set_error (error, _dbus_error_from_errno (errno),
00256 "Could not write to %s: %s", tmp_filename_c,
00257 _dbus_strerror (errno));
00258
00259 goto out;
00260 }
00261
00262 total += bytes_written;
00263 }
00264
00265 if (fsync(fd))
00266 {
00267 dbus_set_error (error, _dbus_error_from_errno (errno),
00268 "Could not synchronize file %s: %s",
00269 tmp_filename_c, _dbus_strerror (errno));
00270
00271 goto out;
00272 }
00273
00274 if (!_dbus_close (fd, NULL))
00275 {
00276 dbus_set_error (error, _dbus_error_from_errno (errno),
00277 "Could not close file %s: %s",
00278 tmp_filename_c, _dbus_strerror (errno));
00279
00280 goto out;
00281 }
00282
00283 fd = -1;
00284
00285 if (rename (tmp_filename_c, filename_c) < 0)
00286 {
00287 dbus_set_error (error, _dbus_error_from_errno (errno),
00288 "Could not rename %s to %s: %s",
00289 tmp_filename_c, filename_c,
00290 _dbus_strerror (errno));
00291
00292 goto out;
00293 }
00294
00295 need_unlink = FALSE;
00296
00297 retval = TRUE;
00298
00299 out:
00300
00301
00302
00303
00304 if (fd >= 0)
00305 _dbus_close (fd, NULL);
00306
00307 if (need_unlink && unlink (tmp_filename_c) < 0)
00308 _dbus_verbose ("Failed to unlink temp file %s: %s\n",
00309 tmp_filename_c, _dbus_strerror (errno));
00310
00311 _dbus_string_free (&tmp_filename);
00312
00313 if (!retval)
00314 _DBUS_ASSERT_ERROR_IS_SET (error);
00315
00316 return retval;
00317 }
00318
00325 dbus_bool_t
00326 _dbus_make_file_world_readable(const DBusString *filename,
00327 DBusError *error)
00328 {
00329 const char *filename_c;
00330
00331 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
00332
00333 filename_c = _dbus_string_get_const_data (filename);
00334 if (chmod (filename_c, 0644) == -1)
00335 {
00336 dbus_set_error (error,
00337 DBUS_ERROR_FAILED,
00338 "Could not change permissions of file %s: %s\n",
00339 filename_c,
00340 _dbus_strerror (errno));
00341 return FALSE;
00342 }
00343 return TRUE;
00344 }
00345
00352 dbus_bool_t
00353 _dbus_create_file_exclusively (const DBusString *filename,
00354 DBusError *error)
00355 {
00356 int fd;
00357 const char *filename_c;
00358
00359 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
00360
00361 filename_c = _dbus_string_get_const_data (filename);
00362
00363 fd = open (filename_c, O_WRONLY | O_BINARY | O_EXCL | O_CREAT,
00364 0600);
00365 if (fd < 0)
00366 {
00367 dbus_set_error (error,
00368 DBUS_ERROR_FAILED,
00369 "Could not create file %s: %s\n",
00370 filename_c,
00371 _dbus_strerror (errno));
00372 return FALSE;
00373 }
00374
00375 _dbus_verbose ("exclusive file fd %d opened\n", fd);
00376
00377 if (!_dbus_close (fd, NULL))
00378 {
00379 dbus_set_error (error,
00380 DBUS_ERROR_FAILED,
00381 "Could not close file %s: %s\n",
00382 filename_c,
00383 _dbus_strerror (errno));
00384 return FALSE;
00385 }
00386
00387 return TRUE;
00388 }
00389
00398 dbus_bool_t
00399 _dbus_delete_file (const DBusString *filename,
00400 DBusError *error)
00401 {
00402 const char *filename_c;
00403
00404 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
00405
00406 filename_c = _dbus_string_get_const_data (filename);
00407
00408 if (unlink (filename_c) < 0)
00409 {
00410 dbus_set_error (error, DBUS_ERROR_FAILED,
00411 "Failed to delete file %s: %s\n",
00412 filename_c, _dbus_strerror (errno));
00413 return FALSE;
00414 }
00415 else
00416 return TRUE;
00417 }