Coverage for /Syzygy/msf/msf_reader_impl.h

CoverageLines executed / instrumented / missingexe / inst / missLanguageGroup
75.4%49650.C++source

Line-by-line coverage:

   1    :  // Copyright 2012 Google Inc. All Rights Reserved.
   2    :  //
   3    :  // Licensed under the Apache License, Version 2.0 (the "License");
   4    :  // you may not use this file except in compliance with the License.
   5    :  // You may obtain a copy of the License at
   6    :  //
   7    :  //     http://www.apache.org/licenses/LICENSE-2.0
   8    :  //
   9    :  // Unless required by applicable law or agreed to in writing, software
  10    :  // distributed under the License is distributed on an "AS IS" BASIS,
  11    :  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12    :  // See the License for the specific language governing permissions and
  13    :  // limitations under the License.
  14    :  //
  15    :  // Internal implementation details for msf_reader.h. Not meant to be included
  16    :  // directly.
  17    :  
  18    :  #ifndef SYZYGY_MSF_MSF_READER_IMPL_H_
  19    :  #define SYZYGY_MSF_MSF_READER_IMPL_H_
  20    :  
  21    :  #include <cstdio>
  22    :  #include <cstring>
  23    :  #include <vector>
  24    :  
  25    :  #include "base/logging.h"
  26    :  #include "base/memory/ref_counted.h"
  27    :  #include "base/strings/string_util.h"
  28    :  #include "syzygy/msf/msf_data.h"
  29    :  #include "syzygy/msf/msf_file_stream.h"
  30    :  
  31    :  namespace msf {
  32    :  namespace detail {
  33    :  
  34    :  namespace {
  35    :  
  36  E :  bool GetFileSize(FILE* file, uint32* size) {
  37  E :    DCHECK(file != NULL);
  38  E :    DCHECK(size != NULL);
  39    :  
  40  E :    if (fseek(file, 0, SEEK_END) != 0) {
  41  i :      LOG(ERROR) << "Failed seeking to end of file.";
  42  i :      return false;
  43    :    }
  44    :  
  45  E :    long temp = ftell(file);
  46  E :    if (temp == -1L) {
  47  i :      LOG(ERROR) << "Failed to read stream position.";
  48  i :      return false;
  49    :    }
  50  E :    DCHECK_GT(temp, 0);
  51    :  
  52  E :    (*size) = static_cast<uint32>(temp);
  53  E :    return true;
  54  E :  }
  55    :  
  56  E :  uint32 GetNumPages(const MsfHeader& header, uint32 num_bytes) {
  57  E :    return (num_bytes + header.page_size - 1) / header.page_size;
  58  E :  }
  59    :  
  60    :  }  // namespace
  61    :  
  62    :  template <MsfFileType T>
  63    :  bool MsfReaderImpl<T>::Read(const base::FilePath& msf_path,
  64  E :                              MsfFileImpl<T>* msf_file) {
  65  E :    DCHECK(msf_file != NULL);
  66    :  
  67  E :    msf_file->Clear();
  68    :  
  69    :    scoped_refptr<RefCountedFILE> file(
  70  E :        new RefCountedFILE(base::OpenFile(msf_path, "rb")));
  71  E :    if (!file->file()) {
  72  E :      LOG(ERROR) << "Unable to open '" << msf_path.value() << "'.";
  73  E :      return false;
  74    :    }
  75    :  
  76    :    // Get the file size.
  77  E :    uint32 file_size = 0;
  78  E :    if (!GetFileSize(file->file(), &file_size)) {
  79  i :      LOG(ERROR) << "Unable to determine size of '" << msf_path.value() << "'.";
  80  i :      return false;
  81    :    }
  82    :  
  83  E :    MsfHeader header = {0};
  84    :  
  85    :    // Read the header from the first page in the file. The page size we use here
  86    :    // is irrelevant as after reading the header we get the actual page size in
  87    :    // use by the MSF and from then on use that.
  88  E :    uint32 header_page = 0;
  89    :    scoped_refptr<MsfFileStreamImpl<T>> header_stream(new MsfFileStreamImpl<T>(
  90  E :        file.get(), sizeof(header), &header_page, kMsfPageSize));
  91  E :    if (!header_stream->Read(&header, 1)) {
  92  i :      LOG(ERROR) << "Failed to read MSF file header.";
  93  i :      return false;
  94    :    }
  95    :  
  96    :    // Sanity checks.
  97  E :    if (header.num_pages * header.page_size != file_size) {
  98  E :      LOG(ERROR) << "Invalid MSF file size.";
  99  E :      return false;
 100    :    }
 101    :  
 102    :    if (memcmp(header.magic_string, kMsfHeaderMagicString,
 103  E :               sizeof(kMsfHeaderMagicString)) != 0) {
 104  i :      LOG(ERROR) << "Invalid MSF magic string.";
 105  i :      return false;
 106    :    }
 107    :  
 108    :    // Load the directory page list (a sequence of uint32 page numbers that is
 109    :    // itself written across multiple root pages). To do this we need to know how
 110    :    // many pages are required to represent the directory, then we load a stream
 111    :    // containing that many page pointers from the root pages array.
 112    :    int num_dir_pages =
 113  E :        static_cast<int>(GetNumPages(header, header.directory_size));
 114    :    scoped_refptr<MsfFileStreamImpl<T>> dir_page_stream(
 115    :        new MsfFileStreamImpl<T>(file.get(), num_dir_pages * sizeof(uint32),
 116  E :                                 header.root_pages, header.page_size));
 117  E :    scoped_ptr<uint32[]> dir_pages(new uint32[num_dir_pages]);
 118  E :    if (dir_pages.get() == NULL) {
 119  i :      LOG(ERROR) << "Failed to allocate directory pages.";
 120  i :      return false;
 121    :    }
 122  E :    if (!dir_page_stream->Read(dir_pages.get(), num_dir_pages)) {
 123  i :      LOG(ERROR) << "Failed to read directory page stream.";
 124  i :      return false;
 125    :    }
 126    :  
 127    :    // Load the actual directory.
 128  E :    int dir_size = static_cast<int>(header.directory_size / sizeof(uint32));
 129    :    scoped_refptr<MsfFileStreamImpl<T>> dir_stream(new MsfFileStreamImpl<T>(
 130  E :        file.get(), header.directory_size, dir_pages.get(), header.page_size));
 131  E :    std::vector<uint32> directory(dir_size);
 132  E :    if (!dir_stream->Read(&directory[0], dir_size)) {
 133  i :      LOG(ERROR) << "Failed to read directory stream.";
 134  i :      return false;
 135    :    }
 136    :  
 137    :    // Iterate through the streams and construct MsfStreams.
 138  E :    const uint32& num_streams = directory[0];
 139  E :    const uint32* stream_lengths = &(directory[1]);
 140  E :    const uint32* stream_pages = &(directory[1 + num_streams]);
 141    :  
 142  E :    uint32 page_index = 0;
 143  E :    for (uint32 stream_index = 0; stream_index < num_streams; ++stream_index) {
 144    :      msf_file->AppendStream(
 145    :          new MsfFileStreamImpl<T>(file.get(), stream_lengths[stream_index],
 146  E :                                   stream_pages + page_index, header.page_size));
 147  E :      page_index += GetNumPages(header, stream_lengths[stream_index]);
 148  E :    }
 149    :  
 150  E :    return true;
 151  E :  }
 152    :  
 153    :  }  // namespace detail
 154    :  }  // namespace msf
 155    :  
 156    :  #endif  // SYZYGY_MSF_MSF_READER_IMPL_H_

Coverage information generated Thu Jan 14 17:40:38 2016.