summaryrefslogtreecommitdiff
path: root/mkudffs
diff options
context:
space:
mode:
Diffstat (limited to 'mkudffs')
-rw-r--r--mkudffs/Makefile.am2
-rw-r--r--mkudffs/Makefile.in8
-rw-r--r--mkudffs/defaults.c2
-rw-r--r--mkudffs/defaults.h2
-rw-r--r--mkudffs/file.c198
-rw-r--r--mkudffs/file.h7
-rw-r--r--mkudffs/main.c11
-rw-r--r--mkudffs/mkudffs.c212
-rw-r--r--mkudffs/mkudffs.h8
-rw-r--r--mkudffs/options.c184
-rw-r--r--mkudffs/options.h2
11 files changed, 434 insertions, 202 deletions
diff --git a/mkudffs/Makefile.am b/mkudffs/Makefile.am
index 8c8ba8d..fc9e54f 100644
--- a/mkudffs/Makefile.am
+++ b/mkudffs/Makefile.am
@@ -1,6 +1,6 @@
sbin_PROGRAMS = mkudffs
mkudffs_LDADD = $(top_builddir)/libudffs/libudffs.la
-mkudffs_SOURCES = main.c mkudffs.c defaults.c file.c options.c mkudffs.h defaults.h file.h options.h ../include/ecma_167.h ../include/osta_udf.h ../include/libudffs.h ../include/udf_endian.h ../include/bswap.h
+mkudffs_SOURCES = main.c mkudffs.c defaults.c file.c options.c mkudffs.h defaults.h file.h options.h ../include/ecma_167.h ../include/osta_udf.h ../include/libudffs.h ../include/bswap.h
AM_CPPFLAGS = -I$(top_srcdir)/include
diff --git a/mkudffs/Makefile.in b/mkudffs/Makefile.in
index 6c24c6b..e8d1ba3 100644
--- a/mkudffs/Makefile.in
+++ b/mkudffs/Makefile.in
@@ -228,11 +228,17 @@ PACKAGE_TARNAME = @PACKAGE_TARNAME@
PACKAGE_URL = @PACKAGE_URL@
PACKAGE_VERSION = @PACKAGE_VERSION@
PATH_SEPARATOR = @PATH_SEPARATOR@
+PKG_CONFIG = @PKG_CONFIG@
+PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@
+PKG_CONFIG_PATH = @PKG_CONFIG_PATH@
RANLIB = @RANLIB@
SED = @SED@
SET_MAKE = @SET_MAKE@
SHELL = @SHELL@
STRIP = @STRIP@
+UDEVDIR = @UDEVDIR@
+UDEV_CFLAGS = @UDEV_CFLAGS@
+UDEV_LIBS = @UDEV_LIBS@
VERSION = @VERSION@
abs_builddir = @abs_builddir@
abs_srcdir = @abs_srcdir@
@@ -288,7 +294,7 @@ top_build_prefix = @top_build_prefix@
top_builddir = @top_builddir@
top_srcdir = @top_srcdir@
mkudffs_LDADD = $(top_builddir)/libudffs/libudffs.la
-mkudffs_SOURCES = main.c mkudffs.c defaults.c file.c options.c mkudffs.h defaults.h file.h options.h ../include/ecma_167.h ../include/osta_udf.h ../include/libudffs.h ../include/udf_endian.h ../include/bswap.h
+mkudffs_SOURCES = main.c mkudffs.c defaults.c file.c options.c mkudffs.h defaults.h file.h options.h ../include/ecma_167.h ../include/osta_udf.h ../include/libudffs.h ../include/bswap.h
AM_CPPFLAGS = -I$(top_srcdir)/include
all: all-am
diff --git a/mkudffs/defaults.c b/mkudffs/defaults.c
index ed0a4d3..b438deb 100644
--- a/mkudffs/defaults.c
+++ b/mkudffs/defaults.c
@@ -1,7 +1,7 @@
/*
* defaults.c
*
- * Copyright (c) 2001-2002 Ben Fennema <bfennema@falcon.csc.calpoly.edu>
+ * Copyright (c) 2001-2002 Ben Fennema
* Copyright (c) 2014-2017 Pali Rohár <pali.rohar@gmail.com>
* All rights reserved.
*
diff --git a/mkudffs/defaults.h b/mkudffs/defaults.h
index 9a6ed99..69ca181 100644
--- a/mkudffs/defaults.h
+++ b/mkudffs/defaults.h
@@ -1,7 +1,7 @@
/*
* defaults.h
*
- * Copyright (c) 2001-2002 Ben Fennema <bfennema@falcon.csc.calpoly.edu>
+ * Copyright (c) 2001-2002 Ben Fennema
* Copyright (c) 2016-2017 Pali Rohár <pali.rohar@gmail.com>
* All rights reserved.
*
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
diff --git a/mkudffs/file.h b/mkudffs/file.h
index d9b4efe..bae6f7b 100644
--- a/mkudffs/file.h
+++ b/mkudffs/file.h
@@ -1,8 +1,8 @@
/*
* libudffs.h
*
- * 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
@@ -27,11 +27,12 @@
#include "libudffs.h"
tag query_tag(struct udf_disc *, struct udf_extent *, struct udf_desc *, uint16_t);
-extern tag udf_query_tag(struct udf_disc *, uint16_t, uint16_t, uint32_t, struct udf_data *, uint16_t);
+extern tag udf_query_tag(struct udf_disc *, uint16_t, uint16_t, uint32_t, struct udf_data *, uint32_t, uint32_t);
extern struct udf_desc *udf_create(struct udf_disc *, struct udf_extent *, const dchars *, uint8_t, uint32_t, struct udf_desc *, uint8_t, uint8_t, uint16_t);
extern struct udf_desc *udf_mkdir(struct udf_disc *, struct udf_extent *, const dchars *, uint8_t, uint32_t, struct udf_desc *);
extern void insert_data(struct udf_disc *disc, struct udf_extent *pspace, struct udf_desc *desc, struct udf_data *data);
extern void insert_fid(struct udf_disc *, struct udf_extent *, struct udf_desc *, struct udf_desc *, const dchars *, uint8_t, uint8_t);
+extern void insert_ea(struct udf_disc *disc, struct udf_desc *desc, struct genericFormat *ea, uint32_t length);
extern int udf_alloc_blocks(struct udf_disc *, struct udf_extent *, uint32_t, uint32_t);
static inline void clear_bits(uint8_t *bitmap, uint32_t offset, uint64_t length)
diff --git a/mkudffs/main.c b/mkudffs/main.c
index 066afac..0932013 100644
--- a/mkudffs/main.c
+++ b/mkudffs/main.c
@@ -1,8 +1,8 @@
/*
* main.c
*
- * Copyright (c) 2001-2002 Ben Fennema <bfennema@falcon.csc.calpoly.edu>
- * Copyright (c) 2014-2017 Pali Rohár <pali.rohar@gmail.com>
+ * Copyright (c) 2001-2002 Ben Fennema
+ * Copyright (c) 2014-2018 Pali Rohár <pali.rohar@gmail.com>
* All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
@@ -30,19 +30,19 @@
#include <stdio.h>
#include <stdlib.h>
+#include <string.h>
#include <locale.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
-#include <time.h>
-#include <sys/time.h>
#include <errno.h>
#include <limits.h>
#include <dirent.h>
#include <sys/ioctl.h>
#include <linux/fs.h>
#include <linux/fd.h>
+#include <sys/sysmacros.h>
#include "mkudffs.h"
#include "defaults.h"
@@ -474,6 +474,9 @@ int main(int argc, char *argv[])
dump_space(&disc);
+ if (disc.blocks <= 257)
+ fprintf(stderr, "%s: Warning: UDF filesystem has less than 258 blocks, it can cause problems\n", appname);
+
if (len == (size_t)-1)
fprintf(stderr, "%s: Warning: Volume Set Identifier must be at least 8 characters long\n", appname);
else if (len < 16)
diff --git a/mkudffs/mkudffs.c b/mkudffs/mkudffs.c
index 9ad3500..59b529c 100644
--- a/mkudffs/mkudffs.c
+++ b/mkudffs/mkudffs.c
@@ -1,8 +1,8 @@
/*
* mkudffs.c
*
- * Copyright (c) 2001-2002 Ben Fennema <bfennema@falcon.csc.calpoly.edu>
- * Copyright (c) 2014-2017 Pali Rohár <pali.rohar@gmail.com>
+ * Copyright (c) 2001-2002 Ben Fennema
+ * Copyright (c) 2014-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/types.h>
#include <sys/stat.h>
#include <fcntl.h>
@@ -50,9 +51,8 @@ void udf_init_disc(struct udf_disc *disc)
struct timeval tv;
struct tm *tm;
int altzone;
- unsigned long int rnd;
-
- srand(time(NULL));
+ uint32_t uuid_time;
+ char uuid[17];
memset(disc, 0x00, sizeof(*disc));
@@ -62,31 +62,50 @@ void udf_init_disc(struct udf_disc *disc)
disc->blkssz = 512;
disc->mode = 0755;
- gettimeofday(&tv, NULL);
- tm = localtime(&tv.tv_sec);
- altzone = timezone - 3600;
- if (daylight)
- ts.typeAndTimezone = cpu_to_le16(((-altzone/60) & 0x0FFF) | 0x1000);
+ if (gettimeofday(&tv, NULL) != 0 || tv.tv_sec == (time_t)-1 || (tm = localtime(&tv.tv_sec)) == NULL || tm->tm_year < 1-1900 || tm->tm_year > 9999-1900)
+ {
+ /* fallback to 1.1.1980 00:00:00 */
+ ts.typeAndTimezone = cpu_to_le16(0x1000);
+ ts.year = cpu_to_le16(1980);
+ ts.month = 1;
+ ts.day = 1;
+ ts.hour = 0;
+ ts.minute = 0;
+ ts.second = 0;
+ ts.centiseconds = 0;
+ ts.hundredsOfMicroseconds = 0;
+ ts.microseconds = 0;
+ /* and for uuid use random bytes */
+ uuid_time = randu32();
+ }
else
- ts.typeAndTimezone = cpu_to_le16(((-timezone/60) & 0x0FFF) | 0x1000);
- ts.year = cpu_to_le16(1900 + tm->tm_year);
- ts.month = 1 + tm->tm_mon;
- ts.day = tm->tm_mday;
- ts.hour = tm->tm_hour;
- ts.minute = tm->tm_min;
- ts.second = tm->tm_sec;
- ts.centiseconds = tv.tv_usec / 10000;
- ts.hundredsOfMicroseconds = (tv.tv_usec - ts.centiseconds * 10000) / 100;
- ts.microseconds = tv.tv_usec - ts.centiseconds * 10000 - ts.hundredsOfMicroseconds * 100;
-
- get_random_bytes(&rnd, sizeof(rnd));
+ {
+ altzone = timezone - 3600;
+ if (daylight)
+ ts.typeAndTimezone = cpu_to_le16(((-altzone/60) & 0x0FFF) | 0x1000);
+ else
+ ts.typeAndTimezone = cpu_to_le16(((-timezone/60) & 0x0FFF) | 0x1000);
+ ts.year = cpu_to_le16(1900 + tm->tm_year);
+ ts.month = 1 + tm->tm_mon;
+ ts.day = tm->tm_mday;
+ ts.hour = tm->tm_hour;
+ ts.minute = tm->tm_min;
+ ts.second = tm->tm_sec;
+ ts.centiseconds = tv.tv_usec / 10000;
+ ts.hundredsOfMicroseconds = (tv.tv_usec - ts.centiseconds * 10000) / 100;
+ ts.microseconds = tv.tv_usec - ts.centiseconds * 10000 - ts.hundredsOfMicroseconds * 100;
+ if (tv.tv_sec < 0)
+ uuid_time = randu32();
+ else
+ uuid_time = tv.tv_sec & 0xFFFFFFFF;
+ }
/* Allocate/Initialize Descriptors */
disc->udf_pvd[0] = malloc(sizeof(struct primaryVolDesc));
memcpy(disc->udf_pvd[0], &default_pvd, sizeof(struct primaryVolDesc));
memcpy(&disc->udf_pvd[0]->recordingDateAndTime, &ts, sizeof(timestamp));
- sprintf((char *)&disc->udf_pvd[0]->volSetIdent[1], "%08lx%08lx%s",
- ((unsigned long int)mktime(tm))%0xFFFFFFFF, rnd%0xFFFFFFFF, &disc->udf_pvd[0]->volSetIdent[17]);
+ snprintf(uuid, sizeof(uuid), "%08lx%08lx", (unsigned long int)uuid_time, (unsigned long int)randu32());
+ memcpy(&disc->udf_pvd[0]->volSetIdent[1], uuid, 16);
disc->udf_pvd[0]->volIdent[31] = strlen((char *)disc->udf_pvd[0]->volIdent);
disc->udf_pvd[0]->volSetIdent[127] = strlen((char *)disc->udf_pvd[0]->volSetIdent);
@@ -142,14 +161,16 @@ void udf_init_disc(struct udf_disc *disc)
disc->head->tail = NULL;
}
-int udf_set_version(struct udf_disc *disc, int udf_rev)
+int udf_set_version(struct udf_disc *disc, uint16_t udf_rev)
{
struct logicalVolIntegrityDescImpUse *lvidiu;
uint16_t udf_rev_le16;
if (disc->udf_rev == udf_rev)
return 0;
- else if (udf_rev != 0x0102 &&
+ else if (
+ udf_rev != 0x0101 &&
+ udf_rev != 0x0102 &&
udf_rev != 0x0150 &&
udf_rev != 0x0200 &&
udf_rev != 0x0201 &&
@@ -172,7 +193,7 @@ int udf_set_version(struct udf_disc *disc, int udf_rev)
disc->flags &= ~FLAG_EFE;
strcpy((char *)disc->udf_pd[0]->partitionContents.ident, PD_PARTITION_CONTENTS_NSR02);
}
- else // 0x0102
+ else // 0x0102 and older
{
disc->flags &= ~FLAG_VAT;
disc->flags &= ~FLAG_EFE;
@@ -185,33 +206,24 @@ int udf_set_version(struct udf_disc *disc, int udf_rev)
memcpy(disc->udf_iuvd[0]->impIdent.identSuffix, &udf_rev_le16, sizeof(udf_rev_le16));
memcpy(disc->udf_stable[0]->sparingIdent.identSuffix, &udf_rev_le16, sizeof(udf_rev_le16));
lvidiu = query_lvidiu(disc);
- if (udf_rev == 0x0260)
- lvidiu->minUDFReadRev = cpu_to_le16(0x0250);
+ if (udf_rev < 0x0102)
+ {
+ /* The ImplementationUse area for the Logical Volume Integrity Descriptor
+ * prior to UDF 1.02 does not define UDF revisions, so clear these fields */
+ lvidiu->minUDFReadRev = cpu_to_le16(0);
+ lvidiu->minUDFWriteRev = cpu_to_le16(0);
+ lvidiu->maxUDFWriteRev = cpu_to_le16(0);
+ }
else
- lvidiu->minUDFReadRev = cpu_to_le16(udf_rev);
- lvidiu->minUDFWriteRev = cpu_to_le16(udf_rev);
- lvidiu->maxUDFWriteRev = cpu_to_le16(udf_rev);
- return 0;
-}
-
-void get_random_bytes(void *buffer, size_t count)
-{
- int fd;
- size_t i;
-
- fd = open("/dev/urandom", O_RDONLY);
- if (fd >= 0)
{
- if (read(fd, buffer, count) == (ssize_t)count)
- {
- close(fd);
- return;
- }
- close(fd);
+ if (udf_rev == 0x0260)
+ lvidiu->minUDFReadRev = cpu_to_le16(0x0250);
+ else
+ lvidiu->minUDFReadRev = cpu_to_le16(udf_rev);
+ lvidiu->minUDFWriteRev = cpu_to_le16(udf_rev);
+ lvidiu->maxUDFWriteRev = cpu_to_le16(udf_rev);
}
-
- for (i = 0; i < count; ++i)
- ((uint8_t *)buffer)[i] = rand() % 0xFF;
+ return 0;
}
void split_space(struct udf_disc *disc)
@@ -276,9 +288,12 @@ void split_space(struct udf_disc *disc)
}
accessType = le32_to_cpu(disc->udf_pd[0]->accessType);
- if ((accessType == PD_ACCESS_TYPE_OVERWRITABLE || accessType == PD_ACCESS_TYPE_REWRITABLE) && sizes[LVID_SIZE] * (size_t)disc->blocksize < 8192)
+ if ((accessType == PD_ACCESS_TYPE_OVERWRITABLE || accessType == PD_ACCESS_TYPE_REWRITABLE) && (uint64_t)sizes[LVID_SIZE] * disc->blocksize < 8192 && blocks > 257)
sizes[LVID_SIZE] = (8192 + disc->blocksize-1) / disc->blocksize;
+ if (sizes[VDS_SIZE] > 6 && blocks <= 257)
+ sizes[VDS_SIZE] = 6;
+
if (!(disc->flags & FLAG_VAT) && blocks < 770)
start = 0;
else
@@ -301,7 +316,7 @@ void split_space(struct udf_disc *disc)
}
set_extent(disc, RVDS, start, sizes[VDS_SIZE]);
}
- else
+ else if (blocks > 257)
{
if (blocks >= 3072)
start = find_next_extent_size(disc, (blocks-257+97)/32*32, USPACE, sizes[VDS_SIZE], offsets[VDS_SIZE]);
@@ -502,7 +517,7 @@ static void fill_mbr(struct udf_disc *disc, struct mbr *mbr, uint32_t start)
}
if (!mbr->disk_signature)
- get_random_bytes(&mbr->disk_signature, sizeof(mbr->disk_signature));
+ mbr->disk_signature = le32_to_cpu(randu32());
lba_blocks = ((uint64_t)disc->blocks * disc->blocksize + disc->blkssz - 1) / disc->blkssz;
@@ -608,13 +623,21 @@ void setup_anchor(struct udf_disc *disc)
mlen = ext->blocks * disc->blocksize;
ext = next_extent(disc->head, RVDS);
- if (!ext)
+ if (!ext && disc->blocks > 257)
{
fprintf(stderr, "%s: Error: Not enough blocks on device\n", appname);
exit(1);
}
- rloc = ext->start;
- rlen = ext->blocks * disc->blocksize;
+ if (disc->blocks > 257)
+ {
+ rloc = ext->start;
+ rlen = ext->blocks * disc->blocksize;
+ }
+ else
+ {
+ rloc = mloc;
+ rlen = mlen;
+ }
ext = next_extent(disc->head, ANCHOR);
if (!ext)
@@ -720,7 +743,7 @@ int setup_space(struct udf_disc *disc, struct udf_extent *pspace, uint32_t offse
if (pspace->blocks%8)
sbd->bitmap[nBytes-1] = 0xFF >> (8-(pspace->blocks%8));
clear_bits(sbd->bitmap, offset, (length + disc->blocksize - 1) / disc->blocksize);
- sbd->descTag = udf_query_tag(disc, TAG_IDENT_SBD, 1, desc->offset, desc->data, sizeof(struct spaceBitmapDesc));
+ sbd->descTag = udf_query_tag(disc, TAG_IDENT_SBD, 1, desc->offset, desc->data, 0, sizeof(struct spaceBitmapDesc));
}
else if (disc->flags & FLAG_SPACE_TABLE)
{
@@ -776,7 +799,7 @@ int setup_space(struct udf_disc *disc, struct udf_extent *pspace, uint32_t offse
use->icbTag.parentICBLocation.partitionReferenceNum = cpu_to_le16(0);
use->icbTag.fileType = ICBTAG_FILE_TYPE_USE;
use->icbTag.flags = cpu_to_le16(ICBTAG_FLAG_AD_SHORT);
- use->descTag = udf_query_tag(disc, TAG_IDENT_USE, 1, desc->offset, desc->data, sizeof(struct unallocSpaceEntry) + le32_to_cpu(use->lengthAllocDescs));
+ use->descTag = udf_query_tag(disc, TAG_IDENT_USE, 1, desc->offset, desc->data, 0, sizeof(struct unallocSpaceEntry) + le32_to_cpu(use->lengthAllocDescs));
if (disc->flags & FLAG_STRATEGY4096)
{
@@ -971,7 +994,7 @@ void setup_vds(struct udf_disc *disc)
stable[0] = next_extent(disc->head, STABLE);
sspace = next_extent(disc->head, SSPACE);
- if (!mvds || !rvds || !lvid)
+ if (!mvds || (!rvds && disc->blocks > 257) || !lvid)
{
fprintf(stderr, "%s: Error: Not enough blocks on device\n", appname);
exit(1);
@@ -993,8 +1016,7 @@ void setup_vds(struct udf_disc *disc)
setup_pd(disc, mvds, rvds, 2);
setup_usd(disc, mvds, rvds, 3);
setup_iuvd(disc, mvds, rvds, 4);
- if (mvds->blocks > 5)
- setup_td(disc, mvds, rvds, 5);
+ setup_td(disc, mvds, rvds, 5);
}
void setup_pvd(struct udf_disc *disc, struct udf_extent *mvds, struct udf_extent *rvds, uint32_t offset)
@@ -1007,6 +1029,8 @@ void setup_pvd(struct udf_disc *disc, struct udf_extent *mvds, struct udf_extent
desc->data->buffer = disc->udf_pvd[0];
disc->udf_pvd[0]->descTag = query_tag(disc, mvds, desc, 1);
+ if (!rvds)
+ return;
desc = set_desc(rvds, TAG_IDENT_PVD, offset, length, NULL);
memcpy(disc->udf_pvd[1] = desc->data->buffer, disc->udf_pvd[0], length);
disc->udf_pvd[1]->descTag = query_tag(disc, rvds, desc, 1);
@@ -1026,6 +1050,8 @@ void setup_lvd(struct udf_disc *disc, struct udf_extent *mvds, struct udf_extent
desc->data->buffer = disc->udf_lvd[0];
disc->udf_lvd[0]->descTag = query_tag(disc, mvds, desc, 1);
+ if (!rvds)
+ return;
desc = set_desc(rvds, TAG_IDENT_LVD, offset, length, NULL);
memcpy(disc->udf_lvd[1] = desc->data->buffer, disc->udf_lvd[0], length);
disc->udf_lvd[1]->descTag = query_tag(disc, rvds, desc, 1);
@@ -1057,6 +1083,8 @@ void setup_pd(struct udf_disc *disc, struct udf_extent *mvds, struct udf_extent
desc->data->buffer = disc->udf_pd[0];
disc->udf_pd[0]->descTag = query_tag(disc, mvds, desc, 1);
+ if (!rvds)
+ return;
desc = set_desc(rvds, TAG_IDENT_PD, offset, length, NULL);
memcpy(disc->udf_pd[1] = desc->data->buffer, disc->udf_pd[0], length);
disc->udf_pd[1]->descTag = query_tag(disc, rvds, desc, 1);
@@ -1086,6 +1114,8 @@ void setup_usd(struct udf_disc *disc, struct udf_extent *mvds, struct udf_extent
desc->data->buffer = disc->udf_usd[0];
disc->udf_usd[0]->descTag = query_tag(disc, mvds, desc, 1);
+ if (!rvds)
+ return;
desc = set_desc(rvds, TAG_IDENT_USD, offset, length, NULL);
memcpy(disc->udf_usd[1] = desc->data->buffer, disc->udf_usd[0], length);
disc->udf_usd[1]->descTag = query_tag(disc, rvds, desc, 1);
@@ -1103,6 +1133,8 @@ void setup_iuvd(struct udf_disc *disc, struct udf_extent *mvds, struct udf_exten
desc->data->buffer = disc->udf_iuvd[0];
disc->udf_iuvd[0]->descTag = query_tag(disc, mvds, desc, 1);
+ if (!rvds)
+ return;
desc = set_desc(rvds, TAG_IDENT_IUVD, offset, length, NULL);
memcpy(disc->udf_iuvd[1] = desc->data->buffer, disc->udf_iuvd[0], length);
disc->udf_iuvd[1]->descTag = query_tag(disc, rvds, desc, 1);
@@ -1118,6 +1150,8 @@ void setup_td(struct udf_disc *disc, struct udf_extent *mvds, struct udf_extent
desc->data->buffer = disc->udf_td[0];
disc->udf_td[0]->descTag = query_tag(disc, mvds, desc, 1);
+ if (!rvds)
+ return;
desc = set_desc(rvds, TAG_IDENT_TD, offset, length, NULL);
memcpy(disc->udf_td[1] = desc->data->buffer, disc->udf_td[0], length);
disc->udf_td[1]->descTag = query_tag(disc, rvds, desc, 1);
@@ -1211,21 +1245,32 @@ void setup_stable(struct udf_disc *disc, struct udf_extent *stable[4], struct ud
void setup_vat(struct udf_disc *disc, struct udf_extent *pspace)
{
- uint32_t offset = 0;
+ uint32_t offset;
struct udf_extent *anchor;
struct udf_desc *vtable;
struct udf_data *data;
- uint32_t len;
+ uint32_t len, i;
struct virtualAllocationTable15 *vat15;
struct virtualAllocationTable20 *vat20;
+ struct impUseExtAttr *ea_attr;
+ struct LVExtensionEA *ea_lv;
+ uint8_t buffer[(sizeof(*ea_attr)+sizeof(*ea_lv)+3)/4*4];
+ uint16_t checksum;
uint16_t udf_rev_le16;
+ uint32_t min_blocks;
+ uint32_t align;
+
+ /* Put VAT to the last sector correctly aligned */
+ align = disc->sizing[PSPACE_SIZE].align;
+ offset = pspace->tail->offset + (pspace->tail->length + disc->blocksize-1) / disc->blocksize;
+ offset = (offset + align) / align * align - 1;
if (disc->flags & FLAG_MIN_300_BLOCKS)
{
- // On optical discs one track has minimal size of 300 sectors, so put VAT to the last sector
- offset = pspace->tail->offset + (pspace->tail->length + disc->blocksize-1) / disc->blocksize;
- if (pspace->start + offset < 299)
- offset = 299 - pspace->start;
+ // On optical TAO discs one track has minimal size of 300 sectors
+ min_blocks = (300 + align) / align * align - 1;
+ if (pspace->start + offset < min_blocks)
+ offset = min_blocks - pspace->start;
}
if (disc->flags & FLAG_CLOSED)
@@ -1260,12 +1305,41 @@ void setup_vat(struct udf_disc *disc, struct udf_extent *pspace)
{
vtable = udf_create(disc, pspace, (const dchars *)"\x08" UDF_ID_ALLOC, strlen(UDF_ID_ALLOC)+1, offset, NULL, FID_FILE_CHAR_HIDDEN, ICBTAG_FILE_TYPE_UNDEF, 0);
disc->vat_entries--; // Remove VAT file itself from VAT table
+ udf_rev_le16 = cpu_to_le16(disc->udf_rev);
+ memset(&buffer, 0, sizeof(buffer));
+ ea_attr = (struct impUseExtAttr *)buffer;
+ ea_attr->attrType = cpu_to_le32(EXTATTR_IMP_USE);
+ ea_attr->attrSubtype = EXTATTR_SUBTYPE;
+ ea_attr->attrLength = cpu_to_le32(sizeof(buffer));
+ ea_attr->impUseLength = cpu_to_le32(sizeof(*ea_lv));
+ ea_attr->impIdent.identSuffix[2] = UDF_OS_CLASS_UNIX;
+ ea_attr->impIdent.identSuffix[3] = UDF_OS_ID_LINUX;
+ memcpy(ea_attr->impIdent.identSuffix, &udf_rev_le16, sizeof(udf_rev_le16));
+ strcpy((char *)ea_attr->impIdent.ident, UDF_ID_VAT_LVEXTENSION);
+ ea_lv = (struct LVExtensionEA *)&ea_attr->impUse[0];
+ checksum = 0;
+ for (i = 0; i < sizeof(*ea_attr); ++i)
+ checksum += ((uint8_t *)ea_attr)[i];
+ ea_lv->headerChecksum = cpu_to_le16(checksum);
+ if (disc->flags & FLAG_EFE)
+ {
+ struct extendedFileEntry *efe = (struct extendedFileEntry *)vtable->data->buffer;
+ ea_lv->verificationID = efe->uniqueID;
+ }
+ else
+ {
+ struct fileEntry *fe = (struct fileEntry *)vtable->data->buffer;
+ ea_lv->verificationID = fe->uniqueID;
+ }
+ ea_lv->numFiles = query_lvidiu(disc)->numFiles;
+ ea_lv->numDirs = query_lvidiu(disc)->numDirs;
+ memcpy(ea_lv->logicalVolIdent, disc->udf_lvd[0]->logicalVolIdent, 128);
+ insert_ea(disc, vtable, (struct genericFormat *)buffer, sizeof(buffer));
len = sizeof(struct virtualAllocationTable15);
data = alloc_data(disc->vat, disc->vat_entries * sizeof(uint32_t));
insert_data(disc, pspace, vtable, data);
data = alloc_data(&default_vat15, len);
vat15 = data->buffer;
- udf_rev_le16 = cpu_to_le16(disc->udf_rev);
memcpy(vat15->vatIdent.identSuffix, &udf_rev_le16, sizeof(udf_rev_le16));
insert_data(disc, pspace, vtable, data);
}
diff --git a/mkudffs/mkudffs.h b/mkudffs/mkudffs.h
index 510c8e0..b9adad3 100644
--- a/mkudffs/mkudffs.h
+++ b/mkudffs/mkudffs.h
@@ -1,8 +1,8 @@
/*
* mkudffs.h
*
- * 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
@@ -26,7 +26,6 @@
#include "ecma_167.h"
#include "osta_udf.h"
-#include "udf_endian.h"
#include "libudffs.h"
#define CS0 0x00000001
@@ -62,8 +61,7 @@ enum media_type {
extern char *udf_space_type_str[UDF_SPACE_TYPE_SIZE];
void udf_init_disc(struct udf_disc *);
-int udf_set_version(struct udf_disc *, int);
-void get_random_bytes(void *, size_t);
+int udf_set_version(struct udf_disc *, uint16_t);
void split_space(struct udf_disc *);
void dump_space(struct udf_disc *);
int write_disc(struct udf_disc *);
diff --git a/mkudffs/options.c b/mkudffs/options.c
index 67a71db..75be672 100644
--- a/mkudffs/options.c
+++ b/mkudffs/options.c
@@ -1,8 +1,8 @@
/*
* options.c
*
- * Copyright (c) 2001-2002 Ben Fennema <bfennema@falcon.csc.calpoly.edu>
- * Copyright (c) 2014-2017 Pali Rohár <pali.rohar@gmail.com>
+ * Copyright (c) 2001-2002 Ben Fennema
+ * Copyright (c) 2014-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 <getopt.h>
#include <ctype.h>
#include <errno.h>
@@ -85,7 +86,7 @@ void usage(void)
"\t--uuid=, -u UDF uuid, first 16 characters of Volume set identifier (default: random)\n"
"\t--blocksize=, -b Size of blocks in bytes (512, 1024, 2048, 4096, 8192, 16384, 32768; default: detect)\n"
"\t--media-type=, -m Media type (hd, dvd, dvdram, dvdrw, dvdr, worm, mo, cdrw, cdr, cd, bdr; default: hd)\n"
- "\t--udfrev=, -r UDF revision (1.02, 1.50, 2.00, 2.01, 2.50, 2.60; default: 2.01)\n"
+ "\t--udfrev=, -r UDF revision (1.01, 1.02, 1.50, 2.00, 2.01, 2.50, 2.60; default: 2.01)\n"
"\t--no-write, -n Not really, do not write to device, just simulate\n"
"\t--new-file Create new image file, fail if already exists\n"
"\t--lvid= Logical Volume Identifier (default: LinuxUDF)\n"
@@ -100,7 +101,7 @@ void usage(void)
"\t--strategy= Allocation strategy to use (4, 4096; default: based on media type)\n"
"\t--spartable Use Sparing Table (default: based on media type) and set its count (1 - 4; default: 2)\n"
"\t--sparspace= Number of entries in Sparing Table (default: 1024, but based on media type)\n"
- "\t--packetlen= Packet length in number of blocks for Sparing Table (default: based on media type)\n"
+ "\t--packetlen= Packet length in number of blocks used for alignment (default: based on media type)\n"
"\t--vat Use Virtual Allocation Table (default: based on media type)\n"
"\t--closed Close disc with Virtual Allocation Table (default: do not close)\n"
"\t--space= Space (freedbitmap, freedtable, unallocbitmap, unalloctable; default: unallocbitmap)\n"
@@ -114,26 +115,16 @@ void usage(void)
exit(1);
}
-static unsigned long int strtoul_safe(const char *str, int base, int *failed)
-{
- char *endptr = NULL;
- unsigned long int ret;
- errno = 0;
- ret = strtoul(str, &endptr, base);
- *failed = (!*str || *endptr || errno) ? 1 : 0;
- return ret;
-}
-
void parse_args(int argc, char *argv[], struct udf_disc *disc, char **device, int *create_new_file, int *blocksize, int *media_ptr)
{
int retval;
int i;
int media = MEDIA_TYPE_NONE;
- uint16_t packetlen = 0;
- unsigned long int blocks = 0;
- int rev = 0;
int use_sparable = 0;
- unsigned long int sparspace = 0;
+ uint16_t rev = 0;
+ uint32_t spartable = 2;
+ uint32_t sparspace = 0;
+ uint16_t packetlen = 0;
int failed;
while ((retval = getopt_long(argc, argv, "l:u:b:m:r:nh", long_options, NULL)) != EOF)
@@ -146,7 +137,7 @@ void parse_args(int argc, char *argv[], struct udf_disc *disc, char **device, in
break;
case OPT_BLK_SIZE:
case 'b':
- disc->blocksize = strtoul_safe(optarg, 0, &failed);
+ disc->blocksize = strtou32(optarg, 0, &failed);
if (failed || disc->blocksize < 512 || disc->blocksize > 32768 || (disc->blocksize & (disc->blocksize - 1)))
{
fprintf(stderr, "%s: Error: Invalid value for option --blocksize\n", appname);
@@ -161,16 +152,14 @@ void parse_args(int argc, char *argv[], struct udf_disc *disc, char **device, in
unsigned char maj = 0;
unsigned char min = 0;
int len = 0;
- if (sscanf(optarg, "%hhx.%hhx%n", &maj, &min, &len) >= 2 && !optarg[len])
+ if (sscanf(optarg, "%*[0-9].%*[0-9]%n", &len) >= 0 && !optarg[len] && sscanf(optarg, "%hhx.%hhx%n", &maj, &min, &len) >= 2 && !optarg[len])
{
rev = (maj << 8) | min;
}
else
{
- unsigned long int rev_opt = strtoul_safe(optarg, 16, &failed);
- if (!failed && rev_opt < INT_MAX)
- rev = rev_opt;
- else
+ rev = strtou16(optarg, 16, &failed);
+ if (failed)
rev = 0;
}
if (!rev || udf_set_version(disc, rev))
@@ -418,40 +407,42 @@ void parse_args(int argc, char *argv[], struct udf_disc *disc, char **device, in
}
case OPT_UID:
{
- unsigned long int uid = strtoul_safe(optarg, 0, &failed);
if (strcmp(optarg, "-1") == 0)
{
- uid = UINT32_MAX;
- failed = 0;
+ disc->uid = UINT32_MAX;
}
- if (failed || uid > UINT32_MAX)
+ else
{
- fprintf(stderr, "%s: Error: Invalid value for option --uid\n", appname);
- exit(1);
+ disc->uid = strtou32(optarg, 0, &failed);
+ if (failed)
+ {
+ fprintf(stderr, "%s: Error: Invalid value for option --uid\n", appname);
+ exit(1);
+ }
}
- disc->uid = uid;
break;
}
case OPT_GID:
{
- unsigned long int gid = strtoul_safe(optarg, 0, &failed);
if (strcmp(optarg, "-1") == 0)
{
- gid = UINT32_MAX;
- failed = 0;
+ disc->gid = UINT32_MAX;
}
- if (failed || gid > UINT32_MAX)
+ else
{
- fprintf(stderr, "%s: Error: Invalid value for option --gid\n", appname);
- exit(1);
+ disc->gid = strtou32(optarg, 0, &failed);
+ if (failed)
+ {
+ fprintf(stderr, "%s: Error: Invalid value for option --gid\n", appname);
+ exit(1);
+ }
}
- disc->gid = gid;
break;
}
case OPT_MODE:
{
- unsigned long int mode = strtoul_safe(optarg, 8, &failed);
- if (failed || mode > UINT16_MAX || (mode & ~(S_IRWXU|S_IRWXG|S_IRWXO)))
+ uint16_t mode = strtou16(optarg, 8, &failed);
+ if (failed || (mode & ~(S_IRWXU|S_IRWXG|S_IRWXO)))
{
fprintf(stderr, "%s: Error: Invalid value for option --mode\n", appname);
exit(1);
@@ -477,25 +468,23 @@ void parse_args(int argc, char *argv[], struct udf_disc *disc, char **device, in
}
case OPT_STRATEGY:
{
- unsigned long int strategy = strtoul_safe(optarg, 0, &failed);
- if (failed || (strategy != 4 && strategy != 4096))
+ if (strcmp(optarg, "4096") == 0)
+ disc->flags |= FLAG_STRATEGY4096;
+ else if (strcmp(optarg, "4") == 0)
+ disc->flags &= ~FLAG_STRATEGY4096;
+ else
{
fprintf(stderr, "%s: Error: Invalid value for option --strategy\n", appname);
exit(1);
}
- if (strategy == 4096)
- disc->flags |= FLAG_STRATEGY4096;
- else
- disc->flags &= ~FLAG_STRATEGY4096;
break;
}
case OPT_SPARTABLE:
{
- unsigned long int spartable = 2;
if (optarg)
{
- spartable = strtoul_safe(optarg, 0, &failed);
- if (failed || spartable > 4)
+ spartable = strtou32(optarg, 0, &failed);
+ if (failed || spartable == 0 || spartable > 4)
{
fprintf(stderr, "%s: Error: Invalid value for option --spartable\n", appname);
exit(1);
@@ -506,7 +495,6 @@ void parse_args(int argc, char *argv[], struct udf_disc *disc, char **device, in
fprintf(stderr, "%s: Error: Cannot use Sparing Table when VAT is enabled\n", appname);
exit(1);
}
- add_type2_sparable_partition(disc, 0, spartable, packetlen);
use_sparable = 1;
break;
}
@@ -517,8 +505,8 @@ void parse_args(int argc, char *argv[], struct udf_disc *disc, char **device, in
fprintf(stderr, "%s: Error: Option --spartable must be specified before option --sparspace\n", appname);
exit(1);
}
- sparspace = strtoul_safe(optarg, 0, &failed);
- if (failed || sparspace > UINT32_MAX)
+ sparspace = strtou32(optarg, 0, &failed);
+ if (failed)
{
fprintf(stderr, "%s: Error: Invalid value for option --sparspace\n", appname);
exit(1);
@@ -527,21 +515,22 @@ void parse_args(int argc, char *argv[], struct udf_disc *disc, char **device, in
}
case OPT_PACKETLEN:
{
- struct sparablePartitionMap *spm;
- unsigned long int packetlen_opt = strtoul_safe(optarg, 0, &failed);
- if (failed || packetlen_opt > UINT16_MAX)
+ packetlen = strtou16(optarg, 0, &failed);
+ if (failed || packetlen == 0)
{
fprintf(stderr, "%s: Error: Invalid value for option --packetlen\n", appname);
exit(1);
}
- packetlen = packetlen_opt;
- if ((spm = find_type2_sparable_partition(disc, 0)))
- spm->packetLength = cpu_to_le16(packetlen);
break;
}
case OPT_MEDIA_TYPE:
case 'm':
{
+ if (media != MEDIA_TYPE_NONE)
+ {
+ fprintf(stderr, "%s: Error: Option --media-type was specified more times\n", appname);
+ exit(1);
+ }
if (rev)
{
fprintf(stderr, "%s: Error: Option --media-type must be specified before option --udfrev\n", appname);
@@ -552,60 +541,59 @@ void parse_args(int argc, char *argv[], struct udf_disc *disc, char **device, in
fprintf(stderr, "%s: Error: Option --media-type must be specified before option --packetlen\n", appname);
exit(1);
}
- if (media != MEDIA_TYPE_NONE)
- {
- fprintf(stderr, "%s: Error: Option --media-type was specified more times\n", appname);
- exit(1);
- }
if (!strcmp(optarg, "hd"))
{
disc->udf_pd[0]->accessType = cpu_to_le32(PD_ACCESS_TYPE_OVERWRITABLE);
media = MEDIA_TYPE_HD;
+ packetlen = 1;
}
else if (!strcmp(optarg, "dvd"))
{
disc->udf_pd[0]->accessType = cpu_to_le32(PD_ACCESS_TYPE_READ_ONLY);
media = MEDIA_TYPE_DVD;
+ packetlen = 16;
}
else if (!strcmp(optarg, "dvdram"))
{
disc->udf_pd[0]->accessType = cpu_to_le32(PD_ACCESS_TYPE_OVERWRITABLE);
media = MEDIA_TYPE_DVDRAM;
+ packetlen = 16;
}
else if (!strcmp(optarg, "dvdrw"))
{
- struct sparablePartitionMap *spm;
disc->udf_pd[0]->accessType = cpu_to_le32(PD_ACCESS_TYPE_OVERWRITABLE);
media = MEDIA_TYPE_DVDRW;
use_sparable = 1;
packetlen = 16;
- if ((spm = find_type2_sparable_partition(disc, 0)))
- spm->packetLength = cpu_to_le16(packetlen);
}
else if (!strcmp(optarg, "dvdr"))
{
disc->udf_pd[0]->accessType = cpu_to_le32(PD_ACCESS_TYPE_WRITE_ONCE);
media = MEDIA_TYPE_DVDR;
- disc->flags |= FLAG_VAT | FLAG_MIN_300_BLOCKS;
+ disc->flags |= FLAG_VAT;
disc->flags &= ~FLAG_CLOSED;
+ packetlen = 16;
}
else if (!strcmp(optarg, "worm"))
{
disc->udf_pd[0]->accessType = cpu_to_le32(PD_ACCESS_TYPE_WRITE_ONCE);
media = MEDIA_TYPE_WORM;
disc->flags |= (FLAG_STRATEGY4096 | FLAG_BLANK_TERMINAL);
+ packetlen = 1;
}
else if (!strcmp(optarg, "mo"))
{
disc->udf_pd[0]->accessType = cpu_to_le32(PD_ACCESS_TYPE_REWRITABLE);
media = MEDIA_TYPE_MO;
disc->flags |= (FLAG_STRATEGY4096 | FLAG_BLANK_TERMINAL);
+ packetlen = 1;
}
else if (!strcmp(optarg, "cdrw"))
{
disc->udf_pd[0]->accessType = cpu_to_le32(PD_ACCESS_TYPE_REWRITABLE);
media = MEDIA_TYPE_CDRW;
use_sparable = 1;
+ packetlen = 32;
}
else if (!strcmp(optarg, "cdr"))
{
@@ -613,19 +601,22 @@ void parse_args(int argc, char *argv[], struct udf_disc *disc, char **device, in
media = MEDIA_TYPE_CDR;
disc->flags |= FLAG_VAT | FLAG_MIN_300_BLOCKS;
disc->flags &= ~FLAG_CLOSED;
+ packetlen = 32;
}
else if (!strcmp(optarg, "cd"))
{
disc->udf_pd[0]->accessType = cpu_to_le32(PD_ACCESS_TYPE_READ_ONLY);
media = MEDIA_TYPE_CD;
+ packetlen = 32;
}
else if (!strcmp(optarg, "bdr"))
{
disc->udf_pd[0]->accessType = cpu_to_le32(PD_ACCESS_TYPE_WRITE_ONCE);
media = MEDIA_TYPE_BDR;
- disc->flags |= FLAG_VAT | FLAG_MIN_300_BLOCKS;
+ disc->flags |= FLAG_VAT;
disc->flags &= ~FLAG_CLOSED;
udf_set_version(disc, 0x0250);
+ packetlen = 32;
}
else
{
@@ -685,46 +676,45 @@ void parse_args(int argc, char *argv[], struct udf_disc *disc, char **device, in
optind ++;
if (optind < argc)
{
- blocks = strtoul_safe(argv[optind++], 0, &failed);
- if (failed || blocks > UINT32_MAX)
+ disc->blocks = strtou32(argv[optind++], 0, &failed);
+ if (failed)
{
fprintf(stderr, "%s: Error: Invalid value for block-count\n", appname);
exit(1);
}
- disc->blocks = blocks;
}
if (optind < argc)
usage();
- if (packetlen && !use_sparable)
+ /* TODO: autodetection */
+ if (media == MEDIA_TYPE_NONE)
{
- fprintf(stderr, "%s: Error: Option --packetlen cannot be used without Sparing Table\n", appname);
- exit(1);
+ media = MEDIA_TYPE_HD;
+ packetlen = 1;
}
- if (le32_to_cpu(disc->udf_lvd[0]->numPartitionMaps) == 0)
+ if (disc->flags & FLAG_VAT)
{
- if (disc->flags & FLAG_VAT)
+ if (disc->udf_rev < 0x0150)
{
- if (disc->udf_rev < 0x0150)
- {
- fprintf(stderr, "%s: Error: At least UDF revision 1.50 is needed for VAT\n", appname);
- exit(1);
- }
- add_type1_partition(disc, 0);
- add_type2_virtual_partition(disc, 0);
+ fprintf(stderr, "%s: Error: At least UDF revision 1.50 is needed for VAT\n", appname);
+ exit(1);
}
- else if (use_sparable)
+ add_type1_partition(disc, 0);
+ add_type2_virtual_partition(disc, 0);
+ }
+ else if (use_sparable)
+ {
+ if (disc->udf_rev < 0x0150)
{
- if (disc->udf_rev < 0x0150)
- {
- fprintf(stderr, "%s: Error: At least UDF revision 1.50 is needed for Sparing Table\n", appname);
- exit(1);
- }
- add_type2_sparable_partition(disc, 0, 2, packetlen);
+ fprintf(stderr, "%s: Error: At least UDF revision 1.50 is needed for Sparing Table\n", appname);
+ exit(1);
}
- else
- add_type1_partition(disc, 0);
+ add_type2_sparable_partition(disc, 0, spartable, packetlen);
+ }
+ else
+ {
+ add_type1_partition(disc, 0);
}
/* TODO: UDF 2.50+ require for non-VAT disks Metadata partition which mkudffs cannot create yet */
@@ -749,12 +739,9 @@ void parse_args(int argc, char *argv[], struct udf_disc *disc, char **device, in
exit(1);
}
- /* TODO: autodetection */
- if (media == MEDIA_TYPE_NONE)
- media = MEDIA_TYPE_HD;
-
for (i=0; i<UDF_ALLOC_TYPE_SIZE; i++)
{
+ disc->sizing[i].align = packetlen;
if (disc->sizing[i].denomSize == 0)
disc->sizing[i] = default_sizing[default_media[media]][i];
}
@@ -766,11 +753,6 @@ void parse_args(int argc, char *argv[], struct udf_disc *disc, char **device, in
disc->sizing[SSPACE_SIZE].minSize = sparspace;
disc->sizing[STABLE_SIZE].minSize = 0; // recalculation is implemented in split_space()
}
- if (!packetlen)
- packetlen = le16_to_cpu(default_sparmap.packetLength);
- disc->sizing[PSPACE_SIZE].align = packetlen;
- disc->sizing[SSPACE_SIZE].align = packetlen;
- disc->sizing[STABLE_SIZE].align = packetlen;
if (disc->sizing[SSPACE_SIZE].minSize == 0)
disc->sizing[SSPACE_SIZE].minSize = 1024;
}
diff --git a/mkudffs/options.h b/mkudffs/options.h
index 883f5be..a40f1e6 100644
--- a/mkudffs/options.h
+++ b/mkudffs/options.h
@@ -1,7 +1,7 @@
/*
* options.h
*
- * Copyright (c) 2001-2002 Ben Fennema <bfennema@falcon.csc.calpoly.edu>
+ * Copyright (c) 2001-2002 Ben Fennema
* Copyright (c) 2014-2017 Pali Rohár <pali.rohar@gmail.com>
* All rights reserved.
*