Merge pull request #263 from ZystemOS/feature/mkfat32-any-stream

mkFAT32 use a anytype stream
This commit is contained in:
Edward Dean 2020-11-11 16:58:59 +00:00 committed by GitHub
commit ea6a0b7a9f
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
2 changed files with 49 additions and 49 deletions

View file

@ -211,7 +211,13 @@ const Fat32BuilderStep = struct {
/// ///
fn make(step: *Step) (error{EndOfStream} || File.OpenError || File.ReadError || File.WriteError || File.SeekError || Fat32.Error)!void { fn make(step: *Step) (error{EndOfStream} || File.OpenError || File.ReadError || File.WriteError || File.SeekError || Fat32.Error)!void {
const self = @fieldParentPtr(Fat32BuilderStep, "step", step); const self = @fieldParentPtr(Fat32BuilderStep, "step", step);
try Fat32.make(self.options, self.out_file_path); // Open the out file
const image = try std.fs.cwd().createFile(self.out_file_path, .{ .read = true });
// If there was an error, delete the image as this will be invalid
errdefer (std.fs.cwd().deleteFile(self.out_file_path) catch unreachable);
defer image.close();
try Fat32.make(self.options, image);
} }
/// ///

View file

@ -1,5 +1,4 @@
const std = @import("std"); const std = @import("std");
const File = std.fs.File;
// This is the assembly for the FAT bootleader. // This is the assembly for the FAT bootleader.
// [bits 16] // [bits 16]
@ -350,23 +349,23 @@ pub const Fat32 = struct {
} }
/// ///
/// Write the FSInfo and backup FSInfo sector to a image file. This uses a valid FAT32 boot /// Write the FSInfo and backup FSInfo sector to a stream. This uses a valid FAT32 boot sector
/// sector header for creating the FSInfo sector. /// header for creating the FSInfo sector.
/// ///
/// Argument: /// Argument:
/// IN/OUT image: File - The image file to write the FSInfo to. /// IN/OUT stream: anytype - The stream to write the FSInfo to.
/// IN fat32_header: Header - A valid FAT32 boot header for creating the FSInfo sector. /// IN fat32_header: Header - A valid FAT32 boot header for creating the FSInfo sector.
/// IN free_cluster_num: u32 - The number of free data clusters on the image. /// IN free_cluster_num: u32 - The number of free data clusters on the image.
/// IN next_free_cluster: u32 - The next free data cluster to start looking for when writing /// IN next_free_cluster: u32 - The next free data cluster to start looking for when writing
/// files. /// files.
/// ///
/// Error File.WriteError || File.SeekError /// Error @TypeOf(stream).WriteError || @TypeOf(stream).SeekError
/// File.WriteError - If there is an error when writing to the image. See File.WriteError /// @TypeOf(stream).WriteError - If there is an error when writing. See the relevant error for the stream.
/// File.SeekError - If there is an error when seeking the image. See File.SeekError /// @TypeOf(stream).SeekError - If there is an error when seeking. See the relevant error for the stream.
/// ///
fn writeFSInfo(image: File, fat32_header: Header, free_cluster_num: u32, next_free_cluster: u32) (File.WriteError || File.SeekError)!void { fn writeFSInfo(stream: anytype, fat32_header: Header, free_cluster_num: u32, next_free_cluster: u32) (@TypeOf(stream).WriteError || @TypeOf(stream).SeekError)!void {
const seekable_stream = image.seekableStream(); const seekable_stream = stream.seekableStream();
const writer = image.writer(); const writer = stream.writer();
// Seek to the correct location // Seek to the correct location
try seekable_stream.seekTo(fat32_header.fsinfo_sector * fat32_header.bytes_per_sector); try seekable_stream.seekTo(fat32_header.fsinfo_sector * fat32_header.bytes_per_sector);
@ -404,20 +403,20 @@ pub const Fat32 = struct {
} }
/// ///
/// Write the FAT to the image. This sets up a blank FAT with end marker of 0x0FFFFFFF and root /// Write the FAT to the stream. This sets up a blank FAT with end marker of 0x0FFFFFFF and root
/// directory cluster of 0x0FFFFFFF (one cluster chain). /// directory cluster of 0x0FFFFFFF (one cluster chain).
/// ///
/// Argument: /// Argument:
/// IN/OUT image: File - The image file to write the FSInfo to. /// IN/OUT stream: anytype - The stream to write the FSInfo to.
/// IN fat32_header: Header - A valid FAT32 boot header for creating the FAT. /// IN fat32_header: Header - A valid FAT32 boot header for creating the FAT.
/// ///
/// Error File.WriteError || File.SeekError /// Error @TypeOf(stream).WriteError || @TypeOf(stream).SeekError
/// File.WriteError - If there is an error when writing to the image. See File.WriteError /// @TypeOf(stream).WriteError - If there is an error when writing. See the relevant error for the stream.
/// File.SeekError - If there is an error when seeking the image. See File.SeekError /// @TypeOf(stream).SeekError - If there is an error when seeking. See the relevant error for the stream.
/// ///
fn writeFAT(image: File, fat32_header: Header) (File.WriteError || File.SeekError)!void { fn writeFAT(stream: anytype, fat32_header: Header) (@TypeOf(stream).WriteError || @TypeOf(stream).SeekError)!void {
const seekable_stream = image.seekableStream(); const seekable_stream = stream.seekableStream();
const writer = image.writer(); const writer = stream.writer();
// This FAT is below the reserved sectors // This FAT is below the reserved sectors
try seekable_stream.seekTo(fat32_header.reserved_sectors * fat32_header.bytes_per_sector); try seekable_stream.seekTo(fat32_header.reserved_sectors * fat32_header.bytes_per_sector);
@ -439,19 +438,19 @@ pub const Fat32 = struct {
} }
/// ///
/// Write the FAT boot sector with the boot code and FAT32 header to the image. /// Write the FAT boot sector with the boot code and FAT32 header to the stream.
/// ///
/// Argument: /// Argument:
/// IN/OUT image: File - The image file to write the FSInfo to. /// IN/OUT stream: anytype - The stream to write the FSInfo to.
/// IN fat32_header: Header - A valid FAT32 boot header for creating the FAT. /// IN fat32_header: Header - A valid FAT32 boot header for creating the FAT.
/// ///
/// Error: File.WriteError || File.SeekError /// Error: @TypeOf(stream).WriteError || @TypeOf(stream).SeekError
/// File.WriteError - If there is an error when writing to the image. See File.WriteError. /// @TypeOf(stream).WriteError - If there is an error when writing. See the relevant error for the stream.
/// File.SeekError - If there is an error when seeking the image. See File.SeekError. /// @TypeOf(stream).SeekError - If there is an error when seeking. See the relevant error for the stream.
/// ///
fn writeBootSector(image: File, fat32_header: Header) (File.WriteError || File.SeekError)!void { fn writeBootSector(stream: anytype, fat32_header: Header) (@TypeOf(stream).WriteError || @TypeOf(stream).SeekError)!void {
const seekable_stream = image.seekableStream(); const seekable_stream = stream.seekableStream();
const writer = image.writer(); const writer = stream.writer();
var boot_sector: [512]u8 = undefined; var boot_sector: [512]u8 = undefined;
std.mem.copy(u8, &boot_sector, &bootsector_boot_code); std.mem.copy(u8, &boot_sector, &bootsector_boot_code);
@ -538,43 +537,38 @@ pub const Fat32 = struct {
/// user. The file will be saved to the path specified. /// user. The file will be saved to the path specified.
/// ///
/// Argument: /// Argument:
/// IN options: Options - The FAT32 options that the user can provide to change /// IN options: Options - The FAT32 options that the user can provide to change the
/// the parameters of a FAT32 image. /// parameters of a FAT32 image.
/// IN out_file_path: []const u8 - The location for which the FAT32 image will be created. /// IN stream: anytype - The stream to create a new FAT32 image. This stream must support
/// reader(), writer() and seekableStream() interfaces.
/// ///
/// Error: File.OpenError || File.WriteError || File.SeekError || Error /// Error: @TypeOf(stream).WriteError || @TypeOf(stream).SeekError || Error
/// File.OpenError || File.WriteError || File.SeekError - Error relating to file operations. See std.fs.File. /// @TypeOf(stream).WriteError - If there is an error when writing. See the relevant error for the stream.
/// @TypeOf(stream).SeekError - If there is an error when seeking. See the relevant error for the stream.
/// Error.InvalidOptionValue - In the user has provided invalid options. /// Error.InvalidOptionValue - In the user has provided invalid options.
/// Error.TooLarge - The image size is too small. < 17.5KB. /// Error.TooLarge - The stream size is too small. < 17.5KB.
/// Error.TooSmall - The image size is to large. > 2TB. /// Error.TooSmall - The stream size is to large. > 2TB.
/// ///
pub fn make(options: Options, out_file_path: []const u8) (File.OpenError || File.WriteError || File.SeekError || Error)!void { pub fn make(options: Options, stream: anytype) (@TypeOf(stream).WriteError || @TypeOf(stream).SeekError || Error)!void {
// First set up the header // First set up the header
const fat32_header = try Fat32.createFATHeader(options); const fat32_header = try Fat32.createFATHeader(options);
// Get the total image size again. As the above has a check for the image size, we don't need one here again // Get the total image size again. As the above has a check for the size, we don't need one here again
const image_size = std.mem.alignBackward(options.image_size, fat32_header.bytes_per_sector); const image_size = std.mem.alignBackward(options.image_size, fat32_header.bytes_per_sector);
// Open the out file // Initialise the stream with all zeros
const image = try std.fs.cwd().createFile(out_file_path, .{ .read = true }); try stream.writer().writeByteNTimes(0x00, image_size);
// If there was an error, delete the image as this will be invalid
errdefer (std.fs.cwd().deleteFile(out_file_path) catch unreachable);
defer image.close();
// Initialise the image with all zeros
try image.writer().writeByteNTimes(0x00, image_size);
// Write the boot sector with the bootstrap code and header and the backup boot sector. // Write the boot sector with the bootstrap code and header and the backup boot sector.
try Fat32.writeBootSector(image, fat32_header); try Fat32.writeBootSector(stream, fat32_header);
// Write the FAT and second FAT // Write the FAT and second FAT
try Fat32.writeFAT(image, fat32_header); try Fat32.writeFAT(stream, fat32_header);
// Calculate the usable clusters. // Calculate the usable clusters.
const usable_sectors = fat32_header.total_sectors - fat32_header.reserved_sectors - (fat32_header.fat_count * fat32_header.sectors_per_fat); const usable_sectors = fat32_header.total_sectors - fat32_header.reserved_sectors - (fat32_header.fat_count * fat32_header.sectors_per_fat);
const usable_clusters = @divFloor(usable_sectors, fat32_header.sectors_per_cluster) - 1; const usable_clusters = @divFloor(usable_sectors, fat32_header.sectors_per_cluster) - 1;
// Write the FSInfo and backup FSInfo sectors // Write the FSInfo and backup FSInfo sectors
try Fat32.writeFSInfo(image, fat32_header, usable_clusters, 2); try Fat32.writeFSInfo(stream, fat32_header, usable_clusters, 2);
} }
}; };