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#include <assert.h>
28#include <err.h>
29#include <errno.h>
30#include <stdbool.h>
31#include <stdint.h>
32#include <stdio.h>
33#include <stdlib.h>
34#include <string.h>
35
36#include "fstyp.h"
37
38/*
39 * https://developer.apple.com/library/archive/technotes/tn/tn1150.html
40 */
41
42#define	VOL_HDR_OFF	1024
43
44typedef uint32_t hfsp_cat_nodeid;
45
46typedef struct hfsp_ext_desc {
47	uint32_t	ex_startBlock;
48	uint32_t	ex_blockCount;
49} hfsp_ext_desc;
50
51typedef struct hfsp_fork_data {
52	uint64_t	fd_logicalSz;
53	uint32_t	fd_clumpSz;
54	uint32_t	fd_totalBlocks;
55	hfsp_ext_desc	fd_extents[8];
56} hfsp_fork_data;
57
58struct hfsp_vol_hdr {
59	char		hp_signature[2];
60	uint16_t	hp_version;
61	uint32_t	hp_attributes;
62	uint32_t	hp_lastMounted;
63	uint32_t	hp_journalInfoBlock;
64
65	/* Creation / etc dates. */
66	uint32_t	hp_create;
67	uint32_t	hp_modify;
68	uint32_t	hp_backup;
69	uint32_t	hp_checked;
70
71	/* Stats */
72	uint32_t	hp_files;
73	uint32_t	hp_folders;
74
75	/* Parameters */
76	uint32_t	hp_blockSize;
77	uint32_t	hp_totalBlocks;
78	uint32_t	hp_freeBlocks;
79
80	uint32_t	hp_nextAlloc;
81	uint32_t	hp_rsrcClumpSz;
82	uint32_t	hp_dataClumpSz;
83
84	hfsp_cat_nodeid	hp_nextCatID;
85
86	uint32_t	hp_writeCount;
87	uint64_t	hp_encodingsBM;
88
89	uint32_t	hp_finderInfo[8];
90
91	hfsp_fork_data	hp_allocationFile;
92	hfsp_fork_data	hp_extentsFile;
93	hfsp_fork_data	hp_catalogFile;
94	hfsp_fork_data	hp_attributesFile;
95	hfsp_fork_data	hp_startupFile;
96};
97_Static_assert(sizeof(struct hfsp_vol_hdr) == 512, "");
98
99int
100fstyp_hfsp(FILE *fp, char *label, size_t size)
101{
102	struct hfsp_vol_hdr *hdr;
103	int retval;
104
105	retval = 1;
106	hdr = read_buf(fp, VOL_HDR_OFF, sizeof(*hdr));
107	if (hdr == NULL)
108		goto fail;
109
110	if ((strncmp(hdr->hp_signature, "H+", 2) != 0 || hdr->hp_version != 4)
111	    &&
112	    (strncmp(hdr->hp_signature, "HX", 2) != 0 || hdr->hp_version != 5))
113		goto fail;
114
115	/* This is an HFS+ volume. */
116	retval = 0;
117
118	/* No label support yet. */
119	(void)size;
120	(void)label;
121
122fail:
123	free(hdr);
124	return (retval);
125}
126