-
-
Save SkypLabs/bc5510838acf7d6a7e3562999091f4c0 to your computer and use it in GitHub Desktop.
Kaitai Struct - .DS_Store - Examples
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package com.ksydsstore.app; | |
import java.net.*; | |
import java.io.*; | |
import java.util.*; | |
import io.kaitai.struct.ByteBufferKaitaiStream; | |
import com.ksydsstore.app.DsStore.Block; | |
import com.ksydsstore.app.DsStore.Block.BlockData; | |
import com.ksydsstore.app.DsStore.MasterBlockRef; | |
import com.ksydsstore.app.DsStore.MasterBlockRef.MasterBlock; | |
public class App { | |
private DsStore dsStore; | |
private Set<String> filenames; | |
public static void main(String[] args) throws Exception { | |
// Random .DS_Store file found on GitHub. | |
URL url = new URL("https://raw.githubusercontent.com/Apress/traefik-api-gateway-microservices/main/ch07/.DS_Store"); | |
App parser = new App(url); | |
parser.printFilenames(); | |
} | |
public App(URL url) throws Exception { | |
this.filenames = new HashSet<String>(); | |
ByteArrayOutputStream baos = new ByteArrayOutputStream(); | |
InputStream is = null; | |
try { | |
is = url.openStream(); | |
byte[] byteChunk = new byte[4096]; | |
int n; | |
while ( (n = is.read(byteChunk)) > 0) { | |
baos.write(byteChunk, 0, n); | |
} | |
} | |
catch (IOException e) { | |
System.err.printf ("Failed while reading bytes from %s: %s", | |
url.toExternalForm(), e.getMessage()); | |
e.printStackTrace (); | |
} | |
finally { | |
if (is != null) { | |
is.close(); | |
} | |
} | |
this.dsStore = new DsStore(new ByteBufferKaitaiStream(baos.toByteArray())); | |
for (MasterBlockRef masterBlockRef : this.dsStore.buddyAllocatorBody().directories()) { | |
// Each B-tree directory has one master block comprising metadata. | |
MasterBlock masterBlock = masterBlockRef.masterBlock(); | |
long blockId = masterBlock.blockId(); | |
long numRecords = masterBlock.numRecords(); | |
Block rootBlock = masterBlock.rootBlock(); | |
// Traverse recursively the B-tree from its root block. | |
traverse(rootBlock); | |
} | |
} | |
private void traverse(Block block) throws Exception { | |
Block nextBlock = block.rightmostBlock(); | |
if (nextBlock != null) { | |
traverse(nextBlock); | |
} | |
for (BlockData blockData : block.data()) { | |
nextBlock = blockData.block(); | |
if (nextBlock != null) { | |
traverse(nextBlock); | |
} | |
this.filenames.add(blockData.record().filename().value()); | |
} | |
} | |
public void printFilenames() { | |
System.out.println("Filenames:"); | |
for (String filename : this.filenames) { | |
System.out.println(" " + filename); | |
} | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
from ds_store import DsStore | |
if __name__ == "__main__": | |
data = DsStore.from_file("ds_store_sample_2.bin") | |
# Use a set to avoid duplicates. | |
filenames = set() | |
def traverse(block): | |
""" | |
Traverse recursively the B-tree from the block given as parameter. | |
All filenames found in the block records are added to the global set of | |
filenames. | |
""" | |
next_block = block.rightmost_block | |
if type(next_block) is DsStore.Block: | |
traverse(next_block) | |
for data in block.data: | |
next_block = data.block | |
if type(next_block) is DsStore.Block: | |
traverse(next_block) | |
filenames.add(data.record.filename.value) | |
print(f"Number of directories: {data.buddy_allocator_body.num_directories}") | |
print(f"Number of blocks: {data.buddy_allocator_body.num_blocks}") | |
# One single DS_Store file can contain multiple B-tree directories. | |
for directory in data.buddy_allocator_body.directories: | |
# Each B-tree directory has one master block comprising metadata. | |
master_block = directory.master_block | |
master_block_id = master_block.block_id | |
nb_records = master_block.num_records | |
print(f"Master block {master_block_id} contains {nb_records} records") | |
# Traverse recursively the B-tree from its root block. | |
traverse(master_block.root_block) | |
# Display all filenames. | |
print("Filenames:") | |
for filename in filenames: | |
print(f" {filename}") |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment