chiark / gitweb /
3bf7886aaa65c8375133226e6b08f35167d28be8
[elogind.git] / extras / volume_id / volume_id.c
1 /*
2  * volume_id - reads filesystem label and uuid
3  *
4  * Copyright (C) 2004 Kay Sievers <kay.sievers@vrfy.org>
5  *
6  *      The superblock structs are taken from the linux kernel sources
7  *      and the libblkid living inside the e2fsprogs. This is a simple
8  *      straightforward implementation for reading the label strings of the
9  *      most common filesystems.
10  *
11  *      This library is free software; you can redistribute it and/or
12  *      modify it under the terms of the GNU Lesser General Public
13  *      License as published by the Free Software Foundation; either
14  *      version 2.1 of the License, or (at your option) any later version.
15  *
16  *      This library is distributed in the hope that it will be useful,
17  *      but WITHOUT ANY WARRANTY; without even the implied warranty of
18  *      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
19  *      Lesser General Public License for more details.
20  *
21  *      You should have received a copy of the GNU Lesser General Public
22  *      License along with this library; if not, write to the Free Software
23  *      Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
24  */
25
26 #ifndef _GNU_SOURCE
27 #define _GNU_SOURCE 1
28 #endif
29
30 #ifdef HAVE_CONFIG_H
31 #  include <config.h>
32 #endif
33
34 #include <stdio.h>
35 #include <stdlib.h>
36 #include <unistd.h>
37 #include <string.h>
38 #include <errno.h>
39 #include <ctype.h>
40 #include <fcntl.h>
41 #include <sys/stat.h>
42 #include <asm/types.h>
43
44 #include "volume_id.h"
45 #include "volume_id_logging.h"
46
47 #define bswap16(x) (__u16)((((__u16)(x) & 0x00ffu) << 8) | \
48                            (((__u16)(x) & 0xff00u) >> 8))
49
50 #define bswap32(x) (__u32)((((__u32)(x) & 0xff000000u) >> 24) | \
51                            (((__u32)(x) & 0x00ff0000u) >>  8) | \
52                            (((__u32)(x) & 0x0000ff00u) <<  8) | \
53                            (((__u32)(x) & 0x000000ffu) << 24))
54
55 #define bswap64(x) (__u64)((((__u64)(x) & 0xff00000000000000ull) >> 56) | \
56                            (((__u64)(x) & 0x00ff000000000000ull) >> 40) | \
57                            (((__u64)(x) & 0x0000ff0000000000ull) >> 24) | \
58                            (((__u64)(x) & 0x000000ff00000000ull) >>  8) | \
59                            (((__u64)(x) & 0x00000000ff000000ull) <<  8) | \
60                            (((__u64)(x) & 0x0000000000ff0000ull) << 24) | \
61                            (((__u64)(x) & 0x000000000000ff00ull) << 40) | \
62                            (((__u64)(x) & 0x00000000000000ffull) << 56))
63
64 #if (__BYTE_ORDER == __LITTLE_ENDIAN)
65 #define le16_to_cpu(x) (x)
66 #define le32_to_cpu(x) (x)
67 #define le64_to_cpu(x) (x)
68 #define be16_to_cpu(x) bswap16(x)
69 #define be32_to_cpu(x) bswap32(x)
70 #elif (__BYTE_ORDER == __BIG_ENDIAN)
71 #define le16_to_cpu(x) bswap16(x)
72 #define le32_to_cpu(x) bswap32(x)
73 #define le64_to_cpu(x) bswap64(x)
74 #define be16_to_cpu(x) (x)
75 #define be32_to_cpu(x) (x)
76 #endif
77
78 /* size of superblock buffer, reiserfs block is at 64k */
79 #define SB_BUFFER_SIZE                          0x11000
80 /* size of seek buffer 4k */
81 #define SEEK_BUFFER_SIZE                        0x10000
82
83
84 static void set_label_raw(struct volume_id *id,
85                           const __u8 *buf, unsigned int count)
86 {
87         memcpy(id->label_raw, buf, count);
88         id->label_raw_len = count;
89 }
90
91 static void set_label_string(struct volume_id *id,
92                              const __u8 *buf, unsigned int count)
93 {
94         unsigned int i;
95
96         memcpy(id->label, buf, count);
97
98         /* remove trailing whitespace */
99         i = strnlen(id->label, count);
100         while (i--) {
101                 if (! isspace(id->label[i]))
102                         break;
103         }
104         id->label[i+1] = '\0';
105 }
106
107 #define LE              0
108 #define BE              1
109 static void set_label_unicode16(struct volume_id *id,
110                                 const __u8 *buf,
111                                 unsigned int endianess,
112                                 unsigned int count)
113 {
114         unsigned int i, j;
115         __u16 c;
116
117         j = 0;
118         for (i = 0; i + 2 <= count; i += 2) {
119                 if (endianess == LE)
120                         c = (buf[i+1] << 8) | buf[i];
121                 else
122                         c = (buf[i] << 8) | buf[i+1];
123                 if (c == 0) {
124                         id->label[j] = '\0';
125                         break;
126                 } else if (c < 0x80) {
127                         id->label[j++] = (__u8) c;
128                 } else if (c < 0x800) {
129                         id->label[j++] = (__u8) (0xc0 | (c >> 6));
130                         id->label[j++] = (__u8) (0x80 | (c & 0x3f));
131                 } else {
132                         id->label[j++] = (__u8) (0xe0 | (c >> 12));
133                         id->label[j++] = (__u8) (0x80 | ((c >> 6) & 0x3f));
134                         id->label[j++] = (__u8) (0x80 | (c & 0x3f));
135                 }
136         }
137 }
138
139 enum uuid_format {
140         UUID_DCE,
141         UUID_DOS,
142         UUID_NTFS,
143         UUID_HFS,
144 };
145
146 static void set_uuid(struct volume_id *id, const __u8 *buf, enum uuid_format format)
147 {
148         unsigned int i;
149         unsigned int count = 0;
150
151         switch(format) {
152         case UUID_DOS:
153                 count = 4;
154                 break;
155         case UUID_NTFS:
156         case UUID_HFS:
157                 count = 8;
158                 break;
159         case UUID_DCE:
160                 count = 16;
161         }
162         memcpy(id->uuid_raw, buf, count);
163
164         /* if set, create string in the same format, the native platform uses */
165         for (i = 0; i < count; i++)
166                 if (buf[i] != 0)
167                         goto set;
168         return;
169
170 set:
171         switch(format) {
172         case UUID_DOS:
173                 sprintf(id->uuid, "%02X%02X-%02X%02X",
174                         buf[3], buf[2], buf[1], buf[0]);
175                 break;
176         case UUID_NTFS:
177                 sprintf(id->uuid,"%02X%02X%02X%02X%02X%02X%02X%02X",
178                         buf[7], buf[6], buf[5], buf[4],
179                         buf[3], buf[2], buf[1], buf[0]);
180                 break;
181         case UUID_HFS:
182                 sprintf(id->uuid,"%02X%02X%02X%02X%02X%02X%02X%02X",
183                         buf[0], buf[1], buf[2], buf[3],
184                         buf[4], buf[5], buf[6], buf[7]);
185                 break;
186         case UUID_DCE:
187                 sprintf(id->uuid,
188                         "%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x",
189                         buf[0], buf[1], buf[2], buf[3],
190                         buf[4], buf[5],
191                         buf[6], buf[7],
192                         buf[8], buf[9],
193                         buf[10], buf[11], buf[12], buf[13], buf[14],buf[15]);
194                 break;
195         }
196 }
197
198 static __u8 *get_buffer(struct volume_id *id, __u64 off, unsigned int len)
199 {
200         unsigned int buf_len;
201
202         dbg("get buffer off 0x%llx, len 0x%x", off, len);
203         /* check if requested area fits in superblock buffer */
204         if (off + len <= SB_BUFFER_SIZE) {
205                 if (id->sbbuf == NULL) {
206                         id->sbbuf = malloc(SB_BUFFER_SIZE);
207                         if (id->sbbuf == NULL)
208                                 return NULL;
209                 }
210
211                 /* check if we need to read */
212                 if ((off + len) > id->sbbuf_len) {
213                         dbg("read sbbuf len:0x%llx", off + len);
214                         lseek(id->fd, 0, SEEK_SET);
215                         buf_len = read(id->fd, id->sbbuf, off + len);
216                         dbg("got 0x%x (%i) bytes", buf_len, buf_len);
217                         id->sbbuf_len = buf_len;
218                         if (buf_len < off + len)
219                                 return NULL;
220                 }
221
222                 return &(id->sbbuf[off]);
223         } else {
224                 if (len > SEEK_BUFFER_SIZE) {
225                         dbg("seek buffer too small %d", SEEK_BUFFER_SIZE);
226                         return NULL;
227                 }
228
229                 /* get seek buffer */
230                 if (id->seekbuf == NULL) {
231                         id->seekbuf = malloc(SEEK_BUFFER_SIZE);
232                         if (id->seekbuf == NULL)
233                                 return NULL;
234                 }
235
236                 /* check if we need to read */
237                 if ((off < id->seekbuf_off) || ((off + len) > (id->seekbuf_off + id->seekbuf_len))) {
238                         dbg("read seekbuf off:0x%llx len:0x%x", off, len);
239                         if (lseek(id->fd, off, SEEK_SET) == -1)
240                                 return NULL;
241                         buf_len = read(id->fd, id->seekbuf, len);
242                         dbg("got 0x%x (%i) bytes", buf_len, buf_len);
243                         id->seekbuf_off = off;
244                         id->seekbuf_len = buf_len;
245                         if (buf_len < len) {
246                                 dbg("requested 0x%x bytes, got only 0x%x bytes", len, buf_len);
247                                 return NULL;
248                         }
249                 }
250
251                 return &(id->seekbuf[off - id->seekbuf_off]);
252         }
253 }
254
255 static void free_buffer(struct volume_id *id)
256 {
257         if (id->sbbuf != NULL) {
258                 free(id->sbbuf);
259                 id->sbbuf = NULL;
260                 id->sbbuf_len = 0;
261         }
262         if (id->seekbuf != NULL) {
263                 free(id->seekbuf);
264                 id->seekbuf = NULL;
265                 id->seekbuf_len = 0;
266         }
267 }
268
269 #define HPT37X_CONFIG_OFF               0x1200
270 #define HPT37X_MAGIC_OK                 0x5a7816f0
271 #define HPT37X_MAGIC_BAD                0x5a7816fd
272 static int probe_highpoint_ataraid(struct volume_id *id, __u64 off)
273 {
274         struct hpt37x {
275                 __u8    filler1[32];
276                 __u32   magic;
277                 __u32   magic_0;
278                 __u32   magic_1;
279         } __attribute__((packed)) *hpt;
280
281         const __u8 *buf;
282
283         buf = get_buffer(id, off + HPT37X_CONFIG_OFF, 0x200);
284         if (buf == NULL)
285                 return -1;
286
287         hpt = (struct hpt37x *) buf;
288
289         if (hpt->magic != HPT37X_MAGIC_OK && hpt->magic != HPT37X_MAGIC_BAD)
290                 return -1;
291
292         id->usage_id = VOLUME_ID_RAID;
293         id->type_id = VOLUME_ID_HPTRAID;
294         id->type = "hpt_ataraid_member";
295
296         return 0;
297 }
298
299 #define LVM1_SB_OFF                     0x400
300 #define LVM1_MAGIC                      "HM"
301 static int probe_lvm1(struct volume_id *id, __u64 off)
302 {
303         struct lvm2_super_block {
304                 __u8    id[2];
305         } __attribute__((packed)) *lvm;
306
307         const __u8 *buf;
308
309         buf = get_buffer(id, off + LVM1_SB_OFF, 0x800);
310         if (buf == NULL)
311                 return -1;
312
313         lvm = (struct lvm2_super_block *) buf;
314
315         if (strncmp(lvm->id, LVM1_MAGIC, 2) != 0)
316                 return -1;
317
318         id->usage_id = VOLUME_ID_RAID;
319         id->type_id = VOLUME_ID_LVM1;
320         id->type = "LVM1_member";
321
322         return 0;
323 }
324
325 #define LVM2_LABEL_ID                   "LABELONE"
326 #define LVM2LABEL_SCAN_SECTORS          4
327 static int probe_lvm2(struct volume_id *id, __u64 off)
328 {
329         struct lvm2_super_block {
330                 __u8    id[8];
331                 __u64   sector_xl;
332                 __u32   crc_xl;
333                 __u32   offset_xl;
334                 __u8    type[8];
335         } __attribute__((packed)) *lvm;
336
337         const __u8 *buf;
338         unsigned int soff;
339
340         buf = get_buffer(id, off, LVM2LABEL_SCAN_SECTORS * 0x200);
341         if (buf == NULL)
342                 return -1;
343
344
345         for (soff = 0; soff < LVM2LABEL_SCAN_SECTORS * 0x200; soff += 0x200) {
346                 lvm = (struct lvm2_super_block *) &buf[soff];
347
348                 if (strncmp(lvm->id, LVM2_LABEL_ID, 8) == 0)
349                         goto found;
350         }
351
352         return -1;
353
354 found:
355         strncpy(id->type_version, lvm->type, 8);
356         id->usage_id = VOLUME_ID_RAID;
357         id->type_id = VOLUME_ID_LVM2;
358         id->type = "LVM2_member";
359
360         return 0;
361 }
362
363 #define MD_RESERVED_BYTES               0x10000
364 #define MD_MAGIC                        0xa92b4efc
365 static int probe_linux_raid(struct volume_id *id, __u64 off, __u64 size)
366 {
367         struct mdp_super_block {
368                 __u32   md_magic;
369                 __u32   major_version;
370                 __u32   minor_version;
371                 __u32   patch_version;
372                 __u32   gvalid_words;
373                 __u32   set_uuid0;
374                 __u32   ctime;
375                 __u32   level;
376                 __u32   size;
377                 __u32   nr_disks;
378                 __u32   raid_disks;
379                 __u32   md_minor;
380                 __u32   not_persistent;
381                 __u32   set_uuid1;
382                 __u32   set_uuid2;
383                 __u32   set_uuid3;
384         } __attribute__((packed)) *mdp;
385
386         const __u8 *buf;
387         __u64 sboff;
388         __u8 uuid[16];
389
390         if (size < 0x10000)
391                 return -1;
392
393         sboff = (size & ~(MD_RESERVED_BYTES - 1)) - MD_RESERVED_BYTES;
394         buf = get_buffer(id, off + sboff, 0x800);
395         if (buf == NULL)
396                 return -1;
397
398         mdp = (struct mdp_super_block *) buf;
399
400         if (le32_to_cpu(mdp->md_magic) != MD_MAGIC)
401                 return -1;
402
403         memcpy(uuid, &mdp->set_uuid0, 4);
404         memcpy(&uuid[4], &mdp->set_uuid1, 12);
405         set_uuid(id, uuid, UUID_DCE);
406
407         snprintf(id->type_version, VOLUME_ID_FORMAT_SIZE-1, "%u.%u.%u",
408                  le32_to_cpu(mdp->major_version),
409                  le32_to_cpu(mdp->minor_version),
410                  le32_to_cpu(mdp->patch_version));
411
412         dbg("found raid signature");
413         id->usage_id = VOLUME_ID_RAID;
414         id->type = "linux_raid_member";
415
416         return 0;
417 }
418
419 #define MSDOS_MAGIC                     "\x55\xaa"
420 #define MSDOS_PARTTABLE_OFFSET          0x1be
421 #define MSDOS_SIG_OFF                   0x1fe
422 #define BSIZE                           0x200
423 #define DOS_EXTENDED_PARTITION          0x05
424 #define LINUX_EXTENDED_PARTITION        0x85
425 #define WIN98_EXTENDED_PARTITION        0x0f
426 #define LINUX_RAID_PARTITION            0xfd
427 #define is_extended(type) \
428         (type == DOS_EXTENDED_PARTITION ||      \
429          type == WIN98_EXTENDED_PARTITION ||    \
430          type == LINUX_EXTENDED_PARTITION)
431 #define is_raid(type) \
432         (type == LINUX_RAID_PARTITION)
433 static int probe_msdos_part_table(struct volume_id *id, __u64 off)
434 {
435         struct msdos_partition_entry {
436                 __u8    boot_ind;
437                 __u8    head;
438                 __u8    sector;
439                 __u8    cyl;
440                 __u8    sys_ind;
441                 __u8    end_head;
442                 __u8    end_sector;
443                 __u8    end_cyl;
444                 __u32   start_sect;
445                 __u32   nr_sects;
446         } __attribute__((packed)) *part;
447
448         const __u8 *buf;
449         int i;
450         __u64 poff;
451         __u64 plen;
452         __u64 extended = 0;
453         __u64 current;
454         __u64 next;
455         int limit;
456         int empty = 1;
457         struct volume_id_partition *p;
458
459         buf = get_buffer(id, off, 0x200);
460         if (buf == NULL)
461                 return -1;
462
463         if (strncmp(&buf[MSDOS_SIG_OFF], MSDOS_MAGIC, 2) != 0)
464                 return -1;
465
466         /* check flags on all entries for a valid partition table */
467         part = (struct msdos_partition_entry*) &buf[MSDOS_PARTTABLE_OFFSET];
468         for (i = 0; i < 4; i++) {
469                 if (part[i].boot_ind != 0 &&
470                     part[i].boot_ind != 0x80)
471                         return -1;
472
473                 if (le32_to_cpu(part[i].nr_sects) != 0)
474                         empty = 0;
475         }
476         if (empty == 1)
477                 return -1;
478
479         if (id->partitions != NULL)
480                 free(id->partitions);
481         id->partitions = malloc(VOLUME_ID_PARTITIONS_MAX *
482                                 sizeof(struct volume_id_partition));
483         if (id->partitions == NULL)
484                 return -1;
485         memset(id->partitions, 0x00,
486                VOLUME_ID_PARTITIONS_MAX * sizeof(struct volume_id_partition));
487
488         for (i = 0; i < 4; i++) {
489                 poff = (__u64) le32_to_cpu(part[i].start_sect) * BSIZE;
490                 plen = (__u64) le32_to_cpu(part[i].nr_sects) * BSIZE;
491
492                 if (plen == 0)
493                         continue;
494
495                 p = &id->partitions[i];
496
497                 p->partition_type_raw = part[i].sys_ind;
498
499                 if (is_extended(part[i].sys_ind)) {
500                         dbg("found extended partition at 0x%llx", poff);
501                         p->usage_id = VOLUME_ID_PARTITIONTABLE;
502                         p->type_id = VOLUME_ID_MSDOSEXTENDED;
503                         p->type = "msdos_extended_partition";
504                         if (extended == 0)
505                                 extended = off + poff;
506                 } else {
507                         dbg("found 0x%x data partition at 0x%llx, len 0x%llx",
508                             part[i].sys_ind, poff, plen);
509
510                         if (is_raid(part[i].sys_ind))
511                                 p->usage_id = VOLUME_ID_RAID;
512                         else
513                                 p->usage_id = VOLUME_ID_UNPROBED;
514                 }
515
516                 p->off = off + poff;
517                 p->len = plen;
518                 id->partition_count = i+1;
519         }
520
521         next = extended;
522         current = extended;
523         limit = 50;
524
525         /* follow extended partition chain and add data partitions */
526         while (next != 0) {
527                 if (limit-- == 0) {
528                         dbg("extended chain limit reached");
529                         break;
530                 }
531
532                 buf = get_buffer(id, current, 0x200);
533                 if (buf == NULL)
534                         break;
535
536                 part = (struct msdos_partition_entry*) &buf[MSDOS_PARTTABLE_OFFSET];
537
538                 if (strncmp(&buf[MSDOS_SIG_OFF], MSDOS_MAGIC, 2) != 0)
539                         break;
540
541                 next = 0;
542
543                 for (i = 0; i < 4; i++) {
544                         poff = (__u64) le32_to_cpu(part[i].start_sect) * BSIZE;
545                         plen = (__u64) le32_to_cpu(part[i].nr_sects) * BSIZE;
546
547                         if (plen == 0)
548                                 continue;
549
550                         if (is_extended(part[i].sys_ind)) {
551                                 dbg("found extended partition at 0x%llx", poff);
552                                 if (next == 0)
553                                         next = extended + poff;
554                         } else {
555                                 dbg("found 0x%x data partition at 0x%llx, len 0x%llx",
556                                         part[i].sys_ind, poff, plen);
557
558                                 /* we always start at the 5th entry */
559                                 while (id->partition_count < 4)
560                                         id->partitions[id->partition_count++].usage_id =
561                                                 VOLUME_ID_UNUSED;
562
563                                 p = &id->partitions[id->partition_count];
564
565                                 if (is_raid(part[i].sys_ind))
566                                         p->usage_id = VOLUME_ID_RAID;
567                                 else
568                                         p->usage_id = VOLUME_ID_UNPROBED;
569
570                                 p->off = current + poff;
571                                 p->len = plen;
572                                 id->partition_count++;
573
574                                 p->partition_type_raw = part[i].sys_ind;
575
576                                 if (id->partition_count >= VOLUME_ID_PARTITIONS_MAX) {
577                                         dbg("too many partitions");
578                                         next = 0;
579                                 }
580                         }
581                 }
582
583                 current = next;
584         }
585
586         id->usage_id = VOLUME_ID_PARTITIONTABLE;
587         id->type_id = VOLUME_ID_MSDOSPARTTABLE;
588         id->type = "msdos_partition_table";
589
590         return 0;
591 }
592
593 #define EXT3_FEATURE_COMPAT_HAS_JOURNAL         0x00000004
594 #define EXT3_FEATURE_INCOMPAT_JOURNAL_DEV       0x00000008
595 #define EXT_SUPERBLOCK_OFFSET                   0x400
596 static int probe_ext(struct volume_id *id, __u64 off)
597 {
598         struct ext2_super_block {
599                 __u32   inodes_count;
600                 __u32   blocks_count;
601                 __u32   r_blocks_count;
602                 __u32   free_blocks_count;
603                 __u32   free_inodes_count;
604                 __u32   first_data_block;
605                 __u32   log_block_size;
606                 __u32   dummy3[7];
607                 __u8    magic[2];
608                 __u16   state;
609                 __u32   dummy5[8];
610                 __u32   feature_compat;
611                 __u32   feature_incompat;
612                 __u32   feature_ro_compat;
613                 __u8    uuid[16];
614                 __u8    volume_name[16];
615         } __attribute__((__packed__)) *es;
616
617         es = (struct ext2_super_block *)
618              get_buffer(id, off + EXT_SUPERBLOCK_OFFSET, 0x200);
619         if (es == NULL)
620                 return -1;
621
622         if (es->magic[0] != 0123 ||
623             es->magic[1] != 0357)
624                 return -1;
625
626         set_label_raw(id, es->volume_name, 16);
627         set_label_string(id, es->volume_name, 16);
628         set_uuid(id, es->uuid, UUID_DCE);
629
630         if ((le32_to_cpu(es->feature_compat) &
631              EXT3_FEATURE_COMPAT_HAS_JOURNAL) != 0) {
632                 id->usage_id = VOLUME_ID_FILESYSTEM;
633                 id->type_id = VOLUME_ID_EXT3;
634                 id->type = "ext3";
635         } else {
636                 id->usage_id = VOLUME_ID_FILESYSTEM;
637                 id->type_id = VOLUME_ID_EXT2;
638                 id->type = "ext2";
639         }
640
641         return 0;
642 }
643
644 #define REISERFS1_SUPERBLOCK_OFFSET             0x2000
645 #define REISERFS_SUPERBLOCK_OFFSET              0x10000
646 static int probe_reiserfs(struct volume_id *id, __u64 off)
647 {
648         struct reiserfs_super_block {
649                 __u32   blocks_count;
650                 __u32   free_blocks;
651                 __u32   root_block;
652                 __u32   journal_block;
653                 __u32   journal_dev;
654                 __u32   orig_journal_size;
655                 __u32   dummy2[5];
656                 __u16   blocksize;
657                 __u16   dummy3[3];
658                 __u8    magic[12];
659                 __u32   dummy4[5];
660                 __u8    uuid[16];
661                 __u8    label[16];
662         } __attribute__((__packed__)) *rs;
663
664         rs = (struct reiserfs_super_block *)
665              get_buffer(id, off + REISERFS_SUPERBLOCK_OFFSET, 0x200);
666         if (rs == NULL)
667                 return -1;
668
669         if (strncmp(rs->magic, "ReIsEr2Fs", 9) == 0) {
670                 strcpy(id->type_version, "3.6");
671                 goto found;
672         }
673
674         if (strncmp(rs->magic, "ReIsEr3Fs", 9) == 0) {
675                 strcpy(id->type_version, "JR");
676                 goto found;
677         }
678
679         rs = (struct reiserfs_super_block *)
680              get_buffer(id, off + REISERFS1_SUPERBLOCK_OFFSET, 0x200);
681         if (rs == NULL)
682                 return -1;
683
684         if (strncmp(rs->magic, "ReIsErFs", 8) == 0) {
685                 strcpy(id->type_version, "3.5");
686                 goto found;
687         }
688
689         return -1;
690
691 found:
692         set_label_raw(id, rs->label, 16);
693         set_label_string(id, rs->label, 16);
694         set_uuid(id, rs->uuid, UUID_DCE);
695
696         id->usage_id = VOLUME_ID_FILESYSTEM;
697         id->type_id = VOLUME_ID_REISERFS;
698         id->type = "reiserfs";
699
700         return 0;
701 }
702
703 static int probe_xfs(struct volume_id *id, __u64 off)
704 {
705         struct xfs_super_block {
706                 __u8    magic[4];
707                 __u32   blocksize;
708                 __u64   dblocks;
709                 __u64   rblocks;
710                 __u32   dummy1[2];
711                 __u8    uuid[16];
712                 __u32   dummy2[15];
713                 __u8    fname[12];
714                 __u32   dummy3[2];
715                 __u64   icount;
716                 __u64   ifree;
717                 __u64   fdblocks;
718         } __attribute__((__packed__)) *xs;
719
720         xs = (struct xfs_super_block *) get_buffer(id, off, 0x200);
721         if (xs == NULL)
722                 return -1;
723
724         if (strncmp(xs->magic, "XFSB", 4) != 0)
725                 return -1;
726
727         set_label_raw(id, xs->fname, 12);
728         set_label_string(id, xs->fname, 12);
729         set_uuid(id, xs->uuid, UUID_DCE);
730
731         id->usage_id = VOLUME_ID_FILESYSTEM;
732         id->type_id = VOLUME_ID_XFS;
733         id->type = "xfs";
734
735         return 0;
736 }
737
738 #define JFS_SUPERBLOCK_OFFSET                   0x8000
739 static int probe_jfs(struct volume_id *id, __u64 off)
740 {
741         struct jfs_super_block {
742                 __u8    magic[4];
743                 __u32   version;
744                 __u64   size;
745                 __u32   bsize;
746                 __u32   dummy1;
747                 __u32   pbsize;
748                 __u32   dummy2[27];
749                 __u8    uuid[16];
750                 __u8    label[16];
751                 __u8    loguuid[16];
752         } __attribute__((__packed__)) *js;
753
754         js = (struct jfs_super_block *)
755              get_buffer(id, off + JFS_SUPERBLOCK_OFFSET, 0x200);
756         if (js == NULL)
757                 return -1;
758
759         if (strncmp(js->magic, "JFS1", 4) != 0)
760                 return -1;
761
762         set_label_raw(id, js->label, 16);
763         set_label_string(id, js->label, 16);
764         set_uuid(id, js->uuid, UUID_DCE);
765
766         id->usage_id = VOLUME_ID_FILESYSTEM;
767         id->type_id = VOLUME_ID_JFS;
768         id->type = "jfs";
769
770         return 0;
771 }
772
773 #define FAT12_MAX                       0xff5
774 #define FAT16_MAX                       0xfff5
775 #define FAT_ATTR_VOLUME_ID              0x08
776 #define FAT_ATTR_DIR                    0x10
777 #define FAT_ATTR_LONG_NAME              0x0f
778 #define FAT_ATTR_MASK                   0x3f
779 #define FAT_ENTRY_FREE                  0xe5
780 static int probe_vfat(struct volume_id *id, __u64 off)
781 {
782         struct vfat_super_block {
783                 __u8    boot_jump[3];
784                 __u8    sysid[8];
785                 __u16   sector_size;
786                 __u8    sectors_per_cluster;
787                 __u16   reserved;
788                 __u8    fats;
789                 __u16   dir_entries;
790                 __u16   sectors;
791                 __u8    media;
792                 __u16   fat_length;
793                 __u16   secs_track;
794                 __u16   heads;
795                 __u32   hidden;
796                 __u32   total_sect;
797                 union {
798                         struct fat_super_block {
799                                 __u8    unknown[3];
800                                 __u8    serno[4];
801                                 __u8    label[11];
802                                 __u8    magic[8];
803                                 __u8    dummy2[192];
804                                 __u8    pmagic[2];
805                         } __attribute__((__packed__)) fat;
806                         struct fat32_super_block {
807                                 __u32   fat32_length;
808                                 __u16   flags;
809                                 __u8    version[2];
810                                 __u32   root_cluster;
811                                 __u16   insfo_sector;
812                                 __u16   backup_boot;
813                                 __u16   reserved2[6];
814                                 __u8    unknown[3];
815                                 __u8    serno[4];
816                                 __u8    label[11];
817                                 __u8    magic[8];
818                                 __u8    dummy2[164];
819                                 __u8    pmagic[2];
820                         } __attribute__((__packed__)) fat32;
821                 } __attribute__((__packed__)) type;
822         } __attribute__((__packed__)) *vs;
823
824         struct vfat_dir_entry {
825                 __u8    name[11];
826                 __u8    attr;
827                 __u16   time_creat;
828                 __u16   date_creat;
829                 __u16   time_acc;
830                 __u16   date_acc;
831                 __u16   cluster_high;
832                 __u16   time_write;
833                 __u16   date_write;
834                 __u16   cluster_low;
835                 __u32   size;
836         } __attribute__((__packed__)) *dir;
837
838         __u16 sector_size;
839         __u16 dir_entries;
840         __u32 sect_count;
841         __u16 reserved;
842         __u32 fat_size;
843         __u32 root_cluster;
844         __u32 dir_size;
845         __u32 cluster_count;
846         __u32 fat_length;
847         __u64 root_start;
848         __u32 start_data_sect;
849         __u16 root_dir_entries;
850         __u8 *buf;
851         __u32 buf_size;
852         __u8 *label = NULL;
853         __u32 next;
854         int maxloop;
855         int i;
856
857         vs = (struct vfat_super_block *) get_buffer(id, off, 0x200);
858         if (vs == NULL)
859                 return -1;
860
861         /* believe only that's fat, don't trust the version
862          * the cluster_count will tell us
863          */
864         if (strncmp(vs->sysid, "NTFS", 4) == 0)
865                 return -1;
866
867         if (strncmp(vs->type.fat32.magic, "MSWIN", 5) == 0)
868                 goto valid;
869
870         if (strncmp(vs->type.fat32.magic, "FAT32   ", 8) == 0)
871                 goto valid;
872
873         if (strncmp(vs->type.fat.magic, "FAT16   ", 8) == 0)
874                 goto valid;
875
876         if (strncmp(vs->type.fat.magic, "MSDOS", 5) == 0)
877                 goto valid;
878
879         if (strncmp(vs->type.fat.magic, "FAT12   ", 8) == 0)
880                 goto valid;
881
882         /*
883          * There are old floppies out there without a magic, so we check
884          * for well known values and guess if it's a fat volume
885          */
886
887         /* boot jump address check */
888         if ((vs->boot_jump[0] != 0xeb || vs->boot_jump[2] != 0x90) &&
889              vs->boot_jump[0] != 0xe9)
890                 return -1;
891
892         /* heads check */
893         if (vs->heads == 0)
894                 return -1;
895
896         /* cluster size check*/ 
897         if (vs->sectors_per_cluster == 0 ||
898             (vs->sectors_per_cluster & (vs->sectors_per_cluster-1)))
899                 return -1;
900
901         /* media check */
902         if (vs->media < 0xf8 && vs->media != 0xf0)
903                 return -1;
904
905         /* fat count*/
906         if (vs->fats != 2)
907                 return -1;
908
909 valid:
910         /* sector size check */
911         sector_size = le16_to_cpu(vs->sector_size);
912         if (sector_size != 0x200 && sector_size != 0x400 &&
913             sector_size != 0x800 && sector_size != 0x1000)
914                 return -1;
915
916         dbg("sector_size 0x%x", sector_size);
917         dbg("sectors_per_cluster 0x%x", vs->sectors_per_cluster);
918
919         dir_entries = le16_to_cpu(vs->dir_entries);
920         reserved = le16_to_cpu(vs->reserved);
921         dbg("reserved 0x%x", reserved);
922
923         sect_count = le16_to_cpu(vs->sectors);
924         if (sect_count == 0)
925                 sect_count = le32_to_cpu(vs->total_sect);
926         dbg("sect_count 0x%x", sect_count);
927
928         fat_length = le16_to_cpu(vs->fat_length);
929         if (fat_length == 0)
930                 fat_length = le32_to_cpu(vs->type.fat32.fat32_length);
931         dbg("fat_length 0x%x", fat_length);
932
933         fat_size = fat_length * vs->fats;
934         dir_size = ((dir_entries * sizeof(struct vfat_dir_entry)) +
935                         (sector_size-1)) / sector_size;
936         dbg("dir_size 0x%x", dir_size);
937
938         cluster_count = sect_count - (reserved + fat_size + dir_size);
939         cluster_count /= vs->sectors_per_cluster;
940         dbg("cluster_count 0x%x", cluster_count);
941
942         if (cluster_count < FAT12_MAX) {
943                 strcpy(id->type_version, "FAT12");
944         } else if (cluster_count < FAT16_MAX) {
945                 strcpy(id->type_version, "FAT16");
946         } else {
947                 strcpy(id->type_version, "FAT32");
948                 goto fat32;
949         }
950
951         /* the label may be an attribute in the root directory */
952         root_start = (reserved + fat_size) * sector_size;
953         dbg("root dir start 0x%llx", root_start);
954         root_dir_entries = le16_to_cpu(vs->dir_entries);
955         dbg("expected entries 0x%x", root_dir_entries);
956
957         buf_size = root_dir_entries * sizeof(struct vfat_dir_entry);
958         buf = get_buffer(id, off + root_start, buf_size);
959         if (buf == NULL)
960                 goto found;
961
962         dir = (struct vfat_dir_entry*) buf;
963
964         for (i = 0; i < root_dir_entries; i++) {
965                 /* end marker */
966                 if (dir[i].name[0] == 0x00) {
967                         dbg("end of dir");
968                         break;
969                 }
970
971                 /* empty entry */
972                 if (dir[i].name[0] == FAT_ENTRY_FREE)
973                         continue;
974
975                 /* long name */
976                 if ((dir[i].attr & FAT_ATTR_MASK) == FAT_ATTR_LONG_NAME)
977                         continue;
978
979                 if ((dir[i].attr & (FAT_ATTR_VOLUME_ID | FAT_ATTR_DIR)) == FAT_ATTR_VOLUME_ID) {
980                         /* labels do not have file data */
981                         if (dir[i].cluster_high != 0 || dir[i].cluster_low != 0)
982                                 continue;
983
984                         dbg("found ATTR_VOLUME_ID id in root dir");
985                         label = dir[i].name;
986                         break;
987                 }
988
989                 dbg("skip dir entry");
990         }
991
992         vs = (struct vfat_super_block *) get_buffer(id, off, 0x200);
993         if (vs == NULL)
994                 return -1;
995
996         if (label != NULL && strncmp(label, "NO NAME    ", 11) != 0) {
997                 set_label_raw(id, label, 11);
998                 set_label_string(id, label, 11);
999         } else if (strncmp(vs->type.fat.label, "NO NAME    ", 11) != 0) {
1000                 set_label_raw(id, vs->type.fat.label, 11);
1001                 set_label_string(id, vs->type.fat.label, 11);
1002         }
1003         set_uuid(id, vs->type.fat.serno, UUID_DOS);
1004         goto found;
1005
1006 fat32:
1007         /* FAT32 root dir is a cluster chain like any other directory */
1008         buf_size = vs->sectors_per_cluster * sector_size;
1009         root_cluster = le32_to_cpu(vs->type.fat32.root_cluster);
1010         dbg("root dir cluster %u", root_cluster);
1011         start_data_sect = reserved + fat_size;
1012
1013         next = root_cluster;
1014         maxloop = 100;
1015         while (--maxloop) {
1016                 __u32 next_sect_off;
1017                 __u64 next_off;
1018                 __u64 fat_entry_off;
1019                 int count;
1020
1021                 dbg("next cluster %u", next);
1022                 next_sect_off = (next - 2) * vs->sectors_per_cluster;
1023                 next_off = (start_data_sect + next_sect_off) * sector_size;
1024                 dbg("cluster offset 0x%llx", next_off);
1025
1026                 /* get cluster */
1027                 buf = get_buffer(id, off + next_off, buf_size);
1028                 if (buf == NULL)
1029                         goto found;
1030
1031                 dir = (struct vfat_dir_entry*) buf;
1032                 count = buf_size / sizeof(struct vfat_dir_entry);
1033                 dbg("expected entries 0x%x", count);
1034
1035                 for (i = 0; i < count; i++) {
1036                         /* end marker */
1037                         if (dir[i].name[0] == 0x00) {
1038                                 dbg("end of dir");
1039                                 goto fat32_label;
1040                         }
1041
1042                         /* empty entry */
1043                         if (dir[i].name[0] == FAT_ENTRY_FREE)
1044                                 continue;
1045
1046                         /* long name */
1047                         if ((dir[i].attr & FAT_ATTR_MASK) == FAT_ATTR_LONG_NAME)
1048                                 continue;
1049
1050                         if ((dir[i].attr & (FAT_ATTR_VOLUME_ID | FAT_ATTR_DIR)) == FAT_ATTR_VOLUME_ID) {
1051                                 /* labels do not have file data */
1052                                 if (dir[i].cluster_high != 0 || dir[i].cluster_low != 0)
1053                                         continue;
1054
1055                                 dbg("found ATTR_VOLUME_ID id in root dir");
1056                                 label = dir[i].name;
1057                                 goto fat32_label;
1058                         }
1059
1060                         dbg("skip dir entry");
1061                 }
1062
1063                 /* get FAT entry */
1064                 fat_entry_off = (reserved * sector_size) + (next * sizeof(__u32));
1065                 buf = get_buffer(id, off + fat_entry_off, buf_size);
1066                 if (buf == NULL)
1067                         goto found;
1068
1069                 /* set next cluster */
1070                 next = le32_to_cpu(*((__u32 *) buf) & 0x0fffffff);
1071                 if (next == 0)
1072                         break;
1073         }
1074         if (maxloop == 0)
1075                 dbg("reached maximum follow count of root cluster chain, give up");
1076
1077 fat32_label:
1078         vs = (struct vfat_super_block *) get_buffer(id, off, 0x200);
1079         if (vs == NULL)
1080                 return -1;
1081
1082         if (label != NULL && strncmp(label, "NO NAME    ", 11) != 0) {
1083                 set_label_raw(id, label, 11);
1084                 set_label_string(id, label, 11);
1085         } else if (strncmp(vs->type.fat32.label, "NO NAME    ", 11) != 0) {
1086                 set_label_raw(id, vs->type.fat32.label, 11);
1087                 set_label_string(id, vs->type.fat32.label, 11);
1088         }
1089         set_uuid(id, vs->type.fat32.serno, UUID_DOS);
1090
1091 found:
1092         id->usage_id = VOLUME_ID_FILESYSTEM;
1093         id->type_id = VOLUME_ID_VFAT;
1094         id->type = "vfat";
1095
1096         return 0;
1097 }
1098
1099 #define UDF_VSD_OFFSET                  0x8000
1100 static int probe_udf(struct volume_id *id, __u64 off)
1101 {
1102         struct volume_descriptor {
1103                 struct descriptor_tag {
1104                         __u16   id;
1105                         __u16   version;
1106                         __u8    checksum;
1107                         __u8    reserved;
1108                         __u16   serial;
1109                         __u16   crc;
1110                         __u16   crc_len;
1111                         __u32   location;
1112                 } __attribute__((__packed__)) tag;
1113                 union {
1114                         struct anchor_descriptor {
1115                                 __u32   length;
1116                                 __u32   location;
1117                         } __attribute__((__packed__)) anchor;
1118                         struct primary_descriptor {
1119                                 __u32   seq_num;
1120                                 __u32   desc_num;
1121                                 struct dstring {
1122                                         __u8    clen;
1123                                         __u8    c[31];
1124                                 } __attribute__((__packed__)) ident;
1125                         } __attribute__((__packed__)) primary;
1126                 } __attribute__((__packed__)) type;
1127         } __attribute__((__packed__)) *vd;
1128
1129         struct volume_structure_descriptor {
1130                 __u8    type;
1131                 __u8    id[5];
1132                 __u8    version;
1133         } *vsd;
1134
1135         unsigned int bs;
1136         unsigned int b;
1137         unsigned int type;
1138         unsigned int count;
1139         unsigned int loc;
1140         unsigned int clen;
1141
1142         vsd = (struct volume_structure_descriptor *)
1143               get_buffer(id, off + UDF_VSD_OFFSET, 0x200);
1144         if (vsd == NULL)
1145                 return -1;
1146
1147         if (strncmp(vsd->id, "NSR02", 5) == 0)
1148                 goto blocksize;
1149         if (strncmp(vsd->id, "NSR03", 5) == 0)
1150                 goto blocksize;
1151         if (strncmp(vsd->id, "BEA01", 5) == 0)
1152                 goto blocksize;
1153         if (strncmp(vsd->id, "BOOT2", 5) == 0)
1154                 goto blocksize;
1155         if (strncmp(vsd->id, "CD001", 5) == 0)
1156                 goto blocksize;
1157         if (strncmp(vsd->id, "CDW02", 5) == 0)
1158                 goto blocksize;
1159         if (strncmp(vsd->id, "TEA03", 5) == 0)
1160                 goto blocksize;
1161         return -1;
1162
1163 blocksize:
1164         /* search the next VSD to get the logical block size of the volume */
1165         for (bs = 0x800; bs < 0x8000; bs += 0x800) {
1166                 vsd = (struct volume_structure_descriptor *)
1167                       get_buffer(id, off + UDF_VSD_OFFSET + bs, 0x800);
1168                 if (vsd == NULL)
1169                         return -1;
1170                 dbg("test for blocksize: 0x%x", bs);
1171                 if (vsd->id[0] != '\0')
1172                         goto nsr;
1173         }
1174         return -1;
1175
1176 nsr:
1177         /* search the list of VSDs for a NSR descriptor */
1178         for (b = 0; b < 64; b++) {
1179                 vsd = (struct volume_structure_descriptor *)
1180                       get_buffer(id, off + UDF_VSD_OFFSET + (b * bs), 0x800);
1181                 if (vsd == NULL)
1182                         return -1;
1183
1184                 dbg("vsd: %c%c%c%c%c",
1185                     vsd->id[0], vsd->id[1], vsd->id[2], vsd->id[3], vsd->id[4]);
1186
1187                 if (vsd->id[0] == '\0')
1188                         return -1;
1189                 if (strncmp(vsd->id, "NSR02", 5) == 0)
1190                         goto anchor;
1191                 if (strncmp(vsd->id, "NSR03", 5) == 0)
1192                         goto anchor;
1193         }
1194         return -1;
1195
1196 anchor:
1197         /* read anchor volume descriptor */
1198         vd = (struct volume_descriptor *)
1199                 get_buffer(id, off + (256 * bs), 0x200);
1200         if (vd == NULL)
1201                 return -1;
1202
1203         type = le16_to_cpu(vd->tag.id);
1204         if (type != 2) /* TAG_ID_AVDP */
1205                 goto found;
1206
1207         /* get desriptor list address and block count */
1208         count = le32_to_cpu(vd->type.anchor.length) / bs;
1209         loc = le32_to_cpu(vd->type.anchor.location);
1210         dbg("0x%x descriptors starting at logical secor 0x%x", count, loc);
1211
1212         /* pick the primary descriptor from the list */
1213         for (b = 0; b < count; b++) {
1214                 vd = (struct volume_descriptor *)
1215                      get_buffer(id, off + ((loc + b) * bs), 0x200);
1216                 if (vd == NULL)
1217                         return -1;
1218
1219                 type = le16_to_cpu(vd->tag.id);
1220                 dbg("descriptor type %i", type);
1221
1222                 /* check validity */
1223                 if (type == 0)
1224                         goto found;
1225                 if (le32_to_cpu(vd->tag.location) != loc + b)
1226                         goto found;
1227
1228                 if (type == 1) /* TAG_ID_PVD */
1229                         goto pvd;
1230         }
1231         goto found;
1232
1233 pvd:
1234         set_label_raw(id, &(vd->type.primary.ident.clen), 32);
1235
1236         clen = vd->type.primary.ident.clen;
1237         dbg("label string charsize=%i bit", clen);
1238         if (clen == 8)
1239                 set_label_string(id, vd->type.primary.ident.c, 31);
1240         else if (clen == 16)
1241                 set_label_unicode16(id, vd->type.primary.ident.c, BE,31);
1242
1243 found:
1244         id->usage_id = VOLUME_ID_FILESYSTEM;
1245         id->type_id = VOLUME_ID_UDF;
1246         id->type = "udf";
1247
1248         return 0;
1249 }
1250
1251 #define ISO_SUPERBLOCK_OFFSET           0x8000
1252 #define ISO_SECTOR_SIZE                 0x800
1253 #define ISO_VD_OFFSET                   (ISO_SUPERBLOCK_OFFSET + ISO_SECTOR_SIZE)
1254 #define ISO_VD_PRIMARY                  0x1
1255 #define ISO_VD_SUPPLEMENTARY            0x2
1256 #define ISO_VD_END                      0xff
1257 #define ISO_VD_MAX                      16
1258 static int probe_iso9660(struct volume_id *id, __u64 off)
1259 {
1260         union iso_super_block {
1261                 struct iso_header {
1262                         __u8    type;
1263                         __u8    id[5];
1264                         __u8    version;
1265                         __u8    unused1;
1266                         __u8            system_id[32];
1267                         __u8            volume_id[32];
1268                 } __attribute__((__packed__)) iso;
1269                 struct hs_header {
1270                         __u8    foo[8];
1271                         __u8    type;
1272                         __u8    id[4];
1273                         __u8    version;
1274                 } __attribute__((__packed__)) hs;
1275         } __attribute__((__packed__)) *is;
1276
1277         is = (union iso_super_block *)
1278              get_buffer(id, off + ISO_SUPERBLOCK_OFFSET, 0x200);
1279         if (is == NULL)
1280                 return -1;
1281
1282         if (strncmp(is->iso.id, "CD001", 5) == 0) {
1283                 char root_label[VOLUME_ID_LABEL_SIZE+1];
1284                 int vd_offset;
1285                 int i;
1286                 int found_svd;
1287
1288                 memset(root_label, 0, sizeof(root_label));
1289                 strncpy(root_label, is->iso.volume_id, sizeof(root_label)-1);
1290
1291                 found_svd = 0;
1292                 vd_offset = ISO_VD_OFFSET;
1293                 for (i = 0; i < ISO_VD_MAX; i++) {
1294                         is = (union iso_super_block *) 
1295                              get_buffer (id, off + vd_offset, 0x200);
1296                         if (is == NULL || is->iso.type == ISO_VD_END)
1297                                 break;
1298                         if (is->iso.type == ISO_VD_SUPPLEMENTARY) {
1299                                 dbg("found ISO supplementary VD at offset 0x%llx", off + vd_offset);
1300                                 set_label_raw(id, is->iso.volume_id, 32);
1301                                 set_label_unicode16(id, is->iso.volume_id, BE, 32);
1302                                 found_svd = 1;
1303                                 break;
1304                         }
1305                         vd_offset += ISO_SECTOR_SIZE;
1306                 }
1307
1308                 if (!found_svd ||
1309                     (found_svd && !strncmp(root_label, id->label, 16)))
1310                 {
1311                         set_label_raw(id, root_label, 32);
1312                         set_label_string(id, root_label, 32);
1313                 }
1314                 goto found;
1315         }
1316         if (strncmp(is->hs.id, "CDROM", 5) == 0)
1317                 goto found;
1318         return -1;
1319
1320 found:
1321         id->usage_id = VOLUME_ID_FILESYSTEM;
1322         id->type_id = VOLUME_ID_ISO9660;
1323         id->type = "iso9660";
1324
1325         return 0;
1326 }
1327
1328 #define UFS_MAGIC                       0x00011954
1329 #define UFS2_MAGIC                      0x19540119
1330 #define UFS_MAGIC_FEA                   0x00195612
1331 #define UFS_MAGIC_LFN                   0x00095014
1332
1333
1334 static int probe_ufs(struct volume_id *id, __u64 off)
1335 {
1336         struct ufs_super_block {
1337                 __u32   fs_link;
1338                 __u32   fs_rlink;
1339                 __u32   fs_sblkno;
1340                 __u32   fs_cblkno;
1341                 __u32   fs_iblkno;
1342                 __u32   fs_dblkno;
1343                 __u32   fs_cgoffset;
1344                 __u32   fs_cgmask;
1345                 __u32   fs_time;
1346                 __u32   fs_size;
1347                 __u32   fs_dsize;
1348                 __u32   fs_ncg; 
1349                 __u32   fs_bsize;
1350                 __u32   fs_fsize;
1351                 __u32   fs_frag;
1352                 __u32   fs_minfree;
1353                 __u32   fs_rotdelay;
1354                 __u32   fs_rps; 
1355                 __u32   fs_bmask;
1356                 __u32   fs_fmask;
1357                 __u32   fs_bshift;
1358                 __u32   fs_fshift;
1359                 __u32   fs_maxcontig;
1360                 __u32   fs_maxbpg;
1361                 __u32   fs_fragshift;
1362                 __u32   fs_fsbtodb;
1363                 __u32   fs_sbsize;
1364                 __u32   fs_csmask;
1365                 __u32   fs_csshift;
1366                 __u32   fs_nindir;
1367                 __u32   fs_inopb;
1368                 __u32   fs_nspf;
1369                 __u32   fs_optim;
1370                 __u32   fs_npsect_state;
1371                 __u32   fs_interleave;
1372                 __u32   fs_trackskew;
1373                 __u32   fs_id[2];
1374                 __u32   fs_csaddr;
1375                 __u32   fs_cssize;
1376                 __u32   fs_cgsize;
1377                 __u32   fs_ntrak;
1378                 __u32   fs_nsect;
1379                 __u32   fs_spc; 
1380                 __u32   fs_ncyl;
1381                 __u32   fs_cpg;
1382                 __u32   fs_ipg;
1383                 __u32   fs_fpg;
1384                 struct ufs_csum {
1385                         __u32   cs_ndir;
1386                         __u32   cs_nbfree;
1387                         __u32   cs_nifree;
1388                         __u32   cs_nffree;
1389                 } __attribute__((__packed__)) fs_cstotal;
1390                 __s8    fs_fmod;
1391                 __s8    fs_clean;
1392                 __s8    fs_ronly;
1393                 __s8    fs_flags;
1394                 union {
1395                         struct {
1396                                 __s8    fs_fsmnt[512];
1397                                 __u32   fs_cgrotor;
1398                                 __u32   fs_csp[31];
1399                                 __u32   fs_maxcluster;
1400                                 __u32   fs_cpc;
1401                                 __u16   fs_opostbl[16][8];
1402                         } __attribute__((__packed__)) fs_u1;
1403                         struct {
1404                                 __s8  fs_fsmnt[468];
1405                                 __u8   fs_volname[32];
1406                                 __u64  fs_swuid;
1407                                 __s32  fs_pad;
1408                                 __u32   fs_cgrotor;
1409                                 __u32   fs_ocsp[28];
1410                                 __u32   fs_contigdirs;
1411                                 __u32   fs_csp; 
1412                                 __u32   fs_maxcluster;
1413                                 __u32   fs_active;
1414                                 __s32   fs_old_cpc;
1415                                 __s32   fs_maxbsize;
1416                                 __s64   fs_sparecon64[17];
1417                                 __s64   fs_sblockloc;
1418                                 struct  ufs2_csum_total {
1419                                         __u64   cs_ndir;
1420                                         __u64   cs_nbfree;
1421                                         __u64   cs_nifree;
1422                                         __u64   cs_nffree;
1423                                         __u64   cs_numclusters;
1424                                         __u64   cs_spare[3];
1425                                 } __attribute__((__packed__)) fs_cstotal;
1426                                 struct  ufs_timeval {
1427                                         __s32   tv_sec;
1428                                         __s32   tv_usec;
1429                                 } __attribute__((__packed__)) fs_time;
1430                                 __s64    fs_size;
1431                                 __s64    fs_dsize;
1432                                 __u64    fs_csaddr;
1433                                 __s64    fs_pendingblocks;
1434                                 __s32    fs_pendinginodes;
1435                         } __attribute__((__packed__)) fs_u2;
1436                 }  fs_u11;
1437                 union {
1438                         struct {
1439                                 __s32   fs_sparecon[53];
1440                                 __s32   fs_reclaim;
1441                                 __s32   fs_sparecon2[1];
1442                                 __s32   fs_state;
1443                                 __u32   fs_qbmask[2];
1444                                 __u32   fs_qfmask[2];
1445                         } __attribute__((__packed__)) fs_sun;
1446                         struct {
1447                                 __s32   fs_sparecon[53];
1448                                 __s32   fs_reclaim;
1449                                 __s32   fs_sparecon2[1];
1450                                 __u32   fs_npsect;
1451                                 __u32   fs_qbmask[2];
1452                                 __u32   fs_qfmask[2];
1453                         } __attribute__((__packed__)) fs_sunx86;
1454                         struct {
1455                                 __s32   fs_sparecon[50];
1456                                 __s32   fs_contigsumsize;
1457                                 __s32   fs_maxsymlinklen;
1458                                 __s32   fs_inodefmt;
1459                                 __u32   fs_maxfilesize[2];
1460                                 __u32   fs_qbmask[2];
1461                                 __u32   fs_qfmask[2];
1462                                 __s32   fs_state;
1463                         } __attribute__((__packed__)) fs_44;
1464                 } fs_u2;
1465                 __s32   fs_postblformat;
1466                 __s32   fs_nrpos;
1467                 __s32   fs_postbloff;
1468                 __s32   fs_rotbloff;
1469                 __u32   fs_magic;
1470                 __u8    fs_space[1];
1471         } __attribute__((__packed__)) *ufs;
1472
1473         __u32   magic;
1474         int     i;
1475         int     offsets[] = {0, 8, 64, 256, -1};
1476
1477         for (i = 0; offsets[i] >= 0; i++) {     
1478                 ufs = (struct ufs_super_block *)
1479                         get_buffer(id, off + (offsets[i] * 0x400), 0x800);
1480                 if (ufs == NULL)
1481                         return -1;
1482
1483                 dbg("offset 0x%x", offsets[i] * 0x400);
1484                 magic = be32_to_cpu(ufs->fs_magic);
1485                 if ((magic == UFS_MAGIC) ||
1486                     (magic == UFS2_MAGIC) ||
1487                     (magic == UFS_MAGIC_FEA) ||
1488                     (magic == UFS_MAGIC_LFN)) {
1489                         dbg("magic 0x%08x(be)", magic);
1490                         goto found;
1491                 }
1492                 magic = le32_to_cpu(ufs->fs_magic);
1493                 if ((magic == UFS_MAGIC) ||
1494                     (magic == UFS2_MAGIC) ||
1495                     (magic == UFS_MAGIC_FEA) ||
1496                     (magic == UFS_MAGIC_LFN)) {
1497                         dbg("magic 0x%08x(le)", magic);
1498                         goto found;
1499                 }
1500         }
1501         return -1;
1502
1503 found:
1504         id->usage_id = VOLUME_ID_FILESYSTEM;
1505         id->type_id = VOLUME_ID_UFS;
1506         id->type = "ufs";
1507
1508         return 0;
1509 }
1510
1511 static int probe_mac_partition_map(struct volume_id *id, __u64 off)
1512 {
1513         struct mac_driver_desc {
1514                 __u8    signature[2];
1515                 __u16   block_size;
1516                 __u32   block_count;
1517         } __attribute__((__packed__)) *driver;
1518
1519         struct mac_partition {
1520                 __u8    signature[2];
1521                 __u16   res1;
1522                 __u32   map_count;
1523                 __u32   start_block;
1524                 __u32   block_count;
1525                 __u8    name[32];
1526                 __u8    type[32];
1527         } __attribute__((__packed__)) *part;
1528
1529         const __u8 *buf;
1530
1531         buf = get_buffer(id, off, 0x200);
1532         if (buf == NULL)
1533                 return -1;
1534
1535         part = (struct mac_partition *) buf;
1536         if ((strncmp(part->signature, "PM", 2) == 0) &&
1537             (strncmp(part->type, "Apple_partition_map", 19) == 0)) {
1538                 /* linux creates an own subdevice for the map
1539                  * just return the type if the drive header is missing */
1540                 id->usage_id = VOLUME_ID_PARTITIONTABLE;
1541                 id->type_id = VOLUME_ID_MACPARTMAP;
1542                 id->type = "mac_partition_map";
1543                 return 0;
1544         }
1545
1546         driver = (struct mac_driver_desc *) buf;
1547         if (strncmp(driver->signature, "ER", 2) == 0) {
1548                 /* we are on a main device, like a CD
1549                  * just try to probe the first partition from the map */
1550                 unsigned int bsize = be16_to_cpu(driver->block_size);
1551                 int part_count;
1552                 int i;
1553
1554                 /* get first entry of partition table */
1555                 buf = get_buffer(id, off +  bsize, 0x200);
1556                 if (buf == NULL)
1557                         return -1;
1558
1559                 part = (struct mac_partition *) buf;
1560                 if (strncmp(part->signature, "PM", 2) != 0)
1561                         return -1;
1562
1563                 part_count = be32_to_cpu(part->map_count);
1564                 dbg("expecting %d partition entries", part_count);
1565
1566                 if (id->partitions != NULL)
1567                         free(id->partitions);
1568                 id->partitions =
1569                         malloc(part_count * sizeof(struct volume_id_partition));
1570                 if (id->partitions == NULL)
1571                         return -1;
1572                 memset(id->partitions, 0x00, sizeof(struct volume_id_partition));
1573
1574                 id->partition_count = part_count;
1575
1576                 for (i = 0; i < part_count; i++) {
1577                         __u64 poff;
1578                         __u64 plen;
1579
1580                         buf = get_buffer(id, off + ((i+1) * bsize), 0x200);
1581                         if (buf == NULL)
1582                                 return -1;
1583
1584                         part = (struct mac_partition *) buf;
1585                         if (strncmp(part->signature, "PM", 2) != 0)
1586                                 return -1;
1587
1588                         poff = be32_to_cpu(part->start_block) * bsize;
1589                         plen = be32_to_cpu(part->block_count) * bsize;
1590                         dbg("found '%s' partition entry at 0x%llx, len 0x%llx",
1591                             part->type, poff, plen);
1592
1593                         id->partitions[i].off = poff;
1594                         id->partitions[i].len = plen;
1595
1596                         if (strncmp(part->type, "Apple_Free", 10) == 0) {
1597                                 id->partitions[i].usage_id = VOLUME_ID_UNUSED;
1598                         } else if (strncmp(part->type, "Apple_partition_map", 19) == 0) {
1599                                 id->partitions[i].usage_id = VOLUME_ID_PARTITIONTABLE;
1600                                 id->partitions[i].type_id = VOLUME_ID_MACPARTMAP;
1601                         } else {
1602                                 id->partitions[i].usage_id = VOLUME_ID_UNPROBED;
1603                         }
1604                 }
1605                 id->usage_id = VOLUME_ID_PARTITIONTABLE;
1606                 id->type_id = VOLUME_ID_MACPARTMAP;
1607                 id->type = "mac_partition_map";
1608                 return 0;
1609         }
1610
1611         return -1;
1612 }
1613
1614 #define HFS_SUPERBLOCK_OFFSET           0x400
1615 #define HFS_NODE_LEAF                   0xff
1616 #define HFSPLUS_POR_CNID                1
1617 #define HFSPLUS_EXTENT_COUNT            8
1618 static int probe_hfs_hfsplus(struct volume_id *id, __u64 off)
1619 {
1620         struct hfs_finder_info{
1621                 __u32   boot_folder;
1622                 __u32   start_app;
1623                 __u32   open_folder;
1624                 __u32   os9_folder;
1625                 __u32   reserved;
1626                 __u32   osx_folder;
1627                 __u8    id[8];
1628         } __attribute__((__packed__));
1629
1630         struct hfs_mdb {
1631                 __u8    signature[2];
1632                 __u32   cr_date;
1633                 __u32   ls_Mod;
1634                 __u16   atrb;
1635                 __u16   nm_fls;
1636                 __u16   vbm_st;
1637                 __u16   alloc_ptr;
1638                 __u16   nm_al_blks;
1639                 __u32   al_blk_size;
1640                 __u32   clp_size;
1641                 __u16   al_bl_st;
1642                 __u32   nxt_cnid;
1643                 __u16   free_bks;
1644                 __u8    label_len;
1645                 __u8    label[27];
1646                 __u32   vol_bkup;
1647                 __u16   vol_seq_num;
1648                 __u32   wr_cnt;
1649                 __u32   xt_clump_size;
1650                 __u32   ct_clump_size;
1651                 __u16   num_root_dirs;
1652                 __u32   file_count;
1653                 __u32   dir_count;
1654                 struct hfs_finder_info finder_info;
1655                 __u8    embed_sig[2];
1656                 __u16   embed_startblock;
1657                 __u16   embed_blockcount;
1658         } __attribute__((__packed__)) *hfs;
1659
1660         struct hfsplus_bnode_descriptor {
1661                 __u32   next;
1662                 __u32   prev;
1663                 __u8    type;
1664                 __u8    height;
1665                 __u16   num_recs;
1666                 __u16   reserved;
1667         } __attribute__((__packed__));
1668
1669         struct hfsplus_bheader_record {
1670                 __u16   depth;
1671                 __u32   root;
1672                 __u32   leaf_count;
1673                 __u32   leaf_head;
1674                 __u32   leaf_tail;
1675                 __u16   node_size;
1676         } __attribute__((__packed__));
1677
1678         struct hfsplus_catalog_key {
1679                 __u16   key_len;
1680                 __u32   parent_id;
1681                 __u16   unicode_len;
1682                 __u8    unicode[255 * 2];
1683         } __attribute__((__packed__));
1684
1685         struct hfsplus_extent {
1686                 __u32 start_block;
1687                 __u32 block_count;
1688         } __attribute__((__packed__));
1689
1690         struct hfsplus_fork {
1691                 __u64 total_size;
1692                 __u32 clump_size;
1693                 __u32 total_blocks;
1694                 struct hfsplus_extent extents[HFSPLUS_EXTENT_COUNT];
1695         } __attribute__((__packed__));
1696
1697         struct hfsplus_vol_header {
1698                 __u8    signature[2];
1699                 __u16   version;
1700                 __u32   attributes;
1701                 __u32   last_mount_vers;
1702                 __u32   reserved;
1703                 __u32   create_date;
1704                 __u32   modify_date;
1705                 __u32   backup_date;
1706                 __u32   checked_date;
1707                 __u32   file_count;
1708                 __u32   folder_count;
1709                 __u32   blocksize;
1710                 __u32   total_blocks;
1711                 __u32   free_blocks;
1712                 __u32   next_alloc;
1713                 __u32   rsrc_clump_sz;
1714                 __u32   data_clump_sz;
1715                 __u32   next_cnid;
1716                 __u32   write_count;
1717                 __u64   encodings_bmp;
1718                 struct hfs_finder_info finder_info;
1719                 struct hfsplus_fork alloc_file;
1720                 struct hfsplus_fork ext_file;
1721                 struct hfsplus_fork cat_file;
1722                 struct hfsplus_fork attr_file;
1723                 struct hfsplus_fork start_file;
1724         } __attribute__((__packed__)) *hfsplus;
1725
1726         unsigned int blocksize;
1727         unsigned int cat_block;
1728         unsigned int ext_block_start;
1729         unsigned int ext_block_count;
1730         int ext;
1731         unsigned int leaf_node_head;
1732         unsigned int leaf_node_count;
1733         unsigned int leaf_node_size;
1734         unsigned int leaf_block;
1735         __u64 leaf_off;
1736         unsigned int alloc_block_size;
1737         unsigned int alloc_first_block;
1738         unsigned int embed_first_block;
1739         unsigned int record_count;
1740         struct hfsplus_bnode_descriptor *descr;
1741         struct hfsplus_bheader_record *bnode;
1742         struct hfsplus_catalog_key *key;
1743         unsigned int    label_len;
1744         struct hfsplus_extent extents[HFSPLUS_EXTENT_COUNT];
1745         const __u8 *buf;
1746
1747         buf = get_buffer(id, off + HFS_SUPERBLOCK_OFFSET, 0x200);
1748         if (buf == NULL)
1749                 return -1;
1750
1751         hfs = (struct hfs_mdb *) buf;
1752         if (strncmp(hfs->signature, "BD", 2) != 0)
1753                 goto checkplus;
1754
1755         /* it may be just a hfs wrapper for hfs+ */
1756         if (strncmp(hfs->embed_sig, "H+", 2) == 0) {
1757                 alloc_block_size = be32_to_cpu(hfs->al_blk_size);
1758                 dbg("alloc_block_size 0x%x", alloc_block_size);
1759
1760                 alloc_first_block = be16_to_cpu(hfs->al_bl_st);
1761                 dbg("alloc_first_block 0x%x", alloc_first_block);
1762
1763                 embed_first_block = be16_to_cpu(hfs->embed_startblock);
1764                 dbg("embed_first_block 0x%x", embed_first_block);
1765
1766                 off += (alloc_first_block * 512) +
1767                        (embed_first_block * alloc_block_size);
1768                 dbg("hfs wrapped hfs+ found at offset 0x%llx", off);
1769
1770                 buf = get_buffer(id, off + HFS_SUPERBLOCK_OFFSET, 0x200);
1771                 if (buf == NULL)
1772                         return -1;
1773                 goto checkplus;
1774         }
1775
1776         if (hfs->label_len > 0 && hfs->label_len < 28) {
1777                 set_label_raw(id, hfs->label, hfs->label_len);
1778                 set_label_string(id, hfs->label, hfs->label_len) ;
1779         }
1780
1781         set_uuid(id, hfs->finder_info.id, UUID_HFS);
1782
1783         id->usage_id = VOLUME_ID_FILESYSTEM;
1784         id->type_id = VOLUME_ID_HFS;
1785         id->type = "hfs";
1786
1787         return 0;
1788
1789 checkplus:
1790         hfsplus = (struct hfsplus_vol_header *) buf;
1791         if (strncmp(hfsplus->signature, "H+", 2) == 0)
1792                 goto hfsplus;
1793         if (strncmp(hfsplus->signature, "HX", 2) == 0)
1794                 goto hfsplus;
1795         return -1;
1796
1797 hfsplus:
1798         set_uuid(id, hfsplus->finder_info.id, UUID_HFS);
1799
1800         blocksize = be32_to_cpu(hfsplus->blocksize);
1801         dbg("blocksize %u", blocksize);
1802
1803         memcpy(extents, hfsplus->cat_file.extents, sizeof(extents));
1804         cat_block = be32_to_cpu(extents[0].start_block);
1805         dbg("catalog start block 0x%x", cat_block);
1806
1807         buf = get_buffer(id, off + (cat_block * blocksize), 0x2000);
1808         if (buf == NULL)
1809                 goto found;
1810
1811         bnode = (struct hfsplus_bheader_record *)
1812                 &buf[sizeof(struct hfsplus_bnode_descriptor)];
1813
1814         leaf_node_head = be32_to_cpu(bnode->leaf_head);
1815         dbg("catalog leaf node 0x%x", leaf_node_head);
1816
1817         leaf_node_size = be16_to_cpu(bnode->node_size);
1818         dbg("leaf node size 0x%x", leaf_node_size);
1819
1820         leaf_node_count = be32_to_cpu(bnode->leaf_count);
1821         dbg("leaf node count 0x%x", leaf_node_count);
1822         if (leaf_node_count == 0)
1823                 goto found;
1824
1825         leaf_block = (leaf_node_head * leaf_node_size) / blocksize;
1826
1827         /* get physical location */
1828         for (ext = 0; ext < HFSPLUS_EXTENT_COUNT; ext++) {
1829                 ext_block_start = be32_to_cpu(extents[ext].start_block);
1830                 ext_block_count = be32_to_cpu(extents[ext].block_count);
1831                 dbg("extent start block 0x%x, count 0x%x", ext_block_start, ext_block_count);
1832
1833                 if (ext_block_count == 0)
1834                         goto found;
1835
1836                 /* this is our extent */
1837                 if (leaf_block < ext_block_count)
1838                         break;
1839
1840                 leaf_block -= ext_block_count;
1841         }
1842         if (ext == HFSPLUS_EXTENT_COUNT)
1843                 goto found;
1844         dbg("found block in extent %i", ext);
1845
1846         leaf_off = (ext_block_start + leaf_block) * blocksize;
1847
1848         buf = get_buffer(id, off + leaf_off, leaf_node_size);
1849         if (buf == NULL)
1850                 goto found;
1851
1852         descr = (struct hfsplus_bnode_descriptor *) buf;
1853         dbg("descriptor type 0x%x", descr->type);
1854
1855         record_count = be16_to_cpu(descr->num_recs);
1856         dbg("number of records %u", record_count);
1857         if (record_count == 0)
1858                 goto found;
1859
1860         if (descr->type != HFS_NODE_LEAF)
1861                 goto found;
1862
1863         key = (struct hfsplus_catalog_key *)
1864                 &buf[sizeof(struct hfsplus_bnode_descriptor)];
1865
1866         dbg("parent id 0x%x", be32_to_cpu(key->parent_id));
1867         if (be32_to_cpu(key->parent_id) != HFSPLUS_POR_CNID)
1868                 goto found;
1869
1870         label_len = be16_to_cpu(key->unicode_len) * 2;
1871         dbg("label unicode16 len %i", label_len);
1872         set_label_raw(id, key->unicode, label_len);
1873         set_label_unicode16(id, key->unicode, BE, label_len);
1874
1875 found:
1876         id->usage_id = VOLUME_ID_FILESYSTEM;
1877         id->type_id = VOLUME_ID_HFSPLUS;
1878         id->type = "hfsplus";
1879
1880         return 0;
1881 }
1882
1883 #define MFT_RECORD_VOLUME                       3
1884 #define MFT_RECORD_ATTR_VOLUME_NAME             0x60
1885 #define MFT_RECORD_ATTR_VOLUME_INFO             0x70
1886 #define MFT_RECORD_ATTR_OBJECT_ID               0x40
1887 #define MFT_RECORD_ATTR_END                     0xffffffffu
1888 static int probe_ntfs(struct volume_id *id, __u64 off)
1889 {
1890         struct ntfs_super_block {
1891                 __u8    jump[3];
1892                 __u8    oem_id[8];
1893                 __u16   bytes_per_sector;
1894                 __u8    sectors_per_cluster;
1895                 __u16   reserved_sectors;
1896                 __u8    fats;
1897                 __u16   root_entries;
1898                 __u16   sectors;
1899                 __u8    media_type;
1900                 __u16   sectors_per_fat;
1901                 __u16   sectors_per_track;
1902                 __u16   heads;
1903                 __u32   hidden_sectors;
1904                 __u32   large_sectors;
1905                 __u16   unused[2];
1906                 __u64   number_of_sectors;
1907                 __u64   mft_cluster_location;
1908                 __u64   mft_mirror_cluster_location;
1909                 __s8    cluster_per_mft_record;
1910                 __u8    reserved1[3];
1911                 __s8    cluster_per_index_record;
1912                 __u8    reserved2[3];
1913                 __u8    volume_serial[8];
1914                 __u16   checksum;
1915         } __attribute__((__packed__)) *ns;
1916
1917         struct master_file_table_record {
1918                 __u8    magic[4];
1919                 __u16   usa_ofs;
1920                 __u16   usa_count;
1921                 __u64   lsn;
1922                 __u16   sequence_number;
1923                 __u16   link_count;
1924                 __u16   attrs_offset;
1925                 __u16   flags;
1926                 __u32   bytes_in_use;
1927                 __u32   bytes_allocated;
1928         } __attribute__((__packed__)) *mftr;
1929
1930         struct file_attribute {
1931                 __u32   type;
1932                 __u32   len;
1933                 __u8    non_resident;
1934                 __u8    name_len;
1935                 __u16   name_offset;
1936                 __u16   flags;
1937                 __u16   instance;
1938                 __u32   value_len;
1939                 __u16   value_offset;
1940         } __attribute__((__packed__)) *attr;
1941
1942         struct volume_info {
1943                 __u64 reserved;
1944                 __u8 major_ver;
1945                 __u8 minor_ver;
1946         } __attribute__((__packed__)) *info;
1947
1948         unsigned int sector_size;
1949         unsigned int cluster_size;
1950         __u64 mft_cluster;
1951         __u64 mft_off;
1952         unsigned int mft_record_size;
1953         unsigned int attr_type;
1954         unsigned int attr_off;
1955         unsigned int attr_len;
1956         unsigned int val_off;
1957         unsigned int val_len;
1958         const __u8 *buf;
1959         const __u8 *val;
1960
1961         ns = (struct ntfs_super_block *) get_buffer(id, off, 0x200);
1962         if (ns == NULL)
1963                 return -1;
1964
1965         if (strncmp(ns->oem_id, "NTFS", 4) != 0)
1966                 return -1;
1967
1968         set_uuid(id, ns->volume_serial, UUID_NTFS);
1969
1970         sector_size = le16_to_cpu(ns->bytes_per_sector);
1971         cluster_size = ns->sectors_per_cluster * sector_size;
1972         mft_cluster = le64_to_cpu(ns->mft_cluster_location);
1973         mft_off = mft_cluster * cluster_size;
1974
1975         if (ns->cluster_per_mft_record < 0)
1976                 /* size = -log2(mft_record_size); normally 1024 Bytes */
1977                 mft_record_size = 1 << -ns->cluster_per_mft_record;
1978         else
1979                 mft_record_size = ns->cluster_per_mft_record * cluster_size;
1980
1981         dbg("sectorsize  0x%x", sector_size);
1982         dbg("clustersize 0x%x", cluster_size);
1983         dbg("mftcluster  %lli", mft_cluster);
1984         dbg("mftoffset  0x%llx", mft_off);
1985         dbg("cluster per mft_record  %i", ns->cluster_per_mft_record);
1986         dbg("mft record size  %i", mft_record_size);
1987
1988         buf = get_buffer(id, off + mft_off + (MFT_RECORD_VOLUME * mft_record_size),
1989                          mft_record_size);
1990         if (buf == NULL)
1991                 goto found;
1992
1993         mftr = (struct master_file_table_record*) buf;
1994
1995         dbg("mftr->magic '%c%c%c%c'", mftr->magic[0], mftr->magic[1], mftr->magic[2], mftr->magic[3]);
1996         if (strncmp(mftr->magic, "FILE", 4) != 0)
1997                 goto found;
1998
1999         attr_off = le16_to_cpu(mftr->attrs_offset);
2000         dbg("file $Volume's attributes are at offset %i", attr_off);
2001
2002         while (1) {
2003                 attr = (struct file_attribute*) &buf[attr_off];
2004                 attr_type = le32_to_cpu(attr->type);
2005                 attr_len = le16_to_cpu(attr->len);
2006                 val_off = le16_to_cpu(attr->value_offset);
2007                 val_len = le32_to_cpu(attr->value_len);
2008                 attr_off += attr_len;
2009
2010                 if (attr_len == 0)
2011                         break;
2012
2013                 if (attr_off >= mft_record_size)
2014                         break;
2015
2016                 if (attr_type == MFT_RECORD_ATTR_END)
2017                         break;
2018
2019                 dbg("found attribute type 0x%x, len %i, at offset %i",
2020                     attr_type, attr_len, attr_off);
2021
2022                 if (attr_type == MFT_RECORD_ATTR_VOLUME_INFO) {
2023                         dbg("found info, len %i", val_len);
2024                         info = (struct volume_info*) (((__u8 *) attr) + val_off);
2025                         snprintf(id->type_version, VOLUME_ID_FORMAT_SIZE-1,
2026                                  "%u.%u", info->major_ver, info->minor_ver);
2027                 }
2028
2029                 if (attr_type == MFT_RECORD_ATTR_VOLUME_NAME) {
2030                         dbg("found label, len %i", val_len);
2031                         if (val_len > VOLUME_ID_LABEL_SIZE)
2032                                 val_len = VOLUME_ID_LABEL_SIZE;
2033
2034                         val = ((__u8 *) attr) + val_off;
2035                         set_label_raw(id, val, val_len);
2036                         set_label_unicode16(id, val, LE, val_len);
2037                 }
2038         }
2039
2040 found:
2041         id->usage_id = VOLUME_ID_FILESYSTEM;
2042         id->type_id = VOLUME_ID_NTFS;
2043         id->type = "ntfs";
2044
2045         return 0;
2046 }
2047
2048 #define LARGEST_PAGESIZE                        0x4000
2049 static int probe_swap(struct volume_id *id, __u64 off)
2050 {
2051         struct swap_header_v1_2 {
2052                 __u8    bootbits[1024];
2053                 __u32   version;
2054                 __u32   last_page;
2055                 __u32   nr_badpages;
2056                 __u8    uuid[16];
2057                 __u8    volume_name[16];
2058         } __attribute__((__packed__)) *sw;
2059
2060         const __u8 *buf;
2061         unsigned int page;
2062
2063         /* the swap signature is at the end of the PAGE_SIZE */
2064         for (page = 0x1000; page <= LARGEST_PAGESIZE; page <<= 1) {
2065                         buf = get_buffer(id, off + page-10, 10);
2066                         if (buf == NULL)
2067                                 return -1;
2068
2069                         if (strncmp(buf, "SWAP-SPACE", 10) == 0) {
2070                                 strcpy(id->type_version, "1");
2071                                 goto found;
2072                         }
2073
2074                         if (strncmp(buf, "SWAPSPACE2", 10) == 0) {
2075                                 sw = (struct swap_header_v1_2 *) get_buffer(id, off, sizeof(struct swap_header_v1_2));
2076                                 if (sw == NULL)
2077                                         return -1;
2078                                 strcpy(id->type_version, "2");
2079                                 set_label_raw(id, sw->volume_name, 16);
2080                                 set_label_string(id, sw->volume_name, 16);
2081                                 set_uuid(id, sw->uuid, UUID_DCE);
2082                                 goto found;
2083                         }
2084         }
2085         return -1;
2086
2087 found:
2088         id->usage_id = VOLUME_ID_OTHER;
2089         id->type_id = VOLUME_ID_SWAP;
2090         id->type = "swap";
2091
2092         return 0;
2093 }
2094
2095 /* probe volume for filesystem type and try to read label+uuid */
2096 int volume_id_probe(struct volume_id *id,
2097                     enum volume_id_type type,
2098                     unsigned long long off,
2099                     unsigned long long size)
2100 {
2101         int rc;
2102
2103         dbg("called with size=0x%llx", size);
2104
2105         if (id == NULL)
2106                 return -EINVAL;
2107
2108         switch (type) {
2109         case VOLUME_ID_MSDOSPARTTABLE:
2110                 rc = probe_msdos_part_table(id, off);
2111                 break;
2112         case VOLUME_ID_EXT3:
2113         case VOLUME_ID_EXT2:
2114                 rc = probe_ext(id, off);
2115                 break;
2116         case VOLUME_ID_REISERFS:
2117                 rc = probe_reiserfs(id, off);
2118                 break;
2119         case VOLUME_ID_XFS:
2120                 rc = probe_xfs(id, off);
2121                 break;
2122         case VOLUME_ID_JFS:
2123                 rc = probe_jfs(id, off);
2124                 break;
2125         case VOLUME_ID_VFAT:
2126                 rc = probe_vfat(id, off);
2127                 break;
2128         case VOLUME_ID_UDF:
2129                 rc = probe_udf(id, off);
2130                 break;
2131         case VOLUME_ID_ISO9660:
2132                 rc = probe_iso9660(id, off);
2133                 break;
2134         case VOLUME_ID_MACPARTMAP:
2135                 rc = probe_mac_partition_map(id, off);
2136                 break;
2137         case VOLUME_ID_HFS:
2138         case VOLUME_ID_HFSPLUS:
2139                 rc = probe_hfs_hfsplus(id, off);
2140                 break;
2141         case VOLUME_ID_UFS:
2142                 rc = probe_ufs(id, off);
2143                 break;
2144         case VOLUME_ID_NTFS:
2145                 rc = probe_ntfs(id, off);
2146                 break;
2147         case VOLUME_ID_SWAP:
2148                 rc = probe_swap(id, off);
2149                 break;
2150         case VOLUME_ID_LINUX_RAID:
2151                 rc = probe_linux_raid(id, off, size);
2152                 break;
2153         case VOLUME_ID_LVM1:
2154                 rc = probe_lvm1(id, off);
2155                 break;
2156         case VOLUME_ID_LVM2:
2157                 rc = probe_lvm2(id, off);
2158                 break;
2159         case VOLUME_ID_HPTRAID:
2160                 rc = probe_highpoint_ataraid(id, off);
2161                 break;
2162         case VOLUME_ID_ALL:
2163         default:
2164                 /* probe for raid first, cause fs probes may be successful on raid members */
2165                 rc = probe_linux_raid(id, off, size);
2166                 if (rc == 0)
2167                         break;
2168                 rc = probe_lvm1(id, off);
2169                 if (rc == 0)
2170                         break;
2171                 rc = probe_lvm2(id, off);
2172                 if (rc == 0)
2173                         break;
2174                 rc = probe_highpoint_ataraid(id, off);
2175                 if (rc == 0)
2176                         break;
2177
2178                 /* signature in the first block, only small buffer needed */
2179                 rc = probe_vfat(id, off);
2180                 if (rc == 0)
2181                         break;
2182                 rc = probe_mac_partition_map(id, off);
2183                 if (rc == 0)
2184                         break;
2185                 rc = probe_xfs(id, off);
2186                 if (rc == 0)
2187                         break;
2188
2189                 /* fill buffer with maximum */
2190                 get_buffer(id, 0, SB_BUFFER_SIZE);
2191
2192                 rc = probe_swap(id, off);
2193                 if (rc == 0)
2194                         break;
2195                 rc = probe_ext(id, off);
2196                 if (rc == 0)
2197                         break;
2198                 rc = probe_reiserfs(id, off);
2199                 if (rc == 0)
2200                         break;
2201                 rc = probe_jfs(id, off);
2202                 if (rc == 0)
2203                         break;
2204                 rc = probe_udf(id, off);
2205                 if (rc == 0)
2206                         break;
2207                 rc = probe_iso9660(id, off);
2208                 if (rc == 0)
2209                         break;
2210                 rc = probe_hfs_hfsplus(id, off);
2211                 if (rc == 0)
2212                         break;
2213                 rc = probe_ufs(id, off);
2214                 if (rc == 0)
2215                         break;
2216                 rc = probe_ntfs(id, off);
2217                 if (rc == 0)
2218                         break;
2219
2220                 rc = -1;
2221         }
2222
2223         /* If the filestystem in recognized, we free the allocated buffers,
2224            otherwise they will stay in place for the possible next probe call */
2225         if (rc == 0)
2226                 free_buffer(id);
2227
2228         return rc;
2229 }
2230
2231 /* open volume by already open file descriptor */
2232 struct volume_id *volume_id_open_fd(int fd)
2233 {
2234         struct volume_id *id;
2235
2236         id = malloc(sizeof(struct volume_id));
2237         if (id == NULL)
2238                 return NULL;
2239         memset(id, 0x00, sizeof(struct volume_id));
2240
2241         id->fd = fd;
2242
2243         return id;
2244 }
2245
2246 /* open volume by device node */
2247 struct volume_id *volume_id_open_node(const char *path)
2248 {
2249         struct volume_id *id;
2250         int fd;
2251
2252         fd = open(path, O_RDONLY);
2253         if (fd < 0) {
2254                 dbg("unable to open '%s'", path);
2255                 return NULL;
2256         }
2257
2258         id = volume_id_open_fd(fd);
2259         if (id == NULL)
2260                 return NULL;
2261
2262         /* close fd on device close */
2263         id->fd_close = 1;
2264
2265         return id;
2266 }
2267
2268 /* open volume by major/minor */
2269 struct volume_id *volume_id_open_dev_t(dev_t devt)
2270 {
2271         struct volume_id *id;
2272         __u8 tmp_node[VOLUME_ID_PATH_MAX];
2273
2274         snprintf(tmp_node, VOLUME_ID_PATH_MAX,
2275                  "/tmp/volume-%u-%u-%u", getpid(), major(devt), minor(devt));
2276         tmp_node[VOLUME_ID_PATH_MAX] = '\0';
2277
2278         /* create tempory node to open the block device */
2279         unlink(tmp_node);
2280         if (mknod(tmp_node, (S_IFBLK | 0600), devt) != 0)
2281                 return NULL;
2282
2283         id = volume_id_open_node(tmp_node);
2284
2285         unlink(tmp_node);
2286
2287         return id;
2288 }
2289
2290 /* free allocated volume info */
2291 void volume_id_close(struct volume_id *id)
2292 {
2293         if (id == NULL)
2294                 return;
2295
2296         if (id->fd_close != 0)
2297                 close(id->fd);
2298
2299         free_buffer(id);
2300
2301         if (id->partitions != NULL)
2302                 free(id->partitions);
2303
2304         free(id);
2305 }