parent
							
								
									b9d2243a6b
								
							
						
					
					
						commit
						d0cc759878
					
				|  | @ -80,7 +80,7 @@ typedef enum { | |||
|  * NTFS version 1.1 and 1.2 are used by Windows NT4. | ||||
|  * NTFS version 2.x is used by Windows 2000 Beta | ||||
|  * NTFS version 3.0 is used by Windows 2000. | ||||
|  * NTFS version 3.1 is used by Windows XP and .NET. | ||||
|  * NTFS version 3.1 is used by Windows XP and Windows Server 2003. | ||||
|  */ | ||||
| 
 | ||||
| #define NTFS_V1_1(major, minor) ((major) == 1 && (minor) == 1) | ||||
|  |  | |||
|  | @ -2785,7 +2785,7 @@ put_err_out: | |||
|  * and do clear the partial run. The latter approach would be more inline with | ||||
|  * what windows would do, even though windows wouldn't even make the attribute | ||||
|  * sparse, it would just allocate clusters instead. TODO: Check what happens on | ||||
|  * WinXP and .NET. FIXME: Make sure to check what NT4 does with an NTFS1.2 | ||||
|  * WinXP and 2003. FIXME: Make sure to check what NT4 does with an NTFS1.2 | ||||
|  * volume that has sparse files. I suspect it will blow up so we will need to | ||||
|  * perform allocations of clusters, like NT4 would do for NTFS1.2 while we can | ||||
|  * use sparse attributes on NTFS3.x. | ||||
|  |  | |||
|  | @ -1100,7 +1100,7 @@ int ntfs_check_if_mounted(const char *file, unsigned long *mnt_flags) | |||
|  * Version 1.1 and 1.2 are used by Windows NT4. | ||||
|  * Version 2.x is used by Windows 2000 Beta's | ||||
|  * Version 3.0 is used by Windows 2000. | ||||
|  * Version 3.1 is used by Windows XP and .NET. | ||||
|  * Version 3.1 is used by Windows XP and Windows Server 2003. | ||||
|  * | ||||
|  * Return 0 if NTFS version is supported otherwise -1 with errno set. | ||||
|  * | ||||
|  |  | |||
|  | @ -1,7 +1,7 @@ | |||
| .\" -*- nroff -*- | ||||
| .\" Copyright 2002-2003 by Szabolcs Szakacsits  All Rights Reserved. | ||||
| .\" | ||||
| .TH NTFSRESIZE 8 "Jan 2003" "ntfsprogs @VERSION@" | ||||
| .TH NTFSRESIZE 8 "Oct 2003" "ntfsprogs @VERSION@" | ||||
| .SH NAME | ||||
| ntfsresize \- resize an NTFS filesystem | ||||
| .SH SYNOPSIS | ||||
|  | @ -12,8 +12,8 @@ ntfsresize \- resize an NTFS filesystem | |||
| .SH DESCRIPTION | ||||
| The | ||||
| .B ntfsresize | ||||
| program non-destructively resizes Windows NT4, 2000, XP or .NET | ||||
| NTFS filesystems.  At present it can be used to enlarge or shrink a | ||||
| program non-destructively resizes Windows NT4, 2000, XP or Windows Server 2003 | ||||
| NTFS filesystems.  At present it can be used to enlarge any or shrink a | ||||
| defragmented NTFS filesystem located on an unmounted | ||||
| .I device | ||||
| (usually a disk partition). The new volume will have | ||||
|  | @ -28,12 +28,29 @@ parameter is given in kilo-, mega- or gigabytes respectively. | |||
| .B ntfsresize | ||||
| conforms to the SI, ATA, IEEE standards and the disk manufacturers | ||||
| by using k=10^3, M=10^6 and G=10^9. | ||||
| The options  | ||||
| 
 | ||||
| If both  | ||||
| .B -i | ||||
| and | ||||
| .B -s | ||||
| are omitted then the  | ||||
| NTFS filesystem will be enlarged to the device size. | ||||
| 
 | ||||
| If the options | ||||
| .B -i  | ||||
| and  | ||||
| .B -s  | ||||
| are mutually exclusive. If both of them are omitted then the  | ||||
| NTFS filesystem will be enlarged to the device size. | ||||
| are used together then list inodes (files) using space over  | ||||
| .I size\fR. At present | ||||
| .B ntfsresize  | ||||
| can not relocate the files listed to the beginning  | ||||
| of the partition thus it refuses to resize at | ||||
| .I size | ||||
| if there is any. | ||||
| To convert the inodes to meaningful file names, you must mount  | ||||
| the partition and run for instance | ||||
|  'find /mount/point -inum <inode1> -o -inum <inode2> ...'. | ||||
| 
 | ||||
| Before a real resize operation, always make a read-only  | ||||
| test run using the  | ||||
| .B -n  | ||||
|  | @ -45,9 +62,9 @@ program doesn't manipulate the size of partitions. | |||
| To do that you have to use a disk partitioning tool, for example | ||||
| .BR fdisk (8). | ||||
| .PP | ||||
| If you wish to enlarge an NTFS filesystem,  | ||||
| you must first make sure you can expand the size of the | ||||
| underlying partition first. This can be done using  | ||||
| If you wish to enlarge an NTFS filesystem  then | ||||
| first you must enlarge the size of the | ||||
| underlying partition. This can be done using  | ||||
| .BR fdisk (8) | ||||
| by deleting the partition and recreating it with a larger size. | ||||
| Then  you may use | ||||
|  | @ -78,7 +95,7 @@ computer from the disk! | |||
| .PP | ||||
| Note, | ||||
| .B ntfsresize | ||||
| schedules 'chkdsk' to make an NTFS consistency check | ||||
| schedules an NTFS consistency check | ||||
| when you will boot Windows. Windows may force a reboot after | ||||
| the successful consistency check. | ||||
| 
 | ||||
|  | @ -96,7 +113,9 @@ Display help and exit. | |||
| .TP | ||||
| .B -i | ||||
| Using this option you can calculate the smallest shrunken volume size supported. | ||||
| This option will not make any changes to the filesystem. | ||||
| This option will not make any changes to the filesystem.  | ||||
| You can use this option with  | ||||
| .B -s\fR. See the meaning of this case above. | ||||
| .TP | ||||
| .B -n | ||||
| Use this option to make a test run before doing the real resize operation. | ||||
|  | @ -109,7 +128,11 @@ Resize volume to \fIsize\fR[\fBk\fR|\fBM\fR|\fBG\fR] bytes. | |||
| The optional modifiers \fBk\fR, \fBM\fR, \fBG\fR mean the | ||||
| .I size | ||||
| parameter is given in kilo-, mega- or gigabytes respectively. | ||||
| Conforming to standards, k=10^3, M=10^6 and G=10^9. | ||||
| Conforming to standards, k=10^3, M=10^6 and G=10^9. You can also use this option | ||||
| with | ||||
| .B -i\fR. See the meaning of this case above. | ||||
| .SH EXIT CODES | ||||
| The exit code is 0 on success, non-zero otherwise.  | ||||
| .SH BUGS | ||||
| No bugs are known or has been reported so far in the current version. | ||||
| If you find otherwise, please report it to <linux-ntfs-dev@lists.sourceforge.net> | ||||
|  | @ -117,8 +140,9 @@ If you find otherwise, please report it to <linux-ntfs-dev@lists.sourceforge.net | |||
| .B MAKE SURE YOU HAVE A BACKUP | ||||
| of your important data in case of an unexpected failure. | ||||
| .PP | ||||
| Future work is planned to include support resizing fragmented NTFS volumes. | ||||
| Please note, Windows 2000, XP and .NET have built in NTFS defragmenter. | ||||
| Future work is planned to include support for resizing fragmented NTFS volumes. | ||||
| Please note, Windows 2000, XP and Windows Server 2003 have built in NTFS  | ||||
| defragmenter.  | ||||
| .SH AUTHOR | ||||
| .B ntfsresize | ||||
| has been written by | ||||
|  | @ -143,5 +167,6 @@ http://mlf.linux.rulez.org/mlf/ezaz/ntfsresize.html | |||
| .BR sfdisk (8), | ||||
| .BR parted (8), | ||||
| .BR mkntfs (8), | ||||
| .BR ntfsclone (8), | ||||
| .BR ntfsprogs (8) | ||||
| 
 | ||||
|  |  | |||
|  | @ -64,8 +64,7 @@ static const char *resize_important_msg = | |||
| "Otherwise you may lose your data or can't boot your computer from the disk!\n"; | ||||
| 
 | ||||
| static const char *fragmented_volume_msg = | ||||
| "The volume end is fragmented, this case is not yet supported. Defragment it\n" | ||||
| "(Windows 2000, XP and .NET have built in defragmentation tool) and try again.\n"; | ||||
| "The volume end is fragmented, this case is not yet supported.\n"; | ||||
| 
 | ||||
| struct { | ||||
| 	int verbose; | ||||
|  | @ -473,11 +472,48 @@ s64 nr_clusters_to_bitmap_byte_size(s64 nr_clusters) | |||
| 	return bm_bsize; | ||||
| } | ||||
| 
 | ||||
| int str2unicode(char *aname, uchar_t **ustr, int *len) | ||||
| { | ||||
| 	if (aname && ((*len = ntfs_mbstoucs(aname, ustr, 0)) == -1)) | ||||
| 		return -1; | ||||
| 
 | ||||
| 	if (!*ustr || !*len) { | ||||
| 		*ustr = AT_UNNAMED; | ||||
| 		*len = 0; | ||||
| 	} | ||||
| 	 | ||||
| 	return 0; | ||||
| } | ||||
| 
 | ||||
| int has_bad_sectors(ntfs_resize_t *resize) | ||||
| { | ||||
| 	int len, ret = 0; | ||||
| 	uchar_t *ustr = NULL; | ||||
| 	ATTR_RECORD *a = resize->ctx->attr; | ||||
| 	 | ||||
| 	if (resize->ni->mft_no != 8) | ||||
| 		return 0; | ||||
| 
 | ||||
| 	if (str2unicode("$Bad", &ustr, &len) == -1) | ||||
| 		return -1; | ||||
| 
 | ||||
| 	if (ustr && ntfs_names_are_equal(ustr, len, | ||||
| 			(uchar_t*)((char*)a + le16_to_cpu(a->name_offset)), | ||||
| 			a->name_length, 0, NULL, 0))  | ||||
| 		ret = 1; | ||||
| 									 | ||||
| 	if (ustr != AT_UNNAMED) | ||||
| 		free(ustr); | ||||
| 
 | ||||
| 	return ret;	 | ||||
| } | ||||
| 
 | ||||
| void collect_shrink_constraints(ntfs_resize_t *resize, s64 last_lcn) | ||||
| { | ||||
| 	s64 inode; | ||||
| 	ATTR_FLAGS flags; | ||||
| 	struct llcn_t *llcn; | ||||
| 	struct llcn_t *llcn = NULL; | ||||
| 	int ret; | ||||
| 
 | ||||
| 	inode = resize->ni->mft_no; | ||||
| 	flags = resize->ctx->attr->flags; | ||||
|  | @ -491,7 +527,12 @@ void collect_shrink_constraints(ntfs_resize_t *resize, s64 last_lcn) | |||
| 	else if (flags & ATTR_IS_COMPRESSED) | ||||
| 		llcn = &resize->last_compressed; | ||||
| 
 | ||||
| 	else if (inode == 0) | ||||
| 	else if ((ret = has_bad_sectors(resize)) != 0) { | ||||
| 		if (ret == -1) | ||||
| 			perr_exit("Couldn't convert string to Unicode."); | ||||
| 		err_exit("Device has bad sectors, not supported yet.\n"); | ||||
| 
 | ||||
| 	} else if (inode == 0) | ||||
| 		llcn = &resize->last_mft; | ||||
| 	 | ||||
| 	else if (inode == 1) | ||||
|  | @ -633,6 +674,7 @@ void compare_bitmaps(struct bitmap *a) | |||
| { | ||||
| 	s64 i, pos, count; | ||||
| 	int mismatch = 0; | ||||
| 	int backup_boot = 0; | ||||
| 	u8 bm[NTFS_BUF_SIZE]; | ||||
| 
 | ||||
| 	printf("Accounting clusters ...\n"); | ||||
|  | @ -664,6 +706,15 @@ void compare_bitmaps(struct bitmap *a) | |||
| 				if (bit == ntfs_bit_get(bm, i * 8 + cl % 8)) | ||||
| 					continue; | ||||
| 
 | ||||
| 				if (!mismatch && !bit && !backup_boot &&  | ||||
| 						cl == vol->nr_clusters / 2) { | ||||
| 					/* FIXME: call also boot sector check */ | ||||
| 					backup_boot = 1; | ||||
| 					printf("Found backup boot sector in " | ||||
| 					       "the middle of the volume.\n"); | ||||
| 					continue;        | ||||
| 				}	 | ||||
| 
 | ||||
| 				if (++mismatch > 10) | ||||
| 					continue; | ||||
| 
 | ||||
|  | @ -679,7 +730,7 @@ void compare_bitmaps(struct bitmap *a) | |||
| 		       mismatch); | ||||
| 		err_exit("Filesystem check failed! Windows wasn't shutdown " | ||||
| 			 "properly or inconsistent\nfilesystem. Please run " | ||||
| 			 "chkdsk on Windows.\n"); | ||||
| 			 "chkdsk /f on Windows.\n"); | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
|  | @ -767,7 +818,7 @@ void print_hint(const char *s, struct llcn_t llcn) | |||
| 	 | ||||
| 	runs_b = llcn.lcn * vol->cluster_size; | ||||
| 	runs_mb = rounded_up_division(runs_b, NTFS_MBYTE); | ||||
| 	printf("%-19s: %6Ld MB      %8Ld\n", s, runs_mb, llcn.inode); | ||||
| 	printf("%-19s: %9Ld MB      %8Ld\n", s, runs_mb, llcn.inode); | ||||
| } | ||||
| 
 | ||||
| /**
 | ||||
|  | @ -788,7 +839,7 @@ void advise_on_resize(ntfs_resize_t *resize) | |||
| 	old_b = vol->nr_clusters * vol->cluster_size; | ||||
| 	old_mb = rounded_up_division(old_b, NTFS_MBYTE); | ||||
| 	 | ||||
| 	printf("File feature         Last used    Last inode\n"); | ||||
| 	printf("File feature         Last used at      By inode\n"); | ||||
| 	print_hint("$MFT", resize->last_mft); | ||||
| 	print_hint("$MFTMirr", resize->last_mftmir); | ||||
| 	print_hint("Compressed", resize->last_compressed); | ||||
|  | @ -828,27 +879,6 @@ void advise_on_resize(ntfs_resize_t *resize) | |||
| 	printf(").\n"); | ||||
| } | ||||
| 
 | ||||
| /**
 | ||||
|  * look_for_bad_sector | ||||
|  * | ||||
|  * Read through the metadata file $BadClus looking for bad sectors on the disk. | ||||
|  */ | ||||
| void look_for_bad_sector(ATTR_RECORD *a) | ||||
| { | ||||
| 	runlist *rl; | ||||
| 	int i; | ||||
| 
 | ||||
| 	rl = ntfs_mapping_pairs_decompress(vol, a, NULL); | ||||
| 	if (!rl) | ||||
| 		perr_exit("ntfs_mapping_pairs_decompress"); | ||||
| 
 | ||||
| 	for (i = 0; rl[i].length; i++) | ||||
| 		if (rl[i].lcn != LCN_HOLE) | ||||
| 			err_exit("Device has bad sectors, not supported\n"); | ||||
| 
 | ||||
| 	free(rl); | ||||
| } | ||||
| 
 | ||||
| /**
 | ||||
|  * rl_set | ||||
|  * | ||||
|  | @ -1101,14 +1131,9 @@ void lookup_data_attr(MFT_REF mref, char *aname, ntfs_attr_search_ctx **ctx) | |||
| 	if (!(*ctx = ntfs_attr_get_search_ctx(ni, NULL))) | ||||
| 		perr_exit("ntfs_get_attr_search_ctx"); | ||||
| 
 | ||||
| 	if (aname && ((len = ntfs_mbstoucs(aname, &ustr, 0)) == -1)) | ||||
| 	if (str2unicode(aname, &ustr, &len) == -1) | ||||
| 		perr_exit("Unable to convert string to Unicode"); | ||||
| 
 | ||||
| 	if (!ustr || !len) { | ||||
| 		ustr = AT_UNNAMED; | ||||
| 		len = 0; | ||||
| 	} | ||||
| 
 | ||||
| 	if (ntfs_attr_lookup(AT_DATA, ustr, len, 0, 0, NULL, 0, *ctx)) | ||||
| 		perr_exit("ntfs_lookup_attr"); | ||||
| 
 | ||||
|  | @ -1145,7 +1170,6 @@ void truncate_badclust_file(s64 nr_clusters) | |||
| 	printf("Updating $BadClust file ...\n"); | ||||
| 
 | ||||
| 	lookup_data_attr((MFT_REF)FILE_BadClus, "$Bad", &ctx); | ||||
| 	look_for_bad_sector(ctx->attr); | ||||
| 	/* FIXME: sanity_check_attr(ctx->attr); */ | ||||
| 	truncate_badclust_bad_attr(ctx->attr, nr_clusters); | ||||
| 
 | ||||
|  | @ -1247,11 +1271,10 @@ void print_volume_size(char *str, s64 bytes) | |||
|  */ | ||||
| void print_disk_usage(ntfs_resize_t *resize) | ||||
| { | ||||
| 	s64 total, used, free, relocations; | ||||
| 	s64 total, used, relocations; | ||||
| 
 | ||||
| 	total = vol->nr_clusters * vol->cluster_size; | ||||
| 	used = resize->inuse * vol->cluster_size; | ||||
| 	free = total - used; | ||||
| 	relocations = resize->relocations * vol->cluster_size; | ||||
| 
 | ||||
| 	printf("Space in use       : %lld MB (%.1f%%)\n", | ||||
|  | @ -1275,9 +1298,12 @@ void mount_volume() | |||
| { | ||||
| 	unsigned long mntflag; | ||||
| 
 | ||||
| 	if (ntfs_check_if_mounted(opt.volume, &mntflag)) | ||||
| 		perr_exit("Failed to check '%s' mount state", opt.volume); | ||||
| 
 | ||||
| 	if (ntfs_check_if_mounted(opt.volume, &mntflag)) { | ||||
| 		perr_printf("Failed to check '%s' mount state", opt.volume); | ||||
| 		printf("Probably /etc/mtab is missing. It's too risky to" | ||||
| 		       "continue.\nYou might try an another Linux distro.\n"); | ||||
| 		exit(1); | ||||
| 	} | ||||
| 	if (mntflag & NTFS_MF_MOUNTED) { | ||||
| 		if (!(mntflag & NTFS_MF_READONLY)) | ||||
| 			err_exit("Device %s is mounted read-write. " | ||||
|  | @ -1303,7 +1329,7 @@ void mount_volume() | |||
| 
 | ||||
| 	if (vol->flags & VOLUME_IS_DIRTY) | ||||
| 		if (opt.force-- <= 0) | ||||
| 			err_exit("Volume is dirty. Run chkdsk and " | ||||
| 			err_exit("Volume is dirty. Run chkdsk /f and " | ||||
| 				 "please try again (or see -f option).\n"); | ||||
| 
 | ||||
| 	printf("NTFS volume version: %d.%d\n", vol->major_ver, vol->minor_ver); | ||||
|  | @ -1383,7 +1409,9 @@ int main(int argc, char **argv) | |||
| 	if (opt.bytes) { | ||||
| 		if (device_size < opt.bytes) | ||||
| 			err_exit("New size can't be bigger than the " | ||||
| 				 "device size (%Ld bytes).\n", device_size); | ||||
| 				 "device size (%Ld bytes).\nIf you want to " | ||||
| 				 "enlarge NTFS then first enlarge the device " | ||||
| 				 "size by e.g. fdisk.\n", device_size); | ||||
| 	} else if (!opt.info) | ||||
| 		opt.bytes = device_size; | ||||
| 
 | ||||
|  | @ -1424,7 +1452,7 @@ int main(int argc, char **argv) | |||
| 		       resize.multi_ref); | ||||
| 		err_exit("Filesystem check failed! Windows wasn't shutdown " | ||||
| 			 "properly or inconsistent\nfilesystem. Please run " | ||||
| 			 "chkdsk on Windows.\n"); | ||||
| 			 "chkdsk /f on Windows.\n"); | ||||
| 	} | ||||
| 	compare_bitmaps(&lcn_bitmap); | ||||
| 
 | ||||
|  |  | |||
		Loading…
	
		Reference in New Issue