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@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