source: MondoRescue/branches/3.3/mindi-busybox/util-linux/volume_id/ntfs.c@ 3625

Last change on this file since 3625 was 3621, checked in by Bruno Cornec, 10 years ago

New 3?3 banch for incorporation of latest busybox 1.25. Changing minor version to handle potential incompatibilities.

  • Property svn:eol-style set to native
File size: 5.5 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//kbuild:lib-$(CONFIG_FEATURE_VOLUMEID_NTFS) += ntfs.o
22
23//config:
24//config:config FEATURE_VOLUMEID_NTFS
25//config: bool "ntfs filesystem"
26//config: default y
27//config: depends on VOLUMEID
28//config: help
29//config: TODO
30//config:
31
32#include "volume_id_internal.h"
33
34struct ntfs_super_block {
35 uint8_t jump[3];
36 uint8_t oem_id[8];
37 uint16_t bytes_per_sector;
38 uint8_t sectors_per_cluster;
39 uint16_t reserved_sectors;
40 uint8_t fats;
41 uint16_t root_entries;
42 uint16_t sectors;
43 uint8_t media_type;
44 uint16_t sectors_per_fat;
45 uint16_t sectors_per_track;
46 uint16_t heads;
47 uint32_t hidden_sectors;
48 uint32_t large_sectors;
49 uint16_t unused[2];
50 uint64_t number_of_sectors;
51 uint64_t mft_cluster_location;
52 uint64_t mft_mirror_cluster_location;
53 int8_t cluster_per_mft_record;
54 uint8_t reserved1[3];
55 int8_t cluster_per_index_record;
56 uint8_t reserved2[3];
57 uint8_t volume_serial[8];
58 uint16_t checksum;
59} PACKED;
60
61struct master_file_table_record {
62 uint8_t magic[4];
63 uint16_t usa_ofs;
64 uint16_t usa_count;
65 uint64_t lsn;
66 uint16_t sequence_number;
67 uint16_t link_count;
68 uint16_t attrs_offset;
69 uint16_t flags;
70 uint32_t bytes_in_use;
71 uint32_t bytes_allocated;
72} PACKED;
73
74struct file_attribute {
75 uint32_t type;
76 uint32_t len;
77 uint8_t non_resident;
78 uint8_t name_len;
79 uint16_t name_offset;
80 uint16_t flags;
81 uint16_t instance;
82 uint32_t value_len;
83 uint16_t value_offset;
84} PACKED;
85
86struct volume_info {
87 uint64_t reserved;
88 uint8_t major_ver;
89 uint8_t minor_ver;
90} PACKED;
91
92#define MFT_RECORD_VOLUME 3
93#define MFT_RECORD_ATTR_VOLUME_NAME 0x60
94#define MFT_RECORD_ATTR_VOLUME_INFO 0x70
95#define MFT_RECORD_ATTR_OBJECT_ID 0x40
96#define MFT_RECORD_ATTR_END 0xffffffffu
97
98int FAST_FUNC volume_id_probe_ntfs(struct volume_id *id /*,uint64_t off*/)
99{
100#define off ((uint64_t)0)
101 unsigned sector_size;
102 unsigned cluster_size;
103 uint64_t mft_cluster;
104 uint64_t mft_off;
105 unsigned mft_record_size;
106 unsigned attr_type;
107 unsigned attr_off;
108 unsigned attr_len;
109 unsigned val_off;
110 unsigned val_len;
111 struct master_file_table_record *mftr;
112 struct ntfs_super_block *ns;
113 const uint8_t *buf;
114 const uint8_t *val;
115
116 dbg("probing at offset 0x%llx", (unsigned long long) off);
117
118 ns = volume_id_get_buffer(id, off, 0x200);
119 if (ns == NULL)
120 return -1;
121
122 if (memcmp(ns->oem_id, "NTFS", 4) != 0)
123 return -1;
124
125 volume_id_set_uuid(id, ns->volume_serial, UUID_NTFS);
126
127 sector_size = le16_to_cpu(ns->bytes_per_sector);
128 cluster_size = ns->sectors_per_cluster * sector_size;
129 mft_cluster = le64_to_cpu(ns->mft_cluster_location);
130 mft_off = mft_cluster * cluster_size;
131
132 if (ns->cluster_per_mft_record < 0)
133 /* size = -log2(mft_record_size); normally 1024 Bytes */
134 mft_record_size = 1 << -ns->cluster_per_mft_record;
135 else
136 mft_record_size = ns->cluster_per_mft_record * cluster_size;
137
138 dbg("sectorsize 0x%x", sector_size);
139 dbg("clustersize 0x%x", cluster_size);
140 dbg("mftcluster %llu", (unsigned long long) mft_cluster);
141 dbg("mftoffset 0x%llx", (unsigned long long) mft_off);
142 dbg("cluster per mft_record %i", ns->cluster_per_mft_record);
143 dbg("mft record size %i", mft_record_size);
144
145 buf = volume_id_get_buffer(id, off + mft_off + (MFT_RECORD_VOLUME * mft_record_size),
146 mft_record_size);
147 if (buf == NULL)
148 goto found;
149
150 mftr = (struct master_file_table_record*) buf;
151
152 dbg("mftr->magic '%c%c%c%c'", mftr->magic[0], mftr->magic[1], mftr->magic[2], mftr->magic[3]);
153 if (memcmp(mftr->magic, "FILE", 4) != 0)
154 goto found;
155
156 attr_off = le16_to_cpu(mftr->attrs_offset);
157 dbg("file $Volume's attributes are at offset %i", attr_off);
158
159 while (1) {
160 struct file_attribute *attr;
161
162 attr = (struct file_attribute*) &buf[attr_off];
163 attr_type = le32_to_cpu(attr->type);
164 attr_len = le32_to_cpu(attr->len);
165 val_off = le16_to_cpu(attr->value_offset);
166 val_len = le32_to_cpu(attr->value_len);
167 attr_off += attr_len;
168
169 if (attr_len == 0)
170 break;
171
172 if (attr_off >= mft_record_size)
173 break;
174
175 if (attr_type == MFT_RECORD_ATTR_END)
176 break;
177
178 dbg("found attribute type 0x%x, len %i, at offset %i",
179 attr_type, attr_len, attr_off);
180
181// if (attr_type == MFT_RECORD_ATTR_VOLUME_INFO) {
182// struct volume_info *info;
183// dbg("found info, len %i", val_len);
184// info = (struct volume_info*) (((uint8_t *) attr) + val_off);
185// snprintf(id->type_version, sizeof(id->type_version)-1,
186// "%u.%u", info->major_ver, info->minor_ver);
187// }
188
189 if (attr_type == MFT_RECORD_ATTR_VOLUME_NAME) {
190 dbg("found label, len %i", val_len);
191 if (val_len > VOLUME_ID_LABEL_SIZE)
192 val_len = VOLUME_ID_LABEL_SIZE;
193
194 val = ((uint8_t *) attr) + val_off;
195// volume_id_set_label_raw(id, val, val_len);
196 volume_id_set_label_unicode16(id, val, LE, val_len);
197 }
198 }
199
200 found:
201// volume_id_set_usage(id, VOLUME_ID_FILESYSTEM);
202 IF_FEATURE_BLKID_TYPE(id->type = "ntfs";)
203
204 return 0;
205}
Note: See TracBrowser for help on using the repository browser.