1275680Strasz/*- 2275680Strasz * Copyright (c) 2005 Takanori Watanabe 3275680Strasz * Copyright (c) 2014 The FreeBSD Foundation 4275680Strasz * All rights reserved. 5275680Strasz * 6275680Strasz * This software was developed by Edward Tomasz Napierala under sponsorship 7275680Strasz * from the FreeBSD Foundation. 8275680Strasz * 9275680Strasz * Redistribution and use in source and binary forms, with or without 10275680Strasz * modification, are permitted provided that the following conditions 11275680Strasz * are met: 12275680Strasz * 1. Redistributions of source code must retain the above copyright 13275680Strasz * notice, this list of conditions and the following disclaimer. 14275680Strasz * 2. Redistributions in binary form must reproduce the above copyright 15275680Strasz * notice, this list of conditions and the following disclaimer in the 16275680Strasz * documentation and/or other materials provided with the distribution. 17275680Strasz * 18275680Strasz * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 19275680Strasz * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 20275680Strasz * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 21275680Strasz * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 22275680Strasz * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 23275680Strasz * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 24275680Strasz * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 25275680Strasz * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 26275680Strasz * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 27275680Strasz * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 28275680Strasz * SUCH DAMAGE. 29275680Strasz */ 30275680Strasz 31275680Strasz#include <sys/cdefs.h> 32275680Strasz__FBSDID("$FreeBSD$"); 33275680Strasz 34275680Strasz#include <stdint.h> 35275680Strasz#include <stdio.h> 36275680Strasz#include <stdlib.h> 37275680Strasz#include <string.h> 38275680Strasz 39275680Strasz#include "fstyp.h" 40275680Strasz 41275680Strasz#define NTFS_A_VOLUMENAME 0x60 42275680Strasz#define NTFS_FILEMAGIC ((uint32_t)(0x454C4946)) 43275680Strasz#define NTFS_VOLUMEINO 3 44275680Strasz 45275680Straszstruct ntfs_attr { 46275680Strasz uint32_t a_type; 47275680Strasz uint32_t reclen; 48275680Strasz uint8_t a_flag; 49275680Strasz uint8_t a_namelen; 50275680Strasz uint8_t a_nameoff; 51275680Strasz uint8_t reserved1; 52275680Strasz uint8_t a_compression; 53275680Strasz uint8_t reserved2; 54275680Strasz uint16_t a_index; 55275680Strasz uint16_t a_datalen; 56275680Strasz uint16_t reserved3; 57275680Strasz uint16_t a_dataoff; 58275680Strasz uint16_t a_indexed; 59275680Strasz} __packed; 60275680Strasz 61275680Straszstruct ntfs_filerec { 62275680Strasz uint32_t fr_hdrmagic; 63275680Strasz uint16_t fr_hdrfoff; 64275680Strasz uint16_t fr_hdrfnum; 65275680Strasz uint8_t reserved[8]; 66275680Strasz uint16_t fr_seqnum; 67275680Strasz uint16_t fr_nlink; 68275680Strasz uint16_t fr_attroff; 69275680Strasz uint16_t fr_flags; 70275680Strasz uint32_t fr_size; 71275680Strasz uint32_t fr_allocated; 72275680Strasz uint64_t fr_mainrec; 73275680Strasz uint16_t fr_attrnum; 74275680Strasz} __packed; 75275680Strasz 76275680Straszstruct ntfs_bootfile { 77275680Strasz uint8_t reserved1[3]; 78275680Strasz uint8_t bf_sysid[8]; 79275680Strasz uint16_t bf_bps; 80275680Strasz uint8_t bf_spc; 81275680Strasz uint8_t reserved2[7]; 82275680Strasz uint8_t bf_media; 83275680Strasz uint8_t reserved3[2]; 84275680Strasz uint16_t bf_spt; 85275680Strasz uint16_t bf_heads; 86275680Strasz uint8_t reserver4[12]; 87275680Strasz uint64_t bf_spv; 88275680Strasz uint64_t bf_mftcn; 89275680Strasz uint64_t bf_mftmirrcn; 90275680Strasz int8_t bf_mftrecsz; 91275680Strasz uint32_t bf_ibsz; 92275680Strasz uint32_t bf_volsn; 93275680Strasz} __packed; 94275680Strasz 95275680Straszint 96275680Straszfstyp_ntfs(FILE *fp, char *label, size_t size) 97275680Strasz{ 98275680Strasz struct ntfs_bootfile *bf; 99275680Strasz struct ntfs_filerec *fr; 100275680Strasz struct ntfs_attr *atr; 101275680Strasz off_t voloff; 102275680Strasz char *filerecp, *ap; 103275680Strasz int8_t mftrecsz; 104275680Strasz char vnchar; 105275680Strasz int recsize, j; 106275680Strasz 107275680Strasz filerecp = NULL; 108275680Strasz 109275680Strasz bf = (struct ntfs_bootfile *)read_buf(fp, 0, 512); 110275680Strasz if (bf == NULL || strncmp(bf->bf_sysid, "NTFS ", 8) != 0) 111277436Strasz goto fail; 112275680Strasz 113275680Strasz mftrecsz = bf->bf_mftrecsz; 114275680Strasz recsize = (mftrecsz > 0) ? (mftrecsz * bf->bf_bps * bf->bf_spc) : (1 << -mftrecsz); 115275680Strasz 116275680Strasz voloff = bf->bf_mftcn * bf->bf_spc * bf->bf_bps + 117275680Strasz recsize * NTFS_VOLUMEINO; 118275680Strasz 119275680Strasz filerecp = read_buf(fp, voloff, recsize); 120275680Strasz if (filerecp == NULL) 121275680Strasz goto fail; 122275680Strasz fr = (struct ntfs_filerec *)filerecp; 123275680Strasz 124275680Strasz if (fr->fr_hdrmagic != NTFS_FILEMAGIC) 125275680Strasz goto fail; 126275680Strasz 127275680Strasz for (ap = filerecp + fr->fr_attroff; 128275680Strasz atr = (struct ntfs_attr *)ap, (int)atr->a_type != -1; 129275680Strasz ap += atr->reclen) { 130275680Strasz if (atr->a_type == NTFS_A_VOLUMENAME) { 131275680Strasz if(atr->a_datalen >= size *2){ 132275680Strasz goto fail; 133275680Strasz } 134275680Strasz /* 135275680Strasz *UNICODE to ASCII. 136275680Strasz * Should we need to use iconv(9)? 137275680Strasz */ 138275680Strasz for (j = 0; j < atr->a_datalen; j++) { 139275680Strasz vnchar = *(ap + atr->a_dataoff + j); 140275680Strasz if (j & 1) { 141275680Strasz if (vnchar) { 142275680Strasz goto fail; 143275680Strasz } 144275680Strasz } else { 145275680Strasz label[j / 2] = vnchar; 146275680Strasz } 147275680Strasz } 148275680Strasz label[j / 2] = 0; 149275680Strasz break; 150275680Strasz } 151275680Strasz } 152275680Strasz 153275680Strasz free(bf); 154275680Strasz free(filerecp); 155275680Strasz 156275680Strasz return (0); 157275680Strasz 158275680Straszfail: 159275680Strasz free(bf); 160275680Strasz free(filerecp); 161275680Strasz 162275680Strasz return (1); 163275680Strasz} 164