source: branches/3.2/mindi-busybox/util-linux/volume_id/ntfs.c @ 3232

Last change on this file since 3232 was 3232, checked in by bruno, 5 years ago
  • Update mindi-busybox to 1.21.1
  • Property svn:eol-style set to native
File size: 5.3 KB
Line 
1/*
2 * volume_id - reads filesystem label and uuid
3 *
4 * Copyright (C) 2004 Kay Sievers <kay.sievers@vrfy.org>
5 *
6 *  This library is free software; you can redistribute it and/or
7 *  modify it under the terms of the GNU Lesser General Public
8 *  License as published by the Free Software Foundation; either
9 *  version 2.1 of the License, or (at your option) any later version.
10 *
11 *  This library is distributed in the hope that it will be useful,
12 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
13 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 *  Lesser General Public License for more details.
15 *
16 *  You should have received a copy of the GNU Lesser General Public
17 *  License along with this library; if not, write to the Free Software
18 *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 */
20
21#include "volume_id_internal.h"
22
23struct ntfs_super_block {
24    uint8_t     jump[3];
25    uint8_t     oem_id[8];
26    uint16_t    bytes_per_sector;
27    uint8_t     sectors_per_cluster;
28    uint16_t    reserved_sectors;
29    uint8_t     fats;
30    uint16_t    root_entries;
31    uint16_t    sectors;
32    uint8_t     media_type;
33    uint16_t    sectors_per_fat;
34    uint16_t    sectors_per_track;
35    uint16_t    heads;
36    uint32_t    hidden_sectors;
37    uint32_t    large_sectors;
38    uint16_t    unused[2];
39    uint64_t    number_of_sectors;
40    uint64_t    mft_cluster_location;
41    uint64_t    mft_mirror_cluster_location;
42    int8_t      cluster_per_mft_record;
43    uint8_t     reserved1[3];
44    int8_t      cluster_per_index_record;
45    uint8_t     reserved2[3];
46    uint8_t     volume_serial[8];
47    uint16_t    checksum;
48} PACKED;
49
50struct master_file_table_record {
51    uint8_t     magic[4];
52    uint16_t    usa_ofs;
53    uint16_t    usa_count;
54    uint64_t    lsn;
55    uint16_t    sequence_number;
56    uint16_t    link_count;
57    uint16_t    attrs_offset;
58    uint16_t    flags;
59    uint32_t    bytes_in_use;
60    uint32_t    bytes_allocated;
61} PACKED;
62
63struct file_attribute {
64    uint32_t    type;
65    uint32_t    len;
66    uint8_t     non_resident;
67    uint8_t     name_len;
68    uint16_t    name_offset;
69    uint16_t    flags;
70    uint16_t    instance;
71    uint32_t    value_len;
72    uint16_t    value_offset;
73} PACKED;
74
75struct volume_info {
76    uint64_t    reserved;
77    uint8_t     major_ver;
78    uint8_t     minor_ver;
79} PACKED;
80
81#define MFT_RECORD_VOLUME           3
82#define MFT_RECORD_ATTR_VOLUME_NAME     0x60
83#define MFT_RECORD_ATTR_VOLUME_INFO     0x70
84#define MFT_RECORD_ATTR_OBJECT_ID       0x40
85#define MFT_RECORD_ATTR_END         0xffffffffu
86
87int FAST_FUNC volume_id_probe_ntfs(struct volume_id *id /*,uint64_t off*/)
88{
89#define off ((uint64_t)0)
90    unsigned sector_size;
91    unsigned cluster_size;
92    uint64_t mft_cluster;
93    uint64_t mft_off;
94    unsigned mft_record_size;
95    unsigned attr_type;
96    unsigned attr_off;
97    unsigned attr_len;
98    unsigned val_off;
99    unsigned val_len;
100    struct master_file_table_record *mftr;
101    struct ntfs_super_block *ns;
102    const uint8_t *buf;
103    const uint8_t *val;
104
105    dbg("probing at offset 0x%llx", (unsigned long long) off);
106
107    ns = volume_id_get_buffer(id, off, 0x200);
108    if (ns == NULL)
109        return -1;
110
111    if (memcmp(ns->oem_id, "NTFS", 4) != 0)
112        return -1;
113
114    volume_id_set_uuid(id, ns->volume_serial, UUID_NTFS);
115
116    sector_size = le16_to_cpu(ns->bytes_per_sector);
117    cluster_size = ns->sectors_per_cluster * sector_size;
118    mft_cluster = le64_to_cpu(ns->mft_cluster_location);
119    mft_off = mft_cluster * cluster_size;
120
121    if (ns->cluster_per_mft_record < 0)
122        /* size = -log2(mft_record_size); normally 1024 Bytes */
123        mft_record_size = 1 << -ns->cluster_per_mft_record;
124    else
125        mft_record_size = ns->cluster_per_mft_record * cluster_size;
126
127    dbg("sectorsize  0x%x", sector_size);
128    dbg("clustersize 0x%x", cluster_size);
129    dbg("mftcluster  %llu", (unsigned long long) mft_cluster);
130    dbg("mftoffset  0x%llx", (unsigned long long) mft_off);
131    dbg("cluster per mft_record  %i", ns->cluster_per_mft_record);
132    dbg("mft record size  %i", mft_record_size);
133
134    buf = volume_id_get_buffer(id, off + mft_off + (MFT_RECORD_VOLUME * mft_record_size),
135            mft_record_size);
136    if (buf == NULL)
137        goto found;
138
139    mftr = (struct master_file_table_record*) buf;
140
141    dbg("mftr->magic '%c%c%c%c'", mftr->magic[0], mftr->magic[1], mftr->magic[2], mftr->magic[3]);
142    if (memcmp(mftr->magic, "FILE", 4) != 0)
143        goto found;
144
145    attr_off = le16_to_cpu(mftr->attrs_offset);
146    dbg("file $Volume's attributes are at offset %i", attr_off);
147
148    while (1) {
149        struct file_attribute *attr;
150
151        attr = (struct file_attribute*) &buf[attr_off];
152        attr_type = le32_to_cpu(attr->type);
153        attr_len = le32_to_cpu(attr->len);
154        val_off = le16_to_cpu(attr->value_offset);
155        val_len = le32_to_cpu(attr->value_len);
156        attr_off += attr_len;
157
158        if (attr_len == 0)
159            break;
160
161        if (attr_off >= mft_record_size)
162            break;
163
164        if (attr_type == MFT_RECORD_ATTR_END)
165            break;
166
167        dbg("found attribute type 0x%x, len %i, at offset %i",
168            attr_type, attr_len, attr_off);
169
170//      if (attr_type == MFT_RECORD_ATTR_VOLUME_INFO) {
171//          struct volume_info *info;
172//          dbg("found info, len %i", val_len);
173//          info = (struct volume_info*) (((uint8_t *) attr) + val_off);
174//          snprintf(id->type_version, sizeof(id->type_version)-1,
175//               "%u.%u", info->major_ver, info->minor_ver);
176//      }
177
178        if (attr_type == MFT_RECORD_ATTR_VOLUME_NAME) {
179            dbg("found label, len %i", val_len);
180            if (val_len > VOLUME_ID_LABEL_SIZE)
181                val_len = VOLUME_ID_LABEL_SIZE;
182
183            val = ((uint8_t *) attr) + val_off;
184//          volume_id_set_label_raw(id, val, val_len);
185            volume_id_set_label_unicode16(id, val, LE, val_len);
186        }
187    }
188
189 found:
190//  volume_id_set_usage(id, VOLUME_ID_FILESYSTEM);
191    IF_FEATURE_BLKID_TYPE(id->type = "ntfs";)
192
193    return 0;
194}
Note: See TracBrowser for help on using the repository browser.