]> glassweightruler.freedombox.rocks Git - Ventoy.git/blob - wimboot/wimboot-2.7.3/src/cpio.c
1.1.07 release
[Ventoy.git] / wimboot / wimboot-2.7.3 / src / cpio.c
1 /*
2 * Copyright (C) 2012 Michael Brown <mbrown@fensystems.co.uk>.
3 *
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License as
6 * published by the Free Software Foundation; either version 2 of the
7 * License, or (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful, but
10 * WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
17 * 02110-1301, USA.
18 */
19
20 /**
21 * @file
22 *
23 * CPIO archives
24 *
25 */
26
27 #include <stdint.h>
28 #include <stddef.h>
29 #include <stdio.h>
30 #include <stdlib.h>
31 #include <string.h>
32 #include "wimboot.h"
33 #include "cpio.h"
34
35 /**
36 * Align CPIO length to nearest dword
37 *
38 * @v len Length
39 * @ret len Aligned length
40 */
41 static size_t cpio_align ( size_t len ) {
42 return ( ( len + 0x03 ) & ~0x03 );
43 }
44
45 /**
46 * Parse CPIO field value
47 *
48 * @v field ASCII field
49 * @ret value Field value
50 */
51 static unsigned long cpio_value ( const char *field ) {
52 char buf[9];
53
54 memcpy ( buf, field, ( sizeof ( buf ) - 1 ) );
55 buf[ sizeof ( buf ) - 1 ] = '\0';
56 return strtoul ( buf, NULL, 16 );
57 }
58
59 /**
60 * Extract files from CPIO archive
61 *
62 * @v data CPIO archive
63 * @v len Maximum length of CPIO archive
64 * @v file File handler
65 * @ret rc Return status code
66 */
67 int cpio_extract ( void *data, size_t len,
68 int ( * file ) ( const char *name, void *data,
69 size_t len ) ) {
70 const struct cpio_header *cpio;
71 const uint32_t *pad;
72 const char *file_name;
73 void *file_data;
74 size_t file_name_len;
75 size_t file_len;
76 size_t cpio_len;
77 int rc;
78
79 while ( 1 ) {
80
81 /* Skip over any padding */
82 while ( len >= sizeof ( *pad ) ) {
83 pad = data;
84 if ( *pad )
85 break;
86 data += sizeof ( *pad );
87 len -= sizeof ( *pad );
88 }
89
90 /* Stop if we have reached the end of the archive */
91 if ( ! len )
92 return 0;
93
94 /* Sanity check */
95 if ( len < sizeof ( *cpio ) ) {
96 DBG ( "Truncated CPIO header\n" );
97 return -1;
98 }
99 cpio = data;
100
101 /* Check magic */
102 if ( memcmp ( cpio->c_magic, CPIO_MAGIC,
103 sizeof ( cpio->c_magic ) ) != 0 ) {
104 DBG ( "Bad CPIO magic\n" );
105 return -1;
106 }
107
108 /* Extract file parameters */
109 file_name = ( ( void * ) ( cpio + 1 ) );
110 file_name_len = cpio_value ( cpio->c_namesize );
111 file_data = ( data + cpio_align ( sizeof ( *cpio ) +
112 file_name_len ) );
113 file_len = cpio_value ( cpio->c_filesize );
114 cpio_len = ( file_data + file_len - data );
115 if ( cpio_len < len )
116 cpio_len = cpio_align ( cpio_len );
117 if ( cpio_len > len ) {
118 DBG ( "Truncated CPIO file\n" );
119 return -1;
120 }
121
122 /* If we reach the trailer, we're done */
123 if ( strcmp ( file_name, CPIO_TRAILER ) == 0 )
124 return 0;
125
126 /* Process file */
127 if ( ( rc = file ( file_name, file_data, file_len ) ) != 0 )
128 return rc;
129
130 /* Move to next file */
131 data += cpio_len;
132 len -= cpio_len;
133 }
134 }