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
46 typedef uint32_t hfsp_cat_nodeid;
47
48 typedef struct hfsp_ext_desc {
49 uint32_t ex_startBlock;
50 uint32_t ex_blockCount;
51 } hfsp_ext_desc;
52
53 typedef 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
60 struct 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
101 int
fstyp_hfsp(FILE * fp,char * label,size_t size,const char * devpath)102 fstyp_hfsp(FILE *fp, char *label, size_t size, const char *devpath)
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
122 fail:
123 free(hdr);
124 return (retval);
125 }
126