Difference between revisions of "PFS"

From PS4 Developer wiki
Jump to: navigation, search
Line 133: Line 133:
} dirent;
} dirent;
== Tools ==
* [https://github.com/maxton/GameArchives/releases/latest GameArchives/ArchiveExplorer] library/tool that supports opening and extracting from PFS images

Revision as of 06:11, 17 October 2016

PFS (Playstation File System) is the file system used by (at least) downloadable content and games on the PS4. It is loosely based on the UFS (Unix File System) used in FreeBSD. PFS typically uses a 64kB block size, although the block size is configurable and specified in the file system header.


There are four main sections in a Playstation File System:

  • Header (superblock)
  • Inode blocks
  • Directory blocks
  • Data blocks


Offset Value Size Notes
0x00 version 0x8 Should be 1
0x08 magic 0x8 Should be 20130315
0x10 id 0x8
0x18 fmode 0x1
0x19 clean 0x1
0x1A ronly 0x1 If 1, this is a readonly filesystem
0x1B rsv 0x1
0x1C mode 0x2
0x1E unknown 0x2
0x20 blocksz 0x4 The size of each block in the filesystem.
0x24 nbackup 0x4
0x28 nblock 0x8
0x30 ndinode 0x8 Number of inodes in the inode blocks
0x38 ndblock 0x8 Number of data blocks
0x40 ndinodeblock 0x8 Number of inode blocks
0x48 superroot_ino 0x8
typedef struct {
    int64 version;
    int64 magic;
    int32 id[2];
    char fmode;
    char clean;
    char ronly;
    char rsv;
    int16 mode;
    int16 unk1;
    int32 blocksz;
    int32 nbackup;
    int64 nblock;
    int64 ndinode;
    int64 ndblock;
    int64 ndinodeblock;
    int64 superroot_ino;


Inode table starts at the second block and continues for ndinodeblock blocks.

Offset Value Size Notes
0x00 mode 0x2 Inode mode (bitwise OR of flags; file=0x8000, directory=0x4000)
0x02 nlink 0x2
0x04 flags 0x4
0x08 size 0x8
0x10 unknown 0x38
0x48 uid 0x4
0x4C gid 0x4
0x50 unknown 0x10
0x60 blocks 0x4 Number of blocks occupied
0x64 db 0x30 Direct blocks
0x94 ib 0x14 Indirect blocks
typedef struct {
    uint16 mode;
    uint16 nlink;
    uint16 flags[2];
    uint64 size;
    char unk1[56];
    uint32 uid;
    uint32 gid;
    uint64 unk2[2];
    uint32 blocks;
    int32 db[12];
    int32 ib[5];
} di_d32;


Dirents are 8-byte aligned. The entsize value will say the total length of this dirent. There is typically padding after name which can just be skipped.

Offset Value Size Notes
0x00 ino 0x4 Inode index
0x04 type 0x4 Type of entry. 2=file, 3=directory
0x08 namelen 0x4 Length of filename (add 1 for 0-terminator)
0x10 name namelen + 1 Filename and 0-terminator
0x11 + namelen padding variable Padding so this structure is exactly entsize bytes.
typedef struct {
    int32 ino;
    int32 type;
    int32 namelen;
    int32 entsize;
    char name[namelen+1];
} dirent;