(root)/
util-linux-2.39/
libblkid/
src/
superblocks/
apfs.c
       1  /*
       2   * Copyright (C) 2018 Harry Mallon <hjmallon@gmail.com>
       3   *
       4   * This file may be redistributed under the terms of the
       5   * GNU Lesser General Public License.
       6   */
       7  
       8  #include "superblocks.h"
       9  
      10  #define APFS_CONTAINER_SUPERBLOCK_TYPE 1
      11  #define APFS_CONTAINER_SUPERBLOCK_SUBTYPE 0
      12  #define APFS_STANDARD_BLOCK_SIZE 4096
      13  
      14  /*
      15   * This struct is much longer than this, but this seems
      16   * to contain the useful bits (for now).
      17   *
      18   * All values are little-endian.
      19   */
      20  struct apfs_super_block {
      21  	// Generic part to all APFS objects
      22  	uint64_t checksum;
      23  	uint64_t oid;
      24  	uint64_t xid;
      25  	uint16_t type;
      26  	uint16_t flags;
      27  	uint16_t subtype;
      28  	uint16_t pad;
      29  
      30  	// Specific to container header
      31  	uint32_t magic; // 'NXSB'
      32  	uint32_t block_size;
      33  	uint64_t block_count;
      34  	uint64_t features;
      35  	uint64_t read_only_features;
      36  	uint64_t incompatible_features;
      37  	uint8_t uuid[16];
      38  };
      39  
      40  static int probe_apfs(blkid_probe pr, const struct blkid_idmag *mag)
      41  {
      42  	struct apfs_super_block *sb;
      43  
      44  	sb = blkid_probe_get_sb(pr, mag, struct apfs_super_block);
      45  	if (!sb)
      46  		return errno ? -errno : BLKID_PROBE_NONE;
      47  
      48  	if (le16_to_cpu(sb->type) != APFS_CONTAINER_SUPERBLOCK_TYPE)
      49  		return BLKID_PROBE_NONE;
      50  
      51  	if (le16_to_cpu(sb->subtype) != APFS_CONTAINER_SUPERBLOCK_SUBTYPE)
      52  		return BLKID_PROBE_NONE;
      53  
      54  	if (le16_to_cpu(sb->pad) != 0)
      55  		return BLKID_PROBE_NONE;
      56  
      57  	/*
      58  	 * This check is pretty draconian, but should avoid false
      59  	 * positives. Can be improved as more APFS documentation
      60  	 * is published.
      61  	 */
      62  	if (le32_to_cpu(sb->block_size) != APFS_STANDARD_BLOCK_SIZE)
      63  		return BLKID_PROBE_NONE;
      64  
      65  	if (blkid_probe_set_uuid(pr, sb->uuid) < 0)
      66  		return BLKID_PROBE_NONE;
      67  
      68  	blkid_probe_set_fsblocksize(pr, le32_to_cpu(sb->block_size));
      69  	blkid_probe_set_block_size(pr, le32_to_cpu(sb->block_size));
      70  
      71  	return BLKID_PROBE_OK;
      72  }
      73  
      74  const struct blkid_idinfo apfs_idinfo =
      75  {
      76  	.name		= "apfs",
      77  	.usage		= BLKID_USAGE_FILESYSTEM,
      78  	.probefunc	= probe_apfs,
      79  	.magics		=
      80  	{
      81  		{ .magic = "NXSB", .len = 4, .sboff = 32 },
      82  		{ NULL }
      83  	}
      84  };