chiark / gitweb /
[PATCH] udev_volume_id: version 27
[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_ENTRY_FREE                  0xe5
778 static int probe_vfat(struct volume_id *id, __u64 off)
779 {
780         struct vfat_super_block {
781                 __u8    boot_jump[3];
782                 __u8    sysid[8];
783                 __u16   sector_size;
784                 __u8    sectors_per_cluster;
785                 __u16   reserved;
786                 __u8    fats;
787                 __u16   dir_entries;
788                 __u16   sectors;
789                 __u8    media;
790                 __u16   fat_length;
791                 __u16   secs_track;
792                 __u16   heads;
793                 __u32   hidden;
794                 __u32   total_sect;
795                 union {
796                         struct fat_super_block {
797                                 __u8    unknown[3];
798                                 __u8    serno[4];
799                                 __u8    label[11];
800                                 __u8    magic[8];
801                                 __u8    dummy2[192];
802                                 __u8    pmagic[2];
803                         } __attribute__((__packed__)) fat;
804                         struct fat32_super_block {
805                                 __u32   fat32_length;
806                                 __u16   flags;
807                                 __u8    version[2];
808                                 __u32   root_cluster;
809                                 __u16   insfo_sector;
810                                 __u16   backup_boot;
811                                 __u16   reserved2[6];
812                                 __u8    unknown[3];
813                                 __u8    serno[4];
814                                 __u8    label[11];
815                                 __u8    magic[8];
816                                 __u8    dummy2[164];
817                                 __u8    pmagic[2];
818                         } __attribute__((__packed__)) fat32;
819                 } __attribute__((__packed__)) type;
820         } __attribute__((__packed__)) *vs;
821
822         struct vfat_dir_entry {
823                 __u8    name[11];
824                 __u8    attr;
825                 __u16   time_creat;
826                 __u16   date_creat;
827                 __u16   time_acc;
828                 __u16   date_acc;
829                 __u16   cluster_high;
830                 __u16   time_write;
831                 __u16   date_write;
832                 __u16   cluster_low;
833                 __u32   size;
834         } __attribute__((__packed__)) *dir;
835
836         __u16 sector_size;
837         __u16 dir_entries;
838         __u32 sect_count;
839         __u16 reserved;
840         __u32 fat_size;
841         __u32 root_cluster;
842         __u32 dir_size;
843         __u32 cluster_count;
844         __u32 fat_length;
845         __u64 root_start;
846         __u32 start_data_sect;
847         __u16 root_dir_entries;
848         __u8 *buf;
849         __u32 buf_size;
850         __u8 *label = NULL;
851         __u32 next;
852         int maxloop;
853         int i;
854
855         vs = (struct vfat_super_block *) get_buffer(id, off, 0x200);
856         if (vs == NULL)
857                 return -1;
858
859         /* believe only that's fat, don't trust the version
860          * the cluster_count will tell us
861          */
862         if (strncmp(vs->type.fat32.magic, "MSWIN", 5) == 0)
863                 goto valid;
864
865         if (strncmp(vs->type.fat32.magic, "FAT32   ", 8) == 0)
866                 goto valid;
867
868         if (strncmp(vs->type.fat.magic, "FAT16   ", 8) == 0)
869                 goto valid;
870
871         if (strncmp(vs->type.fat.magic, "MSDOS", 5) == 0)
872                 goto valid;
873
874         if (strncmp(vs->type.fat.magic, "FAT12   ", 8) == 0)
875                 goto valid;
876
877         /*
878          * There are old floppies out there without a magic, so we check
879          * for well known values and guess if it's a fat volume
880          */
881
882         /* boot jump address check */
883         if ((vs->boot_jump[0] != 0xeb || vs->boot_jump[2] != 0x90) &&
884              vs->boot_jump[0] != 0xe9)
885                 return -1;
886
887         /* heads check */
888         if (vs->heads == 0)
889                 return -1;
890
891         /* cluster size check*/ 
892         if (vs->sectors_per_cluster == 0 ||
893             (vs->sectors_per_cluster & (vs->sectors_per_cluster-1)))
894                 return -1;
895
896         /* media check */
897         if (vs->media < 0xf8 && vs->media != 0xf0)
898                 return -1;
899
900         /* fat count*/
901         if (vs->fats != 2)
902                 return -1;
903
904 valid:
905         /* sector size check */
906         sector_size = le16_to_cpu(vs->sector_size);
907         if (sector_size != 0x200 && sector_size != 0x400 &&
908             sector_size != 0x800 && sector_size != 0x1000)
909                 return -1;
910
911         dbg("sector_size 0x%x", sector_size);
912         dbg("sectors_per_cluster 0x%x", vs->sectors_per_cluster);
913
914         dir_entries = le16_to_cpu(vs->dir_entries);
915         reserved = le16_to_cpu(vs->reserved);
916         dbg("reserved 0x%x", reserved);
917
918         sect_count = le16_to_cpu(vs->sectors);
919         if (sect_count == 0)
920                 sect_count = le32_to_cpu(vs->total_sect);
921         dbg("sect_count 0x%x", sect_count);
922
923         fat_length = le16_to_cpu(vs->fat_length);
924         if (fat_length == 0)
925                 fat_length = le32_to_cpu(vs->type.fat32.fat32_length);
926         dbg("fat_length 0x%x", fat_length);
927
928         fat_size = fat_length * vs->fats;
929         dir_size = ((dir_entries * sizeof(struct vfat_dir_entry)) +
930                         (sector_size-1)) / sector_size;
931         dbg("dir_size 0x%x", dir_size);
932
933         cluster_count = sect_count - (reserved + fat_size + dir_size);
934         cluster_count /= vs->sectors_per_cluster;
935         dbg("cluster_count 0x%x", cluster_count);
936
937         if (cluster_count < FAT12_MAX) {
938                 strcpy(id->type_version, "FAT12");
939         } else if (cluster_count < FAT16_MAX) {
940                 strcpy(id->type_version, "FAT16");
941         } else {
942                 strcpy(id->type_version, "FAT32");
943                 goto fat32;
944         }
945
946         /* the label may be an attribute in the root directory */
947         root_start = (reserved + fat_size) * sector_size;
948         dbg("root dir start 0x%llx", root_start);
949         root_dir_entries = le16_to_cpu(vs->dir_entries);
950         dbg("expected entries 0x%x", root_dir_entries);
951
952         buf_size = root_dir_entries * sizeof(struct vfat_dir_entry);
953         buf = get_buffer(id, off + root_start, buf_size);
954         if (buf == NULL)
955                 goto found;
956
957         dir = (struct vfat_dir_entry*) buf;
958
959         for (i = 0; i <= root_dir_entries; i++) {
960                 /* end marker */
961                 if (dir[i].name[0] == 0x00) {
962                         dbg("end of dir");
963                         break;
964                 }
965
966                 /* empty entry */
967                 if (dir[i].name[0] == FAT_ENTRY_FREE)
968                         continue;
969
970                 if ((dir[i].attr & (FAT_ATTR_VOLUME_ID | FAT_ATTR_DIR)) == FAT_ATTR_VOLUME_ID) {
971                         dbg("found ATTR_VOLUME_ID id in root dir");
972                         label = dir[i].name;
973                         break;
974                 }
975
976                 dbg("skip dir entry");
977         }
978
979         if (label != NULL && strncmp(label, "NO NAME    ", 11) != 0) {
980                 set_label_raw(id, label, 11);
981                 set_label_string(id, label, 11);
982         } else if (strncmp(vs->type.fat.label, "NO NAME    ", 11) != 0) {
983                 set_label_raw(id, vs->type.fat.label, 11);
984                 set_label_string(id, vs->type.fat.label, 11);
985         }
986         set_uuid(id, vs->type.fat.serno, UUID_DOS);
987         goto found;
988
989 fat32:
990         /* FAT32 root dir is a cluster chain like any other directory */
991         buf_size = vs->sectors_per_cluster * sector_size;
992         root_cluster = le32_to_cpu(vs->type.fat32.root_cluster);
993         dbg("root dir cluster %u", root_cluster);
994         start_data_sect = reserved + fat_size;
995
996         next = root_cluster;
997         maxloop = 100;
998         while (--maxloop) {
999                 __u32 next_sect_off;
1000                 __u64 next_off;
1001                 __u64 fat_entry_off;
1002                 int count;
1003
1004                 dbg("next cluster %u", next);
1005                 next_sect_off = (next - 2) * vs->sectors_per_cluster;
1006                 next_off = (start_data_sect + next_sect_off) * sector_size;
1007                 dbg("cluster offset 0x%llx", next_off);
1008
1009                 /* get cluster */
1010                 buf = get_buffer(id, off + next_off, buf_size);
1011                 if (buf == NULL)
1012                         goto found;
1013
1014                 dir = (struct vfat_dir_entry*) buf;
1015                 count = buf_size / sizeof(struct vfat_dir_entry);
1016                 dbg("expected entries 0x%x", count);
1017
1018                 for (i = 0; i <= count; i++) {
1019                         /* end marker */
1020                         if (dir[i].name[0] == 0x00) {
1021                                 dbg("end of dir");
1022                                 goto fat32_label;
1023                         }
1024
1025                         /* empty entry */
1026                         if (dir[i].name[0] == FAT_ENTRY_FREE)
1027                                 continue;
1028
1029                         if ((dir[i].attr & (FAT_ATTR_VOLUME_ID | FAT_ATTR_DIR)) == FAT_ATTR_VOLUME_ID) {
1030                                 dbg("found ATTR_VOLUME_ID id in root dir");
1031                                 label = dir[i].name;
1032                                 goto fat32_label;
1033                         }
1034
1035                         dbg("skip dir entry");
1036                 }
1037
1038                 /* get FAT entry */
1039                 fat_entry_off = (reserved * sector_size) + (next * sizeof(__u32));
1040                 buf = get_buffer(id, off + fat_entry_off, buf_size);
1041                 if (buf == NULL)
1042                         goto found;
1043
1044                 /* set next cluster */
1045                 next = le32_to_cpu(*((__u32 *) buf) & 0x0fffffff);
1046                 if (next == 0)
1047                         break;
1048         }
1049         if (maxloop == 0)
1050                 dbg("reached maximum follow count of root cluster chain, give up");
1051
1052 fat32_label:
1053         if (label != NULL && strncmp(label, "NO NAME    ", 11) != 0) {
1054                 set_label_raw(id, label, 11);
1055                 set_label_string(id, label, 11);
1056         } else if (strncmp(vs->type.fat32.label, "NO NAME    ", 11) != 0) {
1057                 set_label_raw(id, vs->type.fat32.label, 11);
1058                 set_label_string(id, vs->type.fat32.label, 11);
1059         }
1060         set_uuid(id, vs->type.fat32.serno, UUID_DOS);
1061
1062 found:
1063         id->usage_id = VOLUME_ID_FILESYSTEM;
1064         id->type_id = VOLUME_ID_VFAT;
1065         id->type = "vfat";
1066
1067         return 0;
1068 }
1069
1070 #define UDF_VSD_OFFSET                  0x8000
1071 static int probe_udf(struct volume_id *id, __u64 off)
1072 {
1073         struct volume_descriptor {
1074                 struct descriptor_tag {
1075                         __u16   id;
1076                         __u16   version;
1077                         __u8    checksum;
1078                         __u8    reserved;
1079                         __u16   serial;
1080                         __u16   crc;
1081                         __u16   crc_len;
1082                         __u32   location;
1083                 } __attribute__((__packed__)) tag;
1084                 union {
1085                         struct anchor_descriptor {
1086                                 __u32   length;
1087                                 __u32   location;
1088                         } __attribute__((__packed__)) anchor;
1089                         struct primary_descriptor {
1090                                 __u32   seq_num;
1091                                 __u32   desc_num;
1092                                 struct dstring {
1093                                         __u8    clen;
1094                                         __u8    c[31];
1095                                 } __attribute__((__packed__)) ident;
1096                         } __attribute__((__packed__)) primary;
1097                 } __attribute__((__packed__)) type;
1098         } __attribute__((__packed__)) *vd;
1099
1100         struct volume_structure_descriptor {
1101                 __u8    type;
1102                 __u8    id[5];
1103                 __u8    version;
1104         } *vsd;
1105
1106         unsigned int bs;
1107         unsigned int b;
1108         unsigned int type;
1109         unsigned int count;
1110         unsigned int loc;
1111         unsigned int clen;
1112
1113         vsd = (struct volume_structure_descriptor *)
1114               get_buffer(id, off + UDF_VSD_OFFSET, 0x200);
1115         if (vsd == NULL)
1116                 return -1;
1117
1118         if (strncmp(vsd->id, "NSR02", 5) == 0)
1119                 goto blocksize;
1120         if (strncmp(vsd->id, "NSR03", 5) == 0)
1121                 goto blocksize;
1122         if (strncmp(vsd->id, "BEA01", 5) == 0)
1123                 goto blocksize;
1124         if (strncmp(vsd->id, "BOOT2", 5) == 0)
1125                 goto blocksize;
1126         if (strncmp(vsd->id, "CD001", 5) == 0)
1127                 goto blocksize;
1128         if (strncmp(vsd->id, "CDW02", 5) == 0)
1129                 goto blocksize;
1130         if (strncmp(vsd->id, "TEA03", 5) == 0)
1131                 goto blocksize;
1132         return -1;
1133
1134 blocksize:
1135         /* search the next VSD to get the logical block size of the volume */
1136         for (bs = 0x800; bs < 0x8000; bs += 0x800) {
1137                 vsd = (struct volume_structure_descriptor *)
1138                       get_buffer(id, off + UDF_VSD_OFFSET + bs, 0x800);
1139                 if (vsd == NULL)
1140                         return -1;
1141                 dbg("test for blocksize: 0x%x", bs);
1142                 if (vsd->id[0] != '\0')
1143                         goto nsr;
1144         }
1145         return -1;
1146
1147 nsr:
1148         /* search the list of VSDs for a NSR descriptor */
1149         for (b = 0; b < 64; b++) {
1150                 vsd = (struct volume_structure_descriptor *)
1151                       get_buffer(id, off + UDF_VSD_OFFSET + (b * bs), 0x800);
1152                 if (vsd == NULL)
1153                         return -1;
1154
1155                 dbg("vsd: %c%c%c%c%c",
1156                     vsd->id[0], vsd->id[1], vsd->id[2], vsd->id[3], vsd->id[4]);
1157
1158                 if (vsd->id[0] == '\0')
1159                         return -1;
1160                 if (strncmp(vsd->id, "NSR02", 5) == 0)
1161                         goto anchor;
1162                 if (strncmp(vsd->id, "NSR03", 5) == 0)
1163                         goto anchor;
1164         }
1165         return -1;
1166
1167 anchor:
1168         /* read anchor volume descriptor */
1169         vd = (struct volume_descriptor *)
1170                 get_buffer(id, off + (256 * bs), 0x200);
1171         if (vd == NULL)
1172                 return -1;
1173
1174         type = le16_to_cpu(vd->tag.id);
1175         if (type != 2) /* TAG_ID_AVDP */
1176                 goto found;
1177
1178         /* get desriptor list address and block count */
1179         count = le32_to_cpu(vd->type.anchor.length) / bs;
1180         loc = le32_to_cpu(vd->type.anchor.location);
1181         dbg("0x%x descriptors starting at logical secor 0x%x", count, loc);
1182
1183         /* pick the primary descriptor from the list */
1184         for (b = 0; b < count; b++) {
1185                 vd = (struct volume_descriptor *)
1186                      get_buffer(id, off + ((loc + b) * bs), 0x200);
1187                 if (vd == NULL)
1188                         return -1;
1189
1190                 type = le16_to_cpu(vd->tag.id);
1191                 dbg("descriptor type %i", type);
1192
1193                 /* check validity */
1194                 if (type == 0)
1195                         goto found;
1196                 if (le32_to_cpu(vd->tag.location) != loc + b)
1197                         goto found;
1198
1199                 if (type == 1) /* TAG_ID_PVD */
1200                         goto pvd;
1201         }
1202         goto found;
1203
1204 pvd:
1205         set_label_raw(id, &(vd->type.primary.ident.clen), 32);
1206
1207         clen = vd->type.primary.ident.clen;
1208         dbg("label string charsize=%i bit", clen);
1209         if (clen == 8)
1210                 set_label_string(id, vd->type.primary.ident.c, 31);
1211         else if (clen == 16)
1212                 set_label_unicode16(id, vd->type.primary.ident.c, BE,31);
1213
1214 found:
1215         id->usage_id = VOLUME_ID_FILESYSTEM;
1216         id->type_id = VOLUME_ID_UDF;
1217         id->type = "udf";
1218
1219         return 0;
1220 }
1221
1222 #define ISO_SUPERBLOCK_OFFSET           0x8000
1223 #define ISO_SECTOR_SIZE                 0x800
1224 #define ISO_VD_OFFSET                   (ISO_SUPERBLOCK_OFFSET + ISO_SECTOR_SIZE)
1225 #define ISO_VD_PRIMARY                  0x1
1226 #define ISO_VD_SUPPLEMENTARY            0x2
1227 #define ISO_VD_END                      0xff
1228 #define ISO_VD_MAX                      16
1229 static int probe_iso9660(struct volume_id *id, __u64 off)
1230 {
1231         union iso_super_block {
1232                 struct iso_header {
1233                         __u8    type;
1234                         __u8    id[5];
1235                         __u8    version;
1236                         __u8    unused1;
1237                         __u8            system_id[32];
1238                         __u8            volume_id[32];
1239                 } __attribute__((__packed__)) iso;
1240                 struct hs_header {
1241                         __u8    foo[8];
1242                         __u8    type;
1243                         __u8    id[4];
1244                         __u8    version;
1245                 } __attribute__((__packed__)) hs;
1246         } __attribute__((__packed__)) *is;
1247
1248         is = (union iso_super_block *)
1249              get_buffer(id, off + ISO_SUPERBLOCK_OFFSET, 0x200);
1250         if (is == NULL)
1251                 return -1;
1252
1253         if (strncmp(is->iso.id, "CD001", 5) == 0) {
1254                 int vd_offset;
1255                 int i;
1256                 int found_svd;
1257
1258                 found_svd = 0;
1259                 vd_offset = ISO_VD_OFFSET;
1260                 for (i = 0; i < ISO_VD_MAX; i++) {
1261                         is = (union iso_super_block *) 
1262                              get_buffer (id, off + vd_offset, 0x200);
1263                         if (is == NULL || is->iso.type == ISO_VD_END)
1264                                 break;
1265                         if (is->iso.type == ISO_VD_SUPPLEMENTARY) {
1266                                 dbg("found ISO supplementary VD at offset 0x%llx", off + vd_offset);
1267                                 found_svd = 1;
1268                                 break;
1269                         }
1270                         vd_offset += ISO_SECTOR_SIZE;
1271                 }
1272
1273                 if (!found_svd) {
1274                         is = (union iso_super_block *)
1275                              get_buffer(id, off + ISO_SUPERBLOCK_OFFSET, 0x200);
1276                         if (is == NULL)
1277                                 return -1;
1278                         set_label_raw(id, is->iso.volume_id, 32);
1279                         set_label_string(id, is->iso.volume_id, 32);
1280                 } else {
1281                         set_label_raw(id, is->iso.volume_id, 32);
1282                         set_label_unicode16(id, is->iso.volume_id, BE, 32);
1283                 }
1284                 goto found;
1285         }
1286         if (strncmp(is->hs.id, "CDROM", 5) == 0)
1287                 goto found;
1288         return -1;
1289
1290 found:
1291         id->usage_id = VOLUME_ID_FILESYSTEM;
1292         id->type_id = VOLUME_ID_ISO9660;
1293         id->type = "iso9660";
1294
1295         return 0;
1296 }
1297
1298 #define UFS_MAGIC                       0x00011954
1299 #define UFS2_MAGIC                      0x19540119
1300 #define UFS_MAGIC_FEA                   0x00195612
1301 #define UFS_MAGIC_LFN                   0x00095014
1302
1303
1304 static int probe_ufs(struct volume_id *id, __u64 off)
1305 {
1306         struct ufs_super_block {
1307                 __u32   fs_link;
1308                 __u32   fs_rlink;
1309                 __u32   fs_sblkno;
1310                 __u32   fs_cblkno;
1311                 __u32   fs_iblkno;
1312                 __u32   fs_dblkno;
1313                 __u32   fs_cgoffset;
1314                 __u32   fs_cgmask;
1315                 __u32   fs_time;
1316                 __u32   fs_size;
1317                 __u32   fs_dsize;
1318                 __u32   fs_ncg; 
1319                 __u32   fs_bsize;
1320                 __u32   fs_fsize;
1321                 __u32   fs_frag;
1322                 __u32   fs_minfree;
1323                 __u32   fs_rotdelay;
1324                 __u32   fs_rps; 
1325                 __u32   fs_bmask;
1326                 __u32   fs_fmask;
1327                 __u32   fs_bshift;
1328                 __u32   fs_fshift;
1329                 __u32   fs_maxcontig;
1330                 __u32   fs_maxbpg;
1331                 __u32   fs_fragshift;
1332                 __u32   fs_fsbtodb;
1333                 __u32   fs_sbsize;
1334                 __u32   fs_csmask;
1335                 __u32   fs_csshift;
1336                 __u32   fs_nindir;
1337                 __u32   fs_inopb;
1338                 __u32   fs_nspf;
1339                 __u32   fs_optim;
1340                 __u32   fs_npsect_state;
1341                 __u32   fs_interleave;
1342                 __u32   fs_trackskew;
1343                 __u32   fs_id[2];
1344                 __u32   fs_csaddr;
1345                 __u32   fs_cssize;
1346                 __u32   fs_cgsize;
1347                 __u32   fs_ntrak;
1348                 __u32   fs_nsect;
1349                 __u32   fs_spc; 
1350                 __u32   fs_ncyl;
1351                 __u32   fs_cpg;
1352                 __u32   fs_ipg;
1353                 __u32   fs_fpg;
1354                 struct ufs_csum {
1355                         __u32   cs_ndir;
1356                         __u32   cs_nbfree;
1357                         __u32   cs_nifree;
1358                         __u32   cs_nffree;
1359                 } __attribute__((__packed__)) fs_cstotal;
1360                 __s8    fs_fmod;
1361                 __s8    fs_clean;
1362                 __s8    fs_ronly;
1363                 __s8    fs_flags;
1364                 union {
1365                         struct {
1366                                 __s8    fs_fsmnt[512];
1367                                 __u32   fs_cgrotor;
1368                                 __u32   fs_csp[31];
1369                                 __u32   fs_maxcluster;
1370                                 __u32   fs_cpc;
1371                                 __u16   fs_opostbl[16][8];
1372                         } __attribute__((__packed__)) fs_u1;
1373                         struct {
1374                                 __s8  fs_fsmnt[468];
1375                                 __u8   fs_volname[32];
1376                                 __u64  fs_swuid;
1377                                 __s32  fs_pad;
1378                                 __u32   fs_cgrotor;
1379                                 __u32   fs_ocsp[28];
1380                                 __u32   fs_contigdirs;
1381                                 __u32   fs_csp; 
1382                                 __u32   fs_maxcluster;
1383                                 __u32   fs_active;
1384                                 __s32   fs_old_cpc;
1385                                 __s32   fs_maxbsize;
1386                                 __s64   fs_sparecon64[17];
1387                                 __s64   fs_sblockloc;
1388                                 struct  ufs2_csum_total {
1389                                         __u64   cs_ndir;
1390                                         __u64   cs_nbfree;
1391                                         __u64   cs_nifree;
1392                                         __u64   cs_nffree;
1393                                         __u64   cs_numclusters;
1394                                         __u64   cs_spare[3];
1395                                 } __attribute__((__packed__)) fs_cstotal;
1396                                 struct  ufs_timeval {
1397                                         __s32   tv_sec;
1398                                         __s32   tv_usec;
1399                                 } __attribute__((__packed__)) fs_time;
1400                                 __s64    fs_size;
1401                                 __s64    fs_dsize;
1402                                 __u64    fs_csaddr;
1403                                 __s64    fs_pendingblocks;
1404                                 __s32    fs_pendinginodes;
1405                         } __attribute__((__packed__)) fs_u2;
1406                 }  fs_u11;
1407                 union {
1408                         struct {
1409                                 __s32   fs_sparecon[53];
1410                                 __s32   fs_reclaim;
1411                                 __s32   fs_sparecon2[1];
1412                                 __s32   fs_state;
1413                                 __u32   fs_qbmask[2];
1414                                 __u32   fs_qfmask[2];
1415                         } __attribute__((__packed__)) fs_sun;
1416                         struct {
1417                                 __s32   fs_sparecon[53];
1418                                 __s32   fs_reclaim;
1419                                 __s32   fs_sparecon2[1];
1420                                 __u32   fs_npsect;
1421                                 __u32   fs_qbmask[2];
1422                                 __u32   fs_qfmask[2];
1423                         } __attribute__((__packed__)) fs_sunx86;
1424                         struct {
1425                                 __s32   fs_sparecon[50];
1426                                 __s32   fs_contigsumsize;
1427                                 __s32   fs_maxsymlinklen;
1428                                 __s32   fs_inodefmt;
1429                                 __u32   fs_maxfilesize[2];
1430                                 __u32   fs_qbmask[2];
1431                                 __u32   fs_qfmask[2];
1432                                 __s32   fs_state;
1433                         } __attribute__((__packed__)) fs_44;
1434                 } fs_u2;
1435                 __s32   fs_postblformat;
1436                 __s32   fs_nrpos;
1437                 __s32   fs_postbloff;
1438                 __s32   fs_rotbloff;
1439                 __u32   fs_magic;
1440                 __u8    fs_space[1];
1441         } __attribute__((__packed__)) *ufs;
1442
1443         __u32   magic;
1444         int     i;
1445         int     offsets[] = {0, 8, 64, 256, -1};
1446
1447         for (i = 0; offsets[i] >= 0; i++) {     
1448                 ufs = (struct ufs_super_block *)
1449                         get_buffer(id, off + (offsets[i] * 0x400), 0x800);
1450                 if (ufs == NULL)
1451                         return -1;
1452
1453                 dbg("offset 0x%x", offsets[i] * 0x400);
1454                 magic = be32_to_cpu(ufs->fs_magic);
1455                 if ((magic == UFS_MAGIC) ||
1456                     (magic == UFS2_MAGIC) ||
1457                     (magic == UFS_MAGIC_FEA) ||
1458                     (magic == UFS_MAGIC_LFN)) {
1459                         dbg("magic 0x%08x(be)", magic);
1460                         goto found;
1461                 }
1462                 magic = le32_to_cpu(ufs->fs_magic);
1463                 if ((magic == UFS_MAGIC) ||
1464                     (magic == UFS2_MAGIC) ||
1465                     (magic == UFS_MAGIC_FEA) ||
1466                     (magic == UFS_MAGIC_LFN)) {
1467                         dbg("magic 0x%08x(le)", magic);
1468                         goto found;
1469                 }
1470         }
1471         return -1;
1472
1473 found:
1474         id->usage_id = VOLUME_ID_FILESYSTEM;
1475         id->type_id = VOLUME_ID_UFS;
1476         id->type = "ufs";
1477
1478         return 0;
1479 }
1480
1481 static int probe_mac_partition_map(struct volume_id *id, __u64 off)
1482 {
1483         struct mac_driver_desc {
1484                 __u8    signature[2];
1485                 __u16   block_size;
1486                 __u32   block_count;
1487         } __attribute__((__packed__)) *driver;
1488
1489         struct mac_partition {
1490                 __u8    signature[2];
1491                 __u16   res1;
1492                 __u32   map_count;
1493                 __u32   start_block;
1494                 __u32   block_count;
1495                 __u8    name[32];
1496                 __u8    type[32];
1497         } __attribute__((__packed__)) *part;
1498
1499         const __u8 *buf;
1500
1501         buf = get_buffer(id, off, 0x200);
1502         if (buf == NULL)
1503                 return -1;
1504
1505         part = (struct mac_partition *) buf;
1506         if ((strncmp(part->signature, "PM", 2) == 0) &&
1507             (strncmp(part->type, "Apple_partition_map", 19) == 0)) {
1508                 /* linux creates an own subdevice for the map
1509                  * just return the type if the drive header is missing */
1510                 id->usage_id = VOLUME_ID_PARTITIONTABLE;
1511                 id->type_id = VOLUME_ID_MACPARTMAP;
1512                 id->type = "mac_partition_map";
1513                 return 0;
1514         }
1515
1516         driver = (struct mac_driver_desc *) buf;
1517         if (strncmp(driver->signature, "ER", 2) == 0) {
1518                 /* we are on a main device, like a CD
1519                  * just try to probe the first partition from the map */
1520                 unsigned int bsize = be16_to_cpu(driver->block_size);
1521                 int part_count;
1522                 int i;
1523
1524                 /* get first entry of partition table */
1525                 buf = get_buffer(id, off +  bsize, 0x200);
1526                 if (buf == NULL)
1527                         return -1;
1528
1529                 part = (struct mac_partition *) buf;
1530                 if (strncmp(part->signature, "PM", 2) != 0)
1531                         return -1;
1532
1533                 part_count = be32_to_cpu(part->map_count);
1534                 dbg("expecting %d partition entries", part_count);
1535
1536                 if (id->partitions != NULL)
1537                         free(id->partitions);
1538                 id->partitions =
1539                         malloc(part_count * sizeof(struct volume_id_partition));
1540                 if (id->partitions == NULL)
1541                         return -1;
1542                 memset(id->partitions, 0x00, sizeof(struct volume_id_partition));
1543
1544                 id->partition_count = part_count;
1545
1546                 for (i = 0; i < part_count; i++) {
1547                         __u64 poff;
1548                         __u64 plen;
1549
1550                         buf = get_buffer(id, off + ((i+1) * bsize), 0x200);
1551                         if (buf == NULL)
1552                                 return -1;
1553
1554                         part = (struct mac_partition *) buf;
1555                         if (strncmp(part->signature, "PM", 2) != 0)
1556                                 return -1;
1557
1558                         poff = be32_to_cpu(part->start_block) * bsize;
1559                         plen = be32_to_cpu(part->block_count) * bsize;
1560                         dbg("found '%s' partition entry at 0x%llx, len 0x%llx",
1561                             part->type, poff, plen);
1562
1563                         id->partitions[i].off = poff;
1564                         id->partitions[i].len = plen;
1565
1566                         if (strncmp(part->type, "Apple_Free", 10) == 0) {
1567                                 id->partitions[i].usage_id = VOLUME_ID_UNUSED;
1568                         } else if (strncmp(part->type, "Apple_partition_map", 19) == 0) {
1569                                 id->partitions[i].usage_id = VOLUME_ID_PARTITIONTABLE;
1570                                 id->partitions[i].type_id = VOLUME_ID_MACPARTMAP;
1571                         } else {
1572                                 id->partitions[i].usage_id = VOLUME_ID_UNPROBED;
1573                         }
1574                 }
1575                 id->usage_id = VOLUME_ID_PARTITIONTABLE;
1576                 id->type_id = VOLUME_ID_MACPARTMAP;
1577                 id->type = "mac_partition_map";
1578                 return 0;
1579         }
1580
1581         return -1;
1582 }
1583
1584 #define HFS_SUPERBLOCK_OFFSET           0x400
1585 #define HFS_NODE_LEAF                   0xff
1586 #define HFSPLUS_POR_CNID                1
1587 #define HFSPLUS_EXTENT_COUNT            8
1588 static int probe_hfs_hfsplus(struct volume_id *id, __u64 off)
1589 {
1590         struct hfs_finder_info{
1591                 __u32   boot_folder;
1592                 __u32   start_app;
1593                 __u32   open_folder;
1594                 __u32   os9_folder;
1595                 __u32   reserved;
1596                 __u32   osx_folder;
1597                 __u8    id[8];
1598         } __attribute__((__packed__));
1599
1600         struct hfs_mdb {
1601                 __u8    signature[2];
1602                 __u32   cr_date;
1603                 __u32   ls_Mod;
1604                 __u16   atrb;
1605                 __u16   nm_fls;
1606                 __u16   vbm_st;
1607                 __u16   alloc_ptr;
1608                 __u16   nm_al_blks;
1609                 __u32   al_blk_size;
1610                 __u32   clp_size;
1611                 __u16   al_bl_st;
1612                 __u32   nxt_cnid;
1613                 __u16   free_bks;
1614                 __u8    label_len;
1615                 __u8    label[27];
1616                 __u32   vol_bkup;
1617                 __u16   vol_seq_num;
1618                 __u32   wr_cnt;
1619                 __u32   xt_clump_size;
1620                 __u32   ct_clump_size;
1621                 __u16   num_root_dirs;
1622                 __u32   file_count;
1623                 __u32   dir_count;
1624                 struct hfs_finder_info finder_info;
1625                 __u8    embed_sig[2];
1626                 __u16   embed_startblock;
1627                 __u16   embed_blockcount;
1628         } __attribute__((__packed__)) *hfs;
1629
1630         struct hfsplus_bnode_descriptor {
1631                 __u32   next;
1632                 __u32   prev;
1633                 __u8    type;
1634                 __u8    height;
1635                 __u16   num_recs;
1636                 __u16   reserved;
1637         } __attribute__((__packed__));
1638
1639         struct hfsplus_bheader_record {
1640                 __u16   depth;
1641                 __u32   root;
1642                 __u32   leaf_count;
1643                 __u32   leaf_head;
1644                 __u32   leaf_tail;
1645                 __u16   node_size;
1646         } __attribute__((__packed__));
1647
1648         struct hfsplus_catalog_key {
1649                 __u16   key_len;
1650                 __u32   parent_id;
1651                 __u16   unicode_len;
1652                 __u8    unicode[255 * 2];
1653         } __attribute__((__packed__));
1654
1655         struct hfsplus_extent {
1656                 __u32 start_block;
1657                 __u32 block_count;
1658         } __attribute__((__packed__));
1659
1660         struct hfsplus_fork {
1661                 __u64 total_size;
1662                 __u32 clump_size;
1663                 __u32 total_blocks;
1664                 struct hfsplus_extent extents[HFSPLUS_EXTENT_COUNT];
1665         } __attribute__((__packed__));
1666
1667         struct hfsplus_vol_header {
1668                 __u8    signature[2];
1669                 __u16   version;
1670                 __u32   attributes;
1671                 __u32   last_mount_vers;
1672                 __u32   reserved;
1673                 __u32   create_date;
1674                 __u32   modify_date;
1675                 __u32   backup_date;
1676                 __u32   checked_date;
1677                 __u32   file_count;
1678                 __u32   folder_count;
1679                 __u32   blocksize;
1680                 __u32   total_blocks;
1681                 __u32   free_blocks;
1682                 __u32   next_alloc;
1683                 __u32   rsrc_clump_sz;
1684                 __u32   data_clump_sz;
1685                 __u32   next_cnid;
1686                 __u32   write_count;
1687                 __u64   encodings_bmp;
1688                 struct hfs_finder_info finder_info;
1689                 struct hfsplus_fork alloc_file;
1690                 struct hfsplus_fork ext_file;
1691                 struct hfsplus_fork cat_file;
1692                 struct hfsplus_fork attr_file;
1693                 struct hfsplus_fork start_file;
1694         } __attribute__((__packed__)) *hfsplus;
1695
1696         unsigned int blocksize;
1697         unsigned int cat_block;
1698         unsigned int ext_block_start;
1699         unsigned int ext_block_count;
1700         int ext;
1701         unsigned int leaf_node_head;
1702         unsigned int leaf_node_count;
1703         unsigned int leaf_node_size;
1704         unsigned int leaf_block;
1705         __u64 leaf_off;
1706         unsigned int alloc_block_size;
1707         unsigned int alloc_first_block;
1708         unsigned int embed_first_block;
1709         unsigned int record_count;
1710         struct hfsplus_bnode_descriptor *descr;
1711         struct hfsplus_bheader_record *bnode;
1712         struct hfsplus_catalog_key *key;
1713         unsigned int    label_len;
1714         struct hfsplus_extent extents[HFSPLUS_EXTENT_COUNT];
1715         const __u8 *buf;
1716
1717         buf = get_buffer(id, off + HFS_SUPERBLOCK_OFFSET, 0x200);
1718         if (buf == NULL)
1719                 return -1;
1720
1721         hfs = (struct hfs_mdb *) buf;
1722         if (strncmp(hfs->signature, "BD", 2) != 0)
1723                 goto checkplus;
1724
1725         /* it may be just a hfs wrapper for hfs+ */
1726         if (strncmp(hfs->embed_sig, "H+", 2) == 0) {
1727                 alloc_block_size = be32_to_cpu(hfs->al_blk_size);
1728                 dbg("alloc_block_size 0x%x", alloc_block_size);
1729
1730                 alloc_first_block = be16_to_cpu(hfs->al_bl_st);
1731                 dbg("alloc_first_block 0x%x", alloc_first_block);
1732
1733                 embed_first_block = be16_to_cpu(hfs->embed_startblock);
1734                 dbg("embed_first_block 0x%x", embed_first_block);
1735
1736                 off += (alloc_first_block * 512) +
1737                        (embed_first_block * alloc_block_size);
1738                 dbg("hfs wrapped hfs+ found at offset 0x%llx", off);
1739
1740                 buf = get_buffer(id, off + HFS_SUPERBLOCK_OFFSET, 0x200);
1741                 if (buf == NULL)
1742                         return -1;
1743                 goto checkplus;
1744         }
1745
1746         if (hfs->label_len > 0 && hfs->label_len < 28) {
1747                 set_label_raw(id, hfs->label, hfs->label_len);
1748                 set_label_string(id, hfs->label, hfs->label_len) ;
1749         }
1750
1751         set_uuid(id, hfs->finder_info.id, UUID_HFS);
1752
1753         id->usage_id = VOLUME_ID_FILESYSTEM;
1754         id->type_id = VOLUME_ID_HFS;
1755         id->type = "hfs";
1756
1757         return 0;
1758
1759 checkplus:
1760         hfsplus = (struct hfsplus_vol_header *) buf;
1761         if (strncmp(hfsplus->signature, "H+", 2) == 0)
1762                 goto hfsplus;
1763         if (strncmp(hfsplus->signature, "HX", 2) == 0)
1764                 goto hfsplus;
1765         return -1;
1766
1767 hfsplus:
1768         set_uuid(id, hfsplus->finder_info.id, UUID_HFS);
1769
1770         blocksize = be32_to_cpu(hfsplus->blocksize);
1771         dbg("blocksize %u", blocksize);
1772
1773         memcpy(extents, hfsplus->cat_file.extents, sizeof(extents));
1774         cat_block = be32_to_cpu(extents[0].start_block);
1775         dbg("catalog start block 0x%x", cat_block);
1776
1777         buf = get_buffer(id, off + (cat_block * blocksize), 0x2000);
1778         if (buf == NULL)
1779                 goto found;
1780
1781         bnode = (struct hfsplus_bheader_record *)
1782                 &buf[sizeof(struct hfsplus_bnode_descriptor)];
1783
1784         leaf_node_head = be32_to_cpu(bnode->leaf_head);
1785         dbg("catalog leaf node 0x%x", leaf_node_head);
1786
1787         leaf_node_size = be16_to_cpu(bnode->node_size);
1788         dbg("leaf node size 0x%x", leaf_node_size);
1789
1790         leaf_node_count = be32_to_cpu(bnode->leaf_count);
1791         dbg("leaf node count 0x%x", leaf_node_count);
1792         if (leaf_node_count == 0)
1793                 goto found;
1794
1795         leaf_block = (leaf_node_head * leaf_node_size) / blocksize;
1796
1797         /* get physical location */
1798         for (ext = 0; ext < HFSPLUS_EXTENT_COUNT; ext++) {
1799                 ext_block_start = be32_to_cpu(extents[ext].start_block);
1800                 ext_block_count = be32_to_cpu(extents[ext].block_count);
1801                 dbg("extent start block 0x%x, count 0x%x", ext_block_start, ext_block_count);
1802
1803                 if (ext_block_count == 0)
1804                         goto found;
1805
1806                 /* this is our extent */
1807                 if (leaf_block < ext_block_count)
1808                         break;
1809
1810                 leaf_block -= ext_block_count;
1811         }
1812         if (ext == HFSPLUS_EXTENT_COUNT)
1813                 goto found;
1814         dbg("found block in extent %i", ext);
1815
1816         leaf_off = (ext_block_start + leaf_block) * blocksize;
1817
1818         buf = get_buffer(id, off + leaf_off, leaf_node_size);
1819         if (buf == NULL)
1820                 goto found;
1821
1822         descr = (struct hfsplus_bnode_descriptor *) buf;
1823         dbg("descriptor type 0x%x", descr->type);
1824
1825         record_count = be16_to_cpu(descr->num_recs);
1826         dbg("number of records %u", record_count);
1827         if (record_count == 0)
1828                 goto found;
1829
1830         if (descr->type != HFS_NODE_LEAF)
1831                 goto found;
1832
1833         key = (struct hfsplus_catalog_key *)
1834                 &buf[sizeof(struct hfsplus_bnode_descriptor)];
1835
1836         dbg("parent id 0x%x", be32_to_cpu(key->parent_id));
1837         if (be32_to_cpu(key->parent_id) != HFSPLUS_POR_CNID)
1838                 goto found;
1839
1840         label_len = be16_to_cpu(key->unicode_len) * 2;
1841         dbg("label unicode16 len %i", label_len);
1842         set_label_raw(id, key->unicode, label_len);
1843         set_label_unicode16(id, key->unicode, BE, label_len);
1844
1845 found:
1846         id->usage_id = VOLUME_ID_FILESYSTEM;
1847         id->type_id = VOLUME_ID_HFSPLUS;
1848         id->type = "hfsplus";
1849
1850         return 0;
1851 }
1852
1853 #define MFT_RECORD_VOLUME                       3
1854 #define MFT_RECORD_ATTR_VOLUME_NAME             0x60
1855 #define MFT_RECORD_ATTR_VOLUME_INFO             0x70
1856 #define MFT_RECORD_ATTR_OBJECT_ID               0x40
1857 #define MFT_RECORD_ATTR_END                     0xffffffffu
1858 static int probe_ntfs(struct volume_id *id, __u64 off)
1859 {
1860         struct ntfs_super_block {
1861                 __u8    jump[3];
1862                 __u8    oem_id[8];
1863                 __u16   bytes_per_sector;
1864                 __u8    sectors_per_cluster;
1865                 __u16   reserved_sectors;
1866                 __u8    fats;
1867                 __u16   root_entries;
1868                 __u16   sectors;
1869                 __u8    media_type;
1870                 __u16   sectors_per_fat;
1871                 __u16   sectors_per_track;
1872                 __u16   heads;
1873                 __u32   hidden_sectors;
1874                 __u32   large_sectors;
1875                 __u16   unused[2];
1876                 __u64   number_of_sectors;
1877                 __u64   mft_cluster_location;
1878                 __u64   mft_mirror_cluster_location;
1879                 __s8    cluster_per_mft_record;
1880                 __u8    reserved1[3];
1881                 __s8    cluster_per_index_record;
1882                 __u8    reserved2[3];
1883                 __u8    volume_serial[8];
1884                 __u16   checksum;
1885         } __attribute__((__packed__)) *ns;
1886
1887         struct master_file_table_record {
1888                 __u8    magic[4];
1889                 __u16   usa_ofs;
1890                 __u16   usa_count;
1891                 __u64   lsn;
1892                 __u16   sequence_number;
1893                 __u16   link_count;
1894                 __u16   attrs_offset;
1895                 __u16   flags;
1896                 __u32   bytes_in_use;
1897                 __u32   bytes_allocated;
1898         } __attribute__((__packed__)) *mftr;
1899
1900         struct file_attribute {
1901                 __u32   type;
1902                 __u32   len;
1903                 __u8    non_resident;
1904                 __u8    name_len;
1905                 __u16   name_offset;
1906                 __u16   flags;
1907                 __u16   instance;
1908                 __u32   value_len;
1909                 __u16   value_offset;
1910         } __attribute__((__packed__)) *attr;
1911
1912         struct volume_info {
1913                 __u64 reserved;
1914                 __u8 major_ver;
1915                 __u8 minor_ver;
1916         } __attribute__((__packed__)) *info;
1917
1918         unsigned int sector_size;
1919         unsigned int cluster_size;
1920         __u64 mft_cluster;
1921         __u64 mft_off;
1922         unsigned int mft_record_size;
1923         unsigned int attr_type;
1924         unsigned int attr_off;
1925         unsigned int attr_len;
1926         unsigned int val_off;
1927         unsigned int val_len;
1928         const __u8 *buf;
1929         const __u8 *val;
1930
1931         ns = (struct ntfs_super_block *) get_buffer(id, off, 0x200);
1932         if (ns == NULL)
1933                 return -1;
1934
1935         if (strncmp(ns->oem_id, "NTFS", 4) != 0)
1936                 return -1;
1937
1938         set_uuid(id, ns->volume_serial, UUID_NTFS);
1939
1940         sector_size = le16_to_cpu(ns->bytes_per_sector);
1941         cluster_size = ns->sectors_per_cluster * sector_size;
1942         mft_cluster = le64_to_cpu(ns->mft_cluster_location);
1943         mft_off = mft_cluster * cluster_size;
1944
1945         if (ns->cluster_per_mft_record < 0)
1946                 /* size = -log2(mft_record_size); normally 1024 Bytes */
1947                 mft_record_size = 1 << -ns->cluster_per_mft_record;
1948         else
1949                 mft_record_size = ns->cluster_per_mft_record * cluster_size;
1950
1951         dbg("sectorsize  0x%x", sector_size);
1952         dbg("clustersize 0x%x", cluster_size);
1953         dbg("mftcluster  %lli", mft_cluster);
1954         dbg("mftoffset  0x%llx", mft_off);
1955         dbg("cluster per mft_record  %i", ns->cluster_per_mft_record);
1956         dbg("mft record size  %i", mft_record_size);
1957
1958         buf = get_buffer(id, off + mft_off + (MFT_RECORD_VOLUME * mft_record_size),
1959                          mft_record_size);
1960         if (buf == NULL)
1961                 goto found;
1962
1963         mftr = (struct master_file_table_record*) buf;
1964
1965         dbg("mftr->magic '%c%c%c%c'", mftr->magic[0], mftr->magic[1], mftr->magic[2], mftr->magic[3]);
1966         if (strncmp(mftr->magic, "FILE", 4) != 0)
1967                 goto found;
1968
1969         attr_off = le16_to_cpu(mftr->attrs_offset);
1970         dbg("file $Volume's attributes are at offset %i", attr_off);
1971
1972         while (1) {
1973                 attr = (struct file_attribute*) &buf[attr_off];
1974                 attr_type = le32_to_cpu(attr->type);
1975                 attr_len = le16_to_cpu(attr->len);
1976                 val_off = le16_to_cpu(attr->value_offset);
1977                 val_len = le32_to_cpu(attr->value_len);
1978                 attr_off += attr_len;
1979
1980                 if (attr_len == 0)
1981                         break;
1982
1983                 if (attr_off >= mft_record_size)
1984                         break;
1985
1986                 if (attr_type == MFT_RECORD_ATTR_END)
1987                         break;
1988
1989                 dbg("found attribute type 0x%x, len %i, at offset %i",
1990                     attr_type, attr_len, attr_off);
1991
1992                 if (attr_type == MFT_RECORD_ATTR_VOLUME_INFO) {
1993                         dbg("found info, len %i", val_len);
1994                         info = (struct volume_info*) (((__u8 *) attr) + val_off);
1995                         snprintf(id->type_version, VOLUME_ID_FORMAT_SIZE-1,
1996                                  "%u.%u", info->major_ver, info->minor_ver);
1997                 }
1998
1999                 if (attr_type == MFT_RECORD_ATTR_VOLUME_NAME) {
2000                         dbg("found label, len %i", val_len);
2001                         if (val_len > VOLUME_ID_LABEL_SIZE)
2002                                 val_len = VOLUME_ID_LABEL_SIZE;
2003
2004                         val = ((__u8 *) attr) + val_off;
2005                         set_label_raw(id, val, val_len);
2006                         set_label_unicode16(id, val, LE, val_len);
2007                 }
2008         }
2009
2010 found:
2011         id->usage_id = VOLUME_ID_FILESYSTEM;
2012         id->type_id = VOLUME_ID_NTFS;
2013         id->type = "ntfs";
2014
2015         return 0;
2016 }
2017
2018 #define LARGEST_PAGESIZE                        0x4000
2019 static int probe_swap(struct volume_id *id, __u64 off)
2020 {
2021         struct swap_header_v1_2 {
2022                 __u8    bootbits[1024];
2023                 __u32   version;
2024                 __u32   last_page;
2025                 __u32   nr_badpages;
2026                 __u8    uuid[16];
2027                 __u8    volume_name[16];
2028         } __attribute__((__packed__)) *sw;
2029
2030         const __u8 *buf;
2031         unsigned int page;
2032
2033         /* the swap signature is at the end of the PAGE_SIZE */
2034         for (page = 0x1000; page <= LARGEST_PAGESIZE; page <<= 1) {
2035                         buf = get_buffer(id, off + page-10, 10);
2036                         if (buf == NULL)
2037                                 return -1;
2038
2039                         if (strncmp(buf, "SWAP-SPACE", 10) == 0) {
2040                                 strcpy(id->type_version, "1");
2041                                 goto found;
2042                         }
2043
2044                         if (strncmp(buf, "SWAPSPACE2", 10) == 0) {
2045                                 sw = (struct swap_header_v1_2 *) get_buffer(id, off, sizeof(struct swap_header_v1_2));
2046                                 if (sw == NULL)
2047                                         return -1;
2048                                 strcpy(id->type_version, "2");
2049                                 set_label_raw(id, sw->volume_name, 16);
2050                                 set_label_string(id, sw->volume_name, 16);
2051                                 set_uuid(id, sw->uuid, UUID_DCE);
2052                                 goto found;
2053                         }
2054         }
2055         return -1;
2056
2057 found:
2058         id->usage_id = VOLUME_ID_OTHER;
2059         id->type_id = VOLUME_ID_SWAP;
2060         id->type = "swap";
2061
2062         return 0;
2063 }
2064
2065 /* probe volume for filesystem type and try to read label+uuid */
2066 int volume_id_probe(struct volume_id *id,
2067                     enum volume_id_type type,
2068                     unsigned long long off,
2069                     unsigned long long size)
2070 {
2071         int rc;
2072
2073         dbg("called with size=0x%llx", size);
2074
2075         if (id == NULL)
2076                 return -EINVAL;
2077
2078         switch (type) {
2079         case VOLUME_ID_MSDOSPARTTABLE:
2080                 rc = probe_msdos_part_table(id, off);
2081                 break;
2082         case VOLUME_ID_EXT3:
2083         case VOLUME_ID_EXT2:
2084                 rc = probe_ext(id, off);
2085                 break;
2086         case VOLUME_ID_REISERFS:
2087                 rc = probe_reiserfs(id, off);
2088                 break;
2089         case VOLUME_ID_XFS:
2090                 rc = probe_xfs(id, off);
2091                 break;
2092         case VOLUME_ID_JFS:
2093                 rc = probe_jfs(id, off);
2094                 break;
2095         case VOLUME_ID_VFAT:
2096                 rc = probe_vfat(id, off);
2097                 break;
2098         case VOLUME_ID_UDF:
2099                 rc = probe_udf(id, off);
2100                 break;
2101         case VOLUME_ID_ISO9660:
2102                 rc = probe_iso9660(id, off);
2103                 break;
2104         case VOLUME_ID_MACPARTMAP:
2105                 rc = probe_mac_partition_map(id, off);
2106                 break;
2107         case VOLUME_ID_HFS:
2108         case VOLUME_ID_HFSPLUS:
2109                 rc = probe_hfs_hfsplus(id, off);
2110                 break;
2111         case VOLUME_ID_UFS:
2112                 rc = probe_ufs(id, off);
2113                 break;
2114         case VOLUME_ID_NTFS:
2115                 rc = probe_ntfs(id, off);
2116                 break;
2117         case VOLUME_ID_SWAP:
2118                 rc = probe_swap(id, off);
2119                 break;
2120         case VOLUME_ID_LINUX_RAID:
2121                 rc = probe_linux_raid(id, off, size);
2122                 break;
2123         case VOLUME_ID_LVM1:
2124                 rc = probe_lvm1(id, off);
2125                 break;
2126         case VOLUME_ID_LVM2:
2127                 rc = probe_lvm2(id, off);
2128                 break;
2129         case VOLUME_ID_HPTRAID:
2130                 rc = probe_highpoint_ataraid(id, off);
2131                 break;
2132         case VOLUME_ID_ALL:
2133         default:
2134                 /* probe for raid first, cause fs probes may be successful on raid members */
2135                 rc = probe_linux_raid(id, off, size);
2136                 if (rc == 0)
2137                         break;
2138                 rc = probe_lvm1(id, off);
2139                 if (rc == 0)
2140                         break;
2141                 rc = probe_lvm2(id, off);
2142                 if (rc == 0)
2143                         break;
2144                 rc = probe_highpoint_ataraid(id, off);
2145                 if (rc == 0)
2146                         break;
2147
2148                 /* signature in the first block, only small buffer needed */
2149                 rc = probe_vfat(id, off);
2150                 if (rc == 0)
2151                         break;
2152                 rc = probe_mac_partition_map(id, off);
2153                 if (rc == 0)
2154                         break;
2155                 rc = probe_xfs(id, off);
2156                 if (rc == 0)
2157                         break;
2158
2159                 /* fill buffer with maximum */
2160                 get_buffer(id, 0, SB_BUFFER_SIZE);
2161
2162                 rc = probe_swap(id, off);
2163                 if (rc == 0)
2164                         break;
2165                 rc = probe_ext(id, off);
2166                 if (rc == 0)
2167                         break;
2168                 rc = probe_reiserfs(id, off);
2169                 if (rc == 0)
2170                         break;
2171                 rc = probe_jfs(id, off);
2172                 if (rc == 0)
2173                         break;
2174                 rc = probe_udf(id, off);
2175                 if (rc == 0)
2176                         break;
2177                 rc = probe_iso9660(id, off);
2178                 if (rc == 0)
2179                         break;
2180                 rc = probe_hfs_hfsplus(id, off);
2181                 if (rc == 0)
2182                         break;
2183                 rc = probe_ufs(id, off);
2184                 if (rc == 0)
2185                         break;
2186                 rc = probe_ntfs(id, off);
2187                 if (rc == 0)
2188                         break;
2189
2190                 rc = -1;
2191         }
2192
2193         /* If the filestystem in recognized, we free the allocated buffers,
2194            otherwise they will stay in place for the possible next probe call */
2195         if (rc == 0)
2196                 free_buffer(id);
2197
2198         return rc;
2199 }
2200
2201 /* open volume by already open file descriptor */
2202 struct volume_id *volume_id_open_fd(int fd)
2203 {
2204         struct volume_id *id;
2205
2206         id = malloc(sizeof(struct volume_id));
2207         if (id == NULL)
2208                 return NULL;
2209         memset(id, 0x00, sizeof(struct volume_id));
2210
2211         id->fd = fd;
2212
2213         return id;
2214 }
2215
2216 /* open volume by device node */
2217 struct volume_id *volume_id_open_node(const char *path)
2218 {
2219         struct volume_id *id;
2220         int fd;
2221
2222         fd = open(path, O_RDONLY);
2223         if (fd < 0) {
2224                 dbg("unable to open '%s'", path);
2225                 return NULL;
2226         }
2227
2228         id = volume_id_open_fd(fd);
2229         if (id == NULL)
2230                 return NULL;
2231
2232         /* close fd on device close */
2233         id->fd_close = 1;
2234
2235         return id;
2236 }
2237
2238 /* open volume by major/minor */
2239 struct volume_id *volume_id_open_dev_t(dev_t devt)
2240 {
2241         struct volume_id *id;
2242         __u8 tmp_node[VOLUME_ID_PATH_MAX];
2243
2244         snprintf(tmp_node, VOLUME_ID_PATH_MAX,
2245                  "/tmp/volume-%u-%u-%u", getpid(), major(devt), minor(devt));
2246         tmp_node[VOLUME_ID_PATH_MAX] = '\0';
2247
2248         /* create tempory node to open the block device */
2249         unlink(tmp_node);
2250         if (mknod(tmp_node, (S_IFBLK | 0600), devt) != 0)
2251                 return NULL;
2252
2253         id = volume_id_open_node(tmp_node);
2254
2255         unlink(tmp_node);
2256
2257         return id;
2258 }
2259
2260 /* free allocated volume info */
2261 void volume_id_close(struct volume_id *id)
2262 {
2263         if (id == NULL)
2264                 return;
2265
2266         if (id->fd_close != 0)
2267                 close(id->fd);
2268
2269         free_buffer(id);
2270
2271         if (id->partitions != NULL)
2272                 free(id->partitions);
2273
2274         free(id);
2275 }