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