Skip to content

Instantly share code, notes, and snippets.

@Deamon5550
Created July 29, 2016 21:18
Show Gist options
  • Save Deamon5550/4184568d1b295f2d807073bc43a583ff to your computer and use it in GitHub Desktop.
Save Deamon5550/4184568d1b295f2d807073bc43a583ff to your computer and use it in GitHub Desktop.
My own filesystem
#include "LLFS.h"
#include <iostream>
#define BLOCK_SIZE 512
#define BLOCK_COUNT 4096
namespace Filesystem {
void format(char *disk) {
std::cout << "Formatting llfs disk '" << disk << "'\n";
char *data = (char *) malloc(BLOCK_SIZE * BLOCK_COUNT);
memset(data, 0, BLOCK_SIZE * BLOCK_COUNT);
superblock_t *superblock = (superblock_t *) data;
superblock->type = 0x53464C4C;
superblock->file_count = 1;
superblock->inode_count = 1;
printf(" Marking all blocks as available except superblock and inode blocks\n");
// mark all blocks as available, except the first 10, and the inode blocks
char *free_blocks = (char *) data + 512;
memset(free_blocks, 0xFF, 512);
for (int i = 0; i < 4096; i++) {
if (i < 10 || (i % 256) == 255) {
free_blocks[i / 8] &= ~(1 << (i % 8));
}
}
printf(" Marking all inodes as available\n");
char *free_inodes = (char *) data + 1024;
memset(free_inodes, 0xFF, 32);
printf(" Allocating first inode for root directory\n");
free_inodes[0] &= ~(1);
inode_t *rootInode = (inode_t *) data + (255 * 16);
rootInode->file_size = 512;
rootInode->file_type = FileType::DIR;
rootInode->blocks[0] = 10;
printf(" Allocating first block for root directory\n");
free_blocks[1] &= ~(1 << (2));
char *dir = data + 10 * 512;
strncpy(dir + 1, ".", 30);
strncpy(dir + 33, "..", 30);
for (int i = 2; i < 16; i++) {
dir[i*32] = (unsigned char) 0xFF;
}
std::FILE *fdisk = fopen(disk, "w+");
fwrite(data, 1, 512 * 4096, fdisk);
fclose(fdisk);
free(data);
}
LLFS *mount(char *disk) {
std::FILE *fdisk = fopen(disk, "r+");
LLFS *fs = new LLFS(fdisk);
return fs;
}
void unmount(LLFS *fs) {
fs->sync();
}
LLFS::LLFS(std::FILE *fdisk) : disk(fdisk) {
superblock = (superblock_t *) malloc(512);
free_blocks = (char *) malloc(512);
free_inodes = (char *) malloc(32);
fseek(disk, 0, SEEK_SET);
fread(superblock, 1, 512, disk);
fread(free_blocks, 1, 512, disk);
fread(free_inodes, 1, 32, disk);
for (int i = 0; i < 32; i++) {
inode_block_cache[i] = nullptr;
}
open_files_size = 32;
open_files_index = 0;
open_files = (File**) malloc(sizeof(File *) * open_files_size);
static_cache_size = 0;
static_cache_index = 0;
static_cache = nullptr;
dynamic_cache_size = 32;
dynamic_cache_index = 0;
dynamic_cache = (BlockCacheEntry **) malloc(sizeof(BlockCacheEntry*) * dynamic_cache_size);
root = new File(this, nullptr, "/", "/", 0, getInode(0), true);
}
/*LLFS::~LLFS() {
sync();
fclose(disk);
delete superblock;
delete free_blocks;
delete free_inodes;
for (int i = 0; i < 32; i++) {
if (inode_block_cache[i] != nullptr) {
delete inode_block_cache[i];
}
}
for (int i = 0; i < open_files_index; i++) {
delete open_files[i];
}
delete root;
delete open_files;
delete[] inode_block_cache;
}*/
File *LLFS::open(char *path) {
if (strcmp("/", path) == 0) {
return root;
}
for (int i = 0; i < open_files_index; i++) {
if (strcmp(open_files[i]->getName(), path) == 0) {
std::cout << "File already open\n";
return nullptr;
}
}
int len = strlen(path);
char part[50];
File *parent = root;
int o = 0;
for (int i = 1; i < len; i++) {
char next = path[i];
if (next == '/') {
part[o] = '\0';
parent = parent->getChildDir(part);
o = 0;
} else {
part[o++] = next;
}
}
part[o] = '\0';
if (o == 0) {
return parent;
}
File *file = parent->getChild(part);
open_files[open_files_index++] = file;
return file;
}
void LLFS::close(File *file) {
bool found = false;
for (int i = 0; i < open_files_index; i++) {
if (found) {
open_files[i - 1] = open_files[i];
} else {
if (open_files[i] == file) {
found = true;
}
}
}
if (found) {
open_files_index--;
}
delete file;
}
inode_t *LLFS::getInode(int number) {
int inode_block = number / 16;
if (inode_block_cache[inode_block] == nullptr) {
std::cout << "Loading inode block " << inode_block << "\n";
char *inode_block_data = (char *) malloc(512);
fseek(disk, (inode_block * 256 + 255) * 512, SEEK_SET);
fread(inode_block_data, 1, 512, disk);
inode_block_cache[inode_block] = inode_block_data;
}
std::cout << "getting inode " << number << "\n";
inode_t *inode = (inode_t *) (inode_block_cache[inode_block] + (number % 16) * 32);
return inode;
}
unsigned int LLFS::createInode() {
int number = -1;
// TODO continue from same point each time
for (int i = 0; i < 32; i++) {
unsigned char next = free_inodes[i];
if (next != 0) {
int o;
for (o = 0; o < 8; o++) {
if (((next >> o) & 1) == 1) {
number = i * 8 + o;
break;
}
}
break;
}
}
if (number == -1) {
printf("Error: no free inodes for allocation");
return NULL;
}
free_inodes[number / 8] &= ~(1 << (number % 8));
printf("Allocating inode %d\n", number);
superblock->inode_count++;
return number;
}
BlockCacheEntry *LLFS::allocateBlock() {
int number = -1;
// TODO continue from same point each time
for (int i = 0; i < 512; i++) {
unsigned char next = free_blocks[i];
if (next != 0) {
int o;
for (o = 0; o < 8; o++) {
if (((next >> o) & 1) == 1) {
number = i * 8 + o;
break;
}
}
break;
}
}
if (number == -1) {
printf("Error: no free blocks for allocation");
return nullptr;
}
free_blocks[number / 8] &= ~(1 << (number % 8));
printf("Allocating block %d\n", number);
return getBlock(number);
}
void LLFS::sync() {
fseek(disk, 0, SEEK_SET);
fwrite(superblock, 1, 512, disk);
fwrite(free_blocks, 1, 512, disk);
fwrite(free_inodes, 1, 32, disk);
// if we crash here then we just have to notice that an inode/block is ununsed when we walk the tree
for (int i = 0; i < 32; i++) {
if (inode_block_cache[i] != nullptr) {
std::cout << "Saving inode block " << i << "\n";
fseek(disk, (i * 256 + 255) * 512, SEEK_SET);
fwrite(inode_block_cache[i], 1, 512, disk);
}
}
// if we crash below here then we lost data but not consistency
for (int i = 0; i < dynamic_cache_index; i++) {
BlockCacheEntry *entry = dynamic_cache[i];
if (entry->modified) {
fseek(disk, entry->number * 512, SEEK_SET);
fwrite(entry->block, 1, 512, disk);
}
delete entry;
dynamic_cache[i] = nullptr;
}
dynamic_cache_index = 0;
}
BlockCacheEntry *LLFS::getBlock(int number) {
if (static_cache_index > 0) {
}
if (dynamic_cache_index > 0) {
for (int i = 0; i < dynamic_cache_index; i++) {
BlockCacheEntry *entry = dynamic_cache[i];
if (entry->number == number) {
std::cout << "Fetched block " << number << " from dynamic cache\n";
return entry;
}
}
}
if (dynamic_cache_index == dynamic_cache_size) {
std::cout << "Dynamic cache full, syncing to disk\n";
sync();
}
std::cout << "Loading block " << number << " from disk\n";
char *block = (char*) malloc(512);
fseek(disk, number*512, SEEK_SET);
fread(block, 1, 512, disk);
BlockCacheEntry *entry = new BlockCacheEntry(number, block);
dynamic_cache[dynamic_cache_index++] = entry;
return entry;
}
std::FILE *LLFS::getDisk() {
return disk;
}
void LLFS::releaseBlock(int num) {
free_blocks[num/8] |= (1 << (num % 8));
std::cout << "Releasing block " << num << "\n";
}
void LLFS::releaseInode(int num) {
free_inodes[num / 8] |= (1 << (num % 8));
int inode_block = num / 16;
if (inode_block_cache[inode_block] == nullptr) {
std::cout << "Loading inode block " << inode_block << "\n";
char *inode_block_data = (char *) malloc(512);
fseek(disk, (inode_block * 256 + 255) * 512, SEEK_SET);
fread(inode_block_data, 1, 512, disk);
inode_block_cache[inode_block] = inode_block_data;
}
memset(inode_block_cache[inode_block] + (num % 16) * 32, 0, 32);
std::cout << "Releasing inode " << num << "\n";
}
File::File(LLFS *fs, File *parent, char *name, char *path, int inode_number, inode_t *in, bool isDir) :
fs(fs), parent(parent), file_name(name), file_path(path), inode(in), isDir(isDir), inode_number(inode_number) {
std::cout << "Creating file '" << path << " \n";
created = inode != nullptr;
seek_pos = 0;
if (isDir) {
entries = (DirectoryEntry**) malloc(sizeof(DirectoryEntry*) * 32);
entries_size = 32;
entries_index = 0;
if (created) {
BlockCacheEntry *data = fs->getBlock(inode->blocks[0]);
char *block = data->block;
for (int i = 0; i < 16; i++) {
unsigned char inode = block[i * 32];
if (inode != 0xFF) {
char *fname = (char*) malloc(31);
memset(fname, 0, 31);
strncpy(fname, (char *) (block + i * 32 + 1), 30);
DirectoryEntry *entry = new DirectoryEntry(inode, fname);
std::cout << "Loaded dir entry " << fname << " for directory " << file_path << "\n";
entries[entries_index++] = entry;
}
}
}
} else {
entries = nullptr;
entries_size = 0;
entries_index = 0;
}
}
char *File::getPath() {
return file_path;
}
char *File::getName() {
return file_name;
}
File *File::getParent() {
return parent;
}
bool File::exists() {
return created;
}
bool File::isFile() {
return !isDir;
}
bool File::isDirectory() {
return isDir;
}
File *File::getChild(char *name) {
if (!isDir) {
std::cout << "[Error: cannot get child of non-directory" << file_path << "]\n";
return nullptr;
}
std::cout << "Getting child " << name << " from " << file_path << "\n";
char *fpath = (char*) malloc(250);
strcpy(fpath, file_path);
strcat(fpath, name);
char *fname = (char*)malloc(strlen(name+1));
strcpy(fname, name);
for (int i = 0; i < entries_index; i++) {
if (strcmp(entries[i]->name, name) == 0) {
return new File(fs, this, fname, fpath, entries[i]->inode, fs->getInode(entries[i]->inode), false);
}
}
return new File(fs, this, fname, fpath, -1, nullptr, false);
}
File *File::getChildDir(char *name) {
if (!isDir) {
std::cout << "[Error: cannot get child of non-directory" << file_path << "]\n";
return nullptr;
}
// TODO needs to call open
std::cout << "Getting child directory " << name << " from " << file_path << "\n";
char *fpath = (char*) malloc(250);
strcpy(fpath, file_path);
strcat(fpath, name);
strcat(fpath, "/");
char *fname = (char*) malloc(strlen(name + 1));
strcpy(fname, name);
for (int i = 0; i < entries_index; i++) {
if (strcmp(entries[i]->name, name) == 0) {
return new File(fs, this, fname, fpath, entries[i]->inode, fs->getInode(entries[i]->inode), true);
}
}
return new File(fs, this, fname, fpath, -1, nullptr, true);
}
DirectoryEntry **File::getDirectoryContents() {
return entries;
}
void File::create() {
if (isDir) {
std::cout << "Use mkdir instead\n";
return;
}
if (created) {
std::cout << "File already created\n";
return;
}
created = true;
inode_number = fs->createInode();
std::cout << "Creating new file '" << file_path << "' " << inode_number << " \n";
inode = fs->getInode(inode_number);
inode->file_size = 0;
inode->file_type = FileType::FILE;
parent->addFile(this);
}
void File::addFile(File *child) {
if (!isDir) {
std::cout << "Can only add files to directories\n";
return;
}
std::cout << "Adding file " << child->file_path << " to directory " << file_path << "\n";
DirectoryEntry *entry = new DirectoryEntry(child->inode_number, child->file_name);
entries[entries_index++] = entry;
BlockCacheEntry *block = fs->getBlock(inode->blocks[0]);
std::cout << "Saving directory contents of " << file_path << " to block " << inode->blocks[0] << "\n";
block->modified = true;
for (int i = 0; i < 16; i++) {
if (i >= entries_index) {
block->block[i * 32] = (unsigned char) 0xFF;
} else {
block->block[i * 32] = entries[i]->inode;
strncpy((char*)(block->block + i * 32 + 1), entries[i]->name, 31);
}
}
}
void File::seek(int pos) {
seek_pos = pos;
std::cout << "Seeking file " << file_path << " to position " << pos << "\n";
}
void File::write(char *src, int len) {
std::cout << "Writing " << len << " bytes to " << file_path << " at position " << seek_pos << "\n";
int remaining = len;
int offset = 0;
while (remaining > 0) {
int block_pos = seek_pos / 512;
BlockCacheEntry *block = nullptr;
if (inode->blocks[block_pos] == 0) {
block = fs->allocateBlock();
inode->blocks[block_pos] = block->number;
} else {
block = fs->getBlock(inode->blocks[block_pos]);
}
int subpos = seek_pos % 512;
int sublen = 512 - subpos;
if (remaining < sublen) {
sublen = remaining;
}
memcpy(block->block + subpos, src + offset, sublen);
block->modified = true;
seek_pos += sublen;
remaining -= sublen;
offset += sublen;
}
if (seek_pos > inode->file_size) {
inode->file_size = seek_pos;
std::cout << "new file size is " << inode->file_size << "\n";
}
}
int File::read(char *dest, int len) {
if (seek_pos + len >= inode->file_size) {
len = inode->file_size - seek_pos;
}
std::cout << "Reading " << len << " bytes from file " << file_path << " at position " << seek_pos << "\n";
int remaining = len;
int offset = 0;
while (remaining > 0) {
int block_pos = seek_pos / 512;
BlockCacheEntry *block = nullptr;
if (inode->blocks[block_pos] == 0) {
block = fs->allocateBlock();
inode->blocks[block_pos] = block->number;
} else {
block = fs->getBlock(inode->blocks[block_pos]);
}
int subpos = seek_pos % 512;
int sublen = 512 - subpos;
if (remaining < sublen) {
sublen = remaining;
}
memcpy(dest + offset, block->block + subpos, sublen);
seek_pos += sublen;
offset += sublen;
remaining -= sublen;
}
return len;
}
void File::mkdir() {
if (!isDir) {
std::cout << "Cannot make a directory in a file\n";
return;
}
if (created) {
std::cout << "Directory already created\n";
return;
}
created = true;
inode_number = fs->createInode();
std::cout << "Creating new dir '" << file_path << "' " << inode_number << " \n";
inode = fs->getInode(inode_number);
inode->file_size = 512;
inode->file_type = FileType::DIR;
parent->addFile(this);
entries = (DirectoryEntry**) malloc(sizeof(DirectoryEntry*) * 32);
entries_size = 32;
entries_index = 0;
DirectoryEntry *self_dir = new DirectoryEntry(inode_number, ".");
DirectoryEntry *parent_dir = new DirectoryEntry(parent->inode_number, "..");
entries[entries_index++] = self_dir;
entries[entries_index++] = parent_dir;
BlockCacheEntry *data = fs->allocateBlock();
inode->blocks[0] = data->number;
std::cout << "Saving directory contents of " << file_path << " to block " << inode->blocks[0] << "\n";
data->modified = true;
for (int i = 0; i < 16; i++) {
if (i >= entries_index) {
data->block[i * 32] = (unsigned char) 0xFF;
} else {
data->block[i * 32] = entries[i]->inode;
strncpy((char*) (data->block + i * 32 + 1), entries[i]->name, 31);
}
}
}
void File::remove() {
if (parent == nullptr) {
std::cout << "Cannot delete the root directory\n";
}
if (isDir) {
std::cout << "Deleting directory " << file_path << "\n";
for (int i = 0; i < entries_index; i++) {
DirectoryEntry *entry = entries[i];
inode_t *child_inode = fs->getInode(entry->inode);
if (child_inode->file_type == FileType::DIR) {
File *child_dir = getChildDir(entry->name);
child_dir->remove();
} else {
File *child = getChild(entry->name);
child->remove();
}
}
} else {
std::cout << "Deleting file " << file_path << "\n";
}
parent->removeFile(inode_number);
for (int i = 0; i < 10; i++) {
if (inode->blocks[i] != 0) {
fs->releaseBlock(inode->blocks[i]);
}
}
fs->releaseInode(inode_number);
}
void File::removeFile(int inode_num) {
if (!isDir) {
std::cout << "Can only remove files from directories\n";
return;
}
bool found = false;
DirectoryEntry *found_entry = nullptr;
for (int i = 0; i < entries_index; i++) {
if (found) {
entries[i - 1] = entries[i];
} else {
if (entries[i]->inode == inode_num) {
found = true;
found_entry = entries[i];
}
}
}
if (found_entry == nullptr) {
std::cout << "File with inode " << inode_num << " not found in directory " << file_path << "\n";
return;
}
entries_index--;
delete found_entry;
BlockCacheEntry *block = fs->getBlock(inode->blocks[0]);
std::cout << "Saving directory contents of " << file_path << " to block " << inode->blocks[0] << "\n";
block->modified = true;
for (int i = 0; i < 16; i++) {
if (i >= entries_index) {
block->block[i * 32] = (unsigned char) 0xFF;
memset(block->block + i * 32 + 1, 0, 31);
} else {
block->block[i * 32] = entries[i]->inode;
strncpy((char*) (block->block + i * 32 + 1), entries[i]->name, 31);
}
}
}
}
#pragma once
#include <cstdio>
namespace Filesystem {
#pragma pack(push, 1)
typedef struct superblock_t {
int type; // the file system type specifier (always the string LLFS)
int file_count; // the count of all files in the system
int inode_count; // the count of all allocated inodes in the system
} superblock_t;
typedef struct inode_t {
int file_size; // the size of the file in bytes
int file_type; // the file type
short blocks[10]; // the first 10 block refs
short single_indirect; // an inode ref containing refs to 16 more inodes each containing 16 block refs
short double_indirect; // two layers of indirection above ^
} inode_t;
#pragma pack(pop)
enum FileType {
FILE,
DIR,
LINK
};
class BlockCacheEntry {
public:
BlockCacheEntry(int number, char *block) : number(number), block(block), modified(false) {}
unsigned int number;
char *block;
bool modified;
};
class DirectoryEntry {
public:
DirectoryEntry(int inode, char *name) : inode(inode), name(name) {}
unsigned char inode;
char *name;
};
class LLFS;
class File {
public:
File(LLFS *fs, File *parent, char *name, char *path, int inode_number, inode_t *inode, bool isDir);
char *getPath();
char *getName();
File *getParent();
bool exists();
bool isFile();
bool isDirectory();
void mkdir();
void create();
void remove();
void seek(int position);
int read(char *dest, int length);
void write(char *src, int length);
File *getChild(char *name);
File *getChildDir(char *name);
DirectoryEntry **getDirectoryContents();
private:
LLFS *fs;
bool isDir;
bool created;
File *parent;
char *file_name;
char *file_path;
inode_t *inode;
unsigned int inode_number;
int seek_pos;
DirectoryEntry **entries;
int entries_size;
int entries_index;
void addFile(File *child);
void removeFile(int inode);
};
class LLFS {
public:
LLFS(std::FILE *disk);
//~LLFS();
File *open(char *path);
void close(File *file);
void sync();
std::FILE *getDisk();
friend class File;
private:
std::FILE *disk;
superblock_t *superblock;
char *free_blocks;
char *free_inodes;
char *inode_block_cache[32];
BlockCacheEntry **static_cache;
int static_cache_size;
int static_cache_index;
BlockCacheEntry **dynamic_cache;
int dynamic_cache_size;
int dynamic_cache_index;
File *root;
File **open_files;
int open_files_size;
int open_files_index;
inode_t *getInode(int number);
unsigned int createInode();
BlockCacheEntry *getBlock(int number);
BlockCacheEntry *allocateBlock();
void releaseBlock(int block);
void releaseInode(int inode);
};
void format(char *disk);
LLFS *mount(char *disk);
void unmount(LLFS *fs);
}
λ hexdump vdisk
00000000: 4C 4C 46 53 01 00 00 00 - 03 00 00 00 00 00 00 00 |LLFS |
00000010: 00 00 00 00 00 00 00 00 - 00 00 00 00 00 00 00 00 | |
*
00000200: 00 E0 FF FF FF FF FF FF - FF FF FF FF FF FF FF FF | |
00000210: FF FF FF FF FF FF FF FF - FF FF FF FF FF FF FF 7F | |
00000220: FF FF FF FF FF FF FF FF - FF FF FF FF FF FF FF FF | |
00000230: FF FF FF FF FF FF FF FF - FF FF FF FF FF FF FF 7F | |
00000240: FF FF FF FF FF FF FF FF - FF FF FF FF FF FF FF FF | |
00000250: FF FF FF FF FF FF FF FF - FF FF FF FF FF FF FF 7F | |
00000260: FF FF FF FF FF FF FF FF - FF FF FF FF FF FF FF FF | |
00000270: FF FF FF FF FF FF FF FF - FF FF FF FF FF FF FF 7F | |
00000280: FF FF FF FF FF FF FF FF - FF FF FF FF FF FF FF FF | |
00000290: FF FF FF FF FF FF FF FF - FF FF FF FF FF FF FF 7F | |
000002a0: FF FF FF FF FF FF FF FF - FF FF FF FF FF FF FF FF | |
000002b0: FF FF FF FF FF FF FF FF - FF FF FF FF FF FF FF 7F | |
000002c0: FF FF FF FF FF FF FF FF - FF FF FF FF FF FF FF FF | |
000002d0: FF FF FF FF FF FF FF FF - FF FF FF FF FF FF FF 7F | |
000002e0: FF FF FF FF FF FF FF FF - FF FF FF FF FF FF FF FF | |
000002f0: FF FF FF FF FF FF FF FF - FF FF FF FF FF FF FF 7F | |
00000300: FF FF FF FF FF FF FF FF - FF FF FF FF FF FF FF FF | |
00000310: FF FF FF FF FF FF FF FF - FF FF FF FF FF FF FF 7F | |
00000320: FF FF FF FF FF FF FF FF - FF FF FF FF FF FF FF FF | |
00000330: FF FF FF FF FF FF FF FF - FF FF FF FF FF FF FF 7F | |
00000340: FF FF FF FF FF FF FF FF - FF FF FF FF FF FF FF FF | |
00000350: FF FF FF FF FF FF FF FF - FF FF FF FF FF FF FF 7F | |
00000360: FF FF FF FF FF FF FF FF - FF FF FF FF FF FF FF FF | |
00000370: FF FF FF FF FF FF FF FF - FF FF FF FF FF FF FF 7F | |
00000380: FF FF FF FF FF FF FF FF - FF FF FF FF FF FF FF FF | |
00000390: FF FF FF FF FF FF FF FF - FF FF FF FF FF FF FF 7F | |
000003a0: FF FF FF FF FF FF FF FF - FF FF FF FF FF FF FF FF | |
000003b0: FF FF FF FF FF FF FF FF - FF FF FF FF FF FF FF 7F | |
000003c0: FF FF FF FF FF FF FF FF - FF FF FF FF FF FF FF FF | |
000003d0: FF FF FF FF FF FF FF FF - FF FF FF FF FF FF FF 7F | |
000003e0: FF FF FF FF FF FF FF FF - FF FF FF FF FF FF FF FF | |
000003f0: FF FF FF FF FF FF FF FF - FF FF FF FF FF FF FF 7F | |
00000400: F8 FF FF FF FF FF FF FF - FF FF FF FF FF FF FF FF | |
00000410: FF FF FF FF FF FF FF FF - FF FF FF FF FF FF FF FF | |
00000420: 00 00 00 00 00 00 00 00 - 00 00 00 00 00 00 00 00 | |
*
00001400: 00 2E 00 00 00 00 00 00 - 00 00 00 00 00 00 00 00 | . |
00001410: 00 00 00 00 00 00 00 00 - 00 00 00 00 00 00 00 00 | |
00001420: 00 2E 2E 00 00 00 00 00 - 00 00 00 00 00 00 00 00 | .. |
00001430: 00 00 00 00 00 00 00 00 - 00 00 00 00 00 00 00 00 | |
00001440: 01 74 6D 70 00 00 00 00 - 00 00 00 00 00 00 00 00 | tmp |
00001450: 00 00 00 00 00 00 00 00 - 00 00 00 00 00 00 00 00 | |
00001460: FF 00 00 00 00 00 00 00 - 00 00 00 00 00 00 00 00 | |
00001470: 00 00 00 00 00 00 00 00 - 00 00 00 00 00 00 00 00 | |
00001480: FF 00 00 00 00 00 00 00 - 00 00 00 00 00 00 00 00 | |
00001490: 00 00 00 00 00 00 00 00 - 00 00 00 00 00 00 00 00 | |
000014a0: FF 00 00 00 00 00 00 00 - 00 00 00 00 00 00 00 00 | |
000014b0: 00 00 00 00 00 00 00 00 - 00 00 00 00 00 00 00 00 | |
000014c0: FF 00 00 00 00 00 00 00 - 00 00 00 00 00 00 00 00 | |
000014d0: 00 00 00 00 00 00 00 00 - 00 00 00 00 00 00 00 00 | |
000014e0: FF 00 00 00 00 00 00 00 - 00 00 00 00 00 00 00 00 | |
000014f0: 00 00 00 00 00 00 00 00 - 00 00 00 00 00 00 00 00 | |
00001500: FF 00 00 00 00 00 00 00 - 00 00 00 00 00 00 00 00 | |
00001510: 00 00 00 00 00 00 00 00 - 00 00 00 00 00 00 00 00 | |
00001520: FF 00 00 00 00 00 00 00 - 00 00 00 00 00 00 00 00 | |
00001530: 00 00 00 00 00 00 00 00 - 00 00 00 00 00 00 00 00 | |
00001540: FF 00 00 00 00 00 00 00 - 00 00 00 00 00 00 00 00 | |
00001550: 00 00 00 00 00 00 00 00 - 00 00 00 00 00 00 00 00 | |
00001560: FF 00 00 00 00 00 00 00 - 00 00 00 00 00 00 00 00 | |
00001570: 00 00 00 00 00 00 00 00 - 00 00 00 00 00 00 00 00 | |
00001580: FF 00 00 00 00 00 00 00 - 00 00 00 00 00 00 00 00 | |
00001590: 00 00 00 00 00 00 00 00 - 00 00 00 00 00 00 00 00 | |
000015a0: FF 00 00 00 00 00 00 00 - 00 00 00 00 00 00 00 00 | |
000015b0: 00 00 00 00 00 00 00 00 - 00 00 00 00 00 00 00 00 | |
000015c0: FF 00 00 00 00 00 00 00 - 00 00 00 00 00 00 00 00 | |
000015d0: 00 00 00 00 00 00 00 00 - 00 00 00 00 00 00 00 00 | |
000015e0: FF 00 00 00 00 00 00 00 - 00 00 00 00 00 00 00 00 | |
000015f0: 00 00 00 00 00 00 00 00 - 00 00 00 00 00 00 00 00 | |
00001600: 01 2E 00 00 00 00 00 00 - 00 00 00 00 00 00 00 00 | . |
00001610: 00 00 00 00 00 00 00 00 - 00 00 00 00 00 00 00 00 | |
00001620: 00 2E 2E 00 00 00 00 00 - 00 00 00 00 00 00 00 00 | .. |
00001630: 00 00 00 00 00 00 00 00 - 00 00 00 00 00 00 00 00 | |
00001640: 02 74 65 73 74 00 00 00 - 00 00 00 00 00 00 00 00 | test |
00001650: 00 00 00 00 00 00 00 00 - 00 00 00 00 00 00 00 00 | |
00001660: FF 00 00 00 00 00 00 00 - 00 00 00 00 00 00 00 00 | |
00001670: 00 00 00 00 00 00 00 00 - 00 00 00 00 00 00 00 00 | |
00001680: FF 00 00 00 00 00 00 00 - 00 00 00 00 00 00 00 00 | |
00001690: 00 00 00 00 00 00 00 00 - 00 00 00 00 00 00 00 00 | |
000016a0: FF 00 00 00 00 00 00 00 - 00 00 00 00 00 00 00 00 | |
000016b0: 00 00 00 00 00 00 00 00 - 00 00 00 00 00 00 00 00 | |
000016c0: FF 00 00 00 00 00 00 00 - 00 00 00 00 00 00 00 00 | |
000016d0: 00 00 00 00 00 00 00 00 - 00 00 00 00 00 00 00 00 | |
000016e0: FF 00 00 00 00 00 00 00 - 00 00 00 00 00 00 00 00 | |
000016f0: 00 00 00 00 00 00 00 00 - 00 00 00 00 00 00 00 00 | |
00001700: FF 00 00 00 00 00 00 00 - 00 00 00 00 00 00 00 00 | |
00001710: 00 00 00 00 00 00 00 00 - 00 00 00 00 00 00 00 00 | |
00001720: FF 00 00 00 00 00 00 00 - 00 00 00 00 00 00 00 00 | |
00001730: 00 00 00 00 00 00 00 00 - 00 00 00 00 00 00 00 00 | |
00001740: FF 00 00 00 00 00 00 00 - 00 00 00 00 00 00 00 00 | |
00001750: 00 00 00 00 00 00 00 00 - 00 00 00 00 00 00 00 00 | |
00001760: FF 00 00 00 00 00 00 00 - 00 00 00 00 00 00 00 00 | |
00001770: 00 00 00 00 00 00 00 00 - 00 00 00 00 00 00 00 00 | |
00001780: FF 00 00 00 00 00 00 00 - 00 00 00 00 00 00 00 00 | |
00001790: 00 00 00 00 00 00 00 00 - 00 00 00 00 00 00 00 00 | |
000017a0: FF 00 00 00 00 00 00 00 - 00 00 00 00 00 00 00 00 | |
000017b0: 00 00 00 00 00 00 00 00 - 00 00 00 00 00 00 00 00 | |
000017c0: FF 00 00 00 00 00 00 00 - 00 00 00 00 00 00 00 00 | |
000017d0: 00 00 00 00 00 00 00 00 - 00 00 00 00 00 00 00 00 | |
000017e0: FF 00 00 00 00 00 00 00 - 00 00 00 00 00 00 00 00 | |
000017f0: 00 00 00 00 00 00 00 00 - 00 00 00 00 00 00 00 00 | |
00001800: 48 65 6C 6C 6F 20 57 6F - 72 6C 64 21 00 00 00 00 |Hello World! |
00001810: 00 00 00 00 00 00 00 00 - 00 00 00 00 00 00 00 00 | |
*
0001fe00: 00 02 00 00 01 00 00 00 - 0D 0A 00 00 00 00 00 00 | |
0001fe10: 00 00 00 00 00 00 00 00 - 00 00 00 00 00 00 00 00 | |
0001fe20: 00 00 02 00 00 01 00 00 - 00 0B 00 00 00 00 00 00 | |
0001fe30: 00 00 00 00 00 00 00 00 - 00 00 00 00 00 00 00 00 | |
0001fe40: 00 0C 00 00 00 00 00 00 - 00 0C 00 00 00 00 00 00 | |
0001fe50: 00 00 00 00 00 00 00 00 - 00 00 00 00 00 00 00 00 | |
*
00200000: 00 - | |
00200001;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment