From 763047bfb10e145ce8fbe2df6ab0f3a9aa2d4ff3 Mon Sep 17 00:00:00 2001 From: Augustin Cavalier Date: Sat, 31 Aug 2019 23:26:28 -0400 Subject: [PATCH] NTFS: Merge changes to the utils from upstream. --- .../kernel/file_systems/ntfs/utils/mkntfs.c | 98 ++++++++++++++++--- .../kernel/file_systems/ntfs/utils/utils.c | 22 ++++- 2 files changed, 107 insertions(+), 13 deletions(-) diff --git a/src/add-ons/kernel/file_systems/ntfs/utils/mkntfs.c b/src/add-ons/kernel/file_systems/ntfs/utils/mkntfs.c index dc32faf1e6..717703a5a8 100644 --- a/src/add-ons/kernel/file_systems/ntfs/utils/mkntfs.c +++ b/src/add-ons/kernel/file_systems/ntfs/utils/mkntfs.c @@ -6,7 +6,7 @@ * Copyright (c) 2002-2006 Szabolcs Szakacsits * Copyright (c) 2005 Erik Sornes * Copyright (c) 2007 Yura Pakhuchiy - * Copyright (c) 2010 Jean-Pierre Andre + * Copyright (c) 2010-2014 Jean-Pierre Andre * * This utility will create an NTFS 1.2 or 3.1 volume on a user * specified (block) device. @@ -161,6 +161,18 @@ struct BITMAP_ALLOCATION { s64 length; /* count of consecutive clusters */ } ; + /* Upcase $Info, used since Windows 8 */ +struct UPCASEINFO { + le32 len; + le32 filler; + le64 crc; + le32 osmajor; + le32 osminor; + le32 build; + le16 packmajor; + le16 packminor; +} ; + /** * global variables */ @@ -170,6 +182,7 @@ static u8 *g_mft_bitmap = NULL; static int g_lcn_bitmap_byte_size = 0; static int g_dynamic_buf_size = 0; static u8 *g_dynamic_buf = NULL; +static struct UPCASEINFO *g_upcaseinfo = NULL; static runlist *g_rl_mft = NULL; static runlist *g_rl_mft_bmp = NULL; static runlist *g_rl_mftmirr = NULL; @@ -211,6 +224,53 @@ static struct mkntfs_options { char *label; /* -L, volume label */ } opts; +/* + * crc64, adapted from http://rpm5.org/docs/api/digest_8c-source.html + * ECMA-182 polynomial, see + * http://www.ecma-international.org/publications/files/ECMA-ST/Ecma-182.pdf + */ + /* make sure the needed types are defined */ +#undef byte +#undef uint32_t +#undef uint64_t +#define byte u8 +#define uint32_t u32 +#define uint64_t u64 +static uint64_t crc64(uint64_t crc, const byte * data, size_t size) + /*@*/ +{ + static uint64_t polynomial = 0x9a6c9329ac4bc9b5ULL; + static uint64_t xorout = 0xffffffffffffffffULL; + static uint64_t table[256]; + + crc ^= xorout; + + if (data == NULL) { + /* generate the table of CRC remainders for all possible bytes */ + uint64_t c; + uint32_t i, j; + for (i = 0; i < 256; i++) { + c = i; + for (j = 0; j < 8; j++) { + if (c & 1) + c = polynomial ^ (c >> 1); + else + c = (c >> 1); + } + table[i] = c; + } + } else + while (size) { + crc = table[(crc ^ *data) & 0xff] ^ (crc >> 8); + size--; + data++; + } + + crc ^= xorout; + + return crc; +} + /* * Mark a run of clusters as allocated * @@ -1490,7 +1550,7 @@ static int insert_resident_attr_in_mft_record(MFT_RECORD *m, } a = ctx->attr; /* sizeof(resident attribute record header) == 24 */ - asize = ((24 + ((name_len + 7) & ~7) + val_len) + 7) & ~7; + asize = ((24 + ((name_len*2 + 7) & ~7) + val_len) + 7) & ~7; err = make_room_for_attribute(m, (char*)a, asize); if (err == -ENOSPC) { /* @@ -4212,6 +4272,14 @@ static BOOL mkntfs_create_root_structures(void) m = (MFT_RECORD*)(g_buf + 4 * g_vol->mft_record_size); err = add_attr_data(m, NULL, 0, CASE_SENSITIVE, const_cpu_to_le16(0), (u8*)g_vol->attrdef, g_vol->attrdef_len); + /* + * The $Info only exists since Windows 8, but it apparently + * does not disturb chkdsk from earlier versions. + */ + if (!err) + err = add_attr_data(m, "$Info", 5, CASE_SENSITIVE, + const_cpu_to_le16(0), + (u8*)g_upcaseinfo, sizeof(struct UPCASEINFO)); if (!err) err = create_hardlink(g_index_block, root_ref, m, MK_LE_MREF(FILE_AttrDef, FILE_AttrDef), @@ -4572,6 +4640,7 @@ static BOOL mkntfs_create_root_structures(void) */ static int mkntfs_redirect(struct mkntfs_options *opts2) { + u64 upcase_crc; int result = 1; ntfs_attr_search_ctx *ctx = NULL; long long lw, pos; @@ -4605,12 +4674,20 @@ static int mkntfs_redirect(struct mkntfs_options *opts2) if (opts.cluster_size >= 0) g_vol->cluster_size = opts.cluster_size; /* Length is in unicode characters. */ - g_vol->upcase_len = 65536; - g_vol->upcase = ntfs_malloc(g_vol->upcase_len * sizeof(ntfschar)); - if (!g_vol->upcase) + g_vol->upcase_len = ntfs_upcase_build_default(&g_vol->upcase); + /* Since Windows 8, there is a $Info stream in $UpCase */ + g_upcaseinfo = + (struct UPCASEINFO*)ntfs_malloc(sizeof(struct UPCASEINFO)); + if (!g_vol->upcase_len || !g_upcaseinfo) goto done; - ntfs_upcase_table_build(g_vol->upcase, + /* If the CRC is correct, chkdsk does not warn about obsolete table */ + crc64(0,(byte*)NULL,0); /* initialize the crc computation */ + upcase_crc = crc64(0,(byte*)g_vol->upcase, g_vol->upcase_len * sizeof(ntfschar)); + /* keep the version fields as zero */ + memset(g_upcaseinfo, 0, sizeof(struct UPCASEINFO)); + g_upcaseinfo->len = const_cpu_to_le32(sizeof(struct UPCASEINFO)); + g_upcaseinfo->crc = cpu_to_le64(upcase_crc); g_vol->attrdef = ntfs_malloc(sizeof(attrdef_ntfs3x_array)); if (!g_vol->attrdef) { ntfs_log_perror("Could not create attrdef structure"); @@ -4768,7 +4845,7 @@ done: * mkntfs_main */ int mkntfs_main(const char *devpath, const char *label) -{ +{ //reset global variables g_buf = NULL; g_mft_bitmap_byte_size = 0; @@ -4789,13 +4866,13 @@ int mkntfs_main(const char *devpath, const char *label) g_mftmirr_lcn = 0; g_logfile_lcn = 0; g_logfile_size = 0; - g_mft_zone_end = 0; + g_mft_zone_end = 0; g_num_bad_blocks = 0; g_bad_blocks = NULL; g_allocation = NULL; - + //init default options - mkntfs_init_options(&opts); + mkntfs_init_options(&opts); opts.dev_name = devpath; opts.label = label; @@ -4805,4 +4882,3 @@ int mkntfs_main(const char *devpath, const char *label) return mkntfs_redirect(&opts); } - diff --git a/src/add-ons/kernel/file_systems/ntfs/utils/utils.c b/src/add-ons/kernel/file_systems/ntfs/utils/utils.c index 545c6092dc..f878e48f02 100644 --- a/src/add-ons/kernel/file_systems/ntfs/utils/utils.c +++ b/src/add-ons/kernel/file_systems/ntfs/utils/utils.c @@ -1026,8 +1026,26 @@ int mft_next_record(struct mft_search_ctx *ctx) ctx->inode = ntfs_inode_open(ctx->vol, (MFT_REF) ctx->mft_num); if (ctx->inode == NULL) { - ntfs_log_error("Error reading inode %llu.\n", (unsigned - long long) ctx->mft_num); + MFT_RECORD *mrec; + int r; + MFT_REF base_inode; + + mrec = (MFT_RECORD*)NULL; + r = ntfs_file_record_read(ctx->vol, + (MFT_REF) ctx->mft_num, &mrec, NULL); + if (r || !mrec || !mrec->base_mft_record) + ntfs_log_error( + "Error reading inode %lld.\n", + (long long)ctx->mft_num); + else { + base_inode = le64_to_cpu( + mrec->base_mft_record); + ntfs_log_error("Inode %lld is an " + "extent of inode %lld.\n", + (long long)ctx->mft_num, + (long long)MREF(base_inode)); + } + free (mrec); continue; }