In this document, we’re going to show an example of one of the default apfsutil scenarios, explain how to work with APFS sub-volumes, describe read/write access, and define the main possible apfsutil error codes you might encounter.
Feel free to jump ahead to the section you’re most interested in:
User scenarios
The apfsutil contains some simple user scenarios by default, such as:
# | Scenario | Name |
---|---|---|
1 | Root folder enumeration | enumroot |
2 | Sub-directory enumeration | enumfolder |
3 | File reading | readfile |
4 | List and show all file extended attributes | listea |
5 | Show all sub-volumes from the container | listsubvolumes |
Working with sub-volumes
The apfsutil can work with all sub-volumes in an APFS container. To mount all volumes, add the option “– subvolumes” to the apfsutil arguments. Without this option, only the main (1st) volume will be mounted.
Paragon APFS SDK puts sub-volumes in the “/Ufsd_Volumes” folder. To read or enumerate files and folders on a sub-volume, its full path should be provided.
For example, let’s first acquire a list of sub-volumes using the command syntax below. Note that for this user scenario, the “– subvolumes” switch is optional. If a required sub-volume name is known, this step can be skipped.
apfsutil listsubvolumes /dev/xxx
Volumes:
Untitled Volume2 MyEncryptedVolume
APFS: listsubvolumes returns 0. finished in 4 ms
Next, enumerate the root sub-volume folder or read any file:
apfsutil enumfolder /dev/xxx/Ufsd_Volumes/Untitled
apfsutil readfile /dev/xxx/Ufsd_Volumes/Untitled/testfile.txt
How to add your case
To create your own custom case, input its name (cannot use a previously defined name) in the list, entitled “s_Cmd” (it can be found in the linutil/apfsutil.cpp). Then create a command handler (function) there. To accomplish this, implement the following:
tatic const t_CmdHandler s_Cmd[] = {
{ "enumroot" , OnEnumRoot }, // readdir example
{ "enumfolder" , OnEnumFolder }, // enumerate folder
{ "readfile" , OnReadFile }, // file reading
{ "listea" , OnListEa }, // list all extended attributes
{ "listsubvolumes" , OnEnumSubvolumes }, // sub-volumes enumeration
// handlers for RW version
{ "createfile" , OnCreateFile }, // create file
{ "createfolder" , OnCreateFolder }, // create folder
{ "queryalloc" , OnQueryAlloc }, // list file extents (allocations)
{ "fsinfo" , OnFsInfo }, // get file system information
//
// TODO: add your handlers here
// ...
{ NULL , NULL },
};
Test handler should be of type:
typedef int (*HandlerFunc)(CFileSystem*, const char*);
Inside your specified handler, all public functions from base UFSD classes CFileSystem, CFile, and CDir are available (for more details see ufs\ufsd\include\ufsd\u_fsbase.h).
After rebuilding the utility, a selected test case will be available to start:
sudo apfsutil my_new_case /dev/xxx/path/to/file/or/folder
Read-Write access
Some operations require the full Read-Write sources (The version will be available soon on site: https://www.paragon-software.com/). In the Community Edition, these cases will return a “not implemented” error.
Test Name | Test Description |
---|---|
createfile | file creation |
createfolder | folder creation |
queryalloc | list file extents |
fsinfo | information about the file system (all sub-volumes, even encrypted) |
Fsinfo example
sudo apfsutil fsinfo /dev/sdb1
APFS Volume [0] 0F7AFC7E-BDF6-4546-8494-2A0C449E8D1F
Name : volume1 (Case-insensitive)
Creator : newfs_apfs (945.200.129)
Used Clusters : 1187894
Reserved Clusters : 0
Files : 63478
Directories : 1630
Symlinks : 5
Special files : 0
Snapshots : 0
Encrypted : Yes
APFS Volume [1] D45089E3-D391-4246-9490-B4EAC8D4E395
Name : volume2 (Case-insensitive)
Creator : diskmanagementd (945.200.129)
Used Clusters : 270
Reserved Clusters : 0
Files : 71
Directories : 19
Symlinks : 1
Special files : 0
Snapshots : 0
Encrypted : No
APFS Volume [2] 9D8EBA18-B110-4FCB-86FC-3E18B304628E
Name : volume3 (Case-insensitive)
Creator : diskmanagementd (945.200.129)
Used Clusters : 265
Reserved Clusters : 0
Files : 64
Directories : 18
Symlinks : 0
Special files : 0
Snapshots : 0
Encrypted : No
Apfsutil error codes
The utility can return following exit codes:
Code | Description |
---|---|
0 | Everything is OK, no error |
-1 | Invalid command line parameters |
-2 | Invalid or empty device name |
-3 | The device is mounted (linux only) |
-4 | No handler specified for the selected test_name |
-5 | Misuse of the –pass option |
0xA0001001 | Errors from the Paragon APFS SDK |
0xA0001026 | Console output will contain an error message |