1/*
2 * Copyright (c) 2019 Conrad Meyer <cem@FreeBSD.org>.  All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
6 * are met:
7 * 1. Redistributions of source code must retain the above copyright
8 *    notice, this list of conditions and the following disclaimer.
9 * 2. Redistributions in binary form must reproduce the above copyright
10 *    notice, this list of conditions and the following disclaimer in the
11 *    documentation and/or other materials provided with the distribution.
12 *
13 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
14 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
16 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
17 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
18 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
19 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
20 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
21 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
22 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
23 * SUCH DAMAGE.
24 */
25
26#include <sys/cdefs.h>
27__FBSDID("$FreeBSD$");
28
29#include <assert.h>
30#include <err.h>
31#include <errno.h>
32#include <stdbool.h>
33#include <stdint.h>
34#include <stdio.h>
35#include <stdlib.h>
36#include <string.h>
37
38#include "fstyp.h"
39
40/*
41 * https://developer.apple.com/library/archive/technotes/tn/tn1150.html
42 */
43
44#define	VOL_HDR_OFF	1024
45
46typedef uint32_t hfsp_cat_nodeid;
47
48typedef struct hfsp_ext_desc {
49	uint32_t	ex_startBlock;
50	uint32_t	ex_blockCount;
51} hfsp_ext_desc;
52
53typedef struct hfsp_fork_data {
54	uint64_t	fd_logicalSz;
55	uint32_t	fd_clumpSz;
56	uint32_t	fd_totalBlocks;
57	hfsp_ext_desc	fd_extents[8];
58} hfsp_fork_data;
59
60struct hfsp_vol_hdr {
61	char		hp_signature[2];
62	uint16_t	hp_version;
63	uint32_t	hp_attributes;
64	uint32_t	hp_lastMounted;
65	uint32_t	hp_journalInfoBlock;
66
67	/* Creation / etc dates. */
68	uint32_t	hp_create;
69	uint32_t	hp_modify;
70	uint32_t	hp_backup;
71	uint32_t	hp_checked;
72
73	/* Stats */
74	uint32_t	hp_files;
75	uint32_t	hp_folders;
76
77	/* Parameters */
78	uint32_t	hp_blockSize;
79	uint32_t	hp_totalBlocks;
80	uint32_t	hp_freeBlocks;
81
82	uint32_t	hp_nextAlloc;
83	uint32_t	hp_rsrcClumpSz;
84	uint32_t	hp_dataClumpSz;
85
86	hfsp_cat_nodeid	hp_nextCatID;
87
88	uint32_t	hp_writeCount;
89	uint64_t	hp_encodingsBM;
90
91	uint32_t	hp_finderInfo[8];
92
93	hfsp_fork_data	hp_allocationFile;
94	hfsp_fork_data	hp_extentsFile;
95	hfsp_fork_data	hp_catalogFile;
96	hfsp_fork_data	hp_attributesFile;
97	hfsp_fork_data	hp_startupFile;
98};
99_Static_assert(sizeof(struct hfsp_vol_hdr) == 512, "");
100
101int
102fstyp_hfsp(FILE *fp, char *label, size_t size)
103{
104	struct hfsp_vol_hdr *hdr;
105	int retval;
106
107	retval = 1;
108	hdr = read_buf(fp, VOL_HDR_OFF, sizeof(*hdr));
109	if (hdr == NULL)
110		goto fail;
111
112	if ((strncmp(hdr->hp_signature, "H+", 2) != 0 || hdr->hp_version != 4)
113	    &&
114	    (strncmp(hdr->hp_signature, "HX", 2) != 0 || hdr->hp_version != 5))
115		goto fail;
116
117	/* This is an HFS+ volume. */
118	retval = 0;
119
120	/* No label support yet. */
121
122fail:
123	free(hdr);
124	return (retval);
125}
126