Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 2009 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 // Update file format: A delta update file contains all the deltas needed | 5 // Update file format: A delta update file contains all the deltas needed |
| 6 // to update a system from one specific version to another specific | 6 // to update a system from one specific version to another specific |
| 7 // version. The update format is represented by this struct pseudocode: | 7 // version. The update format is represented by this struct pseudocode: |
| 8 // struct delta_update_file { | 8 // struct delta_update_file { |
| 9 // char magic[4] = "CrAU"; | 9 // char magic[4] = "CrAU"; |
| 10 // uint64 bom_offset; // Offset of protobuf DeltaArchiveManifest | 10 // uint32 file_format_version = 1; |
| 11 // uint64 bom_size; // Sise of protobuf DeltaArchiveManifest | 11 // uint64 manifest_size; // Size of protobuf DeltaArchiveManifest |
| 12 // // The Bzip2 compressed DeltaArchiveManifest | |
| 13 // char manifest[]; | |
| 12 // | 14 // |
| 13 // // Data blobs for files, no specific format. The specific offset | 15 // // Data blobs for files, no specific format. The specific offset |
| 14 // // and length of each data blob is recorded in the DeltaArchiveManifest. | 16 // // and length of each data blob is recorded in the DeltaArchiveManifest. |
| 15 // struct { | 17 // struct { |
| 16 // char data[]; | 18 // char data[]; |
| 17 // } blobs[]; | 19 // } blobs[]; |
| 18 // | 20 // |
| 19 // // The Gzip compressed DeltaArchiveManifest | |
| 20 // char bom[]; | |
| 21 // }; | 21 // }; |
| 22 | 22 |
| 23 // The DeltaArchiveManifest protobuf is an ordered list of File objects. | 23 // The DeltaArchiveManifest protobuf is an ordered list of InstallOperation |
| 24 // These File objects are stored in a linear array in the | 24 // objects. These objects are stored in a linear array in the |
| 25 // DeltaArchiveManifest, each with a specific index. Each File object | 25 // DeltaArchiveManifest. Each operation is applied in order by the client. |
| 26 // can contain children in its children list. Each child in the list | |
| 27 // has a name and an index. The index refers to the index within | |
| 28 // DeltaArchiveManifest.files. Thus, the DeltaArchiveManifest.files | |
| 29 // can be seen as a tree structure that mimicks the filesystem. | |
| 30 // The root object (the object an index 0) has no name, since names | |
| 31 // for children are stored in the parent. | |
| 32 | 26 |
| 33 // The DeltaArchiveManifest will contain one File entry for each | 27 // The DeltaArchiveManifest also contains the initial and final |
| 34 // file that will be on the resultant filesystem. Because we have | 28 // checksums for the device. |
| 35 // a tree structure, and children are ordered alphabetically within | |
| 36 // a parent, we can do log-time˜path lookup on a DeltaArchiveManifest | |
| 37 // object. We can also iterate through a DeltaArchiveManifest object | |
| 38 // using a preorder tree traversal to see each file in the | |
| 39 // DeltaArchiveManifest, seeing each directory before any of its children; | |
| 40 // this takes linear time. | |
| 41 | 29 |
| 42 // Here's an example from Dan Erat showing DeltaArchiveManifest | 30 // The client will perform each InstallOperation in order, beginning even |
| 43 // for a filesystem with files /bin/cat and /bin/ls.: | 31 // before the entire delta file is downloaded (but after at least the |
| 44 | 32 // protobuf is downloaded). The types of operations are explained: |
| 45 // files[0] { // "/" directory | 33 // - REPLACE: Replace the dst_extents on the drive with the attached data, |
| 46 // children[0] { | 34 // zero padding out to block size. |
| 47 // name "bin" | 35 // - REPLACE_BZ: bzip2-uncompress the attached data and write it into |
| 48 // index 1 | 36 // dst_extents on the drive, zero padding to block size. |
| 49 // } | 37 // - MOVE: Copy the data in src_extents to dst_extents. Extents may overlap, |
| 50 // } | 38 // so it may be desirable to read all src_extents data into memory before |
| 51 // files[1] { // "/bin" directory | 39 // writing it out. |
| 52 // children[0] { | 40 // - BSDIFF: Read src_length bytes from src_extents into memory, perform |
| 53 // name "cat" | 41 // bspatch with attached data, write new data to dst_extents, zero padding |
| 54 // index 2 | 42 // to block size. |
| 55 // } | |
| 56 // children[1] { | |
| 57 // name "ls" | |
| 58 // index 3 | |
| 59 // } | |
| 60 // } | |
| 61 // files[2] { // "/bin/cat" | |
| 62 // } | |
| 63 // files[3] { // "/bin/ls" | |
| 64 // } | |
| 65 | |
| 66 // If a file has a data_format set, it should also have data_offset and | |
| 67 // data_length set. data_offset and data_length refer to a range of bytes | |
| 68 // in the delta update file itself which have the format specified by | |
| 69 // data_format. FULL and FULL_GZ mean the entire file is present (FULL_GZ, | |
| 70 // gzip compressed). BSDIFF means the old file with the same path should be | |
| 71 // patched with 'bspatch' to produce the desired output file. COURGETTE | |
| 72 // is not yet used, but it will be another binary diff format. | |
| 73 | |
| 74 // Directories should not have any data. | |
| 75 | |
| 76 // There are other types of files, too: symlinks, block and character devices, | |
| 77 // fifos, and sockets. Fifos and sockets contain no data. Block and | |
| 78 // character devices have data. It must be the format FULL or FULL_GZ, and | |
| 79 // the contents are a serialized LinuxDevice protobuf. Symlinks must either | |
| 80 // be FULL, FULL_GZ, or have no data. A symlink with no data is unchanged, | |
| 81 // and with data it's set to that data. | |
| 82 | |
| 83 // TODO(adlr): Add support for hard links; CL is prepared already. | |
| 84 // Extended attributes are unsupported at this time. | |
| 85 | 43 |
| 86 package chromeos_update_engine; | 44 package chromeos_update_engine; |
| 87 | 45 |
| 88 message DeltaArchiveManifest { | 46 // Data is packed into blocks on disk, always starting from the beginning |
| 89 message File { | 47 // of the block. If a file's data is too large for one block, it overflows |
| 90 // This is st_mode from struct stat. It includes file type and permission | 48 // into another block, which may or may not be the following block on the |
| 91 // bits. | 49 // physical partition. An ordered list of extents is another |
| 92 optional uint32 mode = 1; | 50 // representation of an ordered list of blocks. For example, a file stored |
| 93 optional uint32 uid = 2; | 51 // in blocks 9, 10, 11, 2, 18, 12 (in that order) would be stored in |
| 94 optional uint32 gid = 3; | 52 // extents { {9, 3}, {2, 1}, {18, 1}, {12, 1} } (in that order). |
| 53 // In general, files are stored sequentially on disk, so it's more efficient | |
| 54 // to use extents to encode the block lists (this is effectively | |
| 55 // run-length encoding). | |
| 56 // A seminal value (kuint64max) as the start block denotes a sparse-hole | |
|
Daniel Erat
2010/01/22 22:51:33
s/seminal/sentinel/
| |
| 57 // in a file whose block-length is specified by num_blocks. | |
| 95 | 58 |
| 96 // File Data, not for directories | 59 message Extent { |
| 97 enum DataFormat { | 60 optional uint64 start_block = 1; |
| 98 FULL = 0; // The data is the complete file | 61 optional uint64 num_blocks = 2; |
| 99 FULL_GZ = 1; // The data is the complete file gzipped | |
| 100 BSDIFF = 2; // The data is a bsdiff binary diff | |
| 101 COURGETTE = 3; // The data is a courgette binary diff | |
| 102 } | |
| 103 // If present, there is data associated with this File object and | |
| 104 // data_offset and data_size must be set. | |
| 105 // If a file object doesn't have this set, it means the data is | |
| 106 // unchanged from the old version of the file. | |
| 107 optional DataFormat data_format = 4; | |
| 108 // The offset into the delta file where the data (if any) is stored | |
| 109 optional uint32 data_offset = 5; | |
| 110 // The length of the data in the delta file | |
| 111 optional uint32 data_length = 6; | |
| 112 | |
| 113 // When a file is a hard link, hardlink_path exists and | |
| 114 // is the path within the DeltaArchiveManifest to the "original" file. | |
| 115 // When iterating through a DeltaArchiveManifest, you will be guaranteed | |
| 116 // to hit a hardlink only after you've hit the path to the first file. | |
| 117 // Directories can't be hardlinked. | |
| 118 optional string hardlink_path = 8; | |
| 119 | |
| 120 message Child { | |
| 121 // A File that's a directory (and only those types of File objects) | |
| 122 // will have exactly one Child submessage per child. | |
| 123 required string name = 1; // File name of child | |
| 124 | |
| 125 // Index into DeltaArchiveManifest.files for the File object of the child. | |
| 126 required uint32 index = 2; | |
| 127 } | |
| 128 repeated Child children = 9; | |
| 129 } | |
| 130 repeated File files = 1; | |
| 131 } | 62 } |
| 132 | 63 |
| 133 message LinuxDevice { | 64 message DeltaArchiveManifest { |
| 134 required int32 major = 1; | 65 message InstallOperation { |
| 135 required int32 minor = 2; | 66 enum Type { |
| 136 } | 67 REPLACE = 0; // Replace destination extents w/ attached data |
| 68 REPLACE_BZ = 1; // Replace destination extents w/ attached bzipped data | |
| 69 MOVE = 2; // Move source extents to destination extents | |
| 70 BSDIFF = 3; // The data is a bsdiff binary diff | |
| 71 } | |
| 72 required Type type = 1; | |
| 73 // The offset into the delta file (after the protobuf) | |
| 74 // where the data (if any) is stored | |
| 75 optional uint32 data_offset = 2; | |
| 76 // The length of the data in the delta file | |
| 77 optional uint32 data_length = 3; | |
| 78 | |
| 79 // Ordered list of extents that are read from (if any) and written to. | |
| 80 repeated Extent src_extents = 4; | |
| 81 // Byte length of src, not necessarily block aligned. It's only used for | |
| 82 // BSDIFF, because we need to pass that external program the number | |
| 83 // of bytes to read from the blocks we pass it. | |
| 84 optional uint64 src_length = 5; | |
| 85 | |
| 86 repeated Extent dst_extents = 6; | |
| 87 // byte length of dst, not necessarily block aligned. It's only used for | |
| 88 // BSDIFF, because we need to fill in the rest of the last block | |
| 89 // that bsdiff writes with '\0' bytes. | |
| 90 optional uint64 dst_length = 7; | |
| 91 } | |
| 92 repeated InstallOperation install_operations = 1; | |
| 93 // The checksums of the install device before and after the install process. | |
| 94 optional string src_checksum = 2; | |
| 95 optional string dst_checksum = 3; | |
| 96 | |
| 97 // (At time of writing) usually 4096 | |
| 98 optional uint32 block_size = 5 [default = 4096]; | |
| 99 } | |
| OLD | NEW |