2 * volume_id - reads filesystem label and uuid
4 * Copyright (C) 2004 Kay Sievers <kay.sievers@vrfy.org>
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.
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.
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
21 #include "volume_id_internal.h"
23 struct ntfs_super_block
{
26 uint16_t bytes_per_sector
;
27 uint8_t sectors_per_cluster
;
28 uint16_t reserved_sectors
;
30 uint16_t root_entries
;
33 uint16_t sectors_per_fat
;
34 uint16_t sectors_per_track
;
36 uint32_t hidden_sectors
;
37 uint32_t large_sectors
;
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
;
44 int8_t cluster_per_index_record
;
46 uint8_t volume_serial
[8];
48 } __attribute__((__packed__
));
50 struct master_file_table_record
{
55 uint16_t sequence_number
;
57 uint16_t attrs_offset
;
59 uint32_t bytes_in_use
;
60 uint32_t bytes_allocated
;
61 } __attribute__((__packed__
));
63 struct file_attribute
{
72 uint16_t value_offset
;
73 } __attribute__((__packed__
));
79 } __attribute__((__packed__
));
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
87 int volume_id_probe_ntfs(struct volume_id
*id
/*,uint64_t off*/)
89 #define off ((uint64_t)0)
91 unsigned cluster_size
;
94 unsigned mft_record_size
;
100 struct master_file_table_record
*mftr
;
101 struct ntfs_super_block
*ns
;
105 dbg("probing at offset 0x%llx", (unsigned long long) off
);
107 ns
= volume_id_get_buffer(id
, off
, 0x200);
111 if (memcmp(ns
->oem_id
, "NTFS", 4) != 0)
114 volume_id_set_uuid(id
, ns
->volume_serial
, UUID_NTFS
);
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
;
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
;
125 mft_record_size
= ns
->cluster_per_mft_record
* cluster_size
;
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
);
134 buf
= volume_id_get_buffer(id
, off
+ mft_off
+ (MFT_RECORD_VOLUME
* mft_record_size
),
139 mftr
= (struct master_file_table_record
*) buf
;
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)
145 attr_off
= le16_to_cpu(mftr
->attrs_offset
);
146 dbg("file $Volume's attributes are at offset %i", attr_off
);
149 struct file_attribute
*attr
;
151 attr
= (struct file_attribute
*) &buf
[attr_off
];
152 attr_type
= le32_to_cpu(attr
->type
);
153 attr_len
= le16_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
;
161 if (attr_off
>= mft_record_size
)
164 if (attr_type
== MFT_RECORD_ATTR_END
)
167 dbg("found attribute type 0x%x, len %i, at offset %i",
168 attr_type
, attr_len
, attr_off
);
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);
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
;
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
);
190 // volume_id_set_usage(id, VOLUME_ID_FILESYSTEM);
191 // id->type = "ntfs";