add a tiny version of libblkid
authorJohn Crispin <blogic@openwrt.org>
Wed, 19 Jun 2013 19:14:23 +0000 (21:14 +0200)
committerJohn Crispin <blogic@openwrt.org>
Wed, 19 Jun 2013 19:14:23 +0000 (21:14 +0200)
Signed-off-by: John Crispin <blogic@openwrt.org>
18 files changed:
libblkid-tiny/bitops.h [new file with mode: 0644]
libblkid-tiny/blkdev.h [new file with mode: 0644]
libblkid-tiny/blkid.h [new file with mode: 0644]
libblkid-tiny/blkidP.h [new file with mode: 0644]
libblkid-tiny/c.h [new file with mode: 0644]
libblkid-tiny/ext.c [new file with mode: 0644]
libblkid-tiny/jffs2.c [new file with mode: 0644]
libblkid-tiny/libblkid-tiny.c [new file with mode: 0644]
libblkid-tiny/libblkid-tiny.h [new file with mode: 0644]
libblkid-tiny/linux_version.h [new file with mode: 0644]
libblkid-tiny/md5.c [new file with mode: 0644]
libblkid-tiny/md5.h [new file with mode: 0644]
libblkid-tiny/mkdev.c [new file with mode: 0644]
libblkid-tiny/squashfs.c [new file with mode: 0644]
libblkid-tiny/superblocks.h [new file with mode: 0644]
libblkid-tiny/swap.c [new file with mode: 0644]
libblkid-tiny/ubifs.c [new file with mode: 0644]
libblkid-tiny/vfat.c [new file with mode: 0644]

diff --git a/libblkid-tiny/bitops.h b/libblkid-tiny/bitops.h
new file mode 100644 (file)
index 0000000..81375d0
--- /dev/null
@@ -0,0 +1,84 @@
+#ifndef BITOPS_H
+#define BITOPS_H
+
+#include <stdint.h>
+
+/*
+ * Bit map related macros. Usually provided by libc.
+ */
+#include <sys/param.h>
+
+#ifndef NBBY
+# define NBBY            CHAR_BIT
+#endif
+
+#ifndef setbit
+# define setbit(a,i)   ((a)[(i)/NBBY] |= 1<<((i)%NBBY))
+# define clrbit(a,i)   ((a)[(i)/NBBY] &= ~(1<<((i)%NBBY)))
+# define isset(a,i)    ((a)[(i)/NBBY] & (1<<((i)%NBBY)))
+# define isclr(a,i)    (((a)[(i)/NBBY] & (1<<((i)%NBBY))) == 0)
+#endif
+
+/*
+ * Byte swab macros (based on linux/byteorder/swab.h)
+ */
+#define swab16(x) \
+       ((uint16_t)( \
+               (((uint16_t)(x) & (uint16_t)0x00ffU) << 8) | \
+               (((uint16_t)(x) & (uint16_t)0xff00U) >> 8) ))
+
+#define swab32(x) \
+       ((uint32_t)( \
+               (((uint32_t)(x) & (uint32_t)0x000000ffUL) << 24) | \
+               (((uint32_t)(x) & (uint32_t)0x0000ff00UL) <<  8) | \
+               (((uint32_t)(x) & (uint32_t)0x00ff0000UL) >>  8) | \
+               (((uint32_t)(x) & (uint32_t)0xff000000UL) >> 24) ))
+
+#define swab64(x) \
+       ((uint64_t)( \
+               (uint64_t)(((uint64_t)(x) & (uint64_t)0x00000000000000ffULL) << 56) | \
+               (uint64_t)(((uint64_t)(x) & (uint64_t)0x000000000000ff00ULL) << 40) | \
+               (uint64_t)(((uint64_t)(x) & (uint64_t)0x0000000000ff0000ULL) << 24) | \
+               (uint64_t)(((uint64_t)(x) & (uint64_t)0x00000000ff000000ULL) <<  8) | \
+               (uint64_t)(((uint64_t)(x) & (uint64_t)0x000000ff00000000ULL) >>  8) | \
+               (uint64_t)(((uint64_t)(x) & (uint64_t)0x0000ff0000000000ULL) >> 24) | \
+               (uint64_t)(((uint64_t)(x) & (uint64_t)0x00ff000000000000ULL) >> 40) | \
+               (uint64_t)(((uint64_t)(x) & (uint64_t)0xff00000000000000ULL) >> 56) ))
+
+
+#ifdef WORDS_BIGENDIAN
+
+#define cpu_to_le16(x) swab16(x)
+#define cpu_to_le32(x) swab32(x)
+#define cpu_to_le64(x) swab64(x)
+#define cpu_to_be16(x) ((uint16_t)(x))
+#define cpu_to_be32(x) ((uint32_t)(x))
+#define cpu_to_be64(x) ((uint64_t)(x))
+
+#define le16_to_cpu(x) swab16(x)
+#define le32_to_cpu(x) swab32(x)
+#define le64_to_cpu(x) swab64(x)
+#define be16_to_cpu(x) ((uint16_t)(x))
+#define be32_to_cpu(x) ((uint32_t)(x))
+#define be64_to_cpu(x) ((uint64_t)(x))
+
+#else /* !WORDS_BIGENDIAN */
+
+#define cpu_to_le16(x) ((uint16_t)(x))
+#define cpu_to_le32(x) ((uint32_t)(x))
+#define cpu_to_le64(x) ((uint64_t)(x))
+#define cpu_to_be16(x) swab16(x)
+#define cpu_to_be32(x) swab32(x)
+#define cpu_to_be64(x) swab64(x)
+
+#define le16_to_cpu(x) ((uint16_t)(x))
+#define le32_to_cpu(x) ((uint32_t)(x))
+#define le64_to_cpu(x) ((uint64_t)(x))
+#define be16_to_cpu(x) swab16(x)
+#define be32_to_cpu(x) swab32(x)
+#define be64_to_cpu(x) swab64(x)
+
+#endif /* WORDS_BIGENDIAN */
+
+#endif /* BITOPS_H */
+
diff --git a/libblkid-tiny/blkdev.h b/libblkid-tiny/blkdev.h
new file mode 100644 (file)
index 0000000..6b18879
--- /dev/null
@@ -0,0 +1,113 @@
+#ifndef BLKDEV_H
+#define BLKDEV_H
+
+#include <sys/types.h>
+#include <sys/ioctl.h>
+#ifdef HAVE_SYS_IOCCOM_H
+# include <sys/ioccom.h> /* for _IO macro on e.g. Solaris */
+#endif
+#include <fcntl.h>
+#include <unistd.h>
+
+#ifdef HAVE_SYS_MKDEV_H
+# include <sys/mkdev.h>                /* major and minor on Solaris */
+#endif
+
+#define DEFAULT_SECTOR_SIZE       512
+
+#ifdef __linux__
+/* very basic ioclts, should be available everywhere */
+# ifndef BLKROSET
+#  define BLKROSET   _IO(0x12,93)      /* set device read-only (0 = read-write) */
+#  define BLKROGET   _IO(0x12,94)      /* get read-only status (0 = read_write) */
+#  define BLKRRPART  _IO(0x12,95)      /* re-read partition table */
+#  define BLKGETSIZE _IO(0x12,96)      /* return device size /512 (long *arg) */
+#  define BLKFLSBUF  _IO(0x12,97)      /* flush buffer cache */
+#  define BLKRASET   _IO(0x12,98)      /* set read ahead for block device */
+#  define BLKRAGET   _IO(0x12,99)      /* get current read ahead setting */
+#  define BLKFRASET  _IO(0x12,100)     /* set filesystem (mm/filemap.c) read-ahead */
+#  define BLKFRAGET  _IO(0x12,101)     /* get filesystem (mm/filemap.c) read-ahead */
+#  define BLKSECTSET _IO(0x12,102)     /* set max sectors per request (ll_rw_blk.c) */
+#  define BLKSECTGET _IO(0x12,103)     /* get max sectors per request (ll_rw_blk.c) */
+#  define BLKSSZGET  _IO(0x12,104)     /* get block device sector size */
+
+/* ioctls introduced in 2.2.16, removed in 2.5.58 */
+#  define BLKELVGET  _IOR(0x12,106,size_t) /* elevator get */
+#  define BLKELVSET  _IOW(0x12,107,size_t) /* elevator set */
+
+#  define BLKBSZGET  _IOR(0x12,112,size_t)
+#  define BLKBSZSET  _IOW(0x12,113,size_t)
+# endif /* !BLKROSET */
+
+# ifndef BLKGETSIZE64
+#  define BLKGETSIZE64 _IOR(0x12,114,size_t) /* return device size in bytes (u64 *arg) */
+# endif
+
+/* block device topology ioctls, introduced in 2.6.32 (commit ac481c20) */
+# ifndef BLKIOMIN
+#  define BLKIOMIN   _IO(0x12,120)
+#  define BLKIOOPT   _IO(0x12,121)
+#  define BLKALIGNOFF _IO(0x12,122)
+#  define BLKPBSZGET _IO(0x12,123)
+# endif
+
+/* discard zeroes support, introduced in 2.6.33 (commit 98262f27) */
+# ifndef BLKDISCARDZEROES
+#  define BLKDISCARDZEROES _IO(0x12,124)
+# endif
+
+/* filesystem freeze, introduced in 2.6.29 (commit fcccf502) */
+# ifndef FIFREEZE
+#  define FIFREEZE   _IOWR('X', 119, int)    /* Freeze */
+#  define FITHAW     _IOWR('X', 120, int)    /* Thaw */
+# endif
+
+#endif /* __linux */
+
+#ifdef APPLE_DARWIN
+# define BLKGETSIZE DKIOCGETBLOCKCOUNT32
+#endif
+
+#ifndef HDIO_GETGEO
+# ifdef __linux__
+#  define HDIO_GETGEO 0x0301
+# endif
+
+/* uniform CD-ROM information */
+#ifndef CDROM_GET_CAPABILITY
+# define CDROM_GET_CAPABILITY 0x5331
+#endif
+
+struct hd_geometry {
+       unsigned char heads;
+       unsigned char sectors;
+       unsigned short cylinders;       /* truncated */
+       unsigned long start;
+};
+#endif
+
+/* are we working with block device? */
+int is_blkdev(int fd);
+
+/* Determine size in bytes */
+off_t blkdev_find_size (int fd);
+
+/* get size in bytes */
+int blkdev_get_size(int fd, unsigned long long *bytes);
+
+/* get 512-byte sector count */
+int blkdev_get_sectors(int fd, unsigned long long *sectors);
+
+/* get hardware sector size */
+int blkdev_get_sector_size(int fd, int *sector_size);
+
+/* specifies whether or not the device is misaligned */
+int blkdev_is_misaligned(int fd);
+
+/* get physical block device size */
+int blkdev_get_physector_size(int fd, int *sector_size);
+
+/* is the device cdrom capable? */
+int blkdev_is_cdrom(int fd);
+
+#endif /* BLKDEV_H */
diff --git a/libblkid-tiny/blkid.h b/libblkid-tiny/blkid.h
new file mode 100644 (file)
index 0000000..9ecfa6b
--- /dev/null
@@ -0,0 +1,353 @@
+/*
+ * blkid.h - Interface for libblkid, a library to identify block devices
+ *
+ * Copyright (C) 2001 Andreas Dilger
+ * Copyright (C) 2003 Theodore Ts'o
+ * Copyright (C) 2008 Karel Zak <kzak@redhat.com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307  USA
+ */
+
+#ifndef _BLKID_BLKID_H
+#define _BLKID_BLKID_H
+
+#include <stdint.h>
+#include <sys/types.h>
+
+#include "libblkid-tiny.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define BLKID_VERSION   "2.21.0"
+#define BLKID_DATE      "25-May-2012"
+
+/**
+ * blkid_dev:
+ *
+ * The device object keeps information about one device
+ */
+typedef struct blkid_struct_dev *blkid_dev;
+
+/**
+ * blkid_cache:
+ *
+ * information about all system devices
+ */
+typedef struct blkid_struct_cache *blkid_cache;
+
+/**
+ * blkid_probe:
+ *
+ * low-level probing setting
+ */
+typedef struct blkid_struct_probe *blkid_probe;
+
+/**
+ * blkid_topology:
+ *
+ * device topology information
+ */
+typedef struct blkid_struct_topology *blkid_topology;
+
+/**
+ * blkid_partlist
+ *
+ * list of all detected partitions and partitions tables
+ */
+typedef struct blkid_struct_partlist *blkid_partlist;
+
+/**
+ * blkid_partition:
+ *
+ * information about a partition
+ */
+typedef struct blkid_struct_partition *blkid_partition;
+
+/**
+ * blkid_parttable:
+ *
+ * information about a partition table
+ */
+typedef struct blkid_struct_parttable *blkid_parttable;
+
+/**
+ * blkid_loff_t:
+ *
+ * 64-bit signed number for offsets and sizes
+ */
+typedef int64_t blkid_loff_t;
+
+/**
+ * blkid_tag_iterate:
+ *
+ * tags iterator for high-level (blkid_cache) API
+ */
+typedef struct blkid_struct_tag_iterate *blkid_tag_iterate;
+
+/**
+ * blkid_dev_iterate:
+ *
+ * devices iterator for high-level (blkid_cache) API
+ */
+typedef struct blkid_struct_dev_iterate *blkid_dev_iterate;
+
+/*
+ * Flags for blkid_get_dev
+ *
+ * BLKID_DEV_CREATE    Create an empty device structure if not found
+ *                     in the cache.
+ * BLKID_DEV_VERIFY    Make sure the device structure corresponds
+ *                     with reality.
+ * BLKID_DEV_FIND      Just look up a device entry, and return NULL
+ *                     if it is not found.
+ * BLKID_DEV_NORMAL    Get a valid device structure, either from the
+ *                     cache or by probing the device.
+ */
+#define BLKID_DEV_FIND         0x0000
+#define BLKID_DEV_CREATE       0x0001
+#define BLKID_DEV_VERIFY       0x0002
+#define BLKID_DEV_NORMAL       (BLKID_DEV_CREATE | BLKID_DEV_VERIFY)
+
+/* cache.c */
+extern void blkid_put_cache(blkid_cache cache);
+extern int blkid_get_cache(blkid_cache *cache, const char *filename);
+extern void blkid_gc_cache(blkid_cache cache);
+
+/* dev.c */
+extern const char *blkid_dev_devname(blkid_dev dev);
+
+extern blkid_dev_iterate blkid_dev_iterate_begin(blkid_cache cache);
+extern int blkid_dev_set_search(blkid_dev_iterate iter,
+                               char *search_type, char *search_value);
+extern int blkid_dev_next(blkid_dev_iterate iterate, blkid_dev *dev);
+extern void blkid_dev_iterate_end(blkid_dev_iterate iterate);
+
+/* devno.c */
+extern char *blkid_devno_to_devname(dev_t devno);
+extern int blkid_devno_to_wholedisk(dev_t dev, char *diskname,
+                        size_t len, dev_t *diskdevno);
+
+/* devname.c */
+extern int blkid_probe_all(blkid_cache cache);
+extern int blkid_probe_all_new(blkid_cache cache);
+extern int blkid_probe_all_removable(blkid_cache cache);
+extern blkid_dev blkid_get_dev(blkid_cache cache, const char *devname,
+                              int flags);
+
+/* getsize.c */
+extern blkid_loff_t blkid_get_dev_size(int fd);
+
+/* verify.c */
+extern blkid_dev blkid_verify(blkid_cache cache, blkid_dev dev);
+
+/* read.c */
+
+/* resolve.c */
+extern char *blkid_get_tag_value(blkid_cache cache, const char *tagname,
+                                      const char *devname);
+extern char *blkid_get_devname(blkid_cache cache, const char *token,
+                              const char *value);
+
+/* tag.c */
+extern blkid_tag_iterate blkid_tag_iterate_begin(blkid_dev dev);
+extern int blkid_tag_next(blkid_tag_iterate iterate,
+                             const char **type, const char **value);
+extern void blkid_tag_iterate_end(blkid_tag_iterate iterate);
+extern int blkid_dev_has_tag(blkid_dev dev, const char *type,
+                            const char *value);
+extern blkid_dev blkid_find_dev_with_tag(blkid_cache cache,
+                                        const char *type,
+                                        const char *value);
+extern int blkid_parse_tag_string(const char *token, char **ret_type,
+                                 char **ret_val);
+
+/* version.c */
+extern int blkid_parse_version_string(const char *ver_string);
+extern int blkid_get_library_version(const char **ver_string,
+                                    const char **date_string);
+
+/* encode.c */
+extern int blkid_encode_string(const char *str, char *str_enc, size_t len);
+extern int blkid_safe_string(const char *str, char *str_safe, size_t len);
+
+/* evaluate.c */
+extern int blkid_send_uevent(const char *devname, const char *action);
+extern char *blkid_evaluate_tag(const char *token, const char *value,
+                               blkid_cache *cache);
+extern char *blkid_evaluate_spec(const char *spec, blkid_cache *cache);
+
+/* probe.c */
+extern blkid_probe blkid_new_probe(void);
+extern blkid_probe blkid_new_probe_from_filename(const char *filename);
+extern void blkid_free_probe(blkid_probe pr);
+extern void blkid_reset_probe(blkid_probe pr);
+
+extern int blkid_probe_set_device(blkid_probe pr, int fd,
+                       blkid_loff_t off, blkid_loff_t size);
+
+extern dev_t blkid_probe_get_devno(blkid_probe pr);
+extern dev_t blkid_probe_get_wholedisk_devno(blkid_probe pr);
+extern int blkid_probe_is_wholedisk(blkid_probe pr);
+
+extern blkid_loff_t blkid_probe_get_size(blkid_probe pr);
+extern blkid_loff_t blkid_probe_get_offset(blkid_probe pr);
+extern unsigned int blkid_probe_get_sectorsize(blkid_probe pr);
+extern blkid_loff_t blkid_probe_get_sectors(blkid_probe pr);
+
+extern int blkid_probe_get_fd(blkid_probe pr);
+
+/*
+ * superblocks probing
+ */
+extern int blkid_known_fstype(const char *fstype);
+extern int blkid_superblocks_get_name(size_t idx, const char **name, int *usage);
+
+extern int blkid_probe_enable_superblocks(blkid_probe pr, int enable);
+
+#define BLKID_SUBLKS_LABEL     (1 << 1) /* read LABEL from superblock */
+#define BLKID_SUBLKS_LABELRAW  (1 << 2) /* read and define LABEL_RAW result value*/
+#define BLKID_SUBLKS_UUID      (1 << 3) /* read UUID from superblock */
+#define BLKID_SUBLKS_UUIDRAW   (1 << 4) /* read and define UUID_RAW result value */
+#define BLKID_SUBLKS_TYPE      (1 << 5) /* define TYPE result value */
+#define BLKID_SUBLKS_SECTYPE   (1 << 6) /* define compatible fs type (second type) */
+#define BLKID_SUBLKS_USAGE     (1 << 7) /* define USAGE result value */
+#define BLKID_SUBLKS_VERSION   (1 << 8) /* read FS type from superblock */
+#define BLKID_SUBLKS_MAGIC     (1 << 9) /* define SBMAGIC and SBMAGIC_OFFSET */
+
+#define BLKID_SUBLKS_DEFAULT   (BLKID_SUBLKS_LABEL | BLKID_SUBLKS_UUID | \
+                                BLKID_SUBLKS_TYPE | BLKID_SUBLKS_SECTYPE)
+
+extern int blkid_probe_set_superblocks_flags(blkid_probe pr, int flags);
+
+extern int blkid_probe_reset_superblocks_filter(blkid_probe pr);
+extern int blkid_probe_invert_superblocks_filter(blkid_probe pr);
+
+/**
+ * BLKID_FLTR_NOTIN
+ */
+#define BLKID_FLTR_NOTIN               1
+/**
+ * BLKID_FLTR_ONLYIN
+ */
+#define BLKID_FLTR_ONLYIN              2
+extern int blkid_probe_filter_superblocks_type(blkid_probe pr, int flag, char *names[]);
+
+#define BLKID_USAGE_FILESYSTEM         (1 << 1)
+#define BLKID_USAGE_RAID               (1 << 2)
+#define BLKID_USAGE_CRYPTO             (1 << 3)
+#define BLKID_USAGE_OTHER              (1 << 4)
+extern int blkid_probe_filter_superblocks_usage(blkid_probe pr, int flag, int usage);
+
+/*
+ * topology probing
+ */
+extern int blkid_probe_enable_topology(blkid_probe pr, int enable);
+
+/* binary interface */
+extern blkid_topology blkid_probe_get_topology(blkid_probe pr);
+
+extern unsigned long blkid_topology_get_alignment_offset(blkid_topology tp);
+extern unsigned long blkid_topology_get_minimum_io_size(blkid_topology tp);
+extern unsigned long blkid_topology_get_optimal_io_size(blkid_topology tp);
+extern unsigned long blkid_topology_get_logical_sector_size(blkid_topology tp);
+extern unsigned long blkid_topology_get_physical_sector_size(blkid_topology tp);
+
+/*
+ * partitions probing
+ */
+extern int blkid_known_pttype(const char *pttype);
+extern int blkid_probe_enable_partitions(blkid_probe pr, int enable);
+
+extern int blkid_probe_reset_partitions_filter(blkid_probe pr);
+extern int blkid_probe_invert_partitions_filter(blkid_probe pr);
+extern int blkid_probe_filter_partitions_type(blkid_probe pr, int flag, char *names[]);
+
+
+/* partitions probing flags */
+#define BLKID_PARTS_FORCE_GPT          (1 << 1)
+#define BLKID_PARTS_ENTRY_DETAILS      (1 << 2)
+#define BLKID_PARTS_MAGIC              (1 << 3)
+extern int blkid_probe_set_partitions_flags(blkid_probe pr, int flags);
+
+/* binary interface */
+extern blkid_partlist blkid_probe_get_partitions(blkid_probe pr);
+
+extern int blkid_partlist_numof_partitions(blkid_partlist ls);
+extern blkid_parttable blkid_partlist_get_table(blkid_partlist ls);
+extern blkid_partition blkid_partlist_get_partition(blkid_partlist ls, int n);
+extern blkid_partition blkid_partlist_devno_to_partition(blkid_partlist ls, dev_t devno);
+
+extern blkid_parttable blkid_partition_get_table(blkid_partition par);
+extern const char *blkid_partition_get_name(blkid_partition par);
+extern const char *blkid_partition_get_uuid(blkid_partition par);
+extern int blkid_partition_get_partno(blkid_partition par);
+extern blkid_loff_t blkid_partition_get_start(blkid_partition par);
+extern blkid_loff_t blkid_partition_get_size(blkid_partition par);
+extern int blkid_partition_get_type(blkid_partition par);
+extern const char *blkid_partition_get_type_string(blkid_partition par);
+extern unsigned long long blkid_partition_get_flags(blkid_partition par);
+extern int blkid_partition_is_logical(blkid_partition par);
+extern int blkid_partition_is_extended(blkid_partition par);
+extern int blkid_partition_is_primary(blkid_partition par);
+
+extern const char *blkid_parttable_get_type(blkid_parttable tab);
+extern blkid_loff_t blkid_parttable_get_offset(blkid_parttable tab);
+extern blkid_partition blkid_parttable_get_parent(blkid_parttable tab);
+
+/*
+ * NAME=value low-level interface
+ */
+extern int blkid_do_probe(blkid_probe pr);
+extern int blkid_do_safeprobe(blkid_probe pr);
+extern int blkid_do_fullprobe(blkid_probe pr);
+
+extern int blkid_probe_numof_values(blkid_probe pr);
+extern int blkid_probe_get_value(blkid_probe pr, int num, const char **name,
+                        const char **data, size_t *len);
+extern int blkid_probe_lookup_value(blkid_probe pr, const char *name,
+                        const char **data, size_t *len);
+extern int blkid_probe_has_value(blkid_probe pr, const char *name);
+
+extern int blkid_do_wipe(blkid_probe pr, int dryrun);
+
+/*
+ * Deprecated functions/macros
+ */
+#ifndef BLKID_DISABLE_DEPRECATED
+
+#define BLKID_PROBREQ_LABEL     BLKID_SUBLKS_LABEL
+#define BLKID_PROBREQ_LABELRAW  BLKID_SUBLKS_LABELRAW
+#define BLKID_PROBREQ_UUID      BLKID_SUBLKS_UUID
+#define BLKID_PROBREQ_UUIDRAW   BLKID_SUBLKS_UUIDRAW
+#define BLKID_PROBREQ_TYPE      BLKID_SUBLKS_TYPE
+#define BLKID_PROBREQ_SECTYPE   BLKID_SUBLKS_SECTYPE
+#define BLKID_PROBREQ_USAGE     BLKID_SUBLKS_USAGE
+#define BLKID_PROBREQ_VERSION   BLKID_SUBLKS_VERSION
+
+extern int blkid_probe_set_request(blkid_probe pr, int flags);
+extern int blkid_probe_filter_usage(blkid_probe pr, int flag, int usage);
+extern int blkid_probe_filter_types(blkid_probe pr, int flag, char *names[]);
+extern int blkid_probe_invert_filter(blkid_probe pr);
+extern int blkid_probe_reset_filter(blkid_probe pr);
+
+#endif /* BLKID_DISABLE_DEPRECATED */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _BLKID_BLKID_H */
diff --git a/libblkid-tiny/blkidP.h b/libblkid-tiny/blkidP.h
new file mode 100644 (file)
index 0000000..0f372a5
--- /dev/null
@@ -0,0 +1,421 @@
+/*
+ * blkidP.h - Internal interfaces for libblkid
+ *
+ * Copyright (C) 2001 Andreas Dilger
+ * Copyright (C) 2003 Theodore Ts'o
+ *
+ * %Begin-Header%
+ * This file may be redistributed under the terms of the
+ * GNU Lesser General Public License.
+ * %End-Header%
+ */
+
+#ifndef _BLKID_BLKIDP_H
+#define _BLKID_BLKIDP_H
+
+
+#define CONFIG_BLKID_DEBUG 1
+
+#include <sys/types.h>
+#include <dirent.h>
+#include <sys/stat.h>
+#include <stdio.h>
+#include <stdarg.h>
+#include <stdint.h>
+
+#include "c.h"
+#include "bitops.h"    /* $(top_srcdir)/include/ */
+#include "blkdev.h"
+
+#include "blkid.h"
+#include <libubox/list.h>
+
+/*
+ * This describes the attributes of a specific device.
+ * We can traverse all of the tags by bid_tags (linking to the tag bit_names).
+ * The bid_label and bid_uuid fields are shortcuts to the LABEL and UUID tag
+ * values, if they exist.
+ */
+struct blkid_struct_dev
+{
+       struct list_head        bid_devs;       /* All devices in the cache */
+       struct list_head        bid_tags;       /* All tags for this device */
+       blkid_cache             bid_cache;      /* Dev belongs to this cache */
+       char                    *bid_name;      /* Device inode pathname */
+       char                    *bid_type;      /* Preferred device TYPE */
+       int                     bid_pri;        /* Device priority */
+       dev_t                   bid_devno;      /* Device major/minor number */
+       time_t                  bid_time;       /* Last update time of device */
+       suseconds_t             bid_utime;      /* Last update time (microseconds) */
+       unsigned int            bid_flags;      /* Device status bitflags */
+       char                    *bid_label;     /* Shortcut to device LABEL */
+       char                    *bid_uuid;      /* Shortcut to binary UUID */
+};
+
+#define BLKID_BID_FL_VERIFIED  0x0001  /* Device data validated from disk */
+#define BLKID_BID_FL_INVALID   0x0004  /* Device is invalid */
+#define BLKID_BID_FL_REMOVABLE 0x0008  /* Device added by blkid_probe_all_removable() */
+
+/*
+ * Each tag defines a NAME=value pair for a particular device.  The tags
+ * are linked via bit_names for a single device, so that traversing the
+ * names list will get you a list of all tags associated with a device.
+ * They are also linked via bit_values for all devices, so one can easily
+ * search all tags with a given NAME for a specific value.
+ */
+struct blkid_struct_tag
+{
+       struct list_head        bit_tags;       /* All tags for this device */
+       struct list_head        bit_names;      /* All tags with given NAME */
+       char                    *bit_name;      /* NAME of tag (shared) */
+       char                    *bit_val;       /* value of tag */
+       blkid_dev               bit_dev;        /* pointer to device */
+};
+typedef struct blkid_struct_tag *blkid_tag;
+
+/*
+ * Chain IDs
+ */
+enum {
+       BLKID_CHAIN_SUBLKS,     /* FS/RAID superblocks (enabled by default) */
+       BLKID_CHAIN_TOPLGY,     /* Block device topology */
+       BLKID_CHAIN_PARTS,      /* Partition tables */
+
+       BLKID_NCHAINS           /* number of chains */
+};
+
+struct blkid_chain {
+       const struct blkid_chaindrv *driver;    /* chain driver */
+
+       int             enabled;        /* boolean */
+       int             flags;          /* BLKID_<chain>_* */
+       int             binary;         /* boolean */
+       int             idx;            /* index of the current prober (or -1) */
+       unsigned long   *fltr;          /* filter or NULL */
+       void            *data;          /* private chain data or NULL */
+};
+
+/*
+ * Chain driver
+ */
+struct blkid_chaindrv {
+       const size_t    id;             /* BLKID_CHAIN_* */
+       const char      *name;          /* name of chain (for debug purpose) */
+       const int       dflt_flags;     /* default chain flags */
+       const int       dflt_enabled;   /* default enabled boolean */
+       int             has_fltr;       /* boolean */
+
+       const struct blkid_idinfo **idinfos; /* description of probing functions */
+       const size_t    nidinfos;       /* number of idinfos */
+
+       /* driver operations */
+       int             (*probe)(blkid_probe, struct blkid_chain *);
+       int             (*safeprobe)(blkid_probe, struct blkid_chain *);
+       void            (*free_data)(blkid_probe, void *);
+};
+
+/*
+ * Low-level probe result
+ */
+#define BLKID_PROBVAL_BUFSIZ   64
+
+#define BLKID_NVALS_SUBLKS     14
+#define BLKID_NVALS_TOPLGY     5
+#define BLKID_NVALS_PARTS      13
+
+/* Max number of all values in probing result */
+#define BLKID_NVALS             (BLKID_NVALS_SUBLKS + \
+                                BLKID_NVALS_TOPLGY + \
+                                BLKID_NVALS_PARTS)
+
+struct blkid_prval
+{
+       const char      *name;                  /* value name */
+       unsigned char   data[BLKID_PROBVAL_BUFSIZ]; /* value data */
+       size_t          len;                    /* length of value data */
+
+       struct blkid_chain      *chain;         /* owner */
+};
+
+/*
+ * Filesystem / Raid magic strings
+ */
+/*
+ * Filesystem / Raid description
+ */
+#define BLKID_NONE_MAGIC       {{ NULL }}
+
+/*
+ * tolerant FS - can share the same device with more filesystems (e.g. typical
+ * on CD-ROMs). We need this flag to detect ambivalent results (e.g. valid fat
+ * and valid linux swap on the same device).
+ */
+#define BLKID_IDINFO_TOLERANT  (1 << 1)
+
+struct blkid_bufinfo {
+       unsigned char           *data;
+       blkid_loff_t            off;
+       blkid_loff_t            len;
+       struct list_head        bufs;   /* list of buffers */
+};
+
+/* private flags library flags */
+#define BLKID_FL_PRIVATE_FD    (1 << 1)        /* see blkid_new_probe_from_filename() */
+#define BLKID_FL_TINY_DEV      (1 << 2)        /* <= 1.47MiB (floppy or so) */
+#define BLKID_FL_CDROM_DEV     (1 << 3)        /* is a CD/DVD drive */
+
+/* private per-probing flags */
+#define BLKID_PROBE_FL_IGNORE_PT (1 << 1)      /* ignore partition table */
+
+extern blkid_probe blkid_clone_probe(blkid_probe parent);
+extern blkid_probe blkid_probe_get_wholedisk_probe(blkid_probe pr);
+
+/*
+ * Evaluation methods (for blkid_eval_* API)
+ */
+enum {
+       BLKID_EVAL_UDEV = 0,
+       BLKID_EVAL_SCAN,
+
+       __BLKID_EVAL_LAST
+};
+
+/*
+ * Library config options
+ */
+struct blkid_config {
+       int eval[__BLKID_EVAL_LAST];    /* array with EVALUATION=<udev,cache> options */
+       int nevals;                     /* number of elems in eval array */
+       int uevent;                     /* SEND_UEVENT=<yes|not> option */
+       char *cachefile;                /* CACHE_FILE=<path> option */
+};
+
+extern struct blkid_config *blkid_read_config(const char *filename);
+extern void blkid_free_config(struct blkid_config *conf);
+
+/*
+ * Minimum number of seconds between device probes, even when reading
+ * from the cache.  This is to avoid re-probing all devices which were
+ * just probed by another program that does not share the cache.
+ */
+#define BLKID_PROBE_MIN                2
+
+/*
+ * Time in seconds an entry remains verified in the in-memory cache
+ * before being reverified (in case of long-running processes that
+ * keep a cache in memory and continue to use it for a long time).
+ */
+#define BLKID_PROBE_INTERVAL   200
+
+/* This describes an entire blkid cache file and probed devices.
+ * We can traverse all of the found devices via bic_list.
+ * We can traverse all of the tag types by bic_tags, which hold empty tags
+ * for each tag type.  Those tags can be used as list_heads for iterating
+ * through all devices with a specific tag type (e.g. LABEL).
+ */
+struct blkid_struct_cache
+{
+       struct list_head        bic_devs;       /* List head of all devices */
+       struct list_head        bic_tags;       /* List head of all tag types */
+       time_t                  bic_time;       /* Last probe time */
+       time_t                  bic_ftime;      /* Mod time of the cachefile */
+       unsigned int            bic_flags;      /* Status flags of the cache */
+       char                    *bic_filename;  /* filename of cache */
+       blkid_probe             probe;          /* low-level probing stuff */
+};
+
+#define BLKID_BIC_FL_PROBED    0x0002  /* We probed /proc/partition devices */
+#define BLKID_BIC_FL_CHANGED   0x0004  /* Cache has changed from disk */
+
+extern char *blkid_strdup(const char *s);
+extern char *blkid_strndup(const char *s, const int length);
+extern char *blkid_strconcat(const char *a, const char *b, const char *c);
+
+/* config file */
+#define BLKID_CONFIG_FILE      "/etc/blkid.conf"
+
+/* cache file on systemds with /run */
+#define BLKID_RUNTIME_TOPDIR   "/run"
+#define BLKID_RUNTIME_DIR      BLKID_RUNTIME_TOPDIR "/blkid"
+#define BLKID_CACHE_FILE       BLKID_RUNTIME_DIR "/blkid.tab"
+
+/* old systems */
+#define BLKID_CACHE_FILE_OLD   "/etc/blkid.tab"
+
+#define BLKID_ERR_IO    5
+#define BLKID_ERR_PROC  9
+#define BLKID_ERR_MEM  12
+#define BLKID_ERR_CACHE        14
+#define BLKID_ERR_DEV  19
+#define BLKID_ERR_PARAM        22
+#define BLKID_ERR_BIG  27
+
+/*
+ * Priority settings for different types of devices
+ */
+#define BLKID_PRI_UBI  50
+#define BLKID_PRI_DM   40
+#define BLKID_PRI_EVMS 30
+#define BLKID_PRI_LVM  20
+#define BLKID_PRI_MD   10
+
+#if defined(TEST_PROGRAM) && !defined(CONFIG_BLKID_DEBUG)
+#define CONFIG_BLKID_DEBUG
+#endif
+
+#define DEBUG_CACHE    0x0001
+#define DEBUG_DUMP     0x0002
+#define DEBUG_DEV      0x0004
+#define DEBUG_DEVNAME  0x0008
+#define DEBUG_DEVNO    0x0010
+#define DEBUG_PROBE    0x0020
+#define DEBUG_READ     0x0040
+#define DEBUG_RESOLVE  0x0080
+#define DEBUG_SAVE     0x0100
+#define DEBUG_TAG      0x0200
+#define DEBUG_LOWPROBE 0x0400
+#define DEBUG_CONFIG   0x0800
+#define DEBUG_EVALUATE 0x1000
+#define DEBUG_INIT     0x8000
+#define DEBUG_ALL      0xFFFF
+
+#ifdef CONFIG_BLKID_DEBUG
+extern int blkid_debug_mask;
+extern void blkid_init_debug(int mask);
+extern void blkid_debug_dump_dev(blkid_dev dev);
+extern void blkid_debug_dump_tag(blkid_tag tag);
+
+#define DBG(m,x)       if ((m) & blkid_debug_mask) x;
+
+#else /* !CONFIG_BLKID_DEBUG */
+#define DBG(m,x)
+#define blkid_init_debug(x)
+#endif /* CONFIG_BLKID_DEBUG */
+
+/* devno.c */
+struct dir_list {
+       char    *name;
+       struct dir_list *next;
+};
+extern void blkid__scan_dir(char *, dev_t, struct dir_list **, char **);
+extern int blkid_driver_has_major(const char *drvname, int major);
+
+/* lseek.c */
+extern blkid_loff_t blkid_llseek(int fd, blkid_loff_t offset, int whence);
+
+/* read.c */
+extern void blkid_read_cache(blkid_cache cache);
+
+/* save.c */
+extern int blkid_flush_cache(blkid_cache cache);
+
+/* cache */
+extern char *blkid_safe_getenv(const char *arg);
+extern char *blkid_get_cache_filename(struct blkid_config *conf);
+
+/*
+ * Functions to create and find a specific tag type: tag.c
+ */
+extern void blkid_free_tag(blkid_tag tag);
+extern blkid_tag blkid_find_tag_dev(blkid_dev dev, const char *type);
+extern int blkid_set_tag(blkid_dev dev, const char *name,
+                        const char *value, const int vlength);
+
+/*
+ * Functions to create and find a specific tag type: dev.c
+ */
+extern blkid_dev blkid_new_dev(void);
+extern void blkid_free_dev(blkid_dev dev);
+
+/* probe.c */
+extern int blkid_probe_is_tiny(blkid_probe pr);
+extern int blkid_probe_is_cdrom(blkid_probe pr);
+extern unsigned char *blkid_probe_get_buffer(blkid_probe pr,
+                                blkid_loff_t off, blkid_loff_t len);
+
+extern unsigned char *blkid_probe_get_sector(blkid_probe pr, unsigned int sector);
+
+extern int blkid_probe_get_dimension(blkid_probe pr,
+                       blkid_loff_t *off, blkid_loff_t *size);
+
+extern int blkid_probe_set_dimension(blkid_probe pr,
+                       blkid_loff_t off, blkid_loff_t size);
+
+extern int blkid_probe_get_idmag(blkid_probe pr, const struct blkid_idinfo *id,
+                       blkid_loff_t *offset, const struct blkid_idmag **res);
+
+/* returns superblok according to 'struct blkid_idmag' */
+#define blkid_probe_get_sb(_pr, _mag, type) \
+                       ((type *) blkid_probe_get_buffer((_pr),\
+                                       (_mag)->kboff << 10, sizeof(type)))
+
+extern blkid_partlist blkid_probe_get_partlist(blkid_probe pr);
+
+extern int blkid_probe_is_covered_by_pt(blkid_probe pr,
+                                       blkid_loff_t offset, blkid_loff_t size);
+
+extern void blkid_probe_chain_reset_vals(blkid_probe pr, struct blkid_chain *chn);
+extern int blkid_probe_chain_copy_vals(blkid_probe pr, struct blkid_chain *chn,
+                                       struct blkid_prval *vals, int nvals);
+extern struct blkid_prval *blkid_probe_assign_value(blkid_probe pr, const char *name);
+extern int blkid_probe_reset_last_value(blkid_probe pr);
+extern void blkid_probe_append_vals(blkid_probe pr, struct blkid_prval *vals, int nvals);
+
+extern struct blkid_chain *blkid_probe_get_chain(blkid_probe pr);
+
+extern struct blkid_prval *__blkid_probe_get_value(blkid_probe pr, int num);
+extern struct blkid_prval *__blkid_probe_lookup_value(blkid_probe pr, const char *name);
+
+extern unsigned long *blkid_probe_get_filter(blkid_probe pr, int chain, int create);
+extern int __blkid_probe_invert_filter(blkid_probe pr, int chain);
+extern int __blkid_probe_reset_filter(blkid_probe pr, int chain);
+extern int __blkid_probe_filter_types(blkid_probe pr, int chain, int flag, char *names[]);
+
+extern void *blkid_probe_get_binary_data(blkid_probe pr, struct blkid_chain *chn);
+
+extern int blkid_probe_set_value(blkid_probe pr, const char *name,
+                unsigned char *data, size_t len);
+extern int blkid_probe_vsprintf_value(blkid_probe pr, const char *name,
+                const char *fmt, va_list ap);
+extern int blkid_probe_sprintf_value(blkid_probe pr, const char *name,
+                const char *fmt, ...);
+extern int blkid_probe_set_magic(blkid_probe pr, blkid_loff_t offset,
+               size_t len, unsigned char *magic);
+
+extern void blkid_unparse_uuid(const unsigned char *uuid, char *str, size_t len);
+extern size_t blkid_rtrim_whitespace(unsigned char *str);
+
+extern void blkid_probe_set_wiper(blkid_probe pr, blkid_loff_t off,
+                                 blkid_loff_t size);
+extern int blkid_probe_is_wiped(blkid_probe pr, struct blkid_chain **chn,
+                               blkid_loff_t off, blkid_loff_t size);
+extern void blkid_probe_use_wiper(blkid_probe pr, blkid_loff_t off, blkid_loff_t size);
+
+/* filter bitmap macros */
+#define blkid_bmp_wordsize             (8 * sizeof(unsigned long))
+#define blkid_bmp_idx_bit(item)                (1UL << ((item) % blkid_bmp_wordsize))
+#define blkid_bmp_idx_byte(item)       ((item) / blkid_bmp_wordsize)
+
+#define blkid_bmp_set_item(bmp, item)  \
+               ((bmp)[ blkid_bmp_idx_byte(item) ] |= blkid_bmp_idx_bit(item))
+
+#define blkid_bmp_unset_item(bmp, item)        \
+               ((bmp)[ blkid_bmp_idx_byte(item) ] &= ~blkid_bmp_idx_bit(item))
+
+#define blkid_bmp_get_item(bmp, item)  \
+               ((bmp)[ blkid_bmp_idx_byte(item) ] & blkid_bmp_idx_bit(item))
+
+#define blkid_bmp_nwords(max_items) \
+               (((max_items) + blkid_bmp_wordsize) / blkid_bmp_wordsize)
+
+#define blkid_bmp_nbytes(max_items) \
+               (blkid_bmp_nwords(max_items) * sizeof(unsigned long))
+
+/* encode.c */
+extern size_t blkid_encode_to_utf8(int enc, unsigned char *dest, size_t len,
+                       const unsigned char *src, size_t count);
+
+#define BLKID_ENC_UTF16BE      0
+#define BLKID_ENC_UTF16LE      1
+
+#endif /* _BLKID_BLKIDP_H */
diff --git a/libblkid-tiny/c.h b/libblkid-tiny/c.h
new file mode 100644 (file)
index 0000000..8c8db73
--- /dev/null
@@ -0,0 +1,247 @@
+/*
+ * Fundamental C definitions.
+ */
+
+#ifndef UTIL_LINUX_C_H
+#define UTIL_LINUX_C_H
+
+#include <limits.h>
+#include <stddef.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <stdarg.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+
+#ifdef HAVE_ERR_H
+# include <err.h>
+#endif
+
+/*
+ * Compiler specific stuff
+ */
+#ifndef __GNUC_PREREQ
+# if defined __GNUC__ && defined __GNUC_MINOR__
+#  define __GNUC_PREREQ(maj, min) \
+       ((__GNUC__ << 16) + __GNUC_MINOR__ >= ((maj) << 16) + (min))
+# else
+#  define __GNUC_PREREQ(maj, min) 0
+# endif
+#endif
+
+#ifdef __GNUC__
+
+/* &a[0] degrades to a pointer: a different type from an array */
+# define __must_be_array(a) \
+       UL_BUILD_BUG_ON_ZERO(__builtin_types_compatible_p(__typeof__(a), __typeof__(&a[0])))
+
+# define ignore_result(x) ({ \
+       __typeof__(x) __dummy __attribute__((__unused__)) = (x); (void) __dummy; \
+})
+
+#else /* !__GNUC__ */
+# define __must_be_array(a)    0
+# define __attribute__(_arg_)
+# define ignore_result(x) ((void) (x))
+#endif /* !__GNUC__ */
+
+/*
+ * Function attributes
+ */
+#ifndef __ul_alloc_size
+# if __GNUC_PREREQ (4, 3)
+#  define __ul_alloc_size(s) __attribute__((alloc_size(s)))
+# else
+#  define __ul_alloc_size(s)
+# endif
+#endif
+
+#ifndef __ul_calloc_size
+# if __GNUC_PREREQ (4, 3)
+#  define __ul_calloc_size(n, s) __attribute__((alloc_size(n, s)))
+# else
+#  define __ul_calloc_size(n, s)
+# endif
+#endif
+
+/* Force a compilation error if condition is true, but also produce a
+ * result (of value 0 and type size_t), so the expression can be used
+ * e.g. in a structure initializer (or where-ever else comma expressions
+ * aren't permitted).
+ */
+#define UL_BUILD_BUG_ON_ZERO(e) (sizeof(struct { int:-!!(e); }))
+#define BUILD_BUG_ON_NULL(e) ((void *)sizeof(struct { int:-!!(e); }))
+
+#ifndef ARRAY_SIZE
+# define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0]) + __must_be_array(arr))
+#endif
+
+#ifndef PATH_MAX
+# define PATH_MAX 4096
+#endif
+
+#ifndef TRUE
+# define TRUE 1
+#endif
+
+#ifndef FALSE
+# define FALSE 0
+#endif
+
+#ifndef min
+# define min(x, y) ({                          \
+       __typeof__(x) _min1 = (x);              \
+       __typeof__(y) _min2 = (y);              \
+       (void) (&_min1 == &_min2);              \
+       _min1 < _min2 ? _min1 : _min2; })
+#endif
+
+#ifndef max
+# define max(x, y) ({                          \
+       __typeof__(x) _max1 = (x);              \
+       __typeof__(y) _max2 = (y);              \
+       (void) (&_max1 == &_max2);              \
+       _max1 > _max2 ? _max1 : _max2; })
+#endif
+
+#ifndef offsetof
+#define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER)
+#endif
+
+#ifndef container_of
+#define container_of(ptr, type, member) ({                       \
+       const __typeof__( ((type *)0)->member ) *__mptr = (ptr); \
+       (type *)( (char *)__mptr - offsetof(type,member) );})
+#endif
+
+#ifndef HAVE_PROGRAM_INVOCATION_SHORT_NAME
+# ifdef HAVE___PROGNAME
+extern char *__progname;
+#  define program_invocation_short_name __progname
+# else
+#  ifdef HAVE_GETEXECNAME
+#   define program_invocation_short_name \
+               prog_inv_sh_nm_from_file(getexecname(), 0)
+#  else
+#   define program_invocation_short_name \
+               prog_inv_sh_nm_from_file(__FILE__, 1)
+#  endif
+static char prog_inv_sh_nm_buf[256];
+static inline char *
+prog_inv_sh_nm_from_file(char *f, char stripext)
+{
+       char *t;
+
+       if ((t = strrchr(f, '/')) != NULL)
+               t++;
+       else
+               t = f;
+
+       strncpy(prog_inv_sh_nm_buf, t, sizeof(prog_inv_sh_nm_buf) - 1);
+       prog_inv_sh_nm_buf[sizeof(prog_inv_sh_nm_buf) - 1] = '\0';
+
+       if (stripext && (t = strrchr(prog_inv_sh_nm_buf, '.')) != NULL)
+               *t = '\0';
+
+       return prog_inv_sh_nm_buf;
+}
+# endif
+#endif
+
+
+#ifndef HAVE_ERR_H
+static inline void
+errmsg(char doexit, int excode, char adderr, const char *fmt, ...)
+{
+       fprintf(stderr, "%s: ", program_invocation_short_name);
+       if (fmt != NULL) {
+               va_list argp;
+               va_start(argp, fmt);
+               vfprintf(stderr, fmt, argp);
+               va_end(argp);
+               if (adderr)
+                       fprintf(stderr, ": ");
+       }
+       if (adderr)
+               fprintf(stderr, "%m");
+       fprintf(stderr, "\n");
+       if (doexit)
+               exit(excode);
+}
+
+#ifndef HAVE_ERR
+# define err(E, FMT...) errmsg(1, E, 1, FMT)
+#endif
+
+#ifndef HAVE_ERRX
+# define errx(E, FMT...) errmsg(1, E, 0, FMT)
+#endif
+
+#ifndef HAVE_WARN
+# define warn(FMT...) errmsg(0, 0, 1, FMT)
+#endif
+
+#ifndef HAVE_WARNX
+# define warnx(FMT...) errmsg(0, 0, 0, FMT)
+#endif
+#endif /* !HAVE_ERR_H */
+
+
+static inline __attribute__((const)) int is_power_of_2(unsigned long num)
+{
+       return (num != 0 && ((num & (num - 1)) == 0));
+}
+
+#ifndef HAVE_LOFF_T
+typedef int64_t loff_t;
+#endif
+
+#if !defined(HAVE_DIRFD) && (!defined(HAVE_DECL_DIRFD) || HAVE_DECL_DIRFD == 0) && defined(HAVE_DIR_DD_FD)
+#include <sys/types.h>
+#include <dirent.h>
+static inline int dirfd(DIR *d)
+{
+       return d->dd_fd;
+}
+#endif
+
+/*
+ * Fallback defines for old versions of glibc
+ */
+#include <fcntl.h>
+#ifndef O_CLOEXEC
+#define O_CLOEXEC 0
+#endif
+
+#ifndef AI_ADDRCONFIG
+#define AI_ADDRCONFIG 0x0020
+#endif
+
+#ifndef IUTF8
+#define IUTF8 0040000
+#endif
+
+/*
+ * Constant strings for usage() functions. For more info see
+ * Documentation/howto-usage-function.txt and sys-utils/arch.c
+ */
+#define USAGE_HEADER     _("\nUsage:\n")
+#define USAGE_OPTIONS    _("\nOptions:\n")
+#define USAGE_SEPARATOR  _("\n")
+#define USAGE_HELP       _(" -h, --help     display this help and exit\n")
+#define USAGE_VERSION    _(" -V, --version  output version information and exit\n")
+#define USAGE_MAN_TAIL(_man)   _("\nFor more details see %s.\n"), _man
+
+#define UTIL_LINUX_VERSION _("%s from %s\n"), program_invocation_short_name, PACKAGE_STRING
+
+/*
+ * scanf modifiers for "strings allocation"
+ */
+#ifdef HAVE_SCANF_MS_MODIFIER
+#define UL_SCNsA       "%ms"
+#elif defined(HAVE_SCANF_AS_MODIFIER)
+#define UL_SCNsA       "%as"
+#endif
+
+#endif /* UTIL_LINUX_C_H */
diff --git a/libblkid-tiny/ext.c b/libblkid-tiny/ext.c
new file mode 100644 (file)
index 0000000..687127d
--- /dev/null
@@ -0,0 +1,531 @@
+/*
+ * Copyright (C) 1999, 2001 by Andries Brouwer
+ * Copyright (C) 1999, 2000, 2003 by Theodore Ts'o
+ * Copyright (C) 2008 Karel Zak <kzak@redhat.com>
+ *
+ * This file may be redistributed under the terms of the
+ * GNU Lesser General Public License.
+ */
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+#include <errno.h>
+#include <ctype.h>
+#include <stdint.h>
+#ifdef __linux__
+#include <sys/utsname.h>
+#endif
+#include <time.h>
+
+#include "linux_version.h"
+#include "superblocks.h"
+
+struct ext2_super_block {
+       uint32_t                s_inodes_count;
+       uint32_t                s_blocks_count;
+       uint32_t                s_r_blocks_count;
+       uint32_t                s_free_blocks_count;
+       uint32_t                s_free_inodes_count;
+       uint32_t                s_first_data_block;
+       uint32_t                s_log_block_size;
+       uint32_t                s_dummy3[7];
+       unsigned char           s_magic[2];
+       uint16_t                s_state;
+       uint16_t                s_errors;
+       uint16_t                s_minor_rev_level;
+       uint32_t                s_lastcheck;
+       uint32_t                s_checkinterval;
+       uint32_t                s_creator_os;
+       uint32_t                s_rev_level;
+       uint16_t                s_def_resuid;
+       uint16_t                s_def_resgid;
+       uint32_t                s_first_ino;
+       uint16_t                s_inode_size;
+       uint16_t                s_block_group_nr;
+       uint32_t                s_feature_compat;
+       uint32_t                s_feature_incompat;
+       uint32_t                s_feature_ro_compat;
+       unsigned char           s_uuid[16];
+       char                    s_volume_name[16];
+       char                    s_last_mounted[64];
+       uint32_t                s_algorithm_usage_bitmap;
+       uint8_t                 s_prealloc_blocks;
+       uint8_t                 s_prealloc_dir_blocks;
+       uint16_t                s_reserved_gdt_blocks;
+       uint8_t                 s_journal_uuid[16];
+       uint32_t                s_journal_inum;
+       uint32_t                s_journal_dev;
+       uint32_t                s_last_orphan;
+       uint32_t                s_hash_seed[4];
+       uint8_t                 s_def_hash_version;
+       uint8_t                 s_jnl_backup_type;
+       uint16_t                s_reserved_word_pad;
+       uint32_t                s_default_mount_opts;
+       uint32_t                s_first_meta_bg;
+       uint32_t                s_mkfs_time;
+       uint32_t                s_jnl_blocks[17];
+       uint32_t                s_blocks_count_hi;
+       uint32_t                s_r_blocks_count_hi;
+       uint32_t                s_free_blocks_hi;
+       uint16_t                s_min_extra_isize;
+       uint16_t                s_want_extra_isize;
+       uint32_t                s_flags;
+       uint16_t                s_raid_stride;
+       uint16_t                s_mmp_interval;
+       uint64_t                s_mmp_block;
+       uint32_t                s_raid_stripe_width;
+       uint32_t                s_reserved[163];
+} __attribute__((packed));
+
+/* magic string */
+#define EXT_SB_MAGIC                           "\123\357"
+/* supper block offset */
+#define EXT_SB_OFF                             0x400
+/* supper block offset in kB */
+#define EXT_SB_KBOFF                           (EXT_SB_OFF >> 10)
+/* magic string offset within super block */
+#define EXT_MAG_OFF                            0x38
+
+
+
+/* for s_flags */
+#define EXT2_FLAGS_TEST_FILESYS                0x0004
+
+/* for s_feature_compat */
+#define EXT3_FEATURE_COMPAT_HAS_JOURNAL                0x0004
+
+/* for s_feature_ro_compat */
+#define EXT2_FEATURE_RO_COMPAT_SPARSE_SUPER    0x0001
+#define EXT2_FEATURE_RO_COMPAT_LARGE_FILE      0x0002
+#define EXT2_FEATURE_RO_COMPAT_BTREE_DIR       0x0004
+#define EXT4_FEATURE_RO_COMPAT_HUGE_FILE       0x0008
+#define EXT4_FEATURE_RO_COMPAT_GDT_CSUM                0x0010
+#define EXT4_FEATURE_RO_COMPAT_DIR_NLINK       0x0020
+#define EXT4_FEATURE_RO_COMPAT_EXTRA_ISIZE     0x0040
+
+/* for s_feature_incompat */
+#define EXT2_FEATURE_INCOMPAT_FILETYPE         0x0002
+#define EXT3_FEATURE_INCOMPAT_RECOVER          0x0004
+#define EXT3_FEATURE_INCOMPAT_JOURNAL_DEV      0x0008
+#define EXT2_FEATURE_INCOMPAT_META_BG          0x0010
+#define EXT4_FEATURE_INCOMPAT_EXTENTS          0x0040 /* extents support */
+#define EXT4_FEATURE_INCOMPAT_64BIT            0x0080
+#define EXT4_FEATURE_INCOMPAT_MMP              0x0100
+#define EXT4_FEATURE_INCOMPAT_FLEX_BG          0x0200
+
+#define EXT2_FEATURE_RO_COMPAT_SUPP    (EXT2_FEATURE_RO_COMPAT_SPARSE_SUPER| \
+                                        EXT2_FEATURE_RO_COMPAT_LARGE_FILE| \
+                                        EXT2_FEATURE_RO_COMPAT_BTREE_DIR)
+#define EXT2_FEATURE_INCOMPAT_SUPP     (EXT2_FEATURE_INCOMPAT_FILETYPE| \
+                                        EXT2_FEATURE_INCOMPAT_META_BG)
+#define EXT2_FEATURE_INCOMPAT_UNSUPPORTED      ~EXT2_FEATURE_INCOMPAT_SUPP
+#define EXT2_FEATURE_RO_COMPAT_UNSUPPORTED     ~EXT2_FEATURE_RO_COMPAT_SUPP
+
+#define EXT3_FEATURE_RO_COMPAT_SUPP    (EXT2_FEATURE_RO_COMPAT_SPARSE_SUPER| \
+                                        EXT2_FEATURE_RO_COMPAT_LARGE_FILE| \
+                                        EXT2_FEATURE_RO_COMPAT_BTREE_DIR)
+#define EXT3_FEATURE_INCOMPAT_SUPP     (EXT2_FEATURE_INCOMPAT_FILETYPE| \
+                                        EXT3_FEATURE_INCOMPAT_RECOVER| \
+                                        EXT2_FEATURE_INCOMPAT_META_BG)
+#define EXT3_FEATURE_INCOMPAT_UNSUPPORTED      ~EXT3_FEATURE_INCOMPAT_SUPP
+#define EXT3_FEATURE_RO_COMPAT_UNSUPPORTED     ~EXT3_FEATURE_RO_COMPAT_SUPP
+
+/*
+ * Check to see if a filesystem is in /proc/filesystems.
+ * Returns 1 if found, 0 if not
+ */
+static int fs_proc_check(const char *fs_name)
+{
+       FILE    *f;
+       char    buf[80], *cp, *t;
+
+       f = fopen("/proc/filesystems", "r");
+       if (!f)
+               return 0;
+       while (!feof(f)) {
+               if (!fgets(buf, sizeof(buf), f))
+                       break;
+               cp = buf;
+               if (!isspace(*cp)) {
+                       while (*cp && !isspace(*cp))
+                               cp++;
+               }
+               while (*cp && isspace(*cp))
+                       cp++;
+               if ((t = strchr(cp, '\n')) != NULL)
+                       *t = 0;
+               if ((t = strchr(cp, '\t')) != NULL)
+                       *t = 0;
+               if ((t = strchr(cp, ' ')) != NULL)
+                       *t = 0;
+               if (!strcmp(fs_name, cp)) {
+                       fclose(f);
+                       return 1;
+               }
+       }
+       fclose(f);
+       return (0);
+}
+
+/*
+ * Check to see if a filesystem is available as a module
+ * Returns 1 if found, 0 if not
+ */
+static int check_for_modules(const char *fs_name)
+{
+#ifdef __linux__
+       struct utsname  uts;
+       FILE            *f;
+       char            buf[1024], *cp;
+       int             namesz;
+
+       if (uname(&uts))
+               return 0;
+       snprintf(buf, sizeof(buf), "/lib/modules/%s/modules.dep", uts.release);
+
+       f = fopen(buf, "r");
+       if (!f)
+               return 0;
+
+       namesz = strlen(fs_name);
+
+       while (!feof(f)) {
+               if (!fgets(buf, sizeof(buf), f))
+                       break;
+               if ((cp = strchr(buf, ':')) != NULL)
+                       *cp = 0;
+               else
+                       continue;
+               if ((cp = strrchr(buf, '/')) == NULL)
+                       continue;
+               cp++;
+
+               if (!strncmp(cp, fs_name, namesz) &&
+                   (!strcmp(cp + namesz, ".ko") ||
+                    !strcmp(cp + namesz, ".ko.gz"))) {
+                       fclose(f);
+                       return 1;
+               }
+       }
+       fclose(f);
+#endif /* __linux__ */
+       return 0;
+}
+
+/*
+ * Starting in 2.6.29, ext4 can be used to support filesystems
+ * without a journal.
+ */
+#define EXT4_SUPPORTS_EXT2 KERNEL_VERSION(2, 6, 29)
+
+static int system_supports_ext2(void)
+{
+       static time_t   last_check = 0;
+       static int      ret = -1;
+       time_t          now = time(0);
+
+       if (ret != -1 || (now - last_check) < 5)
+               return ret;
+       last_check = now;
+       ret = (fs_proc_check("ext2") || check_for_modules("ext2"));
+       return ret;
+}
+
+static int system_supports_ext4(void)
+{
+       static time_t   last_check = 0;
+       static int      ret = -1;
+       time_t          now = time(0);
+
+       if (ret != -1 || (now - last_check) < 5)
+               return ret;
+       last_check = now;
+       ret = (fs_proc_check("ext4") || check_for_modules("ext4"));
+       return ret;
+}
+
+static int system_supports_ext4dev(void)
+{
+       static time_t   last_check = 0;
+       static int      ret = -1;
+       time_t          now = time(0);
+
+       if (ret != -1 || (now - last_check) < 5)
+               return ret;
+       last_check = now;
+       ret = (fs_proc_check("ext4dev") || check_for_modules("ext4dev"));
+       return ret;
+}
+/*
+ * reads superblock and returns:
+ *     fc = feature_compat
+ *     fi = feature_incompat
+ *     frc = feature_ro_compat
+ */
+static struct ext2_super_block *ext_get_super(
+               blkid_probe pr, uint32_t *fc, uint32_t *fi, uint32_t *frc)
+{
+       struct ext2_super_block *es;
+
+       es = (struct ext2_super_block *)
+                       blkid_probe_get_buffer(pr, EXT_SB_OFF, 0x200);
+       if (!es)
+               return NULL;
+       if (fc)
+               *fc = le32_to_cpu(es->s_feature_compat);
+       if (fi)
+               *fi = le32_to_cpu(es->s_feature_incompat);
+       if (frc)
+               *frc = le32_to_cpu(es->s_feature_ro_compat);
+
+       return es;
+}
+
+static void ext_get_info(blkid_probe pr, int ver, struct ext2_super_block *es)
+{
+       //struct blkid_chain *chn = blkid_probe_get_chain(pr);
+
+       DBG(DEBUG_PROBE, printf("ext2_sb.compat = %08X:%08X:%08X\n",
+                  le32_to_cpu(es->s_feature_compat),
+                  le32_to_cpu(es->s_feature_incompat),
+                  le32_to_cpu(es->s_feature_ro_compat)));
+
+       if (strlen(es->s_volume_name))
+               blkid_probe_set_label(pr, (unsigned char *) es->s_volume_name,
+                                       sizeof(es->s_volume_name));
+       blkid_probe_set_uuid(pr, es->s_uuid);
+
+       if (le32_to_cpu(es->s_feature_compat) & EXT3_FEATURE_COMPAT_HAS_JOURNAL)
+               blkid_probe_set_uuid_as(pr, es->s_journal_uuid, "EXT_JOURNAL");
+
+/*     if (ver != 2 && (chn->flags & BLKID_SUBLKS_SECTYPE) &&
+           ((le32_to_cpu(es->s_feature_incompat) & EXT2_FEATURE_INCOMPAT_UNSUPPORTED) == 0))
+               blkid_probe_set_value(pr, "SEC_TYPE",
+                               (unsigned char *) "ext2",
+                               sizeof("ext2"));*/
+
+       blkid_probe_sprintf_version(pr, "%u.%u",
+               le32_to_cpu(es->s_rev_level),
+               le16_to_cpu(es->s_minor_rev_level));
+}
+
+
+static int probe_jbd(blkid_probe pr,
+               const struct blkid_idmag *mag __attribute__((__unused__)))
+{
+       struct ext2_super_block *es;
+       uint32_t fi;
+
+       es = ext_get_super(pr, NULL, &fi, NULL);
+       if (!es)
+               return -BLKID_ERR_PARAM;
+       if (!(fi & EXT3_FEATURE_INCOMPAT_JOURNAL_DEV))
+               return -BLKID_ERR_PARAM;
+
+       ext_get_info(pr, 2, es);
+       return 0;
+}
+
+static int probe_ext2(blkid_probe pr,
+               const struct blkid_idmag *mag __attribute__((__unused__)))
+{
+       struct ext2_super_block *es;
+       uint32_t fc, frc, fi;
+
+       es = ext_get_super(pr, &fc, &fi, &frc);
+       if (!es)
+               return -BLKID_ERR_PARAM;
+
+       /* Distinguish between ext3 and ext2 */
+       if (fc & EXT3_FEATURE_COMPAT_HAS_JOURNAL)
+               return -BLKID_ERR_PARAM;
+
+       /* Any features which ext2 doesn't understand */
+       if ((frc & EXT2_FEATURE_RO_COMPAT_UNSUPPORTED) ||
+           (fi  & EXT2_FEATURE_INCOMPAT_UNSUPPORTED))
+               return -BLKID_ERR_PARAM;
+
+       /*
+        * If ext2 is not present, but ext4 or ext4dev are, then
+        * disclaim we are ext2
+        */
+       if (!system_supports_ext2() &&
+           (system_supports_ext4() || system_supports_ext4dev()) &&
+           get_linux_version() >= EXT4_SUPPORTS_EXT2)
+               return -BLKID_ERR_PARAM;
+
+       ext_get_info(pr, 2, es);
+       return 0;
+}
+
+static int probe_ext3(blkid_probe pr,
+               const struct blkid_idmag *mag __attribute__((__unused__)))
+{
+       struct ext2_super_block *es;
+       uint32_t fc, frc, fi;
+
+       es = ext_get_super(pr, &fc, &fi, &frc);
+       if (!es)
+               return -BLKID_ERR_PARAM;
+
+       /* ext3 requires journal */
+       if (!(fc & EXT3_FEATURE_COMPAT_HAS_JOURNAL))
+               return -BLKID_ERR_PARAM;
+
+       /* Any features which ext3 doesn't understand */
+       if ((frc & EXT3_FEATURE_RO_COMPAT_UNSUPPORTED) ||
+           (fi  & EXT3_FEATURE_INCOMPAT_UNSUPPORTED))
+               return -BLKID_ERR_PARAM;
+
+       ext_get_info(pr, 3, es);
+       return 0;
+}
+
+
+static int probe_ext4dev(blkid_probe pr,
+               const struct blkid_idmag *mag __attribute__((__unused__)))
+{
+       struct ext2_super_block *es;
+       uint32_t fc, frc, fi;
+
+       es = ext_get_super(pr, &fc, &fi, &frc);
+       if (!es)
+               return -BLKID_ERR_PARAM;
+
+       /* Distinguish from jbd */
+       if (fi & EXT3_FEATURE_INCOMPAT_JOURNAL_DEV)
+               return -BLKID_ERR_PARAM;
+
+       /*
+        * If the filesystem does not have a journal and ext2 and ext4
+        * is not present, then force this to be detected as an
+        * ext4dev filesystem.
+        */
+       if (!(fc & EXT3_FEATURE_COMPAT_HAS_JOURNAL) &&
+           !system_supports_ext2() && !system_supports_ext4() &&
+           system_supports_ext4dev() &&
+           get_linux_version() >= EXT4_SUPPORTS_EXT2)
+               goto force_ext4dev;
+
+       /*
+        * If the filesystem is marked as OK for use by in-development
+        * filesystem code, but ext4dev is not supported, and ext4 is,
+        * then don't call ourselves ext4dev, since we should be
+        * detected as ext4 in that case.
+        *
+        * If the filesystem is marked as in use by production
+        * filesystem, then it can only be used by ext4 and NOT by
+        * ext4dev, so always disclaim we are ext4dev in that case.
+        */
+       if (le32_to_cpu(es->s_flags) & EXT2_FLAGS_TEST_FILESYS) {
+               if (!system_supports_ext4dev() && system_supports_ext4())
+                       return -BLKID_ERR_PARAM;
+       } else
+               return -BLKID_ERR_PARAM;
+
+force_ext4dev:
+       ext_get_info(pr, 4, es);
+       return 0;
+}
+
+static int probe_ext4(blkid_probe pr,
+               const struct blkid_idmag *mag __attribute__((__unused__)))
+{
+       struct ext2_super_block *es;
+       uint32_t fc, frc, fi;
+
+       es = ext_get_super(pr, &fc, &fi, &frc);
+       if (!es)
+               return -1;
+
+       /* Distinguish from jbd */
+       if (fi & EXT3_FEATURE_INCOMPAT_JOURNAL_DEV)
+               return -BLKID_ERR_PARAM;
+
+       /*
+        * If the filesystem does not have a journal and ext2 is not
+        * present, then force this to be detected as an ext2
+        * filesystem.
+        */
+       if (!(fc & EXT3_FEATURE_COMPAT_HAS_JOURNAL) &&
+           !system_supports_ext2() && system_supports_ext4() &&
+           get_linux_version() >= EXT4_SUPPORTS_EXT2)
+               goto force_ext4;
+
+       /* Ext4 has at least one feature which ext3 doesn't understand */
+       if (!(frc & EXT3_FEATURE_RO_COMPAT_UNSUPPORTED) &&
+           !(fi  & EXT3_FEATURE_INCOMPAT_UNSUPPORTED))
+               return -BLKID_ERR_PARAM;
+
+force_ext4:
+       /*
+        * If the filesystem is a OK for use by in-development
+        * filesystem code, and ext4dev is supported or ext4 is not
+        * supported, then don't call ourselves ext4, so we can redo
+        * the detection and mark the filesystem as ext4dev.
+        *
+        * If the filesystem is marked as in use by production
+        * filesystem, then it can only be used by ext4 and NOT by
+        * ext4dev.
+        */
+       if (le32_to_cpu(es->s_flags) & EXT2_FLAGS_TEST_FILESYS) {
+               if (system_supports_ext4dev() || !system_supports_ext4())
+                       return -BLKID_ERR_PARAM;
+       }
+
+       ext_get_info(pr, 4, es);
+       return 0;
+}
+
+#define BLKID_EXT_MAGICS \
+       { \
+               {        \
+                       .magic = EXT_SB_MAGIC, \
+                       .len = sizeof(EXT_SB_MAGIC) - 1, \
+                       .kboff = EXT_SB_KBOFF, \
+                       .sboff = EXT_MAG_OFF \
+               }, \
+               { NULL } \
+       }
+
+const struct blkid_idinfo jbd_idinfo =
+{
+       .name           = "jbd",
+       .usage          = BLKID_USAGE_OTHER,
+       .probefunc      = probe_jbd,
+       .magics         = BLKID_EXT_MAGICS
+};
+
+const struct blkid_idinfo ext2_idinfo =
+{
+       .name           = "ext2",
+       .usage          = BLKID_USAGE_FILESYSTEM,
+       .probefunc      = probe_ext2,
+       .magics         = BLKID_EXT_MAGICS
+};
+
+const struct blkid_idinfo ext3_idinfo =
+{
+       .name           = "ext3",
+       .usage          = BLKID_USAGE_FILESYSTEM,
+       .probefunc      = probe_ext3,
+       .magics         = BLKID_EXT_MAGICS
+};
+
+const struct blkid_idinfo ext4_idinfo =
+{
+       .name           = "ext4",
+       .usage          = BLKID_USAGE_FILESYSTEM,
+       .probefunc      = probe_ext4,
+       .magics         = BLKID_EXT_MAGICS
+};
+
+const struct blkid_idinfo ext4dev_idinfo =
+{
+       .name           = "ext4dev",
+       .usage          = BLKID_USAGE_FILESYSTEM,
+       .probefunc      = probe_ext4dev,
+       .magics         = BLKID_EXT_MAGICS
+};
+
diff --git a/libblkid-tiny/jffs2.c b/libblkid-tiny/jffs2.c
new file mode 100644 (file)
index 0000000..098c557
--- /dev/null
@@ -0,0 +1,35 @@
+/*
+ * Copyright (C) 2008 Karel Zak <kzak@redhat.com>
+ *
+ * Inspired by libvolume_id by
+ *     Kay Sievers <kay.sievers@vrfy.org>
+ *
+ * This file may be redistributed under the terms of the
+ * GNU Lesser General Public License.
+ */
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+#include <stdint.h>
+
+#include "bitops.h"    /* swab16() */
+#include "superblocks.h"
+
+static int probe_jffs2(blkid_probe pr, const struct blkid_idmag *mag)
+{
+       return 0;
+}
+
+const struct blkid_idinfo jffs2_idinfo =
+{
+       .name           = "jffs2",
+       .usage          = BLKID_USAGE_FILESYSTEM,
+       .probefunc      = probe_jffs2,
+       .magics         =
+       {
+               { .magic = "\x19\x85", .len = 2 },
+               { .magic = "\x85\x19", .len = 2 },
+               { NULL }
+       }
+};
diff --git a/libblkid-tiny/libblkid-tiny.c b/libblkid-tiny/libblkid-tiny.c
new file mode 100644 (file)
index 0000000..bd86c41
--- /dev/null
@@ -0,0 +1,210 @@
+#include <stdio.h>
+#include <sys/utsname.h>
+
+#include "superblocks.h"
+#include "linux_version.h"
+
+#if 0
+#define DEBUG(fmt, ...)        printf(fmt, __VA_ARGS__)
+#else
+#define DEBUG(fmt, ...)
+#endif
+
+int blkid_debug_mask = 0;
+
+static unsigned char *probe_buffer;
+
+int get_linux_version (void)
+{
+       static int kver = -1;
+       struct utsname uts;
+       int major = 0;
+       int minor = 0;
+       int teeny = 0;
+       int n;
+
+       if (kver != -1)
+               return kver;
+       if (uname (&uts))
+               return kver = 0;
+
+       n = sscanf(uts.release, "%d.%d.%d", &major, &minor, &teeny);
+       if (n < 1 || n > 3)
+               return kver = 0;
+
+       return kver = KERNEL_VERSION(major, minor, teeny);
+}
+
+int blkid_probe_is_tiny(blkid_probe pr)
+{
+       /* never true ? */
+       return 0;
+}
+
+int blkid_probe_set_value(blkid_probe pr, const char *name,
+                unsigned char *data, size_t len)
+{
+       /* empty stub */
+       return 0;
+}
+
+int blkid_probe_set_version(blkid_probe pr, const char *version)
+{
+       int len = strlen(version);
+       if (len > (sizeof(pr->version) - 1)) {
+               fprintf(stderr, "version buffer too small %d\n", len);
+               return -1;
+       }
+
+       strncpy(pr->version, version, sizeof(pr->version));
+
+       return 0;
+}
+
+int blkid_probe_sprintf_version(blkid_probe pr, const char *fmt, ...)
+{
+       va_list ap;
+       int n;
+
+       va_start(ap, fmt);
+       n = vsnprintf(pr->version, sizeof(pr->version), fmt, ap);
+       va_end(ap);
+
+       if (n >= sizeof(pr->version))
+               fprintf(stderr, "version buffer too small %d\n", n);
+
+       return 0;
+}
+
+unsigned char *blkid_probe_get_buffer(blkid_probe pr,
+                               blkid_loff_t off, blkid_loff_t len)
+{
+       int ret;
+
+       if (len > 4096) {
+               fprintf(stderr, "probe buffer too small %d\n", (int) len);
+               return NULL;
+       }
+
+       if (!probe_buffer) {
+               probe_buffer = malloc(4096);
+               memset(probe_buffer, 0, 4096);
+       }
+
+       lseek(pr->fd, off, SEEK_SET);
+       ret = read(pr->fd, probe_buffer, len);
+
+       if (ret != len)
+               fprintf(stderr, "faile to read blkid\n");
+
+       return probe_buffer;
+}
+
+int blkid_probe_set_label(blkid_probe pr, unsigned char *label, size_t len)
+{
+       if (len > (sizeof(pr->label) - 1)) {
+               fprintf(stderr, "label buffer too small %d > %d\n",
+                       (int) len, (int) sizeof(pr->label) - 1);
+               return -1;
+       }
+       memcpy(pr->label, label, len + 1);
+
+       return 0;
+}
+
+int blkid_probe_set_uuid_as(blkid_probe pr, unsigned char *uuid, const char *name)
+{
+       short unsigned int*u = (short unsigned int*) uuid;
+
+       if (u[0])
+               sprintf(pr->uuid,
+                       "%04x%04x-%04x-%04x-%04x-%04x%04x%04x",
+                       be16_to_cpu(u[0]), be16_to_cpu(u[1]), be16_to_cpu(u[2]), be16_to_cpu(u[3]),
+                       be16_to_cpu(u[4]), be16_to_cpu(u[5]), be16_to_cpu(u[6]), be16_to_cpu(u[7]));
+       if (name)
+               strncpy(pr->name, name, sizeof(pr->name));
+
+       return 0;
+}
+
+int blkid_probe_set_uuid(blkid_probe pr, unsigned char *uuid)
+{
+       return blkid_probe_set_uuid_as(pr, uuid, NULL);
+}
+
+int blkid_probe_sprintf_uuid(blkid_probe pr, unsigned char *uuid,
+                            size_t len, const char *fmt, ...)
+{
+       va_list ap;
+
+       va_start(ap, fmt);
+       vsnprintf(pr->uuid, sizeof(pr->uuid), fmt, ap);
+       va_end(ap);
+
+       return 0;
+}
+
+static const struct blkid_idinfo *idinfos[] =
+{
+       &vfat_idinfo,
+       &swsuspend_idinfo,
+       &swap_idinfo,
+       &ext4dev_idinfo,
+       &ext4_idinfo,
+       &ext3_idinfo,
+       &ext2_idinfo,
+       &jbd_idinfo,
+       &squashfs_idinfo,
+       &jffs2_idinfo,
+};
+
+int probe_block(char *block, struct blkid_struct_probe *pr)
+{
+       struct stat s;
+       int i;
+
+       if (stat(block, &s) || !S_ISBLK(s.st_mode))
+               return -1;
+
+       pr->err = -1;
+       pr->fd = open(block, O_RDONLY);
+       if (!pr->fd)
+               return -1;
+
+       for (i = 0; i < ARRAY_SIZE(idinfos); i++) {
+               /* loop over all magic handlers */
+               const struct blkid_idmag *mag;
+
+               /* loop over all probe handlers */
+               DEBUG("scanning %s\n", idinfos[i]->name);
+
+               mag = &idinfos[i]->magics[0];
+
+               while (mag->magic) {
+                       int off = (mag->kboff * 1024) + mag->sboff;
+                       char magic[32] = { 0 };
+
+                       lseek(pr->fd, off, SEEK_SET);
+                       read(pr->fd, magic, mag->len);
+
+                       DEBUG("magic: %s %s %d\n", mag->magic, magic, mag->len);
+                       if (!memcmp(mag->magic, magic, mag->len))
+                               break;
+                       mag++;
+               }
+
+               if (mag && mag->magic) {
+                       DEBUG("probing %s\n", idinfos[i]->name);
+                       pr->err = idinfos[i]->probefunc(pr, mag);
+                       pr->id = idinfos[i];
+                       strcpy(pr->dev, block);
+                       if (!pr->err)
+                               break;
+               }
+       }
+
+       close(pr->fd);
+
+       return 0;
+}
+
diff --git a/libblkid-tiny/libblkid-tiny.h b/libblkid-tiny/libblkid-tiny.h
new file mode 100644 (file)
index 0000000..af12658
--- /dev/null
@@ -0,0 +1,58 @@
+/*
+ * Copyright (C) 2013 Felix Fietkau <nbd@openwrt.org>
+ * Copyright (C) 2013 John Crispin <blogic@openwrt.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 2.1
+ * as published by the Free Software Foundation
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#include <libubox/list.h>
+
+struct blkid_idmag;
+struct blkid_idmag;
+struct blkid_idinfo;
+
+struct blkid_idmag
+{
+       const char      *magic;
+       unsigned int    len;
+
+       long            kboff;
+       unsigned int    sboff;
+};
+
+
+struct blkid_idinfo;
+
+struct blkid_struct_probe
+{
+       const struct blkid_idinfo       *id;
+       struct list_head                list;
+
+       int     fd;
+       int     err;
+       char    dev[32];
+       char    uuid[64];
+       char    label[64];
+       char    name[64];
+       char    version[64];
+};
+
+struct blkid_idinfo
+{
+       const char      *name;
+       int             usage;
+       int             flags;
+       int             minsz;
+       int (*probefunc)(struct blkid_struct_probe *pr, const struct blkid_idmag *mag);
+       struct blkid_idmag      magics[];
+};
+
+extern int probe_block(char *block, struct blkid_struct_probe *pr);
+extern int mkblkdev(void);
diff --git a/libblkid-tiny/linux_version.h b/libblkid-tiny/linux_version.h
new file mode 100644 (file)
index 0000000..a6a1e99
--- /dev/null
@@ -0,0 +1,14 @@
+#ifndef LINUX_VERSION_H
+#define LINUX_VERSION_H
+
+#ifdef HAVE_LINUX_VERSION_H
+# include <linux/version.h>
+#endif
+
+#ifndef KERNEL_VERSION
+# define KERNEL_VERSION(a,b,c) (((a) << 16) + ((b) << 8) + (c))
+#endif
+
+int get_linux_version(void);
+
+#endif /* LINUX_VERSION_H */
diff --git a/libblkid-tiny/md5.c b/libblkid-tiny/md5.c
new file mode 100644 (file)
index 0000000..ec24dd2
--- /dev/null
@@ -0,0 +1,242 @@
+/*
+ *  md5.c - Compute MD5 checksum of strings according to the
+ *          definition of MD5 in RFC 1321 from April 1992.
+ *
+ *  Written by Ulrich Drepper <drepper@gnu.ai.mit.edu>, 1995.
+ *
+ *  Copyright (C) 1995-1999 Free Software Foundation, Inc.
+ *  Copyright (C) 2001 Manuel Novoa III
+ *  Copyright (C) 2003 Glenn L. McGrath
+ *  Copyright (C) 2003 Erik Andersen
+ *
+ *  Licensed under the GPL v2 or later, see the file LICENSE in this tarball.
+ */
+
+#include <libubox/blob.h> /* TODO: better include for bswap_32 compat */
+#include "md5.h"
+
+#if __BYTE_ORDER == __LITTLE_ENDIAN
+#define SWAP_LE32(x) (x)
+#else
+#define SWAP_LE32(x) bswap_32(x)
+#endif
+
+/* Initialize structure containing state of computation.
+ * (RFC 1321, 3.3: Step 3)
+ */
+void md5_begin(md5_ctx_t *ctx)
+{
+       ctx->A = 0x67452301;
+       ctx->B = 0xefcdab89;
+       ctx->C = 0x98badcfe;
+       ctx->D = 0x10325476;
+
+       ctx->total = 0;
+       ctx->buflen = 0;
+}
+
+/* These are the four functions used in the four steps of the MD5 algorithm
+ * and defined in the RFC 1321.  The first function is a little bit optimized
+ * (as found in Colin Plumbs public domain implementation).
+ * #define FF(b, c, d) ((b & c) | (~b & d))
+ */
+# define FF(b, c, d) (d ^ (b & (c ^ d)))
+# define FG(b, c, d) FF (d, b, c)
+# define FH(b, c, d) (b ^ c ^ d)
+# define FI(b, c, d) (c ^ (b | ~d))
+
+/* Hash a single block, 64 bytes long and 4-byte aligned. */
+static void md5_hash_block(const void *buffer, md5_ctx_t *ctx)
+{
+       uint32_t correct_words[16];
+       const uint32_t *words = buffer;
+
+       static const uint32_t C_array[] = {
+               /* round 1 */
+               0xd76aa478, 0xe8c7b756, 0x242070db, 0xc1bdceee,
+               0xf57c0faf, 0x4787c62a, 0xa8304613, 0xfd469501,
+               0x698098d8, 0x8b44f7af, 0xffff5bb1, 0x895cd7be,
+               0x6b901122, 0xfd987193, 0xa679438e, 0x49b40821,
+               /* round 2 */
+               0xf61e2562, 0xc040b340, 0x265e5a51, 0xe9b6c7aa,
+               0xd62f105d, 0x2441453, 0xd8a1e681, 0xe7d3fbc8,
+               0x21e1cde6, 0xc33707d6, 0xf4d50d87, 0x455a14ed,
+               0xa9e3e905, 0xfcefa3f8, 0x676f02d9, 0x8d2a4c8a,
+               /* round 3 */
+               0xfffa3942, 0x8771f681, 0x6d9d6122, 0xfde5380c,
+               0xa4beea44, 0x4bdecfa9, 0xf6bb4b60, 0xbebfbc70,
+               0x289b7ec6, 0xeaa127fa, 0xd4ef3085, 0x4881d05,
+               0xd9d4d039, 0xe6db99e5, 0x1fa27cf8, 0xc4ac5665,
+               /* round 4 */
+               0xf4292244, 0x432aff97, 0xab9423a7, 0xfc93a039,
+               0x655b59c3, 0x8f0ccc92, 0xffeff47d, 0x85845dd1,
+               0x6fa87e4f, 0xfe2ce6e0, 0xa3014314, 0x4e0811a1,
+               0xf7537e82, 0xbd3af235, 0x2ad7d2bb, 0xeb86d391
+       };
+
+       static const char P_array[] = {
+               0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,   /* 1 */
+               1, 6, 11, 0, 5, 10, 15, 4, 9, 14, 3, 8, 13, 2, 7, 12,   /* 2 */
+               5, 8, 11, 14, 1, 4, 7, 10, 13, 0, 3, 6, 9, 12, 15, 2,   /* 3 */
+               0, 7, 14, 5, 12, 3, 10, 1, 8, 15, 6, 13, 4, 11, 2, 9    /* 4 */
+       };
+
+       static const char S_array[] = {
+               7, 12, 17, 22,
+               5, 9, 14, 20,
+               4, 11, 16, 23,
+               6, 10, 15, 21
+       };
+
+       uint32_t A = ctx->A;
+       uint32_t B = ctx->B;
+       uint32_t C = ctx->C;
+       uint32_t D = ctx->D;
+
+       uint32_t *cwp = correct_words;
+
+#  define CYCLIC(w, s) (w = (w << s) | (w >> (32 - s)))
+
+       const uint32_t *pc;
+       const char *pp;
+       const char *ps;
+       int i;
+       uint32_t temp;
+
+       for (i = 0; i < 16; i++) {
+               cwp[i] = SWAP_LE32(words[i]);
+       }
+       words += 16;
+
+       pc = C_array;
+       pp = P_array;
+       ps = S_array;
+
+       for (i = 0; i < 16; i++) {
+               temp = A + FF(B, C, D) + cwp[(int) (*pp++)] + *pc++;
+               CYCLIC(temp, ps[i & 3]);
+               temp += B;
+               A = D;
+               D = C;
+               C = B;
+               B = temp;
+       }
+
+       ps += 4;
+       for (i = 0; i < 16; i++) {
+               temp = A + FG(B, C, D) + cwp[(int) (*pp++)] + *pc++;
+               CYCLIC(temp, ps[i & 3]);
+               temp += B;
+               A = D;
+               D = C;
+               C = B;
+               B = temp;
+       }
+       ps += 4;
+       for (i = 0; i < 16; i++) {
+               temp = A + FH(B, C, D) + cwp[(int) (*pp++)] + *pc++;
+               CYCLIC(temp, ps[i & 3]);
+               temp += B;
+               A = D;
+               D = C;
+               C = B;
+               B = temp;
+       }
+       ps += 4;
+       for (i = 0; i < 16; i++) {
+               temp = A + FI(B, C, D) + cwp[(int) (*pp++)] + *pc++;
+               CYCLIC(temp, ps[i & 3]);
+               temp += B;
+               A = D;
+               D = C;
+               C = B;
+               B = temp;
+       }
+
+
+       ctx->A += A;
+       ctx->B += B;
+       ctx->C += C;
+       ctx->D += D;
+}
+
+/* Feed data through a temporary buffer to call md5_hash_aligned_block()
+ * with chunks of data that are 4-byte aligned and a multiple of 64 bytes.
+ * This function's internal buffer remembers previous data until it has 64
+ * bytes worth to pass on.  Call md5_end() to flush this buffer. */
+
+void md5_hash(const void *buffer, size_t len, md5_ctx_t *ctx)
+{
+       char *buf = (char *)buffer;
+
+       /* RFC 1321 specifies the possible length of the file up to 2^64 bits,
+        * Here we only track the number of bytes.  */
+
+       ctx->total += len;
+
+       // Process all input.
+
+       while (len) {
+               unsigned i = 64 - ctx->buflen;
+
+               // Copy data into aligned buffer.
+
+               if (i > len)
+                       i = len;
+               memcpy(ctx->buffer + ctx->buflen, buf, i);
+               len -= i;
+               ctx->buflen += i;
+               buf += i;
+
+               // When buffer fills up, process it.
+
+               if (ctx->buflen == 64) {
+                       md5_hash_block(ctx->buffer, ctx);
+                       ctx->buflen = 0;
+               }
+       }
+}
+
+/* Process the remaining bytes in the buffer and put result from CTX
+ * in first 16 bytes following RESBUF.  The result is always in little
+ * endian byte order, so that a byte-wise output yields to the wanted
+ * ASCII representation of the message digest.
+ *
+ * IMPORTANT: On some systems it is required that RESBUF is correctly
+ * aligned for a 32 bits value.
+ */
+void md5_end(void *resbuf, md5_ctx_t *ctx)
+{
+       char *buf = ctx->buffer;
+       int i;
+
+       /* Pad data to block size.  */
+
+       buf[ctx->buflen++] = 0x80;
+       memset(buf + ctx->buflen, 0, 128 - ctx->buflen);
+
+       /* Put the 64-bit file length in *bits* at the end of the buffer.  */
+       ctx->total <<= 3;
+       if (ctx->buflen > 56)
+               buf += 64;
+
+       for (i = 0; i < 8; i++)
+               buf[56 + i] = ctx->total >> (i*8);
+
+       /* Process last bytes.  */
+       if (buf != ctx->buffer)
+               md5_hash_block(ctx->buffer, ctx);
+       md5_hash_block(buf, ctx);
+
+       /* Put result from CTX in first 16 bytes following RESBUF.  The result is
+        * always in little endian byte order, so that a byte-wise output yields
+        * to the wanted ASCII representation of the message digest.
+        *
+        * IMPORTANT: On some systems it is required that RESBUF is correctly
+        * aligned for a 32 bits value.
+        */
+       ((uint32_t *) resbuf)[0] = SWAP_LE32(ctx->A);
+       ((uint32_t *) resbuf)[1] = SWAP_LE32(ctx->B);
+       ((uint32_t *) resbuf)[2] = SWAP_LE32(ctx->C);
+       ((uint32_t *) resbuf)[3] = SWAP_LE32(ctx->D);
+}
diff --git a/libblkid-tiny/md5.h b/libblkid-tiny/md5.h
new file mode 100644 (file)
index 0000000..e1731ef
--- /dev/null
@@ -0,0 +1,35 @@
+/*
+ * Copyright (C) 2013 Felix Fietkau <nbd@openwrt.org>
+ * Copyright (C) 2013 John Crispin <blogic@openwrt.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 2.1
+ * as published by the Free Software Foundation
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef __PROCD_MD5_H
+#define __PROCD_MD5_H
+
+#include <stdint.h>
+#include <stddef.h>
+
+typedef struct md5_ctx {
+       uint32_t A;
+       uint32_t B;
+       uint32_t C;
+       uint32_t D;
+       uint64_t total;
+       uint32_t buflen;
+       char buffer[128];
+} md5_ctx_t;
+
+void md5_begin(md5_ctx_t *ctx);
+void md5_hash(const void *data, size_t length, md5_ctx_t *ctx);
+void md5_end(void *resbuf, md5_ctx_t *ctx);
+
+#endif
diff --git a/libblkid-tiny/mkdev.c b/libblkid-tiny/mkdev.c
new file mode 100644 (file)
index 0000000..3d067b2
--- /dev/null
@@ -0,0 +1,94 @@
+/*
+ * Copyright (C) 2013 Felix Fietkau <nbd@openwrt.org>
+ * Copyright (C) 2013 John Crispin <blogic@openwrt.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 2.1
+ * as published by the Free Software Foundation
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#define _BSD_SOURCE
+
+#include <sys/stat.h>
+#include <sys/types.h>
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <stdbool.h>
+#include <dirent.h>
+#include <limits.h>
+#include <fnmatch.h>
+
+#include "libblkid-tiny.h"
+
+#include <syslog.h>
+
+static char buf[PATH_MAX];
+static char buf2[PATH_MAX];
+static unsigned int mode = 0600;
+
+static void make_dev(const char *path, bool block, int major, int minor)
+{
+       unsigned int _mode = mode | (block ? S_IFBLK : S_IFCHR);
+
+       mknod(path, _mode, makedev(major, minor));
+}
+
+static void find_devs(bool block)
+{
+       char *path = block ? "/sys/dev/block" : "/sys/dev/char";
+       struct dirent *dp;
+       DIR *dir;
+
+       dir = opendir(path);
+       if (!dir)
+               return;
+
+       path = buf2 + sprintf(buf2, "%s/", path);
+       while ((dp = readdir(dir)) != NULL) {
+               char *c;
+               int major = 0, minor = 0;
+               int len;
+
+               if (dp->d_type != DT_LNK)
+                       continue;
+
+               if (sscanf(dp->d_name, "%d:%d", &major, &minor) != 2)
+                       continue;
+
+               strcpy(path, dp->d_name);
+               len = readlink(buf2, buf, sizeof(buf));
+               if (len <= 0)
+                       continue;
+
+               buf[len] = 0;
+
+               c = strrchr(buf, '/');
+               if (!c)
+                       continue;
+
+
+               c++;
+               make_dev(c, block, major, minor);
+       }
+       closedir(dir);
+}
+
+int mkblkdev(void)
+{
+       if (chdir("/dev"))
+               return 1;
+
+       mode = 0600;
+       find_devs(true);
+       chdir("/");
+
+       return 0;
+}
diff --git a/libblkid-tiny/squashfs.c b/libblkid-tiny/squashfs.c
new file mode 100644 (file)
index 0000000..d2033b6
--- /dev/null
@@ -0,0 +1,87 @@
+/*
+ * Copyright (C) 2008 Karel Zak <kzak@redhat.com>
+ *
+ * Inspired by libvolume_id by
+ *     Kay Sievers <kay.sievers@vrfy.org>
+ *
+ * This file may be redistributed under the terms of the
+ * GNU Lesser General Public License.
+ */
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+#include <stdint.h>
+
+#include "bitops.h"    /* swab16() */
+#include "superblocks.h"
+
+#include "md5.h"
+
+struct squashfs_super_block {
+       uint32_t s_magic;
+       uint32_t inodes;
+       uint32_t mkfs_time;
+       uint32_t block_size;
+       uint32_t fragments;
+       uint16_t compression;
+       uint16_t block_log;
+       uint16_t flags;
+       uint16_t no_ids;
+       uint16_t s_major;
+       uint16_t s_minor;
+       uint64_t root_inode;
+       uint64_t bytes_used;
+       uint64_t id_table_start;
+       uint64_t xattr_id_table_start;
+       uint64_t inode_table_start;
+       uint64_t directory_table_start;
+       uint64_t fragment_table_start;
+       uint64_t lookup_table_start;
+} __attribute__((packed));
+
+static int probe_squashfs(blkid_probe pr, const struct blkid_idmag *mag)
+{
+       md5_ctx_t ctx = { 0 };
+       uint8_t md5[4];
+       struct squashfs_super_block *sq;
+
+       sq = blkid_probe_get_sb(pr, mag, struct squashfs_super_block);
+       if (!sq)
+               return -1;
+
+       if (strcmp(mag->magic, "sqsh") == 0 ||
+           strcmp(mag->magic, "qshs") == 0)
+               blkid_probe_sprintf_version(pr, "%u.%u",
+                               sq->s_major,
+                               sq->s_minor);
+       else
+               blkid_probe_sprintf_version(pr, "%u.%u",
+                               swab16(sq->s_major),
+                               swab16(sq->s_minor));
+       md5_begin(&ctx);
+       md5_hash(sq, sizeof(*sq), &ctx);
+       md5_end(&md5, &ctx);
+       blkid_probe_sprintf_uuid(pr, NULL, 4, "%02x%02x-%02x%02x",
+                       md5[3], md5[2], md5[1], md5[0]);
+       return 0;
+}
+
+const struct blkid_idinfo squashfs_idinfo =
+{
+       .name           = "squashfs",
+       .usage          = BLKID_USAGE_FILESYSTEM,
+       .probefunc      = probe_squashfs,
+       .magics         =
+       {
+               { .magic = "sqsh", .len = 4 },
+               { .magic = "hsqs", .len = 4 }, /* swap */
+
+               /* LZMA version */
+               { .magic = "qshs", .len = 4 },
+               { .magic = "shsq", .len = 4 }, /* swap */
+               { NULL }
+       }
+};
+
+
diff --git a/libblkid-tiny/superblocks.h b/libblkid-tiny/superblocks.h
new file mode 100644 (file)
index 0000000..24f59bb
--- /dev/null
@@ -0,0 +1,92 @@
+/*
+ * Copyright (C) 2008-2009 Karel Zak <kzak@redhat.com>
+ *
+ * This file may be redistributed under the terms of the
+ * GNU Lesser General Public License.
+ */
+#ifndef _BLKID_SUPERBLOCKS_H
+#define _BLKID_SUPERBLOCKS_H
+
+#include "blkidP.h"
+
+extern const struct blkid_idinfo cramfs_idinfo;
+extern const struct blkid_idinfo swap_idinfo;
+extern const struct blkid_idinfo swsuspend_idinfo;
+extern const struct blkid_idinfo adraid_idinfo;
+extern const struct blkid_idinfo ddfraid_idinfo;
+extern const struct blkid_idinfo iswraid_idinfo;
+extern const struct blkid_idinfo jmraid_idinfo;
+extern const struct blkid_idinfo lsiraid_idinfo;
+extern const struct blkid_idinfo nvraid_idinfo;
+extern const struct blkid_idinfo pdcraid_idinfo;
+extern const struct blkid_idinfo silraid_idinfo;
+extern const struct blkid_idinfo viaraid_idinfo;
+extern const struct blkid_idinfo linuxraid_idinfo;
+extern const struct blkid_idinfo ext4dev_idinfo;
+extern const struct blkid_idinfo ext4_idinfo;
+extern const struct blkid_idinfo ext3_idinfo;
+extern const struct blkid_idinfo ext2_idinfo;
+extern const struct blkid_idinfo jbd_idinfo;
+extern const struct blkid_idinfo jfs_idinfo;
+extern const struct blkid_idinfo xfs_idinfo;
+extern const struct blkid_idinfo gfs_idinfo;
+extern const struct blkid_idinfo gfs2_idinfo;
+extern const struct blkid_idinfo romfs_idinfo;
+extern const struct blkid_idinfo ocfs_idinfo;
+extern const struct blkid_idinfo ocfs2_idinfo;
+extern const struct blkid_idinfo oracleasm_idinfo;
+extern const struct blkid_idinfo reiser_idinfo;
+extern const struct blkid_idinfo reiser4_idinfo;
+extern const struct blkid_idinfo hfs_idinfo;
+extern const struct blkid_idinfo hfsplus_idinfo;
+extern const struct blkid_idinfo ntfs_idinfo;
+extern const struct blkid_idinfo iso9660_idinfo;
+extern const struct blkid_idinfo udf_idinfo;
+extern const struct blkid_idinfo vxfs_idinfo;
+extern const struct blkid_idinfo minix_idinfo;
+extern const struct blkid_idinfo vfat_idinfo;
+extern const struct blkid_idinfo ufs_idinfo;
+extern const struct blkid_idinfo hpfs_idinfo;
+extern const struct blkid_idinfo lvm2_idinfo;
+extern const struct blkid_idinfo lvm1_idinfo;
+extern const struct blkid_idinfo snapcow_idinfo;
+extern const struct blkid_idinfo luks_idinfo;
+extern const struct blkid_idinfo highpoint37x_idinfo;
+extern const struct blkid_idinfo highpoint45x_idinfo;
+extern const struct blkid_idinfo squashfs_idinfo;
+extern const struct blkid_idinfo netware_idinfo;
+extern const struct blkid_idinfo sysv_idinfo;
+extern const struct blkid_idinfo xenix_idinfo;
+extern const struct blkid_idinfo btrfs_idinfo;
+extern const struct blkid_idinfo ubifs_idinfo;
+extern const struct blkid_idinfo zfs_idinfo;
+extern const struct blkid_idinfo bfs_idinfo;
+extern const struct blkid_idinfo vmfs_volume_idinfo;
+extern const struct blkid_idinfo vmfs_fs_idinfo;
+extern const struct blkid_idinfo drbd_idinfo;
+extern const struct blkid_idinfo drbdproxy_datalog_idinfo;
+extern const struct blkid_idinfo befs_idinfo;
+extern const struct blkid_idinfo nilfs2_idinfo;
+extern const struct blkid_idinfo exfat_idinfo;
+extern const struct blkid_idinfo jffs2_idinfo;
+
+/*
+ * superblock functions
+ */
+extern int blkid_probe_set_version(blkid_probe pr, const char *version);
+extern int blkid_probe_sprintf_version(blkid_probe pr, const char *fmt, ...)
+               __attribute__ ((format (printf, 2, 3)));
+
+extern int blkid_probe_set_label(blkid_probe pr, unsigned char *label, size_t len);
+extern int blkid_probe_set_utf8label(blkid_probe pr, unsigned char *label,
+                size_t len, int enc);
+extern int blkid_probe_sprintf_uuid(blkid_probe pr, unsigned char *uuid,
+                size_t len, const char *fmt, ...)
+               __attribute__ ((format (printf, 4, 5)));
+extern int blkid_probe_strncpy_uuid(blkid_probe pr, unsigned char *str, size_t len);
+
+extern int blkid_probe_set_uuid(blkid_probe pr, unsigned char *uuid);
+extern int blkid_probe_set_uuid_as(blkid_probe pr, unsigned char *uuid, const char *name);
+
+
+#endif /* _BLKID_SUPERBLOCKS_H */
diff --git a/libblkid-tiny/swap.c b/libblkid-tiny/swap.c
new file mode 100644 (file)
index 0000000..a598a7c
--- /dev/null
@@ -0,0 +1,171 @@
+/*
+ * Copyright (C) 1999 by Andries Brouwer
+ * Copyright (C) 1999, 2000, 2003 by Theodore Ts'o
+ * Copyright (C) 2001 by Andreas Dilger
+ * Copyright (C) 2004 Kay Sievers <kay.sievers@vrfy.org>
+ * Copyright (C) 2008 Karel Zak <kzak@redhat.com>
+ *
+ * This file may be redistributed under the terms of the
+ * GNU Lesser General Public License.
+ */
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+#include <errno.h>
+#include <ctype.h>
+#include <stdint.h>
+
+#include "superblocks.h"
+
+/* linux-2.6/include/linux/swap.h */
+struct swap_header_v1_2 {
+     /*        char            bootbits[1024]; */ /* Space for disklabel etc. */
+       uint32_t        version;
+       uint32_t        lastpage;
+       uint32_t        nr_badpages;
+       unsigned char   uuid[16];
+       unsigned char   volume[16];
+       uint32_t        padding[117];
+       uint32_t        badpages[1];
+} __attribute__((packed));
+
+#define PAGESIZE_MIN   0xff6   /* 4086 (arm, i386, ...) */
+#define PAGESIZE_MAX   0xfff6  /* 65526 (ia64) */
+
+#define TOI_MAGIC_STRING       "\xed\xc3\x02\xe9\x98\x56\xe5\x0c"
+#define TOI_MAGIC_STRLEN       (sizeof(TOI_MAGIC_STRING) - 1)
+
+static int swap_set_info(blkid_probe pr, const char *version)
+{
+       struct swap_header_v1_2 *hdr;
+
+       /* Swap header always located at offset of 1024 bytes */
+       hdr = (struct swap_header_v1_2 *) blkid_probe_get_buffer(pr, 1024,
+                               sizeof(struct swap_header_v1_2));
+       if (!hdr)
+               return -1;
+
+       /* SWAPSPACE2 - check for wrong version or zeroed pagecount */
+       if (strcmp(version, "2") == 0 &&
+               ((hdr->version != 1 && swab32(hdr->version) != 1) || hdr->lastpage == 0))
+               return -1;
+
+       /* arbitrary sanity check.. is there any garbage down there? */
+       if (hdr->padding[32] == 0 && hdr->padding[33] == 0) {
+               if (hdr->volume[0] && blkid_probe_set_label(pr, hdr->volume,
+                               sizeof(hdr->volume)) < 0)
+                       return -1;
+               if (blkid_probe_set_uuid(pr, hdr->uuid) < 0)
+                       return -1;
+       }
+
+       blkid_probe_set_version(pr, version);
+       return 0;
+}
+
+static int probe_swap(blkid_probe pr, const struct blkid_idmag *mag)
+{
+       unsigned char *buf;
+
+       if (!mag)
+               return -1;
+
+       /* TuxOnIce keeps valid swap header at the end of the 1st page */
+       buf = blkid_probe_get_buffer(pr, 0, TOI_MAGIC_STRLEN);
+       if (!buf)
+               return -1;
+
+       if (memcmp(buf, TOI_MAGIC_STRING, TOI_MAGIC_STRLEN) == 0)
+               return 1;       /* Ignore swap signature, it's TuxOnIce */
+
+       if (!memcmp(mag->magic, "SWAP-SPACE", mag->len)) {
+               /* swap v0 doesn't support LABEL or UUID */
+               blkid_probe_set_version(pr, "1");
+               return 0;
+
+       } else if (!memcmp(mag->magic, "SWAPSPACE2", mag->len))
+               return swap_set_info(pr, "2");
+
+       return -1;
+}
+
+static int probe_swsuspend(blkid_probe pr, const struct blkid_idmag *mag)
+{
+       if (!mag)
+               return -1;
+       if (!memcmp(mag->magic, "S1SUSPEND", mag->len))
+               return swap_set_info(pr, "s1suspend");
+       if (!memcmp(mag->magic, "S2SUSPEND", mag->len))
+               return swap_set_info(pr, "s2suspend");
+       if (!memcmp(mag->magic, "ULSUSPEND", mag->len))
+               return swap_set_info(pr, "ulsuspend");
+       if (!memcmp(mag->magic, TOI_MAGIC_STRING, mag->len))
+               return swap_set_info(pr, "tuxonice");
+       if (!memcmp(mag->magic, "LINHIB0001", mag->len))
+               return swap_set_info(pr, "linhib0001");
+
+       return -1;      /* no signature detected */
+}
+
+const struct blkid_idinfo swap_idinfo =
+{
+       .name           = "swap",
+       .usage          = BLKID_USAGE_OTHER,
+       .probefunc      = probe_swap,
+       .minsz          = 10 * 4096,    /* 10 pages */
+       .magics         =
+       {
+               { "SWAP-SPACE", 10, 0,  0xff6 },
+               { "SWAPSPACE2", 10, 0,  0xff6 },
+               { "SWAP-SPACE", 10, 0, 0x1ff6 },
+               { "SWAPSPACE2", 10, 0, 0x1ff6 },
+               { "SWAP-SPACE", 10, 0, 0x3ff6 },
+               { "SWAPSPACE2", 10, 0, 0x3ff6 },
+               { "SWAP-SPACE", 10, 0, 0x7ff6 },
+               { "SWAPSPACE2", 10, 0, 0x7ff6 },
+               { "SWAP-SPACE", 10, 0, 0xfff6 },
+               { "SWAPSPACE2", 10, 0, 0xfff6 },
+               { NULL }
+       }
+};
+
+
+const struct blkid_idinfo swsuspend_idinfo =
+{
+       .name           = "swsuspend",
+       .usage          = BLKID_USAGE_OTHER,
+       .probefunc      = probe_swsuspend,
+       .minsz          = 10 * 4096,    /* 10 pages */
+       .magics         =
+       {
+               { TOI_MAGIC_STRING, TOI_MAGIC_STRLEN, 0, 0 },
+               { "S1SUSPEND", 9, 0, 0xff6 },
+               { "S2SUSPEND", 9, 0, 0xff6 },
+               { "ULSUSPEND", 9, 0, 0xff6 },
+               { "LINHIB0001",10,0, 0xff6 },
+
+               { "S1SUSPEND", 9, 0, 0x1ff6 },
+               { "S2SUSPEND", 9, 0, 0x1ff6 },
+               { "ULSUSPEND", 9, 0, 0x1ff6 },
+               { "LINHIB0001",10,0, 0x1ff6 },
+
+               { "S1SUSPEND", 9, 0, 0x3ff6 },
+               { "S2SUSPEND", 9, 0, 0x3ff6 },
+               { "ULSUSPEND", 9, 0, 0x3ff6 },
+               { "LINHIB0001",10,0, 0x3ff6 },
+
+               { "S1SUSPEND", 9, 0, 0x7ff6 },
+               { "S2SUSPEND", 9, 0, 0x7ff6 },
+               { "ULSUSPEND", 9, 0, 0x7ff6 },
+               { "LINHIB0001",10,0, 0x7ff6 },
+
+               { "S1SUSPEND", 9, 0, 0xfff6 },
+               { "S2SUSPEND", 9, 0, 0xfff6 },
+               { "ULSUSPEND", 9, 0, 0xfff6 },
+               { "LINHIB0001",10,0, 0xfff6 },
+
+               { NULL }
+       }
+};
+
diff --git a/libblkid-tiny/ubifs.c b/libblkid-tiny/ubifs.c
new file mode 100644 (file)
index 0000000..2d69c2b
--- /dev/null
@@ -0,0 +1,120 @@
+/*
+ * Copyright (C) 2009 Corentin Chary <corentincj@iksaif.net>
+ *
+ * This file may be redistributed under the terms of the
+ * GNU Lesser General Public License.
+ */
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+#include <stdint.h>
+
+#include "superblocks.h"
+
+/*
+ * struct ubifs_ch - common header node.
+ * @magic: UBIFS node magic number (%UBIFS_NODE_MAGIC)
+ * @crc: CRC-32 checksum of the node header
+ * @sqnum: sequence number
+ * @len: full node length
+ * @node_type: node type
+ * @group_type: node group type
+ * @padding: reserved for future, zeroes
+ *
+ * Every UBIFS node starts with this common part. If the node has a key, the
+ * key always goes next.
+ */
+struct ubifs_ch {
+       uint32_t magic;
+       uint32_t crc;
+       uint64_t sqnum;
+       uint32_t len;
+       uint8_t node_type;
+       uint8_t group_type;
+       uint8_t padding[2];
+} __attribute__ ((packed));
+
+/*
+ * struct ubifs_sb_node - superblock node.
+ * @ch: common header
+ * @padding: reserved for future, zeroes
+ * @key_hash: type of hash function used in keys
+ * @key_fmt: format of the key
+ * @flags: file-system flags (%UBIFS_FLG_BIGLPT, etc)
+ * @min_io_size: minimal input/output unit size
+ * @leb_size: logical eraseblock size in bytes
+ * @leb_cnt: count of LEBs used by file-system
+ * @max_leb_cnt: maximum count of LEBs used by file-system
+ * @max_bud_bytes: maximum amount of data stored in buds
+ * @log_lebs: log size in logical eraseblocks
+ * @lpt_lebs: number of LEBs used for lprops table
+ * @orph_lebs: number of LEBs used for recording orphans
+ * @jhead_cnt: count of journal heads
+ * @fanout: tree fanout (max. number of links per indexing node)
+ * @lsave_cnt: number of LEB numbers in LPT's save table
+ * @fmt_version: UBIFS on-flash format version
+ * @default_compr: default compression algorithm (%UBIFS_COMPR_LZO, etc)
+ * @padding1: reserved for future, zeroes
+ * @rp_uid: reserve pool UID
+ * @rp_gid: reserve pool GID
+ * @rp_size: size of the reserved pool in bytes
+ * @padding2: reserved for future, zeroes
+ * @time_gran: time granularity in nanoseconds
+ * @uuid: UUID generated when the file system image was created
+ * @ro_compat_version: UBIFS R/O compatibility version
+ */
+struct ubifs_sb_node {
+       struct ubifs_ch ch;
+       uint8_t padding[2];
+       uint8_t key_hash;
+       uint8_t key_fmt;
+       uint32_t flags;
+       uint32_t min_io_size;
+       uint32_t leb_size;
+       uint32_t leb_cnt;
+       uint32_t max_leb_cnt;
+       uint64_t max_bud_bytes;
+       uint32_t log_lebs;
+       uint32_t lpt_lebs;
+       uint32_t orph_lebs;
+       uint32_t jhead_cnt;
+       uint32_t fanout;
+       uint32_t lsave_cnt;
+       uint32_t fmt_version;
+       uint16_t default_compr;
+       uint8_t padding1[2];
+       uint32_t rp_uid;
+       uint32_t rp_gid;
+       uint64_t rp_size;
+       uint32_t time_gran;
+       uint8_t uuid[16];
+       uint32_t ro_compat_version;
+       uint8_t padding2[3968];
+} __attribute__ ((packed));
+
+static int probe_ubifs(blkid_probe pr, const struct blkid_idmag *mag)
+{
+       struct ubifs_sb_node *sb;
+
+       sb = blkid_probe_get_sb(pr, mag, struct ubifs_sb_node);
+       if (!sb)
+               return -1;
+
+       blkid_probe_set_uuid(pr, sb->uuid);
+       blkid_probe_sprintf_version(pr, "w%dr%d",
+                                   sb->fmt_version, sb->ro_compat_version);
+       return 0;
+}
+
+const struct blkid_idinfo ubifs_idinfo =
+{
+       .name           = "ubifs",
+       .usage          = BLKID_USAGE_FILESYSTEM,
+       .probefunc      = probe_ubifs,
+       .magics         =
+       {
+               { .magic = "\x31\x18\x10\x06", .len = 4 },
+               { NULL }
+       }
+};
diff --git a/libblkid-tiny/vfat.c b/libblkid-tiny/vfat.c
new file mode 100644 (file)
index 0000000..c805f60
--- /dev/null
@@ -0,0 +1,433 @@
+/*
+ * Copyright (C) 1999 by Andries Brouwer
+ * Copyright (C) 1999, 2000, 2003 by Theodore Ts'o
+ * Copyright (C) 2001 by Andreas Dilger
+ * Copyright (C) 2004 Kay Sievers <kay.sievers@vrfy.org>
+ * Copyright (C) 2008 Karel Zak <kzak@redhat.com>
+ *
+ * This file may be redistributed under the terms of the
+ * GNU Lesser General Public License.
+ */
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+#include <errno.h>
+#include <ctype.h>
+#include <stdint.h>
+
+#include "superblocks.h"
+
+/* Yucky misaligned values */
+struct vfat_super_block {
+/* 00*/        unsigned char   vs_ignored[3];
+/* 03*/        unsigned char   vs_sysid[8];
+/* 0b*/        unsigned char   vs_sector_size[2];
+/* 0d*/        uint8_t         vs_cluster_size;
+/* 0e*/        uint16_t        vs_reserved;
+/* 10*/        uint8_t         vs_fats;
+/* 11*/        unsigned char   vs_dir_entries[2];
+/* 13*/        unsigned char   vs_sectors[2];
+/* 15*/        unsigned char   vs_media;
+/* 16*/        uint16_t        vs_fat_length;
+/* 18*/        uint16_t        vs_secs_track;
+/* 1a*/        uint16_t        vs_heads;
+/* 1c*/        uint32_t        vs_hidden;
+/* 20*/        uint32_t        vs_total_sect;
+/* 24*/        uint32_t        vs_fat32_length;
+/* 28*/        uint16_t        vs_flags;
+/* 2a*/        uint8_t         vs_version[2];
+/* 2c*/        uint32_t        vs_root_cluster;
+/* 30*/        uint16_t        vs_fsinfo_sector;
+/* 32*/        uint16_t        vs_backup_boot;
+/* 34*/        uint16_t        vs_reserved2[6];
+/* 40*/        unsigned char   vs_unknown[3];
+/* 43*/        unsigned char   vs_serno[4];
+/* 47*/        unsigned char   vs_label[11];
+/* 52*/        unsigned char   vs_magic[8];
+/* 5a*/        unsigned char   vs_dummy2[0x1fe - 0x5a];
+/*1fe*/        unsigned char   vs_pmagic[2];
+} __attribute__((packed));
+
+/* Yucky misaligned values */
+struct msdos_super_block {
+/* 00*/        unsigned char   ms_ignored[3];
+/* 03*/        unsigned char   ms_sysid[8];
+/* 0b*/        unsigned char   ms_sector_size[2];
+/* 0d*/        uint8_t         ms_cluster_size;
+/* 0e*/        uint16_t        ms_reserved;
+/* 10*/        uint8_t         ms_fats;
+/* 11*/        unsigned char   ms_dir_entries[2];
+/* 13*/        unsigned char   ms_sectors[2]; /* =0 iff V3 or later */
+/* 15*/        unsigned char   ms_media;
+/* 16*/        uint16_t        ms_fat_length; /* Sectors per FAT */
+/* 18*/        uint16_t        ms_secs_track;
+/* 1a*/        uint16_t        ms_heads;
+/* 1c*/        uint32_t        ms_hidden;
+/* V3 BPB */
+/* 20*/        uint32_t        ms_total_sect; /* iff ms_sectors == 0 */
+/* V4 BPB */
+/* 24*/        unsigned char   ms_unknown[3]; /* Phys drive no., resvd, V4 sig (0x29) */
+/* 27*/        unsigned char   ms_serno[4];
+/* 2b*/        unsigned char   ms_label[11];
+/* 36*/        unsigned char   ms_magic[8];
+/* 3e*/        unsigned char   ms_dummy2[0x1fe - 0x3e];
+/*1fe*/        unsigned char   ms_pmagic[2];
+} __attribute__((packed));
+
+struct vfat_dir_entry {
+       uint8_t         name[11];
+       uint8_t         attr;
+       uint16_t        time_creat;
+       uint16_t        date_creat;
+       uint16_t        time_acc;
+       uint16_t        date_acc;
+       uint16_t        cluster_high;
+       uint16_t        time_write;
+       uint16_t        date_write;
+       uint16_t        cluster_low;
+       uint32_t        size;
+} __attribute__((packed));
+
+struct fat32_fsinfo {
+       uint8_t signature1[4];
+       uint32_t reserved1[120];
+       uint8_t signature2[4];
+       uint32_t free_clusters;
+       uint32_t next_cluster;
+       uint32_t reserved2[4];
+} __attribute__((packed));
+
+/* maximum number of clusters */
+#define FAT12_MAX 0xFF4
+#define FAT16_MAX 0xFFF4
+#define FAT32_MAX 0x0FFFFFF6
+
+#define FAT_ATTR_VOLUME_ID             0x08
+#define FAT_ATTR_DIR                   0x10
+#define FAT_ATTR_LONG_NAME             0x0f
+#define FAT_ATTR_MASK                  0x3f
+#define FAT_ENTRY_FREE                 0xe5
+
+static const char *no_name = "NO NAME    ";
+
+#define unaligned_le16(x) \
+               (((unsigned char *) x)[0] + (((unsigned char *) x)[1] << 8))
+
+/*
+ * Look for LABEL (name) in the FAT root directory.
+ */
+static unsigned char *search_fat_label(blkid_probe pr,
+                               uint64_t offset, uint32_t entries)
+{
+       struct vfat_dir_entry *ent, *dir = NULL;
+       uint32_t i;
+
+       DBG(DEBUG_LOWPROBE,
+               printf("\tlook for label in root-dir "
+                       "(entries: %d, offset: %jd)\n", entries, offset));
+
+       if (!blkid_probe_is_tiny(pr)) {
+               /* large disk, read whole root directory */
+               dir = (struct vfat_dir_entry *)
+                       blkid_probe_get_buffer(pr,
+                                       offset,
+                                       (blkid_loff_t) entries *
+                                               sizeof(struct vfat_dir_entry));
+               if (!dir)
+                       return NULL;
+       }
+
+       for (i = 0; i < entries; i++) {
+               /*
+                * The root directory could be relatively large (4-16kB).
+                * Fortunately, the LABEL is usually the first entry in the
+                * directory. On tiny disks we call read() per entry.
+                */
+               if (!dir)
+                       ent = (struct vfat_dir_entry *)
+                               blkid_probe_get_buffer(pr,
+                                       (blkid_loff_t) offset + (i *
+                                               sizeof(struct vfat_dir_entry)),
+                                       sizeof(struct vfat_dir_entry));
+               else
+                       ent = &dir[i];
+
+               if (!ent || ent->name[0] == 0x00)
+                       break;
+
+               if ((ent->name[0] == FAT_ENTRY_FREE) ||
+                   (ent->cluster_high != 0 || ent->cluster_low != 0) ||
+                   ((ent->attr & FAT_ATTR_MASK) == FAT_ATTR_LONG_NAME))
+                       continue;
+
+               if ((ent->attr & (FAT_ATTR_VOLUME_ID | FAT_ATTR_DIR)) ==
+                   FAT_ATTR_VOLUME_ID) {
+                       DBG(DEBUG_LOWPROBE,
+                               printf("\tfound fs LABEL at entry %d\n", i));
+                       return ent->name;
+               }
+       }
+       return NULL;
+}
+
+static int fat_valid_superblock(const struct blkid_idmag *mag,
+                       struct msdos_super_block *ms,
+                       struct vfat_super_block *vs,
+                       uint32_t *cluster_count, uint32_t *fat_size)
+{
+       uint16_t sector_size, dir_entries, reserved;
+       uint32_t sect_count, __fat_size, dir_size, __cluster_count, fat_length;
+       uint32_t max_count;
+
+       /* extra check for FATs without magic strings */
+       if (mag->len <= 2) {
+               /* Old floppies have a valid MBR signature */
+               if (ms->ms_pmagic[0] != 0x55 || ms->ms_pmagic[1] != 0xAA)
+                       return 0;
+
+               /*
+                * OS/2 and apparently DFSee will place a FAT12/16-like
+                * pseudo-superblock in the first 512 bytes of non-FAT
+                * filesystems --- at least JFS and HPFS, and possibly others.
+                * So we explicitly check for those filesystems at the
+                * FAT12/16 filesystem magic field identifier, and if they are
+                * present, we rule this out as a FAT filesystem, despite the
+                * FAT-like pseudo-header.
+                */
+               if ((memcmp(ms->ms_magic, "JFS     ", 8) == 0) ||
+                   (memcmp(ms->ms_magic, "HPFS    ", 8) == 0))
+                       return 0;
+       }
+
+       /* fat counts(Linux kernel expects at least 1 FAT table) */
+       if (!ms->ms_fats)
+               return 0;
+       if (!ms->ms_reserved)
+               return 0;
+       if (!(0xf8 <= ms->ms_media || ms->ms_media == 0xf0))
+               return 0;
+       if (!is_power_of_2(ms->ms_cluster_size))
+               return 0;
+
+       sector_size = unaligned_le16(&ms->ms_sector_size);
+       if (!is_power_of_2(sector_size) ||
+           sector_size < 512 || sector_size > 4096)
+               return 0;
+
+       dir_entries = unaligned_le16(&ms->ms_dir_entries);
+       reserved =  le16_to_cpu(ms->ms_reserved);
+       sect_count = unaligned_le16(&ms->ms_sectors);
+
+       if (sect_count == 0)
+               sect_count = le32_to_cpu(ms->ms_total_sect);
+
+       fat_length = le16_to_cpu(ms->ms_fat_length);
+       if (fat_length == 0)
+               fat_length = le32_to_cpu(vs->vs_fat32_length);
+
+       __fat_size = fat_length * ms->ms_fats;
+       dir_size = ((dir_entries * sizeof(struct vfat_dir_entry)) +
+                                       (sector_size-1)) / sector_size;
+
+       __cluster_count = (sect_count - (reserved + __fat_size + dir_size)) /
+                                                       ms->ms_cluster_size;
+       if (!ms->ms_fat_length && vs->vs_fat32_length)
+               max_count = FAT32_MAX;
+       else
+               max_count = __cluster_count > FAT12_MAX ? FAT16_MAX : FAT12_MAX;
+
+       if (__cluster_count > max_count)
+               return 0;
+
+       if (fat_size)
+               *fat_size = __fat_size;
+       if (cluster_count)
+               *cluster_count = __cluster_count;
+
+       return 1;       /* valid */
+}
+
+/*
+ * This function is used by MBR partition table parser to avoid
+ * misinterpretation of FAT filesystem.
+ */
+/*static int blkid_probe_is_vfat(blkid_probe pr)
+{
+       struct vfat_super_block *vs;
+       struct msdos_super_block *ms;
+       const struct blkid_idmag *mag = NULL;
+
+       if (blkid_probe_get_idmag(pr, &vfat_idinfo, NULL, &mag) || !mag)
+               return 0;
+
+       ms = blkid_probe_get_sb(pr, mag, struct msdos_super_block);
+       if (!ms)
+               return 0;
+       vs = blkid_probe_get_sb(pr, mag, struct vfat_super_block);
+       if (!vs)
+               return 0;
+
+       return fat_valid_superblock(mag, ms, vs, NULL, NULL);
+}*/
+static struct vfat_super_block vs;
+static struct msdos_super_block ms;
+
+/* FAT label extraction from the root directory taken from Kay
+ * Sievers's volume_id library */
+static int probe_vfat(blkid_probe pr, const struct blkid_idmag *mag)
+{
+       struct vfat_super_block *_vs;
+       struct msdos_super_block *_ms;
+       const unsigned char *vol_label = 0;
+       unsigned char *vol_serno = NULL, vol_label_buf[11];
+       uint16_t sector_size = 0, reserved;
+       uint32_t cluster_count, fat_size;
+       const char *version = NULL;
+
+       _ms = blkid_probe_get_sb(pr, mag, struct msdos_super_block);
+       if (!_ms)
+               return 0;
+       _vs = blkid_probe_get_sb(pr, mag, struct vfat_super_block);
+       if (!_vs)
+               return 0;
+       memcpy(&ms, _ms, sizeof(struct vfat_super_block));
+       memcpy(&vs, _vs, sizeof(struct msdos_super_block));
+       if (!fat_valid_superblock(mag, &ms, &vs, &cluster_count, &fat_size))
+               return 1;
+
+       sector_size = unaligned_le16(&ms.ms_sector_size);
+       reserved =  le16_to_cpu(ms.ms_reserved);
+
+       if (ms.ms_fat_length) {
+               /* the label may be an attribute in the root directory */
+               uint32_t root_start = (reserved + fat_size) * sector_size;
+               uint32_t root_dir_entries = unaligned_le16(&vs.vs_dir_entries);
+
+               vol_label = search_fat_label(pr, root_start, root_dir_entries);
+               if (vol_label) {
+                       memcpy(vol_label_buf, vol_label, 11);
+                       vol_label = vol_label_buf;
+               }
+
+               if (!vol_label || !memcmp(vol_label, no_name, 11))
+                       vol_label = ms.ms_label;
+               vol_serno = ms.ms_serno;
+
+               blkid_probe_set_value(pr, "SEC_TYPE", (unsigned char *) "msdos",
+                              sizeof("msdos"));
+
+               if (cluster_count < FAT12_MAX)
+                       version = "FAT12";
+               else if (cluster_count < FAT16_MAX)
+                       version = "FAT16";
+
+       } else if (vs.vs_fat32_length) {
+               unsigned char *buf;
+               uint16_t fsinfo_sect;
+               int maxloop = 100;
+
+               /* Search the FAT32 root dir for the label attribute */
+               uint32_t buf_size = vs.vs_cluster_size * sector_size;
+               uint32_t start_data_sect = reserved + fat_size;
+               uint32_t entries = le32_to_cpu(vs.vs_fat32_length) *
+                                       sector_size / sizeof(uint32_t);
+               uint32_t next = le32_to_cpu(vs.vs_root_cluster);
+
+               while (next && next < entries && --maxloop) {
+                       uint32_t next_sect_off;
+                       uint64_t next_off, fat_entry_off;
+                       int count;
+
+                       next_sect_off = (next - 2) * le32_to_cpu(vs.vs_cluster_size);
+                       next_off = (uint64_t)(start_data_sect + next_sect_off) *
+                               sector_size;
+
+                       count = buf_size / sizeof(struct vfat_dir_entry);
+
+                       vol_label = search_fat_label(pr, next_off, count);
+                       if (vol_label) {
+                               memcpy(vol_label_buf, vol_label, 11);
+                               vol_label = vol_label_buf;
+                               break;
+                       }
+
+                       /* get FAT entry */
+                       fat_entry_off = ((uint64_t) reserved * sector_size) +
+                               (next * sizeof(uint32_t));
+                       buf = blkid_probe_get_buffer(pr, fat_entry_off, buf_size);
+                       if (buf == NULL)
+                               break;
+
+                       /* set next cluster */
+                       next = le32_to_cpu(*((uint32_t *) buf)) & 0x0fffffff;
+               }
+
+               version = "FAT32";
+
+               if (!vol_label || !memcmp(vol_label, no_name, 11))
+                       vol_label = NULL;
+               vol_serno = vs.vs_serno;
+
+               /*
+                * FAT32 should have a valid signature in the fsinfo block,
+                * but also allow all bytes set to '\0', because some volumes
+                * do not set the signature at all.
+                */
+               fsinfo_sect = le16_to_cpu(vs.vs_fsinfo_sector);
+               if (fsinfo_sect) {
+                       struct fat32_fsinfo *fsinfo;
+
+                       buf = blkid_probe_get_buffer(pr,
+                                       (blkid_loff_t) fsinfo_sect * sector_size,
+                                       sizeof(struct fat32_fsinfo));
+                       if (buf == NULL)
+                               return -1;
+
+                       fsinfo = (struct fat32_fsinfo *) buf;
+                       *fsinfo->signature1 = le32_to_cpu(*fsinfo->signature1);
+                       *fsinfo->signature2 = le32_to_cpu(*fsinfo->signature2);
+                       if (memcmp(fsinfo->signature1, "\x52\x52\x61\x41", 4) != 0 &&
+                           memcmp(fsinfo->signature1, "\x52\x52\x64\x41", 4) != 0 &&
+                           memcmp(fsinfo->signature1, "\x00\x00\x00\x00", 4) != 0)
+                               return -1;
+                       if (memcmp(fsinfo->signature2, "\x72\x72\x41\x61", 4) != 0 &&
+                           memcmp(fsinfo->signature2, "\x00\x00\x00\x00", 4) != 0)
+                               return -1;
+               }
+       }
+
+       if (vol_label && memcmp(vol_label, no_name, 11))
+               blkid_probe_set_label(pr, (unsigned char *) vol_label, 11);
+
+       /* We can't just print them as %04X, because they are unaligned */
+       if (vol_serno)
+               blkid_probe_sprintf_uuid(pr, vol_serno, 4, "%02x%02x-%02x%02x",
+                       vol_serno[3], vol_serno[2], vol_serno[1], vol_serno[0]);
+       if (version)
+               blkid_probe_set_version(pr, version);
+
+       return 0;
+}
+
+
+const struct blkid_idinfo vfat_idinfo =
+{
+       .name           = "vfat",
+       .usage          = BLKID_USAGE_FILESYSTEM,
+       .probefunc      = probe_vfat,
+       .magics         =
+       {
+               { .magic = "MSWIN",    .len = 5, .sboff = 0x52 },
+               { .magic = "FAT32   ", .len = 8, .sboff = 0x52 },
+               { .magic = "MSDOS",    .len = 5, .sboff = 0x36 },
+               { .magic = "FAT16   ", .len = 8, .sboff = 0x36 },
+               { .magic = "FAT12   ", .len = 8, .sboff = 0x36 },
+               { .magic = "FAT     ", .len = 8, .sboff = 0x36 },
+               { .magic = "\353",     .len = 1, },
+               { .magic = "\351",     .len = 1, },
+               { .magic = "\125\252", .len = 2, .sboff = 0x1fe },
+               { NULL }
+       }
+};
+