NTFS: Merge changes to the utils from upstream.

This commit is contained in:
Augustin Cavalier 2019-08-31 23:26:28 -04:00
parent 01339a54db
commit 763047bfb1
2 changed files with 107 additions and 13 deletions

View File

@ -6,7 +6,7 @@
* Copyright (c) 2002-2006 Szabolcs Szakacsits * Copyright (c) 2002-2006 Szabolcs Szakacsits
* Copyright (c) 2005 Erik Sornes * Copyright (c) 2005 Erik Sornes
* Copyright (c) 2007 Yura Pakhuchiy * 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 * This utility will create an NTFS 1.2 or 3.1 volume on a user
* specified (block) device. * specified (block) device.
@ -161,6 +161,18 @@ struct BITMAP_ALLOCATION {
s64 length; /* count of consecutive clusters */ 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 * global variables
*/ */
@ -170,6 +182,7 @@ static u8 *g_mft_bitmap = NULL;
static int g_lcn_bitmap_byte_size = 0; static int g_lcn_bitmap_byte_size = 0;
static int g_dynamic_buf_size = 0; static int g_dynamic_buf_size = 0;
static u8 *g_dynamic_buf = NULL; static u8 *g_dynamic_buf = NULL;
static struct UPCASEINFO *g_upcaseinfo = NULL;
static runlist *g_rl_mft = NULL; static runlist *g_rl_mft = NULL;
static runlist *g_rl_mft_bmp = NULL; static runlist *g_rl_mft_bmp = NULL;
static runlist *g_rl_mftmirr = NULL; static runlist *g_rl_mftmirr = NULL;
@ -211,6 +224,53 @@ static struct mkntfs_options {
char *label; /* -L, volume label */ char *label; /* -L, volume label */
} opts; } 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 * 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; a = ctx->attr;
/* sizeof(resident attribute record header) == 24 */ /* 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); err = make_room_for_attribute(m, (char*)a, asize);
if (err == -ENOSPC) { 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); 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), err = add_attr_data(m, NULL, 0, CASE_SENSITIVE, const_cpu_to_le16(0),
(u8*)g_vol->attrdef, g_vol->attrdef_len); (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) if (!err)
err = create_hardlink(g_index_block, root_ref, m, err = create_hardlink(g_index_block, root_ref, m,
MK_LE_MREF(FILE_AttrDef, FILE_AttrDef), 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) static int mkntfs_redirect(struct mkntfs_options *opts2)
{ {
u64 upcase_crc;
int result = 1; int result = 1;
ntfs_attr_search_ctx *ctx = NULL; ntfs_attr_search_ctx *ctx = NULL;
long long lw, pos; long long lw, pos;
@ -4605,12 +4674,20 @@ static int mkntfs_redirect(struct mkntfs_options *opts2)
if (opts.cluster_size >= 0) if (opts.cluster_size >= 0)
g_vol->cluster_size = opts.cluster_size; g_vol->cluster_size = opts.cluster_size;
/* Length is in unicode characters. */ /* Length is in unicode characters. */
g_vol->upcase_len = 65536; g_vol->upcase_len = ntfs_upcase_build_default(&g_vol->upcase);
g_vol->upcase = ntfs_malloc(g_vol->upcase_len * sizeof(ntfschar)); /* Since Windows 8, there is a $Info stream in $UpCase */
if (!g_vol->upcase) g_upcaseinfo =
(struct UPCASEINFO*)ntfs_malloc(sizeof(struct UPCASEINFO));
if (!g_vol->upcase_len || !g_upcaseinfo)
goto done; 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)); 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)); g_vol->attrdef = ntfs_malloc(sizeof(attrdef_ntfs3x_array));
if (!g_vol->attrdef) { if (!g_vol->attrdef) {
ntfs_log_perror("Could not create attrdef structure"); ntfs_log_perror("Could not create attrdef structure");
@ -4805,4 +4882,3 @@ int mkntfs_main(const char *devpath, const char *label)
return mkntfs_redirect(&opts); return mkntfs_redirect(&opts);
} }

View File

@ -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); ctx->inode = ntfs_inode_open(ctx->vol, (MFT_REF) ctx->mft_num);
if (ctx->inode == NULL) { if (ctx->inode == NULL) {
ntfs_log_error("Error reading inode %llu.\n", (unsigned MFT_RECORD *mrec;
long long) ctx->mft_num); 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; continue;
} }