Sol Boucher | e3260a0 | 2015-03-25 13:40:08 -0700 | [diff] [blame] | 1 | /* |
| 2 | * partitioned_file.h, read and write binary file "partitions" described by FMAP |
| 3 | * |
| 4 | * Copyright (C) 2015 Google, Inc. |
| 5 | * |
| 6 | * This program is free software; you can redistribute it and/or modify |
| 7 | * it under the terms of the GNU General Public License as published by |
| 8 | * the Free Software Foundation; version 2 of the License. |
| 9 | * |
| 10 | * This program is distributed in the hope that it will be useful, |
| 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
| 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| 13 | * GNU General Public License for more details. |
Sol Boucher | e3260a0 | 2015-03-25 13:40:08 -0700 | [diff] [blame] | 14 | */ |
| 15 | |
| 16 | #ifndef PARITITONED_FILE_H_ |
| 17 | #define PARITITONED_FILE_H_ |
| 18 | |
| 19 | #include "common.h" |
| 20 | #include "flashmap/fmap.h" |
| 21 | |
| 22 | #include <stdbool.h> |
| 23 | #include <stddef.h> |
| 24 | |
| 25 | typedef struct partitioned_file partitioned_file_t; |
| 26 | |
Sol Boucher | e3260a0 | 2015-03-25 13:40:08 -0700 | [diff] [blame] | 27 | /** |
| 28 | * Create a new filesystem-backed flat buffer. |
| 29 | * This backwards-compatibility function creates a new in-memory buffer and |
| 30 | * backing binary file of the specified size. Although the file won't actually |
| 31 | * have multiple regions, it'll still be possible to access and manipulate it |
| 32 | * using this module; this is accomplished by requesting the special region |
| 33 | * whose name matches SECTION_NAME_PRIMARY_CBFS, which maps to the whole file. |
| 34 | * Note that the caller will be responsible for calling partitioned_file_close() |
| 35 | * on the returned object, and that this function will overwrite any existing |
| 36 | * file with the given name without warning. |
| 37 | * |
| 38 | * @param filename Name of the backing file |
| 39 | * @param image_size Size of the image |
| 40 | * @return Caller-owned partitioned file, or NULL on error |
| 41 | */ |
| 42 | partitioned_file_t *partitioned_file_create_flat(const char *filename, |
| 43 | size_t image_size); |
| 44 | |
| 45 | /** |
| 46 | * Create a new filesystem-backed partitioned buffer. |
| 47 | * This creates a new in-memory buffer and backing binary file. Both are |
| 48 | * segmented into regions according to the provided flashmap's sections, and the |
| 49 | * flashmap itself is automatically copied into the region named |
| 50 | * SECTION_NAME_FMAP: a section with this name must already exist in the FMAP. |
| 51 | * After calling this function, it is safe for the caller to clean up flashmap |
| 52 | * at any time. The partitioned_file_t returned from this function is separately |
| 53 | * owned by the caller, and must later be passed to partitioned_file_close(). |
| 54 | * Note that this function will overwrite any existing file with the given name |
| 55 | * without warning. |
| 56 | * |
| 57 | * @param filename Name of the backing file |
| 58 | * @param flashmap Buffer containing an FMAP file layout |
| 59 | * @return Caller-owned partitioned file, or NULL on error |
| 60 | */ |
| 61 | partitioned_file_t *partitioned_file_create(const char *filename, |
| 62 | struct buffer *flashmap); |
| 63 | |
| 64 | /** |
| 65 | * Read a file back in from the disk. |
Patrick Georgi | 2f953d3 | 2015-09-11 18:34:39 +0200 | [diff] [blame] | 66 | * An in-memory buffer is created and populated with the file's |
| 67 | * contents. If the image contains an FMAP, it will be opened as a |
| 68 | * full partitioned file; otherwise, it will be opened as a flat file as |
| 69 | * if it had been created by partitioned_file_create_flat(). |
Sol Boucher | e3260a0 | 2015-03-25 13:40:08 -0700 | [diff] [blame] | 70 | * The partitioned_file_t returned from this function is separately owned by the |
| 71 | * caller, and must later be passed to partitioned_file_close(); |
| 72 | * |
| 73 | * @param filename Name of the file to read in |
Vadim Bendebury | 7559946 | 2015-12-09 09:39:31 -0800 | [diff] [blame] | 74 | * @param write_access True if the file needs to be modified |
Sol Boucher | e3260a0 | 2015-03-25 13:40:08 -0700 | [diff] [blame] | 75 | * @return Caller-owned partitioned file, or NULL on error |
| 76 | */ |
Vadim Bendebury | 7559946 | 2015-12-09 09:39:31 -0800 | [diff] [blame] | 77 | partitioned_file_t *partitioned_file_reopen(const char *filename, |
| 78 | bool write_access); |
Sol Boucher | e3260a0 | 2015-03-25 13:40:08 -0700 | [diff] [blame] | 79 | |
| 80 | /** |
| 81 | * Write a buffer's contents to its original region within a segmented file. |
| 82 | * This function should only be called on buffers originally retrieved by a call |
| 83 | * to partitioned_file_read_region() on the same partitioned file object. The |
| 84 | * contents of this buffer are copied back to the same region of the buffer and |
| 85 | * backing file that the region occupied before. |
| 86 | * |
| 87 | * @param file Partitioned file to which to write the data |
| 88 | * @param buffer Modified buffer obtained from partitioned_file_read_region() |
| 89 | * @return Whether the operation was successful |
| 90 | */ |
| 91 | bool partitioned_file_write_region(partitioned_file_t *file, |
| 92 | const struct buffer *buffer); |
| 93 | |
| 94 | /** |
| 95 | * Obtain one particular region of a segmented file. |
| 96 | * The result is owned by the partitioned_file_t and shared among every caller |
| 97 | * of this function. Thus, it is an error to buffer_delete() it; instead, clean |
| 98 | * up the entire partitioned_file_t once it's no longer needed with a single |
| 99 | * call to partitioned_file_close(). |
| 100 | * Note that, if the buffer obtained from this function is modified, the changes |
| 101 | * will be reflected in any buffers handed out---whether earlier or later---for |
| 102 | * any region inclusive of the altered location(s). However, the backing file |
| 103 | * will not be updated until someone calls partitioned_file_write_region() on a |
| 104 | * buffer that includes the alterations. |
| 105 | * |
| 106 | * @param dest Empty destination buffer for the data |
| 107 | * @param file Partitioned file from which to read the data |
| 108 | * @param region Name of the desired FMAP region |
| 109 | * @return Whether the copy was performed successfully |
| 110 | */ |
| 111 | bool partitioned_file_read_region(struct buffer *dest, |
| 112 | const partitioned_file_t *file, const char *region); |
| 113 | |
| 114 | /** @param file Partitioned file to flush and cleanup */ |
| 115 | void partitioned_file_close(partitioned_file_t *file); |
| 116 | |
| 117 | /** @return Whether the file is partitioned (i.e. not flat). */ |
| 118 | bool partitioned_file_is_partitioned(const partitioned_file_t *file); |
| 119 | |
Sol Boucher | 67d5998 | 2015-05-07 02:39:22 -0700 | [diff] [blame] | 120 | /** @return The image's overall filesize, regardless of whether it's flat. */ |
| 121 | size_t partitioned_file_total_size(const partitioned_file_t *file); |
| 122 | |
Sol Boucher | e3260a0 | 2015-03-25 13:40:08 -0700 | [diff] [blame] | 123 | /** @return Whether the specified region begins with the magic bytes. */ |
| 124 | bool partitioned_file_region_check_magic(const partitioned_file_t *file, |
| 125 | const char *region, const char *magic, size_t magic_len); |
| 126 | |
| 127 | /** @return Whether the specified region exists and contains nested regions. */ |
| 128 | bool partitioned_file_region_contains_nested(const partitioned_file_t *file, |
| 129 | const char *region); |
| 130 | |
| 131 | /** @return An immutable reference to the FMAP, or NULL for flat images. */ |
| 132 | const struct fmap *partitioned_file_get_fmap(const partitioned_file_t *file); |
| 133 | |
| 134 | /** @return Whether to include area in the running count. */ |
| 135 | typedef bool (*partitioned_file_fmap_selector_t) |
| 136 | (const struct fmap_area *area, const void *arg); |
| 137 | |
| 138 | /** |
| 139 | * Count the number of FMAP entries fulfilling a certain criterion. |
| 140 | * The result is always 0 if run on a flat (non-partitioned) image. |
| 141 | * |
| 142 | * @param file File on whose FMAP entries the operation should be run |
| 143 | * @param callback Decider answering whether each individual region should count |
| 144 | * @param arg Additional information to furnish to the decider on each call |
| 145 | * @return The number of FMAP sections with that property |
| 146 | */ |
| 147 | unsigned partitioned_file_fmap_count(const partitioned_file_t *file, |
| 148 | partitioned_file_fmap_selector_t callback, const void *arg); |
| 149 | |
| 150 | /** Selector that counts every single FMAP section. */ |
| 151 | extern const partitioned_file_fmap_selector_t partitioned_file_fmap_select_all; |
| 152 | |
| 153 | /** Selector that counts FMAP sections that are descendants of fmap_area arg. */ |
| 154 | extern const partitioned_file_fmap_selector_t |
| 155 | partitioned_file_fmap_select_children_of; |
| 156 | |
| 157 | /** Selector that counts FMAP sections that contain the fmap_area arg. */ |
| 158 | extern const partitioned_file_fmap_selector_t |
| 159 | partitioned_file_fmap_select_parents_of; |
| 160 | |
| 161 | #endif |