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

📄 super.c

📁 linux 内核源代码
💻 C
📖 第 1 页 / 共 5 页
字号:
 * check_windows_hibernation_status - check if Windows is suspended on a volume * @vol:	ntfs super block of device to check * * Check if Windows is hibernated on the ntfs volume @vol.  This is done by * looking for the file hiberfil.sys in the root directory of the volume.  If * the file is not present Windows is definitely not suspended. * * If hiberfil.sys exists and is less than 4kiB in size it means Windows is * definitely suspended (this volume is not the system volume).  Caveat:  on a * system with many volumes it is possible that the < 4kiB check is bogus but * for now this should do fine. * * If hiberfil.sys exists and is larger than 4kiB in size, we need to read the * hiberfil header (which is the first 4kiB).  If this begins with "hibr", * Windows is definitely suspended.  If it is completely full of zeroes, * Windows is definitely not hibernated.  Any other case is treated as if * Windows is suspended.  This caters for the above mentioned caveat of a * system with many volumes where no "hibr" magic would be present and there is * no zero header. * * Return 0 if Windows is not hibernated on the volume, >0 if Windows is * hibernated on the volume, and -errno on error. */static int check_windows_hibernation_status(ntfs_volume *vol){	MFT_REF mref;	struct inode *vi;	ntfs_inode *ni;	struct page *page;	u32 *kaddr, *kend;	ntfs_name *name = NULL;	int ret = 1;	static const ntfschar hiberfil[13] = { const_cpu_to_le16('h'),			const_cpu_to_le16('i'), const_cpu_to_le16('b'),			const_cpu_to_le16('e'), const_cpu_to_le16('r'),			const_cpu_to_le16('f'), const_cpu_to_le16('i'),			const_cpu_to_le16('l'), const_cpu_to_le16('.'),			const_cpu_to_le16('s'), const_cpu_to_le16('y'),			const_cpu_to_le16('s'), 0 };	ntfs_debug("Entering.");	/*	 * Find the inode number for the hibernation file by looking up the	 * filename hiberfil.sys in the root directory.	 */	mutex_lock(&vol->root_ino->i_mutex);	mref = ntfs_lookup_inode_by_name(NTFS_I(vol->root_ino), hiberfil, 12,			&name);	mutex_unlock(&vol->root_ino->i_mutex);	if (IS_ERR_MREF(mref)) {		ret = MREF_ERR(mref);		/* If the file does not exist, Windows is not hibernated. */		if (ret == -ENOENT) {			ntfs_debug("hiberfil.sys not present.  Windows is not "					"hibernated on the volume.");			return 0;		}		/* A real error occured. */		ntfs_error(vol->sb, "Failed to find inode number for "				"hiberfil.sys.");		return ret;	}	/* We do not care for the type of match that was found. */	kfree(name);	/* Get the inode. */	vi = ntfs_iget(vol->sb, MREF(mref));	if (IS_ERR(vi) || is_bad_inode(vi)) {		if (!IS_ERR(vi))			iput(vi);		ntfs_error(vol->sb, "Failed to load hiberfil.sys.");		return IS_ERR(vi) ? PTR_ERR(vi) : -EIO;	}	if (unlikely(i_size_read(vi) < NTFS_HIBERFIL_HEADER_SIZE)) {		ntfs_debug("hiberfil.sys is smaller than 4kiB (0x%llx).  "				"Windows is hibernated on the volume.  This "				"is not the system volume.", i_size_read(vi));		goto iput_out;	}	ni = NTFS_I(vi);	page = ntfs_map_page(vi->i_mapping, 0);	if (IS_ERR(page)) {		ntfs_error(vol->sb, "Failed to read from hiberfil.sys.");		ret = PTR_ERR(page);		goto iput_out;	}	kaddr = (u32*)page_address(page);	if (*(le32*)kaddr == const_cpu_to_le32(0x72626968)/*'hibr'*/) {		ntfs_debug("Magic \"hibr\" found in hiberfil.sys.  Windows is "				"hibernated on the volume.  This is the "				"system volume.");		goto unm_iput_out;	}	kend = kaddr + NTFS_HIBERFIL_HEADER_SIZE/sizeof(*kaddr);	do {		if (unlikely(*kaddr)) {			ntfs_debug("hiberfil.sys is larger than 4kiB "					"(0x%llx), does not contain the "					"\"hibr\" magic, and does not have a "					"zero header.  Windows is hibernated "					"on the volume.  This is not the "					"system volume.", i_size_read(vi));			goto unm_iput_out;		}	} while (++kaddr < kend);	ntfs_debug("hiberfil.sys contains a zero header.  Windows is not "			"hibernated on the volume.  This is the system "			"volume.");	ret = 0;unm_iput_out:	ntfs_unmap_page(page);iput_out:	iput(vi);	return ret;}/** * load_and_init_quota - load and setup the quota file for a volume if present * @vol:	ntfs super block describing device whose quota file to load * * Return 'true' on success or 'false' on error.  If $Quota is not present, we * leave vol->quota_ino as NULL and return success. */static bool load_and_init_quota(ntfs_volume *vol){	MFT_REF mref;	struct inode *tmp_ino;	ntfs_name *name = NULL;	static const ntfschar Quota[7] = { const_cpu_to_le16('$'),			const_cpu_to_le16('Q'), const_cpu_to_le16('u'),			const_cpu_to_le16('o'), const_cpu_to_le16('t'),			const_cpu_to_le16('a'), 0 };	static ntfschar Q[3] = { const_cpu_to_le16('$'),			const_cpu_to_le16('Q'), 0 };	ntfs_debug("Entering.");	/*	 * Find the inode number for the quota file by looking up the filename	 * $Quota in the extended system files directory $Extend.	 */	mutex_lock(&vol->extend_ino->i_mutex);	mref = ntfs_lookup_inode_by_name(NTFS_I(vol->extend_ino), Quota, 6,			&name);	mutex_unlock(&vol->extend_ino->i_mutex);	if (IS_ERR_MREF(mref)) {		/*		 * If the file does not exist, quotas are disabled and have		 * never been enabled on this volume, just return success.		 */		if (MREF_ERR(mref) == -ENOENT) {			ntfs_debug("$Quota not present.  Volume does not have "					"quotas enabled.");			/*			 * No need to try to set quotas out of date if they are			 * not enabled.			 */			NVolSetQuotaOutOfDate(vol);			return true;		}		/* A real error occured. */		ntfs_error(vol->sb, "Failed to find inode number for $Quota.");		return false;	}	/* We do not care for the type of match that was found. */	kfree(name);	/* Get the inode. */	tmp_ino = ntfs_iget(vol->sb, MREF(mref));	if (IS_ERR(tmp_ino) || is_bad_inode(tmp_ino)) {		if (!IS_ERR(tmp_ino))			iput(tmp_ino);		ntfs_error(vol->sb, "Failed to load $Quota.");		return false;	}	vol->quota_ino = tmp_ino;	/* Get the $Q index allocation attribute. */	tmp_ino = ntfs_index_iget(vol->quota_ino, Q, 2);	if (IS_ERR(tmp_ino)) {		ntfs_error(vol->sb, "Failed to load $Quota/$Q index.");		return false;	}	vol->quota_q_ino = tmp_ino;	ntfs_debug("Done.");	return true;}/** * load_and_init_usnjrnl - load and setup the transaction log if present * @vol:	ntfs super block describing device whose usnjrnl file to load * * Return 'true' on success or 'false' on error. * * If $UsnJrnl is not present or in the process of being disabled, we set * NVolUsnJrnlStamped() and return success. * * If the $UsnJrnl $DATA/$J attribute has a size equal to the lowest valid usn, * i.e. transaction logging has only just been enabled or the journal has been * stamped and nothing has been logged since, we also set NVolUsnJrnlStamped() * and return success. */static bool load_and_init_usnjrnl(ntfs_volume *vol){	MFT_REF mref;	struct inode *tmp_ino;	ntfs_inode *tmp_ni;	struct page *page;	ntfs_name *name = NULL;	USN_HEADER *uh;	static const ntfschar UsnJrnl[9] = { const_cpu_to_le16('$'),			const_cpu_to_le16('U'), const_cpu_to_le16('s'),			const_cpu_to_le16('n'), const_cpu_to_le16('J'),			const_cpu_to_le16('r'), const_cpu_to_le16('n'),			const_cpu_to_le16('l'), 0 };	static ntfschar Max[5] = { const_cpu_to_le16('$'),			const_cpu_to_le16('M'), const_cpu_to_le16('a'),			const_cpu_to_le16('x'), 0 };	static ntfschar J[3] = { const_cpu_to_le16('$'),			const_cpu_to_le16('J'), 0 };	ntfs_debug("Entering.");	/*	 * Find the inode number for the transaction log file by looking up the	 * filename $UsnJrnl in the extended system files directory $Extend.	 */	mutex_lock(&vol->extend_ino->i_mutex);	mref = ntfs_lookup_inode_by_name(NTFS_I(vol->extend_ino), UsnJrnl, 8,			&name);	mutex_unlock(&vol->extend_ino->i_mutex);	if (IS_ERR_MREF(mref)) {		/*		 * If the file does not exist, transaction logging is disabled,		 * just return success.		 */		if (MREF_ERR(mref) == -ENOENT) {			ntfs_debug("$UsnJrnl not present.  Volume does not "					"have transaction logging enabled.");not_enabled:			/*			 * No need to try to stamp the transaction log if			 * transaction logging is not enabled.			 */			NVolSetUsnJrnlStamped(vol);			return true;		}		/* A real error occured. */		ntfs_error(vol->sb, "Failed to find inode number for "				"$UsnJrnl.");		return false;	}	/* We do not care for the type of match that was found. */	kfree(name);	/* Get the inode. */	tmp_ino = ntfs_iget(vol->sb, MREF(mref));	if (unlikely(IS_ERR(tmp_ino) || is_bad_inode(tmp_ino))) {		if (!IS_ERR(tmp_ino))			iput(tmp_ino);		ntfs_error(vol->sb, "Failed to load $UsnJrnl.");		return false;	}	vol->usnjrnl_ino = tmp_ino;	/*	 * If the transaction log is in the process of being deleted, we can	 * ignore it.	 */	if (unlikely(vol->vol_flags & VOLUME_DELETE_USN_UNDERWAY)) {		ntfs_debug("$UsnJrnl in the process of being disabled.  "				"Volume does not have transaction logging "				"enabled.");		goto not_enabled;	}	/* Get the $DATA/$Max attribute. */	tmp_ino = ntfs_attr_iget(vol->usnjrnl_ino, AT_DATA, Max, 4);	if (IS_ERR(tmp_ino)) {		ntfs_error(vol->sb, "Failed to load $UsnJrnl/$DATA/$Max "				"attribute.");		return false;	}	vol->usnjrnl_max_ino = tmp_ino;	if (unlikely(i_size_read(tmp_ino) < sizeof(USN_HEADER))) {		ntfs_error(vol->sb, "Found corrupt $UsnJrnl/$DATA/$Max "				"attribute (size is 0x%llx but should be at "				"least 0x%zx bytes).", i_size_read(tmp_ino),				sizeof(USN_HEADER));		return false;	}	/* Get the $DATA/$J attribute. */	tmp_ino = ntfs_attr_iget(vol->usnjrnl_ino, AT_DATA, J, 2);	if (IS_ERR(tmp_ino)) {		ntfs_error(vol->sb, "Failed to load $UsnJrnl/$DATA/$J "				"attribute.");		return false;	}	vol->usnjrnl_j_ino = tmp_ino;	/* Verify $J is non-resident and sparse. */	tmp_ni = NTFS_I(vol->usnjrnl_j_ino);	if (unlikely(!NInoNonResident(tmp_ni) || !NInoSparse(tmp_ni))) {		ntfs_error(vol->sb, "$UsnJrnl/$DATA/$J attribute is resident "				"and/or not sparse.");		return false;	}	/* Read the USN_HEADER from $DATA/$Max. */	page = ntfs_map_page(vol->usnjrnl_max_ino->i_mapping, 0);	if (IS_ERR(page)) {		ntfs_error(vol->sb, "Failed to read from $UsnJrnl/$DATA/$Max "				"attribute.");		return false;	}	uh = (USN_HEADER*)page_address(page);	/* Sanity check the $Max. */	if (unlikely(sle64_to_cpu(uh->allocation_delta) >			sle64_to_cpu(uh->maximum_size))) {		ntfs_error(vol->sb, "Allocation delta (0x%llx) exceeds "				"maximum size (0x%llx).  $UsnJrnl is corrupt.",				(long long)sle64_to_cpu(uh->allocation_delta),				(long long)sle64_to_cpu(uh->maximum_size));		ntfs_unmap_page(page);		return false;	}	/*	 * If the transaction log has been stamped and nothing has been written	 * to it since, we do not need to stamp it.	 */	if (unlikely(sle64_to_cpu(uh->lowest_valid_usn) >=			i_size_read(vol->usnjrnl_j_ino))) {		if (likely(sle64_to_cpu(uh->lowest_valid_usn) ==				i_size_read(vol->usnjrnl_j_ino))) {			ntfs_unmap_page(page);			ntfs_debug("$UsnJrnl is enabled but nothing has been "					"logged since it was last stamped.  "					"Treating this as if the volume does "					"not have transaction logging "					"enabled.");			goto not_enabled;		}		ntfs_error(vol->sb, "$UsnJrnl has lowest valid usn (0x%llx) "				"which is out of bounds (0x%llx).  $UsnJrnl "				"is corrupt.",				(long long)sle64_to_cpu(uh->lowest_valid_usn),				i_size_read(vol->usnjrnl_j_ino));		ntfs_unmap_page(page);		return false;	}	ntfs_unmap_page(page);	ntfs_debug("Done.");	return true;}/** * load_and_init_attrdef - load the attribute definitions table for a volume * @vol:	ntfs super block describing device whose attrdef to load * * Return 'true' on success or 'false' on error. */static bool load_and_init_attrdef(ntfs_volume *vol){	loff_t i_size;	struct super_block *sb = vol->sb;	struct inode *ino;	struct page *page;	pgoff_t index, max_index;	unsigned int size;	ntfs_debug("Entering.");	/* Read attrdef table and setup vol->attrdef and vol->attrdef_size. */	ino = ntfs_iget(sb, FILE_AttrDef);	if (IS_ERR(ino) || is_bad_inode(ino)) {		if (!IS_ERR(ino))			iput(ino);		goto failed;	}	NInoSetSparseDisabled(NTFS_I(ino));	/* The size of FILE_AttrDef must be above 0 and fit inside 31 bits. */	i_size = i_size_read(ino);	if (i_size <= 0 || i_size > 0x7fffffff)		goto iput_failed;	vol->attrdef = (ATTR_DEF*)ntfs_malloc_nofs(i_size);	if (!vol->attrdef)		goto iput_failed;	index = 0;	max_index = i_size >> PAGE_CACHE_SHIFT;	size = PAGE_CACHE_SIZE;	while (index < max_index) {		/* Read the attrdef table and copy it into the linear buffer. */read_partial_attrdef_page:		page = ntfs_map_page(ino->i_mapping, index);		if (IS_ERR(page))			goto free_iput_failed;		memcpy((u8*)vol->attrdef + (index++ << PAGE_CACHE_SHIFT),				page_address(page), size);		ntfs_unmap_page(page);	};	if (size == PAGE_CACHE_SIZE) {		size = i_size & ~PAGE_CACHE_MASK;		if (size)			goto read_partial_attrdef_page;	}	vol->attrdef_size = i_size;	ntfs_debug("Read %llu bytes from $AttrDef.", i_size);	iput(ino);	return true;free_iput_failed:	ntfs_free(vol->attrdef);	vol->attrdef = NULL;iput_failed:	iput(ino);failed:

⌨️ 快捷键说明

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