⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 ntfsresize.c

📁 上一个上传的有问题,这个是好的。visopsys包括系统内核和GUI的全部SOURCE code ,还包括一些基本的docs文档。里面src子目录对应所有SOURCE code.对于想研究操作系统的朋
💻 C
📖 第 1 页 / 共 5 页
字号:
			opt.debug++;			break;		case 'f':			opt.force++;			break;		case 'h':		case '?':			help++;			break;		case 'i':			opt.info++;			break;		case 'n':			opt.ro_flag = MS_RDONLY;			break;		case 'P':			opt.show_progress = 0;			break;		case 's':			if (!err && (opt.bytes == 0))				opt.bytes = get_new_volume_size(optarg);			else				err++;			break;		case 'v':			opt.verbose++;			ntfs_log_set_levels(NTFS_LOG_LEVEL_VERBOSE);			break;		case 'V':			ver++;			break;		default:			if (optopt == 's') {				printf("Option '%s' requires an argument.\n", argv[optind-1]);			} else {				printf("Unknown option '%s'.\n", argv[optind-1]);			}			err++;			break;		}	}	if (!help && !ver) {		if (opt.volume == NULL) {			if (argc > 1)				printf("You must specify exactly one device.\n");			err++;		}		if (opt.info) {			opt.ro_flag = MS_RDONLY;			if (opt.bytes) {				printf(NERR_PREFIX "Options --info and --size "					"can't be used together.\n");				usage();			}		}	}	/* Redirect stderr to stdout, note fflush()es are essential! */	fflush(stdout);	fflush(stderr);	if (dup2(STDOUT_FILENO, STDERR_FILENO) == -1)		perr_exit("Failed to redirect stderr to stdout");	fflush(stdout);	fflush(stderr);#ifdef DEBUG	if (!opt.debug)		if (!freopen("/dev/null", "w", stderr))			perr_exit("Failed to redirect stderr to /dev/null");#endif	if (ver)		version();	if (help || err)		usage();	return (!err && !help && !ver);}static void print_advise(ntfs_volume *vol, s64 supp_lcn){	s64 old_b, new_b, freed_b, old_mb, new_mb, freed_mb;	old_b = vol->nr_clusters * vol->cluster_size;	old_mb = rounded_up_division(old_b, NTFS_MBYTE);	/* Take the next supported cluster (free or relocatable)	   plus reserve a cluster for the backup boot sector */	supp_lcn += 2;	if (supp_lcn > vol->nr_clusters) {		err_printf("Very rare fragmentation type detected. "			   "Sorry, it's not supported yet.\n"			   "Try to defragment your NTFS, perhaps it helps.\n");		exit(1);	}	new_b = supp_lcn * vol->cluster_size;	new_mb = rounded_up_division(new_b, NTFS_MBYTE);	freed_b = (vol->nr_clusters - supp_lcn + 1) * vol->cluster_size;	freed_mb = freed_b / NTFS_MBYTE;	/* WARNING: don't modify the text, external tools grep for it */	printf("You might resize at %lld bytes ", (long long)new_b);	if ((new_mb * NTFS_MBYTE) < old_b)		printf("or %lld MB ", (long long)new_mb);	printf("(freeing ");	if (freed_mb && (old_mb - new_mb))	    printf("%lld MB", (long long)(old_mb - new_mb));	else	    printf("%lld bytes", (long long)freed_b);	printf(").\n");	printf("Please make a test run using both the -n and -s options "	       "before real resizing!\n");}#endif /* __VISOPSYS__ */__attribute__((format(printf, 2, 3)))static void progress_message(ntfs_resize_t *resize, const char *fmt, ...){	va_list ap;	char tmp[PROGRESS_MAX_MESSAGELEN];	va_start(ap, fmt);	vsprintf(tmp, fmt, ap);	va_end(ap);	if (resize->prog && (lockGet(&(resize->prog->lock)) >= 0))	  {	    strncpy((char *) resize->prog->statusMessage, tmp,		    PROGRESS_MAX_MESSAGELEN);	    lockRelease(&(resize->prog->lock));	  }	ntfs_log_debug("%s\n", tmp);}__attribute__((format(printf, 3, 4)))static void _err_printf(ntfs_resize_t *resize, const char *function,			const char *fmt, ...){	va_list ap;	char tmp[PROGRESS_MAX_MESSAGELEN];	strcpy(tmp, ERR_PREFIX);	if (function)	  sprintf((tmp + strlen(tmp)), "%s: ", function);	va_start(ap, fmt);	vsprintf((tmp + strlen(tmp)), fmt, ap);	va_end(ap);	if (resize->prog && (lockGet(&(resize->prog->lock)) >= 0))	  {	    strncpy((char *) resize->prog->statusMessage, tmp,		    PROGRESS_MAX_MESSAGELEN);	    resize->prog->error = 1;	    lockRelease(&(resize->prog->lock));	    while (resize->prog->error)	      multitaskerYield();	  }	ntfs_log_trace("%s\n", tmp);}#ifdef DEBUG#define err_printf(r, f, a...) _err_printf(r, __FUNCTION__, f, ##a)#else#define err_printf(r, f, a...) _err_printf(r, NULL, f, ##a)#endifstatic void rl_set(runlist *rl, VCN vcn, LCN lcn, s64 len){	rl->vcn = vcn;	rl->lcn = lcn;	rl->length = len;}static int rl_items(runlist *rl){	int i = 0;	while (rl[i++].length)		;	return i;}#ifndef __VISOPSYS__static void dump_run(runlist_element *r){	ntfs_log_verbose(" %8lld  %8lld (0x%08llx)  %lld\n", (long long)r->vcn,			 (long long)r->lcn, (long long)r->lcn,			 (long long)r->length);}static void dump_runlist(runlist *rl){	while (rl->length)		dump_run(rl++);}#endif /* __VISOPSYS__ *//** * nr_clusters_to_bitmap_byte_size * * Take the number of clusters in the volume and calculate the size of $Bitmap. * The size must be always a multiple of 8 bytes. */static s64 nr_clusters_to_bitmap_byte_size(s64 nr_clusters){	s64 bm_bsize;	bm_bsize = rounded_up_division(nr_clusters, 8);	bm_bsize = (bm_bsize + 7) & ~7;	return bm_bsize;}static int collect_resize_constraints(ntfs_resize_t *resize, runlist *rl){	s64 inode, last_lcn;	ATTR_FLAGS flags;	ATTR_TYPES atype;	struct llcn_t *llcn = NULL;	int ret, supported = 0;	last_lcn = rl->lcn + (rl->length - 1);	inode = resize->ni->mft_no;	flags = resize->ctx->attr->flags;	atype = resize->ctx->attr->type;	if ((ret = ntfs_inode_badclus_bad(inode, resize->ctx->attr)) != 0) {		if (ret == -1)			err_printf(resize, "Bad sector list check failed");		return (-1);	}	if (inode == FILE_Bitmap) {		llcn = &resize->last_lcn;		if (atype == AT_DATA && NInoAttrList(resize->ni)) {			err_printf(resize, "Highly fragmented $Bitmap isn't supported yet.");			return (-1);		}		supported = 1;	} else if (inode == FILE_MFT) {		llcn = &resize->last_mft;		/*		 *  First run of $MFT AT_DATA isn't supported yet.		 */		if (atype != AT_DATA || rl->vcn)			supported = 1;	} else if (NInoAttrList(resize->ni)) {		llcn = &resize->last_multi_mft;		if (inode != FILE_MFTMirr)			supported = 1;	} else if (flags & ATTR_IS_SPARSE) {		llcn = &resize->last_sparse;		supported = 1;	} else if (flags & ATTR_IS_COMPRESSED) {		llcn = &resize->last_compressed;		supported = 1;	} else if (inode == FILE_MFTMirr) {		llcn = &resize->last_mftmir;		supported = 1;		/* Fragmented $MFTMirr DATA attribute isn't supported yet */		if (atype == AT_DATA)			if (rl[1].length != 0 || rl->vcn)				supported = 0;	} else {		llcn = &resize->last_lcn;		supported = 1;	}	if (llcn->lcn < last_lcn) {		llcn->lcn = last_lcn;		llcn->inode = inode;	}	if (supported)		return (0);	if (resize->last_unsupp < last_lcn)		resize->last_unsupp = last_lcn;	return (0);}static int collect_relocation_info(ntfs_resize_t *resize, runlist *rl){	s64 lcn, lcn_length, start, len, inode;	s64 new_vol_size;	/* (last LCN on the volume) + 1 */	lcn = rl->lcn;	lcn_length = rl->length;	inode = resize->ni->mft_no;	new_vol_size = resize->new_volume_size;	if (lcn + lcn_length <= new_vol_size)		return (0);	if (inode == FILE_Bitmap && resize->ctx->attr->type == AT_DATA)		return (0);		start = lcn;	len = lcn_length;	if (lcn < new_vol_size) {		start = new_vol_size;		len = lcn_length - (new_vol_size - lcn);		if (!opt.info && (inode == FILE_MFTMirr)) {			err_printf(resize, "$MFTMirr can't be split up yet.  "				   "Please try a different size.");			return (-1);		}	}	resize->relocations += len;	if (!opt.info || !resize->new_volume_size)		return (0);	progress_message(resize, "Relocation needed for inode %8lld", (long long)inode);	return (0);}/** * build_lcn_usage_bitmap * * lcn_bitmap has one bit for each cluster on the disk.  Initially, lcn_bitmap * has no bits set.  As each attribute record is read the bits in lcn_bitmap are * checked to ensure that no other file already references that cluster. * * This serves as a rudimentary "chkdsk" operation. */static int build_lcn_usage_bitmap(ntfs_resize_t *resize, ntfs_volume *vol, ntfsck_t *fsck){	s64 inode;	ATTR_RECORD *a;	runlist *rl;	int i, j;	struct bitmap *lcn_bitmap = &fsck->lcn_bitmap;	a = fsck->ctx->attr;	inode = fsck->ni->mft_no;	if (!a->non_resident)		return (0);	if (!(rl = ntfs_mapping_pairs_decompress(vol, a, NULL))) {		if (errno == EIO)			err_printf(resize, "ntfs_decompress_mapping_pairs: %s", corrupt_volume_msg);		return (-1);	}	for (i = 0; rl[i].length; i++) {		s64 lcn = rl[i].lcn;		s64 lcn_length = rl[i].length;		/* CHECKME: LCN_RL_NOT_MAPPED check isn't needed */		if (lcn == LCN_HOLE || lcn == LCN_RL_NOT_MAPPED)			continue;		/* FIXME: ntfs_mapping_pairs_decompress should return error */		if (lcn < 0 || lcn_length <= 0)		  {			err_printf(resize, "Corrupt runlist in inode %lld attr %x LCN "				 "%llx length %llx", inode,				 (unsigned int)le32_to_cpu(a->type), lcn,				 lcn_length);			return (-1);		  }		for (j = 0; j < lcn_length; j++) {			u64 k = (u64)lcn + j;			if (k >= (u64)vol->nr_clusters) {				long long outsiders = lcn_length - j;				fsck->outsider += outsiders;				if (++fsck->show_outsider <= 10)					progress_message(resize, "Outside of the volume reference"					       " for inode %lld at %lld:%lld",					       inode, (long long)k, outsiders);				break;			}			if (ntfs_bit_get_and_set(lcn_bitmap->bm, k, 1)) {				if (++fsck->multi_ref <= 10)					progress_message(resize, "Cluster %lld is referenced "					       "multiple times!",					       (long long)k);				continue;			}		}		fsck->inuse += lcn_length;	}	free(rl);	return (0);}static ntfs_attr_search_ctx *attr_get_search_ctx(ntfs_resize_t *resize, ntfs_inode *ni, MFT_RECORD *mrec){	ntfs_attr_search_ctx *ret;	if ((ret = ntfs_attr_get_search_ctx(ni, mrec)) == NULL)		err_printf(resize, "ntfs_attr_get_search_ctx failed");	return ret;}/** * walk_attributes * * For a given MFT Record, iterate through all its attributes.  Any non-resident * data runs will be marked in lcn_bitmap. */static int walk_attributes(ntfs_resize_t *resize, ntfs_volume *vol, ntfsck_t *fsck){	if (!(fsck->ctx = attr_get_search_ctx(resize, fsck->ni, NULL)))		return -1;	while (!ntfs_attrs_walk(fsck->ctx)) {		if (fsck->ctx->attr->type == AT_END)			break;		if (build_lcn_usage_bitmap(resize, vol, fsck) != 0)		  return -1;	}	ntfs_attr_put_search_ctx(fsck->ctx);	return 0;}/** * progress_update * * Update the progress bar and tell the user. */void progress_update(progress *prog, int myPercentIndex, u64 current,		     u64 total){  unsigned finished = 0;  int count;  if (prog && (lockGet(&(prog->lock)) >= 0))    {      for (count = 0; count < myPercentIndex; count ++)	finished += progressPercentages[count];      finished +=	(unsigned) ((current * progressPercentages[myPercentIndex]) / total);      if (finished >= 100)	finished = 99;      prog->finished = finished;      prog->percentFinished = finished;      lockRelease(&(prog->lock));    }}/** * compare_bitmaps * * Compare two bitmaps.  In this case, $Bitmap as read from the disk and * lcn_bitmap which we built from the MFT Records. */static int compare_bitmaps(ntfs_resize_t *resize, ntfs_volume *vol, struct bitmap *a){	s64 i, pos, count;	int mismatch = 0;	int backup_boot = 0;	u8 *bm = NULL;	progress_message(resize, "Accounting clusters");	bm = calloc(NTFS_BUF_SIZE, 1);	if (bm == NULL)	  {	    err_printf(resize, "Not enough memory");	    return (-1);	  }	pos = 0;	while (1) {		count = ntfs_attr_pread(vol->lcnbmp_na, pos, NTFS_BUF_SIZE, bm);		if (count == -1)		  {			err_printf(resize, "Couldn't get $Bitmap $DATA");			free(bm);			return (-1);		  }		if (count == 0) {			if (a->size > pos)			  {				err_printf(resize, "$Bitmap size is smaller than expected"					 " (%lld != %lld)", a->size, pos);				free(bm);				return (-1);			  }			break;		}		for (i = 0; i < count; i++, pos++) {			s64 cl;  /* current cluster */			progress_update(resize->prog, RSZPCNT_ACCOUNTING,					pos, a->size);

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -