Skip to content

Commit e9ba557

Browse files
committed
[emu・fat] implement emu disk detection and pc98 partition, bpb
1 parent 8a6edb0 commit e9ba557

29 files changed

+1790
-510
lines changed

README.md

+2-1
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@ https://jitpack.io/#umjammer/vavi-nio-file-discutils
3737
| iSCSI | 🚫 | | | | | | | | | | server [jscsi](https://github.com/sebastiangraf/jSCSI) |
3838
| NFS | 🚫 | | | | | | | | | | server [nfs4j](https://github.com/dcache/nfs4j) |
3939
| ODS | 🚫 | | | | | | | | | | server [vavi-net-ods](https://github.com/umjammer/vavi-net-ods) |
40+
| EMU | ✅ (nhd) | | | | | | | | | | [vavi-nio-file-emu](https://github.com/umjammer/vavi-nio-file-emu) [vavi-nio-file-fat](https://github.com/umjammer/vavi-nio-file-Fat) |
4041

4142
## Project Description
4243

@@ -169,6 +170,6 @@ Automated CI builds are available on [Github](https://github.com/umjammer/vavi-n
169170
* ~~https://github.com/AssafTzurEl/discUtils/commit/3853944811a16d6220dcb6e8d408561e05569e43~~
170171
* img ... https://github.com/hessu/bchunk
171172
* ~~file separator~~
172-
* pc98 partition (wip)
173+
* ~~pc98 partition~~ (done)
173174
* d88 floppy disk
174175
* qcow2

pom.xml

+1-1
Original file line numberDiff line numberDiff line change
@@ -196,7 +196,7 @@
196196
<dependency>
197197
<groupId>vavi</groupId>
198198
<artifactId>vavi-nio-file-emu</artifactId>
199-
<version>2.0.0</version>
199+
<version>2.0.1-SNAPSHOT</version>
200200
</dependency>
201201

202202
<dependency>

src/main/java/discUtils/core/FileSystemManager.java

+4
Original file line numberDiff line numberDiff line change
@@ -27,10 +27,12 @@
2727
import java.util.Arrays;
2828
import java.util.List;
2929
import java.util.ServiceLoader;
30+
import java.util.logging.Level;
3031

3132
import discUtils.core.vfs.VfsFileSystemFactory;
3233
import dotnet4j.io.BufferedStream;
3334
import dotnet4j.io.Stream;
35+
import vavi.util.Debug;
3436

3537

3638
/**
@@ -85,8 +87,10 @@ private static List<FileSystemInfo> doDetect(Stream stream, VolumeInfo volume) {
8587
BufferedStream detectStream = new BufferedStream(stream);
8688
List<FileSystemInfo> detected = new ArrayList<>();
8789
for (VfsFileSystemFactory factory : factories) {
90+
Debug.println(Level.FINE, factory);
8891
detected.addAll(Arrays.asList(factory.detect(detectStream, volume)));
8992
}
93+
Debug.println(Level.FINE, detected);
9094
return detected;
9195
}
9296
}

src/main/java/discUtils/core/VirtualDiskLayer.java

+3-2
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@
4040
* through to the layer underneath (all other layers).
4141
*/
4242
public abstract class VirtualDiskLayer implements Closeable {
43+
4344
/**
4445
* Gets the capacity of the disk (in bytes).
4546
*/
@@ -76,9 +77,9 @@ public String getFullPath() {
7677

7778
/**
7879
* Gets a {@link FileLocator} that can resolve relative paths, or
79-
* {@code null} .
80+
* {@code null}.
8081
*
81-
* Typically used to locate parent disks.
82+
* Typically, used to locate parent disks.
8283
*/
8384
public abstract FileLocator getRelativeFileLocator();
8485

src/main/java/discUtils/core/partitions/BiosPartitionRecord.java

+19-1
Original file line numberDiff line numberDiff line change
@@ -88,7 +88,7 @@ public int getIndex() {
8888
}
8989

9090
public boolean isValid() {
91-
return endHead != 0 || endSector != 0 || endCylinder != 0 || lbaLength != 0;
91+
return partitionType != 0 && (endHead != 0 || endSector != 0 || endCylinder != 0 || lbaLength != 0);
9292
}
9393

9494
private int lbaLength;
@@ -181,4 +181,22 @@ public void writeTo(byte[] buffer, int offset) {
181181
EndianUtilities.writeBytesLittleEndian(lbaStart, buffer, offset + 8);
182182
EndianUtilities.writeBytesLittleEndian(lbaLength, buffer, offset + 12);
183183
}
184+
185+
@Override
186+
public String toString() {
187+
return "BiosPartitionRecord{" +
188+
"lbaOffset=" + lbaOffset +
189+
", endCylinder=" + endCylinder +
190+
", endHead=" + endHead +
191+
", endSector=" + endSector +
192+
", index=" + index +
193+
", lbaLength=" + lbaLength +
194+
", lbaStart=" + lbaStart +
195+
", partitionType=" + partitionType +
196+
", startCylinder=" + startCylinder +
197+
", startHead=" + startHead +
198+
", startSector=" + startSector +
199+
", status=" + status +
200+
'}';
201+
}
184202
}

src/main/java/discUtils/core/partitions/BiosPartitionTable.java

+2-1
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@
4141
import discUtils.streams.util.Sizes;
4242
import discUtils.streams.util.StreamUtilities;
4343
import dotnet4j.io.Stream;
44+
import vavi.util.Debug;
4445

4546

4647
/**
@@ -160,7 +161,7 @@ public static boolean isValid(Stream disk) {
160161
for (BiosPartitionRecord record : readPrimaryRecords(bootSector)) {
161162
// If the partition extends beyond the end of the disk, this is
162163
// probably an invalid partition table
163-
if (record.getLBALength() != 0xFFFFFFFF &&
164+
if (record.getLBALength() != 0xFFFF_FFFF &&
164165
(record.getLBAStart() + record.getLBALength()) * Sizes.Sector > disk.getLength()) {
165166
return false;
166167
}

src/main/java/discUtils/core/partitions/PartitionTable.java

+5
Original file line numberDiff line numberDiff line change
@@ -26,11 +26,13 @@
2626
import java.util.List;
2727
import java.util.ServiceLoader;
2828
import java.util.UUID;
29+
import java.util.logging.Level;
2930

3031
import discUtils.core.VirtualDisk;
3132
import discUtils.core.raw.Disk;
3233
import discUtils.streams.util.Ownership;
3334
import dotnet4j.io.Stream;
35+
import vavi.util.Debug;
3436

3537

3638
/**
@@ -115,9 +117,12 @@ public static List<PartitionTable> getPartitionTables(VirtualDisk disk) {
115117
for (PartitionTableFactory factory : factories) {
116118
PartitionTable table = factory.detectPartitionTable(disk);
117119
if (table != null) {
120+
Debug.println(Level.FINE, factory + ", " + table);
118121
tables.add(table);
119122
}
123+
factory.adhoc(tables);
120124
}
125+
Debug.println(Level.FINE, tables);
121126
return tables;
122127
}
123128

src/main/java/discUtils/core/partitions/PartitionTableFactory.java

+5
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,8 @@
2222

2323
package discUtils.core.partitions;
2424

25+
import java.util.List;
26+
2527
import discUtils.core.VirtualDisk;
2628
import dotnet4j.io.Stream;
2729

@@ -46,4 +48,7 @@ public interface PartitionTableFactory {
4648
boolean detectIsPartitioned(Stream s);
4749

4850
PartitionTable detectPartitionTable(VirtualDisk disk);
51+
52+
default void adhoc(List<PartitionTable> tables) {
53+
}
4954
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,109 @@
1+
/*
2+
* Copyright (c) 2022 by Naohide Sano, All rights reserved.
3+
*
4+
* Programmed by Naohide Sano
5+
*/
6+
7+
package discUtils.core.pc98;
8+
9+
import java.io.ByteArrayInputStream;
10+
import java.io.IOException;
11+
12+
import discUtils.fat.BootSector;
13+
import discUtils.fat.FatType;
14+
import discUtils.streams.util.StreamUtilities;
15+
import dotnet4j.io.Stream;
16+
import vavi.util.serdes.Serdes;
17+
import vavix.io.fat.PC98BiosParameterBlock;
18+
19+
20+
/**
21+
* Pc98BootSector.
22+
*
23+
* @author <a href="mailto:umjammer@gmail.com">Naohide Sano</a> (nsano)
24+
* @version 0.00 2022-08-06 nsano initial version <br>
25+
*/
26+
public class Pc98BootSector implements BootSector {
27+
28+
private PC98BiosParameterBlock bpb;
29+
30+
public Pc98BootSector(Stream stream) {
31+
try {
32+
byte[] sector = StreamUtilities.readExact(stream, 512);
33+
ByteArrayInputStream bais = new ByteArrayInputStream(sector);
34+
35+
this.bpb = new PC98BiosParameterBlock();
36+
Serdes.Util.deserialize(bais, bpb);
37+
//System.err.println("■ bootRecord ----\n" + bpb);
38+
bpb.compute();
39+
//System.err.println("■ bootRecord ----\n" + bpb);
40+
} catch (IOException e) {
41+
throw new dotnet4j.io.IOException(e);
42+
}
43+
}
44+
45+
@Override
46+
public int getFatCount() {
47+
return bpb.numberOfFAT;
48+
}
49+
50+
@Override
51+
public byte getActiveFat() {
52+
return 0;
53+
}
54+
55+
@Override
56+
public int getBytesPerSector() {
57+
return bpb.getBytesPerSector();
58+
}
59+
60+
@Override
61+
public long getFatSize() {
62+
return bpb.numberOfFATSector;
63+
}
64+
65+
@Override
66+
public FatType getFatVariant() {
67+
return FatType.valueOf(bpb.getFatType().getValue());
68+
}
69+
70+
@Override
71+
public String getOemName() {
72+
return bpb.oemLabel;
73+
}
74+
75+
@Override
76+
public int getReservedSectorCount() {
77+
return bpb.reservedSectors;
78+
}
79+
80+
@Override
81+
public int getSectorsPerCluster() {
82+
return bpb.getSectorsPerCluster();
83+
}
84+
85+
@Override
86+
public long getTotalSectors() {
87+
return bpb.numberOfSmallSectors != 0 ? bpb.numberOfSmallSectors : bpb.numberOfLargeSectors;
88+
}
89+
90+
@Override
91+
public String getVolumeLabel() {
92+
return bpb.volumeLabel;
93+
}
94+
95+
@Override
96+
public int getMaxRootDirectoryEntries() {
97+
return bpb.maxRootDirectoryEntries;
98+
}
99+
100+
@Override
101+
public long getRootDirectoryCluster() {
102+
return bpb.getStartClusterOfRootDirectory();
103+
}
104+
105+
@Override
106+
public int getFatSize16() {
107+
return bpb.numberOfFATSector;
108+
}
109+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
1+
/*
2+
* Copyright (c) 2022 by Naohide Sano, All rights reserved.
3+
*
4+
* Programmed by Naohide Sano
5+
*/
6+
7+
package discUtils.core.pc98;
8+
9+
import java.io.ByteArrayInputStream;
10+
import java.io.IOException;
11+
import java.nio.charset.Charset;
12+
import java.util.logging.Level;
13+
14+
import discUtils.core.DiscFileSystem;
15+
import discUtils.core.FileSystemInfo;
16+
import discUtils.core.FileSystemParameters;
17+
import discUtils.core.VolumeInfo;
18+
import discUtils.core.coreCompat.EncodingHelper;
19+
import discUtils.core.vfs.VfsFileSystemFactory;
20+
import discUtils.core.vfs.VfsFileSystemInfo;
21+
import discUtils.fat.BootSector;
22+
import discUtils.fat.FatFileSystem;
23+
import discUtils.streams.util.Ownership;
24+
import discUtils.streams.util.StreamUtilities;
25+
import dotnet4j.io.Stream;
26+
import vavi.util.Debug;
27+
import vavi.util.serdes.Serdes;
28+
import vavix.io.fat.PC98BiosParameterBlock;
29+
30+
31+
/**
32+
* Pc98FileSystemFactory.
33+
*
34+
* @author <a href="mailto:umjammer@gmail.com">Naohide Sano</a> (nsano)
35+
* @version 0.00 2022-07-24 nsano initial version <br>
36+
*/
37+
public class Pc98FileSystemFactory implements VfsFileSystemFactory {
38+
39+
public FileSystemInfo[] detect(Stream stream, VolumeInfo volume) {
40+
if (detectFAT(stream)) {
41+
return new FileSystemInfo[] {
42+
new VfsFileSystemInfo("PC98_FAT", "NEC FAT", this::open)
43+
};
44+
}
45+
46+
return new FileSystemInfo[0];
47+
}
48+
49+
private DiscFileSystem open(Stream stream, VolumeInfo volumeInfo, FileSystemParameters parameters) {
50+
BootSector bs = new Pc98BootSector(stream);
51+
parameters.setFileNameEncoding(EncodingHelper.forCodePage(932)); // TODO system property
52+
return new FatFileSystem(stream, bs, Ownership.None, parameters);
53+
}
54+
55+
/**
56+
* Detects if a stream contains a FAT file system.
57+
*
58+
* @param stream The stream to inspect.
59+
* @return {@code true} if the stream appears to be a FAT file system, else
60+
* {@code false}.
61+
*/
62+
private static boolean detectFAT(Stream stream) {
63+
if (stream.getLength() < 512) {
64+
Debug.println(Level.FINE, "stream length < 512");
65+
return false;
66+
}
67+
68+
stream.setPosition(0);
69+
byte[] sector = StreamUtilities.readExact(stream, 512);
70+
ByteArrayInputStream bais = new ByteArrayInputStream(sector);
71+
72+
PC98BiosParameterBlock bpb;
73+
try {
74+
bpb = new PC98BiosParameterBlock();
75+
Serdes.Util.deserialize(bais, bpb);
76+
} catch (IOException e) {
77+
Debug.println(Level.FINE, e);
78+
return false;
79+
}
80+
81+
return bpb.validate();
82+
}
83+
}

0 commit comments

Comments
 (0)