1413c3537b8730940d516af4823e83ac8df001edeRalf Habacker/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ 2413c3537b8730940d516af4823e83ac8df001edeRalf Habacker/* dbus-file-win.c windows related file implementation (internal to D-Bus implementation) 3413c3537b8730940d516af4823e83ac8df001edeRalf Habacker * 4413c3537b8730940d516af4823e83ac8df001edeRalf Habacker * Copyright (C) 2002, 2003, 2006 Red Hat, Inc. 5413c3537b8730940d516af4823e83ac8df001edeRalf Habacker * Copyright (C) 2003 CodeFactory AB 6413c3537b8730940d516af4823e83ac8df001edeRalf Habacker * 7413c3537b8730940d516af4823e83ac8df001edeRalf Habacker * Licensed under the Academic Free License version 2.1 8413c3537b8730940d516af4823e83ac8df001edeRalf Habacker * 9413c3537b8730940d516af4823e83ac8df001edeRalf Habacker * This program is free software; you can redistribute it and/or modify 10413c3537b8730940d516af4823e83ac8df001edeRalf Habacker * it under the terms of the GNU General Public License as published by 11413c3537b8730940d516af4823e83ac8df001edeRalf Habacker * the Free Software Foundation; either version 2 of the License, or 12413c3537b8730940d516af4823e83ac8df001edeRalf Habacker * (at your option) any later version. 13413c3537b8730940d516af4823e83ac8df001edeRalf Habacker * 14413c3537b8730940d516af4823e83ac8df001edeRalf Habacker * This program is distributed in the hope that it will be useful, 15413c3537b8730940d516af4823e83ac8df001edeRalf Habacker * but WITHOUT ANY WARRANTY; without even the implied warranty of 16413c3537b8730940d516af4823e83ac8df001edeRalf Habacker * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 17413c3537b8730940d516af4823e83ac8df001edeRalf Habacker * GNU General Public License for more details. 18413c3537b8730940d516af4823e83ac8df001edeRalf Habacker * 19413c3537b8730940d516af4823e83ac8df001edeRalf Habacker * You should have received a copy of the GNU General Public License 20413c3537b8730940d516af4823e83ac8df001edeRalf Habacker * along with this program; if not, write to the Free Software 21413c3537b8730940d516af4823e83ac8df001edeRalf Habacker * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 22413c3537b8730940d516af4823e83ac8df001edeRalf Habacker * 23413c3537b8730940d516af4823e83ac8df001edeRalf Habacker */ 24413c3537b8730940d516af4823e83ac8df001edeRalf Habacker 25dbecdeabb20e0ce11121819c63373f0afba57c58Marcus Brinkmann#include <config.h> 26413c3537b8730940d516af4823e83ac8df001edeRalf Habacker#include "dbus-protocol.h" 27413c3537b8730940d516af4823e83ac8df001edeRalf Habacker#include "dbus-string.h" 28413c3537b8730940d516af4823e83ac8df001edeRalf Habacker#include "dbus-internals.h" 29413c3537b8730940d516af4823e83ac8df001edeRalf Habacker#include "dbus-sysdeps-win.h" 30413c3537b8730940d516af4823e83ac8df001edeRalf Habacker#include "dbus-pipe.h" 31413c3537b8730940d516af4823e83ac8df001edeRalf Habacker 32413c3537b8730940d516af4823e83ac8df001edeRalf Habacker#include <windows.h> 336e214b5b3c283798b5743b4ebf7c9ec466fe3667Marcus Brinkmann 346e214b5b3c283798b5743b4ebf7c9ec466fe3667Marcus Brinkmann 356e214b5b3c283798b5743b4ebf7c9ec466fe3667Marcus Brinkmann/** 366e214b5b3c283798b5743b4ebf7c9ec466fe3667Marcus Brinkmann * Thin wrapper around the read() system call that appends 376e214b5b3c283798b5743b4ebf7c9ec466fe3667Marcus Brinkmann * the data it reads to the DBusString buffer. It appends 386e214b5b3c283798b5743b4ebf7c9ec466fe3667Marcus Brinkmann * up to the given count. 396e214b5b3c283798b5743b4ebf7c9ec466fe3667Marcus Brinkmann * 406e214b5b3c283798b5743b4ebf7c9ec466fe3667Marcus Brinkmann * @param hnd the HANDLE to read from 416e214b5b3c283798b5743b4ebf7c9ec466fe3667Marcus Brinkmann * @param buffer the buffer to append data to 426e214b5b3c283798b5743b4ebf7c9ec466fe3667Marcus Brinkmann * @param count the amount of data to read 436e214b5b3c283798b5743b4ebf7c9ec466fe3667Marcus Brinkmann * @param error place to set an error 446e214b5b3c283798b5743b4ebf7c9ec466fe3667Marcus Brinkmann * @returns the number of bytes read or -1 456e214b5b3c283798b5743b4ebf7c9ec466fe3667Marcus Brinkmann */ 466e214b5b3c283798b5743b4ebf7c9ec466fe3667Marcus Brinkmannstatic int 476e214b5b3c283798b5743b4ebf7c9ec466fe3667Marcus Brinkmann_dbus_file_read (HANDLE hnd, 486e214b5b3c283798b5743b4ebf7c9ec466fe3667Marcus Brinkmann DBusString *buffer, 496e214b5b3c283798b5743b4ebf7c9ec466fe3667Marcus Brinkmann int count, 506e214b5b3c283798b5743b4ebf7c9ec466fe3667Marcus Brinkmann DBusError *error) 516e214b5b3c283798b5743b4ebf7c9ec466fe3667Marcus Brinkmann{ 526e214b5b3c283798b5743b4ebf7c9ec466fe3667Marcus Brinkmann BOOL result; 536e214b5b3c283798b5743b4ebf7c9ec466fe3667Marcus Brinkmann DWORD bytes_read; 546e214b5b3c283798b5743b4ebf7c9ec466fe3667Marcus Brinkmann int start; 556e214b5b3c283798b5743b4ebf7c9ec466fe3667Marcus Brinkmann char *data; 566e214b5b3c283798b5743b4ebf7c9ec466fe3667Marcus Brinkmann 576e214b5b3c283798b5743b4ebf7c9ec466fe3667Marcus Brinkmann _DBUS_ASSERT_ERROR_IS_CLEAR (error); 586e214b5b3c283798b5743b4ebf7c9ec466fe3667Marcus Brinkmann 596e214b5b3c283798b5743b4ebf7c9ec466fe3667Marcus Brinkmann _dbus_assert (count >= 0); 606e214b5b3c283798b5743b4ebf7c9ec466fe3667Marcus Brinkmann 616e214b5b3c283798b5743b4ebf7c9ec466fe3667Marcus Brinkmann start = _dbus_string_get_length (buffer); 626e214b5b3c283798b5743b4ebf7c9ec466fe3667Marcus Brinkmann 636e214b5b3c283798b5743b4ebf7c9ec466fe3667Marcus Brinkmann if (!_dbus_string_lengthen (buffer, count)) 646e214b5b3c283798b5743b4ebf7c9ec466fe3667Marcus Brinkmann { 656e214b5b3c283798b5743b4ebf7c9ec466fe3667Marcus Brinkmann dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL); 666e214b5b3c283798b5743b4ebf7c9ec466fe3667Marcus Brinkmann return -1; 676e214b5b3c283798b5743b4ebf7c9ec466fe3667Marcus Brinkmann } 686e214b5b3c283798b5743b4ebf7c9ec466fe3667Marcus Brinkmann 696e214b5b3c283798b5743b4ebf7c9ec466fe3667Marcus Brinkmann data = _dbus_string_get_data_len (buffer, start, count); 706e214b5b3c283798b5743b4ebf7c9ec466fe3667Marcus Brinkmann 716e214b5b3c283798b5743b4ebf7c9ec466fe3667Marcus Brinkmann result = ReadFile (hnd, data, count, &bytes_read, NULL); 726e214b5b3c283798b5743b4ebf7c9ec466fe3667Marcus Brinkmann if (result == 0) 736e214b5b3c283798b5743b4ebf7c9ec466fe3667Marcus Brinkmann { 746e214b5b3c283798b5743b4ebf7c9ec466fe3667Marcus Brinkmann char *emsg = _dbus_win_error_string (GetLastError ()); 756e214b5b3c283798b5743b4ebf7c9ec466fe3667Marcus Brinkmann dbus_set_error (error, _dbus_win_error_from_last_error (), 766e214b5b3c283798b5743b4ebf7c9ec466fe3667Marcus Brinkmann "Failed to read from 0x%x: %s", hnd, emsg); 776e214b5b3c283798b5743b4ebf7c9ec466fe3667Marcus Brinkmann _dbus_win_free_error_string (emsg); 786e214b5b3c283798b5743b4ebf7c9ec466fe3667Marcus Brinkmann return -1; 796e214b5b3c283798b5743b4ebf7c9ec466fe3667Marcus Brinkmann } 806e214b5b3c283798b5743b4ebf7c9ec466fe3667Marcus Brinkmann 816e214b5b3c283798b5743b4ebf7c9ec466fe3667Marcus Brinkmann if (bytes_read) 826e214b5b3c283798b5743b4ebf7c9ec466fe3667Marcus Brinkmann { 836e214b5b3c283798b5743b4ebf7c9ec466fe3667Marcus Brinkmann /* put length back (doesn't actually realloc) */ 846e214b5b3c283798b5743b4ebf7c9ec466fe3667Marcus Brinkmann _dbus_string_set_length (buffer, start + bytes_read); 856e214b5b3c283798b5743b4ebf7c9ec466fe3667Marcus Brinkmann 866e214b5b3c283798b5743b4ebf7c9ec466fe3667Marcus Brinkmann#if 0 876e214b5b3c283798b5743b4ebf7c9ec466fe3667Marcus Brinkmann if (bytes_read > 0) 886e214b5b3c283798b5743b4ebf7c9ec466fe3667Marcus Brinkmann _dbus_verbose_bytes_of_string (buffer, start, bytes_read); 896e214b5b3c283798b5743b4ebf7c9ec466fe3667Marcus Brinkmann#endif 906e214b5b3c283798b5743b4ebf7c9ec466fe3667Marcus Brinkmann } 916e214b5b3c283798b5743b4ebf7c9ec466fe3667Marcus Brinkmann 926e214b5b3c283798b5743b4ebf7c9ec466fe3667Marcus Brinkmann return bytes_read; 936e214b5b3c283798b5743b4ebf7c9ec466fe3667Marcus Brinkmann} 946e214b5b3c283798b5743b4ebf7c9ec466fe3667Marcus Brinkmann 956e214b5b3c283798b5743b4ebf7c9ec466fe3667Marcus Brinkmann 96413c3537b8730940d516af4823e83ac8df001edeRalf Habacker/** 97413c3537b8730940d516af4823e83ac8df001edeRalf Habacker * Appends the contents of the given file to the string, 98413c3537b8730940d516af4823e83ac8df001edeRalf Habacker * returning error code. At the moment, won't open a file 99413c3537b8730940d516af4823e83ac8df001edeRalf Habacker * more than a megabyte in size. 100413c3537b8730940d516af4823e83ac8df001edeRalf Habacker * 101413c3537b8730940d516af4823e83ac8df001edeRalf Habacker * @param str the string to append to 102413c3537b8730940d516af4823e83ac8df001edeRalf Habacker * @param filename filename to load 103413c3537b8730940d516af4823e83ac8df001edeRalf Habacker * @param error place to set an error 104413c3537b8730940d516af4823e83ac8df001edeRalf Habacker * @returns #FALSE if error was set 105413c3537b8730940d516af4823e83ac8df001edeRalf Habacker */ 106413c3537b8730940d516af4823e83ac8df001edeRalf Habackerdbus_bool_t 107413c3537b8730940d516af4823e83ac8df001edeRalf Habacker_dbus_file_get_contents (DBusString *str, 108413c3537b8730940d516af4823e83ac8df001edeRalf Habacker const DBusString *filename, 109413c3537b8730940d516af4823e83ac8df001edeRalf Habacker DBusError *error) 110413c3537b8730940d516af4823e83ac8df001edeRalf Habacker{ 1116e214b5b3c283798b5743b4ebf7c9ec466fe3667Marcus Brinkmann HANDLE hnd; 1126e214b5b3c283798b5743b4ebf7c9ec466fe3667Marcus Brinkmann DWORD fsize; 1136e214b5b3c283798b5743b4ebf7c9ec466fe3667Marcus Brinkmann DWORD fsize_hi; 114413c3537b8730940d516af4823e83ac8df001edeRalf Habacker int orig_len; 115cd815c347a279f324e5025fcda71a16ad9b08c7dRalf Habacker unsigned int total; 116413c3537b8730940d516af4823e83ac8df001edeRalf Habacker const char *filename_c; 117413c3537b8730940d516af4823e83ac8df001edeRalf Habacker 118413c3537b8730940d516af4823e83ac8df001edeRalf Habacker _DBUS_ASSERT_ERROR_IS_CLEAR (error); 119413c3537b8730940d516af4823e83ac8df001edeRalf Habacker 120413c3537b8730940d516af4823e83ac8df001edeRalf Habacker filename_c = _dbus_string_get_const_data (filename); 121413c3537b8730940d516af4823e83ac8df001edeRalf Habacker 1226e214b5b3c283798b5743b4ebf7c9ec466fe3667Marcus Brinkmann hnd = CreateFileA (filename_c, GENERIC_READ, 1236e214b5b3c283798b5743b4ebf7c9ec466fe3667Marcus Brinkmann FILE_SHARE_READ | FILE_SHARE_WRITE, 1246e214b5b3c283798b5743b4ebf7c9ec466fe3667Marcus Brinkmann NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); 1256e214b5b3c283798b5743b4ebf7c9ec466fe3667Marcus Brinkmann if (hnd == INVALID_HANDLE_VALUE) 126413c3537b8730940d516af4823e83ac8df001edeRalf Habacker { 1276e214b5b3c283798b5743b4ebf7c9ec466fe3667Marcus Brinkmann char *emsg = _dbus_win_error_string (GetLastError ()); 1286e214b5b3c283798b5743b4ebf7c9ec466fe3667Marcus Brinkmann dbus_set_error (error, _dbus_win_error_from_last_error (), 1296e214b5b3c283798b5743b4ebf7c9ec466fe3667Marcus Brinkmann "Failed to open \"%s\": %s", filename_c, emsg); 1306e214b5b3c283798b5743b4ebf7c9ec466fe3667Marcus Brinkmann _dbus_win_free_error_string (emsg); 131413c3537b8730940d516af4823e83ac8df001edeRalf Habacker return FALSE; 132413c3537b8730940d516af4823e83ac8df001edeRalf Habacker } 133413c3537b8730940d516af4823e83ac8df001edeRalf Habacker 134e419a5cff71bf71c626223393692c341f3db35e9Marcus Brinkmann _dbus_verbose ("file %s hnd %p opened\n", filename_c, hnd); 1356e214b5b3c283798b5743b4ebf7c9ec466fe3667Marcus Brinkmann 1366e214b5b3c283798b5743b4ebf7c9ec466fe3667Marcus Brinkmann fsize = GetFileSize (hnd, &fsize_hi); 1376e214b5b3c283798b5743b4ebf7c9ec466fe3667Marcus Brinkmann if (fsize == 0xFFFFFFFF && GetLastError() != NO_ERROR) 1386e214b5b3c283798b5743b4ebf7c9ec466fe3667Marcus Brinkmann { 1396e214b5b3c283798b5743b4ebf7c9ec466fe3667Marcus Brinkmann char *emsg = _dbus_win_error_string (GetLastError ()); 1406e214b5b3c283798b5743b4ebf7c9ec466fe3667Marcus Brinkmann dbus_set_error (error, _dbus_win_error_from_last_error (), 1416e214b5b3c283798b5743b4ebf7c9ec466fe3667Marcus Brinkmann "Failed to get file size for \"%s\": %s", 1426e214b5b3c283798b5743b4ebf7c9ec466fe3667Marcus Brinkmann filename_c, emsg); 1436e214b5b3c283798b5743b4ebf7c9ec466fe3667Marcus Brinkmann _dbus_win_free_error_string (emsg); 144413c3537b8730940d516af4823e83ac8df001edeRalf Habacker 1456e214b5b3c283798b5743b4ebf7c9ec466fe3667Marcus Brinkmann _dbus_verbose ("GetFileSize() failed: %s", emsg); 146413c3537b8730940d516af4823e83ac8df001edeRalf Habacker 1476e214b5b3c283798b5743b4ebf7c9ec466fe3667Marcus Brinkmann CloseHandle (hnd); 148413c3537b8730940d516af4823e83ac8df001edeRalf Habacker 149413c3537b8730940d516af4823e83ac8df001edeRalf Habacker return FALSE; 150413c3537b8730940d516af4823e83ac8df001edeRalf Habacker } 151413c3537b8730940d516af4823e83ac8df001edeRalf Habacker 1526e214b5b3c283798b5743b4ebf7c9ec466fe3667Marcus Brinkmann if (fsize_hi != 0 || fsize > _DBUS_ONE_MEGABYTE) 153413c3537b8730940d516af4823e83ac8df001edeRalf Habacker { 154413c3537b8730940d516af4823e83ac8df001edeRalf Habacker dbus_set_error (error, DBUS_ERROR_FAILED, 1556e214b5b3c283798b5743b4ebf7c9ec466fe3667Marcus Brinkmann "File size %lu/%lu of \"%s\" is too large.", 1566e214b5b3c283798b5743b4ebf7c9ec466fe3667Marcus Brinkmann (unsigned long) fsize_hi, 1576e214b5b3c283798b5743b4ebf7c9ec466fe3667Marcus Brinkmann (unsigned long) fsize, filename_c); 1586e214b5b3c283798b5743b4ebf7c9ec466fe3667Marcus Brinkmann CloseHandle (hnd); 159413c3537b8730940d516af4823e83ac8df001edeRalf Habacker return FALSE; 160413c3537b8730940d516af4823e83ac8df001edeRalf Habacker } 161413c3537b8730940d516af4823e83ac8df001edeRalf Habacker 162413c3537b8730940d516af4823e83ac8df001edeRalf Habacker total = 0; 163413c3537b8730940d516af4823e83ac8df001edeRalf Habacker orig_len = _dbus_string_get_length (str); 1646e214b5b3c283798b5743b4ebf7c9ec466fe3667Marcus Brinkmann if (fsize > 0) 165413c3537b8730940d516af4823e83ac8df001edeRalf Habacker { 166413c3537b8730940d516af4823e83ac8df001edeRalf Habacker int bytes_read; 167413c3537b8730940d516af4823e83ac8df001edeRalf Habacker 1686e214b5b3c283798b5743b4ebf7c9ec466fe3667Marcus Brinkmann while (total < fsize) 169413c3537b8730940d516af4823e83ac8df001edeRalf Habacker { 1706e214b5b3c283798b5743b4ebf7c9ec466fe3667Marcus Brinkmann bytes_read = _dbus_file_read (hnd, str, fsize - total, error); 171413c3537b8730940d516af4823e83ac8df001edeRalf Habacker if (bytes_read <= 0) 172413c3537b8730940d516af4823e83ac8df001edeRalf Habacker { 1736e214b5b3c283798b5743b4ebf7c9ec466fe3667Marcus Brinkmann if (bytes_read == 0) 1746e214b5b3c283798b5743b4ebf7c9ec466fe3667Marcus Brinkmann { 1756e214b5b3c283798b5743b4ebf7c9ec466fe3667Marcus Brinkmann dbus_set_error (error, DBUS_ERROR_FAILED, 1766e214b5b3c283798b5743b4ebf7c9ec466fe3667Marcus Brinkmann "Premature EOF reading \"%s\"", 1776e214b5b3c283798b5743b4ebf7c9ec466fe3667Marcus Brinkmann filename_c); 1786e214b5b3c283798b5743b4ebf7c9ec466fe3667Marcus Brinkmann } 1796e214b5b3c283798b5743b4ebf7c9ec466fe3667Marcus Brinkmann else 1806e214b5b3c283798b5743b4ebf7c9ec466fe3667Marcus Brinkmann _DBUS_ASSERT_ERROR_IS_SET (error); 1816e214b5b3c283798b5743b4ebf7c9ec466fe3667Marcus Brinkmann 1826e214b5b3c283798b5743b4ebf7c9ec466fe3667Marcus Brinkmann CloseHandle (hnd); 183413c3537b8730940d516af4823e83ac8df001edeRalf Habacker _dbus_string_set_length (str, orig_len); 184413c3537b8730940d516af4823e83ac8df001edeRalf Habacker return FALSE; 185413c3537b8730940d516af4823e83ac8df001edeRalf Habacker } 186413c3537b8730940d516af4823e83ac8df001edeRalf Habacker else 187413c3537b8730940d516af4823e83ac8df001edeRalf Habacker total += bytes_read; 188413c3537b8730940d516af4823e83ac8df001edeRalf Habacker } 189413c3537b8730940d516af4823e83ac8df001edeRalf Habacker 1906e214b5b3c283798b5743b4ebf7c9ec466fe3667Marcus Brinkmann CloseHandle (hnd); 191413c3537b8730940d516af4823e83ac8df001edeRalf Habacker return TRUE; 192413c3537b8730940d516af4823e83ac8df001edeRalf Habacker } 193413c3537b8730940d516af4823e83ac8df001edeRalf Habacker else 194413c3537b8730940d516af4823e83ac8df001edeRalf Habacker { 1956e214b5b3c283798b5743b4ebf7c9ec466fe3667Marcus Brinkmann CloseHandle (hnd); 196413c3537b8730940d516af4823e83ac8df001edeRalf Habacker return TRUE; 197413c3537b8730940d516af4823e83ac8df001edeRalf Habacker } 198413c3537b8730940d516af4823e83ac8df001edeRalf Habacker} 199413c3537b8730940d516af4823e83ac8df001edeRalf Habacker 2006e214b5b3c283798b5743b4ebf7c9ec466fe3667Marcus Brinkmann 201413c3537b8730940d516af4823e83ac8df001edeRalf Habacker/** 202413c3537b8730940d516af4823e83ac8df001edeRalf Habacker * Writes a string out to a file. If the file exists, 203413c3537b8730940d516af4823e83ac8df001edeRalf Habacker * it will be atomically overwritten by the new data. 204413c3537b8730940d516af4823e83ac8df001edeRalf Habacker * 205413c3537b8730940d516af4823e83ac8df001edeRalf Habacker * @param str the string to write out 206413c3537b8730940d516af4823e83ac8df001edeRalf Habacker * @param filename the file to save string to 20745d53565bc13678d6aa5edec1d4efb5bf8a64e0bColin Walters * @param world_readable if true, ensure file is world readable 208413c3537b8730940d516af4823e83ac8df001edeRalf Habacker * @param error error to be filled in on failure 209413c3537b8730940d516af4823e83ac8df001edeRalf Habacker * @returns #FALSE on failure 210413c3537b8730940d516af4823e83ac8df001edeRalf Habacker */ 211413c3537b8730940d516af4823e83ac8df001edeRalf Habackerdbus_bool_t 212413c3537b8730940d516af4823e83ac8df001edeRalf Habacker_dbus_string_save_to_file (const DBusString *str, 213413c3537b8730940d516af4823e83ac8df001edeRalf Habacker const DBusString *filename, 21445d53565bc13678d6aa5edec1d4efb5bf8a64e0bColin Walters dbus_bool_t world_readable, 215413c3537b8730940d516af4823e83ac8df001edeRalf Habacker DBusError *error) 216413c3537b8730940d516af4823e83ac8df001edeRalf Habacker{ 2176e214b5b3c283798b5743b4ebf7c9ec466fe3667Marcus Brinkmann HANDLE hnd; 218413c3537b8730940d516af4823e83ac8df001edeRalf Habacker int bytes_to_write; 219413c3537b8730940d516af4823e83ac8df001edeRalf Habacker const char *filename_c; 220413c3537b8730940d516af4823e83ac8df001edeRalf Habacker DBusString tmp_filename; 221413c3537b8730940d516af4823e83ac8df001edeRalf Habacker const char *tmp_filename_c; 222413c3537b8730940d516af4823e83ac8df001edeRalf Habacker int total; 223413c3537b8730940d516af4823e83ac8df001edeRalf Habacker const char *str_c; 224413c3537b8730940d516af4823e83ac8df001edeRalf Habacker dbus_bool_t need_unlink; 225413c3537b8730940d516af4823e83ac8df001edeRalf Habacker dbus_bool_t retval; 226413c3537b8730940d516af4823e83ac8df001edeRalf Habacker 227413c3537b8730940d516af4823e83ac8df001edeRalf Habacker _DBUS_ASSERT_ERROR_IS_CLEAR (error); 228413c3537b8730940d516af4823e83ac8df001edeRalf Habacker 2296e214b5b3c283798b5743b4ebf7c9ec466fe3667Marcus Brinkmann hnd = INVALID_HANDLE_VALUE; 230413c3537b8730940d516af4823e83ac8df001edeRalf Habacker retval = FALSE; 231413c3537b8730940d516af4823e83ac8df001edeRalf Habacker need_unlink = FALSE; 232413c3537b8730940d516af4823e83ac8df001edeRalf Habacker 233413c3537b8730940d516af4823e83ac8df001edeRalf Habacker if (!_dbus_string_init (&tmp_filename)) 234413c3537b8730940d516af4823e83ac8df001edeRalf Habacker { 235413c3537b8730940d516af4823e83ac8df001edeRalf Habacker dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL); 236413c3537b8730940d516af4823e83ac8df001edeRalf Habacker return FALSE; 237413c3537b8730940d516af4823e83ac8df001edeRalf Habacker } 238413c3537b8730940d516af4823e83ac8df001edeRalf Habacker 239413c3537b8730940d516af4823e83ac8df001edeRalf Habacker if (!_dbus_string_copy (filename, 0, &tmp_filename, 0)) 240413c3537b8730940d516af4823e83ac8df001edeRalf Habacker { 241413c3537b8730940d516af4823e83ac8df001edeRalf Habacker dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL); 242413c3537b8730940d516af4823e83ac8df001edeRalf Habacker _dbus_string_free (&tmp_filename); 243413c3537b8730940d516af4823e83ac8df001edeRalf Habacker return FALSE; 244413c3537b8730940d516af4823e83ac8df001edeRalf Habacker } 245413c3537b8730940d516af4823e83ac8df001edeRalf Habacker 246413c3537b8730940d516af4823e83ac8df001edeRalf Habacker if (!_dbus_string_append (&tmp_filename, ".")) 247413c3537b8730940d516af4823e83ac8df001edeRalf Habacker { 248413c3537b8730940d516af4823e83ac8df001edeRalf Habacker dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL); 249413c3537b8730940d516af4823e83ac8df001edeRalf Habacker _dbus_string_free (&tmp_filename); 250413c3537b8730940d516af4823e83ac8df001edeRalf Habacker return FALSE; 251413c3537b8730940d516af4823e83ac8df001edeRalf Habacker } 252413c3537b8730940d516af4823e83ac8df001edeRalf Habacker 253413c3537b8730940d516af4823e83ac8df001edeRalf Habacker#define N_TMP_FILENAME_RANDOM_BYTES 8 254413c3537b8730940d516af4823e83ac8df001edeRalf Habacker if (!_dbus_generate_random_ascii (&tmp_filename, N_TMP_FILENAME_RANDOM_BYTES)) 255413c3537b8730940d516af4823e83ac8df001edeRalf Habacker { 256413c3537b8730940d516af4823e83ac8df001edeRalf Habacker dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL); 257413c3537b8730940d516af4823e83ac8df001edeRalf Habacker _dbus_string_free (&tmp_filename); 258413c3537b8730940d516af4823e83ac8df001edeRalf Habacker return FALSE; 259413c3537b8730940d516af4823e83ac8df001edeRalf Habacker } 260413c3537b8730940d516af4823e83ac8df001edeRalf Habacker 261413c3537b8730940d516af4823e83ac8df001edeRalf Habacker filename_c = _dbus_string_get_const_data (filename); 262413c3537b8730940d516af4823e83ac8df001edeRalf Habacker tmp_filename_c = _dbus_string_get_const_data (&tmp_filename); 263413c3537b8730940d516af4823e83ac8df001edeRalf Habacker 26445d53565bc13678d6aa5edec1d4efb5bf8a64e0bColin Walters /* TODO - support world-readable in an atomic fashion */ 2656e214b5b3c283798b5743b4ebf7c9ec466fe3667Marcus Brinkmann hnd = CreateFileA (tmp_filename_c, GENERIC_WRITE, 2666e214b5b3c283798b5743b4ebf7c9ec466fe3667Marcus Brinkmann FILE_SHARE_READ | FILE_SHARE_WRITE, 2676e214b5b3c283798b5743b4ebf7c9ec466fe3667Marcus Brinkmann NULL, CREATE_NEW, FILE_ATTRIBUTE_NORMAL, 2686e214b5b3c283798b5743b4ebf7c9ec466fe3667Marcus Brinkmann INVALID_HANDLE_VALUE); 2696e214b5b3c283798b5743b4ebf7c9ec466fe3667Marcus Brinkmann if (hnd == INVALID_HANDLE_VALUE) 270413c3537b8730940d516af4823e83ac8df001edeRalf Habacker { 2716e214b5b3c283798b5743b4ebf7c9ec466fe3667Marcus Brinkmann char *emsg = _dbus_win_error_string (GetLastError ()); 2726e214b5b3c283798b5743b4ebf7c9ec466fe3667Marcus Brinkmann dbus_set_error (error, _dbus_win_error_from_last_error (), 2736e214b5b3c283798b5743b4ebf7c9ec466fe3667Marcus Brinkmann "Could not create \"%s\": %s", filename_c, emsg); 2746e214b5b3c283798b5743b4ebf7c9ec466fe3667Marcus Brinkmann _dbus_win_free_error_string (emsg); 275413c3537b8730940d516af4823e83ac8df001edeRalf Habacker goto out; 276413c3537b8730940d516af4823e83ac8df001edeRalf Habacker } 27745d53565bc13678d6aa5edec1d4efb5bf8a64e0bColin Walters if (world_readable) 27845d53565bc13678d6aa5edec1d4efb5bf8a64e0bColin Walters _dbus_make_file_world_readable (tmp_filename_c); 279413c3537b8730940d516af4823e83ac8df001edeRalf Habacker 280e419a5cff71bf71c626223393692c341f3db35e9Marcus Brinkmann _dbus_verbose ("tmp file %s hnd %p opened\n", tmp_filename_c, hnd); 281413c3537b8730940d516af4823e83ac8df001edeRalf Habacker 282413c3537b8730940d516af4823e83ac8df001edeRalf Habacker need_unlink = TRUE; 283413c3537b8730940d516af4823e83ac8df001edeRalf Habacker 284413c3537b8730940d516af4823e83ac8df001edeRalf Habacker total = 0; 285413c3537b8730940d516af4823e83ac8df001edeRalf Habacker bytes_to_write = _dbus_string_get_length (str); 286413c3537b8730940d516af4823e83ac8df001edeRalf Habacker str_c = _dbus_string_get_const_data (str); 287413c3537b8730940d516af4823e83ac8df001edeRalf Habacker 288413c3537b8730940d516af4823e83ac8df001edeRalf Habacker while (total < bytes_to_write) 289413c3537b8730940d516af4823e83ac8df001edeRalf Habacker { 2906e214b5b3c283798b5743b4ebf7c9ec466fe3667Marcus Brinkmann DWORD bytes_written; 2916e214b5b3c283798b5743b4ebf7c9ec466fe3667Marcus Brinkmann BOOL res; 292413c3537b8730940d516af4823e83ac8df001edeRalf Habacker 2936e214b5b3c283798b5743b4ebf7c9ec466fe3667Marcus Brinkmann res = WriteFile (hnd, str_c + total, bytes_to_write - total, 2946e214b5b3c283798b5743b4ebf7c9ec466fe3667Marcus Brinkmann &bytes_written, NULL); 295413c3537b8730940d516af4823e83ac8df001edeRalf Habacker 2966e214b5b3c283798b5743b4ebf7c9ec466fe3667Marcus Brinkmann if (res == 0 || bytes_written <= 0) 297413c3537b8730940d516af4823e83ac8df001edeRalf Habacker { 2986e214b5b3c283798b5743b4ebf7c9ec466fe3667Marcus Brinkmann char *emsg = _dbus_win_error_string (GetLastError ()); 2996e214b5b3c283798b5743b4ebf7c9ec466fe3667Marcus Brinkmann dbus_set_error (error, _dbus_win_error_from_last_error (), 3006e214b5b3c283798b5743b4ebf7c9ec466fe3667Marcus Brinkmann "Could not write to %s: %s", tmp_filename_c, emsg); 3016e214b5b3c283798b5743b4ebf7c9ec466fe3667Marcus Brinkmann _dbus_win_free_error_string (emsg); 302413c3537b8730940d516af4823e83ac8df001edeRalf Habacker goto out; 303413c3537b8730940d516af4823e83ac8df001edeRalf Habacker } 304413c3537b8730940d516af4823e83ac8df001edeRalf Habacker 305413c3537b8730940d516af4823e83ac8df001edeRalf Habacker total += bytes_written; 306413c3537b8730940d516af4823e83ac8df001edeRalf Habacker } 307413c3537b8730940d516af4823e83ac8df001edeRalf Habacker 3086e214b5b3c283798b5743b4ebf7c9ec466fe3667Marcus Brinkmann if (CloseHandle (hnd) == 0) 309413c3537b8730940d516af4823e83ac8df001edeRalf Habacker { 3106e214b5b3c283798b5743b4ebf7c9ec466fe3667Marcus Brinkmann char *emsg = _dbus_win_error_string (GetLastError ()); 3116e214b5b3c283798b5743b4ebf7c9ec466fe3667Marcus Brinkmann dbus_set_error (error, _dbus_win_error_from_last_error (), 3126e214b5b3c283798b5743b4ebf7c9ec466fe3667Marcus Brinkmann "Could not close file %s: %s", tmp_filename_c, emsg); 3136e214b5b3c283798b5743b4ebf7c9ec466fe3667Marcus Brinkmann _dbus_win_free_error_string (emsg); 314413c3537b8730940d516af4823e83ac8df001edeRalf Habacker goto out; 315413c3537b8730940d516af4823e83ac8df001edeRalf Habacker } 316413c3537b8730940d516af4823e83ac8df001edeRalf Habacker 3176e214b5b3c283798b5743b4ebf7c9ec466fe3667Marcus Brinkmann hnd = INVALID_HANDLE_VALUE; 318413c3537b8730940d516af4823e83ac8df001edeRalf Habacker 319413c3537b8730940d516af4823e83ac8df001edeRalf Habacker /* Unlike rename(), MoveFileEx() can replace existing files */ 320378e090e71b1b34227453727354783a173049df4Marcus Brinkmann if (!MoveFileExA (tmp_filename_c, filename_c, MOVEFILE_REPLACE_EXISTING)) 321413c3537b8730940d516af4823e83ac8df001edeRalf Habacker { 322413c3537b8730940d516af4823e83ac8df001edeRalf Habacker char *emsg = _dbus_win_error_string (GetLastError ()); 3236e214b5b3c283798b5743b4ebf7c9ec466fe3667Marcus Brinkmann dbus_set_error (error, _dbus_win_error_from_last_error (), 3246e214b5b3c283798b5743b4ebf7c9ec466fe3667Marcus Brinkmann "Could not rename %s to %s: %s", 3256e214b5b3c283798b5743b4ebf7c9ec466fe3667Marcus Brinkmann tmp_filename_c, filename_c, emsg); 326413c3537b8730940d516af4823e83ac8df001edeRalf Habacker _dbus_win_free_error_string (emsg); 327413c3537b8730940d516af4823e83ac8df001edeRalf Habacker 328413c3537b8730940d516af4823e83ac8df001edeRalf Habacker goto out; 329413c3537b8730940d516af4823e83ac8df001edeRalf Habacker } 330413c3537b8730940d516af4823e83ac8df001edeRalf Habacker 331413c3537b8730940d516af4823e83ac8df001edeRalf Habacker need_unlink = FALSE; 332413c3537b8730940d516af4823e83ac8df001edeRalf Habacker 333413c3537b8730940d516af4823e83ac8df001edeRalf Habacker retval = TRUE; 334413c3537b8730940d516af4823e83ac8df001edeRalf Habacker 335413c3537b8730940d516af4823e83ac8df001edeRalf Habacker out: 336413c3537b8730940d516af4823e83ac8df001edeRalf Habacker /* close first, then unlink */ 337413c3537b8730940d516af4823e83ac8df001edeRalf Habacker 3386e214b5b3c283798b5743b4ebf7c9ec466fe3667Marcus Brinkmann if (hnd != INVALID_HANDLE_VALUE) 3396e214b5b3c283798b5743b4ebf7c9ec466fe3667Marcus Brinkmann CloseHandle (hnd); 340413c3537b8730940d516af4823e83ac8df001edeRalf Habacker 3416e214b5b3c283798b5743b4ebf7c9ec466fe3667Marcus Brinkmann if (need_unlink && DeleteFileA (tmp_filename_c) == 0) 3426e214b5b3c283798b5743b4ebf7c9ec466fe3667Marcus Brinkmann { 3436e214b5b3c283798b5743b4ebf7c9ec466fe3667Marcus Brinkmann char *emsg = _dbus_win_error_string (GetLastError ()); 3446e214b5b3c283798b5743b4ebf7c9ec466fe3667Marcus Brinkmann _dbus_verbose ("Failed to unlink temp file %s: %s", tmp_filename_c, 3456e214b5b3c283798b5743b4ebf7c9ec466fe3667Marcus Brinkmann emsg); 3466e214b5b3c283798b5743b4ebf7c9ec466fe3667Marcus Brinkmann _dbus_win_free_error_string (emsg); 3476e214b5b3c283798b5743b4ebf7c9ec466fe3667Marcus Brinkmann } 348413c3537b8730940d516af4823e83ac8df001edeRalf Habacker 349413c3537b8730940d516af4823e83ac8df001edeRalf Habacker _dbus_string_free (&tmp_filename); 350413c3537b8730940d516af4823e83ac8df001edeRalf Habacker 351413c3537b8730940d516af4823e83ac8df001edeRalf Habacker if (!retval) 352413c3537b8730940d516af4823e83ac8df001edeRalf Habacker _DBUS_ASSERT_ERROR_IS_SET (error); 353413c3537b8730940d516af4823e83ac8df001edeRalf Habacker 354413c3537b8730940d516af4823e83ac8df001edeRalf Habacker return retval; 355413c3537b8730940d516af4823e83ac8df001edeRalf Habacker} 356413c3537b8730940d516af4823e83ac8df001edeRalf Habacker 357413c3537b8730940d516af4823e83ac8df001edeRalf Habacker 358413c3537b8730940d516af4823e83ac8df001edeRalf Habacker/** Creates the given file, failing if the file already exists. 359413c3537b8730940d516af4823e83ac8df001edeRalf Habacker * 360413c3537b8730940d516af4823e83ac8df001edeRalf Habacker * @param filename the filename 361413c3537b8730940d516af4823e83ac8df001edeRalf Habacker * @param error error location 362413c3537b8730940d516af4823e83ac8df001edeRalf Habacker * @returns #TRUE if we created the file and it didn't exist 363413c3537b8730940d516af4823e83ac8df001edeRalf Habacker */ 364413c3537b8730940d516af4823e83ac8df001edeRalf Habackerdbus_bool_t 365413c3537b8730940d516af4823e83ac8df001edeRalf Habacker_dbus_create_file_exclusively (const DBusString *filename, 366413c3537b8730940d516af4823e83ac8df001edeRalf Habacker DBusError *error) 367413c3537b8730940d516af4823e83ac8df001edeRalf Habacker{ 3686e214b5b3c283798b5743b4ebf7c9ec466fe3667Marcus Brinkmann HANDLE hnd; 369413c3537b8730940d516af4823e83ac8df001edeRalf Habacker const char *filename_c; 370413c3537b8730940d516af4823e83ac8df001edeRalf Habacker 371413c3537b8730940d516af4823e83ac8df001edeRalf Habacker _DBUS_ASSERT_ERROR_IS_CLEAR (error); 372413c3537b8730940d516af4823e83ac8df001edeRalf Habacker 373413c3537b8730940d516af4823e83ac8df001edeRalf Habacker filename_c = _dbus_string_get_const_data (filename); 374413c3537b8730940d516af4823e83ac8df001edeRalf Habacker 3756e214b5b3c283798b5743b4ebf7c9ec466fe3667Marcus Brinkmann hnd = CreateFileA (filename_c, GENERIC_WRITE, 3766e214b5b3c283798b5743b4ebf7c9ec466fe3667Marcus Brinkmann FILE_SHARE_READ | FILE_SHARE_WRITE, 3776e214b5b3c283798b5743b4ebf7c9ec466fe3667Marcus Brinkmann NULL, CREATE_NEW, FILE_ATTRIBUTE_NORMAL, 3786e214b5b3c283798b5743b4ebf7c9ec466fe3667Marcus Brinkmann INVALID_HANDLE_VALUE); 3796e214b5b3c283798b5743b4ebf7c9ec466fe3667Marcus Brinkmann if (hnd == INVALID_HANDLE_VALUE) 380413c3537b8730940d516af4823e83ac8df001edeRalf Habacker { 3816e214b5b3c283798b5743b4ebf7c9ec466fe3667Marcus Brinkmann char *emsg = _dbus_win_error_string (GetLastError ()); 3826e214b5b3c283798b5743b4ebf7c9ec466fe3667Marcus Brinkmann dbus_set_error (error, _dbus_win_error_from_last_error (), 3836e214b5b3c283798b5743b4ebf7c9ec466fe3667Marcus Brinkmann "Could not create file %s: %s", 3846e214b5b3c283798b5743b4ebf7c9ec466fe3667Marcus Brinkmann filename_c, emsg); 3856e214b5b3c283798b5743b4ebf7c9ec466fe3667Marcus Brinkmann _dbus_win_free_error_string (emsg); 386413c3537b8730940d516af4823e83ac8df001edeRalf Habacker return FALSE; 387413c3537b8730940d516af4823e83ac8df001edeRalf Habacker } 388413c3537b8730940d516af4823e83ac8df001edeRalf Habacker 389e419a5cff71bf71c626223393692c341f3db35e9Marcus Brinkmann _dbus_verbose ("exclusive file %s hnd %p opened\n", filename_c, hnd); 390413c3537b8730940d516af4823e83ac8df001edeRalf Habacker 3916e214b5b3c283798b5743b4ebf7c9ec466fe3667Marcus Brinkmann if (CloseHandle (hnd) == 0) 392413c3537b8730940d516af4823e83ac8df001edeRalf Habacker { 3936e214b5b3c283798b5743b4ebf7c9ec466fe3667Marcus Brinkmann char *emsg = _dbus_win_error_string (GetLastError ()); 3946e214b5b3c283798b5743b4ebf7c9ec466fe3667Marcus Brinkmann dbus_set_error (error, _dbus_win_error_from_last_error (), 3956e214b5b3c283798b5743b4ebf7c9ec466fe3667Marcus Brinkmann "Could not close file %s: %s", 3966e214b5b3c283798b5743b4ebf7c9ec466fe3667Marcus Brinkmann filename_c, emsg); 3976e214b5b3c283798b5743b4ebf7c9ec466fe3667Marcus Brinkmann _dbus_win_free_error_string (emsg); 3986e214b5b3c283798b5743b4ebf7c9ec466fe3667Marcus Brinkmann 399413c3537b8730940d516af4823e83ac8df001edeRalf Habacker return FALSE; 400413c3537b8730940d516af4823e83ac8df001edeRalf Habacker } 401413c3537b8730940d516af4823e83ac8df001edeRalf Habacker 402413c3537b8730940d516af4823e83ac8df001edeRalf Habacker return TRUE; 403413c3537b8730940d516af4823e83ac8df001edeRalf Habacker} 404413c3537b8730940d516af4823e83ac8df001edeRalf Habacker 405