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

📄 volume.c

📁 添加linux下对NTFS格式文件系统访问支持的源代码ntfs-3g
💻 C
📖 第 1 页 / 共 3 页
字号:
		/* 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("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 = ntfs_malloc(u + 1);			if (!vol->vol_name) {				ntfs_log_debug(FAILED);				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 $AttrDef");		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_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 = ntfs_malloc(na->data_size);	if (!vol->attrdef) {		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->attrdef);	if (l != na->data_size) {		ntfs_log_debug(FAILED);		ntfs_log_error("Failed to read $AttrDef, unexpected length "			       "(%lld != %lld).\n", (long long)l,			       (long long)na->data_size);		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);	free(m);	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}/** * 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 = ntfs_malloc(PATH_MAX + 1);	if (!real_file)		return -1;	real_fsname = ntfs_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 *//** * 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 *file __attribute__((unused)),		unsigned long *mnt_flags){	*mnt_flags = 0;#ifdef HAVE_MNTENT_H	return ntfs_mntent_check(file, 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...) * * On success return 0. * * On error return -1 with errno set to the error code. */int ntfs_logfile_reset(ntfs_volume *vol){	ntfs_inode *ni;	ntfs_attr *na;	int eo;	if (!vol) {		errno = EINVAL;		return -1;	}	if ((ni = ntfs_inode_open(vol, FILE_LogFile)) == NULL) {		ntfs_log_perror("Failed to open inode FILE_LogFile.");		return -1;	}	if ((na = ntfs_attr_open(ni, AT_DATA, AT_UNNAMED, 0)) == NULL) {		eo = errno;		ntfs_log_perror("Failed to open $FILE_LogFile/$DATA");		goto error_exit;	}	if (ntfs_empty_logfile(na)) {		eo = errno;		ntfs_log_perror("Failed to empty $FILE_LogFile/$DATA");		ntfs_attr_close(na);		goto error_exit;	}	ntfs_attr_close(na);	return ntfs_inode_close(ni);error_exit:	ntfs_inode_close(ni);	errno = eo;	return -1;}/** * ntfs_volume_write_flags - set the flags of an ntfs volume * @vol:	ntfs volume where we set the volume flags * @flags:	new flags * * Set the on-disk volume flags in the mft record of $Volume and * on volume @vol to @flags. * * Return 0 if successful and -1 if not with errno set to the error code. */int ntfs_volume_write_flags(ntfs_volume *vol, const u16 flags){	ATTR_RECORD *a;	VOLUME_INFORMATION *c;	ntfs_attr_search_ctx *ctx;	int ret = -1;	/* failure */	if (!vol || !vol->vol_ni) {		errno = EINVAL;		return -1;	}	/* Get a pointer to the volume information attribute. */	ctx = ntfs_attr_get_search_ctx(vol->vol_ni, NULL);	if (!ctx) {		ntfs_log_perror("Failed to allocate attribute search context");		return -1;	}	if (ntfs_attr_lookup(AT_VOLUME_INFORMATION, AT_UNNAMED, 0, 0, 0, NULL,			0, ctx)) {		ntfs_log_error("Attribute $VOLUME_INFORMATION was not found "			       "in $Volume!\n");		goto err_out;	}	a = ctx->attr;	/* Sanity check. */	if (a->non_resident) {		ntfs_log_error("Attribute $VOLUME_INFORMATION must be resident "			       "but it isn't.\n");		errno = EIO;		goto err_out;	}	/* Get a pointer to the value of the attribute. */	c = (VOLUME_INFORMATION*)(le16_to_cpu(a->value_offset) + (char*)a);	/* Sanity checks. */	if ((char*)c + 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_error("Attribute $VOLUME_INFORMATION in $Volume is "			       "corrupt!\n");		errno = EIO;		goto err_out;	}	/* Set the volume flags. */	vol->flags = c->flags = flags & VOLUME_FLAGS_MASK;	/* Write them to disk. */	ntfs_inode_mark_dirty(vol->vol_ni);	if (ntfs_inode_sync(vol->vol_ni)) {		ntfs_log_perror("Error writing $Volume");		goto err_out;	}	ret = 0; /* success */err_out:	ntfs_attr_put_search_ctx(ctx);	return ret;}

⌨️ 快捷键说明

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