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

📄 file.c

📁 linux下的DVD格式udf文件读取库
💻 C
📖 第 1 页 / 共 2 页
字号:
/* * file.c * * Copyright (c) 2001-2002  Ben Fennema <bfennema@falcon.csc.calpoly.edu> * All rights reserved. * * This program 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 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; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * */#include <malloc.h>#include "libudffs.h"#include "defaults.h"#include "config.h"tag query_tag(struct udf_disc *disc, struct udf_extent *ext, struct udf_desc *desc, uint16_t SerialNum){	tag ret;	int i;	struct udf_data *data;	uint16_t crc = 0;	int offset = sizeof(tag);	ret.tagIdent = cpu_to_le16(desc->ident);	if (disc->udf_rev >= 0x0200)		ret.descVersion = cpu_to_le16(3);	else		ret.descVersion = cpu_to_le16(2);	ret.tagChecksum = 0;	ret.reserved = 0;	ret.tagSerialNum = cpu_to_le16(SerialNum);	ret.descCRCLength = cpu_to_le16(desc->length - sizeof(tag));	data = desc->data;	while (data != NULL)	{		crc = udf_crc(data->buffer + offset, data->length - offset, crc);		offset = 0;		data = data->next;	}	ret.descCRC = cpu_to_le16(crc);	if (ext->space_type & PSPACE)		ret.tagLocation = cpu_to_le32(desc->offset);	else		ret.tagLocation = cpu_to_le32(ext->start + desc->offset);	for (i=0; i<16; i++)		if (i != 4)			ret.tagChecksum += (uint8_t)(((char *)&ret)[i]);	return ret;}tag udf_query_tag(struct udf_disc *disc, uint16_t Ident, uint16_t SerialNum, uint32_t Location, struct udf_data *data, uint16_t length){	tag ret;	int i;	uint16_t crc = 0;	int offset = sizeof(tag);	int clength;	ret.tagIdent = cpu_to_le16(Ident);	if (disc->udf_rev >= 0x0200)		ret.descVersion = cpu_to_le16(3);	else		ret.descVersion = cpu_to_le16(2);	ret.tagChecksum = 0;	ret.reserved = 0;	ret.tagSerialNum = cpu_to_le16(SerialNum);	ret.descCRCLength = cpu_to_le16(length - sizeof(tag));	while (data != NULL && length)	{		if ((clength = data->length) > length)			clength = length;		crc = udf_crc(data->buffer + offset, clength - offset, crc);		length -= clength;		offset = 0;		data = data->next;	}	ret.descCRC = cpu_to_le16(crc);	ret.tagLocation = cpu_to_le32(Location);	for (i=0; i<16; i++)		if (i != 4)			ret.tagChecksum += (uint8_t)(((char *)&ret)[i]);	return ret;}int insert_desc(struct udf_disc *disc, struct udf_extent *pspace, struct udf_desc *desc, struct udf_desc *parent, struct udf_data *data){	uint32_t block = 0;	if (disc->flags & FLAG_EFE)	{		struct extendedFileEntry *efe;		efe = (struct extendedFileEntry *)parent->data->buffer;		if ((le16_to_cpu(efe->icbTag.flags) & ICBTAG_FLAG_AD_MASK) == ICBTAG_FLAG_AD_IN_ICB)		{			block = parent->offset;			append_data(parent, data);			efe->lengthAllocDescs = cpu_to_le32(le32_to_cpu(efe->lengthAllocDescs) + data->length);		}		else		{			struct udf_desc *fiddesc = NULL;			if (le32_to_cpu(efe->lengthAllocDescs) == 0)			{				block = udf_alloc_blocks(disc, pspace, desc->offset, 1);				fiddesc = set_desc(disc, pspace, TAG_IDENT_FID, block, data->length, data);				if ((le16_to_cpu(efe->icbTag.flags) & ICBTAG_FLAG_AD_MASK) == ICBTAG_FLAG_AD_SHORT)				{					short_ad *sad;					parent->length += sizeof(short_ad);					parent->data->length += sizeof(short_ad);					parent->data->buffer = realloc(parent->data->buffer, parent->length);					efe = (struct extendedFileEntry *)parent->data->buffer;					sad = (short_ad *)&efe->allocDescs[le32_to_cpu(efe->lengthExtendedAttr) + le32_to_cpu(efe->lengthAllocDescs)];					sad->extPosition = cpu_to_le32(block);					sad->extLength = cpu_to_le32(data->length);					efe->lengthAllocDescs = cpu_to_le32(sizeof(short_ad));				}				else if ((le16_to_cpu(efe->icbTag.flags) & ICBTAG_FLAG_AD_MASK) == ICBTAG_FLAG_AD_LONG)				{					long_ad *lad;					parent->length += sizeof(long_ad);					parent->data->length += sizeof(long_ad);					parent->data->buffer = realloc(parent->data->buffer, parent->length);					efe = (struct extendedFileEntry *)parent->data->buffer;					lad = (long_ad *)&efe->allocDescs[le32_to_cpu(efe->lengthExtendedAttr) + le32_to_cpu(efe->lengthAllocDescs)];					lad->extLocation.logicalBlockNum = cpu_to_le32(block);					lad->extLocation.partitionReferenceNum = cpu_to_le16(0);					lad->extLength = cpu_to_le32(data->length);					efe->lengthAllocDescs = cpu_to_le32(sizeof(long_ad));				}				efe->logicalBlocksRecorded = cpu_to_le32(1);			}			else			{				if ((le16_to_cpu(efe->icbTag.flags) & ICBTAG_FLAG_AD_MASK) == ICBTAG_FLAG_AD_SHORT)				{					short_ad *sad;					sad = (short_ad *)&efe->allocDescs[le32_to_cpu(efe->lengthExtendedAttr) + le32_to_cpu(efe->lengthAllocDescs) - sizeof(short_ad)];					fiddesc = find_desc(pspace, le32_to_cpu(sad->extPosition));					block = fiddesc->offset;					append_data(fiddesc, data);					sad->extLength = cpu_to_le32(le32_to_cpu(sad->extLength) + data->length);				}				else if ((le16_to_cpu(efe->icbTag.flags) & ICBTAG_FLAG_AD_MASK) == ICBTAG_FLAG_AD_LONG)				{					long_ad *lad;					lad = (long_ad *)&efe->allocDescs[le32_to_cpu(efe->lengthExtendedAttr) + le32_to_cpu(efe->lengthAllocDescs) - sizeof(long_ad)];					fiddesc = find_desc(pspace, le32_to_cpu(lad->extLocation.logicalBlockNum));					block = fiddesc->offset;					append_data(fiddesc, data);					lad->extLength = cpu_to_le32(le32_to_cpu(lad->extLength) + data->length);				}			}		}	}	else	{		struct fileEntry *fe;		fe = (struct fileEntry *)parent->data->buffer;		if ((le16_to_cpu(fe->icbTag.flags) & ICBTAG_FLAG_AD_MASK) == ICBTAG_FLAG_AD_IN_ICB)		{			block = parent->offset;			append_data(parent, data);			fe->lengthAllocDescs = cpu_to_le32(le32_to_cpu(fe->lengthAllocDescs) + data->length);		}		else		{			struct udf_desc *fiddesc = NULL;			if (le32_to_cpu(fe->lengthAllocDescs) == 0)			{				block = udf_alloc_blocks(disc, pspace, desc->offset, 1);				fiddesc = set_desc(disc, pspace, TAG_IDENT_FID, block, data->length, data);				if ((le16_to_cpu(fe->icbTag.flags) & ICBTAG_FLAG_AD_MASK) == ICBTAG_FLAG_AD_SHORT)				{					short_ad *sad;					parent->length += sizeof(short_ad);					parent->data->length += sizeof(short_ad);					parent->data->buffer = realloc(parent->data->buffer, parent->length);					fe = (struct fileEntry *)parent->data->buffer;					sad = (short_ad *)&fe->allocDescs[le32_to_cpu(fe->lengthExtendedAttr) + le32_to_cpu(fe->lengthAllocDescs)];					sad->extPosition = cpu_to_le32(block);					sad->extLength = cpu_to_le32(data->length);					fe->lengthAllocDescs = cpu_to_le32(sizeof(short_ad));				}				else if ((le16_to_cpu(fe->icbTag.flags) & ICBTAG_FLAG_AD_MASK) == ICBTAG_FLAG_AD_LONG)				{					long_ad *lad;					parent->length += sizeof(long_ad);					parent->data->length += sizeof(long_ad);					parent->data->buffer = realloc(parent->data->buffer, parent->length);					fe = (struct fileEntry *)parent->data->buffer;					lad = (long_ad *)&fe->allocDescs[le32_to_cpu(fe->lengthExtendedAttr) + le32_to_cpu(fe->lengthAllocDescs)];					lad->extLocation.logicalBlockNum = cpu_to_le32(block);					lad->extLocation.partitionReferenceNum = cpu_to_le16(0);					lad->extLength = cpu_to_le32(data->length);					fe->lengthAllocDescs = cpu_to_le32(sizeof(long_ad));				}				fe->logicalBlocksRecorded = cpu_to_le32(1);			}			else			{				if ((le16_to_cpu(fe->icbTag.flags) & ICBTAG_FLAG_AD_MASK) == ICBTAG_FLAG_AD_SHORT)				{					short_ad *sad;					sad = (short_ad *)&fe->allocDescs[le32_to_cpu(fe->lengthExtendedAttr) + le32_to_cpu(fe->lengthAllocDescs) - sizeof(short_ad)];					fiddesc = find_desc(pspace, le32_to_cpu(sad->extPosition));					block = fiddesc->offset;					append_data(fiddesc, data);					sad->extLength = cpu_to_le32(le32_to_cpu(sad->extLength) + data->length);				}				else if ((le16_to_cpu(fe->icbTag.flags) & ICBTAG_FLAG_AD_MASK) == ICBTAG_FLAG_AD_LONG)				{					long_ad *lad;					lad = (long_ad *)&fe->allocDescs[le32_to_cpu(fe->lengthExtendedAttr) + le32_to_cpu(fe->lengthAllocDescs) - sizeof(long_ad)];					fiddesc = find_desc(pspace, le32_to_cpu(lad->extLocation.logicalBlockNum));					block = fiddesc->offset;					append_data(fiddesc, data);					lad->extLength = cpu_to_le32(le32_to_cpu(lad->extLength) + data->length);				}			}		}	}	return block;}void insert_data(struct udf_disc *disc, struct udf_extent *pspace, struct udf_desc *desc, struct udf_data *data){	if (disc->flags & FLAG_EFE)	{		struct extendedFileEntry *efe;		efe = (struct extendedFileEntry *)desc->data->buffer;		if ((le16_to_cpu(efe->icbTag.flags) & ICBTAG_FLAG_AD_MASK) == ICBTAG_FLAG_AD_IN_ICB)		{			append_data(desc, data);			efe->lengthAllocDescs = cpu_to_le32(le32_to_cpu(efe->lengthAllocDescs) + data->length);			efe->informationLength = cpu_to_le64(le64_to_cpu(efe->informationLength) + data->length);			efe->objectSize = cpu_to_le64(le64_to_cpu(efe->objectSize) + data->length);		}	}	else	{		struct fileEntry *fe;		fe = (struct fileEntry *)desc->data->buffer;		if ((le16_to_cpu(fe->icbTag.flags) & ICBTAG_FLAG_AD_MASK) == ICBTAG_FLAG_AD_IN_ICB)		{			append_data(desc, data);			fe->lengthAllocDescs = cpu_to_le32(le32_to_cpu(fe->lengthAllocDescs) + data->length);			fe->informationLength = cpu_to_le64(le64_to_cpu(fe->informationLength) + data->length);		}	}	*(tag *)desc->data->buffer = query_tag(disc, pspace, desc, 1);}uint32_t compute_ident_length(uint32_t length){	return length + (4 - (length % 4)) %4;}void insert_fid(struct udf_disc *disc, struct udf_extent *pspace, struct udf_desc *desc, struct udf_desc *parent, uint8_t *name, uint8_t length, uint8_t fc){	struct udf_data *data;	struct fileIdentDesc *fid;	int ilength = compute_ident_length(sizeof(struct fileIdentDesc) + length);	int offset;	uint64_t uniqueID;		data = alloc_data(NULL, ilength);	fid = data->buffer;	offset = insert_desc(disc, pspace, desc, parent, data);	fid->descTag.tagLocation = cpu_to_le32(offset);	if (disc->flags & FLAG_EFE)	{		struct extendedFileEntry *efe;		efe = (struct extendedFileEntry *)desc->data->buffer;		efe->fileLinkCount = cpu_to_le16(le16_to_cpu(efe->fileLinkCount) + 1);		uniqueID = le64_to_cpu(efe->uniqueID);		efe = (struct extendedFileEntry *)parent->data->buffer;		if (disc->flags & FLAG_STRATEGY4096)			fid->icb.extLength = cpu_to_le32(disc->blocksize * 2);		else			fid->icb.extLength = cpu_to_le32(disc->blocksize);		fid->icb.extLocation.logicalBlockNum = cpu_to_le32(desc->offset);		fid->icb.extLocation.partitionReferenceNum = cpu_to_le16(0);		*(uint32_t *)((struct allocDescImpUse *)fid->icb.impUse)->impUse = cpu_to_le32(uniqueID & 0x00000000FFFFFFFFUL);		fid->fileVersionNum = cpu_to_le16(1);		fid->fileCharacteristics = fc;		fid->lengthFileIdent = length;		fid->lengthOfImpUse = cpu_to_le16(0);		memcpy(fid->fileIdent, name, length);		fid->descTag = udf_query_tag(disc, TAG_IDENT_FID, 1, le32_to_cpu(fid->descTag.tagLocation), data, ilength);		efe->informationLength = cpu_to_le64(le64_to_cpu(efe->informationLength) + ilength);		efe->objectSize = cpu_to_le64(le64_to_cpu(efe->objectSize) + ilength);	}	else	{		struct fileEntry *fe;		fe = (struct fileEntry *)desc->data->buffer;		fe->fileLinkCount = cpu_to_le16(le16_to_cpu(fe->fileLinkCount) + 1);		uniqueID = le64_to_cpu(fe->uniqueID);		fe = (struct fileEntry *)parent->data->buffer;		if (disc->flags & FLAG_STRATEGY4096)			fid->icb.extLength = cpu_to_le32(disc->blocksize * 2);		else			fid->icb.extLength = cpu_to_le32(disc->blocksize);		fid->icb.extLocation.logicalBlockNum = cpu_to_le32(desc->offset);		fid->icb.extLocation.partitionReferenceNum = cpu_to_le16(0);		*(uint32_t *)((struct allocDescImpUse *)fid->icb.impUse)->impUse = cpu_to_le32(uniqueID & 0x00000000FFFFFFFFUL);		fid->fileVersionNum = cpu_to_le16(1);

⌨️ 快捷键说明

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