1 /* 2 * SPDX-FileCopyrightText: 2019-2022 Espressif Systems (Shanghai) CO LTD 3 * 4 * SPDX-License-Identifier: Apache-2.0 5 */ 6 7 8 /** 9 * Archive to parse cpio data in the newc and crc formats. Generate a cpio archive like that by e.g. 10 * find . | cpio -o -H newc > archive.cpio 11 */ 12 13 #pragma once 14 15 #include <stdio.h> 16 #include <stdint.h> 17 #include <stdbool.h> 18 19 #ifdef __cplusplus 20 extern "C" { 21 #endif 22 23 #define CPIO_MODE_FILETYPE_MASK 0xF000 24 #define CPIO_MODE_FILETYPE_SOCKET 0xC000 25 #define CPIO_MODE_FILETYPE_SYMLINK 0xA000 26 #define CPIO_MODE_FILETYPE_REGULAR 0x8000 27 #define CPIO_MODE_FILETYPE_BLOCKDEV 0x6000 28 #define CPIO_MODE_FILETYPE_DIR 0x4000 29 #define CPIO_MODE_FILETYPE_CHARDEV 0x2000 30 #define CPIO_MODE_FILETYPE_FIFO 0x1000 31 #define CPIO_MODE_SUID 0x0800 32 #define CPIO_MODE_SGID 0x0400 33 #define CPIO_MODE_STICKY 0x0200 34 35 typedef struct { 36 size_t filesize; 37 char *name; 38 uint32_t mode; 39 uint32_t check; 40 } cpio_file_t; 41 42 typedef enum { 43 CPIO_RET_MORE = 0, 44 CPIO_RET_DONE, 45 CPIO_RET_ERR 46 } cpio_ret_t; 47 48 typedef struct cpio_handle_data_t cpio_handle_data_t; 49 typedef cpio_handle_data_t *cpio_handle_t; 50 51 typedef enum { 52 CPIO_RSN_FILE_ALL = 0, 53 CPIO_RSN_FILE_INITIAL, 54 CPIO_RSN_FILE_MORE, 55 CPIO_RSN_FILE_END 56 } cpio_callback_reason_t; 57 58 59 /** 60 * Callback for cpio file data. 61 * 62 * This callback will be called by the library to indicate data for a file is available. 63 * 64 * For files in the cpio archive that fit entirely in the internal buffer, or when no internal 65 * buffer is available, are entirely contained in the buffer fed to cpio_feed(), this callback 66 * is only called once, with reason=CPIO_RNS_FILE_ALL. fileinfo will contain the information 67 * for that specific file (name, size, ...), buff_offset will be 0, buff_len is the file 68 * size and buff contains all the information for the file. 69 * 70 * For files that do not fit in the buffer, this callback will be called multiple times. 71 * The initial time with reason=CPIO_RSN_FILE_INITIAL, when more data is available with 72 * CPIO_RSN_FILE_MORE and finally with CPIO_RSN_FILE_END. For these calls, fileinfo 73 * will again contain file information. buff will be the information contained in the 74 * file at offset buff_offset, and the length of this buffer will be in buff_len. 75 * 76 * The library guarantees to feed all file data to the callback consequitively, so 77 * within the same file, the buff_offset from a call will always be (buff_offset+buff_len) 78 * from the call before that. If cpio_start is 79 * 80 * The library also guarantees every file in the cpio archive will either generate a single 81 * callback call with CPIO_RSN_ALL, or multiple with in sequence CPIO_RSN_FILE_INITIAL, 0 or 82 * more CPIO_RSN_FILE_MORE and finally a CPIO_RSN_FILE_END. 83 * 84 * When a non-zero buffer size is passed to cpio_start, the library guarantees that all callback 85 * calls with a reason of CPIO_RSN_FILE_INITIAL and CPIO_RSN_FILE_MORE will have a buffer 86 * filled with exactly this amount of bytes. 87 * 88 */ 89 typedef void (*cpio_callback_t)(cpio_callback_reason_t reason, cpio_file_t *fileinfo, size_t buff_offset, size_t buff_len, char *buff, void *arg); 90 91 92 /** 93 * @brief Initialize a cpio handle. 94 * 95 * Call this to start parsing a cpio archive. You can set the callback that handles the 96 * files/data here. 97 * 98 * @param callback The callback that will handle the data of the files inside the cpio archive 99 * 100 * @param cbarg User-supplied argument. The callback will be called with this as an argument. 101 * 102 * @param buflen Length of internal buffer used. 103 * If this is zero, the callback will be called with data that lives in the data buffer 104 * supplied to the cpio library by whomever called cpio_feed(). Because this library has 105 * no power over that buffer, the callback can be passed as little as 1 and as many as 106 * INT_MAX bytes at a time. 107 * If this is non-zero, the library will allocate an internal buffer of this size. All 108 * cpio_feed()-calls will be rebuffered, and the callback is guaranteed to only be called 109 * with this many bytes in the buffer, given there's enough data in the file to fill it. 110 * 111 * @param memchunk Chunk of memory to allocate everything (handle, I/O buffer, filename buffer) in. Minimum size 112 * (estimate) is 160+buflen+sizeof(largest filename/path). 113 * @param memchunklen Size of the mem chunk 114 * 115 * @return 116 * - Success: A pointer to a cpio handle 117 * - Error: NULL 118 * 119 */ 120 cpio_handle_t cpio_start(cpio_callback_t callback, void *cbarg, size_t buflen, void *memchunk, int memchunklen); 121 122 /** 123 * @brief Feed data from a cpio archive into the library 124 * 125 * This routine is used to feed consecutive data of the cpio archive into the library. While processing, 126 * the library can call the callback function one or more times if needed. 127 * 128 * @param cpio Handle obtained by calling cpio_start() 129 * 130 * @param buffer Pointer to buffer containing cpio archive data 131 * 132 * @param len Length of the buffer, in bytes 133 * 134 * @return 135 * - CPIO_RET_MORE: CPIO archive isn't done yet, please feed more data. 136 * - CPIO_RET_DONE: CPUI archive is finished. 137 * - CPIO_RET_ERR: Invalid CPIO archive data; decoding aborted. 138 * 139 */ 140 cpio_ret_t cpio_feed(cpio_handle_t cpio, char *buffer, int len); 141 142 /** 143 * @brief Indicate there is no more cpio data to be fed into the archive 144 * 145 * This call is to be called when the source data is exhausted. Normally, the library can find the end of the 146 * cpio archive by looking for the end marker, 147 * 148 * @param timer_conf Pointer of LEDC timer configure struct 149 * 150 * 151 * @return 152 * - CPIO_RET_DONE on success 153 * - CPIO_RET_ERR when cpio archive is invalid 154 * 155 */ 156 cpio_ret_t cpio_done(cpio_handle_t cpio); 157 158 159 /** 160 * @brief Free the memory allocated for a cpio handle. 161 * 162 * @param cpio Handle obtained by calling cpio_start() 163 * 164 * @return 165 * - CPIO_RET_DONE on success 166 * 167 */ 168 cpio_ret_t cpio_destroy(cpio_handle_t cpio); 169 170 #ifdef __cplusplus 171 } 172 #endif 173