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

📄 volume.c

📁 上一个上传的有问题,这个是好的。visopsys包括系统内核和GUI的全部SOURCE code ,还包括一些基本的docs文档。里面src子目录对应所有SOURCE code.对于想研究操作系统的朋
💻 C
📖 第 1 页 / 共 4 页
字号:
	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_debug("$VOLUME_INFORMATION attribute not found in "				"$Volume?!?\n");		goto error_exit;	}	a = ctx->attr;	/* Has to be resident. */	if (a->non_resident) {		ntfs_log_debug(FAILED);		ntfs_log_debug("Error: Attribute $VOLUME_INFORMATION must be "				"resident (and 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_debug("Error: Attribute $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_debug("Error: Lookup of $VOLUME_NAME attribute in "					"$Volume failed.  This probably means "					"something is corrupt.  Run chkdsk.\n");			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 = malloc(1);		if (!vol->vol_name) {			ntfs_log_debug(FAILED);			ntfs_log_debug("Error: Unable to allocate memory for volume "					"name!\n");			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_debug("Error: Attribute $VOLUME_NAME must be "					"resident!\n");			errno = EIO;			goto error_exit;		}		/* Get a pointer to the value of the attribute. */		vname = (ntfschar*)(le16_to_cpu(a->value_offset) + (char*)a);		u = le32_to_cpu(a->value_length) / 2;		/*		 * Convert Unicode volume name to current locale multibyte		 * format.		 */		vol->vol_name = NULL;		if (ntfs_ucstombs(vname, u, &vol->vol_name, 0) == -1) {			ntfs_log_perror("Error: Volume name could not be converted "					"to current locale");			ntfs_log_debug("Forcing name into ASCII by replacing "				"non-ASCII characters with underscores.\n");			vol->vol_name = malloc(u + 1);			if (!vol->vol_name) {				ntfs_log_debug(FAILED);				ntfs_log_debug("Error: Unable to allocate memory for "						"volume name!\n");				goto error_exit;			}			for (j = 0; j < (s32)u; j++) {				ntfschar uc = le16_to_cpu(vname[j]);				if (uc > 0xff)					uc = (ntfschar)'_';				vol->vol_name[j] = (char)uc;			}			vol->vol_name[u] = '\0';		}	}	ntfs_log_debug(OK);	ntfs_attr_put_search_ctx(ctx);	ctx = NULL;	/* Now load the attribute definitions from $AttrDef. */	ntfs_log_debug("Loading $AttrDef... ");	ni = ntfs_inode_open(vol, FILE_AttrDef);	if (!ni) {		ntfs_log_debug(FAILED);		ntfs_log_perror("Failed to open inode");		goto error_exit;	}	/* Get an ntfs attribute for $AttrDef/$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;	}	/* Check we don't overflow 32-bits. */	if (na->data_size > 0xffffffffLL) {		ntfs_log_debug(FAILED);		ntfs_log_debug("Error: Attribute definition table is too big (max "				"32-bit allowed).\n");		errno = EINVAL;		goto error_exit;	}	vol->attrdef_len = na->data_size;	vol->attrdef = (ATTR_DEF*)malloc(na->data_size);	if (!vol->attrdef) {		ntfs_log_debug(FAILED);		ntfs_log_debug("Not enough memory to load $AttrDef.\n");		goto error_exit;	}	/* Read in the $DATA attribute value into the buffer. */	l = ntfs_attr_pread(na, 0, na->data_size, vol->attrdef);	if (l != na->data_size) {		ntfs_log_debug(FAILED);		ntfs_log_debug("Amount of data read does not correspond to expected "				"length!\n");		errno = EIO;		goto error_exit;	}	/* Done with the $AttrDef mft record. */	ntfs_log_debug(OK);	ntfs_attr_close(na);	if (ntfs_inode_close(ni))		ntfs_log_perror("Failed to close inode, leaking memory");	/*	 * Check for dirty logfile and hibernated Windows.	 * We care only about read-write mounts.	 */	if (!(flags & MS_RDONLY)) {		if (ntfs_volume_check_logfile(vol) < 0)			goto error_exit;		if (ntfs_volume_check_hiberfile(vol) < 0)			goto error_exit;	}	return vol;io_error_exit:	errno = EIO;error_exit:	eo = errno;	if (ctx)		ntfs_attr_put_search_ctx(ctx);	if (m)		free(m);	if (m2)		free(m2);	__ntfs_volume_release(vol);	errno = eo;	return NULL;}/** * ntfs_mount - open ntfs volume * @name:	name of device/file to open * @flags:	optional mount flags * * This function mounts an ntfs volume. @name should contain the name of the * device/file 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 or file @name 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. * * Note, that a copy is made of @name, and hence it can be discarded as * soon as the function returns. */ntfs_volume *ntfs_mount(const char *name __attribute__((unused)),		unsigned long flags __attribute__((unused))){#ifndef NO_NTFS_DEVICE_DEFAULT_IO_OPS	struct ntfs_device *dev;	ntfs_volume *vol;	/* Allocate an ntfs_device structure. */	dev = ntfs_device_alloc(name, 0, &ntfs_device_default_io_ops, NULL);	if (!dev)		return NULL;	/* Call ntfs_device_mount() to do the actual mount. */	vol = ntfs_device_mount(dev, flags);	if (!vol) {		int eo = errno;		ntfs_device_free(dev);		errno = eo;	}	return vol;#else	/*	 * ntfs_mount() makes no sense if NO_NTFS_DEVICE_DEFAULT_IO_OPS is	 * defined as there are no device operations available in libntfs in	 * this case.	 */	errno = EOPNOTSUPP;	return NULL;#endif}#ifndef __VISOPSYS__/** * ntfs_device_umount - close ntfs volume * @vol: address of ntfs_volume structure of volume to close * @force: if true force close the volume even if it is busy * * Deallocate all structures (including @vol itself) associated with the ntfs * volume @vol. * * Note it is up to the caller to destroy the device associated with the volume * being unmounted after this function returns. * * Return 0 on success. On error return -1 with errno set appropriately * (most likely to one of EAGAIN, EBUSY or EINVAL). The EAGAIN error means that * an operation is in progress and if you try the close later the operation * might be completed and the close succeed. * * If @force is true (i.e. not zero) this function will close the volume even * if this means that data might be lost. * * @vol must have previously been returned by a call to ntfs_device_mount(). * * @vol itself is deallocated and should no longer be dereferenced after this * function returns success. If it returns an error then nothing has been done * so it is safe to continue using @vol. */int ntfs_device_umount(ntfs_volume *vol,		const BOOL force __attribute__((unused))){	if (!vol) {		errno = EINVAL;		return -1;	}	__ntfs_volume_release(vol);	return 0;}/** * ntfs_umount - close ntfs volume * @vol: address of ntfs_volume structure of volume to close * @force: if true force close the volume even if it is busy * * Deallocate all structures (including @vol itself) associated with the ntfs * volume @vol. * * Return 0 on success. On error return -1 with errno set appropriately * (most likely to one of EAGAIN, EBUSY or EINVAL). The EAGAIN error means that * an operation is in progress and if you try the close later the operation * might be completed and the close succeed. * * If @force is true (i.e. not zero) this function will close the volume even * if this means that data might be lost. * * @vol must have previously been returned by a call to ntfs_mount(). * * @vol itself is deallocated and should no longer be dereferenced after this * function returns success. If it returns an error then nothing has been done * so it is safe to continue using @vol. */int ntfs_umount(ntfs_volume *vol,		const BOOL force __attribute__((unused))){	struct ntfs_device *dev;	if (!vol) {		errno = EINVAL;		return -1;	}	dev = vol->dev;	__ntfs_volume_release(vol);	ntfs_device_free(dev);	return 0;}#ifdef HAVE_MNTENT_H#ifndef HAVE_REALPATH/** * realpath - If there is no realpath on the system */static char *realpath(const char *path, char *resolved_path){	strncpy(resolved_path, path, PATH_MAX);	resolved_path[PATH_MAX] = '\0';	return resolved_path;}#endif/** * ntfs_mntent_check - desc * * If you are wanting to use this, you actually wanted to use * ntfs_check_if_mounted(), you just didn't realize. (-: * * See description of ntfs_check_if_mounted(), below. */static int ntfs_mntent_check(const char *file, unsigned long *mnt_flags){	struct mntent *mnt;	char *real_file = NULL, *real_fsname = NULL;	FILE *f;	int err = 0;	real_file = malloc(PATH_MAX + 1);	if (!real_file)		return -1;	real_fsname = malloc(PATH_MAX + 1);	if (!real_fsname) {		err = errno;		goto exit;	}	if (!realpath(file, real_file)) {		err = errno;		goto exit;	}	if (!(f = setmntent(MOUNTED, "r"))) {		err = errno;		goto exit;	}	while ((mnt = getmntent(f))) {		if (!realpath(mnt->mnt_fsname, real_fsname))			continue;		if (!strcmp(real_file, real_fsname))			break;	}	endmntent(f);	if (!mnt)		goto exit;	*mnt_flags = NTFS_MF_MOUNTED;	if (!strcmp(mnt->mnt_dir, "/"))		*mnt_flags |= NTFS_MF_ISROOT;#ifdef HAVE_HASMNTOPT	if (hasmntopt(mnt, "ro") && !hasmntopt(mnt, "rw"))		*mnt_flags |= NTFS_MF_READONLY;#endifexit:	free(real_file);	free(real_fsname);	if (err) {		errno = err;		return -1;	}	return 0;}#endif /* HAVE_MNTENT_H */#endif /* __VISOPSYS__ *//** * ntfs_check_if_mounted - check if an ntfs volume is currently mounted * @file:	device file to check * @mnt_flags:	pointer into which to return the ntfs mount flags (see volume.h) * * If the running system does not support the {set,get,end}mntent() calls, * just return 0 and set *@mnt_flags to zero. * * When the system does support the calls, ntfs_check_if_mounted() first tries * to find the device @file in /etc/mtab (or wherever this is kept on the * running system). If it is not found, assume the device is not mounted and * return 0 and set *@mnt_flags to zero. * * If the device @file is found, set the NTFS_MF_MOUNTED flags in *@mnt_flags. * * Further if @file is mounted as the file system root ("/"), set the flag * NTFS_MF_ISROOT in *@mnt_flags. * * Finally, check if the file system is mounted read-only, and if so set the * NTFS_MF_READONLY flag in *@mnt_flags. * * On success return 0 with *@mnt_flags set to the ntfs mount flags. * * On error return -1 with errno set to the error code. */int ntfs_check_if_mounted(const char *filenm __attribute__((unused)),		unsigned long *mnt_flags){	*mnt_flags = 0;#ifdef HAVE_MNTENT_H	return ntfs_mntent_check(filenm, mnt_flags);#else	return 0;#endif}/** * ntfs_version_is_supported - check if NTFS version is supported. * @vol:	ntfs volume whose version we're interested in. * * The function checks if the NTFS volume version is known or not. * Version 1.1 and 1.2 are used by Windows NT3.x and NT4. * Version 2.x is used by Windows 2000 Betas. * Version 3.0 is used by Windows 2000. * Version 3.1 is used by Windows XP, Windows Server 2003 and Longhorn. * * Return 0 if NTFS version is supported otherwise -1 with errno set. * * The following error codes are defined: *	EOPNOTSUPP - Unknown NTFS version *	EINVAL	   - Invalid argument */int ntfs_version_is_supported(ntfs_volume *vol){	u8 major, minor;	if (!vol) {		errno = EINVAL;		return -1;	}	major = vol->major_ver;	minor = vol->minor_ver;	if (NTFS_V1_1(major, minor) || NTFS_V1_2(major, minor))		return 0;	if (NTFS_V2_X(major, minor))		return 0;	if (NTFS_V3_0(major, minor) || NTFS_V3_1(major, minor))		return 0;	errno = EOPNOTSUPP;	return -1;}/** * ntfs_logfile_reset - "empty" $LogFile data attribute value * @vol:	ntfs volume whose $LogFile we intend to reset. * * Fill the value of the $LogFile data attribute, i.e. the contents of * the file, with 0xff's, thus marking the journal as empty. * * FIXME(?): We might need to zero the LSN field of every single mft * record as well. (But, first try without doing that and see what * happens, since chkdsk might pickup the pieces and do it for us...)

⌨️ 快捷键说明

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