15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved.
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file.
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/tools/dump_cache/cache_dumper.h"
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
71320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "base/files/file_util.h"
8868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/strings/utf_string_conversions.h"
95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/base/io_buffer.h"
105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/base/net_errors.h"
11a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include "net/disk_cache/blockfile/entry_impl.h"
125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/http/http_cache.h"
135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/http/http_response_headers.h"
145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/http/http_response_info.h"
155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/tools/dump_cache/url_to_filename_encoder.h"
165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)CacheDumper::CacheDumper(disk_cache::Backend* cache)
182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    : cache_(cache) {
192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int CacheDumper::CreateEntry(const std::string& key,
225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                             disk_cache::Entry** entry,
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                             const net::CompletionCallback& callback) {
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return cache_->CreateEntry(key, entry, callback);
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int CacheDumper::WriteEntry(disk_cache::Entry* entry, int index, int offset,
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                            net::IOBuffer* buf, int buf_len,
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                            const net::CompletionCallback& callback) {
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return entry->WriteData(index, offset, buf, buf_len, callback, false);
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void CacheDumper::CloseEntry(disk_cache::Entry* entry, base::Time last_used,
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                             base::Time last_modified) {
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (entry) {
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    static_cast<disk_cache::EntryImpl*>(entry)->SetTimes(last_used,
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                                         last_modified);
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    entry->Close();
395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// A version of CreateDirectory which supports lengthy filenames.
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Returns true on success, false on failure.
442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)bool SafeCreateDirectory(const base::FilePath& path) {
455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef WIN32_LARGE_FILENAME_SUPPORT
465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Due to large paths on windows, it can't simply do a
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // CreateDirectory("a/b/c").  Instead, create each subdirectory manually.
485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool rv = false;
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::wstring::size_type pos(0);
505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::wstring backslash(L"\\");
515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // If the path starts with the long file header, skip over that
535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const std::wstring kLargeFilenamePrefix(L"\\\\?\\");
545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::wstring header(kLargeFilenamePrefix);
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (path.value().find(header) == 0)
565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    pos = 4;
575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Create the subdirectories individually
595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  while ((pos = path.value().find(backslash, pos)) != std::wstring::npos) {
602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    base::FilePath::StringType subdir = path.value().substr(0, pos);
615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CreateDirectoryW(subdir.c_str(), NULL);
625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // we keep going even if directory creation failed.
635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    pos++;
645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Now create the full path
665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return CreateDirectoryW(path.value().c_str(), NULL) == TRUE;
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#else
68a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  return base::CreateDirectory(path);
695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)DiskDumper::DiskDumper(const base::FilePath& path)
732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    : path_(path), entry_(NULL) {
74a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  base::CreateDirectory(path);
752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int DiskDumper::CreateEntry(const std::string& key,
785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                            disk_cache::Entry** entry,
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                            const net::CompletionCallback& callback) {
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // The URL may not start with a valid protocol; search for it.
815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int urlpos = key.find("http");
825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string url = urlpos > 0 ? key.substr(urlpos) : key;
832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  std::string base_path = path_.MaybeAsASCII();
845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string new_path =
855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      net::UrlToFilenameEncoder::Encode(url, base_path, false);
862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  entry_path_ = base::FilePath::FromUTF8Unsafe(new_path);
875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef WIN32_LARGE_FILENAME_SUPPORT
895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // In order for long filenames to work, we'll need to prepend
905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // the windows magic token.
915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const std::wstring kLongFilenamePrefix(L"\\\\?\\");
925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // There is no way to prepend to a filename.  We simply *have*
935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // to convert to a wstring to do this.
945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::wstring name = kLongFilenamePrefix;
955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  name.append(entry_path_.value());
962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  entry_path_ = base::FilePath(name);
975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  entry_url_ = key;
1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SafeCreateDirectory(entry_path_.DirName());
1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  base::FilePath::StringType file = entry_path_.value();
1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef WIN32_LARGE_FILENAME_SUPPORT
1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  entry_ = CreateFileW(file.c_str(), GENERIC_WRITE|GENERIC_READ, 0, 0,
1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                       CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, 0);
1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (entry_ == INVALID_HANDLE_VALUE)
1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    wprintf(L"CreateFileW (%s) failed: %d\n", file.c_str(), GetLastError());
1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return (entry_ != INVALID_HANDLE_VALUE) ? net::OK : net::ERR_FAILED;
1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#else
111a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  entry_ = base::OpenFile(entry_path_, "w+");
1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return (entry_ != NULL) ? net::OK : net::ERR_FAILED;
1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Utility Function to create a normalized header string from a
1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// HttpResponseInfo.  The output will be formatted exactly
1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// like so:
1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//     HTTP/<version> <status_code> <status_text>\n
1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//     [<header-name>: <header-values>\n]*
1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// meaning, each line is \n-terminated, and there is no extra whitespace
1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// beyond the single space separators shown (of course, values can contain
1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// whitespace within them).  If a given header-name appears more than once
1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// in the set of headers, they are combined into a single line like so:
1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//     <header-name>: <header-value1>, <header-value2>, ...<header-valueN>\n
1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//
1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// DANGER: For some headers (e.g., "Set-Cookie"), the normalized form can be
1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// a lossy format.  This is due to the fact that some servers generate
1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Set-Cookie headers that contain unquoted commas (usually as part of the
1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// value of an "expires" attribute).  So, use this function with caution.  Do
1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// not expect to be able to re-parse Set-Cookie headers from this output.
1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//
1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// NOTE: Do not make any assumptions about the encoding of this output
1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// string.  It may be non-ASCII, and the encoding used by the server is not
1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// necessarily known to us.  Do not assume that this output is UTF-8!
1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void GetNormalizedHeaders(const net::HttpResponseInfo& info,
1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                          std::string* output) {
1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Start with the status line
1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  output->assign(info.headers->GetStatusLine());
1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  output->append("\r\n");
1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Enumerate the headers
1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void* iter = 0;
1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string name, value;
1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  while (info.headers->EnumerateHeaderLines(&iter, &name, &value)) {
1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    output->append(name);
1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    output->append(": ");
1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    output->append(value);
1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    output->append("\r\n");
1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Mark the end of headers
1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  output->append("\r\n");
1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int DiskDumper::WriteEntry(disk_cache::Entry* entry, int index, int offset,
1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                           net::IOBuffer* buf, int buf_len,
1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                           const net::CompletionCallback& callback) {
1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!entry_)
1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return 0;
1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string headers;
1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const char *data;
1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  size_t len;
1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (index == 0) {  // Stream 0 is the headers.
1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    net::HttpResponseInfo response_info;
1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    bool truncated;
1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!net::HttpCache::ParseResponseInfo(buf->data(), buf_len,
1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                           &response_info, &truncated))
1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return 0;
1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Skip this entry if it was truncated (results in an empty file).
1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (truncated)
1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return buf_len;
1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Remove the size headers.
1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    response_info.headers->RemoveHeader("transfer-encoding");
1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    response_info.headers->RemoveHeader("content-length");
1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    response_info.headers->RemoveHeader("x-original-url");
1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Convert the headers into a string ending with LF.
1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    GetNormalizedHeaders(response_info, &headers);
1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Append a header for the original URL.
1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    std::string url = entry_url_;
1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // strip off the "XXGET" which may be in the key.
1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    std::string::size_type pos(0);
1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if ((pos = url.find("http")) != 0) {
1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (pos != std::string::npos)
1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        url = url.substr(pos);
1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    std::string x_original_url = "X-Original-Url: " + url + "\r\n";
1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // we know that the last two bytes are CRLF.
1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    headers.replace(headers.length() - 2, 0, x_original_url);
1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    data = headers.c_str();
1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    len = headers.size();
1982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  } else if (index == 1) {
1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    data = buf->data();
2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    len = buf_len;
2012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  } else {
2022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return 0;
2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef WIN32_LARGE_FILENAME_SUPPORT
2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DWORD bytes;
2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!WriteFile(entry_, data, len, &bytes, 0))
2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return 0;
2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return bytes;
2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#else
2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return fwrite(data, 1, len, entry_);
2135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void DiskDumper::CloseEntry(disk_cache::Entry* entry, base::Time last_used,
2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                          base::Time last_modified) {
2185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef WIN32_LARGE_FILENAME_SUPPORT
2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CloseHandle(entry_);
2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#else
221a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  base::CloseFile(entry_);
2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
2235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
224