ntfs.c revision 1.1 1 /* $NetBSD: ntfs.c,v 1.1 2018/01/09 03:31:15 christos Exp $ */
2
3 /*-
4 * Copyright (c) 2017 The NetBSD Foundation, Inc.
5 * Copyright (c) 2016 The DragonFly Project
6 * Copyright (c) 2005 Takanori Watanabe
7 * Copyright (c) 2014 The FreeBSD Foundation
8 * All rights reserved.
9 *
10 * This code is derived from software contributed to The NetBSD Foundation
11 * by Tomohiro Kusumi <kusumi.tomohiro (at) gmail.com>.
12 *
13 * This software was developed by Edward Tomasz Napierala under sponsorship
14 * from the FreeBSD Foundation.
15 *
16 * Redistribution and use in source and binary forms, with or without
17 * modification, are permitted provided that the following conditions
18 * are met:
19 * 1. Redistributions of source code must retain the above copyright
20 * notice, this list of conditions and the following disclaimer.
21 * 2. Redistributions in binary form must reproduce the above copyright
22 * notice, this list of conditions and the following disclaimer in the
23 * documentation and/or other materials provided with the distribution.
24 *
25 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
26 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
27 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
28 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
29 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
30 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
31 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
32 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
33 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
34 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
35 * SUCH DAMAGE.
36 */
37 #include <sys/cdefs.h>
38 __RCSID("$NetBSD: ntfs.c,v 1.1 2018/01/09 03:31:15 christos Exp $");
39
40 #include <stdint.h>
41 #include <stdio.h>
42 #include <stdlib.h>
43 #include <string.h>
44
45 #include "fstyp.h"
46
47 #define NTFS_A_VOLUMENAME 0x60
48 #define NTFS_FILEMAGIC ((uint32_t)(0x454C4946))
49 #define NTFS_VOLUMEINO 3
50
51 struct ntfs_attr {
52 uint32_t a_type;
53 uint32_t reclen;
54 uint8_t a_flag;
55 uint8_t a_namelen;
56 uint8_t a_nameoff;
57 uint8_t reserved1;
58 uint8_t a_compression;
59 uint8_t reserved2;
60 uint16_t a_index;
61 uint16_t a_datalen;
62 uint16_t reserved3;
63 uint16_t a_dataoff;
64 uint16_t a_indexed;
65 } __packed;
66
67 struct ntfs_filerec {
68 uint32_t fr_hdrmagic;
69 uint16_t fr_hdrfoff;
70 uint16_t fr_hdrfnum;
71 uint8_t reserved[8];
72 uint16_t fr_seqnum;
73 uint16_t fr_nlink;
74 uint16_t fr_attroff;
75 uint16_t fr_flags;
76 uint32_t fr_size;
77 uint32_t fr_allocated;
78 uint64_t fr_mainrec;
79 uint16_t fr_attrnum;
80 } __packed;
81
82 struct ntfs_bootfile {
83 uint8_t reserved1[3];
84 uint8_t bf_sysid[8];
85 uint16_t bf_bps;
86 uint8_t bf_spc;
87 uint8_t reserved2[7];
88 uint8_t bf_media;
89 uint8_t reserved3[2];
90 uint16_t bf_spt;
91 uint16_t bf_heads;
92 uint8_t reserver4[12];
93 uint64_t bf_spv;
94 uint64_t bf_mftcn;
95 uint64_t bf_mftmirrcn;
96 int8_t bf_mftrecsz;
97 uint32_t bf_ibsz;
98 uint32_t bf_volsn;
99 } __packed;
100
101 int
102 fstyp_ntfs(FILE *fp, char *label, size_t size)
103 {
104 struct ntfs_bootfile *bf;
105 struct ntfs_filerec *fr;
106 struct ntfs_attr *atr;
107 off_t voloff;
108 char *filerecp, *ap;
109 int8_t mftrecsz;
110 char vnchar;
111 size_t recsize, j;
112
113 filerecp = NULL;
114
115 bf = read_buf(fp, 0, 512);
116 if (bf == NULL || strncmp((char*)bf->bf_sysid, "NTFS ", 8) != 0)
117 goto fail;
118
119 mftrecsz = bf->bf_mftrecsz;
120 recsize = mftrecsz > 0 ? (size_t)(mftrecsz * bf->bf_bps * bf->bf_spc)
121 : (size_t)(1 << -mftrecsz);
122
123 voloff = (off_t)(bf->bf_mftcn * bf->bf_spc * bf->bf_bps +
124 recsize * NTFS_VOLUMEINO);
125
126 filerecp = read_buf(fp, voloff, recsize);
127 if (filerecp == NULL)
128 goto fail;
129 fr = (struct ntfs_filerec *)filerecp;
130
131 if (fr->fr_hdrmagic != NTFS_FILEMAGIC)
132 goto fail;
133
134 for (ap = filerecp + fr->fr_attroff;
135 atr = (struct ntfs_attr *)ap, (int)atr->a_type != -1;
136 ap += atr->reclen) {
137 if (atr->a_type == NTFS_A_VOLUMENAME) {
138 if(atr->a_datalen >= size *2){
139 goto fail;
140 }
141 /*
142 * UNICODE to ASCII.
143 * Should we need to use iconv(9)?
144 */
145 for (j = 0; j < atr->a_datalen; j++) {
146 vnchar = *(ap + atr->a_dataoff + j);
147 if (j & 1) {
148 if (vnchar) {
149 goto fail;
150 }
151 } else {
152 label[j / 2] = vnchar;
153 }
154 }
155 label[j / 2] = 0;
156 break;
157 }
158 }
159
160 free(bf);
161 free(filerecp);
162
163 return 0;
164
165 fail:
166 free(bf);
167 free(filerecp);
168
169 return 1;
170 }
171