| /* |
| apfs.c -- parted support for apfs file systems |
| Copyright (C) 1998-2000, 2007 Free Software Foundation, Inc. |
| |
| This program is free software; you can redistribute it and/or modify |
| it under the terms of the GNU General Public License as published by |
| the Free Software Foundation; either version 2 of the License, or |
| (at your option) any later version. |
| |
| This program is distributed in the hope that it will be useful, |
| but WITHOUT ANY WARRANTY; without even the implied warranty of |
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| GNU General Public License for more details. |
| |
| You should have received a copy of the GNU General Public License |
| along with this program; if not, write to the Free Software |
| Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. |
| */ |
| |
| #include <config.h> |
| |
| #include <parted/parted.h> |
| #include <parted/debug.h> |
| #include <parted/endian.h> |
| |
| #include "amiga.h" |
| #include "apfs.h" |
| |
| #if ENABLE_NLS |
| # include <libintl.h> |
| # define _(String) dgettext (PACKAGE, String) |
| #else |
| # define _(String) (String) |
| #endif /* ENABLE_NLS */ |
| |
| static int |
| _apfs_probe_root (uint32_t *block, uint32_t blocksize, uint32_t kind) { |
| if (PED_BE32_TO_CPU (block[0]) != kind) return 0; |
| return 1; |
| } |
| |
| static PedGeometry* |
| _generic_apfs_probe (PedGeometry* geom, uint32_t kind) |
| { |
| uint32_t *block; |
| PedSector root; |
| struct PartitionBlock * part; |
| uint32_t blocksize = 1, reserved = 2, prealloc = 0; |
| |
| PED_ASSERT (geom != NULL, return NULL); |
| PED_ASSERT (geom->dev != NULL, return NULL); |
| |
| /* Finds the blocksize, prealloc and reserved values of the partition block */ |
| if (!(part = ped_malloc (PED_SECTOR_SIZE_DEFAULT*blocksize))) { |
| ped_exception_throw(PED_EXCEPTION_ERROR, PED_EXCEPTION_CANCEL, |
| _("%s : Failed to allocate partition block\n"), __func__); |
| goto error_part; |
| } |
| if (amiga_find_part(geom, part) != NULL) { |
| prealloc = PED_BE32_TO_CPU (part->de_PreAlloc); |
| reserved = PED_BE32_TO_CPU (part->de_Reserved); |
| blocksize = PED_BE32_TO_CPU (part->de_SizeBlock) |
| * PED_BE32_TO_CPU (part->de_SectorPerBlock) / 128; |
| } |
| ped_free (part); |
| |
| /* Test boot block */ |
| if (!(block = ped_malloc (PED_SECTOR_SIZE_DEFAULT*blocksize))) { |
| ped_exception_throw(PED_EXCEPTION_ERROR, PED_EXCEPTION_CANCEL, |
| _("%s : Failed to allocate block\n"), __func__); |
| goto error_block; |
| } |
| if (!ped_device_read (geom->dev, block, geom->start, blocksize)) { |
| ped_exception_throw(PED_EXCEPTION_ERROR, PED_EXCEPTION_CANCEL, |
| _("%s : Couldn't read boot block %llu\n"), __func__, geom->start); |
| goto error; |
| } |
| if (PED_BE32_TO_CPU (block[0]) != kind) { |
| goto error; |
| } |
| |
| /* Find and test the root block */ |
| root = geom->start+reserved*blocksize; |
| if (!ped_device_read (geom->dev, block, root, blocksize)) { |
| ped_exception_throw(PED_EXCEPTION_ERROR, PED_EXCEPTION_CANCEL, |
| _("%s : Couldn't read root block %llu\n"), __func__, root); |
| goto error; |
| } |
| if (_apfs_probe_root(block, blocksize, kind) == 1) { |
| ped_free(block); |
| return ped_geometry_duplicate (geom); |
| } |
| |
| error: |
| ped_free (block); |
| error_block: |
| error_part: |
| return NULL; |
| } |
| |
| static PedGeometry* |
| _apfs1_probe (PedGeometry* geom) { |
| return _generic_apfs_probe (geom, 0x50463101); |
| } |
| |
| static PedGeometry* |
| _apfs2_probe (PedGeometry* geom) { |
| return _generic_apfs_probe (geom, 0x50463102); |
| } |
| |
| static PedFileSystemOps _apfs1_ops = { |
| probe: _apfs1_probe, |
| clobber: NULL, |
| open: NULL, |
| create: NULL, |
| close: NULL, |
| check: NULL, |
| resize: NULL, |
| copy: NULL, |
| get_create_constraint: NULL, |
| get_copy_constraint: NULL, |
| get_resize_constraint: NULL |
| }; |
| static PedFileSystemOps _apfs2_ops = { |
| probe: _apfs2_probe, |
| clobber: NULL, |
| open: NULL, |
| create: NULL, |
| close: NULL, |
| check: NULL, |
| resize: NULL, |
| copy: NULL, |
| get_create_constraint: NULL, |
| get_copy_constraint: NULL, |
| get_resize_constraint: NULL |
| }; |
| |
| #define APFS_BLOCK_SIZES ((int[2]){512, 0}) |
| |
| PedFileSystemType _apfs1_type = { |
| next: NULL, |
| ops: &_apfs1_ops, |
| name: "apfs1", |
| block_sizes: APFS_BLOCK_SIZES |
| }; |
| PedFileSystemType _apfs2_type = { |
| next: NULL, |
| ops: &_apfs2_ops, |
| name: "apfs2", |
| block_sizes: APFS_BLOCK_SIZES |
| }; |