D-Bus 1.4.20
|
00001 /* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ 00002 /* dbus-file-unix.c unix related file implementation (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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 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 /* O_BINARY useful on Cygwin */ 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 /* Ensure the file is world readable even in the presence of 00227 * possibly restrictive umasks; 00228 * see http://lists.freedesktop.org/archives/dbus/2010-September/013367.html 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 /* close first, then unlink, to prevent ".nfs34234235" garbage 00301 * files 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 }