summaryrefslogtreecommitdiff
path: root/package/system/fstools/patches/002-ntfs-exfat.patch
diff options
context:
space:
mode:
Diffstat (limited to 'package/system/fstools/patches/002-ntfs-exfat.patch')
-rw-r--r--package/system/fstools/patches/002-ntfs-exfat.patch525
1 files changed, 525 insertions, 0 deletions
diff --git a/package/system/fstools/patches/002-ntfs-exfat.patch b/package/system/fstools/patches/002-ntfs-exfat.patch
new file mode 100644
index 0000000..3d8c7e5
--- /dev/null
+++ b/package/system/fstools/patches/002-ntfs-exfat.patch
@@ -0,0 +1,525 @@
+Index: fstools-2015-02-25.1/CMakeLists.txt
+===================================================================
+--- fstools-2015-02-25.1.orig/CMakeLists.txt
++++ fstools-2015-02-25.1/CMakeLists.txt
+@@ -23,6 +23,8 @@ ADD_LIBRARY(blkid-tiny SHARED
+ libblkid-tiny/ext.c
+ libblkid-tiny/jffs2.c
+ libblkid-tiny/vfat.c
++ libblkid-tiny/ntfs.c
++ libblkid-tiny/exfat.c
+ libblkid-tiny/hfs.c
+ libblkid-tiny/swap.c
+ libblkid-tiny/ubifs.c
+Index: fstools-2015-02-25.1/libblkid-tiny/libblkid-tiny.c
+===================================================================
+--- fstools-2015-02-25.1.orig/libblkid-tiny/libblkid-tiny.c
++++ fstools-2015-02-25.1/libblkid-tiny/libblkid-tiny.c
+@@ -10,6 +10,8 @@
+ #define DEBUG(fmt, ...)
+ #endif
+
++#define isspace(x) ((x == ' ') || (x == '\t') || (x == '\r') || (x == '\n'))
++
+ int blkid_debug_mask = 0;
+
+ static unsigned char *probe_buffer;
+@@ -152,9 +154,77 @@ int blkid_probe_sprintf_uuid(blkid_probe
+ return 0;
+ }
+
++size_t blkid_encode_to_utf8(int enc, unsigned char *dest, size_t len,
++ const unsigned char *src, size_t count)
++{
++ size_t i, j;
++ uint16_t c;
++
++ for (j = i = 0; i + 2 <= count; i += 2)
++ {
++ if (enc == BLKID_ENC_UTF16LE)
++ c = (src[i+1] << 8) | src[i];
++ else /* BLKID_ENC_UTF16BE */
++ c = (src[i] << 8) | src[i+1];
++ if (c == 0)
++ {
++ dest[j] = '\0';
++ break;
++ }
++ else if (c < 0x80)
++ {
++ if (j+1 >= len)
++ break;
++ dest[j++] = (uint8_t) c;
++ }
++ else if (c < 0x800)
++ {
++ if (j+2 >= len)
++ break;
++ dest[j++] = (uint8_t) (0xc0 | (c >> 6));
++ dest[j++] = (uint8_t) (0x80 | (c & 0x3f));
++ }
++ else
++ {
++ if (j+3 >= len)
++ break;
++ dest[j++] = (uint8_t) (0xe0 | (c >> 12));
++ dest[j++] = (uint8_t) (0x80 | ((c >> 6) & 0x3f));
++ dest[j++] = (uint8_t) (0x80 | (c & 0x3f));
++ }
++ }
++ dest[j] = '\0';
++ return j;
++}
++
++size_t blkid_rtrim_whitespace(unsigned char *str)
++{
++ size_t i = strlen((char *) str);
++
++ while (i--)
++ {
++ if (!isspace(str[i]))
++ break;
++ }
++ str[++i] = '\0';
++ return i;
++}
++
++int blkid_probe_set_utf8label(blkid_probe pr, unsigned char *label,
++ size_t len, int enc)
++{
++ blkid_encode_to_utf8(enc, (unsigned char *) pr->label, sizeof(pr->label), label, len);
++ blkid_rtrim_whitespace((unsigned char *) pr->label);
++ return 0;
++}
++
++
++
+ static const struct blkid_idinfo *idinfos[] =
+ {
+ &vfat_idinfo,
++ &ntfs_idinfo,
++ &exfat_idinfo,
+ &swsuspend_idinfo,
+ &swap_idinfo,
+ &ext4dev_idinfo,
+Index: fstools-2015-02-25.1/libblkid-tiny/ntfs.c
+===================================================================
+--- /dev/null
++++ fstools-2015-02-25.1/libblkid-tiny/ntfs.c
+@@ -0,0 +1,246 @@
++/*
++ * 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 <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;
++ struct master_file_table_record *mft;
++
++ uint32_t sectors_per_cluster, mft_record_size, attr_off;
++ uint16_t sector_size;
++ uint64_t nr_clusters, off;
++ unsigned char *buf_mft;
++
++ ns = blkid_probe_get_sb(pr, mag, struct ntfs_super_block);
++ if (!ns)
++ return -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(DEBUG_LOWPROBE, printf("NTFS: sector_size=%d, mft_record_size=%d, "
++ "sectors_per_cluster=%d, nr_clusters=%ju "
++ "cluster_offset=%jd",
++ (int) 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 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 1;
++
++ if (memcmp(buf_mft, "FILE", 4))
++ return 1;
++
++ mft = (struct master_file_table_record *) buf_mft;
++ attr_off = le16_to_cpu(mft->attrs_offset);
++
++ while (attr_off < 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;
++
++ blkid_probe_set_utf8label(pr, val, val_len, BLKID_ENC_UTF16LE);
++ break;
++ }
++
++ if (UINT_MAX - attr_len < attr_off)
++ break;
++ attr_off += attr_len;
++ }
++
++ 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 = 5, .sboff = 3 },
++ { NULL }
++ }
++};
+Index: fstools-2015-02-25.1/libblkid-tiny/exfat.c
+===================================================================
+--- /dev/null
++++ fstools-2015-02-25.1/libblkid-tiny/exfat.c
+@@ -0,0 +1,151 @@
++/*
++ * Copyright (C) 2010 Andrew Nayenko <resver@gmail.com>
++ *
++ * This file may be redistributed under the terms of the
++ * GNU Lesser General Public License.
++ */
++#include "superblocks.h"
++
++struct exfat_super_block
++{
++ uint8_t jump[3];
++ uint8_t oem_name[8];
++ uint8_t __unused1[53];
++ uint64_t block_start;
++ uint64_t block_count;
++ uint32_t fat_block_start;
++ uint32_t fat_block_count;
++ uint32_t cluster_block_start;
++ uint32_t cluster_count;
++ uint32_t rootdir_cluster;
++ uint8_t volume_serial[4];
++ struct
++ {
++ uint8_t minor;
++ uint8_t major;
++ } version;
++ uint16_t volume_state;
++ uint8_t block_bits;
++ uint8_t bpc_bits;
++ uint8_t fat_count;
++ uint8_t drive_no;
++ uint8_t allocated_percent;
++} __attribute__((__packed__));
++
++struct exfat_entry_label
++{
++ uint8_t type;
++ uint8_t length;
++ uint8_t name[30];
++} __attribute__((__packed__));
++
++#define BLOCK_SIZE(sb) (1 << (sb)->block_bits)
++#define CLUSTER_SIZE(sb) (BLOCK_SIZE(sb) << (sb)->bpc_bits)
++#define EXFAT_FIRST_DATA_CLUSTER 2
++#define EXFAT_LAST_DATA_CLUSTER 0xffffff6
++#define EXFAT_ENTRY_SIZE 32
++
++#define EXFAT_ENTRY_EOD 0x00
++#define EXFAT_ENTRY_LABEL 0x83
++
++static blkid_loff_t block_to_offset(const struct exfat_super_block *sb,
++ blkid_loff_t block)
++{
++ return (blkid_loff_t) block << sb->block_bits;
++}
++
++static blkid_loff_t cluster_to_block(const struct exfat_super_block *sb,
++ uint32_t cluster)
++{
++ return le32_to_cpu(sb->cluster_block_start) +
++ ((blkid_loff_t) (cluster - EXFAT_FIRST_DATA_CLUSTER)
++ << sb->bpc_bits);
++}
++
++static blkid_loff_t cluster_to_offset(const struct exfat_super_block *sb,
++ uint32_t cluster)
++{
++ return block_to_offset(sb, cluster_to_block(sb, cluster));
++}
++
++static uint32_t next_cluster(blkid_probe pr,
++ const struct exfat_super_block *sb, uint32_t cluster)
++{
++ uint32_t *next;
++ blkid_loff_t fat_offset;
++
++ fat_offset = block_to_offset(sb, le32_to_cpu(sb->fat_block_start))
++ + (blkid_loff_t) cluster * sizeof(cluster);
++ next = (uint32_t *) blkid_probe_get_buffer(pr, fat_offset,
++ sizeof(uint32_t));
++ if (!next)
++ return 0;
++ return le32_to_cpu(*next);
++}
++
++static struct exfat_entry_label *find_label(blkid_probe pr,
++ const struct exfat_super_block *sb)
++{
++ uint32_t cluster = le32_to_cpu(sb->rootdir_cluster);
++ blkid_loff_t offset = cluster_to_offset(sb, cluster);
++ uint8_t *entry;
++
++ for (;;)
++ {
++ entry = (uint8_t *) blkid_probe_get_buffer(pr, offset,
++ EXFAT_ENTRY_SIZE);
++ if (!entry)
++ return NULL;
++ if (entry[0] == EXFAT_ENTRY_EOD)
++ return NULL;
++ if (entry[0] == EXFAT_ENTRY_LABEL)
++ return (struct exfat_entry_label *) entry;
++ offset += EXFAT_ENTRY_SIZE;
++ if (offset % CLUSTER_SIZE(sb) == 0)
++ {
++ cluster = next_cluster(pr, sb, cluster);
++ if (cluster < EXFAT_FIRST_DATA_CLUSTER)
++ return NULL;
++ if (cluster > EXFAT_LAST_DATA_CLUSTER)
++ return NULL;
++ offset = cluster_to_offset(sb, cluster);
++ }
++ }
++}
++
++static int probe_exfat(blkid_probe pr, const struct blkid_idmag *mag)
++{
++ struct exfat_super_block *sb;
++ struct exfat_entry_label *label;
++
++ sb = blkid_probe_get_sb(pr, mag, struct exfat_super_block);
++ if (!sb)
++ return -1;
++
++ blkid_probe_sprintf_uuid(pr, sb->volume_serial, 4,
++ "%02hhX%02hhX-%02hhX%02hhX",
++ sb->volume_serial[3], sb->volume_serial[2],
++ sb->volume_serial[1], sb->volume_serial[0]);
++
++ blkid_probe_sprintf_version(pr, "%u.%u",
++ sb->version.major, sb->version.minor);
++
++ label = find_label(pr, sb);
++ if (label)
++ blkid_probe_set_utf8label(pr, label->name,
++ min(label->length * 2, 30), BLKID_ENC_UTF16LE);
++
++ return 0;
++}
++
++const struct blkid_idinfo exfat_idinfo =
++{
++ .name = "exfat",
++ .usage = BLKID_USAGE_FILESYSTEM,
++ .probefunc = probe_exfat,
++ .magics =
++ {
++ { .magic = "EXFAT ", .len = 8, .sboff = 3 },
++ { NULL }
++ }
++};
+Index: fstools-2015-02-25.1/libblkid-tiny/superblocks.h
+===================================================================
+--- fstools-2015-02-25.1.orig/libblkid-tiny/superblocks.h
++++ fstools-2015-02-25.1/libblkid-tiny/superblocks.h
+@@ -87,6 +87,8 @@ extern int blkid_probe_strncpy_uuid(blki
+
+ 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);
+-
++extern size_t blkid_encode_to_utf8(int enc, unsigned char *dest, size_t len,
++ const unsigned char *src, size_t count);
++
+
+ #endif /* _BLKID_SUPERBLOCKS_H */