• Main Page
  • Related Pages
  • Modules
  • Data Structures
  • Files
  • File List

dbus-file-win.c

00001 /* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
00002 /* dbus-file-win.c windows 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 #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       /* put length back (doesn't actually realloc) */
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   /* TODO - support world-readable in an atomic fashion */
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     _dbus_make_file_world_readable (tmp_filename_c);
00279 
00280   _dbus_verbose ("tmp file %s hnd %p opened\n", tmp_filename_c, hnd);
00281 
00282   need_unlink = TRUE;
00283 
00284   total = 0;
00285   bytes_to_write = _dbus_string_get_length (str);
00286   str_c = _dbus_string_get_const_data (str);
00287 
00288   while (total < bytes_to_write)
00289     {
00290       DWORD bytes_written;
00291       BOOL res;
00292 
00293       res = WriteFile (hnd, str_c + total, bytes_to_write - total,
00294                        &bytes_written, NULL);
00295 
00296       if (res == 0 || bytes_written <= 0)
00297         {
00298           char *emsg = _dbus_win_error_string (GetLastError ());
00299           dbus_set_error (error, _dbus_win_error_from_last_error (),
00300                            "Could not write to %s: %s", tmp_filename_c, emsg);
00301           _dbus_win_free_error_string (emsg);
00302           goto out;
00303         }
00304 
00305       total += bytes_written;
00306     }
00307 
00308   if (CloseHandle (hnd) == 0)
00309     {
00310       char *emsg = _dbus_win_error_string (GetLastError ());
00311       dbus_set_error (error, _dbus_win_error_from_last_error (),
00312                        "Could not close file %s: %s", tmp_filename_c, emsg);
00313       _dbus_win_free_error_string (emsg);
00314       goto out;
00315     }
00316 
00317   hnd = INVALID_HANDLE_VALUE;
00318 
00319   /* Unlike rename(), MoveFileEx() can replace existing files */
00320   if (!MoveFileExA (tmp_filename_c, filename_c, MOVEFILE_REPLACE_EXISTING))
00321     {
00322       char *emsg = _dbus_win_error_string (GetLastError ());
00323       dbus_set_error (error, _dbus_win_error_from_last_error (),
00324                        "Could not rename %s to %s: %s",
00325                        tmp_filename_c, filename_c, emsg);
00326       _dbus_win_free_error_string (emsg);
00327 
00328       goto out;
00329     }
00330 
00331   need_unlink = FALSE;
00332 
00333   retval = TRUE;
00334 
00335  out:
00336   /* close first, then unlink */
00337 
00338   if (hnd != INVALID_HANDLE_VALUE)
00339     CloseHandle (hnd);
00340 
00341   if (need_unlink && DeleteFileA (tmp_filename_c) == 0)
00342     {
00343       char *emsg = _dbus_win_error_string (GetLastError ());
00344       _dbus_verbose ("Failed to unlink temp file %s: %s", tmp_filename_c,
00345                      emsg);
00346       _dbus_win_free_error_string (emsg);
00347     }
00348 
00349   _dbus_string_free (&tmp_filename);
00350 
00351   if (!retval)
00352     _DBUS_ASSERT_ERROR_IS_SET (error);
00353 
00354   return retval;
00355 }
00356 
00357 
00364 dbus_bool_t
00365 _dbus_create_file_exclusively (const DBusString *filename,
00366                                DBusError        *error)
00367 {
00368   HANDLE hnd;
00369   const char *filename_c;
00370 
00371   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
00372 
00373   filename_c = _dbus_string_get_const_data (filename);
00374 
00375   hnd = CreateFileA (filename_c, GENERIC_WRITE,
00376                      FILE_SHARE_READ | FILE_SHARE_WRITE,
00377                      NULL, CREATE_NEW, FILE_ATTRIBUTE_NORMAL,
00378                      INVALID_HANDLE_VALUE);
00379   if (hnd == INVALID_HANDLE_VALUE)
00380     {
00381       char *emsg = _dbus_win_error_string (GetLastError ());
00382       dbus_set_error (error, _dbus_win_error_from_last_error (),
00383                        "Could not create file %s: %s",
00384                        filename_c, emsg);
00385       _dbus_win_free_error_string (emsg);
00386       return FALSE;
00387     }
00388 
00389   _dbus_verbose ("exclusive file %s hnd %p opened\n", filename_c, hnd);
00390 
00391   if (CloseHandle (hnd) == 0)
00392     {
00393       char *emsg = _dbus_win_error_string (GetLastError ());
00394       dbus_set_error (error, _dbus_win_error_from_last_error (),
00395                        "Could not close file %s: %s",
00396                        filename_c, emsg);
00397       _dbus_win_free_error_string (emsg);
00398 
00399       return FALSE;
00400     }
00401 
00402   return TRUE;
00403 }
00404 

Generated on Fri Jul 22 2011 16:59:34 for D-Bus by  doxygen 1.7.1