wimfile.c 3.82 KB
Newer Older
longpanda's avatar
longpanda committed
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
/*
 * Copyright (C) 2014 Michael Brown <mbrown@fensystems.co.uk>.
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License as
 * published by the Free Software Foundation; either version 2 of the
 * License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful, but
 * WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
 * 02110-1301, USA.
 */

/**
 * @file
 *
 * WIM virtual files
 *
 */

#include <stddef.h>
#include <stdio.h>
#include <string.h>
#include <strings.h>
#include <wchar.h>
#include "wimboot.h"
#include "vdisk.h"
#include "wim.h"
#include "wimfile.h"

/** A WIM virtual file */
struct wim_file {
	/** Underlying virtual file */
	struct vdisk_file *file;
	/** WIM header */
	struct wim_header header;
	/** Resource */
	struct wim_resource_header resource;
};

/** Maximum number of WIM virtual files */
#define WIM_MAX_FILES 8

/** WIM virtual files */
static struct wim_file wim_files[WIM_MAX_FILES];

/**
 * Read from WIM virtual file
 *
 * @v file		Virtual file
 * @v data		Data buffer
 * @v offset		Offset
 * @v len		Length
 */
static void wim_read_file ( struct vdisk_file *file, void *data,
			    size_t offset, size_t len ) {
	struct wim_file *wfile = file->opaque;
	int rc;

	/* Read from resource */
	if ( ( rc = wim_read ( wfile->file, &wfile->header, &wfile->resource,
			       data, offset, len ) ) != 0 ) {
		die ( "Could not read from WIM virtual file\n" );
	}
}

/**
 * Add WIM virtual file
 *
 * @v file		Underlying virtual file
 * @v index		Image index, or 0 to use boot image
 * @v path		Path to file within WIM
 * @v wname		New virtual file name
 * @ret file		Virtual file, or NULL if not found
 */
struct vdisk_file * wim_add_file ( struct vdisk_file *file, unsigned int index,
				   const wchar_t *path, const wchar_t *wname ) {
	static unsigned int wim_file_idx = 0;
	struct wim_resource_header meta;
	struct wim_file *wfile;
	char name[ VDISK_NAME_LEN + 1 /* NUL */ ];
	unsigned int i;
	int rc;

	/* Sanity check */
	if ( wim_file_idx >= WIM_MAX_FILES )
		die ( "Too many WIM files\n" );
	wfile = &wim_files[wim_file_idx];

	/* Construct ASCII file name */
	snprintf ( name, sizeof ( name ), "%ls", wname );

	/* Skip files already added explicitly */
	for ( i = 0 ; i < VDISK_MAX_FILES ; i++ ) {
		if ( strcasecmp ( name, vdisk_files[i].name ) == 0 )
			return NULL;
	}

	/* Get WIM header */
	if ( ( rc = wim_header ( file, &wfile->header ) ) != 0 )
		return NULL;

	/* Get image metadata */
	if ( ( rc = wim_metadata ( file, &wfile->header, index, &meta ) ) != 0 )
		return NULL;

	/* Get file resource */
	if ( ( rc = wim_file ( file, &wfile->header, &meta, path,
			       &wfile->resource ) ) != 0 )
		return NULL;

	/* Add virtual file */
	wim_file_idx++;
	wfile->file = file;
	return vdisk_add_file ( name, wfile, wfile->resource.len,
				wim_read_file );
}

/**
 * Add WIM virtual files
 *
 * @v file		Underlying virtual file
 * @v index		Image index, or 0 to use boot image
 * @v paths		List of paths to files within WIM
 */
void wim_add_files ( struct vdisk_file *file, unsigned int index,
		     const wchar_t **paths ) {
	const wchar_t **path;
	const wchar_t *wname;
	const wchar_t *tmp;

	/* Add any existent files within the list */
	for ( path = paths ; *path ; path++ ) {

		/* Construct file name */
		wname = *path;
		for ( tmp = wname ; *tmp ; tmp++ ) {
			if ( *tmp == L'\\' )
				wname = ( tmp + 1 );
		}

		/* Add virtual file, if existent */
		wim_add_file ( file, index, *path, wname );
	}
}