adlr@google.com | 3defe6a | 2009-12-04 20:57:17 +0000 | [diff] [blame^] | 1 | // Copyright (c) 2009 The Chromium Authors. All rights reserved. |
| 2 | // Use of this source code is governed by a BSD-style license that can be |
| 3 | // found in the LICENSE file. |
| 4 | |
| 5 | #ifndef CHROMEOS_PLATFORM_UPDATE_ENGINE_DELTA_DIFF_PARSER_H__ |
| 6 | #define CHROMEOS_PLATFORM_UPDATE_ENGINE_DELTA_DIFF_PARSER_H__ |
| 7 | |
| 8 | #include <string> |
| 9 | #include <vector> |
| 10 | #include "chromeos/obsolete_logging.h" |
| 11 | #include "base/basictypes.h" |
| 12 | #include "update_engine/update_metadata.pb.h" |
| 13 | |
| 14 | // The DeltaDiffParser class is used to parse a delta file on disk. It will |
| 15 | // copy the metadata into memory, but not the file data. This class can |
| 16 | // also be used to copy file data out to disk. |
| 17 | |
| 18 | // The DeltaDiffParserIterator class is used to iterate through the |
| 19 | // metadata of a delta file. It will return directories before their |
| 20 | // children. |
| 21 | |
| 22 | namespace chromeos_update_engine { |
| 23 | |
| 24 | class DeltaDiffParser; |
| 25 | |
| 26 | class DeltaDiffParserIterator { |
| 27 | friend class DeltaDiffParser; |
| 28 | public: |
| 29 | void Increment(); |
| 30 | |
| 31 | // Returns the full path for the current file, e.g. "/bin/bash". |
| 32 | // Returns empty string for root. |
| 33 | const std::string& path() const { |
| 34 | return path_; |
| 35 | } |
| 36 | |
| 37 | // Returns the basename for the current file. If path() returns |
| 38 | // "/bin/bash", then GetName() returns "bash". |
| 39 | // Returns empty string for root |
| 40 | const std::string GetName() const; |
| 41 | |
| 42 | const DeltaArchiveManifest_File& GetFile() const; |
| 43 | bool operator==(const DeltaDiffParserIterator& that) const { |
| 44 | return path_indices_ == that.path_indices_ && |
| 45 | child_indices_ == that.child_indices_ && |
| 46 | path_ == that.path_ && |
| 47 | archive_ == that.archive_; |
| 48 | } |
| 49 | bool operator!=(const DeltaDiffParserIterator& that) const { |
| 50 | return !(*this == that); |
| 51 | } |
| 52 | private: |
| 53 | // Container of all the File messages. Each File message has an index |
| 54 | // in archive_. The root directory is always stored at index 0. |
| 55 | const DeltaArchiveManifest* archive_; |
| 56 | |
| 57 | // These variables are used to implement the common recursive depth-first |
| 58 | // search algorithm (which we can't use here, since we need to walk the |
| 59 | // tree incrementally). |
| 60 | |
| 61 | // Indices into 'archive_' of the current path components. For example, if |
| 62 | // the current path is "/bin/bash", 'path_stack_' will contain the archive |
| 63 | // indices for "/", "/bin", and "/bin/bash", in that order. This is |
| 64 | // analogous to the call stack of the recursive algorithm. |
| 65 | std::vector<int> path_indices_; |
| 66 | |
| 67 | // For each component in 'path_stack_', the currently-selected child in its |
| 68 | // child vector. In the previous example, if "/" has "abc" and "bin" |
| 69 | // subdirectories and "/bin" contains only "bash", this will contain |
| 70 | // [0, 1, 0], since we are using the 0th child at the root directory level |
| 71 | // (there's only one child there), the first of the root dir's children |
| 72 | // ("bin"), and the 0th child of /bin ("bash"). This is analogous to the |
| 73 | // state of each function (in terms of which child it's currently |
| 74 | // handling) in the call stack of the recursive algorithm. |
| 75 | std::vector<int> child_indices_; |
| 76 | |
| 77 | std::string path_; |
| 78 | // Instantiated by friend class DeltaDiffParser |
| 79 | explicit DeltaDiffParserIterator(const DeltaArchiveManifest* archive) |
| 80 | : archive_(archive) {} |
| 81 | DeltaDiffParserIterator() { |
| 82 | CHECK(false); // Should never be called. |
| 83 | } |
| 84 | }; |
| 85 | |
| 86 | class DeltaDiffParser { |
| 87 | public: |
| 88 | DeltaDiffParser(const std::string& delta_file); |
| 89 | ~DeltaDiffParser(); |
| 90 | bool valid() const { return valid_; } |
| 91 | bool ContainsPath(const std::string& path) const; |
| 92 | const DeltaArchiveManifest_File& GetFileAtPath(const std::string& path) const; |
| 93 | |
| 94 | // Reads length bytes at offset of the delta file into the out string |
| 95 | // or vector. Be careful not to call this with large length values, |
| 96 | // since that much memory will have to be allocated to store the output. |
| 97 | // Returns true on success. |
| 98 | bool ReadDataVector(off_t offset, off_t length, std::vector<char>* out) const; |
| 99 | |
| 100 | // Copies length bytes of data from offset into a new file at path specified. |
| 101 | // If should_decompress is true, will gzip decompress while writing to the |
| 102 | // file. Returns true on success. |
| 103 | bool CopyDataToFile(off_t offset, off_t length, bool should_decompress, |
| 104 | const std::string& path) const; |
| 105 | |
| 106 | typedef DeltaDiffParserIterator Iterator; |
| 107 | const Iterator Begin(); |
| 108 | const Iterator End(); |
| 109 | |
| 110 | // The identifier we expect at the beginning of a delta file. |
| 111 | static const char* const kFileMagic; |
| 112 | |
| 113 | private: |
| 114 | // (Binary) Searches the children of 'file' for one named child_name. |
| 115 | // If found, returns the index into the archive. If not found, returns -1. |
| 116 | int GetIndexOfFileChild(const DeltaArchiveManifest_File& file, |
| 117 | const std::string& child_name) const; |
| 118 | |
| 119 | // Returns -1 if not found, 0 for root |
| 120 | int GetIndexForPath(const std::string& path) const; |
| 121 | |
| 122 | // We keep a filedescriptor open to the delta file. |
| 123 | int fd_; |
| 124 | |
| 125 | DeltaArchiveManifest archive_; |
| 126 | bool valid_; |
| 127 | DISALLOW_COPY_AND_ASSIGN(DeltaDiffParser); |
| 128 | }; |
| 129 | |
| 130 | }; // namespace chromeos_update_engine |
| 131 | |
| 132 | #endif // CHROMEOS_PLATFORM_UPDATE_ENGINE_DELTA_DIFF_PARSER_H__ |