Skip to content

Instantly share code, notes, and snippets.

@SkypLabs
Last active January 17, 2023 19:49
Show Gist options
  • Save SkypLabs/bc5510838acf7d6a7e3562999091f4c0 to your computer and use it in GitHub Desktop.
Save SkypLabs/bc5510838acf7d6a7e3562999091f4c0 to your computer and use it in GitHub Desktop.
Kaitai Struct - .DS_Store - Examples
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);
}
}
}
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