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

📄 attrib.c

📁 上一个上传的有问题,这个是好的。visopsys包括系统内核和GUI的全部SOURCE code ,还包括一些基本的docs文档。里面src子目录对应所有SOURCE code.对于想研究操作系统的朋
💻 C
📖 第 1 页 / 共 5 页
字号:
/** * attrib.c - Attribute handling code. Part of the Linux-NTFS project. * * Copyright (c) 2000-2005 Anton Altaparmakov * Copyright (c) 2002-2005 Richard Russon * Copyright (c) 2004-2006 Yura Pakhuchiy * * This program/include file is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as published * by the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program/include file is distributed in the hope that it will be * useful, but WITHOUT ANY WARRANTY; without even the implied warranty * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program (in the main directory of the Linux-NTFS * distribution in the file COPYING); if not, write to the Free Software * Foundation,Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA * * Modified 01/2007 by Andy McLaughlin for Visopsys port. */#ifdef HAVE_CONFIG_H#include "config.h"#endif#ifdef HAVE_STDIO_H#include <stdio.h>#endif#ifdef HAVE_STRING_H#include <string.h>#endif#ifdef HAVE_STDLIB_H#include <stdlib.h>#endif#ifdef HAVE_ERRNO_H#include <errno.h>#endif#include "compat.h"#include "attrib.h"#include "attrlist.h"#include "device.h"#include "mft.h"#include "debug.h"#include "mst.h"#include "volume.h"#include "types.h"#include "layout.h"#include "inode.h"#include "runlist.h"#include "lcnalloc.h"#include "dir.h"#include "compress.h"#include "bitmap.h"#include "logging.h"ntfschar AT_UNNAMED[] = { const_cpu_to_le16('\0') };/** * ntfs_get_attribute_value_length - Find the length of an attribute * @a: * * Description... * * Returns: */s64 ntfs_get_attribute_value_length(const ATTR_RECORD *a){	if (!a) {		errno = EINVAL;		return 0;	}	errno = 0;	if (a->non_resident)		return sle64_to_cpu(a->data_size);	else		return (s64)le32_to_cpu(a->value_length);	errno = EINVAL;	return 0;}/** * ntfs_get_attribute_value - Get a copy of an attribute * @vol:	 * @a:	 * @b:	 * * Description... * * Returns: */s64 ntfs_get_attribute_value(const ntfs_volume *vol,		const ATTR_RECORD *a, u8 *b){	runlist *rl;	s64 total, r;	int i;	/* Sanity checks. */	if (!vol || !a || !b) {		errno = EINVAL;		return 0;	}	/* Complex attribute? */	/*	 * Ignore the flags in case they are not zero for an attribute list	 * attribute.  Windows does not complain about invalid flags and chkdsk	 * does not detect or fix them so we need to cope with it, too.	 */	if (a->type != AT_ATTRIBUTE_LIST && a->flags) {		ntfs_log_error("Non-zero (%04x) attribute flags. Cannot handle "			       "this yet.\n", le16_to_cpu(a->flags));		errno = EOPNOTSUPP;		return 0;	}	if (!a->non_resident) {		/* Attribute is resident. */		/* Sanity check. */		if (le32_to_cpu(a->value_length) + le16_to_cpu(a->value_offset)				> le32_to_cpu(a->length)) {			return 0;		}		memcpy(b, (const char*)a + le16_to_cpu(a->value_offset),				le32_to_cpu(a->value_length));		errno = 0;		return (s64)le32_to_cpu(a->value_length);	}	/* Attribute is not resident. */	/* If no data, return 0. */	if (!(a->data_size)) {		errno = 0;		return 0;	}	/*	 * FIXME: What about attribute lists?!? (AIA)	 */	/* Decompress the mapping pairs array into a runlist. */	rl = ntfs_mapping_pairs_decompress(vol, a, NULL);	if (!rl) {		errno = EINVAL;		return 0;	}	/*	 * FIXED: We were overflowing here in a nasty fashion when we	 * reach the last cluster in the runlist as the buffer will	 * only be big enough to hold data_size bytes while we are	 * reading in allocated_size bytes which is usually larger	 * than data_size, since the actual data is unlikely to have a	 * size equal to a multiple of the cluster size!	 * FIXED2:  We were also overflowing here in the same fashion	 * when the data_size was more than one run smaller than the	 * allocated size which happens with Windows XP sometimes.	 */	/* Now load all clusters in the runlist into b. */	for (i = 0, total = 0; rl[i].length; i++) {		if (total + (rl[i].length << vol->cluster_size_bits) >=				sle64_to_cpu(a->data_size)) {			unsigned char *intbuf = NULL;			/*			 * We have reached the last run so we were going to			 * overflow when executing the ntfs_pread() which is			 * BAAAAAAAD!			 * Temporary fix:			 *	Allocate a new buffer with size:			 *	rl[i].length << vol->cluster_size_bits, do the			 *	read into our buffer, then memcpy the correct			 *	amount of data into the caller supplied buffer,			 *	free our buffer, and continue.			 * We have reached the end of data size so we were			 * going to overflow in the same fashion.			 * Temporary fix:  same as above.			 */			intbuf = malloc(rl[i].length << vol->cluster_size_bits);			if (!intbuf) {				int eo = errno;				ntfs_log_perror("Couldn't allocate memory for "						"internal buffer.");				free(rl);				errno = eo;				return 0;			}			/*			 * FIXME: If compressed file: Only read if lcn != -1.			 * Otherwise, we are dealing with a sparse run and we			 * just memset the user buffer to 0 for the length of			 * the run, which should be 16 (= compression unit			 * size).			 * FIXME: Really only when file is compressed, or can			 * we have sparse runs in uncompressed files as well?			 * - Yes we can, in sparse files! But not necessarily			 * size of 16, just run length.			 */			r = ntfs_pread(vol->dev, rl[i].lcn <<					vol->cluster_size_bits, rl[i].length <<					vol->cluster_size_bits, intbuf);			if (r != rl[i].length << vol->cluster_size_bits) {#define ESTR "Error reading attribute value"				if (r == -1) {					int eo = errno;					ntfs_log_perror(ESTR);					errno = eo;				} else if (r < rl[i].length <<						vol->cluster_size_bits) {					ntfs_log_debug(ESTR ": Ran out of input data.\n");					errno = EIO;				} else {					ntfs_log_debug(ESTR ": unknown error\n");					errno = EIO;				}#undef ESTR				free(rl);				free(intbuf);				return 0;			}			memcpy(b + total, intbuf, sle64_to_cpu(a->data_size) -					total);			free(intbuf);			total = sle64_to_cpu(a->data_size);			break;		}		/*		 * FIXME: If compressed file: Only read if lcn != -1.		 * Otherwise, we are dealing with a sparse run and we just		 * memset the user buffer to 0 for the length of the run, which		 * should be 16 (= compression unit size).		 * FIXME: Really only when file is compressed, or can		 * we have sparse runs in uncompressed files as well?		 * - Yes we can, in sparse files! But not necessarily size of		 * 16, just run length.		 */		r = ntfs_pread(vol->dev, rl[i].lcn << vol->cluster_size_bits,				rl[i].length << vol->cluster_size_bits,				b + total);		if (r != rl[i].length << vol->cluster_size_bits) {#define ESTR "Error reading attribute value"			if (r == -1) {				int eo = errno;				ntfs_log_perror(ESTR);				errno = eo;			} else if (r < rl[i].length << vol->cluster_size_bits) {				ntfs_log_debug(ESTR ": Ran out of input data.\n");				errno = EIO;			} else {				ntfs_log_debug(ESTR ": unknown error\n");				errno = EIO;			}#undef ESTR			return 0;		}		total += r;	}	free(rl);	return total;}/* Already cleaned up code below, but still look for FIXME:... *//** * __ntfs_attr_init - primary initialization of an ntfs attribute structure * @na:		ntfs attribute to initialize * @ni:		ntfs inode with which to initialize the ntfs attribute * @type:	attribute type * @name:	attribute name in little endian Unicode or NULL * @name_len:	length of attribute @name in Unicode characters (if @name given) * * Initialize the ntfs attribute @na with @ni, @type, @name, and @name_len. */static __inline__ void __ntfs_attr_init(ntfs_attr *na, ntfs_inode *ni,		const ATTR_TYPES type, ntfschar *name, const u32 name_len){	na->rl = NULL;	na->ni = ni;	na->type = type;	na->name = name;	if (name)		na->name_len = name_len;	else		na->name_len = 0;}/** * ntfs_attr_init - initialize an ntfs_attr with data sizes and status * @na: * @non_resident: * @compressed: * @encrypted: * @sparse: * @allocated_size: * @data_size: * @initialized_size: * @compressed_size: * @compression_unit: * * Final initialization for an ntfs attribute. */void ntfs_attr_init(ntfs_attr *na, const BOOL non_resident,		const BOOL compressed, const BOOL encrypted, const BOOL sparse,		const s64 allocated_size, const s64 data_size,		const s64 initialized_size, const s64 compressed_size,		const u8 compression_unit){	if (!NAttrInitialized(na)) {		if (non_resident)			NAttrSetNonResident(na);		if (compressed)			NAttrSetCompressed(na);		if (encrypted)			NAttrSetEncrypted(na);		if (sparse)			NAttrSetSparse(na);		na->allocated_size = allocated_size;		na->data_size = data_size;		na->initialized_size = initialized_size;		if (compressed || sparse) {			ntfs_volume *vol = na->ni->vol;			na->compressed_size = compressed_size;			na->compression_block_clusters = 1 << compression_unit;			na->compression_block_size = 1 << (compression_unit +					vol->cluster_size_bits);			na->compression_block_size_bits = ffs(					na->compression_block_size) - 1;		}		NAttrSetInitialized(na);	}}/** * ntfs_attr_open - open an ntfs attribute for access * @ni:		open ntfs inode in which the ntfs attribute resides * @type:	attribute type * @name:	attribute name in little endian Unicode or AT_UNNAMED or NULL * @name_len:	length of attribute @name in Unicode characters (if @name given) * * Allocate a new ntfs attribute structure, initialize it with @ni, @type, * @name, and @name_len, then return it. Return NULL on error with * errno set to the error code. * * If @name is AT_UNNAMED look specifically for an unnamed attribute.  If you * do not care whether the attribute is named or not set @name to NULL.  In * both those cases @name_len is not used at all. */ntfs_attr *ntfs_attr_open(ntfs_inode *ni, const ATTR_TYPES type,		ntfschar *name, u32 name_len){	ntfs_attr_search_ctx *ctx;	ntfs_attr *na;	ATTR_RECORD *a;	int err;	BOOL cs;	ntfs_log_trace("Entering for inode 0x%llx, attr 0x%x.\n",		(unsigned long long)ni->mft_no, type);	if (!ni || !ni->vol || !ni->mrec) {		errno = EINVAL;		return NULL;	}	na = calloc(sizeof(ntfs_attr), 1);	if (!na)		return NULL;	if (name && name != AT_UNNAMED && name != NTFS_INDEX_I30) {		name = ntfs_ucsndup(name, name_len);		if (!name) {			err = errno;			free(na);			errno = err;			return NULL;		}	}	ctx = ntfs_attr_get_search_ctx(ni, NULL);	if (!ctx) {		err = errno;		goto err_out;	}	if (ntfs_attr_lookup(type, name, name_len, 0, 0, NULL, 0, ctx)) {		err = errno;		goto put_err_out;	}	a = ctx->attr;	/*	 * Wipe the flags in case they are not zero for an attribute list	 * attribute.  Windows does not complain about invalid flags and chkdsk	 * does not detect or fix them so we need to cope with it, too.	 */	if (type == AT_ATTRIBUTE_LIST)		a->flags = 0;	cs = a->flags & (ATTR_IS_COMPRESSED | ATTR_IS_SPARSE);	if (!name) {		if (a->name_length) {			name = ntfs_ucsndup((ntfschar*)((u8*)a + le16_to_cpu(					a->name_offset)), a->name_length);			if (!name) {				err = errno;				goto put_err_out;			}			name_len = a->name_length;		} else {			name = AT_UNNAMED;			name_len = 0;		}	}	__ntfs_attr_init(na, ni, type, name, name_len);	if (a->non_resident) {		ntfs_attr_init(na, TRUE, a->flags & ATTR_IS_COMPRESSED,				a->flags & ATTR_IS_ENCRYPTED,				a->flags & ATTR_IS_SPARSE,				sle64_to_cpu(a->allocated_size),				sle64_to_cpu(a->data_size),				sle64_to_cpu(a->initialized_size),				cs ? sle64_to_cpu(a->compressed_size) : 0,				cs ? a->compression_unit : 0);	} else {		s64 l = le32_to_cpu(a->value_length);		ntfs_attr_init(na, FALSE, a->flags & ATTR_IS_COMPRESSED,				a->flags & ATTR_IS_ENCRYPTED,				a->flags & ATTR_IS_SPARSE, (l + 7) & ~7, l, l,				cs ? (l + 7) & ~7 : 0, 0);	}	ntfs_attr_put_search_ctx(ctx);	return na;

⌨️ 快捷键说明

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