1149492Stakawata/*- 2149492Stakawata * Copyright (c) 2005 Takanori Watanabe 3149492Stakawata * All rights reserved. 4149492Stakawata * 5149492Stakawata * Redistribution and use in source and binary forms, with or without 6149492Stakawata * modification, are permitted provided that the following conditions 7149492Stakawata * are met: 8149492Stakawata * 1. Redistributions of source code must retain the above copyright 9149492Stakawata * notice, this list of conditions and the following disclaimer. 10149492Stakawata * 2. Redistributions in binary form must reproduce the above copyright 11149492Stakawata * notice, this list of conditions and the following disclaimer in the 12149492Stakawata * documentation and/or other materials provided with the distribution. 13149492Stakawata * 14149492Stakawata * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 15149492Stakawata * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16149492Stakawata * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17149492Stakawata * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 18149492Stakawata * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19149492Stakawata * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20149492Stakawata * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21149492Stakawata * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22149492Stakawata * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23149492Stakawata * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24149492Stakawata * SUCH DAMAGE. 25149492Stakawata */ 26149492Stakawata 27149492Stakawata#include <sys/cdefs.h> 28149492Stakawata__FBSDID("$FreeBSD$"); 29149492Stakawata 30149492Stakawata#include <sys/param.h> 31149492Stakawata#include <sys/systm.h> 32149492Stakawata#include <sys/kernel.h> 33149492Stakawata#include <sys/malloc.h> 34149492Stakawata 35149492Stakawata#include <geom/geom.h> 36149492Stakawata#include <geom/label/g_label.h> 37149492Stakawata 38247662Sattilio#define NTFS_A_VOLUMENAME 0x60 39247662Sattilio#define NTFS_FILEMAGIC ((uint32_t)(0x454C4946)) 40247662Sattilio#define NTFS_VOLUMEINO 3 41247662Sattilio 42149492Stakawata#define G_LABEL_NTFS_DIR "ntfs" 43149492Stakawata 44247662Sattiliostruct ntfs_attr { 45247662Sattilio uint32_t a_type; 46247662Sattilio uint32_t reclen; 47247662Sattilio uint8_t a_flag; 48247662Sattilio uint8_t a_namelen; 49247662Sattilio uint8_t a_nameoff; 50247662Sattilio uint8_t reserved1; 51247662Sattilio uint8_t a_compression; 52247662Sattilio uint8_t reserved2; 53247662Sattilio uint16_t a_index; 54247662Sattilio uint16_t a_datalen; 55247662Sattilio uint16_t reserved3; 56247662Sattilio uint16_t a_dataoff; 57247662Sattilio uint16_t a_indexed; 58247837Sdumbbell} __packed; 59149492Stakawata 60247662Sattiliostruct ntfs_filerec { 61247662Sattilio uint32_t fr_hdrmagic; 62247662Sattilio uint16_t fr_hdrfoff; 63247662Sattilio uint16_t fr_hdrfnum; 64247662Sattilio uint8_t reserved[8]; 65247662Sattilio uint16_t fr_seqnum; 66247662Sattilio uint16_t fr_nlink; 67247662Sattilio uint16_t fr_attroff; 68247662Sattilio uint16_t fr_flags; 69247662Sattilio uint32_t fr_size; 70247662Sattilio uint32_t fr_allocated; 71247662Sattilio uint64_t fr_mainrec; 72247662Sattilio uint16_t fr_attrnum; 73247837Sdumbbell} __packed; 74247662Sattilio 75247662Sattiliostruct ntfs_bootfile { 76247662Sattilio uint8_t reserved1[3]; 77247662Sattilio uint8_t bf_sysid[8]; 78247662Sattilio uint16_t bf_bps; 79247662Sattilio uint8_t bf_spc; 80247662Sattilio uint8_t reserved2[7]; 81247662Sattilio uint8_t bf_media; 82247662Sattilio uint8_t reserved3[2]; 83247662Sattilio uint16_t bf_spt; 84247662Sattilio uint16_t bf_heads; 85247662Sattilio uint8_t reserver4[12]; 86247662Sattilio uint64_t bf_spv; 87247662Sattilio uint64_t bf_mftcn; 88247662Sattilio uint64_t bf_mftmirrcn; 89250264Sstas int8_t bf_mftrecsz; 90247662Sattilio uint32_t bf_ibsz; 91247662Sattilio uint32_t bf_volsn; 92247837Sdumbbell} __packed; 93247662Sattilio 94149492Stakawatastatic void 95149492Stakawatag_label_ntfs_taste(struct g_consumer *cp, char *label, size_t size) 96149492Stakawata{ 97149492Stakawata struct g_provider *pp; 98247662Sattilio struct ntfs_bootfile *bf; 99247662Sattilio struct ntfs_filerec *fr; 100247662Sattilio struct ntfs_attr *atr; 101154513Spjd off_t voloff; 102154513Spjd char *filerecp, *ap; 103250264Sstas int8_t mftrecsz; 104250264Sstas char vnchar; 105154513Spjd int recsize, j; 106154513Spjd 107149492Stakawata g_topology_assert_not(); 108154513Spjd 109154513Spjd label[0] = '\0'; 110149492Stakawata pp = cp->provider; 111154513Spjd filerecp = NULL; 112154513Spjd 113247662Sattilio bf = (struct ntfs_bootfile *)g_read_data(cp, 0, pp->sectorsize, NULL); 114154513Spjd if (bf == NULL || strncmp(bf->bf_sysid, "NTFS ", 8) != 0) 115154513Spjd goto done; 116149492Stakawata 117250264Sstas mftrecsz = bf->bf_mftrecsz; 118149492Stakawata recsize = (mftrecsz > 0) ? (mftrecsz * bf->bf_bps * bf->bf_spc) : (1 << -mftrecsz); 119248058Sdumbbell if (recsize == 0 || recsize % pp->sectorsize != 0) 120149538Spjd goto done; 121154513Spjd 122149492Stakawata voloff = bf->bf_mftcn * bf->bf_spc * bf->bf_bps + 123154513Spjd recsize * NTFS_VOLUMEINO; 124154513Spjd if (voloff % pp->sectorsize != 0) 125149492Stakawata goto done; 126149492Stakawata 127152922Spjd filerecp = g_read_data(cp, voloff, recsize, NULL); 128152913Ssobomax if (filerecp == NULL) 129152913Ssobomax goto done; 130247662Sattilio fr = (struct ntfs_filerec *)filerecp; 131151684Stakawata 132247662Sattilio if (fr->fr_hdrmagic != NTFS_FILEMAGIC) 133151684Stakawata goto done; 134151684Stakawata 135154513Spjd for (ap = filerecp + fr->fr_attroff; 136247662Sattilio atr = (struct ntfs_attr *)ap, atr->a_type != -1; 137247662Sattilio ap += atr->reclen) { 138247662Sattilio if (atr->a_type == NTFS_A_VOLUMENAME) { 139247662Sattilio if(atr->a_datalen >= size *2){ 140149492Stakawata label[0] = 0; 141149492Stakawata goto done; 142149492Stakawata } 143149492Stakawata /* 144149492Stakawata *UNICODE to ASCII. 145149492Stakawata * Should we need to use iconv(9)? 146149492Stakawata */ 147247662Sattilio for (j = 0; j < atr->a_datalen; j++) { 148247662Sattilio vnchar = *(ap + atr->a_dataoff + j); 149154513Spjd if (j & 1) { 150149492Stakawata if (vnchar) { 151149492Stakawata label[0] = 0; 152149492Stakawata goto done; 153149492Stakawata } 154149492Stakawata } else { 155149492Stakawata label[j / 2] = vnchar; 156149492Stakawata } 157149492Stakawata } 158149492Stakawata label[j / 2] = 0; 159149492Stakawata break; 160149492Stakawata } 161149492Stakawata } 162149492Stakawatadone: 163149492Stakawata if (bf != NULL) 164149492Stakawata g_free(bf); 165149492Stakawata if (filerecp != NULL) 166149492Stakawata g_free(filerecp); 167149492Stakawata} 168149492Stakawata 169199875Straszstruct g_label_desc g_label_ntfs = { 170149492Stakawata .ld_taste = g_label_ntfs_taste, 171199875Strasz .ld_dir = G_LABEL_NTFS_DIR, 172199875Strasz .ld_enabled = 1 173149492Stakawata}; 174199875Strasz 175199875StraszG_LABEL_INIT(ntfs, g_label_ntfs, "Create device nodes for NTFS volumes"); 176