summaryrefslogtreecommitdiff
path: root/mkudffs/file.c
diff options
context:
space:
mode:
Diffstat (limited to 'mkudffs/file.c')
-rw-r--r--mkudffs/file.c198
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