Module Name:    src
Committed By:   reinoud
Date:           Thu Jul 18 12:44:21 UTC 2013

Modified Files:
        src/sbin/newfs_udf: Makefile newfs_udf.c
Added Files:
        src/sbin/newfs_udf: newfs_udf.h udf_write.c udf_write.h

Log Message:
Initial split up for making newfs_udf(8) routines suitable for makefs_udf(8)


To generate a diff of this commit:
cvs rdiff -u -r1.3 -r1.4 src/sbin/newfs_udf/Makefile
cvs rdiff -u -r1.13 -r1.14 src/sbin/newfs_udf/newfs_udf.c
cvs rdiff -u -r0 -r1.1 src/sbin/newfs_udf/newfs_udf.h \
    src/sbin/newfs_udf/udf_write.c src/sbin/newfs_udf/udf_write.h

Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.

Modified files:

Index: src/sbin/newfs_udf/Makefile
diff -u src/sbin/newfs_udf/Makefile:1.3 src/sbin/newfs_udf/Makefile:1.4
--- src/sbin/newfs_udf/Makefile:1.3	Sat Apr 11 07:58:13 2009
+++ src/sbin/newfs_udf/Makefile	Thu Jul 18 12:44:21 2013
@@ -1,10 +1,10 @@
-# $NetBSD: Makefile,v 1.3 2009/04/11 07:58:13 lukem Exp $
+# $NetBSD: Makefile,v 1.4 2013/07/18 12:44:21 reinoud Exp $
 
 .include <bsd.own.mk>
 
 PROG=	newfs_udf
 MAN=	newfs_udf.8
-SRCS=	newfs_udf.c udf_create.c udf_osta.c fattr.c
+SRCS=	newfs_udf.c udf_create.c udf_write.c udf_osta.c fattr.c
 
 MOUNT=  ${NETBSDSRCDIR}/sbin/mount
 KUDF=	${NETBSDSRCDIR}/sys/fs/udf

Index: src/sbin/newfs_udf/newfs_udf.c
diff -u src/sbin/newfs_udf/newfs_udf.c:1.13 src/sbin/newfs_udf/newfs_udf.c:1.14
--- src/sbin/newfs_udf/newfs_udf.c:1.13	Tue Jul  2 14:59:01 2013
+++ src/sbin/newfs_udf/newfs_udf.c	Thu Jul 18 12:44:21 2013
@@ -1,4 +1,4 @@
-/* $NetBSD: newfs_udf.c,v 1.13 2013/07/02 14:59:01 reinoud Exp $ */
+/* $NetBSD: newfs_udf.c,v 1.14 2013/07/18 12:44:21 reinoud Exp $ */
 
 /*
  * Copyright (c) 2006, 2008, 2013 Reinoud Zandijk
@@ -65,25 +65,23 @@
 
 #include "mountprog.h"
 #include "udf_create.h"
-
-/* general settings */
-#define UDF_512_TRACK	0	/* NOT recommended */
-#define UDF_META_PERC  20	/* picked */
-
+#include "udf_write.h"
+#include "newfs_udf.h"
 
 /* prototypes */
 int newfs_udf(int argc, char **argv);
 static void usage(void) __attribute__((__noreturn__));
 
-int udf_derive_format(int req_en, int req_dis, int force);
-int udf_proces_names(void);
-int udf_do_newfs(void);
-
-/* Identifying myself */
-#define APP_NAME		"*NetBSD newfs"
-#define APP_VERSION_MAIN	0
-#define APP_VERSION_SUB		3
-#define IMPL_NAME		"*NetBSD userland UDF"
+
+/* queue for temporary storage of sectors to be written out */
+struct wrsect {
+	uint32_t  sectornr;
+	uint8_t	 *sector_data;
+	TAILQ_ENTRY(wrsect) next;
+};
+
+/* write queue and track blocking skew */
+TAILQ_HEAD(wrsect_list, wrsect) write_queue;
 
 
 /* global variables describing disc and format requests */
@@ -102,29 +100,13 @@ int	 meta_perc = UDF_META_PERC;
 float	 meta_fract = (float) UDF_META_PERC / 100.0;
 
 
-/* shared structure between udf_create.c users */
-struct udf_create_context context;
-struct udf_disclayout     layout;
-
-
-/* queue for temporary storage of sectors to be written out */
-struct wrsect {
-	uint32_t  sectornr;
-	uint8_t	 *sector_data;
-	TAILQ_ENTRY(wrsect) next;
-};
-
-/* write queue and track blocking skew */
-TAILQ_HEAD(wrsect_list, wrsect) write_queue;
-
-
 /* --------------------------------------------------------------------- */
 
 /*
  * write queue implementation
  */
 
-static int
+int
 udf_write_sector(void *sector, uint32_t location)
 {
 	struct wrsect *pos, *seekpos;
@@ -167,7 +149,7 @@ udf_write_sector(void *sector, uint32_t 
  * XXX support for growing vnd?
  */
 
-static int
+int
 writeout_write_queue(void)
 {
 	struct wrsect *pos;
@@ -357,7 +339,7 @@ udf_update_discinfo(struct mmc_discinfo 
 }
 
 
-static int
+int
 udf_update_trackinfo(struct mmc_discinfo *di, struct mmc_trackinfo *ti)
 {
 	int error, class;
@@ -447,276 +429,6 @@ udf_synchronise_caches(void)
 /* --------------------------------------------------------------------- */
 
 static int
-udf_write_dscr_phys(union dscrptr *dscr, uint32_t location,
-	uint32_t sects)
-{
-	uint32_t phys, cnt;
-	uint8_t *bpos;
-	int error;
-
-	dscr->tag.tag_loc = udf_rw32(location);
-	(void) udf_validate_tag_and_crc_sums(dscr);
-
-	for (cnt = 0; cnt < sects; cnt++) {
-		bpos  = (uint8_t *) dscr;
-		bpos += context.sector_size * cnt;
-
-		phys = location + cnt;
-		error = udf_write_sector(bpos, phys);
-		if (error)
-			return error;
-	}
-	return 0;
-}
-
-
-static int
-udf_write_dscr_virt(union dscrptr *dscr, uint32_t location, uint32_t vpart,
-	uint32_t sects)
-{
-	struct file_entry *fe;
-	struct extfile_entry *efe;
-	struct extattrhdr_desc *extattrhdr;
-	uint32_t phys, cnt;
-	uint8_t *bpos;
-	int error;
-
-	extattrhdr = NULL;
-	if (udf_rw16(dscr->tag.id) == TAGID_FENTRY) {
-		fe = (struct file_entry *) dscr;
-		if (udf_rw32(fe->l_ea) > 0)
-			extattrhdr = (struct extattrhdr_desc *) fe->data;
-	}
-	if (udf_rw16(dscr->tag.id) == TAGID_EXTFENTRY) {
-		efe = (struct extfile_entry *) dscr;
-		if (udf_rw32(efe->l_ea) > 0)
-			extattrhdr = (struct extattrhdr_desc *) efe->data;
-	}
-	if (extattrhdr) {
-		extattrhdr->tag.tag_loc = udf_rw32(location);
-		udf_validate_tag_and_crc_sums((union dscrptr *) extattrhdr);
-	}
-
-	dscr->tag.tag_loc = udf_rw32(location);
-	udf_validate_tag_and_crc_sums(dscr);
-
-	for (cnt = 0; cnt < sects; cnt++) {
-		bpos  = (uint8_t *) dscr;
-		bpos += context.sector_size * cnt;
-
-		/* NOTE linear mapping assumed in the ranges used */
-		phys = context.vtop_offset[vpart] + location + cnt;
-
-		error = udf_write_sector(bpos, phys);
-		if (error)
-			return error;
-	}
-	return 0;
-}
-
-/* --------------------------------------------------------------------- */
-
-/*
- * udf_derive_format derives the format_flags from the disc's mmc_discinfo.
- * The resulting flags uniquely define a disc format. Note there are at least
- * 7 distinct format types defined in UDF.
- */
-
-#define UDF_VERSION(a) \
-	(((a) == 0x100) || ((a) == 0x102) || ((a) == 0x150) || ((a) == 0x200) || \
-	 ((a) == 0x201) || ((a) == 0x250) || ((a) == 0x260))
-
-int
-udf_derive_format(int req_enable, int req_disable, int force)
-{
-	/* disc writability, formatted, appendable */
-	if ((mmc_discinfo.mmc_cur & MMC_CAP_RECORDABLE) == 0) {
-		(void)printf("Can't newfs readonly device\n");
-		return EROFS;
-	}
-	if (mmc_discinfo.mmc_cur & MMC_CAP_SEQUENTIAL) {
-		/* sequentials need sessions appended */
-		if (mmc_discinfo.disc_state == MMC_STATE_CLOSED) {
-			(void)printf("Can't append session to a closed disc\n");
-			return EROFS;
-		}
-		if ((mmc_discinfo.disc_state != MMC_STATE_EMPTY) && !force) {
-			(void)printf("Disc not empty! Use -F to force "
-			    "initialisation\n");
-			return EROFS;
-		}
-	} else {
-		/* check if disc (being) formatted or has been started on */
-		if (mmc_discinfo.disc_state == MMC_STATE_EMPTY) {
-			(void)printf("Disc is not formatted\n");
-			return EROFS;
-		}
-	}
-
-	/* determine UDF format */
-	format_flags = 0;
-	if (mmc_discinfo.mmc_cur & MMC_CAP_REWRITABLE) {
-		/* all rewritable media */
-		format_flags |= FORMAT_REWRITABLE;
-		if (context.min_udf >= 0x0250) {
-			/* standard dictates meta as default */
-			format_flags |= FORMAT_META;
-		}
-
-		if ((mmc_discinfo.mmc_cur & MMC_CAP_HW_DEFECTFREE) == 0) {
-			/* sparables for defect management */
-			if (context.min_udf >= 0x150)
-				format_flags |= FORMAT_SPARABLE;
-		}
-	} else {
-		/* all once recordable media */
-		format_flags |= FORMAT_WRITEONCE;
-		if (mmc_discinfo.mmc_cur & MMC_CAP_SEQUENTIAL) {
-			format_flags |= FORMAT_SEQUENTIAL;
-
-			if (mmc_discinfo.mmc_cur & MMC_CAP_PSEUDOOVERWRITE) {
-				/* logical overwritable */
-				format_flags |= FORMAT_LOW;
-			} else {
-				/* have to use VAT for overwriting */
-				format_flags |= FORMAT_VAT;
-			}
-		} else {
-			/* rare WORM devices, but BluRay has one, strat4096 */
-			format_flags |= FORMAT_WORM;
-		}
-	}
-
-	/* enable/disable requests */
-	if (req_disable & FORMAT_META) {
-		format_flags &= ~(FORMAT_META | FORMAT_LOW);
-		req_disable  &= ~FORMAT_META;
-	}
-	if (req_disable || req_enable) {
-		(void)printf("Internal error\n");
-		(void)printf("\tunrecognised enable/disable req.\n");
-		return EIO;
-	}
-	if ((format_flags & FORMAT_VAT) & UDF_512_TRACK)
-		format_flags |= FORMAT_TRACK512;
-
-	/* determine partition/media access type */
-	media_accesstype = UDF_ACCESSTYPE_NOT_SPECIFIED;
-	if (mmc_discinfo.mmc_cur & MMC_CAP_REWRITABLE) {
-		media_accesstype = UDF_ACCESSTYPE_OVERWRITABLE;
-		if (mmc_discinfo.mmc_cur & MMC_CAP_ERASABLE)
-			media_accesstype = UDF_ACCESSTYPE_REWRITEABLE;
-	} else {
-		/* all once recordable media */
-		media_accesstype = UDF_ACCESSTYPE_WRITE_ONCE;
-	}
-	if (mmc_discinfo.mmc_cur & MMC_CAP_PSEUDOOVERWRITE)
-		media_accesstype = UDF_ACCESSTYPE_PSEUDO_OVERWITE;
-
-	/* adjust minimum version limits */
-	if (format_flags & FORMAT_VAT)
-		context.min_udf = MAX(context.min_udf, 0x0150);
-	if (format_flags & FORMAT_SPARABLE)
-		context.min_udf = MAX(context.min_udf, 0x0150);
-	if (format_flags & FORMAT_META)
-		context.min_udf = MAX(context.min_udf, 0x0250);
-	if (format_flags & FORMAT_LOW)
-		context.min_udf = MAX(context.min_udf, 0x0260);
-
-	/* adjust maximum version limits not to tease or break things */
-	if (!(format_flags & (FORMAT_META | FORMAT_LOW)) &&
-	    (context.max_udf > 0x200))
-		context.max_udf = 0x201;
-
-	if ((format_flags & (FORMAT_VAT | FORMAT_SPARABLE)) == 0)
-		if (context.max_udf <= 0x150)
-			context.min_udf = 0x102;
-
-	/* limit Ecma 167 descriptor if possible/needed */
-	context.dscrver = 3;
-	if ((context.min_udf < 0x200) || (context.max_udf < 0x200)) {
-		context.dscrver = 2;
-		context.max_udf = 0x150;	/* last version < 0x200 */
-	}
-
-	/* is it possible ? */
-	if (context.min_udf > context.max_udf) {
-		(void)printf("Initialisation prohibited by specified maximum "
-		    "UDF version 0x%04x. Minimum version required 0x%04x\n",
-		    context.max_udf, context.min_udf);
-		return EPERM;
-	}
-
-	if (!UDF_VERSION(context.min_udf) || !UDF_VERSION(context.max_udf)) {
-		printf("Choose UDF version numbers from "
-			"0x102, 0x150, 0x200, 0x201, 0x250 and 0x260\n");
-		printf("Default version is 0x201\n");
-		return EPERM;
-	}
-
-	return 0;
-}
-
-#undef UDF_VERSION
-
-
-/* --------------------------------------------------------------------- */
-
-int
-udf_proces_names(void)
-{
-	uint32_t primary_nr;
-	uint64_t volset_nr;
-
-	if (context.logvol_name == NULL)
-		context.logvol_name = strdup("anonymous");
-	if (context.primary_name == NULL) {
-		if (mmc_discinfo.disc_flags & MMC_DFLAGS_DISCIDVALID) {
-			primary_nr = mmc_discinfo.disc_id;
-		} else {
-			primary_nr = (uint32_t) random();
-		}
-		context.primary_name = calloc(32, 1);
-		sprintf(context.primary_name, "%08"PRIx32, primary_nr);
-	}
-	if (context.volset_name == NULL) {
-		if (mmc_discinfo.disc_flags & MMC_DFLAGS_BARCODEVALID) {
-			volset_nr = mmc_discinfo.disc_barcode;
-		} else {
-			volset_nr  =  (uint32_t) random();
-			volset_nr |= ((uint64_t) random()) << 32;
-		}
-		context.volset_name = calloc(128,1);
-		sprintf(context.volset_name, "%016"PRIx64, volset_nr);
-	}
-	if (context.fileset_name == NULL)
-		context.fileset_name = strdup("anonymous");
-
-	/* check passed/created identifiers */
-	if (strlen(context.logvol_name)  > 128) {
-		(void)printf("Logical volume name too long\n");
-		return EINVAL;
-	}
-	if (strlen(context.primary_name) >  32) {
-		(void)printf("Primary volume name too long\n");
-		return EINVAL;
-	}
-	if (strlen(context.volset_name)  > 128) {
-		(void)printf("Volume set name too long\n");
-		return EINVAL;
-	}
-	if (strlen(context.fileset_name) > 32) {
-		(void)printf("Fileset name too long\n");
-		return EINVAL;
-	}
-
-	/* signal all OK */
-	return 0;
-}
-
-/* --------------------------------------------------------------------- */
-
-static int
 udf_prepare_disc(void)
 {
 	struct mmc_trackinfo ti;
@@ -833,7 +545,7 @@ udf_prepare_disc(void)
 
 /* --------------------------------------------------------------------- */
 
-static int
+int
 udf_surface_check(void)
 {
 	uint32_t loc, block_bytes;
@@ -901,498 +613,28 @@ udf_surface_check(void)
 	return 0;
 }
 
-/* --------------------------------------------------------------------- */
-
-static int
-udf_write_iso9660_vrs(void)
-{
-	struct vrs_desc *iso9660_vrs_desc;
-	uint32_t pos;
-	int error, cnt, dpos;
-
-	/* create ISO/Ecma-167 identification descriptors */
-	if ((iso9660_vrs_desc = calloc(1, context.sector_size)) == NULL)
-		return ENOMEM;
-
-	/*
-	 * All UDF formats should have their ISO/Ecma-167 descriptors written
-	 * except when not possible due to track reservation in the case of
-	 * VAT
-	 */
-	if ((format_flags & FORMAT_TRACK512) == 0) {
-		dpos = (2048 + context.sector_size - 1) / context.sector_size;
-
-		/* wipe at least 6 times 2048 byte `sectors' */
-		for (cnt = 0; cnt < 6 *dpos; cnt++) {
-			pos = layout.iso9660_vrs + cnt;
-			if ((error = udf_write_sector(iso9660_vrs_desc, pos))) {
-				free(iso9660_vrs_desc);
-				return error;
-			}
-		}
-
-		/* common VRS fields in all written out ISO descriptors */
-		iso9660_vrs_desc->struct_type = 0;
-		iso9660_vrs_desc->version     = 1;
-		pos = layout.iso9660_vrs;
-
-		/* BEA01, NSR[23], TEA01 */
-		memcpy(iso9660_vrs_desc->identifier, "BEA01", 5);
-		if ((error = udf_write_sector(iso9660_vrs_desc, pos))) {
-			free(iso9660_vrs_desc);
-			return error;
-		}
-		pos += dpos;
-
-		if (context.dscrver == 2)
-			memcpy(iso9660_vrs_desc->identifier, "NSR02", 5);
-		else
-			memcpy(iso9660_vrs_desc->identifier, "NSR03", 5);
-		;
-		if ((error = udf_write_sector(iso9660_vrs_desc, pos))) {
-			free(iso9660_vrs_desc);
-			return error;
-		}
-		pos += dpos;
-
-		memcpy(iso9660_vrs_desc->identifier, "TEA01", 5);
-		if ((error = udf_write_sector(iso9660_vrs_desc, pos))) {
-			free(iso9660_vrs_desc);
-			return error;
-		}
-	}
-
-	free(iso9660_vrs_desc);
-	/* return success */
-	return 0;
-}
-
 
 /* --------------------------------------------------------------------- */
 
-/*
- * Main function that creates and writes out disc contents based on the
- * format_flags's that uniquely define the type of disc to create.
- */
-
-int
+static int
 udf_do_newfs(void)
 {
-	union dscrptr *zero_dscr;
-	union dscrptr *terminator_dscr;
-	union dscrptr *root_dscr;
-	union dscrptr *vat_dscr;
-	union dscrptr *dscr;
-	struct mmc_trackinfo ti;
-	uint32_t sparable_blocks;
-	uint32_t sector_size, blockingnr;
-	uint32_t cnt, loc, len;
-	int sectcopy;
-	int error, integrity_type;
-	int data_part, metadata_part;
-
-	/* init */
-	sector_size = mmc_discinfo.sector_size;
-
-	/* determine span/size */
-	ti.tracknr = mmc_discinfo.first_track_last_session;
-	error = udf_update_trackinfo(&mmc_discinfo, &ti);
-	if (error)
-		return error;
-
-	if (mmc_discinfo.sector_size < context.sector_size) {
-		fprintf(stderr, "Impossible to format: sectorsize too small\n");
-		return EIO;
-	}
-	context.sector_size = sector_size;
-
-	/* determine blockingnr */
-	blockingnr = ti.packet_size;
-	if (blockingnr <= 1) {
-		/* paranoia on blockingnr */
-		switch (mmc_discinfo.mmc_profile) {
-		case 0x09 : /* CD-R    */
-		case 0x0a : /* CD-RW   */
-			blockingnr = 32;	/* UDF requirement */
-			break;
-		case 0x11 : /* DVD-R (DL) */
-		case 0x1b : /* DVD+R      */
-		case 0x2b : /* DVD+R Dual layer */
-		case 0x13 : /* DVD-RW restricted overwrite */
-		case 0x14 : /* DVD-RW sequential */
-			blockingnr = 16;	/* SCSI definition */
-			break;
-		case 0x41 : /* BD-R Sequential recording (SRM) */
-		case 0x51 : /* HD DVD-R   */
-			blockingnr = 32;	/* SCSI definition */
-			break;
-		default:
-			break;
-		}
-
-	}
-	if (blockingnr <= 0) {
-		printf("Can't fixup blockingnumber for device "
-			"type %d\n", mmc_discinfo.mmc_profile);
-
-		printf("Device is not returning valid blocking"
-			" number and media type is unknown.\n");
-
-		return EINVAL;
-	}
-
-	/* setup sector writeout queue's */
-	TAILQ_INIT(&write_queue);
-	wrtrack_skew = ti.track_start % blockingnr;
-
-	if (mmc_discinfo.mmc_class == MMC_CLASS_CD) {
-		/* not too much for CD-RW, still 20MiB */
-		sparable_blocks = 32;
-	} else {
-		/* take a value for DVD*RW mainly, BD is `defect free' */
-		sparable_blocks = 512;
-	}
-
-	/* get layout */
-	error = udf_calculate_disc_layout(format_flags, context.min_udf,
-		wrtrack_skew,
-		ti.track_start, mmc_discinfo.last_possible_lba,
-		sector_size, blockingnr, sparable_blocks,
-		meta_fract);
-
-	/* cache partition for we need it often */
-	data_part     = context.data_part;
-	metadata_part = context.metadata_part;
-
-	/* Create sparing table descriptor if applicable */
-	if (format_flags & FORMAT_SPARABLE) {
-		if ((error = udf_create_sparing_tabled()))
-			return error;
-
-		if (check_surface) {
-			if ((error = udf_surface_check()))
-				return error;
-		}
-	}
-
-	/* Create a generic terminator descriptor */
-	terminator_dscr = calloc(1, sector_size);
-	if (terminator_dscr == NULL)
-		return ENOMEM;
-	udf_create_terminator(terminator_dscr, 0);
-
-	/*
-	 * Start with wipeout of VRS1 upto start of partition. This allows
-	 * formatting for sequentials with the track reservation and it 
-	 * cleans old rubbish on rewritables. For sequentuals without the
-	 * track reservation all is wiped from track start.
-	 */
-	if ((zero_dscr = calloc(1, context.sector_size)) == NULL)
-		return ENOMEM;
-
-	loc = (format_flags & FORMAT_TRACK512) ? layout.vds1 : ti.track_start;
-	for (; loc < layout.part_start_lba; loc++) {
-		if ((error = udf_write_sector(zero_dscr, loc))) {
-			free(zero_dscr);
-			return error;
-		}
-	}
-	free(zero_dscr);
-
-	/* Create anchors */
-	for (cnt = 0; cnt < 3; cnt++) {
-		if ((error = udf_create_anchor(cnt))) {
-			return error;
-		}
-	}
-
-	/* 
-	 * Create the two Volume Descriptor Sets (VDS) each containing the
-	 * following descriptors : primary volume, partition space,
-	 * unallocated space, logical volume, implementation use and the
-	 * terminator
-	 */
-
-	/* start of volume recognision sequence building */
-	context.vds_seq = 0;
-
-	/* Create primary volume descriptor */
-	if ((error = udf_create_primaryd()))
-		return error;
-
-	/* Create partition descriptor */
-	if ((error = udf_create_partitiond(context.data_part, media_accesstype)))
-		return error;
-
-	/* Create unallocated space descriptor */
-	if ((error = udf_create_unalloc_spaced()))
-		return error;
-
-	/* Create logical volume descriptor */
-	if ((error = udf_create_logical_dscr(format_flags)))
-		return error;
-
-	/* Create implementation use descriptor */
-	/* TODO input of fields 1,2,3 and passing them */
-	if ((error = udf_create_impvold(NULL, NULL, NULL)))
-		return error;
-
-	/* write out what we've created so far */
-
-	/* writeout iso9660 vrs */
-	if ((error = udf_write_iso9660_vrs()))
-		return error;
-
-	/* Writeout anchors */
-	for (cnt = 0; cnt < 3; cnt++) {
-		dscr = (union dscrptr *) context.anchors[cnt];
-		loc  = layout.anchors[cnt];
-		if ((error = udf_write_dscr_phys(dscr, loc, 1)))
-			return error;
-
-		/* sequential media has only one anchor */
-		if (format_flags & FORMAT_SEQUENTIAL)
-			break;
-	}
-
-	/* write out main and secondary VRS */
-	for (sectcopy = 1; sectcopy <= 2; sectcopy++) {
-		loc = (sectcopy == 1) ? layout.vds1 : layout.vds2;
-
-		/* primary volume descriptor */
-		dscr = (union dscrptr *) context.primary_vol;
-		error = udf_write_dscr_phys(dscr, loc, 1);
-		if (error)
-			return error;
-		loc++;
-
-		/* partition descriptor(s) */
-		for (cnt = 0; cnt < UDF_PARTITIONS; cnt++) {
-			dscr = (union dscrptr *) context.partitions[cnt];
-			if (dscr) {
-				error = udf_write_dscr_phys(dscr, loc, 1);
-				if (error)
-					return error;
-				loc++;
-			}
-		}
-
-		/* unallocated space descriptor */
-		dscr = (union dscrptr *) context.unallocated;
-		error = udf_write_dscr_phys(dscr, loc, 1);
-		if (error)
-			return error;
-		loc++;
-
-		/* logical volume descriptor */
-		dscr = (union dscrptr *) context.logical_vol;
-		error = udf_write_dscr_phys(dscr, loc, 1);
-		if (error)
-			return error;
-		loc++;
-
-		/* implementation use descriptor */
-		dscr = (union dscrptr *) context.implementation;
-		error = udf_write_dscr_phys(dscr, loc, 1);
-		if (error)
-			return error;
-		loc++;
-
-		/* terminator descriptor */
-		error = udf_write_dscr_phys(terminator_dscr, loc, 1);
-		if (error)
-			return error;
-		loc++;
-	}
-
-	/* writeout the two sparable table descriptors (if needed) */
-	if (format_flags & FORMAT_SPARABLE) {
-		for (sectcopy = 1; sectcopy <= 2; sectcopy++) {
-			loc  = (sectcopy == 1) ? layout.spt_1 : layout.spt_2;
-			dscr = (union dscrptr *) context.sparing_table;
-			len  = layout.sparing_table_dscr_lbas;
-
-			/* writeout */
-			error = udf_write_dscr_phys(dscr, loc, len);
-			if (error)
-				return error;
-		}
-	}
-
-	/*
-	 * Create unallocated space bitmap descriptor. Sequential recorded
-	 * media report their own free/used space; no free/used space tables
-	 * should be recorded for these.
-	 */
-	if ((format_flags & FORMAT_SEQUENTIAL) == 0) {
-		error = udf_create_space_bitmap(
-				layout.alloc_bitmap_dscr_size,
-				layout.part_size_lba,
-				&context.part_unalloc_bits[data_part]);
-		if (error)
-			return error;
-		/* TODO: freed space bitmap if applicable */
-
-		/* mark space allocated for the unallocated space bitmap */
-		udf_mark_allocated(layout.unalloc_space, data_part,
-			layout.alloc_bitmap_dscr_size);
-	}
-
-	/*
-	 * Create metadata partition file entries and allocate and init their
-	 * space and free space maps.
-	 */
-	if (format_flags & FORMAT_META) {
-		error = udf_create_space_bitmap(
-				layout.meta_bitmap_dscr_size,
-				layout.meta_part_size_lba,
-				&context.part_unalloc_bits[metadata_part]);
-		if (error)
-			return error;
-	
-		error = udf_create_meta_files();
-		if (error)
-			return error;
-
-		/* mark space allocated for meta partition and its bitmap */
-		udf_mark_allocated(layout.meta_file,   data_part, 1);
-		udf_mark_allocated(layout.meta_mirror, data_part, 1);
-		udf_mark_allocated(layout.meta_bitmap, data_part, 1);
-		udf_mark_allocated(layout.meta_part_start_lba, data_part,
-			layout.meta_part_size_lba);
-
-		/* mark space allocated for the unallocated space bitmap */
-		udf_mark_allocated(layout.meta_bitmap_space, data_part,
-			layout.meta_bitmap_dscr_size);
-	}
-
-	/* create logical volume integrity descriptor */
-	context.num_files = 0;
-	context.num_directories = 0;
-	integrity_type = UDF_INTEGRITY_OPEN;
-	if ((error = udf_create_lvintd(integrity_type)))
-		return error;
-
-	/* create FSD */
-	if ((error = udf_create_fsd()))
-		return error;
-	udf_mark_allocated(layout.fsd, metadata_part, 1);
-
-	/* create root directory */
-	assert(context.unique_id == 0x10);
-	context.unique_id = 0;
-	if ((error = udf_create_new_rootdir(&root_dscr)))
-		return error;
-	udf_mark_allocated(layout.rootdir, metadata_part, 1);
-
-	/* writeout FSD + rootdir */
-	dscr = (union dscrptr *) context.fileset_desc;
-	error = udf_write_dscr_virt(dscr, layout.fsd, metadata_part, 1);
-	if (error)
-		return error;
-
-	error = udf_write_dscr_virt(root_dscr, layout.rootdir, metadata_part, 1);
-	if (error)
-		return error;
+	int error;
 
-	/* writeout initial open integrity sequence + terminator */
-	loc = layout.lvis;
-	dscr = (union dscrptr *) context.logvol_integrity;
-	error = udf_write_dscr_phys(dscr, loc, 1);
+	error = udf_do_newfs_prefix();
 	if (error)
 		return error;
-	loc++;
-	error = udf_write_dscr_phys(terminator_dscr, loc, 1);
+	error = udf_do_rootdir();
 	if (error)
 		return error;
+	error = udf_do_newfs_postfix();
 
-
-	/* XXX the place to add more files */
-
-
-	if ((format_flags & FORMAT_SEQUENTIAL) == 0) {
-		/* update lvint and mark it closed */
-		udf_update_lvintd(UDF_INTEGRITY_CLOSED);
-
-		/* overwrite initial terminator */
-		loc = layout.lvis+1;
-		dscr = (union dscrptr *) context.logvol_integrity;
-		error = udf_write_dscr_phys(dscr, loc, 1);
-		if (error)
-			return error;
-		loc++;
-	
-		/* mark end of integrity desciptor sequence again */
-		error = udf_write_dscr_phys(terminator_dscr, loc, 1);
-		if (error)
-			return error;
-	}
-
-	/* write out unallocated space bitmap on non sequential media */
-	if ((format_flags & FORMAT_SEQUENTIAL) == 0) {
-		/* writeout unallocated space bitmap */
-		loc  = layout.unalloc_space;
-		dscr = (union dscrptr *) (context.part_unalloc_bits[data_part]);
-		len  = layout.alloc_bitmap_dscr_size;
-		error = udf_write_dscr_virt(dscr, loc, data_part, len);
-		if (error)
-			return error;
-	}
-
-	if (format_flags & FORMAT_META) {
-		loc = layout.meta_file;
-		dscr = (union dscrptr *) context.meta_file;
-		error = udf_write_dscr_virt(dscr, loc, data_part, 1);
-		if (error)
-			return error;
-	
-		loc = layout.meta_mirror;
-		dscr = (union dscrptr *) context.meta_mirror;
-		error = udf_write_dscr_virt(dscr, loc, data_part, 1);
-		if (error)
-			return error;
-
-		loc = layout.meta_bitmap;
-		dscr = (union dscrptr *) context.meta_bitmap;
-		error = udf_write_dscr_virt(dscr, loc, data_part, 1);
-		if (error)
-			return error;
-
-		/* writeout unallocated space bitmap */
-		loc  = layout.meta_bitmap_space;
-		dscr = (union dscrptr *) (context.part_unalloc_bits[metadata_part]);
-		len  = layout.meta_bitmap_dscr_size;
-		error = udf_write_dscr_virt(dscr, loc, data_part, len);
-		if (error)
-			return error;
-	}
-
-	/* create a VAT and account for FSD+root */
-	vat_dscr = NULL;
-	if (format_flags & FORMAT_VAT) {
-		/* update lvint to reflect the newest values (no writeout) */
-		udf_update_lvintd(UDF_INTEGRITY_CLOSED);
-
-		error = udf_create_new_VAT(&vat_dscr);
-		if (error)
-			return error;
-
-		loc = layout.vat;
-		error = udf_write_dscr_virt(vat_dscr, loc, metadata_part, 1);
-		if (error)
-			return error;
-	}
-
-	/* write out sectors */
-	if ((error = writeout_write_queue()))
-		return error;
-
-	/* done */
-	return 0;
+	return error;
 }
 
 /* --------------------------------------------------------------------- */
 
+
 /* version can be specified as 0xabc or a.bc */
 static int
 parse_udfversion(const char *pos, uint32_t *version) {
@@ -1675,8 +917,15 @@ main(int argc, char **argv)
 		return EXIT_FAILURE;
 	};
 
-	/* set up administration */
+	/* setup sector writeout queue's */
+	TAILQ_INIT(&write_queue);
+
+	/* perform the newfs itself */
 	error = udf_do_newfs();
+	if (!error) {
+		/* write out sectors */
+		error = writeout_write_queue();
+	}
 
 	/* in any case, synchronise the drive's cache to prevent lockups */
 	udf_synchronise_caches();

Added files:

Index: src/sbin/newfs_udf/newfs_udf.h
diff -u /dev/null src/sbin/newfs_udf/newfs_udf.h:1.1
--- /dev/null	Thu Jul 18 12:44:21 2013
+++ src/sbin/newfs_udf/newfs_udf.h	Thu Jul 18 12:44:21 2013
@@ -0,0 +1,68 @@
+/*
+ * Copyright (c) 2006, 2008, 2013 Reinoud Zandijk
+ * All rights reserved.
+ * 
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ * 
+ */
+
+#ifndef _FS_UDF_NEWFS_UDF_H_
+#define _FS_UDF_NEWFS_UDF_H_
+
+/* general settings */
+#define UDF_512_TRACK	0	/* NOT recommended */
+#define UDF_META_PERC  20	/* picked */
+
+/* Identifying myself */
+#define APP_NAME		"*NetBSD newfs"
+#define APP_VERSION_MAIN	0
+#define APP_VERSION_SUB		4
+#define IMPL_NAME		"*NetBSD userland UDF"
+
+
+/* global variables describing disc and format requests */
+extern int	 fd;				/* device: file descriptor */
+extern char	*dev;				/* device: name		   */
+extern struct mmc_discinfo mmc_discinfo;	/* device: disc info	   */
+
+extern char	*format_str;			/* format: string representation */
+extern int	 format_flags;			/* format: attribute flags	 */
+extern int	 media_accesstype;		/* derived from current mmc cap  */
+extern int	 check_surface;			/* for rewritables               */
+
+extern int	 wrtrack_skew;
+extern int	 meta_perc;
+extern float	 meta_fract;
+
+
+/* shared structure between udf_create.c users */
+struct udf_create_context context;
+struct udf_disclayout     layout;
+
+/* prototypes */
+int udf_write_sector(void *sector, uint32_t location);
+int udf_update_trackinfo(struct mmc_discinfo *di, struct mmc_trackinfo *ti);
+
+/* tmp */
+int writeout_write_queue(void);
+int udf_surface_check(void);
+
+#endif /* _FS_UDF_UDF_WRITE_H_ */
Index: src/sbin/newfs_udf/udf_write.c
diff -u /dev/null src/sbin/newfs_udf/udf_write.c:1.1
--- /dev/null	Thu Jul 18 12:44:21 2013
+++ src/sbin/newfs_udf/udf_write.c	Thu Jul 18 12:44:21 2013
@@ -0,0 +1,819 @@
+/* $NetBSD: udf_write.c,v 1.1 2013/07/18 12:44:21 reinoud Exp $ */
+
+/*
+ * Copyright (c) 2006, 2008, 2013 Reinoud Zandijk
+ * All rights reserved.
+ * 
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ * 
+ */
+
+#include <sys/cdefs.h>
+#ifndef lint
+__RCSID("$NetBSD: udf_write.c,v 1.1 2013/07/18 12:44:21 reinoud Exp $");
+#endif /* not lint */
+
+#define _EXPOSE_MMC
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+#include <time.h>
+#include <assert.h>
+#include <err.h>
+#include <sys/types.h>
+#include <sys/param.h>
+#include <sys/cdio.h>
+
+#include "udf_create.h"
+#include "udf_write.h"
+#include "newfs_udf.h"
+
+
+union dscrptr *terminator_dscr;
+
+
+static int
+udf_write_dscr_phys(union dscrptr *dscr, uint32_t location,
+	uint32_t sects)
+{
+	uint32_t phys, cnt;
+	uint8_t *bpos;
+	int error;
+
+	dscr->tag.tag_loc = udf_rw32(location);
+	(void) udf_validate_tag_and_crc_sums(dscr);
+
+	for (cnt = 0; cnt < sects; cnt++) {
+		bpos  = (uint8_t *) dscr;
+		bpos += context.sector_size * cnt;
+
+		phys = location + cnt;
+		error = udf_write_sector(bpos, phys);
+		if (error)
+			return error;
+	}
+	return 0;
+}
+
+
+static int
+udf_write_dscr_virt(union dscrptr *dscr, uint32_t location, uint32_t vpart,
+	uint32_t sects)
+{
+	struct file_entry *fe;
+	struct extfile_entry *efe;
+	struct extattrhdr_desc *extattrhdr;
+	uint32_t phys, cnt;
+	uint8_t *bpos;
+	int error;
+
+	extattrhdr = NULL;
+	if (udf_rw16(dscr->tag.id) == TAGID_FENTRY) {
+		fe = (struct file_entry *) dscr;
+		if (udf_rw32(fe->l_ea) > 0)
+			extattrhdr = (struct extattrhdr_desc *) fe->data;
+	}
+	if (udf_rw16(dscr->tag.id) == TAGID_EXTFENTRY) {
+		efe = (struct extfile_entry *) dscr;
+		if (udf_rw32(efe->l_ea) > 0)
+			extattrhdr = (struct extattrhdr_desc *) efe->data;
+	}
+	if (extattrhdr) {
+		extattrhdr->tag.tag_loc = udf_rw32(location);
+		udf_validate_tag_and_crc_sums((union dscrptr *) extattrhdr);
+	}
+
+	dscr->tag.tag_loc = udf_rw32(location);
+	udf_validate_tag_and_crc_sums(dscr);
+
+	for (cnt = 0; cnt < sects; cnt++) {
+		bpos  = (uint8_t *) dscr;
+		bpos += context.sector_size * cnt;
+
+		/* NOTE linear mapping assumed in the ranges used */
+		phys = context.vtop_offset[vpart] + location + cnt;
+
+		error = udf_write_sector(bpos, phys);
+		if (error)
+			return error;
+	}
+	return 0;
+}
+
+/* --------------------------------------------------------------------- */
+
+/*
+ * udf_derive_format derives the format_flags from the disc's mmc_discinfo.
+ * The resulting flags uniquely define a disc format. Note there are at least
+ * 7 distinct format types defined in UDF.
+ */
+
+#define UDF_VERSION(a) \
+	(((a) == 0x100) || ((a) == 0x102) || ((a) == 0x150) || ((a) == 0x200) || \
+	 ((a) == 0x201) || ((a) == 0x250) || ((a) == 0x260))
+
+int
+udf_derive_format(int req_enable, int req_disable, int force)
+{
+	/* disc writability, formatted, appendable */
+	if ((mmc_discinfo.mmc_cur & MMC_CAP_RECORDABLE) == 0) {
+		(void)printf("Can't newfs readonly device\n");
+		return EROFS;
+	}
+	if (mmc_discinfo.mmc_cur & MMC_CAP_SEQUENTIAL) {
+		/* sequentials need sessions appended */
+		if (mmc_discinfo.disc_state == MMC_STATE_CLOSED) {
+			(void)printf("Can't append session to a closed disc\n");
+			return EROFS;
+		}
+		if ((mmc_discinfo.disc_state != MMC_STATE_EMPTY) && !force) {
+			(void)printf("Disc not empty! Use -F to force "
+			    "initialisation\n");
+			return EROFS;
+		}
+	} else {
+		/* check if disc (being) formatted or has been started on */
+		if (mmc_discinfo.disc_state == MMC_STATE_EMPTY) {
+			(void)printf("Disc is not formatted\n");
+			return EROFS;
+		}
+	}
+
+	/* determine UDF format */
+	format_flags = 0;
+	if (mmc_discinfo.mmc_cur & MMC_CAP_REWRITABLE) {
+		/* all rewritable media */
+		format_flags |= FORMAT_REWRITABLE;
+		if (context.min_udf >= 0x0250) {
+			/* standard dictates meta as default */
+			format_flags |= FORMAT_META;
+		}
+
+		if ((mmc_discinfo.mmc_cur & MMC_CAP_HW_DEFECTFREE) == 0) {
+			/* sparables for defect management */
+			if (context.min_udf >= 0x150)
+				format_flags |= FORMAT_SPARABLE;
+		}
+	} else {
+		/* all once recordable media */
+		format_flags |= FORMAT_WRITEONCE;
+		if (mmc_discinfo.mmc_cur & MMC_CAP_SEQUENTIAL) {
+			format_flags |= FORMAT_SEQUENTIAL;
+
+			if (mmc_discinfo.mmc_cur & MMC_CAP_PSEUDOOVERWRITE) {
+				/* logical overwritable */
+				format_flags |= FORMAT_LOW;
+			} else {
+				/* have to use VAT for overwriting */
+				format_flags |= FORMAT_VAT;
+			}
+		} else {
+			/* rare WORM devices, but BluRay has one, strat4096 */
+			format_flags |= FORMAT_WORM;
+		}
+	}
+
+	/* enable/disable requests */
+	if (req_disable & FORMAT_META) {
+		format_flags &= ~(FORMAT_META | FORMAT_LOW);
+		req_disable  &= ~FORMAT_META;
+	}
+	if (req_disable || req_enable) {
+		(void)printf("Internal error\n");
+		(void)printf("\tunrecognised enable/disable req.\n");
+		return EIO;
+	}
+	if ((format_flags & FORMAT_VAT) & UDF_512_TRACK)
+		format_flags |= FORMAT_TRACK512;
+
+	/* determine partition/media access type */
+	media_accesstype = UDF_ACCESSTYPE_NOT_SPECIFIED;
+	if (mmc_discinfo.mmc_cur & MMC_CAP_REWRITABLE) {
+		media_accesstype = UDF_ACCESSTYPE_OVERWRITABLE;
+		if (mmc_discinfo.mmc_cur & MMC_CAP_ERASABLE)
+			media_accesstype = UDF_ACCESSTYPE_REWRITEABLE;
+	} else {
+		/* all once recordable media */
+		media_accesstype = UDF_ACCESSTYPE_WRITE_ONCE;
+	}
+	if (mmc_discinfo.mmc_cur & MMC_CAP_PSEUDOOVERWRITE)
+		media_accesstype = UDF_ACCESSTYPE_PSEUDO_OVERWITE;
+
+	/* adjust minimum version limits */
+	if (format_flags & FORMAT_VAT)
+		context.min_udf = MAX(context.min_udf, 0x0150);
+	if (format_flags & FORMAT_SPARABLE)
+		context.min_udf = MAX(context.min_udf, 0x0150);
+	if (format_flags & FORMAT_META)
+		context.min_udf = MAX(context.min_udf, 0x0250);
+	if (format_flags & FORMAT_LOW)
+		context.min_udf = MAX(context.min_udf, 0x0260);
+
+	/* adjust maximum version limits not to tease or break things */
+	if (!(format_flags & (FORMAT_META | FORMAT_LOW)) &&
+	    (context.max_udf > 0x200))
+		context.max_udf = 0x201;
+
+	if ((format_flags & (FORMAT_VAT | FORMAT_SPARABLE)) == 0)
+		if (context.max_udf <= 0x150)
+			context.min_udf = 0x102;
+
+	/* limit Ecma 167 descriptor if possible/needed */
+	context.dscrver = 3;
+	if ((context.min_udf < 0x200) || (context.max_udf < 0x200)) {
+		context.dscrver = 2;
+		context.max_udf = 0x150;	/* last version < 0x200 */
+	}
+
+	/* is it possible ? */
+	if (context.min_udf > context.max_udf) {
+		(void)printf("Initialisation prohibited by specified maximum "
+		    "UDF version 0x%04x. Minimum version required 0x%04x\n",
+		    context.max_udf, context.min_udf);
+		return EPERM;
+	}
+
+	if (!UDF_VERSION(context.min_udf) || !UDF_VERSION(context.max_udf)) {
+		printf("Choose UDF version numbers from "
+			"0x102, 0x150, 0x200, 0x201, 0x250 and 0x260\n");
+		printf("Default version is 0x201\n");
+		return EPERM;
+	}
+
+	return 0;
+}
+
+#undef UDF_VERSION
+
+
+/* --------------------------------------------------------------------- */
+
+int
+udf_proces_names(void)
+{
+	uint32_t primary_nr;
+	uint64_t volset_nr;
+
+	if (context.logvol_name == NULL)
+		context.logvol_name = strdup("anonymous");
+	if (context.primary_name == NULL) {
+		if (mmc_discinfo.disc_flags & MMC_DFLAGS_DISCIDVALID) {
+			primary_nr = mmc_discinfo.disc_id;
+		} else {
+			primary_nr = (uint32_t) random();
+		}
+		context.primary_name = calloc(32, 1);
+		sprintf(context.primary_name, "%08"PRIx32, primary_nr);
+	}
+	if (context.volset_name == NULL) {
+		if (mmc_discinfo.disc_flags & MMC_DFLAGS_BARCODEVALID) {
+			volset_nr = mmc_discinfo.disc_barcode;
+		} else {
+			volset_nr  =  (uint32_t) random();
+			volset_nr |= ((uint64_t) random()) << 32;
+		}
+		context.volset_name = calloc(128,1);
+		sprintf(context.volset_name, "%016"PRIx64, volset_nr);
+	}
+	if (context.fileset_name == NULL)
+		context.fileset_name = strdup("anonymous");
+
+	/* check passed/created identifiers */
+	if (strlen(context.logvol_name)  > 128) {
+		(void)printf("Logical volume name too long\n");
+		return EINVAL;
+	}
+	if (strlen(context.primary_name) >  32) {
+		(void)printf("Primary volume name too long\n");
+		return EINVAL;
+	}
+	if (strlen(context.volset_name)  > 128) {
+		(void)printf("Volume set name too long\n");
+		return EINVAL;
+	}
+	if (strlen(context.fileset_name) > 32) {
+		(void)printf("Fileset name too long\n");
+		return EINVAL;
+	}
+
+	/* signal all OK */
+	return 0;
+}
+
+/* --------------------------------------------------------------------- */
+
+static int
+udf_write_iso9660_vrs(void)
+{
+	struct vrs_desc *iso9660_vrs_desc;
+	uint32_t pos;
+	int error, cnt, dpos;
+
+	/* create ISO/Ecma-167 identification descriptors */
+	if ((iso9660_vrs_desc = calloc(1, context.sector_size)) == NULL)
+		return ENOMEM;
+
+	/*
+	 * All UDF formats should have their ISO/Ecma-167 descriptors written
+	 * except when not possible due to track reservation in the case of
+	 * VAT
+	 */
+	if ((format_flags & FORMAT_TRACK512) == 0) {
+		dpos = (2048 + context.sector_size - 1) / context.sector_size;
+
+		/* wipe at least 6 times 2048 byte `sectors' */
+		for (cnt = 0; cnt < 6 *dpos; cnt++) {
+			pos = layout.iso9660_vrs + cnt;
+			if ((error = udf_write_sector(iso9660_vrs_desc, pos))) {
+				free(iso9660_vrs_desc);
+				return error;
+			}
+		}
+
+		/* common VRS fields in all written out ISO descriptors */
+		iso9660_vrs_desc->struct_type = 0;
+		iso9660_vrs_desc->version     = 1;
+		pos = layout.iso9660_vrs;
+
+		/* BEA01, NSR[23], TEA01 */
+		memcpy(iso9660_vrs_desc->identifier, "BEA01", 5);
+		if ((error = udf_write_sector(iso9660_vrs_desc, pos))) {
+			free(iso9660_vrs_desc);
+			return error;
+		}
+		pos += dpos;
+
+		if (context.dscrver == 2)
+			memcpy(iso9660_vrs_desc->identifier, "NSR02", 5);
+		else
+			memcpy(iso9660_vrs_desc->identifier, "NSR03", 5);
+		;
+		if ((error = udf_write_sector(iso9660_vrs_desc, pos))) {
+			free(iso9660_vrs_desc);
+			return error;
+		}
+		pos += dpos;
+
+		memcpy(iso9660_vrs_desc->identifier, "TEA01", 5);
+		if ((error = udf_write_sector(iso9660_vrs_desc, pos))) {
+			free(iso9660_vrs_desc);
+			return error;
+		}
+	}
+
+	free(iso9660_vrs_desc);
+	/* return success */
+	return 0;
+}
+
+
+/* --------------------------------------------------------------------- */
+
+/*
+ * Main function that creates and writes out disc contents based on the
+ * format_flags's that uniquely define the type of disc to create.
+ */
+
+int
+udf_do_newfs_prefix(void)
+{
+	union dscrptr *zero_dscr;
+	union dscrptr *dscr;
+	struct mmc_trackinfo ti;
+	uint32_t sparable_blocks;
+	uint32_t sector_size, blockingnr;
+	uint32_t cnt, loc, len;
+	int sectcopy;
+	int error, integrity_type;
+	int data_part, metadata_part;
+
+	/* init */
+	sector_size = mmc_discinfo.sector_size;
+
+	/* determine span/size */
+	ti.tracknr = mmc_discinfo.first_track_last_session;
+	error = udf_update_trackinfo(&mmc_discinfo, &ti);
+	if (error)
+		return error;
+
+	if (mmc_discinfo.sector_size < context.sector_size) {
+		fprintf(stderr, "Impossible to format: sectorsize too small\n");
+		return EIO;
+	}
+	context.sector_size = sector_size;
+
+	/* determine blockingnr */
+	blockingnr = ti.packet_size;
+	if (blockingnr <= 1) {
+		/* paranoia on blockingnr */
+		switch (mmc_discinfo.mmc_profile) {
+		case 0x09 : /* CD-R    */
+		case 0x0a : /* CD-RW   */
+			blockingnr = 32;	/* UDF requirement */
+			break;
+		case 0x11 : /* DVD-R (DL) */
+		case 0x1b : /* DVD+R      */
+		case 0x2b : /* DVD+R Dual layer */
+		case 0x13 : /* DVD-RW restricted overwrite */
+		case 0x14 : /* DVD-RW sequential */
+			blockingnr = 16;	/* SCSI definition */
+			break;
+		case 0x41 : /* BD-R Sequential recording (SRM) */
+		case 0x51 : /* HD DVD-R   */
+			blockingnr = 32;	/* SCSI definition */
+			break;
+		default:
+			break;
+		}
+
+	}
+	if (blockingnr <= 0) {
+		printf("Can't fixup blockingnumber for device "
+			"type %d\n", mmc_discinfo.mmc_profile);
+
+		printf("Device is not returning valid blocking"
+			" number and media type is unknown.\n");
+
+		return EINVAL;
+	}
+	wrtrack_skew = ti.track_start % blockingnr;
+
+	if (mmc_discinfo.mmc_class == MMC_CLASS_CD) {
+		/* not too much for CD-RW, still 20MiB */
+		sparable_blocks = 32;
+	} else {
+		/* take a value for DVD*RW mainly, BD is `defect free' */
+		sparable_blocks = 512;
+	}
+
+	/* get layout */
+	error = udf_calculate_disc_layout(format_flags, context.min_udf,
+		wrtrack_skew,
+		ti.track_start, mmc_discinfo.last_possible_lba,
+		context.sector_size, blockingnr, sparable_blocks,
+		meta_fract);
+
+	/* cache partition for we need it often */
+	data_part     = context.data_part;
+	metadata_part = context.metadata_part;
+
+	/* Create sparing table descriptor if applicable */
+	if (format_flags & FORMAT_SPARABLE) {
+		if ((error = udf_create_sparing_tabled()))
+			return error;
+
+		if (check_surface) {
+			if ((error = udf_surface_check()))
+				return error;
+		}
+	}
+
+	/* Create a generic terminator descriptor (later reused) */
+	terminator_dscr = calloc(1, sector_size);
+	if (terminator_dscr == NULL)
+		return ENOMEM;
+	udf_create_terminator(terminator_dscr, 0);
+
+	/*
+	 * Start with wipeout of VRS1 upto start of partition. This allows
+	 * formatting for sequentials with the track reservation and it 
+	 * cleans old rubbish on rewritables. For sequentuals without the
+	 * track reservation all is wiped from track start.
+	 */
+	if ((zero_dscr = calloc(1, context.sector_size)) == NULL)
+		return ENOMEM;
+
+	loc = (format_flags & FORMAT_TRACK512) ? layout.vds1 : ti.track_start;
+	for (; loc < layout.part_start_lba; loc++) {
+		if ((error = udf_write_sector(zero_dscr, loc))) {
+			free(zero_dscr);
+			return error;
+		}
+	}
+	free(zero_dscr);
+
+	/* Create anchors */
+	for (cnt = 0; cnt < 3; cnt++) {
+		if ((error = udf_create_anchor(cnt))) {
+			return error;
+		}
+	}
+
+	/* 
+	 * Create the two Volume Descriptor Sets (VDS) each containing the
+	 * following descriptors : primary volume, partition space,
+	 * unallocated space, logical volume, implementation use and the
+	 * terminator
+	 */
+
+	/* start of volume recognision sequence building */
+	context.vds_seq = 0;
+
+	/* Create primary volume descriptor */
+	if ((error = udf_create_primaryd()))
+		return error;
+
+	/* Create partition descriptor */
+	if ((error = udf_create_partitiond(context.data_part, media_accesstype)))
+		return error;
+
+	/* Create unallocated space descriptor */
+	if ((error = udf_create_unalloc_spaced()))
+		return error;
+
+	/* Create logical volume descriptor */
+	if ((error = udf_create_logical_dscr(format_flags)))
+		return error;
+
+	/* Create implementation use descriptor */
+	/* TODO input of fields 1,2,3 and passing them */
+	if ((error = udf_create_impvold(NULL, NULL, NULL)))
+		return error;
+
+	/* write out what we've created so far */
+
+	/* writeout iso9660 vrs */
+	if ((error = udf_write_iso9660_vrs()))
+		return error;
+
+	/* Writeout anchors */
+	for (cnt = 0; cnt < 3; cnt++) {
+		dscr = (union dscrptr *) context.anchors[cnt];
+		loc  = layout.anchors[cnt];
+		if ((error = udf_write_dscr_phys(dscr, loc, 1)))
+			return error;
+
+		/* sequential media has only one anchor */
+		if (format_flags & FORMAT_SEQUENTIAL)
+			break;
+	}
+
+	/* write out main and secondary VRS */
+	for (sectcopy = 1; sectcopy <= 2; sectcopy++) {
+		loc = (sectcopy == 1) ? layout.vds1 : layout.vds2;
+
+		/* primary volume descriptor */
+		dscr = (union dscrptr *) context.primary_vol;
+		error = udf_write_dscr_phys(dscr, loc, 1);
+		if (error)
+			return error;
+		loc++;
+
+		/* partition descriptor(s) */
+		for (cnt = 0; cnt < UDF_PARTITIONS; cnt++) {
+			dscr = (union dscrptr *) context.partitions[cnt];
+			if (dscr) {
+				error = udf_write_dscr_phys(dscr, loc, 1);
+				if (error)
+					return error;
+				loc++;
+			}
+		}
+
+		/* unallocated space descriptor */
+		dscr = (union dscrptr *) context.unallocated;
+		error = udf_write_dscr_phys(dscr, loc, 1);
+		if (error)
+			return error;
+		loc++;
+
+		/* logical volume descriptor */
+		dscr = (union dscrptr *) context.logical_vol;
+		error = udf_write_dscr_phys(dscr, loc, 1);
+		if (error)
+			return error;
+		loc++;
+
+		/* implementation use descriptor */
+		dscr = (union dscrptr *) context.implementation;
+		error = udf_write_dscr_phys(dscr, loc, 1);
+		if (error)
+			return error;
+		loc++;
+
+		/* terminator descriptor */
+		error = udf_write_dscr_phys(terminator_dscr, loc, 1);
+		if (error)
+			return error;
+		loc++;
+	}
+
+	/* writeout the two sparable table descriptors (if needed) */
+	if (format_flags & FORMAT_SPARABLE) {
+		for (sectcopy = 1; sectcopy <= 2; sectcopy++) {
+			loc  = (sectcopy == 1) ? layout.spt_1 : layout.spt_2;
+			dscr = (union dscrptr *) context.sparing_table;
+			len  = layout.sparing_table_dscr_lbas;
+
+			/* writeout */
+			error = udf_write_dscr_phys(dscr, loc, len);
+			if (error)
+				return error;
+		}
+	}
+
+	/*
+	 * Create unallocated space bitmap descriptor. Sequential recorded
+	 * media report their own free/used space; no free/used space tables
+	 * should be recorded for these.
+	 */
+	if ((format_flags & FORMAT_SEQUENTIAL) == 0) {
+		error = udf_create_space_bitmap(
+				layout.alloc_bitmap_dscr_size,
+				layout.part_size_lba,
+				&context.part_unalloc_bits[data_part]);
+		if (error)
+			return error;
+		/* TODO: freed space bitmap if applicable */
+
+		/* mark space allocated for the unallocated space bitmap */
+		udf_mark_allocated(layout.unalloc_space, data_part,
+			layout.alloc_bitmap_dscr_size);
+	}
+
+	/*
+	 * Create metadata partition file entries and allocate and init their
+	 * space and free space maps.
+	 */
+	if (format_flags & FORMAT_META) {
+		error = udf_create_space_bitmap(
+				layout.meta_bitmap_dscr_size,
+				layout.meta_part_size_lba,
+				&context.part_unalloc_bits[metadata_part]);
+		if (error)
+			return error;
+	
+		error = udf_create_meta_files();
+		if (error)
+			return error;
+
+		/* mark space allocated for meta partition and its bitmap */
+		udf_mark_allocated(layout.meta_file,   data_part, 1);
+		udf_mark_allocated(layout.meta_mirror, data_part, 1);
+		udf_mark_allocated(layout.meta_bitmap, data_part, 1);
+		udf_mark_allocated(layout.meta_part_start_lba, data_part,
+			layout.meta_part_size_lba);
+
+		/* mark space allocated for the unallocated space bitmap */
+		udf_mark_allocated(layout.meta_bitmap_space, data_part,
+			layout.meta_bitmap_dscr_size);
+	}
+
+	/* create logical volume integrity descriptor */
+	context.num_files = 0;
+	context.num_directories = 0;
+	integrity_type = UDF_INTEGRITY_OPEN;
+	if ((error = udf_create_lvintd(integrity_type)))
+		return error;
+
+	/* writeout initial open integrity sequence + terminator */
+	loc = layout.lvis;
+	dscr = (union dscrptr *) context.logvol_integrity;
+	error = udf_write_dscr_phys(dscr, loc, 1);
+	if (error)
+		return error;
+	loc++;
+	error = udf_write_dscr_phys(terminator_dscr, loc, 1);
+	if (error)
+		return error;
+
+	/* create FSD and writeout */
+	if ((error = udf_create_fsd()))
+		return error;
+	udf_mark_allocated(layout.fsd, metadata_part, 1);
+
+	dscr = (union dscrptr *) context.fileset_desc;
+	error = udf_write_dscr_virt(dscr, layout.fsd, metadata_part, 1);
+
+	return error;
+}
+
+
+int
+udf_do_rootdir(void) {
+	union dscrptr *root_dscr;
+	int error;
+
+	/* create root directory and write out */
+	assert(context.unique_id == 0x10);
+	context.unique_id = 0;
+	if ((error = udf_create_new_rootdir(&root_dscr)))
+		return error;
+	udf_mark_allocated(layout.rootdir, context.metadata_part, 1);
+
+	error = udf_write_dscr_virt(root_dscr, layout.rootdir, context.metadata_part, 1);
+
+	/* XXX the place to add more files */
+	return error;
+}
+
+
+int
+udf_do_newfs_postfix(void)
+{
+	union dscrptr *vat_dscr;
+	union dscrptr *dscr;
+	uint32_t loc, len;
+	int data_part, metadata_part;
+	int error;
+
+	/* cache partition for we need it often */
+	data_part     = context.data_part;
+	metadata_part = context.metadata_part;
+
+	if ((format_flags & FORMAT_SEQUENTIAL) == 0) {
+		/* update lvint and mark it closed */
+		udf_update_lvintd(UDF_INTEGRITY_CLOSED);
+
+		/* overwrite initial terminator */
+		loc = layout.lvis+1;
+		dscr = (union dscrptr *) context.logvol_integrity;
+		error = udf_write_dscr_phys(dscr, loc, 1);
+		if (error)
+			return error;
+		loc++;
+	
+		/* mark end of integrity desciptor sequence again */
+		error = udf_write_dscr_phys(terminator_dscr, loc, 1);
+		if (error)
+			return error;
+	}
+
+	/* write out unallocated space bitmap on non sequential media */
+	if ((format_flags & FORMAT_SEQUENTIAL) == 0) {
+		/* writeout unallocated space bitmap */
+		loc  = layout.unalloc_space;
+		dscr = (union dscrptr *) (context.part_unalloc_bits[data_part]);
+		len  = layout.alloc_bitmap_dscr_size;
+		error = udf_write_dscr_virt(dscr, loc, data_part, len);
+		if (error)
+			return error;
+	}
+
+	if (format_flags & FORMAT_META) {
+		loc = layout.meta_file;
+		dscr = (union dscrptr *) context.meta_file;
+		error = udf_write_dscr_virt(dscr, loc, data_part, 1);
+		if (error)
+			return error;
+	
+		loc = layout.meta_mirror;
+		dscr = (union dscrptr *) context.meta_mirror;
+		error = udf_write_dscr_virt(dscr, loc, data_part, 1);
+		if (error)
+			return error;
+
+		loc = layout.meta_bitmap;
+		dscr = (union dscrptr *) context.meta_bitmap;
+		error = udf_write_dscr_virt(dscr, loc, data_part, 1);
+		if (error)
+			return error;
+
+		/* writeout unallocated space bitmap */
+		loc  = layout.meta_bitmap_space;
+		dscr = (union dscrptr *) (context.part_unalloc_bits[metadata_part]);
+		len  = layout.meta_bitmap_dscr_size;
+		error = udf_write_dscr_virt(dscr, loc, data_part, len);
+		if (error)
+			return error;
+	}
+
+	/* create a VAT and account for FSD+root */
+	vat_dscr = NULL;
+	if (format_flags & FORMAT_VAT) {
+		/* update lvint to reflect the newest values (no writeout) */
+		udf_update_lvintd(UDF_INTEGRITY_CLOSED);
+
+		error = udf_create_new_VAT(&vat_dscr);
+		if (error)
+			return error;
+
+		loc = layout.vat;
+		error = udf_write_dscr_virt(vat_dscr, loc, metadata_part, 1);
+		if (error)
+			return error;
+	}
+
+	/* done */
+	return 0;
+}
Index: src/sbin/newfs_udf/udf_write.h
diff -u /dev/null src/sbin/newfs_udf/udf_write.h:1.1
--- /dev/null	Thu Jul 18 12:44:21 2013
+++ src/sbin/newfs_udf/udf_write.h	Thu Jul 18 12:44:21 2013
@@ -0,0 +1,42 @@
+/*
+ * Copyright (c) 2006, 2008, 2013 Reinoud Zandijk
+ * All rights reserved.
+ * 
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ * 
+ */
+
+#ifndef _FS_UDF_UDF_WRITE_H_
+#define _FS_UDF_UDF_WRITE_H_
+
+#include "udf_create.h"
+#include <sys/cdio.h>
+
+/* prototypes */
+
+int udf_derive_format(int req_enable, int req_disable, int force);
+int udf_proces_names(void);
+
+int udf_do_newfs_prefix(void);
+int udf_do_rootdir(void);
+int udf_do_newfs_postfix(void);
+
+#endif /* _FS_UDF_UDF_WRITE_H_ */

Reply via email to