diff options
Diffstat (limited to 'mkudffs/file.c')
-rw-r--r-- | mkudffs/file.c | 198 |
1 files changed, 183 insertions, 15 deletions
diff --git a/mkudffs/file.c b/mkudffs/file.c index a931b69..555bec3 100644 --- a/mkudffs/file.c +++ b/mkudffs/file.c @@ -1,8 +1,8 @@ /* * file.c * - * Copyright (c) 2001-2002 Ben Fennema <bfennema@falcon.csc.calpoly.edu> - * Copyright (c) 2016-2017 Pali Rohár <pali.rohar@gmail.com> + * Copyright (c) 2001-2002 Ben Fennema + * Copyright (c) 2016-2018 Pali Rohár <pali.rohar@gmail.com> * All rights reserved. * * This program is free software; you can redistribute it and/or modify @@ -30,6 +30,7 @@ #include <stdio.h> #include <stdlib.h> +#include <string.h> #include <sys/stat.h> #include "libudffs.h" @@ -126,16 +127,17 @@ tag query_tag(struct udf_disc *disc, struct udf_extent *ext, struct udf_desc *de * @param SerialNum the serial number to assign * @param Location the block number of the on-disc tag:Ident udf_descriptor * @param data the udf_data list head + * @param skip the skip data length * @param length the summed data length * @return the tag */ -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 udf_query_tag(struct udf_disc *disc, uint16_t Ident, uint16_t SerialNum, uint32_t Location, struct udf_data *data, uint32_t skip, uint32_t length) { tag ret; int i; uint16_t crc = 0; - int offset = sizeof(tag); - int clength; + uint32_t clength; + uint32_t offset = sizeof(tag); ret.tagIdent = cpu_to_le16(Ident); if (disc->udf_rev >= 0x0200) @@ -150,9 +152,10 @@ tag udf_query_tag(struct udf_disc *disc, uint16_t Ident, uint16_t SerialNum, uin { if ((clength = data->length) > length) clength = length; - crc = udf_crc(data->buffer + offset, clength - offset, crc); + crc = udf_crc(data->buffer + skip + offset, clength - offset, crc); length -= clength; offset = 0; + skip = 0; data = data->next; } ret.descCRC = cpu_to_le16(crc); @@ -439,7 +442,7 @@ void insert_fid(struct udf_disc *disc, struct udf_extent *pspace, struct udf_des 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); + fid->descTag = udf_query_tag(disc, TAG_IDENT_FID, 1, le32_to_cpu(fid->descTag.tagLocation), data, 0, ilength); efe->informationLength = cpu_to_le64(le64_to_cpu(efe->informationLength) + ilength); efe->objectSize = cpu_to_le64(le64_to_cpu(efe->objectSize) + ilength); @@ -472,13 +475,177 @@ void insert_fid(struct udf_disc *disc, struct udf_extent *pspace, struct udf_des 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); + fid->descTag = udf_query_tag(disc, TAG_IDENT_FID, 1, le32_to_cpu(fid->descTag.tagLocation), data, 0, ilength); fe->informationLength = cpu_to_le64(le64_to_cpu(fe->informationLength) + ilength); } *(tag *)desc->data->buffer = query_tag(disc, pspace, desc, 1); *(tag *)parent->data->buffer = query_tag(disc, pspace, parent, 1); } +void insert_ea(struct udf_disc *disc, struct udf_desc *desc, struct genericFormat *ea, uint32_t length) +{ + struct extendedAttrHeaderDesc *ea_hdr; + struct extendedFileEntry *efe = NULL; + struct fileEntry *fe = NULL; + uint8_t *extendedAttr; + uint32_t lengthExtendedAttr; + uint32_t location = 0; + +#define UPDATE_PTR \ + do { \ + if (disc->flags & FLAG_EFE) \ + { \ + efe = (struct extendedFileEntry *)desc->data->buffer; \ + lengthExtendedAttr = efe->lengthExtendedAttr; \ + extendedAttr = efe->extendedAttr; \ + } \ + else \ + { \ + fe = (struct fileEntry *)desc->data->buffer; \ + lengthExtendedAttr = fe->lengthExtendedAttr; \ + extendedAttr = fe->extendedAttr; \ + } \ + ea_hdr = (struct extendedAttrHeaderDesc *)extendedAttr; \ + } while ( 0 ) + + UPDATE_PTR; + + if (le32_to_cpu(lengthExtendedAttr) && le32_to_cpu(ea_hdr->impAttrLocation) > le32_to_cpu(lengthExtendedAttr)) + ea_hdr->impAttrLocation = cpu_to_le32(0xFFFFFFFF); + if (le32_to_cpu(lengthExtendedAttr) && le32_to_cpu(ea_hdr->appAttrLocation) > le32_to_cpu(lengthExtendedAttr)) + ea_hdr->appAttrLocation = cpu_to_le32(0xFFFFFFFF); + + if (!le32_to_cpu(lengthExtendedAttr)) + { + desc->length += sizeof(*ea_hdr); + desc->data->length += sizeof(*ea_hdr); + desc->data->buffer = realloc(desc->data->buffer, desc->data->length); + + UPDATE_PTR; + + if (disc->flags & FLAG_EFE) + { + lengthExtendedAttr = efe->lengthExtendedAttr = cpu_to_le32(sizeof(*ea_hdr)); + if (le32_to_cpu(efe->lengthAllocDescs)) + memmove(&efe->allocDescs[sizeof(*ea_hdr)], efe->allocDescs, le32_to_cpu(efe->lengthAllocDescs)); + } + else + { + lengthExtendedAttr = fe->lengthExtendedAttr = cpu_to_le32(sizeof(*ea_hdr)); + if (le32_to_cpu(fe->lengthAllocDescs)) + memmove(&fe->allocDescs[sizeof(*ea_hdr)], fe->allocDescs, le32_to_cpu(fe->lengthAllocDescs)); + } + + ea_hdr->impAttrLocation = cpu_to_le32(0xFFFFFFFF); + ea_hdr->appAttrLocation = cpu_to_le32(0xFFFFFFFF); + } + + if (le32_to_cpu(ea->attrType) < 2048) + { + desc->length += length; + desc->data->length += length; + desc->data->buffer = realloc(desc->data->buffer, desc->data->length); + + UPDATE_PTR; + + if (le32_to_cpu(ea_hdr->appAttrLocation) != 0xFFFFFFFF) + { + location = le32_to_cpu(ea_hdr->appAttrLocation); + memmove(&extendedAttr[location+length], &extendedAttr[location], le32_to_cpu(lengthExtendedAttr) - location); + ea_hdr->appAttrLocation = cpu_to_le32(location+length); + } + + if (le32_to_cpu(ea_hdr->impAttrLocation) != 0xFFFFFFFF) + { + location = le32_to_cpu(ea_hdr->impAttrLocation); + if (le32_to_cpu(ea_hdr->appAttrLocation) == 0xFFFFFFFF) + memmove(&extendedAttr[location+length], &extendedAttr[location], le32_to_cpu(lengthExtendedAttr) - location); + else + memmove(&extendedAttr[location+length], &extendedAttr[location], le32_to_cpu(ea_hdr->appAttrLocation) - location); + ea_hdr->impAttrLocation = cpu_to_le32(location+length); + } + else if (le32_to_cpu(ea_hdr->appAttrLocation) == 0xFFFFFFFF) + { + location = le32_to_cpu(lengthExtendedAttr); + } + + memcpy(&extendedAttr[location], ea, length); + lengthExtendedAttr = cpu_to_le32(le32_to_cpu(lengthExtendedAttr) + length); + if (disc->flags & FLAG_EFE) + efe->lengthExtendedAttr = lengthExtendedAttr; + else + fe->lengthExtendedAttr = lengthExtendedAttr; + } + else if (le32_to_cpu(ea->attrType) < 65536) + { + desc->length += length; + desc->data->length += length; + desc->data->buffer = realloc(desc->data->buffer, desc->data->length); + + UPDATE_PTR; + + if (le32_to_cpu(ea_hdr->appAttrLocation) != 0xFFFFFFFF) + { + location = le32_to_cpu(ea_hdr->appAttrLocation); + memmove(&extendedAttr[location+length], &extendedAttr[location], le32_to_cpu(lengthExtendedAttr) - location); + ea_hdr->appAttrLocation = cpu_to_le32(location+length); + } + else + { + location = le32_to_cpu(lengthExtendedAttr); + } + + if (le32_to_cpu(ea_hdr->impAttrLocation) == 0xFFFFFFFF) + { + if (le32_to_cpu(ea_hdr->appAttrLocation) == 0xFFFFFFFF) + ea_hdr->impAttrLocation = lengthExtendedAttr; + else + ea_hdr->impAttrLocation = ea_hdr->appAttrLocation; + } + + memcpy(&extendedAttr[location], ea, length); + lengthExtendedAttr = cpu_to_le32(le32_to_cpu(lengthExtendedAttr) + length); + if (disc->flags & FLAG_EFE) + efe->lengthExtendedAttr = lengthExtendedAttr; + else + fe->lengthExtendedAttr = lengthExtendedAttr; + } + else + { + desc->length += length; + desc->data->length += length; + desc->data->buffer = realloc(desc->data->buffer, desc->data->length); + + UPDATE_PTR; + + if (le32_to_cpu(ea_hdr->appAttrLocation) == 0xFFFFFFFF) + ea_hdr->appAttrLocation = lengthExtendedAttr; + + memcpy(&extendedAttr[le32_to_cpu(lengthExtendedAttr)], ea, length); + lengthExtendedAttr = cpu_to_le32(le32_to_cpu(lengthExtendedAttr) + length); + if (disc->flags & FLAG_EFE) + efe->lengthExtendedAttr = lengthExtendedAttr; + else + fe->lengthExtendedAttr = lengthExtendedAttr; + } + + /* UDF-1.50: 3.3.4.1 Extended Attribute Header Descriptor + * If the attributes associated with the location fields highlighted above do not exist, + * then the value of the location field shall point to the byte after the extended + * attribute space. */ + if (disc->udf_rev < 0x0200) + { + if (le32_to_cpu(lengthExtendedAttr) && le32_to_cpu(ea_hdr->impAttrLocation) == 0xFFFFFFFF) + ea_hdr->impAttrLocation = lengthExtendedAttr; + if (le32_to_cpu(lengthExtendedAttr) && le32_to_cpu(ea_hdr->appAttrLocation) == 0xFFFFFFFF) + ea_hdr->appAttrLocation = lengthExtendedAttr; + } + + ea_hdr->descTag = udf_query_tag(disc, TAG_IDENT_EAHD, 1, desc->offset, desc->data, (disc->flags & FLAG_EFE) ? sizeof(*efe) : sizeof(*fe), sizeof(*ea_hdr)); + +#undef UPDATE_PTR +} + /** * @brief create a file tag:FE/EFE udf_descriptor and add the file to a directory * @param disc the udf_disc @@ -722,6 +889,7 @@ static inline unsigned long udf_find_next_one_bit (void * addr, unsigned long si tmp = leBPL_to_cpup(&tmp); found_first: tmp &= ~0UL >> (BITS_PER_LONG-size); + tmp |= (1UL << size); found_middle: return result + ffz(~tmp); } @@ -791,18 +959,18 @@ int udf_alloc_bitmap_blocks(struct udf_disc *disc, struct udf_desc *bitmap, uint do { start = ((start + alignment - 1) / alignment) * alignment; - if (start + blocks >= sbd->numOfBits) + if (start + blocks > le32_to_cpu(sbd->numOfBits)) { fprintf(stderr, "%s: Error: Not enough blocks on device\n", appname); exit(1); } if (sbd->bitmap[start/8] & (1 << (start%8))) { - end = udf_find_next_zero_bit(sbd->bitmap, sbd->numOfBits, start); + end = udf_find_next_zero_bit(sbd->bitmap, le32_to_cpu(sbd->numOfBits), start); } else - start = end = udf_find_next_one_bit(sbd->bitmap, sbd->numOfBits, start); - } while ((end - start) <= blocks); + start = end = udf_find_next_one_bit(sbd->bitmap, le32_to_cpu(sbd->numOfBits), start); + } while ((end - start) < blocks); clear_bits(sbd->bitmap, start, blocks); return start; @@ -825,7 +993,7 @@ int udf_alloc_table_blocks(struct udf_disc *disc, struct udf_desc *table, uint32 do { - if (offset >= use->lengthAllocDescs) + if (offset >= le32_to_cpu(use->lengthAllocDescs)) { fprintf(stderr, "%s: Error: Not enough blocks on device\n", appname); exit(1); @@ -869,7 +1037,7 @@ int udf_alloc_table_blocks(struct udf_disc *disc, struct udf_desc *table, uint32 sad->extLength = cpu_to_le32(EXT_NOT_RECORDED_ALLOCATED | (end - start - blocks) * disc->blocksize); use->lengthAllocDescs = cpu_to_le32(le32_to_cpu(use->lengthAllocDescs) + sizeof(short_ad)); } - use->descTag = udf_query_tag(disc, TAG_IDENT_USE, 1, table->offset, table->data, sizeof(struct unallocSpaceEntry) + le32_to_cpu(use->lengthAllocDescs)); + use->descTag = udf_query_tag(disc, TAG_IDENT_USE, 1, table->offset, table->data, 0, sizeof(struct unallocSpaceEntry) + le32_to_cpu(use->lengthAllocDescs)); return start; } @@ -923,7 +1091,7 @@ int udf_alloc_blocks(struct udf_disc *disc, struct udf_extent *pspace, uint32_t exit(1); } for (i = 0; i < blocks; ++i) - disc->vat[disc->vat_entries++] = start+i; + disc->vat[disc->vat_entries++] = cpu_to_le32(start+i); return start; } else |