~ubuntu-branches/ubuntu/trusty/util-linux/trusty-proposed

« back to all changes in this revision

Viewing changes to libblkid/src/superblocks/ntfs.c

  • Committer: Package Import Robot
  • Author(s): LaMont Jones
  • Date: 2011-11-03 15:38:23 UTC
  • mto: (4.5.5 sid) (1.6.4)
  • mto: This revision was merged to the branch mainline in revision 85.
  • Revision ID: package-import@ubuntu.com-20111103153823-10sx16jprzxlhkqf
ImportĀ upstreamĀ versionĀ 2.20.1

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * Copyright (C) 2004 Kay Sievers <kay.sievers@vrfy.org>
 
3
 * Copyright (C) 2008 Karel Zak <kzak@redhat.com>
 
4
 *
 
5
 * This file may be redistributed under the terms of the
 
6
 * GNU Lesser General Public License.
 
7
 */
 
8
#include <stdio.h>
 
9
#include <stdlib.h>
 
10
#include <unistd.h>
 
11
#include <string.h>
 
12
#include <inttypes.h>
 
13
 
 
14
#include "superblocks.h"
 
15
 
 
16
struct ntfs_super_block {
 
17
        uint8_t         jump[3];
 
18
        uint8_t         oem_id[8];
 
19
        uint8_t         bios_parameter_block[25];
 
20
        uint16_t        unused[2];
 
21
        uint64_t        number_of_sectors;
 
22
        uint64_t        mft_cluster_location;
 
23
        uint64_t        mft_mirror_cluster_location;
 
24
        int8_t          cluster_per_mft_record;
 
25
        uint8_t         reserved1[3];
 
26
        int8_t          cluster_per_index_record;
 
27
        uint8_t         reserved2[3];
 
28
        uint64_t        volume_serial;
 
29
        uint16_t        checksum;
 
30
} __attribute__((packed));
 
31
 
 
32
struct master_file_table_record {
 
33
        uint32_t        magic;
 
34
        uint16_t        usa_ofs;
 
35
        uint16_t        usa_count;
 
36
        uint64_t        lsn;
 
37
        uint16_t        sequence_number;
 
38
        uint16_t        link_count;
 
39
        uint16_t        attrs_offset;
 
40
        uint16_t        flags;
 
41
        uint32_t        bytes_in_use;
 
42
        uint32_t        bytes_allocated;
 
43
} __attribute__((__packed__));
 
44
 
 
45
struct file_attribute {
 
46
        uint32_t        type;
 
47
        uint32_t        len;
 
48
        uint8_t         non_resident;
 
49
        uint8_t         name_len;
 
50
        uint16_t        name_offset;
 
51
        uint16_t        flags;
 
52
        uint16_t        instance;
 
53
        uint32_t        value_len;
 
54
        uint16_t        value_offset;
 
55
} __attribute__((__packed__));
 
56
 
 
57
#define MFT_RECORD_VOLUME                       3
 
58
#define MFT_RECORD_ATTR_VOLUME_NAME             0x60
 
59
#define MFT_RECORD_ATTR_VOLUME_INFO             0x70
 
60
#define MFT_RECORD_ATTR_OBJECT_ID               0x40
 
61
#define MFT_RECORD_ATTR_END                     0xffffffffu
 
62
 
 
63
static int probe_ntfs(blkid_probe pr, const struct blkid_idmag *mag)
 
64
{
 
65
        struct ntfs_super_block *ns;
 
66
        struct master_file_table_record *mft;
 
67
        struct file_attribute *attr;
 
68
        int             bytes_per_sector, sectors_per_cluster;
 
69
        int             mft_record_size, attr_off, attr_len;
 
70
        unsigned int    attr_type, val_len;
 
71
        int             val_off;
 
72
        uint64_t                nr_clusters;
 
73
        blkid_loff_t off;
 
74
        unsigned char *buf_mft, *val;
 
75
 
 
76
        ns = blkid_probe_get_sb(pr, mag, struct ntfs_super_block);
 
77
        if (!ns)
 
78
                return -1;
 
79
 
 
80
        bytes_per_sector = ns->bios_parameter_block[0] +
 
81
                (ns->bios_parameter_block[1]  << 8);
 
82
        sectors_per_cluster = ns->bios_parameter_block[2];
 
83
 
 
84
        if ((bytes_per_sector < 512) || (sectors_per_cluster == 0))
 
85
                return 1;
 
86
 
 
87
        if (ns->cluster_per_mft_record < 0)
 
88
                mft_record_size = 1 << (0 - ns->cluster_per_mft_record);
 
89
        else
 
90
                mft_record_size = ns->cluster_per_mft_record *
 
91
                        sectors_per_cluster * bytes_per_sector;
 
92
        nr_clusters = le64_to_cpu(ns->number_of_sectors) / sectors_per_cluster;
 
93
 
 
94
        if ((le64_to_cpu(ns->mft_cluster_location) > nr_clusters) ||
 
95
            (le64_to_cpu(ns->mft_mirror_cluster_location) > nr_clusters))
 
96
                return 1;
 
97
 
 
98
        off = le64_to_cpu(ns->mft_mirror_cluster_location) *
 
99
                bytes_per_sector * sectors_per_cluster;
 
100
 
 
101
        buf_mft = blkid_probe_get_buffer(pr, off, mft_record_size);
 
102
        if (!buf_mft)
 
103
                return 1;
 
104
 
 
105
        if (memcmp(buf_mft, "FILE", 4))
 
106
                return 1;
 
107
 
 
108
        off = le64_to_cpu(ns->mft_cluster_location) * bytes_per_sector *
 
109
                sectors_per_cluster;
 
110
 
 
111
        buf_mft = blkid_probe_get_buffer(pr, off, mft_record_size);
 
112
        if (!buf_mft)
 
113
                return 1;
 
114
 
 
115
        if (memcmp(buf_mft, "FILE", 4))
 
116
                return 1;
 
117
 
 
118
        off += MFT_RECORD_VOLUME * mft_record_size;
 
119
 
 
120
        buf_mft = blkid_probe_get_buffer(pr, off, mft_record_size);
 
121
        if (!buf_mft)
 
122
                return 1;
 
123
 
 
124
        if (memcmp(buf_mft, "FILE", 4))
 
125
                return 1;
 
126
 
 
127
        mft = (struct master_file_table_record *) buf_mft;
 
128
 
 
129
        attr_off = le16_to_cpu(mft->attrs_offset);
 
130
 
 
131
        while (1) {
 
132
                attr = (struct file_attribute *) (buf_mft + attr_off);
 
133
                attr_len = le32_to_cpu(attr->len);
 
134
                attr_type = le32_to_cpu(attr->type);
 
135
                val_off = le16_to_cpu(attr->value_offset);
 
136
                val_len = le32_to_cpu(attr->value_len);
 
137
 
 
138
                attr_off += attr_len;
 
139
 
 
140
                if ((attr_off > mft_record_size) ||
 
141
                    (attr_len == 0))
 
142
                        break;
 
143
 
 
144
                if (attr_type == MFT_RECORD_ATTR_END)
 
145
                        break;
 
146
 
 
147
                if (attr_type == MFT_RECORD_ATTR_VOLUME_NAME) {
 
148
                        val = ((uint8_t *) attr) + val_off;
 
149
                        blkid_probe_set_utf8label(pr, val, val_len, BLKID_ENC_UTF16LE);
 
150
                }
 
151
        }
 
152
 
 
153
        blkid_probe_sprintf_uuid(pr,
 
154
                        (unsigned char *) &ns->volume_serial,
 
155
                        sizeof(ns->volume_serial),
 
156
                        "%016" PRIX64, le64_to_cpu(ns->volume_serial));
 
157
        return 0;
 
158
}
 
159
 
 
160
 
 
161
const struct blkid_idinfo ntfs_idinfo =
 
162
{
 
163
        .name           = "ntfs",
 
164
        .usage          = BLKID_USAGE_FILESYSTEM,
 
165
        .probefunc      = probe_ntfs,
 
166
        .magics         =
 
167
        {
 
168
                { .magic = "NTFS    ", .len = 8, .sboff = 3 },
 
169
                { NULL }
 
170
        }
 
171
};
 
172