PJFS (Partitioning, Journaling File System) is a filesystem developed by Green Hills Software, Inc. Features:
- Journaling
- Multiple volumes per file system
- Endianness support
- Support for different block sizes
This is a very basic fuse implementation of PJFS. Current limitations:
- Read-only
- No journal support
- Maximum file size 55296 bytes
- Fixed block size of 512 bytes
- Up to 4096 blocks per volume (2 MiB)
- Little endian support only
- No timestamps
This program is licensed under the terms of the GNU General Public License version 3 and no later version. See license.md for details.
PJFS has the concept of virtual block IDs. It maps between actual memory offset (physical block ID) and volume-specific identifier per block. Physical block IDs are relative to the whole PJFS, not to a volume.
All files and directories in a PJFS are items which share a common set of properties.
Item type | Description |
---|---|
1 | File |
2 | Directory |
An Item Key is the virtual block ID of the item's first block and its type.
Offset | Length | Description |
---|---|---|
+ 0x0 | 4 | Virtual block ID |
+ 0x4 | 4 | Type |
A Range describes a range of numeric values including the first and excluding the last value.
Offset | Length | Description |
---|---|---|
+ 0x0 | 4 | Begin of range (inclusive) |
+ 0x4 | 4 | End of range (exclusive) |
The Superblock contains information about the PJFS file system. It is the first block of a PJFS file system. It is 0x80 bytes large.
00000000 70 6a 66 73 5f 76 31 5f 6c 65 00 00 00 00 00 00 |pjfs_v1_le......|
00000010 00 08 08 04 40 40 40 00 01 00 00 00 80 00 00 00 |....@@@.........|
00000020 01 00 00 00 00 00 00 00 00 02 00 00 08 00 00 00 |................|
00000030 01 00 00 00 01 00 00 00 00 00 00 00 a8 01 00 00 |................|
00000040 a8 01 00 00 01 00 00 00 a8 01 00 00 a7 01 00 00 |................|
00000050 00 00 00 00 02 00 00 00 02 00 00 00 02 00 00 00 |................|
00000060 04 00 00 00 02 00 00 00 04 00 00 00 05 00 00 00 |................|
00000070 01 00 00 00 05 00 00 00 06 00 00 00 01 00 00 00 |................|
Offset | Length | Description |
---|---|---|
0x0 | 16 (?) | Magic string |
0x10 | 1 | Big endian |
0x11 | 1 | Size of disk size |
0x12 | 1 | Size of file size |
0x13 | 1 | Size of time |
0x14 | 1 | Size of directory header |
0x15 | 1 | Size of directory entry |
0x16 | 1 | Size of item |
0x17 | 1 | ? |
0x18 | 4 | Superblock version |
0x1c | 4 | Superblock size |
0x20 | 4 | FS version |
0x24 | 4 | FS flags |
0x28 | 4 | Block size |
Directly followed by the superblock follows the volume table header, which is followed by table entries.
00000080 00 00 00 00 01 00 00 00 40 00 00 00 00 00 00 00 |........@.......|
00000090 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
Offset | Length | Description |
---|---|---|
0x80 | 4 | CRC32 from 0x84 over all volume table entries, or zero |
0x84 | 4 | Number of volumes |
0x88 | 4 | Size of one volume table entry (?) |
Every volume table entry is presumably 0x40 bytes large.
000000a0 76 6f 6c 30 00 00 00 00 00 00 00 00 00 00 00 00 |vol0............|
000000b0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
000000c0 01 00 00 00 a8 01 00 00 a7 01 00 00 00 00 00 00 |................|
000000d0 5f 00 00 00 5f 00 00 00 5f 00 00 00 04 01 00 00 |_..._..._.......|
Offset | Length | Description |
---|---|---|
+ 0x0 | 32 (?) | Volume name |
+ 0x20 | 8 | Range of the volume, in physical blocks |
+ 0x28 | 16 | ? |
+ 0x38 | 8 | "Slash dir key", the key of the root directory |
The first block of a volume contains a list of pointers to block allocation tables. Every entry consists of the physical block ID of a block allocation table block and presumably flags. A physical block ID of 0xffffffff marks the end of the list.
00000200 02 00 00 00 00 00 00 00 04 00 00 00 00 00 00 00 |................|
00000210 08 00 00 00 00 00 00 00 26 00 00 00 00 00 00 00 |........&.......|
00000220 48 00 00 00 00 00 00 00 07 00 00 00 00 00 00 00 |H...............|
00000230 81 01 00 00 11 00 00 00 ff ff ff ff 00 00 00 00 |................|
00000240 ff ff ff ff 00 00 00 00 ff ff ff ff 00 00 00 00 |................|
00000250 ff ff ff ff 00 00 00 00 ff ff ff ff 00 00 00 00 |................|
00000260 ff ff ff ff 00 00 00 00 ff ff ff ff 00 00 00 00 |................|
00000270 ff ff ff ff 00 00 00 00 ff ff ff ff 00 00 00 00 |................|
...
Offset | Length | Description |
---|---|---|
+ 0x0 | 4 | Physical block ID |
+ 0x4 | 4 | Flags (?) |
A block allocation table contains a list of pointers to blocks. Every entry consists of the physical block ID of the block being pointed to and flags. A physical block ID of 0xffffffff marks the end of the list. To look up a virtual block with ID n, take the nth entry of all block allocation table blocks.
The following example shows the second block allocation table block. To look up the block with virtual ID 95 (0x5f in hex), you have to skip the first block allocation table block as every such block only contains up to 64 entries. Then, in the second block allocation table block (shown below), look at the 95-64=31th entry at offset 0x8f8. The block has the physical block ID 0x6e and has flags 0x104, i.e. you'll find it at offset 0x6e*512=56320.
00000800 33 01 00 00 02 00 00 00 34 01 00 00 02 00 00 00 |3.......4.......|
00000810 4c 01 00 00 02 00 00 00 5a 01 00 00 02 00 00 00 |L.......Z.......|
00000820 60 01 00 00 02 00 00 00 64 01 00 00 02 00 00 00 |`.......d.......|
00000830 6b 01 00 00 02 00 00 00 6d 01 00 00 02 00 00 00 |k.......m.......|
00000840 6f 01 00 00 02 00 00 00 52 00 00 00 02 00 00 00 |o.......R.......|
00000850 53 00 00 00 02 00 00 00 54 00 00 00 02 00 00 00 |S.......T.......|
00000860 55 00 00 00 02 00 00 00 56 00 00 00 02 00 00 00 |U.......V.......|
00000870 57 00 00 00 02 00 00 00 58 00 00 00 02 00 00 00 |W.......X.......|
00000880 59 00 00 00 02 00 00 00 5a 00 00 00 02 00 00 00 |Y.......Z.......|
00000890 5b 00 00 00 02 00 00 00 5c 00 00 00 02 00 00 00 |[.......\.......|
000008a0 5d 00 00 00 02 00 00 00 5e 00 00 00 02 00 00 00 |].......^.......|
000008b0 5f 00 00 00 02 00 00 00 60 00 00 00 02 00 00 00 |_.......`.......|
000008c0 61 00 00 00 02 00 00 00 62 00 00 00 02 00 00 00 |a.......b.......|
000008d0 63 00 00 00 02 00 00 00 64 00 00 00 02 00 00 00 |c.......d.......|
000008e0 65 00 00 00 02 00 00 00 66 00 00 00 02 00 00 00 |e.......f.......|
000008f0 67 00 00 00 02 00 00 00 6e 00 00 00 04 01 00 00 |g.......n.......|
00000900 87 01 00 00 04 01 00 00 5c 01 00 00 04 01 00 00 |........\.......|
00000910 3b 00 00 00 04 01 00 00 69 00 00 00 04 01 00 00 |;.......i.......|
00000920 0d 00 00 00 04 01 00 00 6b 00 00 00 04 01 00 00 |........k.......|
00000930 69 01 00 00 04 01 00 00 10 00 00 00 04 01 00 00 |i...............|
00000940 3e 00 00 00 06 01 00 00 41 00 00 00 06 01 00 00 |>.......A.......|
00000950 32 00 00 00 06 01 00 00 29 00 00 00 06 01 00 00 |2.......).......|
00000960 11 00 00 00 06 01 00 00 30 00 00 00 06 01 00 00 |........0.......|
00000970 45 00 00 00 06 01 00 00 2f 00 00 00 06 01 00 00 |E......./.......|
00000980 2e 00 00 00 06 01 00 00 13 00 00 00 06 01 00 00 |................|
00000990 47 01 00 00 06 01 00 00 15 00 00 00 06 01 00 00 |G...............|
000009a0 18 00 00 00 06 01 00 00 19 00 00 00 06 01 00 00 |................|
000009b0 1a 00 00 00 06 01 00 00 16 00 00 00 06 01 00 00 |................|
000009c0 1b 00 00 00 06 01 00 00 1d 00 00 00 06 01 00 00 |................|
000009d0 1e 00 00 00 06 01 00 00 1c 00 00 00 06 01 00 00 |................|
000009e0 1f 00 00 00 06 01 00 00 21 00 00 00 06 01 00 00 |........!.......|
000009f0 22 00 00 00 06 01 00 00 23 00 00 00 06 01 00 00 |".......#.......|
Offset | Length | Description |
---|---|---|
+ 0x0 | 4 | Physical block ID |
+ 0x4 | 4 | Flags |
An item may span over multiple blocks. If offset + 0x4c is 0xffffffff, the item's contents directly follow at + 0x50. If it is not, a list of virtual block IDs starting at + 0x4c point to the blocks containing the contents of the item. The rest of the block is then filled with 0xff.
00007000 00 01 00 00 7e 01 00 00 04 01 00 00 62 00 00 00 |....~.......b...|
00007010 04 01 00 00 01 00 00 00 46 00 00 00 00 00 00 00 |................|
00007020 00 00 00 00 00 00 00 00 ff ff ff ff ff ff ff 7f |................|
00007030 7e 02 00 00 7e 02 00 00 00 00 00 00 00 00 00 00 |~...~...........|
00007040 ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |................|
00007050 23 69 6e 63 6c 75 64 65 20 3c 73 74 64 69 6f 2e |#include <stdio.|
00007060 68 3e 0a 0a 69 6e 74 20 6d 61 69 6e 28 29 0a 7b |h>..int main().{|
00007070 0a 09 70 75 74 73 28 22 48 65 6c 6c 6f 2c 20 77 |..puts("Hello, w|
00007080 6f 72 6c 64 21 22 29 3b 0a 09 72 65 74 75 72 6e |orld!");..return|
00007090 20 30 3b 0a 7d 0a 00 00 00 00 00 00 00 00 00 00 | 0;.}...........|
000070a0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
000070b0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
000070c0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
000070d0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
000070e0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
000070f0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
00007100 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
00007110 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
00007120 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
00007130 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
00007140 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
00007150 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
00007160 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
00007170 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
00007180 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
00007190 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
000071a0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
000071b0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
000071c0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
000071d0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
000071e0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
000071f0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
Offset | Length | Description |
---|---|---|
+ 0x0 | 1 | ? |
+ 0x1 | 1 | Type |
+ 0x2 | 2 | ? |
+ 0x4 | 8 | Item key of this item |
+ 0xc | 8 | Item key of the parent item |
+ 0x14 | 4 | ? |
+ 0x18 | 8 | Size |
+ 0x20 | 8 | ? |
+ 0x28 | 8 | ? |
+ 0x2c | 4 | ? |
+ 0x30 | 4 | ? |
+ 0x34 | 4 | ? |
+ 0x38 | 4 | ? |
+ 0x3c | 4 | ? |
A directory is an item with type 2 and a special structure of contents. The directory's first 0x40 bytes describe the number of directory entries. The parent directory of a volume's root directory is the directory itself, i.e. the item's parent's key is the item's key.
00007600 00 02 00 00 62 00 00 00 04 01 00 00 5f 00 00 00 |....b......._...|
00007610 04 01 00 00 01 00 00 00 40 01 00 00 00 00 00 00 |........@.......|
00007620 00 00 00 00 00 00 00 00 ff ff ff ff ff ff ff 7f |................|
00007630 4f 00 00 00 7e 02 00 00 00 00 00 00 00 00 00 00 |O...~...........|
00007640 ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |................|
00007650 04 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
00007660 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
00007670 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
00007680 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
00007690 63 00 00 00 04 01 00 00 02 00 00 00 00 00 00 00 |c...............|
000076a0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
000076b0 66 6f 6f 00 00 00 00 00 00 00 00 00 00 00 00 00 |foo.............|
000076c0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
000076d0 64 00 00 00 04 01 00 00 02 00 00 00 00 00 00 00 |d...............|
000076e0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
000076f0 62 61 72 00 00 00 00 00 00 00 00 00 00 00 00 00 |bar.............|
00007700 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
00007710 65 00 00 00 04 01 00 00 02 00 00 00 00 00 00 00 |e...............|
00007720 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
00007730 62 61 7a 00 00 00 00 00 00 00 00 00 00 00 00 00 |baz.............|
00007740 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
00007750 7e 01 00 00 04 01 00 00 01 00 00 00 00 00 00 00 |~...............|
00007760 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
00007770 71 75 75 78 00 00 00 00 00 00 00 00 00 00 00 00 |quux............|
00007780 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
00007790 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
000077a0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
000077b0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
000077c0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
000077d0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
000077e0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
000077f0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
Offset | Length | Description |
---|---|---|
+ 0x0 | 8 | Item key |
+ 0x8 | 1 | Type |
+ 0x9 | 23 | ? |
+ 0x20 | 32 | Name |