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