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