[LEDE-DEV] [PATCH fstools] libblkid-tiny: add support for NTFS superblock
John Crispin
john at phrozen.org
Fri Dec 29 13:30:26 PST 2017
On 25/12/17 20:52, Rafał Miłecki wrote:
> From: Rafał Miłecki <rafal at milecki.pl>
>
> Its copied from the util-linux project and its libblkid. Call to the
> blkid_probe_set_utf8label was commented out due to libblkid-tiny not
> supporting it yet.
>
> Signed-off-by: Rafał Miłecki <rafal at milecki.pl>
Acked-by: John Crispin <john at phrozen.org>
> ---
> CMakeLists.txt | 1 +
> libblkid-tiny/libblkid-tiny.c | 1 +
> libblkid-tiny/ntfs.c | 228 ++++++++++++++++++++++++++++++++++++++++++
> 3 files changed, 230 insertions(+)
> create mode 100644 libblkid-tiny/ntfs.c
>
> diff --git a/CMakeLists.txt b/CMakeLists.txt
> index 8752612..9e855bd 100644
> --- a/CMakeLists.txt
> +++ b/CMakeLists.txt
> @@ -24,6 +24,7 @@ ADD_LIBRARY(blkid-tiny SHARED
> libblkid-tiny/ext.c
> libblkid-tiny/jffs2.c
> libblkid-tiny/vfat.c
> + libblkid-tiny/ntfs.c
> libblkid-tiny/hfs.c
> libblkid-tiny/swap.c
> libblkid-tiny/ubi.c
> diff --git a/libblkid-tiny/libblkid-tiny.c b/libblkid-tiny/libblkid-tiny.c
> index 352d1f6..f020e23 100644
> --- a/libblkid-tiny/libblkid-tiny.c
> +++ b/libblkid-tiny/libblkid-tiny.c
> @@ -162,6 +162,7 @@ static const struct blkid_idinfo *idinfos[] =
> &ext3_idinfo,
> &ext2_idinfo,
> &jbd_idinfo,
> + &ntfs_idinfo,
> &squashfs_idinfo,
> &ubi_idinfo,
> &ubifs_idinfo,
> diff --git a/libblkid-tiny/ntfs.c b/libblkid-tiny/ntfs.c
> new file mode 100644
> index 0000000..93c1d88
> --- /dev/null
> +++ b/libblkid-tiny/ntfs.c
> @@ -0,0 +1,228 @@
> +/*
> + * Copyright (C) 2004 Kay Sievers <kay.sievers at vrfy.org>
> + * Copyright (C) 2008 Karel Zak <kzak at 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 <inttypes.h>
> +
> +#include "superblocks.h"
> +
> +struct ntfs_bios_parameters {
> + uint16_t sector_size; /* Size of a sector in bytes. */
> + uint8_t sectors_per_cluster; /* Size of a cluster in sectors. */
> + uint16_t reserved_sectors; /* zero */
> + uint8_t fats; /* zero */
> + uint16_t root_entries; /* zero */
> + uint16_t sectors; /* zero */
> + uint8_t media_type; /* 0xf8 = hard disk */
> + uint16_t sectors_per_fat; /* zero */
> + uint16_t sectors_per_track; /* irrelevant */
> + uint16_t heads; /* irrelevant */
> + uint32_t hidden_sectors; /* zero */
> + uint32_t large_sectors; /* zero */
> +} __attribute__ ((__packed__));
> +
> +struct ntfs_super_block {
> + uint8_t jump[3];
> + uint8_t oem_id[8]; /* magic string */
> +
> + struct ntfs_bios_parameters bpb;
> +
> + uint16_t unused[2];
> + uint64_t number_of_sectors;
> + uint64_t mft_cluster_location;
> + uint64_t mft_mirror_cluster_location;
> + int8_t clusters_per_mft_record;
> + uint8_t reserved1[3];
> + int8_t cluster_per_index_record;
> + uint8_t reserved2[3];
> + uint64_t volume_serial;
> + uint32_t checksum;
> +} __attribute__((packed));
> +
> +struct master_file_table_record {
> + uint32_t magic;
> + uint16_t usa_ofs;
> + uint16_t usa_count;
> + uint64_t lsn;
> + uint16_t sequence_number;
> + uint16_t link_count;
> + uint16_t attrs_offset;
> + uint16_t flags;
> + uint32_t bytes_in_use;
> + uint32_t bytes_allocated;
> +} __attribute__((__packed__));
> +
> +struct file_attribute {
> + uint32_t type;
> + uint32_t len;
> + uint8_t non_resident;
> + uint8_t name_len;
> + uint16_t name_offset;
> + uint16_t flags;
> + uint16_t instance;
> + uint32_t value_len;
> + uint16_t value_offset;
> +} __attribute__((__packed__));
> +
> +#define MFT_RECORD_VOLUME 3
> +#define NTFS_MAX_CLUSTER_SIZE (64 * 1024)
> +
> +enum {
> + MFT_RECORD_ATTR_VOLUME_NAME = 0x60,
> + MFT_RECORD_ATTR_END = 0xffffffff
> +};
> +
> +static int probe_ntfs(blkid_probe pr, const struct blkid_idmag *mag)
> +{
> + struct ntfs_super_block *ns;
> +#if 0
> + struct master_file_table_record *mft;
> +#endif
> +
> + uint32_t sectors_per_cluster, mft_record_size;
> + uint16_t sector_size;
> + uint64_t nr_clusters, off; //, attr_off;
> + unsigned char *buf_mft;
> +
> + ns = blkid_probe_get_sb(pr, mag, struct ntfs_super_block);
> + if (!ns)
> + return errno ? -errno : 1;
> +
> + /*
> + * Check bios parameters block
> + */
> + sector_size = le16_to_cpu(ns->bpb.sector_size);
> + sectors_per_cluster = ns->bpb.sectors_per_cluster;
> +
> + if (sector_size < 256 || sector_size > 4096)
> + return 1;
> +
> + switch (sectors_per_cluster) {
> + case 1: case 2: case 4: case 8: case 16: case 32: case 64: case 128:
> + break;
> + default:
> + return 1;
> + }
> +
> + if ((uint16_t) le16_to_cpu(ns->bpb.sector_size) *
> + ns->bpb.sectors_per_cluster > NTFS_MAX_CLUSTER_SIZE)
> + return 1;
> +
> + /* Unused fields must be zero */
> + if (le16_to_cpu(ns->bpb.reserved_sectors)
> + || le16_to_cpu(ns->bpb.root_entries)
> + || le16_to_cpu(ns->bpb.sectors)
> + || le16_to_cpu(ns->bpb.sectors_per_fat)
> + || le32_to_cpu(ns->bpb.large_sectors)
> + || ns->bpb.fats)
> + return 1;
> +
> + if ((uint8_t) ns->clusters_per_mft_record < 0xe1
> + || (uint8_t) ns->clusters_per_mft_record > 0xf7) {
> +
> + switch (ns->clusters_per_mft_record) {
> + case 1: case 2: case 4: case 8: case 16: case 32: case 64:
> + break;
> + default:
> + return 1;
> + }
> + }
> +
> + if (ns->clusters_per_mft_record > 0)
> + mft_record_size = ns->clusters_per_mft_record *
> + sectors_per_cluster * sector_size;
> + else
> + mft_record_size = 1 << (0 - ns->clusters_per_mft_record);
> +
> + nr_clusters = le64_to_cpu(ns->number_of_sectors) / sectors_per_cluster;
> +
> + if ((le64_to_cpu(ns->mft_cluster_location) > nr_clusters) ||
> + (le64_to_cpu(ns->mft_mirror_cluster_location) > nr_clusters))
> + return 1;
> +
> +
> + off = le64_to_cpu(ns->mft_cluster_location) * sector_size *
> + sectors_per_cluster;
> +
> + DBG(LOWPROBE, ul_debug("NTFS: sector_size=%"PRIu16", mft_record_size=%"PRIu32", "
> + "sectors_per_cluster=%"PRIu32", nr_clusters=%"PRIu64" "
> + "cluster_offset=%"PRIu64"",
> + sector_size, mft_record_size,
> + sectors_per_cluster, nr_clusters,
> + off));
> +
> + buf_mft = blkid_probe_get_buffer(pr, off, mft_record_size);
> + if (!buf_mft)
> + return errno ? -errno : 1;
> +
> + if (memcmp(buf_mft, "FILE", 4))
> + return 1;
> +
> + off += MFT_RECORD_VOLUME * mft_record_size;
> +
> + buf_mft = blkid_probe_get_buffer(pr, off, mft_record_size);
> + if (!buf_mft)
> + return errno ? -errno : 1;
> +
> + if (memcmp(buf_mft, "FILE", 4))
> + return 1;
> +
> +#if 0
> + mft = (struct master_file_table_record *) buf_mft;
> + attr_off = le16_to_cpu(mft->attrs_offset);
> +
> + while (attr_off + sizeof(struct file_attribute) <= mft_record_size &&
> + attr_off <= le32_to_cpu(mft->bytes_allocated)) {
> +
> + uint32_t attr_len;
> + struct file_attribute *attr;
> +
> + attr = (struct file_attribute *) (buf_mft + attr_off);
> + attr_len = le32_to_cpu(attr->len);
> + if (!attr_len)
> + break;
> +
> + if (le32_to_cpu(attr->type) == MFT_RECORD_ATTR_END)
> + break;
> + if (le32_to_cpu(attr->type) == MFT_RECORD_ATTR_VOLUME_NAME) {
> + unsigned int val_off = le16_to_cpu(attr->value_offset);
> + unsigned int val_len = le32_to_cpu(attr->value_len);
> + unsigned char *val = ((uint8_t *) attr) + val_off;
> +
> + if (attr_off + val_off + val_len <= mft_record_size)
> + blkid_probe_set_utf8label(pr, val, val_len,
> + BLKID_ENC_UTF16LE);
> + break;
> + }
> +
> + attr_off += attr_len;
> + }
> +#endif
> +
> + blkid_probe_sprintf_uuid(pr,
> + (unsigned char *) &ns->volume_serial,
> + sizeof(ns->volume_serial),
> + "%016" PRIX64, le64_to_cpu(ns->volume_serial));
> + return 0;
> +}
> +
> +
> +const struct blkid_idinfo ntfs_idinfo =
> +{
> + .name = "ntfs",
> + .usage = BLKID_USAGE_FILESYSTEM,
> + .probefunc = probe_ntfs,
> + .magics =
> + {
> + { .magic = "NTFS ", .len = 8, .sboff = 3 },
> + { NULL }
> + }
> +};
> +
More information about the Lede-dev
mailing list