mirror of
https://git.code.sf.net/p/ntfs-3g/ntfs-3g.git
synced 2024-11-23 18:14:24 +08:00
parse_options - make sure it always spots missing options
fix mem leak in upgrade_to_large_index fix bug - srandom called before options parsed start separating user-type things from lib-type things (e-22)
This commit is contained in:
parent
d605234a3a
commit
2a2ecd2abd
@ -354,13 +354,13 @@ static void mkntfs_init_options(struct mkntfs_options *opts2) // XXX rename arg
|
|||||||
memset(opts2, 0, sizeof(*opts2));
|
memset(opts2, 0, sizeof(*opts2));
|
||||||
|
|
||||||
/* Mark all the numeric options as "unset". */
|
/* Mark all the numeric options as "unset". */
|
||||||
|
opts2->cluster_size = -1;
|
||||||
opts2->heads = -1;
|
opts2->heads = -1;
|
||||||
|
opts2->mft_zone_multiplier = -1;
|
||||||
|
opts2->num_sectors = -1;
|
||||||
opts2->part_start_sect = -1;
|
opts2->part_start_sect = -1;
|
||||||
opts2->sector_size = -1;
|
opts2->sector_size = -1;
|
||||||
opts2->sectors_per_track = -1;
|
opts2->sectors_per_track = -1;
|
||||||
opts2->mft_zone_multiplier = -1;
|
|
||||||
opts2->num_sectors = -1;
|
|
||||||
opts2->cluster_size = -1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -512,8 +512,15 @@ static BOOL mkntfs_parse_options(int argc, char *argv[], struct mkntfs_options *
|
|||||||
default:
|
default:
|
||||||
if (ntfs_log_parse_option (argv[optind-1]))
|
if (ntfs_log_parse_option (argv[optind-1]))
|
||||||
break;
|
break;
|
||||||
if (optopt != '?')
|
if (((optopt == 'c') || (optopt == 'H') ||
|
||||||
|
(optopt == 'L') || (optopt == 'p') ||
|
||||||
|
(optopt == 's') || (optopt == 'S') ||
|
||||||
|
(optopt == 'w') || (optopt == 'z')) &&
|
||||||
|
(!optarg)) {
|
||||||
|
ntfs_log_error("Option '%s' requires an argument.\n", argv[optind-1]);
|
||||||
|
} else if (optopt != '?') {
|
||||||
ntfs_log_error("Unknown option '%s'.\n", argv[optind-1]);
|
ntfs_log_error("Unknown option '%s'.\n", argv[optind-1]);
|
||||||
|
}
|
||||||
err++;
|
err++;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -2626,6 +2633,7 @@ static int upgrade_to_large_index(MFT_RECORD *m, const char *name,
|
|||||||
err = -EINVAL;
|
err = -EINVAL;
|
||||||
goto err_out;
|
goto err_out;
|
||||||
}
|
}
|
||||||
|
ntfs_attr_put_search_ctx(ctx);
|
||||||
r = (INDEX_ROOT*)((char*)a + le16_to_cpu(a->value_offset));
|
r = (INDEX_ROOT*)((char*)a + le16_to_cpu(a->value_offset));
|
||||||
re_end = (char*)r + le32_to_cpu(a->value_length);
|
re_end = (char*)r + le32_to_cpu(a->value_length);
|
||||||
re_start = (char*)&r->index + le32_to_cpu(r->index.entries_offset);
|
re_start = (char*)&r->index + le32_to_cpu(r->index.entries_offset);
|
||||||
@ -2722,8 +2730,7 @@ static int upgrade_to_large_index(MFT_RECORD *m, const char *name,
|
|||||||
*idx = ia_val;
|
*idx = ia_val;
|
||||||
return 0;
|
return 0;
|
||||||
err_out:
|
err_out:
|
||||||
if (ctx)
|
ntfs_attr_put_search_ctx(ctx);
|
||||||
ntfs_attr_put_search_ctx(ctx);
|
|
||||||
free(ia_val);
|
free(ia_val);
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
@ -3550,54 +3557,46 @@ static int create_hardlink(INDEX_BLOCK *idx, const MFT_REF ref_parent,
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* init_options
|
|
||||||
*/
|
|
||||||
static void init_options(void)
|
|
||||||
{
|
|
||||||
memset(&opts, 0, sizeof(opts));
|
|
||||||
opts.sectors_per_track = -1;
|
|
||||||
opts.heads = -1;
|
|
||||||
opts.part_start_sect = -1;
|
|
||||||
g_index_block_size = 4096;
|
|
||||||
g_attr_defs = (ATTR_DEF*)&attrdef_ntfs12_array;
|
|
||||||
g_attr_defs_len = sizeof(attrdef_ntfs12_array);
|
|
||||||
/* ntfs_log_debug("Attr_defs table length = %u\n", g_attr_defs_len); */
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* mkntfs_exit
|
* mkntfs_exit
|
||||||
*/
|
*/
|
||||||
static void mkntfs_exit(void)
|
static void mkntfs_exit(void)
|
||||||
{
|
{
|
||||||
free(g_index_block);
|
/* Close the volume */
|
||||||
free(g_buf_sds_init);
|
if (g_vol) {
|
||||||
free(g_buf_sds);
|
if (g_vol->dev) {
|
||||||
free(g_buf);
|
if (NDevOpen(g_vol->dev) && g_vol->dev->d_ops->close(g_vol->dev))
|
||||||
free(g_buf2);
|
ntfs_log_perror("Warning: Could not close %s", g_vol->dev->d_name);
|
||||||
free(g_lcn_bitmap);
|
ntfs_device_free(g_vol->dev);
|
||||||
free(g_mft_bitmap);
|
}
|
||||||
free(g_rl_mft);
|
free(g_vol->upcase);
|
||||||
free(g_rl_mft_bmp);
|
free(g_vol);
|
||||||
free(g_rl_mftmirr);
|
g_vol = NULL;
|
||||||
free(g_rl_logfile);
|
}
|
||||||
free(g_rl_boot);
|
|
||||||
free(g_rl_bad);
|
/* Free any memory we've used */
|
||||||
free(g_rl_index);
|
free(g_bad_blocks); g_bad_blocks = NULL;
|
||||||
free(g_bad_blocks);
|
free(g_buf); g_buf = NULL;
|
||||||
if ((g_attr_defs != (const ATTR_DEF*)attrdef_ntfs12_array) &&
|
free(g_buf2); g_buf2 = NULL;
|
||||||
(g_attr_defs != (const ATTR_DEF*)attrdef_ntfs3x_array))
|
free(g_buf_sds); g_buf_sds = NULL;
|
||||||
free(g_attr_defs);
|
free(g_buf_sds_init); g_buf_sds_init = NULL;
|
||||||
if (!g_vol)
|
free(g_index_block); g_index_block = NULL;
|
||||||
return;
|
free(g_lcn_bitmap); g_lcn_bitmap = NULL;
|
||||||
free(g_vol->upcase);
|
free(g_mft_bitmap); g_mft_bitmap = NULL;
|
||||||
if (g_vol->dev) {
|
free(g_rl_bad); g_rl_bad = NULL;
|
||||||
if (NDevOpen(g_vol->dev) && g_vol->dev->d_ops->close(g_vol->dev))
|
free(g_rl_boot); g_rl_boot = NULL;
|
||||||
ntfs_log_error("Warning: Could not close %s: %s\n",
|
free(g_rl_index); g_rl_index = NULL;
|
||||||
g_vol->dev->d_name, strerror(errno));
|
free(g_rl_logfile); g_rl_logfile = NULL;
|
||||||
ntfs_device_free(g_vol->dev);
|
free(g_rl_mft); g_rl_mft = NULL;
|
||||||
|
free(g_rl_mft_bmp); g_rl_mft_bmp = NULL;
|
||||||
|
free(g_rl_mftmirr); g_rl_mftmirr = NULL;
|
||||||
|
|
||||||
|
/* Only free the attribute definitions, if we originally allocated them. */
|
||||||
|
if ((g_attr_defs != (const ATTR_DEF*)attrdef_ntfs12_array) &&
|
||||||
|
(g_attr_defs != (const ATTR_DEF*)attrdef_ntfs3x_array)) {
|
||||||
|
free(g_attr_defs);
|
||||||
|
g_attr_defs = NULL;
|
||||||
}
|
}
|
||||||
free(g_vol);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -3605,8 +3604,12 @@ static void mkntfs_exit(void)
|
|||||||
*
|
*
|
||||||
* Note: Might not return.
|
* Note: Might not return.
|
||||||
*/
|
*/
|
||||||
static void mkntfs_open_partition(void)
|
static int mkntfs_open_partition(void)
|
||||||
{
|
{
|
||||||
|
/* This function uses:
|
||||||
|
* g_vol
|
||||||
|
*/
|
||||||
|
int result = 1;
|
||||||
int i;
|
int i;
|
||||||
struct stat sbuf;
|
struct stat sbuf;
|
||||||
unsigned long mnt_flags;
|
unsigned long mnt_flags;
|
||||||
@ -3615,9 +3618,12 @@ static void mkntfs_open_partition(void)
|
|||||||
* Allocate and initialize an ntfs device structure and attach it to
|
* Allocate and initialize an ntfs device structure and attach it to
|
||||||
* the volume.
|
* the volume.
|
||||||
*/
|
*/
|
||||||
if (!(g_vol->dev = ntfs_device_alloc(opts.dev_name, 0,
|
g_vol->dev = ntfs_device_alloc(opts.dev_name, 0, &ntfs_device_default_io_ops, NULL);
|
||||||
&ntfs_device_default_io_ops, NULL)))
|
if (!g_vol->dev) {
|
||||||
err_exit("Could not allocate memory for internal buffer.\n");
|
ntfs_log_perror("Could not create device");
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
|
||||||
/* Open the device for reading or reading and writing. */
|
/* Open the device for reading or reading and writing. */
|
||||||
if (opts.no_action) {
|
if (opts.no_action) {
|
||||||
ntfs_log_quiet("Running in READ-ONLY mode!\n");
|
ntfs_log_quiet("Running in READ-ONLY mode!\n");
|
||||||
@ -3627,31 +3633,33 @@ static void mkntfs_open_partition(void)
|
|||||||
}
|
}
|
||||||
if (g_vol->dev->d_ops->open(g_vol->dev, i)) {
|
if (g_vol->dev->d_ops->open(g_vol->dev, i)) {
|
||||||
if (errno == ENOENT)
|
if (errno == ENOENT)
|
||||||
err_exit("The device doesn't exist; did you specify "
|
ntfs_log_error("The device doesn't exist; did you specify it correctly?\n");
|
||||||
"it correctly?\n");
|
else
|
||||||
err_exit("Could not open %s: %s\n", g_vol->dev->d_name,
|
ntfs_log_perror("Could not open %s", g_vol->dev->d_name);
|
||||||
strerror(errno));
|
goto done;
|
||||||
}
|
}
|
||||||
/* Verify we are dealing with a block device. */
|
/* Verify we are dealing with a block device. */
|
||||||
if (g_vol->dev->d_ops->stat(g_vol->dev, &sbuf)) {
|
if (g_vol->dev->d_ops->stat(g_vol->dev, &sbuf)) {
|
||||||
err_exit("Error getting information about %s: %s\n",
|
ntfs_log_perror("Error getting information about %s", g_vol->dev->d_name);
|
||||||
g_vol->dev->d_name, strerror(errno));
|
goto done;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!S_ISBLK(sbuf.st_mode)) {
|
if (!S_ISBLK(sbuf.st_mode)) {
|
||||||
ntfs_log_error("%s is not a block device.\n", g_vol->dev->d_name);
|
ntfs_log_error("%s is not a block device.\n", g_vol->dev->d_name);
|
||||||
if (!opts.force)
|
if (!opts.force) {
|
||||||
err_exit("Refusing to make a filesystem here!\n");
|
ntfs_log_error("Refusing to make a filesystem here!\n");
|
||||||
if (opts.num_sectors < 0) {
|
goto done;
|
||||||
if (!sbuf.st_size && !sbuf.st_blocks)
|
}
|
||||||
err_exit("You must specify the number of "
|
if (!opts.num_sectors) {
|
||||||
"sectors.\n");
|
if (!sbuf.st_size && !sbuf.st_blocks) {
|
||||||
|
ntfs_log_error("You must specify the number of sectors.\n");
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
if (opts.sector_size) {
|
if (opts.sector_size) {
|
||||||
if (sbuf.st_size)
|
if (sbuf.st_size)
|
||||||
opts.num_sectors = sbuf.st_size /
|
opts.num_sectors = sbuf.st_size / opts.sector_size;
|
||||||
opts.sector_size;
|
|
||||||
else
|
else
|
||||||
opts.num_sectors = ((s64)sbuf.st_blocks
|
opts.num_sectors = ((s64)sbuf.st_blocks << 9) / opts.sector_size;
|
||||||
<< 9) / opts.sector_size;
|
|
||||||
} else {
|
} else {
|
||||||
if (sbuf.st_size)
|
if (sbuf.st_size)
|
||||||
opts.num_sectors = sbuf.st_size / 512;
|
opts.num_sectors = sbuf.st_size / 512;
|
||||||
@ -3662,28 +3670,29 @@ static void mkntfs_open_partition(void)
|
|||||||
}
|
}
|
||||||
ntfs_log_warning("mkntfs forced anyway.\n");
|
ntfs_log_warning("mkntfs forced anyway.\n");
|
||||||
#ifdef HAVE_LINUX_MAJOR_H
|
#ifdef HAVE_LINUX_MAJOR_H
|
||||||
} else if ((IDE_DISK_MAJOR(MAJOR(sbuf.st_rdev)) &&
|
} else if ((IDE_DISK_MAJOR(MAJOR(sbuf.st_rdev)) && MINOR(sbuf.st_rdev) % 64 == 0) || (SCSI_DISK_MAJOR(MAJOR(sbuf.st_rdev)) && MINOR(sbuf.st_rdev) % 16 == 0)) {
|
||||||
MINOR(sbuf.st_rdev) % 64 == 0) ||
|
ntfs_log_error("%s is entire device, not just one partition.\n", g_vol->dev->d_name);
|
||||||
(SCSI_DISK_MAJOR(MAJOR(sbuf.st_rdev)) &&
|
if (!opts.force) {
|
||||||
MINOR(sbuf.st_rdev) % 16 == 0)) {
|
ntfs_log_error("Refusing to make a filesystem here!\n");
|
||||||
ntfs_log_error("%s is entire device, not just one partition.\n",
|
goto done;
|
||||||
g_vol->dev->d_name);
|
}
|
||||||
if (!opts.force)
|
|
||||||
err_exit("Refusing to make a filesystem here!\n");
|
|
||||||
ntfs_log_warning("mkntfs forced anyway.\n");
|
ntfs_log_warning("mkntfs forced anyway.\n");
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
/* Make sure the file system is not mounted. */
|
/* Make sure the file system is not mounted. */
|
||||||
if (ntfs_check_if_mounted(g_vol->dev->d_name, &mnt_flags)) {
|
if (ntfs_check_if_mounted(g_vol->dev->d_name, &mnt_flags)) {
|
||||||
ntfs_log_error("Failed to determine whether %s is mounted: %s\n",
|
ntfs_log_perror("Failed to determine whether %s is mounted", g_vol->dev->d_name);
|
||||||
g_vol->dev->d_name, strerror(errno));
|
|
||||||
} else if (mnt_flags & NTFS_MF_MOUNTED) {
|
} else if (mnt_flags & NTFS_MF_MOUNTED) {
|
||||||
ntfs_log_error("%s is mounted.\n", g_vol->dev->d_name);
|
ntfs_log_error("%s is mounted.\n", g_vol->dev->d_name);
|
||||||
if (!opts.force)
|
if (!opts.force) {
|
||||||
err_exit("Refusing to make a filesystem here!\n");
|
ntfs_log_error("Refusing to make a filesystem here!\n");
|
||||||
ntfs_log_warning("mkntfs forced anyway. Hope /etc/mtab is "
|
goto done;
|
||||||
"incorrect.\n");
|
}
|
||||||
|
ntfs_log_warning("mkntfs forced anyway. Hope /etc/mtab is incorrect.\n");
|
||||||
}
|
}
|
||||||
|
result = 0;
|
||||||
|
done:
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -3693,6 +3702,11 @@ static void mkntfs_open_partition(void)
|
|||||||
*/
|
*/
|
||||||
static void mkntfs_override_phys_params(void)
|
static void mkntfs_override_phys_params(void)
|
||||||
{
|
{
|
||||||
|
/* This function uses:
|
||||||
|
* g_num_clusters
|
||||||
|
* g_vol
|
||||||
|
* g_volume_size
|
||||||
|
*/
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
/* If user didn't specify the sector size, determine it now. */
|
/* If user didn't specify the sector size, determine it now. */
|
||||||
@ -3700,10 +3714,10 @@ static void mkntfs_override_phys_params(void)
|
|||||||
#ifdef BLKSSZGET
|
#ifdef BLKSSZGET
|
||||||
int sect_size = 0;
|
int sect_size = 0;
|
||||||
|
|
||||||
if (g_vol->dev->d_ops->ioctl(g_vol->dev, BLKSSZGET, §_size)
|
if (g_vol->dev->d_ops->ioctl(g_vol->dev, BLKSSZGET, §_size) >= 0) {
|
||||||
>= 0) {
|
|
||||||
opts.sector_size = sect_size;
|
opts.sector_size = sect_size;
|
||||||
} else
|
} else
|
||||||
|
/* XXX UGLY */
|
||||||
#endif
|
#endif
|
||||||
{
|
{
|
||||||
ntfs_log_error("No sector size specified for %s and it could "
|
ntfs_log_error("No sector size specified for %s and it could "
|
||||||
@ -3794,6 +3808,7 @@ static void mkntfs_override_phys_params(void)
|
|||||||
}
|
}
|
||||||
/* If user didn't specify the number of heads, determine it now. */
|
/* If user didn't specify the number of heads, determine it now. */
|
||||||
if (opts.heads < 0) {
|
if (opts.heads < 0) {
|
||||||
|
//XXX this will break if sizeof(int) != sizeof(long) -- signextend
|
||||||
opts.heads = ntfs_device_heads_get(g_vol->dev);
|
opts.heads = ntfs_device_heads_get(g_vol->dev);
|
||||||
if (opts.heads < 0) {
|
if (opts.heads < 0) {
|
||||||
ntfs_log_error("No number of heads specified for %s and it "
|
ntfs_log_error("No number of heads specified for %s and it "
|
||||||
@ -3916,6 +3931,17 @@ static void mkntfs_override_phys_params(void)
|
|||||||
*/
|
*/
|
||||||
static void mkntfs_initialize_bitmaps(void)
|
static void mkntfs_initialize_bitmaps(void)
|
||||||
{
|
{
|
||||||
|
/* This function uses:
|
||||||
|
* g_lcn_bitmap
|
||||||
|
* g_lcn_bitmap_byte_size
|
||||||
|
* g_mft_bitmap
|
||||||
|
* g_mft_bitmap_byte_size
|
||||||
|
* g_mft_bitmap_size
|
||||||
|
* g_mft_size
|
||||||
|
* g_num_clusters
|
||||||
|
* g_rl_mft_bmp
|
||||||
|
* g_vol
|
||||||
|
*/
|
||||||
int i, j;
|
int i, j;
|
||||||
|
|
||||||
/* Determine lcn bitmap byte size and allocate it. */
|
/* Determine lcn bitmap byte size and allocate it. */
|
||||||
@ -3981,6 +4007,19 @@ static void mkntfs_initialize_bitmaps(void)
|
|||||||
*/
|
*/
|
||||||
static void mkntfs_initialize_rl_mft(void)
|
static void mkntfs_initialize_rl_mft(void)
|
||||||
{
|
{
|
||||||
|
/* This function uses:
|
||||||
|
* g_lcn_bitmap
|
||||||
|
* g_logfile_lcn
|
||||||
|
* g_mft_lcn
|
||||||
|
* g_mftmirr_lcn
|
||||||
|
* g_mft_size
|
||||||
|
* g_mft_zone_end
|
||||||
|
* g_num_clusters
|
||||||
|
* g_rl_mft
|
||||||
|
* g_rl_mft_bmp
|
||||||
|
* g_rl_mftmirr
|
||||||
|
* g_vol
|
||||||
|
*/
|
||||||
int i, j;
|
int i, j;
|
||||||
|
|
||||||
/* If user didn't specify the mft lcn, determine it now. */
|
/* If user didn't specify the mft lcn, determine it now. */
|
||||||
@ -4071,6 +4110,15 @@ static void mkntfs_initialize_rl_mft(void)
|
|||||||
*/
|
*/
|
||||||
static void mkntfs_initialize_rl_logfile(void)
|
static void mkntfs_initialize_rl_logfile(void)
|
||||||
{
|
{
|
||||||
|
/* This function uses:
|
||||||
|
* g_lcn_bitmap
|
||||||
|
* g_logfile_lcn
|
||||||
|
* g_logfile_size
|
||||||
|
* g_num_clusters
|
||||||
|
* g_rl_logfile
|
||||||
|
* g_vol
|
||||||
|
* g_volume_size
|
||||||
|
*/
|
||||||
int i, j;
|
int i, j;
|
||||||
|
|
||||||
/* Create runlist for log file. */
|
/* Create runlist for log file. */
|
||||||
@ -4132,6 +4180,11 @@ static void mkntfs_initialize_rl_logfile(void)
|
|||||||
*/
|
*/
|
||||||
static void mkntfs_initialize_rl_boot(void)
|
static void mkntfs_initialize_rl_boot(void)
|
||||||
{
|
{
|
||||||
|
/* This function uses:
|
||||||
|
* g_lcn_bitmap
|
||||||
|
* g_rl_boot
|
||||||
|
* g_vol
|
||||||
|
*/
|
||||||
int i, j;
|
int i, j;
|
||||||
/* Create runlist for $Boot. */
|
/* Create runlist for $Boot. */
|
||||||
g_rl_boot = malloc(2 * sizeof(runlist));
|
g_rl_boot = malloc(2 * sizeof(runlist));
|
||||||
@ -4160,6 +4213,10 @@ static void mkntfs_initialize_rl_boot(void)
|
|||||||
*/
|
*/
|
||||||
static void mkntfs_initialize_rl_bad(void)
|
static void mkntfs_initialize_rl_bad(void)
|
||||||
{
|
{
|
||||||
|
/* This function uses:
|
||||||
|
* g_num_clusters
|
||||||
|
* g_rl_bad
|
||||||
|
*/
|
||||||
/* Create runlist for $BadClus, $DATA named stream $Bad. */
|
/* Create runlist for $BadClus, $DATA named stream $Bad. */
|
||||||
g_rl_bad = malloc(2 * sizeof(runlist));
|
g_rl_bad = malloc(2 * sizeof(runlist));
|
||||||
if (!g_rl_bad)
|
if (!g_rl_bad)
|
||||||
@ -4185,6 +4242,12 @@ static void mkntfs_initialize_rl_bad(void)
|
|||||||
*/
|
*/
|
||||||
static void mkntfs_fill_device_with_zeroes(void)
|
static void mkntfs_fill_device_with_zeroes(void)
|
||||||
{
|
{
|
||||||
|
/* This function uses:
|
||||||
|
* g_buf
|
||||||
|
* g_num_clusters
|
||||||
|
* g_vol
|
||||||
|
* g_volume_size
|
||||||
|
*/
|
||||||
/*
|
/*
|
||||||
* If not quick format, fill the device with 0s.
|
* If not quick format, fill the device with 0s.
|
||||||
* FIXME: Except bad blocks! (AIA)
|
* FIXME: Except bad blocks! (AIA)
|
||||||
@ -4263,6 +4326,10 @@ static void mkntfs_fill_device_with_zeroes(void)
|
|||||||
static void mkntfs_sync_index_record(INDEX_ALLOCATION* idx, MFT_RECORD* m,
|
static void mkntfs_sync_index_record(INDEX_ALLOCATION* idx, MFT_RECORD* m,
|
||||||
ntfschar* name, u32 name_len)
|
ntfschar* name, u32 name_len)
|
||||||
{
|
{
|
||||||
|
/* This function uses:
|
||||||
|
* g_rl_index
|
||||||
|
* g_vol
|
||||||
|
*/
|
||||||
int i, err;
|
int i, err;
|
||||||
ntfs_attr_search_ctx *ctx;
|
ntfs_attr_search_ctx *ctx;
|
||||||
ATTR_RECORD *a;
|
ATTR_RECORD *a;
|
||||||
@ -4395,6 +4462,34 @@ bb_err:
|
|||||||
*/
|
*/
|
||||||
static void mkntfs_create_root_structures(void)
|
static void mkntfs_create_root_structures(void)
|
||||||
{
|
{
|
||||||
|
/* This function uses:
|
||||||
|
* g_attr_defs
|
||||||
|
* g_attr_defs_len
|
||||||
|
* g_buf
|
||||||
|
* g_buf_sds
|
||||||
|
* g_buf_sds_first_size
|
||||||
|
* g_buf_sds_init
|
||||||
|
* g_buf_sds_size
|
||||||
|
* g_index_block
|
||||||
|
* g_index_block_size
|
||||||
|
* g_lcn_bitmap
|
||||||
|
* g_lcn_bitmap_byte_size
|
||||||
|
* g_logfile_size
|
||||||
|
* g_mft_bitmap
|
||||||
|
* g_mft_bitmap_byte_size
|
||||||
|
* g_mft_lcn
|
||||||
|
* g_mftmirr_lcn
|
||||||
|
* g_mft_size
|
||||||
|
* g_num_clusters
|
||||||
|
* g_rl_bad
|
||||||
|
* g_rl_boot
|
||||||
|
* g_rl_logfile
|
||||||
|
* g_rl_mft
|
||||||
|
* g_rl_mft_bmp
|
||||||
|
* g_rl_mftmirr
|
||||||
|
* g_vol
|
||||||
|
* g_volume_obj_id
|
||||||
|
*/
|
||||||
NTFS_BOOT_SECTOR *bs;
|
NTFS_BOOT_SECTOR *bs;
|
||||||
ATTR_RECORD *a;
|
ATTR_RECORD *a;
|
||||||
MFT_RECORD *m;
|
MFT_RECORD *m;
|
||||||
@ -4973,64 +5068,76 @@ static void mkntfs_create_root_structures(void)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* main
|
* mkntfs_redirect
|
||||||
*/
|
*/
|
||||||
int main(int argc, char **argv)
|
static int mkntfs_redirect(struct mkntfs_options *opts2) // XXX rename arg
|
||||||
{
|
{
|
||||||
ntfs_attr_search_ctx *ctx;
|
int result = 1;
|
||||||
|
ntfs_attr_search_ctx *ctx = NULL;
|
||||||
long long lw, pos;
|
long long lw, pos;
|
||||||
ATTR_RECORD *a;
|
ATTR_RECORD *a;
|
||||||
MFT_RECORD *m;
|
MFT_RECORD *m;
|
||||||
int i, err;
|
int i, err;
|
||||||
|
|
||||||
ntfs_log_set_handler(ntfs_log_handler_outerr);
|
if (!opts2) {
|
||||||
|
ntfs_log_error("Internal error: invalid parameters to mkntfs_options.\n");
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
|
||||||
/* Setup the correct locale for string output and conversion. */
|
|
||||||
utils_set_locale();
|
|
||||||
/* Initialize the random number generator with the current time. */
|
|
||||||
srandom(mkntfs_time());
|
|
||||||
/* Allocate and initialize ntfs_volume structure g_vol. */
|
|
||||||
g_vol = ntfs_volume_alloc();
|
|
||||||
if (!g_vol)
|
|
||||||
err_exit("Could not allocate memory for internal buffer.\n");
|
|
||||||
/* Register our exit function which will cleanup everything. */
|
/* Register our exit function which will cleanup everything. */
|
||||||
err = atexit(&mkntfs_exit);
|
err = atexit(&mkntfs_exit);
|
||||||
if (err == -1) {
|
if (err == -1) {
|
||||||
ntfs_log_error("Could not set up exit() function because atexit() "
|
ntfs_log_error("Could not set up exit() function because atexit() failed. Aborting...\n");
|
||||||
"failed. Aborting...\n");
|
goto done;
|
||||||
mkntfs_exit();
|
|
||||||
exit(1);
|
|
||||||
}
|
}
|
||||||
g_vol->major_ver = 1;
|
|
||||||
g_vol->minor_ver = 2;
|
/* Initialize the random number generator with the current time. */
|
||||||
g_vol->mft_record_size = 1024;
|
srandom(mkntfs_time());
|
||||||
g_vol->mft_record_size_bits = 10;
|
|
||||||
/* Length is in unicode characters. */
|
/* Allocate and initialize ntfs_volume structure g_vol. */
|
||||||
g_vol->upcase_len = 65536;
|
g_vol = ntfs_volume_alloc();
|
||||||
g_vol->upcase = malloc(g_vol->upcase_len * sizeof(ntfschar));
|
if (!g_vol) {
|
||||||
if (!g_vol->upcase)
|
ntfs_log_perror("Could not create volume");
|
||||||
err_exit("Could not allocate memory for internal buffer.\n");
|
goto done;
|
||||||
init_upcase_table(g_vol->upcase, g_vol->upcase_len * sizeof(ntfschar));
|
}
|
||||||
/* Initialize opts to zero / required values. */
|
|
||||||
init_options();
|
|
||||||
mkntfs_init_options(&opts);
|
|
||||||
/* Parse command line options. */
|
|
||||||
if (!mkntfs_parse_options(argc, argv, &opts))
|
|
||||||
exit(1);
|
|
||||||
mkntfs_validate_options(&opts);
|
|
||||||
|
|
||||||
/* transfer some options to the volume */
|
/* transfer some options to the volume */
|
||||||
g_vol->vol_name = opts.label; // XXX when this be strdup, either free it, or call ntfs_umount
|
g_vol->vol_name = opts.label; // XXX when this is strdup, either free it, or call ntfs_umount
|
||||||
if (opts.ver_major && opts.ver_minor) {
|
if (opts.ver_major && opts.ver_minor) {
|
||||||
g_vol->major_ver = opts.ver_major;
|
g_vol->major_ver = opts.ver_major;
|
||||||
g_vol->minor_ver = opts.ver_minor;
|
g_vol->minor_ver = opts.ver_minor;
|
||||||
|
} else {
|
||||||
|
g_vol->major_ver = 1;
|
||||||
|
g_vol->minor_ver = 2;
|
||||||
}
|
}
|
||||||
if (opts.cluster_size >= 0)
|
if (opts.cluster_size >= 0)
|
||||||
g_vol->cluster_size = opts.cluster_size;
|
g_vol->cluster_size = opts.cluster_size;
|
||||||
|
|
||||||
/* Open the partition. */
|
g_vol->mft_record_size = 1024;
|
||||||
mkntfs_open_partition();
|
g_vol->mft_record_size_bits = 10;
|
||||||
|
|
||||||
|
/* Length is in unicode characters. */
|
||||||
|
g_vol->upcase_len = 65536;
|
||||||
|
g_vol->upcase = malloc(g_vol->upcase_len * sizeof(ntfschar));
|
||||||
|
if (!g_vol->upcase) {
|
||||||
|
ntfs_log_perror("Could not create upcase structure");
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
init_upcase_table(g_vol->upcase, g_vol->upcase_len * sizeof(ntfschar));
|
||||||
|
|
||||||
|
/* Initialize opts to zero / required values. */
|
||||||
|
g_index_block_size = 4096;
|
||||||
|
g_attr_defs = (ATTR_DEF*)&attrdef_ntfs12_array;
|
||||||
|
g_attr_defs_len = sizeof(attrdef_ntfs12_array);
|
||||||
|
/* ntfs_log_debug("Attr_defs table length = %u\n", g_attr_defs_len); */
|
||||||
|
|
||||||
|
if (mkntfs_open_partition()) /* Open the partition. */
|
||||||
|
goto done;
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------------------
|
||||||
|
|
||||||
/* Decide on the sectors/tracks/heads/size, etc. */
|
/* Decide on the sectors/tracks/heads/size, etc. */
|
||||||
mkntfs_override_phys_params();
|
mkntfs_override_phys_params();
|
||||||
/* Initialize $Bitmap and $MFT/$BITMAP related stuff. */
|
/* Initialize $Bitmap and $MFT/$BITMAP related stuff. */
|
||||||
@ -5041,11 +5148,14 @@ int main(int argc, char **argv)
|
|||||||
mkntfs_initialize_rl_logfile();
|
mkntfs_initialize_rl_logfile();
|
||||||
/* Initialize $Boot. */
|
/* Initialize $Boot. */
|
||||||
mkntfs_initialize_rl_boot();
|
mkntfs_initialize_rl_boot();
|
||||||
|
|
||||||
/* Allocate a buffer large enough to hold the mft. */
|
/* Allocate a buffer large enough to hold the mft. */
|
||||||
g_buf = calloc(1, g_mft_size);
|
g_buf = calloc(1, g_mft_size);
|
||||||
if (!g_buf)
|
if (!g_buf) {
|
||||||
err_exit("Failed to allocate internal buffer: %s\n",
|
ntfs_log_perror("Could not create work space");
|
||||||
strerror(errno));
|
goto done;
|
||||||
|
}
|
||||||
|
|
||||||
/* Create runlist for $BadClus, $DATA named stream $Bad. */
|
/* Create runlist for $BadClus, $DATA named stream $Bad. */
|
||||||
mkntfs_initialize_rl_bad();
|
mkntfs_initialize_rl_bad();
|
||||||
/* If not quick format, fill the device with 0s. */
|
/* If not quick format, fill the device with 0s. */
|
||||||
@ -5068,37 +5178,42 @@ int main(int argc, char **argv)
|
|||||||
* update during each subsequent c&w of each system file.
|
* update during each subsequent c&w of each system file.
|
||||||
*/
|
*/
|
||||||
ntfs_log_verbose("Syncing root directory index record.\n");
|
ntfs_log_verbose("Syncing root directory index record.\n");
|
||||||
mkntfs_sync_index_record(g_index_block, (MFT_RECORD*)(g_buf +
|
mkntfs_sync_index_record(g_index_block, (MFT_RECORD*)(g_buf + 5 * g_vol->mft_record_size), NTFS_INDEX_I30, 4);
|
||||||
5 * g_vol->mft_record_size), NTFS_INDEX_I30, 4);
|
|
||||||
|
|
||||||
ntfs_log_verbose("Syncing $Bitmap.\n");
|
ntfs_log_verbose("Syncing $Bitmap.\n");
|
||||||
m = (MFT_RECORD*)(g_buf + 6 * g_vol->mft_record_size);
|
m = (MFT_RECORD*)(g_buf + 6 * g_vol->mft_record_size);
|
||||||
|
|
||||||
ctx = ntfs_attr_get_search_ctx(NULL, m);
|
ctx = ntfs_attr_get_search_ctx(NULL, m);
|
||||||
if (!ctx)
|
if (!ctx) {
|
||||||
err_exit("Failed to allocate attribute search context: %s\n",
|
ntfs_log_perror("Could not create an attribute search context");
|
||||||
strerror(errno));
|
goto done;
|
||||||
if (mkntfs_attr_lookup(AT_DATA, AT_UNNAMED, 0, 0, 0, NULL, 0, ctx)) {
|
|
||||||
ntfs_attr_put_search_ctx(ctx);
|
|
||||||
err_exit("BUG: $DATA attribute not found.\n");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (mkntfs_attr_lookup(AT_DATA, AT_UNNAMED, 0, 0, 0, NULL, 0, ctx)) {
|
||||||
|
ntfs_log_error("BUG: $DATA attribute not found.\n");
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
|
||||||
a = ctx->attr;
|
a = ctx->attr;
|
||||||
if (a->non_resident) {
|
if (a->non_resident) {
|
||||||
runlist *rl = ntfs_mapping_pairs_decompress(g_vol, a, NULL);
|
runlist *rl = ntfs_mapping_pairs_decompress(g_vol, a, NULL);
|
||||||
ntfs_attr_put_search_ctx(ctx);
|
if (!rl) {
|
||||||
if (!rl)
|
ntfs_log_error("ntfs_mapping_pairs_decompress() failed\n");
|
||||||
err_exit("ntfs_mapping_pairs_decompress() failed\n");
|
goto done;
|
||||||
lw = ntfs_rlwrite(g_vol->dev, rl, g_lcn_bitmap,
|
}
|
||||||
g_lcn_bitmap_byte_size, NULL);
|
lw = ntfs_rlwrite(g_vol->dev, rl, g_lcn_bitmap, g_lcn_bitmap_byte_size, NULL);
|
||||||
err = errno;
|
err = errno;
|
||||||
free(rl);
|
free(rl);
|
||||||
if (lw != g_lcn_bitmap_byte_size)
|
if (lw != g_lcn_bitmap_byte_size) {
|
||||||
err_exit("%s\n", lw == -1 ? strerror(err) :
|
ntfs_log_error("%s\n", lw == -1 ? strerror(err) : "unknown error");
|
||||||
"unknown error");
|
goto done;
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
memcpy((char*)a + le16_to_cpu(a->value_offset), g_lcn_bitmap,
|
memcpy((char*)a + le16_to_cpu(a->value_offset), g_lcn_bitmap, le32_to_cpu(a->value_length));
|
||||||
le32_to_cpu(a->value_length));
|
|
||||||
ntfs_attr_put_search_ctx(ctx);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------------------
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* No need to sync $MFT/$BITMAP as that has never been modified since
|
* No need to sync $MFT/$BITMAP as that has never been modified since
|
||||||
* its creation.
|
* its creation.
|
||||||
@ -5108,19 +5223,17 @@ int main(int argc, char **argv)
|
|||||||
lw = 1;
|
lw = 1;
|
||||||
for (i = 0; i < g_mft_size / (s32)g_vol->mft_record_size; i++) {
|
for (i = 0; i < g_mft_size / (s32)g_vol->mft_record_size; i++) {
|
||||||
if (!opts.no_action)
|
if (!opts.no_action)
|
||||||
lw = ntfs_mst_pwrite(g_vol->dev, pos, 1,
|
lw = ntfs_mst_pwrite(g_vol->dev, pos, 1, g_vol->mft_record_size, g_buf + i * g_vol->mft_record_size);
|
||||||
g_vol->mft_record_size,
|
if (lw != 1) {
|
||||||
g_buf + i * g_vol->mft_record_size);
|
ntfs_log_error("%s\n", lw == -1 ? strerror(errno) : "unknown error");
|
||||||
if (lw != 1)
|
goto done;
|
||||||
err_exit("%s\n", lw == -1 ? strerror(errno) :
|
}
|
||||||
"unknown error");
|
|
||||||
pos += g_vol->mft_record_size;
|
pos += g_vol->mft_record_size;
|
||||||
}
|
}
|
||||||
ntfs_log_verbose("Updating $MFTMirr.\n");
|
ntfs_log_verbose("Updating $MFTMirr.\n");
|
||||||
pos = g_mftmirr_lcn * g_vol->cluster_size;
|
pos = g_mftmirr_lcn * g_vol->cluster_size;
|
||||||
lw = 1;
|
lw = 1;
|
||||||
for (i = 0; i < g_rl_mftmirr[0].length * g_vol->cluster_size /
|
for (i = 0; i < g_rl_mftmirr[0].length * g_vol->cluster_size / g_vol->mft_record_size; i++) {
|
||||||
g_vol->mft_record_size; i++) {
|
|
||||||
u16 usn, *usnp;
|
u16 usn, *usnp;
|
||||||
m = (MFT_RECORD*)(g_buf + i * g_vol->mft_record_size);
|
m = (MFT_RECORD*)(g_buf + i * g_vol->mft_record_size);
|
||||||
/*
|
/*
|
||||||
@ -5135,22 +5248,51 @@ int main(int argc, char **argv)
|
|||||||
usn = 0xfffe;
|
usn = 0xfffe;
|
||||||
*usnp = cpu_to_le16(usn);
|
*usnp = cpu_to_le16(usn);
|
||||||
if (!opts.no_action)
|
if (!opts.no_action)
|
||||||
lw = ntfs_mst_pwrite(g_vol->dev, pos, 1,
|
lw = ntfs_mst_pwrite(g_vol->dev, pos, 1, g_vol->mft_record_size, g_buf + i * g_vol->mft_record_size);
|
||||||
g_vol->mft_record_size,
|
if (lw != 1) {
|
||||||
g_buf + i * g_vol->mft_record_size);
|
ntfs_log_error("%s\n", lw == -1 ? strerror(errno) : "unknown error");
|
||||||
if (lw != 1)
|
goto done;
|
||||||
err_exit("%s\n", lw == -1 ? strerror(errno) :
|
}
|
||||||
"unknown error");
|
|
||||||
pos += g_vol->mft_record_size;
|
pos += g_vol->mft_record_size;
|
||||||
}
|
}
|
||||||
ntfs_log_verbose("Syncing device.\n");
|
ntfs_log_verbose("Syncing device.\n");
|
||||||
if (g_vol->dev->d_ops->sync(g_vol->dev))
|
if (g_vol->dev->d_ops->sync(g_vol->dev)) {
|
||||||
err_exit("Syncing device. FAILED: %s", strerror(errno));
|
ntfs_log_error("Syncing device. FAILED");
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
ntfs_log_quiet("mkntfs completed successfully. Have a nice day.\n");
|
ntfs_log_quiet("mkntfs completed successfully. Have a nice day.\n");
|
||||||
/*
|
result = 0;
|
||||||
* Device is unlocked and closed by the registered exit function
|
done:
|
||||||
* mkntfs_exit().
|
ntfs_attr_put_search_ctx(ctx);
|
||||||
*/
|
mkntfs_exit(); /* Device is unlocked and closed here */
|
||||||
return 0;
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* main - Begin here
|
||||||
|
*
|
||||||
|
* Start from here.
|
||||||
|
*
|
||||||
|
* Return: 0 Success, the program worked
|
||||||
|
* 1 Error, something went wrong
|
||||||
|
*/
|
||||||
|
int main(int argc, char *argv[])
|
||||||
|
{
|
||||||
|
int result = 1;
|
||||||
|
|
||||||
|
ntfs_log_set_handler(ntfs_log_handler_outerr);
|
||||||
|
utils_set_locale();
|
||||||
|
|
||||||
|
mkntfs_init_options(&opts); /* Set up the options */
|
||||||
|
|
||||||
|
if (!mkntfs_parse_options(argc, argv, &opts)) /* Read the command line options */
|
||||||
|
goto done;
|
||||||
|
if (!mkntfs_validate_options(&opts)) /* Validate those options */
|
||||||
|
goto done;
|
||||||
|
|
||||||
|
result = mkntfs_redirect(&opts);
|
||||||
|
done:
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user