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 #include "dbus-protocol.h"
00027 #include "dbus-string.h"
00028 #include "dbus-internals.h"
00029 #include "dbus-sysdeps-win.h"
00030 #include "dbus-pipe.h"
00031
00032 #include <windows.h>
00033
00034
00046 static int
00047 _dbus_file_read (HANDLE hnd,
00048 DBusString *buffer,
00049 int count,
00050 DBusError *error)
00051 {
00052 BOOL result;
00053 DWORD bytes_read;
00054 int start;
00055 char *data;
00056
00057 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
00058
00059 _dbus_assert (count >= 0);
00060
00061 start = _dbus_string_get_length (buffer);
00062
00063 if (!_dbus_string_lengthen (buffer, count))
00064 {
00065 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
00066 return -1;
00067 }
00068
00069 data = _dbus_string_get_data_len (buffer, start, count);
00070
00071 result = ReadFile (hnd, data, count, &bytes_read, NULL);
00072 if (result == 0)
00073 {
00074 char *emsg = _dbus_win_error_string (GetLastError ());
00075 dbus_set_error (error, _dbus_win_error_from_last_error (),
00076 "Failed to read from 0x%x: %s", hnd, emsg);
00077 _dbus_win_free_error_string (emsg);
00078 return -1;
00079 }
00080
00081 if (bytes_read)
00082 {
00083
00084 _dbus_string_set_length (buffer, start + bytes_read);
00085
00086 #if 0
00087 if (bytes_read > 0)
00088 _dbus_verbose_bytes_of_string (buffer, start, bytes_read);
00089 #endif
00090 }
00091
00092 return bytes_read;
00093 }
00094
00095
00106 dbus_bool_t
00107 _dbus_file_get_contents (DBusString *str,
00108 const DBusString *filename,
00109 DBusError *error)
00110 {
00111 HANDLE hnd;
00112 DWORD fsize;
00113 DWORD fsize_hi;
00114 int orig_len;
00115 unsigned int total;
00116 const char *filename_c;
00117
00118 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
00119
00120 filename_c = _dbus_string_get_const_data (filename);
00121
00122 hnd = CreateFileA (filename_c, GENERIC_READ,
00123 FILE_SHARE_READ | FILE_SHARE_WRITE,
00124 NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
00125 if (hnd == INVALID_HANDLE_VALUE)
00126 {
00127 char *emsg = _dbus_win_error_string (GetLastError ());
00128 dbus_set_error (error, _dbus_win_error_from_last_error (),
00129 "Failed to open \"%s\": %s", filename_c, emsg);
00130 _dbus_win_free_error_string (emsg);
00131 return FALSE;
00132 }
00133
00134 _dbus_verbose ("file %s hnd %p opened\n", filename_c, hnd);
00135
00136 fsize = GetFileSize (hnd, &fsize_hi);
00137 if (fsize == 0xFFFFFFFF && GetLastError() != NO_ERROR)
00138 {
00139 char *emsg = _dbus_win_error_string (GetLastError ());
00140 dbus_set_error (error, _dbus_win_error_from_last_error (),
00141 "Failed to get file size for \"%s\": %s",
00142 filename_c, emsg);
00143 _dbus_win_free_error_string (emsg);
00144
00145 _dbus_verbose ("GetFileSize() failed: %s", emsg);
00146
00147 CloseHandle (hnd);
00148
00149 return FALSE;
00150 }
00151
00152 if (fsize_hi != 0 || fsize > _DBUS_ONE_MEGABYTE)
00153 {
00154 dbus_set_error (error, DBUS_ERROR_FAILED,
00155 "File size %lu/%lu of \"%s\" is too large.",
00156 (unsigned long) fsize_hi,
00157 (unsigned long) fsize, filename_c);
00158 CloseHandle (hnd);
00159 return FALSE;
00160 }
00161
00162 total = 0;
00163 orig_len = _dbus_string_get_length (str);
00164 if (fsize > 0)
00165 {
00166 int bytes_read;
00167
00168 while (total < fsize)
00169 {
00170 bytes_read = _dbus_file_read (hnd, str, fsize - total, error);
00171 if (bytes_read <= 0)
00172 {
00173 if (bytes_read == 0)
00174 {
00175 dbus_set_error (error, DBUS_ERROR_FAILED,
00176 "Premature EOF reading \"%s\"",
00177 filename_c);
00178 }
00179 else
00180 _DBUS_ASSERT_ERROR_IS_SET (error);
00181
00182 CloseHandle (hnd);
00183 _dbus_string_set_length (str, orig_len);
00184 return FALSE;
00185 }
00186 else
00187 total += bytes_read;
00188 }
00189
00190 CloseHandle (hnd);
00191 return TRUE;
00192 }
00193 else
00194 {
00195 CloseHandle (hnd);
00196 return TRUE;
00197 }
00198 }
00199
00200
00211 dbus_bool_t
00212 _dbus_string_save_to_file (const DBusString *str,
00213 const DBusString *filename,
00214 dbus_bool_t world_readable,
00215 DBusError *error)
00216 {
00217 HANDLE hnd;
00218 int bytes_to_write;
00219 const char *filename_c;
00220 DBusString tmp_filename;
00221 const char *tmp_filename_c;
00222 int total;
00223 const char *str_c;
00224 dbus_bool_t need_unlink;
00225 dbus_bool_t retval;
00226
00227 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
00228
00229 hnd = INVALID_HANDLE_VALUE;
00230 retval = FALSE;
00231 need_unlink = FALSE;
00232
00233 if (!_dbus_string_init (&tmp_filename))
00234 {
00235 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
00236 return FALSE;
00237 }
00238
00239 if (!_dbus_string_copy (filename, 0, &tmp_filename, 0))
00240 {
00241 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
00242 _dbus_string_free (&tmp_filename);
00243 return FALSE;
00244 }
00245
00246 if (!_dbus_string_append (&tmp_filename, "."))
00247 {
00248 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
00249 _dbus_string_free (&tmp_filename);
00250 return FALSE;
00251 }
00252
00253 #define N_TMP_FILENAME_RANDOM_BYTES 8
00254 if (!_dbus_generate_random_ascii (&tmp_filename, N_TMP_FILENAME_RANDOM_BYTES))
00255 {
00256 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
00257 _dbus_string_free (&tmp_filename);
00258 return FALSE;
00259 }
00260
00261 filename_c = _dbus_string_get_const_data (filename);
00262 tmp_filename_c = _dbus_string_get_const_data (&tmp_filename);
00263
00264
00265 hnd = CreateFileA (tmp_filename_c, GENERIC_WRITE,
00266 FILE_SHARE_READ | FILE_SHARE_WRITE,
00267 NULL, CREATE_NEW, FILE_ATTRIBUTE_NORMAL,
00268 INVALID_HANDLE_VALUE);
00269 if (hnd == INVALID_HANDLE_VALUE)
00270 {
00271 char *emsg = _dbus_win_error_string (GetLastError ());
00272 dbus_set_error (error, _dbus_win_error_from_last_error (),
00273 "Could not create \"%s\": %s", filename_c, emsg);
00274 _dbus_win_free_error_string (emsg);
00275 goto out;
00276 }
00277 if (world_readable)
00278 {
00279 if (! _dbus_make_file_world_readable (&tmp_filename, error))
00280 goto out;
00281 }
00282
00283 _dbus_verbose ("tmp file %s hnd %p opened\n", tmp_filename_c, hnd);
00284
00285 need_unlink = TRUE;
00286
00287 total = 0;
00288 bytes_to_write = _dbus_string_get_length (str);
00289 str_c = _dbus_string_get_const_data (str);
00290
00291 while (total < bytes_to_write)
00292 {
00293 DWORD bytes_written;
00294 BOOL res;
00295
00296 res = WriteFile (hnd, str_c + total, bytes_to_write - total,
00297 &bytes_written, NULL);
00298
00299 if (res == 0 || bytes_written <= 0)
00300 {
00301 char *emsg = _dbus_win_error_string (GetLastError ());
00302 dbus_set_error (error, _dbus_win_error_from_last_error (),
00303 "Could not write to %s: %s", tmp_filename_c, emsg);
00304 _dbus_win_free_error_string (emsg);
00305 goto out;
00306 }
00307
00308 total += bytes_written;
00309 }
00310
00311 if (CloseHandle (hnd) == 0)
00312 {
00313 char *emsg = _dbus_win_error_string (GetLastError ());
00314 dbus_set_error (error, _dbus_win_error_from_last_error (),
00315 "Could not close file %s: %s", tmp_filename_c, emsg);
00316 _dbus_win_free_error_string (emsg);
00317 goto out;
00318 }
00319
00320 hnd = INVALID_HANDLE_VALUE;
00321
00322
00323 if (!MoveFileExA (tmp_filename_c, filename_c, MOVEFILE_REPLACE_EXISTING))
00324 {
00325 char *emsg = _dbus_win_error_string (GetLastError ());
00326 dbus_set_error (error, _dbus_win_error_from_last_error (),
00327 "Could not rename %s to %s: %s",
00328 tmp_filename_c, filename_c, emsg);
00329 _dbus_win_free_error_string (emsg);
00330
00331 goto out;
00332 }
00333
00334 need_unlink = FALSE;
00335
00336 retval = TRUE;
00337
00338 out:
00339
00340
00341 if (hnd != INVALID_HANDLE_VALUE)
00342 CloseHandle (hnd);
00343
00344 if (need_unlink && DeleteFileA (tmp_filename_c) == 0)
00345 {
00346 char *emsg = _dbus_win_error_string (GetLastError ());
00347 _dbus_verbose ("Failed to unlink temp file %s: %s", tmp_filename_c,
00348 emsg);
00349 _dbus_win_free_error_string (emsg);
00350 }
00351
00352 _dbus_string_free (&tmp_filename);
00353
00354 if (!retval)
00355 _DBUS_ASSERT_ERROR_IS_SET (error);
00356
00357 return retval;
00358 }
00359
00360
00367 dbus_bool_t
00368 _dbus_create_file_exclusively (const DBusString *filename,
00369 DBusError *error)
00370 {
00371 HANDLE hnd;
00372 const char *filename_c;
00373
00374 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
00375
00376 filename_c = _dbus_string_get_const_data (filename);
00377
00378 hnd = CreateFileA (filename_c, GENERIC_WRITE,
00379 FILE_SHARE_READ | FILE_SHARE_WRITE,
00380 NULL, CREATE_NEW, FILE_ATTRIBUTE_NORMAL,
00381 INVALID_HANDLE_VALUE);
00382 if (hnd == INVALID_HANDLE_VALUE)
00383 {
00384 char *emsg = _dbus_win_error_string (GetLastError ());
00385 dbus_set_error (error, _dbus_win_error_from_last_error (),
00386 "Could not create file %s: %s",
00387 filename_c, emsg);
00388 _dbus_win_free_error_string (emsg);
00389 return FALSE;
00390 }
00391
00392 _dbus_verbose ("exclusive file %s hnd %p opened\n", filename_c, hnd);
00393
00394 if (CloseHandle (hnd) == 0)
00395 {
00396 char *emsg = _dbus_win_error_string (GetLastError ());
00397 dbus_set_error (error, _dbus_win_error_from_last_error (),
00398 "Could not close file %s: %s",
00399 filename_c, emsg);
00400 _dbus_win_free_error_string (emsg);
00401
00402 return FALSE;
00403 }
00404
00405 return TRUE;
00406 }
00407