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

📄 volume.c

📁 添加linux下对NTFS格式文件系统访问支持的源代码ntfs-3g
💻 C
📖 第 1 页 / 共 3 页
字号:
	 * Set the current position within each data zone to the start of the	 * respective zone.	 */	vol->data1_zone_pos = vol->mft_zone_end;	ntfs_log_debug("data1_zone_pos = 0x%llx\n", vol->data1_zone_pos);	vol->data2_zone_pos = 0;	ntfs_log_debug("data2_zone_pos = 0x%llx\n", vol->data2_zone_pos);	/* Set the mft data allocation position to mft record 24. */	vol->mft_data_pos = 24;	/*	 * The cluster allocator is now fully operational.	 */	/* Need to setup $MFT so we can use the library read functions. */	ntfs_log_debug("Loading $MFT... ");	if (ntfs_mft_load(vol) < 0) {		ntfs_log_debug(FAILED);		ntfs_log_perror("Failed to load $MFT");		goto error_exit;	}	ntfs_log_debug(OK);	/* Need to setup $MFTMirr so we can use the write functions, too. */	ntfs_log_debug("Loading $MFTMirr... ");	if (ntfs_mftmirr_load(vol) < 0) {		ntfs_log_debug(FAILED);		ntfs_log_perror("Failed to load $MFTMirr");		goto error_exit;	}	ntfs_log_debug(OK);	return vol;error_exit:	eo = errno;	free(bs);	if (vol)		__ntfs_volume_release(vol);	errno = eo;	return NULL;}/** * ntfs_volume_check_logfile - check logfile on target volume * @vol:	volume on which to check logfile * * Return 0 on success and -1 on error with errno set error code. */static int ntfs_volume_check_logfile(ntfs_volume *vol){	ntfs_inode *ni;	ntfs_attr *na = NULL;	RESTART_PAGE_HEADER *rp = NULL;	int err = 0;	if ((ni = ntfs_inode_open(vol, FILE_LogFile)) == NULL) {		ntfs_log_perror("Failed to open inode FILE_LogFile");		errno = EIO;		return -1;	}	if ((na = ntfs_attr_open(ni, AT_DATA, AT_UNNAMED, 0)) == NULL) {		ntfs_log_perror("Failed to open $FILE_LogFile/$DATA");		err = EIO;		goto exit;	}	if (!ntfs_check_logfile(na, &rp) || !ntfs_is_logfile_clean(na, rp))		err = EOPNOTSUPP;	free(rp);exit:	if (na)		ntfs_attr_close(na);	ntfs_inode_close(ni);	if (err) {		errno = err;		return -1;	}	return 0;}/** * ntfs_hiberfile_open - Find and open '/hiberfil.sys' * @vol:    An ntfs volume obtained from ntfs_mount * * Return:  inode  Success, hiberfil.sys is valid *	    NULL   hiberfil.sys doesn't exist or some other error occurred */static ntfs_inode *ntfs_hiberfile_open(ntfs_volume *vol){	u64 inode;	ntfs_inode *ni_root;	ntfs_inode *ni_hibr = NULL;	ntfschar   *unicode = NULL;	int unicode_len;	const char *hiberfile = "hiberfil.sys";	if (!vol) {		errno = EINVAL;		return NULL;	}	ni_root = ntfs_inode_open(vol, FILE_root);	if (!ni_root) {		ntfs_log_debug("Couldn't open the root directory.\n");		return NULL;	}	unicode_len = ntfs_mbstoucs(hiberfile, &unicode, 0);	if (unicode_len < 0) {		ntfs_log_perror("Couldn't convert 'hiberfil.sys' to Unicode");		goto out;	}	inode = ntfs_inode_lookup_by_name(ni_root, unicode, unicode_len);	if (inode == (u64)-1) {		ntfs_log_debug("Couldn't find file '%s'.\n", hiberfile);		goto out;	}	inode = MREF(inode);	ni_hibr = ntfs_inode_open(vol, inode);	if (!ni_hibr) {		ntfs_log_debug("Couldn't open inode %lld.\n", (long long)inode);		goto out;	}out:	ntfs_inode_close(ni_root);	free(unicode);	return ni_hibr;}#define NTFS_HIBERFILE_HEADER_SIZE	4096/** * ntfs_volume_check_hiberfile - check hiberfil.sys whether Windows is *                               hibernated on the target volume * @vol:    volume on which to check hiberfil.sys * * Return:  0 if Windows isn't hibernated for sure *         -1 otherwise and errno is set to the appropriate value */static int ntfs_volume_check_hiberfile(ntfs_volume *vol){	ntfs_inode *ni;	ntfs_attr *na = NULL;	int i, bytes_read, ret = -1;	char *buf = NULL;	ni = ntfs_hiberfile_open(vol);	if (!ni) {		if (errno == ENOENT)			return 0;		return -1;	}	buf = ntfs_malloc(NTFS_HIBERFILE_HEADER_SIZE);	if (!buf)		goto out;	na = ntfs_attr_open(ni, AT_DATA, AT_UNNAMED, 0);	if (!na) {		ntfs_log_perror("Failed to open hiberfil.sys data attribute");		goto out;	}	bytes_read = ntfs_attr_pread(na, 0, NTFS_HIBERFILE_HEADER_SIZE, buf);	if (bytes_read == -1) {		ntfs_log_perror("Failed to read hiberfil.sys");		goto out;	}	if (bytes_read < NTFS_HIBERFILE_HEADER_SIZE) {		ntfs_log_error("Hibernated non-system partition, refused to "			       "mount.\n");		errno = EPERM;		goto out;	}	if (memcmp(buf, "hibr", 4) == 0) {		ntfs_log_error("Windows is hibernated, refused to mount.\n");		errno = EPERM;		goto out;	}	for (i = 0; i < NTFS_HIBERFILE_HEADER_SIZE; i++) {		if (buf[i]) {			ntfs_log_error("Windows is hibernated, won't mount.\n");			errno = EPERM;			goto out;		}	}        /* All right, all header bytes are zero */	ret = 0;out:	if (na)		ntfs_attr_close(na);	free(buf);	ntfs_inode_close(ni);	return ret;}/** * ntfs_device_mount - open ntfs volume * @dev:	device to open * @flags:	optional mount flags * * This function mounts an ntfs volume. @dev should describe the device which * to mount as the ntfs volume. * * @flags is an optional second parameter. The same flags are used as for * the mount system call (man 2 mount). Currently only the following flags * are implemented: *	MS_RDONLY	- mount volume read-only *	MS_NOATIME	- do not update access time * * The function opens the device @dev and verifies that it contains a valid * bootsector. Then, it allocates an ntfs_volume structure and initializes * some of the values inside the structure from the information stored in the * bootsector. It proceeds to load the necessary system files and completes * setting up the structure. * * Return the allocated volume structure on success and NULL on error with * errno set to the error code. */ntfs_volume *ntfs_device_mount(struct ntfs_device *dev, unsigned long flags){	s64 l;#ifdef DEBUG	const char *OK = "OK\n";	const char *FAILED = "FAILED\n";#endif		ntfs_volume *vol;	u8 *m = NULL, *m2 = NULL;	ntfs_attr_search_ctx *ctx = NULL;	ntfs_inode *ni;	ntfs_attr *na;	ATTR_RECORD *a;	VOLUME_INFORMATION *vinf;	ntfschar *vname;	int i, j, eo;	u32 u;	vol = ntfs_volume_startup(dev, flags);	if (!vol) {		ntfs_log_perror("Failed to startup volume");		return NULL;	}	/* Load data from $MFT and $MFTMirr and compare the contents. */	m  = ntfs_malloc(vol->mftmirr_size << vol->mft_record_size_bits);	m2 = ntfs_malloc(vol->mftmirr_size << vol->mft_record_size_bits);	if (!m || !m2)		goto error_exit;	l = ntfs_attr_mst_pread(vol->mft_na, 0, vol->mftmirr_size,			vol->mft_record_size, m);	if (l != vol->mftmirr_size) {		if (l == -1)			ntfs_log_perror("Failed to read $MFT");		else {			ntfs_log_error("Failed to read $MFT, unexpected length "				       "(%lld != %d).\n", (long long)l,				       vol->mftmirr_size);			errno = EIO;		}		goto error_exit;	}	l = ntfs_attr_mst_pread(vol->mftmirr_na, 0, vol->mftmirr_size,			vol->mft_record_size, m2);	if (l != vol->mftmirr_size) {		if (l == 4)			vol->mftmirr_size = 4;		else {			if (l == -1)				ntfs_log_perror("Failed to read $MFTMirr");			else {				ntfs_log_error("Failed to read $MFTMirr "					       "unexpected length (%d != %lld)."					       "\n", vol->mftmirr_size,					       (long long)l);				errno = EIO;			}			goto error_exit;		}	}	ntfs_log_debug("Comparing $MFTMirr to $MFT... ");	for (i = 0; i < vol->mftmirr_size; ++i) {		MFT_RECORD *mrec, *mrec2;		const char *ESTR[12] = { "$MFT", "$MFTMirr", "$LogFile",			"$Volume", "$AttrDef", "root directory", "$Bitmap",			"$Boot", "$BadClus", "$Secure", "$UpCase", "$Extend" };		const char *s;		if (i < 12)			s = ESTR[i];		else if (i < 16)			s = "system file";		else			s = "mft record";		mrec = (MFT_RECORD*)(m + i * vol->mft_record_size);		if (mrec->flags & MFT_RECORD_IN_USE) {			if (ntfs_is_baad_recordp(mrec)) {				ntfs_log_debug("FAILED\n");				ntfs_log_error("$MFT error: Incomplete multi "					       "sector transfer detected in "					       "'%s'.\n", s);				goto io_error_exit;			}			if (!ntfs_is_mft_recordp(mrec)) {				ntfs_log_debug("FAILED\n");				ntfs_log_error("$MFT error: Invalid mft "						"record for '%s'.\n", s);				goto io_error_exit;			}		}		mrec2 = (MFT_RECORD*)(m2 + i * vol->mft_record_size);		if (mrec2->flags & MFT_RECORD_IN_USE) {			if (ntfs_is_baad_recordp(mrec2)) {				ntfs_log_debug("FAILED\n");				ntfs_log_error("$MFTMirr error: Incomplete "						"multi sector transfer "						"detected in '%s'.\n", s);				goto io_error_exit;			}			if (!ntfs_is_mft_recordp(mrec2)) {				ntfs_log_debug("FAILED\n");				ntfs_log_error("$MFTMirr error: Invalid mft "						"record for '%s'.\n", s);				goto io_error_exit;			}		}		if (memcmp(mrec, mrec2, ntfs_mft_record_get_data_size(mrec))) {			ntfs_log_debug(FAILED);			ntfs_log_error("$MFTMirr does not match $MFT (record "				       "%d).\n", i);			goto io_error_exit;		}	}	ntfs_log_debug(OK);	free(m2);	free(m);	m = m2 = NULL;	/* Now load the bitmap from $Bitmap. */	ntfs_log_debug("Loading $Bitmap... ");	vol->lcnbmp_ni = ntfs_inode_open(vol, FILE_Bitmap);	if (!vol->lcnbmp_ni) {		ntfs_log_debug(FAILED);		ntfs_log_perror("Failed to open inode");		goto error_exit;	}	/* Get an ntfs attribute for $Bitmap/$DATA. */	vol->lcnbmp_na = ntfs_attr_open(vol->lcnbmp_ni, AT_DATA, AT_UNNAMED, 0);	if (!vol->lcnbmp_na) {		ntfs_log_debug(FAILED);		ntfs_log_perror("Failed to open ntfs attribute");		goto error_exit;	}	/* Done with the $Bitmap mft record. */	ntfs_log_debug(OK);	/* Now load the upcase table from $UpCase. */	ntfs_log_debug("Loading $UpCase... ");	ni = ntfs_inode_open(vol, FILE_UpCase);	if (!ni) {		ntfs_log_debug(FAILED);		ntfs_log_perror("Failed to open inode");		goto error_exit;	}	/* Get an ntfs attribute for $UpCase/$DATA. */	na = ntfs_attr_open(ni, AT_DATA, AT_UNNAMED, 0);	if (!na) {		ntfs_log_debug(FAILED);		ntfs_log_perror("Failed to open ntfs attribute");		goto error_exit;	}	/*	 * Note: Normally, the upcase table has a length equal to 65536	 * 2-byte Unicode characters but allow for different cases, so no	 * checks done. Just check we don't overflow 32-bits worth of Unicode	 * characters.	 */	if (na->data_size & ~0x1ffffffffULL) {		ntfs_log_debug(FAILED);		ntfs_log_error("Error: Upcase table is too big (max 32-bit "				"allowed).\n");		errno = EINVAL;		goto error_exit;	}	if (vol->upcase_len != na->data_size >> 1) {		vol->upcase_len = na->data_size >> 1;		/* Throw away default table. */		free(vol->upcase);		vol->upcase = ntfs_malloc(na->data_size);		if (!vol->upcase) {			ntfs_log_debug(FAILED);			goto error_exit;		}	}	/* Read in the $DATA attribute value into the buffer. */	l = ntfs_attr_pread(na, 0, na->data_size, vol->upcase);	if (l != na->data_size) {		ntfs_log_debug(FAILED);		ntfs_log_error("Failed to read $UpCase, unexpected length "			       "(%lld != %lld).\n", (long long)l,			       (long long)na->data_size);		errno = EIO;		goto error_exit;	}	/* Done with the $UpCase mft record. */	ntfs_log_debug(OK);	ntfs_attr_close(na);	if (ntfs_inode_close(ni))		ntfs_log_perror("Failed to close inode, leaking memory");	/*	 * Now load $Volume and set the version information and flags in the	 * vol structure accordingly.	 */	ntfs_log_debug("Loading $Volume... ");	vol->vol_ni = ntfs_inode_open(vol, FILE_Volume);	if (!vol->vol_ni) {		ntfs_log_debug(FAILED);		ntfs_log_perror("Failed to open inode");		goto error_exit;	}	/* Get a search context for the $Volume/$VOLUME_INFORMATION lookup. */	ctx = ntfs_attr_get_search_ctx(vol->vol_ni, NULL);	if (!ctx) {		ntfs_log_debug(FAILED);		ntfs_log_perror("Failed to allocate attribute search context");		goto error_exit;	}	/* Find the $VOLUME_INFORMATION attribute. */	if (ntfs_attr_lookup(AT_VOLUME_INFORMATION, AT_UNNAMED, 0, 0, 0, NULL,			0, ctx)) {		ntfs_log_debug(FAILED);		ntfs_log_perror("$VOLUME_INFORMATION attribute not found in "				"$Volume");		goto error_exit;	}	a = ctx->attr;	/* Has to be resident. */	if (a->non_resident) {		ntfs_log_debug(FAILED);		ntfs_log_error("Attribute $VOLUME_INFORMATION must be "			       "resident but it isn't.\n");		errno = EIO;		goto error_exit;	}	/* Get a pointer to the value of the attribute. */	vinf = (VOLUME_INFORMATION*)(le16_to_cpu(a->value_offset) + (char*)a);	/* Sanity checks. */	if ((char*)vinf + le32_to_cpu(a->value_length) > (char*)ctx->mrec +			le32_to_cpu(ctx->mrec->bytes_in_use) ||			le16_to_cpu(a->value_offset) + le32_to_cpu(			a->value_length) > le32_to_cpu(a->length)) {		ntfs_log_debug(FAILED);		ntfs_log_error("$VOLUME_INFORMATION in $Volume is corrupt.\n");		errno = EIO;		goto error_exit;	}	/* Setup vol from the volume information attribute value. */	vol->major_ver = vinf->major_ver;	vol->minor_ver = vinf->minor_ver;	/* Do not use le16_to_cpu() macro here as our VOLUME_FLAGS are	   defined using cpu_to_le16() macro and hence are consistent. */	vol->flags = vinf->flags;	/*	 * Reinitialize the search context for the $Volume/$VOLUME_NAME lookup.	 */	ntfs_attr_reinit_search_ctx(ctx);	if (ntfs_attr_lookup(AT_VOLUME_NAME, AT_UNNAMED, 0, 0, 0, NULL, 0,			ctx)) {		if (errno != ENOENT) {			ntfs_log_debug(FAILED);			ntfs_log_perror("Failed to lookup of $VOLUME_NAME in "					"$Volume failed");			goto error_exit;		}		/*		 * Attribute not present.  This has been seen in the field.		 * Treat this the same way as if the attribute was present but		 * had zero length.		 */		vol->vol_name = ntfs_malloc(1);		if (!vol->vol_name) {			ntfs_log_debug(FAILED);			goto error_exit;		}		vol->vol_name[0] = '\0';	} else {		a = ctx->attr;		/* Has to be resident. */		if (a->non_resident) {			ntfs_log_debug(FAILED);			ntfs_log_error("$VOLUME_NAME must be resident.\n");			errno = EIO;			goto error_exit;		}

⌨️ 快捷键说明

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