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:
flatcap 2005-11-06 21:40:26 +00:00
parent d605234a3a
commit 2a2ecd2abd

View File

@ -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, &sect_size) if (g_vol->dev->d_ops->ioctl(g_vol->dev, BLKSSZGET, &sect_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;
} }