📄 file.c
字号:
/* * 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 + -