@@ -285,10 +285,45 @@ int wim_read ( struct vdisk_file *file, struct wim_header *header,
285285 return 0 ;
286286}
287287
288+ /**
289+ * Get number of images
290+ *
291+ * @v file Virtual file
292+ * @v header WIM header
293+ * @v count Count of images to fill in
294+ * @ret rc Return status code
295+ */
296+ int wim_count ( struct vdisk_file * file , struct wim_header * header ,
297+ unsigned int * count ) {
298+ struct wim_lookup_entry entry ;
299+ size_t offset ;
300+ int rc ;
301+
302+ /* Count metadata entries */
303+ for ( offset = 0 ; ( offset + sizeof ( entry ) ) <= header -> lookup .len ;
304+ offset += sizeof ( entry ) ) {
305+
306+ /* Read entry */
307+ if ( ( rc = wim_read ( file , header , & header -> lookup , & entry ,
308+ offset , sizeof ( entry ) ) ) != 0 )
309+ return rc ;
310+
311+ /* Check for metadata entries */
312+ if ( entry .resource .zlen__flags & WIM_RESHDR_METADATA ) {
313+ (* count )++ ;
314+ DBG2 ( "...found image %d metadata at +%#zx\n" ,
315+ * count , offset );
316+ }
317+ }
318+
319+ return 0 ;
320+ }
321+
288322/**
289323 * Get WIM image metadata
290324 *
291325 * @v file Virtual file
326+ * @v header WIM header
292327 * @v index Image index, or 0 to use boot image
293328 * @v meta Metadata to fill in
294329 * @ret rc Return status code
@@ -318,8 +353,8 @@ int wim_metadata ( struct vdisk_file *file, struct wim_header *header,
318353 /* Look for our target entry */
319354 if ( entry .resource .zlen__flags & WIM_RESHDR_METADATA ) {
320355 found ++ ;
321- DBG ( "...found image %d metadata at +%#zx\n" ,
322- found , offset );
356+ DBG2 ( "...found image %d metadata at +%#zx\n" ,
357+ found , offset );
323358 if ( found == index ) {
324359 memcpy ( meta , & entry .resource ,
325360 sizeof ( * meta ) );
@@ -339,23 +374,23 @@ int wim_metadata ( struct vdisk_file *file, struct wim_header *header,
339374 * @v file Virtual file
340375 * @v header WIM header
341376 * @v meta Metadata
342- * @v offset Directory offset
343377 * @v name Name
378+ * @v offset Directory offset (will be updated)
344379 * @v direntry Directory entry to fill in
345380 * @ret rc Return status code
346381 */
347382static int wim_direntry ( struct vdisk_file * file , struct wim_header * header ,
348- struct wim_resource_header * meta , size_t offset ,
349- const wchar_t * name ,
383+ struct wim_resource_header * meta ,
384+ const wchar_t * name , size_t * offset ,
350385 struct wim_directory_entry * direntry ) {
351386 wchar_t name_buf [ wcslen ( name ) + 1 /* NUL */ ];
352387 int rc ;
353388
354389 /* Search directory */
355- for ( ; ; offset += direntry -> len ) {
390+ for ( ; ; * offset += direntry -> len ) {
356391
357392 /* Read length field */
358- if ( ( rc = wim_read ( file , header , meta , direntry , offset ,
393+ if ( ( rc = wim_read ( file , header , meta , direntry , * offset ,
359394 sizeof ( direntry -> len ) ) ) != 0 )
360395 return rc ;
361396
@@ -366,7 +401,7 @@ static int wim_direntry ( struct vdisk_file *file, struct wim_header *header,
366401 }
367402
368403 /* Read fixed-length portion of directory entry */
369- if ( ( rc = wim_read ( file , header , meta , direntry , offset ,
404+ if ( ( rc = wim_read ( file , header , meta , direntry , * offset ,
370405 sizeof ( * direntry ) ) ) != 0 )
371406 return rc ;
372407
@@ -376,7 +411,7 @@ static int wim_direntry ( struct vdisk_file *file, struct wim_header *header,
376411
377412 /* Read name */
378413 if ( ( rc = wim_read ( file , header , meta , & name_buf ,
379- ( offset + sizeof ( * direntry ) ),
414+ ( * offset + sizeof ( * direntry ) ),
380415 sizeof ( name_buf ) ) ) != 0 )
381416 return rc ;
382417
@@ -390,23 +425,21 @@ static int wim_direntry ( struct vdisk_file *file, struct wim_header *header,
390425}
391426
392427/**
393- * Get file resource
428+ * Get directory entry for a path
394429 *
395430 * @v file Virtual file
396431 * @v header WIM header
397432 * @v meta Metadata
398- * @v path Path to file
399- * @v resource File resource to fill in
433+ * @v path Path to file/directory
434+ * @v offset Directory entry offset to fill in
435+ * @v direntry Directory entry to fill in
400436 * @ret rc Return status code
401437 */
402- int wim_file ( struct vdisk_file * file , struct wim_header * header ,
438+ int wim_path ( struct vdisk_file * file , struct wim_header * header ,
403439 struct wim_resource_header * meta , const wchar_t * path ,
404- struct wim_resource_header * resource ) {
440+ size_t * offset , struct wim_directory_entry * direntry ) {
405441 wchar_t path_copy [ wcslen ( path ) + 1 /* WNUL */ ];
406442 struct wim_security_header security ;
407- struct wim_directory_entry direntry ;
408- struct wim_lookup_entry entry ;
409- size_t offset ;
410443 wchar_t * name ;
411444 wchar_t * next ;
412445 int rc ;
@@ -417,22 +450,48 @@ int wim_file ( struct vdisk_file *file, struct wim_header *header,
417450 return rc ;
418451
419452 /* Get root directory offset */
420- offset = ( ( security .len + sizeof ( uint64_t ) - 1 ) &
421- ~( sizeof ( uint64_t ) - 1 ) );
453+ direntry -> subdir = ( ( security .len + sizeof ( uint64_t ) - 1 ) &
454+ ~( sizeof ( uint64_t ) - 1 ) );
422455
423456 /* Find directory entry */
424457 name = memcpy ( path_copy , path , sizeof ( path_copy ) );
425458 do {
426459 next = wcschr ( name , L'\\' );
427460 if ( next )
428461 * next = L'\0' ;
429- if ( ( rc = wim_direntry ( file , header , meta , offset , name ,
430- & direntry ) ) != 0 )
462+ * offset = direntry -> subdir ;
463+ if ( ( rc = wim_direntry ( file , header , meta , name , offset ,
464+ direntry ) ) != 0 )
431465 return rc ;
432- offset = direntry .subdir ;
433466 name = ( next + 1 );
434467 } while ( next );
435468
469+ return 0 ;
470+ }
471+
472+ /**
473+ * Get file resource
474+ *
475+ * @v file Virtual file
476+ * @v header WIM header
477+ * @v meta Metadata
478+ * @v path Path to file
479+ * @v resource File resource to fill in
480+ * @ret rc Return status code
481+ */
482+ int wim_file ( struct vdisk_file * file , struct wim_header * header ,
483+ struct wim_resource_header * meta , const wchar_t * path ,
484+ struct wim_resource_header * resource ) {
485+ struct wim_directory_entry direntry ;
486+ struct wim_lookup_entry entry ;
487+ size_t offset ;
488+ int rc ;
489+
490+ /* Find directory entry */
491+ if ( ( rc = wim_path ( file , header , meta , path , & offset ,
492+ & direntry ) ) != 0 )
493+ return rc ;
494+
436495 /* File matching file entry */
437496 for ( offset = 0 ; ( offset + sizeof ( entry ) ) <= header -> lookup .len ;
438497 offset += sizeof ( entry ) ) {
@@ -455,3 +514,34 @@ int wim_file ( struct vdisk_file *file, struct wim_header *header,
455514 DBG ( "Cannot find file %ls\n" , path );
456515 return -1 ;
457516}
517+
518+ /**
519+ * Get length of a directory
520+ *
521+ * @v file Virtual file
522+ * @v header WIM header
523+ * @v meta Metadata
524+ * @v offset Directory offset
525+ * @v len Directory length to fill in (excluding terminator)
526+ * @ret rc Return status code
527+ */
528+ int wim_dir_len ( struct vdisk_file * file , struct wim_header * header ,
529+ struct wim_resource_header * meta , size_t offset ,
530+ size_t * len ) {
531+ struct wim_directory_entry direntry ;
532+ int rc ;
533+
534+ /* Search directory */
535+ for ( * len = 0 ; ; * len += direntry .len ) {
536+
537+ /* Read length field */
538+ if ( ( rc = wim_read ( file , header , meta , & direntry ,
539+ ( offset + * len ),
540+ sizeof ( direntry .len ) ) ) != 0 )
541+ return rc ;
542+
543+ /* Check for end of this directory */
544+ if ( ! direntry .len )
545+ return 0 ;
546+ }
547+ }
0 commit comments