~pr0gg3d/ubuntu/oneiric/util-linux/bug-805886

« back to all changes in this revision

Viewing changes to shlibs/blkid/src/probers/ntfs.c

  • Committer: Bazaar Package Importer
  • Author(s): Scott James Remnant
  • Date: 2009-07-16 15:48:23 UTC
  • mfrom: (1.3.7 upstream)
  • Revision ID: james.westby@ubuntu.com-20090716154823-i26fshvs4v8h90qh
Tags: 2.16-1ubuntu1
* Merge from Debian, remaining changes:
  - Since udev is required in Ubuntu, the hwclock.sh init script is
    not called on startup and the hwclockfirst.sh init script is
    removed.
  - Remove /etc/adjtime on upgrade if it was not used.
  - Install custom blkid.conf to use /dev/.blkid.tab since we don't
    expect device names to survive a reboot
  - No lsb_release call in mount.preinst since we'd need Pre-Depends
    (LP: #383697).

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 "blkidP.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
};
 
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
        unsigned char   label_str[129], *cp;
 
69
        int             bytes_per_sector, sectors_per_cluster;
 
70
        int             mft_record_size, attr_off, attr_len;
 
71
        unsigned int    i, attr_type, val_len;
 
72
        int             val_off;
 
73
        uint64_t                nr_clusters;
 
74
        blkid_loff_t off;
 
75
        unsigned char *buf_mft, *val;
 
76
 
 
77
        ns = blkid_probe_get_sb(pr, mag, struct ntfs_super_block);
 
78
        if (!ns)
 
79
                return -1;
 
80
 
 
81
        bytes_per_sector = ns->bios_parameter_block[0] +
 
82
                (ns->bios_parameter_block[1]  << 8);
 
83
        sectors_per_cluster = ns->bios_parameter_block[2];
 
84
 
 
85
        if ((bytes_per_sector < 512) || (sectors_per_cluster == 0))
 
86
                return 1;
 
87
 
 
88
        if (ns->cluster_per_mft_record < 0)
 
89
                mft_record_size = 1 << (0 - ns->cluster_per_mft_record);
 
90
        else
 
91
                mft_record_size = ns->cluster_per_mft_record *
 
92
                        sectors_per_cluster * bytes_per_sector;
 
93
        nr_clusters = le64_to_cpu(ns->number_of_sectors) / sectors_per_cluster;
 
94
 
 
95
        if ((le64_to_cpu(ns->mft_cluster_location) > nr_clusters) ||
 
96
            (le64_to_cpu(ns->mft_mirror_cluster_location) > nr_clusters))
 
97
                return 1;
 
98
 
 
99
        off = le64_to_cpu(ns->mft_mirror_cluster_location) *
 
100
                bytes_per_sector * sectors_per_cluster;
 
101
 
 
102
        buf_mft = blkid_probe_get_buffer(pr, off, mft_record_size);
 
103
        if (!buf_mft)
 
104
                return 1;
 
105
 
 
106
        if (memcmp(buf_mft, "FILE", 4))
 
107
                return 1;
 
108
 
 
109
        off = le64_to_cpu(ns->mft_cluster_location) * bytes_per_sector *
 
110
                sectors_per_cluster;
 
111
 
 
112
        buf_mft = blkid_probe_get_buffer(pr, off, mft_record_size);
 
113
        if (!buf_mft)
 
114
                return 1;
 
115
 
 
116
        if (memcmp(buf_mft, "FILE", 4))
 
117
                return 1;
 
118
 
 
119
        off += MFT_RECORD_VOLUME * mft_record_size;
 
120
 
 
121
        buf_mft = blkid_probe_get_buffer(pr, off, mft_record_size);
 
122
        if (!buf_mft)
 
123
                return 1;
 
124
 
 
125
        if (memcmp(buf_mft, "FILE", 4))
 
126
                return 1;
 
127
 
 
128
        mft = (struct master_file_table_record *) buf_mft;
 
129
 
 
130
        attr_off = le16_to_cpu(mft->attrs_offset);
 
131
        label_str[0] = 0;
 
132
 
 
133
        while (1) {
 
134
                attr = (struct file_attribute *) (buf_mft + attr_off);
 
135
                attr_len = le16_to_cpu(attr->len);
 
136
                attr_type = le32_to_cpu(attr->type);
 
137
                val_off = le16_to_cpu(attr->value_offset);
 
138
                val_len = le32_to_cpu(attr->value_len);
 
139
 
 
140
                attr_off += attr_len;
 
141
 
 
142
                if ((attr_off > mft_record_size) ||
 
143
                    (attr_len == 0))
 
144
                        break;
 
145
 
 
146
                if (attr_type == MFT_RECORD_ATTR_END)
 
147
                        break;
 
148
 
 
149
                if (attr_type == MFT_RECORD_ATTR_VOLUME_NAME) {
 
150
                        if (val_len > sizeof(label_str))
 
151
                                val_len = sizeof(label_str)-1;
 
152
 
 
153
                        for (i=0, cp=label_str; i < val_len; i+=2,cp++) {
 
154
                                val = ((uint8_t *) attr) + val_off + i;
 
155
                                *cp = val[0];
 
156
                                if (val[1])
 
157
                                        *cp = '?';
 
158
                        }
 
159
                        *cp = 0;
 
160
                }
 
161
        }
 
162
 
 
163
        blkid_probe_sprintf_uuid(pr,
 
164
                        (unsigned char *) &ns->volume_serial,
 
165
                        sizeof(ns->volume_serial),
 
166
                        "%016" PRIX64, le64_to_cpu(ns->volume_serial));
 
167
        if (label_str[0])
 
168
                blkid_probe_set_label(pr, label_str, strlen((char *)label_str));
 
169
        return 0;
 
170
}
 
171
 
 
172
 
 
173
const struct blkid_idinfo ntfs_idinfo =
 
174
{
 
175
        .name           = "ntfs",
 
176
        .usage          = BLKID_USAGE_FILESYSTEM,
 
177
        .probefunc      = probe_ntfs,
 
178
        .magics         =
 
179
        {
 
180
                { .magic = "NTFS    ", .len = 8, .sboff = 3 },
 
181
                { NULL }
 
182
        }
 
183
};
 
184