diff options
Diffstat (limited to 'package/system/fstools/patches/002-ntfs-exfat.patch')
-rw-r--r-- | package/system/fstools/patches/002-ntfs-exfat.patch | 525 |
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 */ |