Module Name: src
Committed By: reinoud
Date: Mon Aug 5 14:11:30 UTC 2013
Modified Files:
src/sbin/newfs_udf: newfs_udf.8 newfs_udf.c udf_create.c udf_create.h
udf_write.c udf_write.h
Added Files:
src/sbin/newfs_udf: unicode.h
Log Message:
Adjust newfs_udf to be sharing code with the new `makefs -t udf' to be
comitted.
To generate a diff of this commit:
cvs rdiff -u -r1.12 -r1.13 src/sbin/newfs_udf/newfs_udf.8
cvs rdiff -u -r1.14 -r1.15 src/sbin/newfs_udf/newfs_udf.c
cvs rdiff -u -r1.17 -r1.18 src/sbin/newfs_udf/udf_create.c
cvs rdiff -u -r1.3 -r1.4 src/sbin/newfs_udf/udf_create.h
cvs rdiff -u -r1.2 -r1.3 src/sbin/newfs_udf/udf_write.c
cvs rdiff -u -r1.1 -r1.2 src/sbin/newfs_udf/udf_write.h
cvs rdiff -u -r0 -r1.1 src/sbin/newfs_udf/unicode.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/newfs_udf.8
diff -u src/sbin/newfs_udf/newfs_udf.8:1.12 src/sbin/newfs_udf/newfs_udf.8:1.13
--- src/sbin/newfs_udf/newfs_udf.8:1.12 Sat Jul 20 21:39:58 2013
+++ src/sbin/newfs_udf/newfs_udf.8 Mon Aug 5 14:11:30 2013
@@ -1,4 +1,4 @@
-.\" $NetBSD: newfs_udf.8,v 1.12 2013/07/20 21:39:58 wiz Exp $
+.\" $NetBSD: newfs_udf.8,v 1.13 2013/08/05 14:11:30 reinoud Exp $
.\"
.\" Copyright (c) 2008 Reinoud Zandijk
.\" All rights reserved.
@@ -26,7 +26,7 @@
.\" IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
.\"
.\"
-.Dd July 2, 2013
+.Dd August 2, 2013
.Dt NEWFS_UDF 8
.Os
.Sh NAME
@@ -40,6 +40,7 @@
.Op Fl p Ar percentage
.Op Fl S Ar sectorsize
.Op Fl s Ar size
+.Op Fl B Ar blockingsize
.Op Fl t Ar gmtoff
.Op Fl V Ar max_udf
.Op Fl v Ar min_udf
@@ -84,6 +85,10 @@ For strict conformance and interchange,
.It Fl s Ar size
For image files, set the file size to the humanized size
.Ar size .
+.It Fl B Ar blockingsize
+When creating image files, specify the blocking size or packetsize of the media
+to
+.Ar blockingsize .
.It Fl t Ar gmtoff
Use the specified
.Ar gmtoff
Index: src/sbin/newfs_udf/newfs_udf.c
diff -u src/sbin/newfs_udf/newfs_udf.c:1.14 src/sbin/newfs_udf/newfs_udf.c:1.15
--- src/sbin/newfs_udf/newfs_udf.c:1.14 Thu Jul 18 12:44:21 2013
+++ src/sbin/newfs_udf/newfs_udf.c Mon Aug 5 14:11:30 2013
@@ -1,4 +1,4 @@
-/* $NetBSD: newfs_udf.c,v 1.14 2013/07/18 12:44:21 reinoud Exp $ */
+/* $NetBSD: newfs_udf.c,v 1.15 2013/08/05 14:11:30 reinoud Exp $ */
/*
* Copyright (c) 2006, 2008, 2013 Reinoud Zandijk
@@ -94,6 +94,7 @@ int format_flags; /* format: attribut
int media_accesstype; /* derived from current mmc cap */
int check_surface; /* for rewritables */
int imagefile_secsize; /* for files */
+int emul_packetsize; /* for discs and files */
int wrtrack_skew;
int meta_perc = UDF_META_PERC;
@@ -289,8 +290,9 @@ udf_update_discinfo(struct mmc_discinfo
sectors = size / secsize;
} else {
/*
- * disc partition support; note we can't use DIOCGPART in userland so
- * get disc label and use the stat info to get the partition number.
+ * disc partition support; note we can't use DIOCGPART in
+ * userland so get disc label and use the stat info to get the
+ * partition number.
*/
if (ioctl(fd, DIOCGDINFO, &disklab) == -1) {
/* failed to get disclabel! */
@@ -303,9 +305,10 @@ udf_update_discinfo(struct mmc_discinfo
partnr = DISKPART(st.st_rdev);
dp = &disklab.d_partitions[partnr];
- /* TODO problem with last_possible_lba on resizable VND; request */
+ /* TODO problem with last_possible_lba on resizable VND */
if (dp->p_size == 0) {
- perror("faulty disklabel partition returned, check label\n");
+ perror("faulty disklabel partition returned, "
+ "check label\n");
return EIO;
}
@@ -363,7 +366,7 @@ udf_update_trackinfo(struct mmc_discinfo
ti->flags = MMC_TRACKINFO_LRA_VALID | MMC_TRACKINFO_NWA_VALID;
ti->track_start = 0;
- ti->packet_size = 1;
+ ti->packet_size = emul_packetsize;
/* TODO support for resizable vnd */
ti->track_size = di->last_possible_lba;
@@ -722,6 +725,7 @@ main(int argc, char **argv)
check_surface = 0;
setsize = 0;
imagefile_secsize = 512; /* minimum allowed sector size */
+ emul_packetsize = 32; /* reasonable default */
srandom((unsigned long) time(NULL));
udf_init_create_context();
@@ -740,7 +744,7 @@ main(int argc, char **argv)
context.gmtoff = tm->tm_gmtoff;
/* process options */
- while ((ch = getopt(argc, argv, "cFL:Mp:P:s:S:t:v:V:")) != -1) {
+ while ((ch = getopt(argc, argv, "cFL:Mp:P:s:S:B:t:v:V:")) != -1) {
switch (ch) {
case 'c' :
check_surface = 1;
@@ -802,6 +806,12 @@ main(int argc, char **argv)
imagefile_secsize = a_num(optarg, "secsize");
imagefile_secsize = MAX(512, imagefile_secsize);
break;
+ case 'B' :
+ emul_packetsize = a_num(optarg,
+ "blockingnr, packetsize");
+ emul_packetsize = MAX(emul_packetsize, 1);
+ emul_packetsize = MIN(emul_packetsize, 32);
+ break;
case 't' :
/* time zone overide */
context.gmtoff = a_num(optarg, "gmtoff");
Index: src/sbin/newfs_udf/udf_create.c
diff -u src/sbin/newfs_udf/udf_create.c:1.17 src/sbin/newfs_udf/udf_create.c:1.18
--- src/sbin/newfs_udf/udf_create.c:1.17 Wed Dec 23 09:13:21 2009
+++ src/sbin/newfs_udf/udf_create.c Mon Aug 5 14:11:30 2013
@@ -1,4 +1,4 @@
-/* $NetBSD: udf_create.c,v 1.17 2009/12/23 09:13:21 mbalmer Exp $ */
+/* $NetBSD: udf_create.c,v 1.18 2013/08/05 14:11:30 reinoud Exp $ */
/*
* Copyright (c) 2006, 2008 Reinoud Zandijk
@@ -28,11 +28,12 @@
#include <sys/cdefs.h>
#ifndef lint
-__RCSID("$NetBSD: udf_create.c,v 1.17 2009/12/23 09:13:21 mbalmer Exp $");
+__RCSID("$NetBSD: udf_create.c,v 1.18 2013/08/05 14:11:30 reinoud Exp $");
#endif /* not lint */
#include <stdio.h>
#include <stdlib.h>
+#include <stddef.h>
#include <string.h>
#include <errno.h>
#include <time.h>
@@ -40,6 +41,7 @@ __RCSID("$NetBSD: udf_create.c,v 1.17 20
#include <err.h>
#include <sys/types.h>
#include <sys/param.h>
+#include "unicode.h"
#include "udf_create.h"
@@ -49,6 +51,10 @@ __RCSID("$NetBSD: udf_create.c,v 1.17 20
# endif
#endif
+/*
+ * NOTE that there is some overlap between this code and the udf kernel fs.
+ * This is intentially though it might better be factored out one day.
+ */
void
udf_init_create_context(void)
@@ -82,6 +88,11 @@ udf_init_create_context(void)
context.num_files = 0;
context.num_directories = 0;
+
+ context.data_part = 0;
+ context.metadata_part = 0;
+ context.metadata_alloc_pos = 0;
+ context.data_alloc_pos = 0;
}
@@ -178,7 +189,7 @@ udf_calculate_disc_layout(int format_fla
/* all non sequential media needs an unallocated space bitmap */
layout.alloc_bitmap_dscr_size = 0;
- if ((format_flags & FORMAT_SEQUENTIAL) == 0) {
+ if ((format_flags & (FORMAT_SEQUENTIAL | FORMAT_READONLY)) == 0) {
bytes = udf_space_bitmap_len(layout.part_size_lba);
layout.alloc_bitmap_dscr_size = udf_bytes_to_sectors(bytes);
@@ -208,7 +219,7 @@ udf_calculate_disc_layout(int format_fla
* not updated sporadically
*/
- if ((format_flags & FORMAT_SEQUENTIAL) == 0) {
+ if ((format_flags & (FORMAT_SEQUENTIAL | FORMAT_READONLY)) == 0) {
#ifdef DEBUG
printf("Lost %d slack sectors at start\n", UDF_ROUNDUP(
first_lba - wrtrack_skew, align_blockingnr) -
@@ -218,8 +229,10 @@ udf_calculate_disc_layout(int format_fla
first_lba - wrtrack_skew, align_blockingnr));
#endif
- first_lba = UDF_ROUNDUP( first_lba - wrtrack_skew, align_blockingnr);
- last_lba = UDF_ROUNDDOWN(last_lba - wrtrack_skew, align_blockingnr);
+ first_lba = UDF_ROUNDUP( first_lba - wrtrack_skew,
+ align_blockingnr);
+ last_lba = UDF_ROUNDDOWN(last_lba - wrtrack_skew,
+ align_blockingnr);
}
if ((format_flags & FORMAT_SPARABLE) == 0)
@@ -335,11 +348,13 @@ udf_calculate_disc_layout(int format_fla
#endif
kbsize = (uint64_t) last_lba * sector_size;
- printf("Total space on this medium approx. %"PRIu64" KiB, %"PRIu64" MiB\n",
+ printf("Total space on this medium approx. "
+ "%"PRIu64" KiB, %"PRIu64" MiB\n",
kbsize/1024, kbsize/(1024*1024));
- kbsize = (uint64_t) (layout.part_size_lba - layout.alloc_bitmap_dscr_size
+ kbsize = (uint64_t)(layout.part_size_lba - layout.alloc_bitmap_dscr_size
- layout.meta_bitmap_dscr_size) * sector_size;
- printf("Free space on this volume approx. %"PRIu64" KiB, %"PRIu64" MiB\n\n",
+ printf("Free space on this volume approx. "
+ "%"PRIu64" KiB, %"PRIu64" MiB\n\n",
kbsize/1024, kbsize/(1024*1024));
return 0;
@@ -520,8 +535,8 @@ udf_add_app_regid(struct regid *regid)
/*
- * Fill in timestamp structure based on clock_gettime(). Time is reported back as a time_t
- * accompanied with a nano second field.
+ * Fill in timestamp structure based on clock_gettime(). Time is reported back
+ * as a time_t accompanied with a nano second field.
*
* The husec, usec and csec could be relaxed in type.
*/
@@ -557,13 +572,17 @@ udf_timespec_to_timestamp(struct timespe
csec = husec / 100; /* only 0-99 in csec */
husec -= csec * 100; /* only 0-99 in husec */
+ /* in rare cases there is overflow in csec */
+ csec = MIN(99, csec);
+ husec = MIN(99, husec);
+ usec = MIN(99, usec);
+
timestamp->centisec = csec;
timestamp->hund_usec = husec;
timestamp->usec = usec;
}
-
void
udf_set_timestamp_now(struct timestamp *timestamp)
{
@@ -574,6 +593,38 @@ udf_set_timestamp_now(struct timestamp *
}
+/* some code copied from sys/fs/udf */
+
+static void
+udf_set_timestamp(struct timestamp *timestamp, time_t value)
+{
+ struct timespec t;
+
+ memset(&t, 0, sizeof(struct timespec));
+ t.tv_sec = value;
+ t.tv_nsec = 0;
+ udf_timespec_to_timestamp(&t, timestamp);
+}
+
+
+static uint32_t
+unix_mode_to_udf_perm(mode_t mode)
+{
+ uint32_t perm;
+
+ perm = ((mode & S_IRWXO) );
+ perm |= ((mode & S_IRWXG) << 2);
+ perm |= ((mode & S_IRWXU) << 4);
+ perm |= ((mode & S_IWOTH) << 3);
+ perm |= ((mode & S_IWGRP) << 5);
+ perm |= ((mode & S_IWUSR) << 7);
+
+ return perm;
+}
+
+/* end of copied code */
+
+
int
udf_create_primaryd(void)
{
@@ -1242,7 +1293,7 @@ udf_mark_allocated(uint32_t start_lb, in
uint8_t *bpos;
uint32_t cnt, bit;
- /* make not on space used on underlying partition */
+ /* account for space used on underlying partition */
context.part_free[partnr] -= blocks;
#ifdef DEBUG
printf("mark allocated : partnr %d, start_lb %d for %d blocks\n",
@@ -1256,6 +1307,10 @@ udf_mark_allocated(uint32_t start_lb, in
case UDF_VTOP_TYPE_PHYS:
case UDF_VTOP_TYPE_SPARABLE:
case UDF_VTOP_TYPE_META:
+ if (context.part_unalloc_bits[context.vtop[partnr]] == NULL) {
+ context.part_free[partnr] = 0;
+ break;
+ }
#ifdef DEBUG
printf("Marking %d+%d as used\n", start_lb, blocks);
#endif
@@ -1274,9 +1329,7 @@ udf_mark_allocated(uint32_t start_lb, in
}
-/* --------------------------------------------------------------------- */
-
-static void
+void
udf_advance_uniqueid(void)
{
/* Minimum value of 16 : UDF 3.2.1.1, 3.3.3.4. */
@@ -1285,10 +1338,192 @@ udf_advance_uniqueid(void)
context.unique_id = 0x10;
}
+/* --------------------------------------------------------------------- */
-static int
-udf_create_parentfid(struct fileid_desc *fid, struct long_ad *parent,
- uint64_t unique_id)
+static void
+unix_to_udf_name(char *result, uint8_t *result_len,
+ char const *name, int name_len, struct charspec *chsp)
+{
+ uint16_t *raw_name;
+ uint16_t *outchp;
+ const char *inchp;
+ const char *osta_id = "OSTA Compressed Unicode";
+ int udf_chars, is_osta_typ0, bits;
+ size_t cnt;
+
+ /* allocate temporary unicode-16 buffer */
+ raw_name = malloc(1024);
+ assert(raw_name);
+
+ /* convert utf8 to unicode-16 */
+ *raw_name = 0;
+ inchp = name;
+ outchp = raw_name;
+ bits = 8;
+ for (cnt = name_len, udf_chars = 0; cnt;) {
+ *outchp = wget_utf8(&inchp, &cnt);
+ if (*outchp > 0xff)
+ bits=16;
+ outchp++;
+ udf_chars++;
+ }
+ /* null terminate just in case */
+ *outchp++ = 0;
+
+ is_osta_typ0 = (chsp->type == 0);
+ is_osta_typ0 &= (strcmp((char *) chsp->inf, osta_id) == 0);
+ if (is_osta_typ0) {
+ udf_chars = udf_CompressUnicode(udf_chars, bits,
+ (unicode_t *) raw_name,
+ (byte *) result);
+ } else {
+ printf("unix to udf name: no CHSP0 ?\n");
+ /* XXX assume 8bit char length byte latin-1 */
+ *result++ = 8; udf_chars = 1;
+ strncpy(result, name + 1, name_len);
+ udf_chars += name_len;
+ }
+ *result_len = udf_chars;
+ free(raw_name);
+}
+
+
+#define UDF_SYMLINKBUFLEN (64*1024) /* picked */
+int
+udf_encode_symlink(uint8_t **pathbufp, uint32_t *pathlenp, char *target)
+{
+ struct charspec osta_charspec;
+ struct pathcomp pathcomp;
+ char *pathbuf, *pathpos, *compnamepos;
+// char *mntonname;
+// int mntonnamelen;
+ int pathlen, len, compnamelen;
+ int error;
+
+ /* process `target' to an UDF structure */
+ pathbuf = malloc(UDF_SYMLINKBUFLEN);
+ assert(pathbuf);
+
+ *pathbufp = NULL;
+ *pathlenp = 0;
+
+ pathpos = pathbuf;
+ pathlen = 0;
+ udf_osta_charset(&osta_charspec);
+
+ if (*target == '/') {
+ /* symlink starts from the root */
+ len = UDF_PATH_COMP_SIZE;
+ memset(&pathcomp, 0, len);
+ pathcomp.type = UDF_PATH_COMP_ROOT;
+
+#if 0
+ /* XXX how to check for in makefs? */
+ /* check if its mount-point relative! */
+ mntonname = udf_node->ump->vfs_mountp->mnt_stat.f_mntonname;
+ mntonnamelen = strlen(mntonname);
+ if (strlen(target) >= mntonnamelen) {
+ if (strncmp(target, mntonname, mntonnamelen) == 0) {
+ pathcomp.type = UDF_PATH_COMP_MOUNTROOT;
+ target += mntonnamelen;
+ }
+ } else {
+ target++;
+ }
+#else
+ target++;
+#endif
+
+ memcpy(pathpos, &pathcomp, len);
+ pathpos += len;
+ pathlen += len;
+ }
+
+ error = 0;
+ while (*target) {
+ /* ignore multiple '/' */
+ while (*target == '/') {
+ target++;
+ }
+ if (!*target)
+ break;
+
+ /* extract component name */
+ compnamelen = 0;
+ compnamepos = target;
+ while ((*target) && (*target != '/')) {
+ target++;
+ compnamelen++;
+ }
+
+ /* just trunc if too long ?? (security issue) */
+ if (compnamelen >= 127) {
+ error = ENAMETOOLONG;
+ break;
+ }
+
+ /* convert unix name to UDF name */
+ len = sizeof(struct pathcomp);
+ memset(&pathcomp, 0, len);
+ pathcomp.type = UDF_PATH_COMP_NAME;
+ len = UDF_PATH_COMP_SIZE;
+
+ if ((compnamelen == 2) && (strncmp(compnamepos, "..", 2) == 0))
+ pathcomp.type = UDF_PATH_COMP_PARENTDIR;
+ if ((compnamelen == 1) && (*compnamepos == '.'))
+ pathcomp.type = UDF_PATH_COMP_CURDIR;
+
+ if (pathcomp.type == UDF_PATH_COMP_NAME) {
+ unix_to_udf_name(
+ (char *) &pathcomp.ident, &pathcomp.l_ci,
+ compnamepos, compnamelen,
+ &osta_charspec);
+ len = UDF_PATH_COMP_SIZE + pathcomp.l_ci;
+ }
+
+ if (pathlen + len >= UDF_SYMLINKBUFLEN) {
+ error = ENAMETOOLONG;
+ break;
+ }
+
+ memcpy(pathpos, &pathcomp, len);
+ pathpos += len;
+ pathlen += len;
+ }
+
+ if (error) {
+ /* aparently too big */
+ free(pathbuf);
+ return error;
+ }
+
+ /* return status of symlink contents writeout */
+ *pathbufp = (uint8_t *) pathbuf;
+ *pathlenp = pathlen;
+
+ return 0;
+
+}
+#undef UDF_SYMLINKBUFLEN
+
+
+int
+udf_fidsize(struct fileid_desc *fid)
+{
+ uint32_t size;
+
+ if (udf_rw16(fid->tag.id) != TAGID_FID)
+ errx(EINVAL, "got udf_fidsize on non FID\n");
+
+ size = UDF_FID_SIZE + fid->l_fi + udf_rw16(fid->l_iu);
+ size = (size + 3) & ~3;
+
+ return size;
+}
+
+
+int
+udf_create_parentfid(struct fileid_desc *fid, struct long_ad *parent)
{
/* the size of an empty FID is 38 but needs to be a multiple of 4 */
int fidsize = 40;
@@ -1297,7 +1532,7 @@ udf_create_parentfid(struct fileid_desc
fid->file_version_num = udf_rw16(1); /* UDF 2.3.4.1 */
fid->file_char = UDF_FILE_CHAR_DIR | UDF_FILE_CHAR_PAR;
fid->icb = *parent;
- fid->icb.longad_uniqueid = udf_rw32((uint32_t) unique_id);
+ fid->icb.longad_uniqueid = parent->longad_uniqueid;
fid->tag.desc_crc_len = udf_rw16(fidsize - UDF_DESC_TAG_LENGTH);
/* we have to do the fid here explicitly for simplicity */
@@ -1307,6 +1542,102 @@ udf_create_parentfid(struct fileid_desc
}
+void
+udf_create_fid(uint32_t diroff, struct fileid_desc *fid, char *name,
+ int file_char, struct long_ad *ref)
+{
+ struct charspec osta_charspec;
+ uint32_t endfid;
+ uint32_t fidsize, lb_rest;
+
+ memset(fid, 0, sizeof(struct fileid_desc *));
+ udf_inittag(&fid->tag, TAGID_FID, udf_rw32(ref->loc.lb_num));
+ fid->file_version_num = udf_rw16(1); /* UDF 2.3.4.1 */
+ fid->file_char = file_char;
+ fid->l_iu = udf_rw16(0);
+ fid->icb = *ref;
+ fid->icb.longad_uniqueid = ref->longad_uniqueid;
+
+ udf_osta_charset(&osta_charspec);
+ unix_to_udf_name((char *) fid->data, &fid->l_fi, name, strlen(name),
+ &osta_charspec);
+
+ /*
+ * OK, tricky part: we need to pad so the next descriptor header won't
+ * cross the sector boundary
+ */
+ endfid = diroff + udf_fidsize(fid);
+ lb_rest = context.sector_size - (endfid % context.sector_size);
+ if (lb_rest < sizeof(struct desc_tag)) {
+ /* add at least 32 */
+ fid->l_iu = udf_rw16(32);
+ udf_set_regid((struct regid *) fid->data, context.impl_name);
+ udf_add_impl_regid((struct regid *) fid->data);
+
+ unix_to_udf_name((char *) fid->data + udf_rw16(fid->l_iu),
+ &fid->l_fi, name, strlen(name), &osta_charspec);
+ }
+
+ fidsize = udf_fidsize(fid);
+ fid->tag.desc_crc_len = udf_rw16(fidsize - UDF_DESC_TAG_LENGTH);
+
+ /* make sure the header sums stays correct */
+ udf_validate_tag_and_crc_sums((union dscrptr *)fid);
+}
+
+
+static void
+udf_append_parentfid(union dscrptr *dscr, struct long_ad *parent_icb)
+{
+ struct file_entry *fe;
+ struct extfile_entry *efe;
+ struct fileid_desc *fid;
+ uint32_t l_ea;
+ uint32_t fidsize, crclen;
+ uint8_t *bpos, *data;
+
+ fe = NULL;
+ efe = NULL;
+ if (udf_rw16(dscr->tag.id) == TAGID_FENTRY) {
+ fe = &dscr->fe;
+ data = fe->data;
+ l_ea = udf_rw32(fe->l_ea);
+ } else if (udf_rw16(dscr->tag.id) == TAGID_EXTFENTRY) {
+ efe = &dscr->efe;
+ data = efe->data;
+ l_ea = udf_rw32(efe->l_ea);
+ } else {
+ errx(1, "Bad tag passed to udf_append_parentfid");
+ }
+
+ /* create '..' */
+ bpos = data + l_ea;
+ fid = (struct fileid_desc *) bpos;
+ fidsize = udf_create_parentfid(fid, parent_icb);
+
+ /* record fidlength information */
+ if (fe) {
+ fe->inf_len = udf_rw64(fidsize);
+ fe->l_ad = udf_rw32(fidsize);
+ fe->logblks_rec = udf_rw64(0); /* intern */
+ crclen = sizeof(struct file_entry);
+ } else {
+ efe->inf_len = udf_rw64(fidsize);
+ efe->obj_size = udf_rw64(fidsize);
+ efe->l_ad = udf_rw32(fidsize);
+ efe->logblks_rec = udf_rw64(0); /* intern */
+ crclen = sizeof(struct extfile_entry);
+ }
+ crclen -= 1 + UDF_DESC_TAG_LENGTH;
+ crclen += l_ea + fidsize;
+ dscr->tag.desc_crc_len = udf_rw16(crclen);
+
+ /* make sure the header sums stays correct */
+ udf_validate_tag_and_crc_sums(dscr);
+}
+
+
+
/*
* Order of extended attributes :
* ECMA 167 EAs
@@ -1425,16 +1756,14 @@ udf_extattr_append_internal(union dscrpt
int
-udf_create_new_fe(struct file_entry **fep, int file_type,
- struct long_ad *parent_icb)
+udf_create_new_fe(struct file_entry **fep, int file_type, struct stat *st)
{
struct file_entry *fe;
struct icb_tag *icb;
struct timestamp birthtime;
struct filetimes_extattr_entry *ft_extattr;
- uint32_t fidsize;
- uint8_t *bpos;
uint32_t crclen; /* XXX: should be 16; need to detect overflow */
+ uint16_t icbflags;
*fep = NULL;
fe = calloc(1, context.sector_size);
@@ -1457,14 +1786,41 @@ udf_create_new_fe(struct file_entry **fe
fe->link_cnt = udf_rw16(0); /* explicit setting */
fe->ckpoint = udf_rw32(1); /* user supplied file version */
+
udf_set_timestamp_now(&birthtime);
udf_set_timestamp_now(&fe->atime);
udf_set_timestamp_now(&fe->attrtime);
udf_set_timestamp_now(&fe->mtime);
+ /* set attributes */
+ if (st) {
+ udf_set_timestamp(&birthtime, st->st_birthtime);
+ udf_set_timestamp(&fe->atime, st->st_atime);
+ udf_set_timestamp(&fe->attrtime, st->st_ctime);
+ udf_set_timestamp(&fe->mtime, st->st_mtime);
+ fe->uid = udf_rw32(st->st_uid);
+ fe->gid = udf_rw32(st->st_gid);
+
+ fe->perm = unix_mode_to_udf_perm(st->st_mode);
+
+ icbflags = udf_rw16(fe->icbtag.flags);
+ icbflags &= ~UDF_ICB_TAG_FLAGS_SETUID;
+ icbflags &= ~UDF_ICB_TAG_FLAGS_SETGID;
+ icbflags &= ~UDF_ICB_TAG_FLAGS_STICKY;
+ if (st->st_mode & S_ISUID)
+ icbflags |= UDF_ICB_TAG_FLAGS_SETUID;
+ if (st->st_mode & S_ISGID)
+ icbflags |= UDF_ICB_TAG_FLAGS_SETGID;
+ if (st->st_mode & S_ISVTX)
+ icbflags |= UDF_ICB_TAG_FLAGS_STICKY;
+ fe->icbtag.flags = udf_rw16(icbflags);
+ }
+
udf_set_regid(&fe->imp_id, context.impl_name);
udf_add_impl_regid(&fe->imp_id);
fe->unique_id = udf_rw64(context.unique_id);
+ udf_advance_uniqueid();
+
fe->l_ea = udf_rw32(0);
/* create extended attribute to record our creation time */
@@ -1480,24 +1836,17 @@ udf_create_new_fe(struct file_entry **fe
(struct extattr_entry *) ft_extattr);
free(ft_extattr);
- /* if its a directory, create '..' */
- bpos = (uint8_t *) fe->data + udf_rw32(fe->l_ea);
- fidsize = 0;
- if (file_type == UDF_ICB_FILETYPE_DIRECTORY) {
- fidsize = udf_create_parentfid((struct fileid_desc *) bpos,
- parent_icb, context.unique_id);
- }
- udf_advance_uniqueid();
-
/* record fidlength information */
- fe->inf_len = udf_rw64(fidsize);
- fe->l_ad = udf_rw32(fidsize);
+ fe->inf_len = udf_rw64(0);
+ fe->l_ad = udf_rw32(0);
fe->logblks_rec = udf_rw64(0); /* intern */
crclen = sizeof(struct file_entry) - 1 - UDF_DESC_TAG_LENGTH;
- crclen += udf_rw32(fe->l_ea) + fidsize;
-/* XXX ensure crclen doesn't exceed UINT16_MAX ? */
+ crclen += udf_rw32(fe->l_ea);
+
+ /* make sure the header sums stays correct */
fe->tag.desc_crc_len = udf_rw16(crclen);
+ udf_validate_tag_and_crc_sums((union dscrptr *) fe);
*fep = fe;
return 0;
@@ -1505,13 +1854,13 @@ udf_create_new_fe(struct file_entry **fe
int
-udf_create_new_efe(struct extfile_entry **efep, int file_type,
- struct long_ad *parent_icb)
+udf_create_new_efe(struct extfile_entry **efep, int file_type, struct stat *st)
{
struct extfile_entry *efe;
struct icb_tag *icb;
uint32_t fidsize;
uint32_t crclen; /* XXX: should be 16; need to detect overflow */
+ uint16_t icbflags;
*efep = NULL;
efe = calloc(1, context.sector_size);
@@ -1534,32 +1883,54 @@ udf_create_new_efe(struct extfile_entry
efe->link_cnt = udf_rw16(0); /* explicit setting */
efe->ckpoint = udf_rw32(1); /* user supplied file version */
+
udf_set_timestamp_now(&efe->ctime);
udf_set_timestamp_now(&efe->atime);
udf_set_timestamp_now(&efe->attrtime);
udf_set_timestamp_now(&efe->mtime);
+ /* set attributes */
+ if (st) {
+ udf_set_timestamp(&efe->ctime, st->st_birthtime);
+ udf_set_timestamp(&efe->atime, st->st_atime);
+ udf_set_timestamp(&efe->attrtime, st->st_ctime);
+ udf_set_timestamp(&efe->mtime, st->st_mtime);
+ efe->uid = udf_rw32(st->st_uid);
+ efe->gid = udf_rw32(st->st_gid);
+
+ efe->perm = unix_mode_to_udf_perm(st->st_mode);
+
+ icbflags = udf_rw16(efe->icbtag.flags);
+ icbflags &= ~UDF_ICB_TAG_FLAGS_SETUID;
+ icbflags &= ~UDF_ICB_TAG_FLAGS_SETGID;
+ icbflags &= ~UDF_ICB_TAG_FLAGS_STICKY;
+ if (st->st_mode & S_ISUID)
+ icbflags |= UDF_ICB_TAG_FLAGS_SETUID;
+ if (st->st_mode & S_ISGID)
+ icbflags |= UDF_ICB_TAG_FLAGS_SETGID;
+ if (st->st_mode & S_ISVTX)
+ icbflags |= UDF_ICB_TAG_FLAGS_STICKY;
+ efe->icbtag.flags = udf_rw16(icbflags);
+ }
+
udf_set_regid(&efe->imp_id, context.impl_name);
udf_add_impl_regid(&efe->imp_id);
fidsize = 0;
efe->unique_id = udf_rw64(context.unique_id);
- if (file_type == UDF_ICB_FILETYPE_DIRECTORY) {
- fidsize = udf_create_parentfid((struct fileid_desc *) efe->data,
- parent_icb, context.unique_id);
- }
udf_advance_uniqueid();
/* record fidlength information */
- efe->inf_len = udf_rw64(fidsize);
- efe->obj_size = udf_rw64(fidsize);
- efe->l_ad = udf_rw32(fidsize);
+ efe->inf_len = udf_rw64(0);
+ efe->obj_size = udf_rw64(0);
+ efe->l_ad = udf_rw32(0);
efe->logblks_rec = udf_rw64(0);
crclen = sizeof(struct extfile_entry) - 1 - UDF_DESC_TAG_LENGTH;
- crclen += fidsize;
-/* XXX ensure crclen doesn't exceed UINT16_MAX ? */
+
+ /* make sure the header sums stays correct */
efe->tag.desc_crc_len = udf_rw16(crclen);
+ udf_validate_tag_and_crc_sums((union dscrptr *) efe);
*efep = efe;
return 0;
@@ -1567,8 +1938,10 @@ udf_create_new_efe(struct extfile_entry
/* --------------------------------------------------------------------- */
+/* for METADATA file appending only */
static void
-udf_append_mapping_part_to_efe(struct extfile_entry *efe, struct short_ad *mapping)
+udf_append_meta_mapping_part_to_efe(struct extfile_entry *efe,
+ struct short_ad *mapping)
{
struct icb_tag *icb;
uint64_t inf_len, obj_size, logblks_rec;
@@ -1606,8 +1979,10 @@ udf_append_mapping_part_to_efe(struct ex
}
+/* for METADATA file appending only */
static void
-udf_append_meta_mapping_to_efe(struct extfile_entry *efe, uint16_t partnr, uint32_t lb_num,
+udf_append_meta_mapping_to_efe(struct extfile_entry *efe,
+ uint16_t partnr, uint32_t lb_num,
uint64_t len)
{
struct short_ad mapping;
@@ -1624,7 +1999,7 @@ udf_append_meta_mapping_to_efe(struct ex
mapping.lb_num = udf_rw32(lb_num);
mapping.len = udf_rw32(part_len);
- udf_append_mapping_part_to_efe(efe, &mapping);
+ udf_append_meta_mapping_part_to_efe(efe, &mapping);
lb_num += part_len / context.sector_size;
len -= part_len;
@@ -1650,7 +2025,7 @@ udf_create_meta_files(void)
/* create metadata file */
meta_icb.loc.lb_num = udf_rw32(layout.meta_file);
filetype = UDF_ICB_FILETYPE_META_MAIN;
- error = udf_create_new_efe(&efe, filetype, &meta_icb);
+ error = udf_create_new_efe(&efe, filetype, NULL);
if (error)
return error;
context.meta_file = efe;
@@ -1658,7 +2033,7 @@ udf_create_meta_files(void)
/* create metadata mirror file */
meta_icb.loc.lb_num = udf_rw32(layout.meta_mirror);
filetype = UDF_ICB_FILETYPE_META_MIRROR;
- error = udf_create_new_efe(&efe, filetype, &meta_icb);
+ error = udf_create_new_efe(&efe, filetype, NULL);
if (error)
return error;
context.meta_mirror = efe;
@@ -1666,7 +2041,7 @@ udf_create_meta_files(void)
/* create metadata bitmap file */
meta_icb.loc.lb_num = udf_rw32(layout.meta_bitmap);
filetype = UDF_ICB_FILETYPE_META_BITMAP;
- error = udf_create_new_efe(&efe, filetype, &meta_icb);
+ error = udf_create_new_efe(&efe, filetype, NULL);
if (error)
return error;
context.meta_bitmap = efe;
@@ -1717,16 +2092,19 @@ udf_create_new_rootdir(union dscrptr **d
filetype = UDF_ICB_FILETYPE_DIRECTORY;
if (context.dscrver == 2) {
- error = udf_create_new_fe(&fe, filetype, &root_icb);
+ error = udf_create_new_fe(&fe, filetype, NULL);
*dscr = (union dscrptr *) fe;
} else {
- error = udf_create_new_efe(&efe, filetype, &root_icb);
+ error = udf_create_new_efe(&efe, filetype, NULL);
*dscr = (union dscrptr *) efe;
}
if (error)
return error;
- /* Rootdir has explicit only one link on creation; '..' is no link */
+ /* append '..' */
+ udf_append_parentfid(*dscr, &root_icb);
+
+ /* rootdir has explicit only one link on creation; '..' is no link */
if (context.dscrver == 2) {
fe->link_cnt = udf_rw16(1);
} else {
@@ -1740,22 +2118,120 @@ udf_create_new_rootdir(union dscrptr **d
}
+void
+udf_prepend_VAT_file(void)
+{
+ /* old style VAT has no prepend */
+ if (context.dscrver == 2) {
+ context.vat_start = 0;
+ context.vat_size = 0;
+ return;
+ }
+
+ context.vat_start = offsetof(struct udf_vat, data);
+ context.vat_size = offsetof(struct udf_vat, data);
+}
+
+
+void
+udf_vat_update(uint32_t virt, uint32_t phys)
+{
+ uint32_t *vatpos;
+ uint32_t new_size;
+
+ if (context.vtop_tp[context.metadata_part] != UDF_VTOP_TYPE_VIRT)
+ return;
+
+ new_size = MAX(context.vat_size,
+ (context.vat_start + (virt+1)*sizeof(uint32_t)));
+
+ if (new_size > context.vat_allocated) {
+ context.vat_allocated =
+ UDF_ROUNDUP(new_size, context.sector_size);
+ context.vat_contents = realloc(context.vat_contents,
+ context.vat_allocated);
+ assert(context.vat_contents);
+ /* XXX could also report error */
+ }
+ vatpos = (uint32_t *) (context.vat_contents + context.vat_start);
+ vatpos[virt] = udf_rw32(phys);
+
+ context.vat_size = MAX(context.vat_size,
+ (context.vat_start + (virt+1)*sizeof(uint32_t)));
+}
+
+
int
-udf_create_new_VAT(union dscrptr **vat_dscr)
+udf_append_VAT_file(void)
+{
+ struct udf_oldvat_tail *oldvat_tail;
+ struct udf_vat *vathdr;
+ int32_t len_diff;
+
+ /* new style VAT has VAT LVInt analog in front */
+ if (context.dscrver == 3) {
+ /* set up VATv2 descriptor */
+ vathdr = (struct udf_vat *) context.vat_contents;
+ vathdr->header_len = udf_rw16(sizeof(struct udf_vat) - 1);
+ vathdr->impl_use_len = udf_rw16(0);
+ memcpy(vathdr->logvol_id, context.logical_vol->logvol_id, 128);
+ vathdr->prev_vat = udf_rw32(UDF_NO_PREV_VAT);
+ vathdr->num_files = udf_rw32(context.num_files);
+ vathdr->num_directories = udf_rw32(context.num_directories);
+
+ vathdr->min_udf_readver = udf_rw16(context.min_udf);
+ vathdr->min_udf_writever = udf_rw16(context.min_udf);
+ vathdr->max_udf_writever = udf_rw16(context.max_udf);
+
+ return 0;
+ }
+
+ /* old style VAT has identifier appended */
+
+ /* append "*UDF Virtual Alloc Tbl" id and prev. VAT location */
+ len_diff = context.vat_allocated - context.vat_size;
+ assert(len_diff >= 0);
+ if (len_diff < (int32_t) sizeof(struct udf_oldvat_tail)) {
+ context.vat_allocated += context.sector_size;
+ context.vat_contents = realloc(context.vat_contents,
+ context.vat_allocated);
+ assert(context.vat_contents);
+ /* XXX could also report error */
+ }
+
+ oldvat_tail = (struct udf_oldvat_tail *) (context.vat_contents +
+ context.vat_size);
+
+ udf_set_regid(&oldvat_tail->id, "*UDF Virtual Alloc Tbl");
+ udf_add_udf_regid(&oldvat_tail->id);
+ oldvat_tail->prev_vat = udf_rw32(UDF_NO_PREV_VAT);
+
+ context.vat_size += sizeof(struct udf_oldvat_tail);
+
+ return 0;
+}
+
+
+int
+udf_create_VAT(union dscrptr **vat_dscr)
{
struct file_entry *fe;
struct extfile_entry *efe;
struct impl_extattr_entry *implext;
struct vatlvext_extattr_entry *vatlvext;
- struct udf_oldvat_tail *oldvat_tail;
- struct udf_vat *vathdr;
- uint32_t *vat_pos;
+ struct long_ad dataloc, *allocpos;
uint8_t *bpos, *extattr;
- uint32_t ea_len, inf_len, vat_len;
+ uint32_t ea_len, inf_len, vat_len, blks;
int filetype;
int error;
assert((layout.rootdir < 2) && (layout.fsd < 2));
+
+ memset(&dataloc, 0, sizeof(struct long_ad));
+ dataloc.len = udf_rw32(context.vat_size);
+ dataloc.loc.part_num = udf_rw16(context.data_part);
+ dataloc.loc.lb_num = udf_rw32(layout.vat);
+
if (context.dscrver == 2) {
/* old style VAT */
filetype = UDF_ICB_FILETYPE_UNKNOWN;
@@ -1785,32 +2261,29 @@ udf_create_new_VAT(union dscrptr **vat_d
vatlvext->unique_id_chk = udf_rw64(fe->unique_id);
vatlvext->num_files = udf_rw32(context.num_files);
vatlvext->num_directories = udf_rw32(context.num_directories);
- memcpy(vatlvext->logvol_id, context.logical_vol->logvol_id, 128);
+ memcpy(vatlvext->logvol_id, context.logical_vol->logvol_id,128);
udf_extattr_append_internal((union dscrptr *) fe,
(struct extattr_entry *) extattr);
free(extattr);
- /* writeout VAT locations (partition offsets) */
- vat_pos = (uint32_t *) (fe->data + udf_rw32(fe->l_ea));
- vat_pos[layout.rootdir] = udf_rw32(layout.rootdir);
- vat_pos[layout.fsd ] = udf_rw32(layout.fsd);
-
- /* Append "*UDF Virtual Alloc Tbl" id and prev. VAT location */
- oldvat_tail = (struct udf_oldvat_tail *) (vat_pos + 2);
- udf_set_regid(&oldvat_tail->id, "*UDF Virtual Alloc Tbl");
- udf_add_udf_regid(&oldvat_tail->id);
- oldvat_tail->prev_vat = udf_rw32(UDF_NO_PREV_VAT);
+ fe->icbtag.flags = udf_rw16(UDF_ICB_LONG_ALLOC);
+
+ allocpos = (struct long_ad *) (fe->data + udf_rw32(fe->l_ea));
+ *allocpos = dataloc;
/* set length */
- inf_len = 2 * 4 + sizeof(struct udf_oldvat_tail);
+ inf_len = context.vat_size;
fe->inf_len = udf_rw64(inf_len);
- fe->l_ad = udf_rw32(inf_len);
+ fe->l_ad = udf_rw32(sizeof(struct long_ad));
+ blks = UDF_ROUNDUP(inf_len, context.sector_size) /
+ context.sector_size;
+ fe->logblks_rec = udf_rw32(blks);
/* update vat descriptor's CRC length */
- vat_len = inf_len + udf_rw32(fe->l_ea) +
- sizeof(struct file_entry) - 1 - UDF_DESC_TAG_LENGTH;
+ vat_len = sizeof(struct file_entry) - 1 - UDF_DESC_TAG_LENGTH;
+ vat_len += udf_rw32(fe->l_ad) + udf_rw32(fe->l_ea);
fe->tag.desc_crc_len = udf_rw16(vat_len);
*vat_dscr = (union dscrptr *) fe;
@@ -1821,33 +2294,22 @@ udf_create_new_VAT(union dscrptr **vat_d
if (error)
return error;
- /* set up VATv2 descriptor */
- vathdr = (struct udf_vat *) efe->data;
- vathdr->header_len = udf_rw16(sizeof(struct udf_vat) - 1);
- vathdr->impl_use_len = udf_rw16(0);
- memcpy(vathdr->logvol_id, context.logical_vol->logvol_id, 128);
- vathdr->prev_vat = udf_rw32(UDF_NO_PREV_VAT);
- vathdr->num_files = udf_rw32(context.num_files);
- vathdr->num_directories = udf_rw32(context.num_directories);
-
- vathdr->min_udf_readver = udf_rw16(context.min_udf);
- vathdr->min_udf_writever = udf_rw16(context.min_udf);
- vathdr->max_udf_writever = udf_rw16(context.max_udf);
+ efe->icbtag.flags = udf_rw16(UDF_ICB_LONG_ALLOC);
- /* writeout VAT locations */
- vat_pos = (uint32_t *) vathdr->data;
- vat_pos[layout.rootdir] = udf_rw32(layout.rootdir);
- vat_pos[layout.fsd ] = udf_rw32(layout.fsd);
+ allocpos = (struct long_ad *) efe->data;
+ *allocpos = dataloc;
/* set length */
- inf_len = 2 * 4 + sizeof(struct udf_vat) - 1;
+ inf_len = context.vat_size;
efe->inf_len = udf_rw64(inf_len);
efe->obj_size = udf_rw64(inf_len);
- efe->l_ad = udf_rw32(inf_len);
- efe->logblks_rec = udf_rw32(0);
+ efe->l_ad = udf_rw32(sizeof(struct long_ad));
+ blks = UDF_ROUNDUP(inf_len, context.sector_size) /
+ context.sector_size;
+ efe->logblks_rec = udf_rw32(blks);
vat_len = sizeof(struct extfile_entry)-1 - UDF_DESC_TAG_LENGTH;
- vat_len += inf_len;
+ vat_len += udf_rw32(efe->l_ad);
efe->tag.desc_crc_len = udf_rw16(vat_len);
*vat_dscr = (union dscrptr *) efe;
Index: src/sbin/newfs_udf/udf_create.h
diff -u src/sbin/newfs_udf/udf_create.h:1.3 src/sbin/newfs_udf/udf_create.h:1.4
--- src/sbin/newfs_udf/udf_create.h:1.3 Sun Jan 18 00:18:41 2009
+++ src/sbin/newfs_udf/udf_create.h Mon Aug 5 14:11:30 2013
@@ -1,4 +1,4 @@
-/* $NetBSD: udf_create.h,v 1.3 2009/01/18 00:18:41 lukem Exp $ */
+/* $NetBSD: udf_create.h,v 1.4 2013/08/05 14:11:30 reinoud Exp $ */
/*
* Copyright (c) 2006, 2008 Reinoud Zandijk
@@ -30,6 +30,7 @@
#define _FS_UDF_UDF_CREATE_H_
#include <sys/types.h>
+#include <sys/stat.h>
#include <fs/udf/ecma167-udf.h>
#include "udf_bswap.h"
#include "udf_osta.h"
@@ -46,9 +47,10 @@
#define FORMAT_WORM 0x00080
#define FORMAT_TRACK512 0x00100
#define FORMAT_INVALID 0x00200
+#define FORMAT_READONLY 0x00400
#define FORMAT_FLAGBITS \
"\10\1WRITEONCE\2SEQUENTIAL\3REWRITABLE\4SPARABLE\5META\6LOW" \
- "\7VAT\10WORM\11TRACK512\12INVALID"
+ "\7VAT\10WORM\11TRACK512\12INVALID\13READONLY"
/* structure space */
@@ -77,10 +79,10 @@
/* handys */
#define UDF_ROUNDUP(val, gran) \
- ((gran) * (((val) + (gran)-1) / (gran)))
+ ((gran) * (((uint64_t)(val) + (gran)-1) / (gran)))
#define UDF_ROUNDDOWN(val, gran) \
- ((gran) * (((val)) / (gran)))
+ ((gran) * (((uint64_t)(val)) / (gran)))
/* disc offsets for various structures and their sizes */
@@ -163,6 +165,10 @@ struct udf_create_context {
int data_part;
int metadata_part;
+ /* block numbers as offset in partition */
+ uint32_t metadata_alloc_pos;
+ uint32_t data_alloc_pos;
+
/* derived; points *into* other structures */
struct udf_logvol_info *logvol_info; /* inside integrity */
@@ -177,6 +183,12 @@ struct udf_create_context {
/* sparable */
struct udf_sparing_table*sparing_table; /* replacements */
+ /* VAT file */
+ uint32_t vat_size; /* length */
+ uint32_t vat_allocated; /* allocated length */
+ uint32_t vat_start; /* offset 1st entry */
+ uint8_t *vat_contents; /* the VAT */
+
/* meta data partition */
struct extfile_entry *meta_file;
struct extfile_entry *meta_mirror;
@@ -221,7 +233,6 @@ int udf_validate_tag_and_crc_sums(union
void udf_set_timestamp_now(struct timestamp *timestamp);
-
void udf_inittag(struct desc_tag *tag, int tagid, uint32_t loc);
int udf_create_anchor(int num);
@@ -242,13 +253,25 @@ int udf_register_bad_block(uint32_t loca
void udf_mark_allocated(uint32_t start_lb, int partnr, uint32_t blocks);
int udf_create_new_fe(struct file_entry **fep, int file_type,
- struct long_ad *parent_icb);
+ struct stat *st);
int udf_create_new_efe(struct extfile_entry **efep, int file_type,
- struct long_ad *parent_icb);
+ struct stat *st);
+
+int udf_encode_symlink(uint8_t **pathbufp, uint32_t *pathlenp, char *target);
+
+void udf_advance_uniqueid(void);
+int udf_fidsize(struct fileid_desc *fid);
+void udf_create_fid(uint32_t diroff, struct fileid_desc *fid,
+ char *name, int namelen, struct long_ad *ref);
+int udf_create_parentfid(struct fileid_desc *fid, struct long_ad *parent);
int udf_create_meta_files(void);
int udf_create_new_rootdir(union dscrptr **dscr);
-int udf_create_new_VAT(union dscrptr **vat_dscr);
+
+int udf_create_VAT(union dscrptr **vat_dscr);
+void udf_prepend_VAT_file(void);
+void udf_vat_update(uint32_t virt, uint32_t phys);
+int udf_append_VAT_file(void);
#endif /* _FS_UDF_UDF_CREATE_H_ */
Index: src/sbin/newfs_udf/udf_write.c
diff -u src/sbin/newfs_udf/udf_write.c:1.2 src/sbin/newfs_udf/udf_write.c:1.3
--- src/sbin/newfs_udf/udf_write.c:1.2 Thu Jul 18 12:50:51 2013
+++ src/sbin/newfs_udf/udf_write.c Mon Aug 5 14:11:30 2013
@@ -1,4 +1,4 @@
-/* $NetBSD: udf_write.c,v 1.2 2013/07/18 12:50:51 reinoud Exp $ */
+/* $NetBSD: udf_write.c,v 1.3 2013/08/05 14:11:30 reinoud Exp $ */
/*
* Copyright (c) 2006, 2008, 2013 Reinoud Zandijk
@@ -28,7 +28,7 @@
#include <sys/cdefs.h>
#ifndef lint
-__RCSID("$NetBSD: udf_write.c,v 1.2 2013/07/18 12:50:51 reinoud Exp $");
+__RCSID("$NetBSD: udf_write.c,v 1.3 2013/08/05 14:11:30 reinoud Exp $");
#endif /* not lint */
#define _EXPOSE_MMC
@@ -53,18 +53,14 @@ union dscrptr *terminator_dscr;
static int
-udf_write_dscr_phys(union dscrptr *dscr, uint32_t location,
- uint32_t sects)
+udf_write_phys(void *blob, 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 = (uint8_t *) blob;
bpos += context.sector_size * cnt;
phys = location + cnt;
@@ -77,15 +73,24 @@ udf_write_dscr_phys(union dscrptr *dscr,
static int
+udf_write_dscr_phys(union dscrptr *dscr, uint32_t location,
+ uint32_t sects)
+{
+ dscr->tag.tag_loc = udf_rw32(location);
+ (void) udf_validate_tag_and_crc_sums(dscr);
+
+ return udf_write_phys(dscr, location, sects);
+}
+
+
+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;
+ uint32_t phys;
extattrhdr = NULL;
if (udf_rw16(dscr->tag.id) == TAGID_FENTRY) {
@@ -106,20 +111,52 @@ udf_write_dscr_virt(union dscrptr *dscr,
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;
+ /* determine physical location */
+ phys = context.vtop_offset[vpart];
+ if (context.vtop_tp[vpart] == UDF_VTOP_TYPE_VIRT) {
+ udf_vat_update(location, context.data_alloc_pos);
+ phys += context.data_alloc_pos++;
+ } else {
+ phys += location;
+ }
- /* NOTE linear mapping assumed in the ranges used */
- phys = context.vtop_offset[vpart] + location + cnt;
+ return udf_write_phys(dscr, phys, sects);
+}
- error = udf_write_sector(bpos, phys);
- if (error)
- return error;
- }
- return 0;
+
+void
+udf_metadata_alloc(int nblk, struct long_ad *pos)
+{
+ memset(pos, 0, sizeof(struct long_ad));
+ pos->len = udf_rw32(nblk * context.sector_size);
+ pos->loc.lb_num = udf_rw32(context.metadata_alloc_pos);
+ pos->loc.part_num = udf_rw16(context.metadata_part);
+
+ udf_mark_allocated(context.metadata_alloc_pos, context.metadata_part,
+ nblk);
+
+ context.metadata_alloc_pos += nblk;
+ if (context.metadata_part == context.data_part)
+ context.data_alloc_pos = context.metadata_alloc_pos;
}
+
+void
+udf_data_alloc(int nblk, struct long_ad *pos)
+{
+ memset(pos, 0, sizeof(struct long_ad));
+ pos->len = udf_rw32(nblk * context.sector_size);
+ pos->loc.lb_num = udf_rw32(context.data_alloc_pos);
+ pos->loc.part_num = udf_rw16(context.data_part);
+
+ udf_mark_allocated(context.data_alloc_pos, context.data_part, nblk);
+ context.data_alloc_pos += nblk;
+ if (context.metadata_part == context.data_part)
+ context.metadata_alloc_pos = context.data_alloc_pos;
+}
+
+
+
/* --------------------------------------------------------------------- */
/*
@@ -198,14 +235,13 @@ udf_derive_format(int req_enable, int re
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;
+ if (req_enable & FORMAT_READONLY) {
+ format_flags |= FORMAT_READONLY;
+ }
+
/* determine partition/media access type */
media_accesstype = UDF_ACCESSTYPE_NOT_SPECIFIED;
if (mmc_discinfo.mmc_cur & MMC_CAP_REWRITABLE) {
@@ -219,6 +255,12 @@ udf_derive_format(int req_enable, int re
if (mmc_discinfo.mmc_cur & MMC_CAP_PSEUDOOVERWRITE)
media_accesstype = UDF_ACCESSTYPE_PSEUDO_OVERWITE;
+ /* patch up media accesstype */
+ if (req_enable & FORMAT_READONLY) {
+ /* better now */
+ media_accesstype = UDF_ACCESSTYPE_READ_ONLY;
+ }
+
/* adjust minimum version limits */
if (format_flags & FORMAT_VAT)
context.min_udf = MAX(context.min_udf, 0x0150);
@@ -432,6 +474,7 @@ udf_do_newfs_prefix(void)
blockingnr = 32; /* UDF requirement */
break;
case 0x11 : /* DVD-R (DL) */
+ case 0x12 : /* DVD-RAM */
case 0x1b : /* DVD+R */
case 0x2b : /* DVD+R Dual layer */
case 0x13 : /* DVD-RW restricted overwrite */
@@ -439,7 +482,10 @@ udf_do_newfs_prefix(void)
blockingnr = 16; /* SCSI definition */
break;
case 0x41 : /* BD-R Sequential recording (SRM) */
+ case 0x42 : /* BD-R Random recording (RRM) */
+ case 0x43 : /* BD-RE */
case 0x51 : /* HD DVD-R */
+ case 0x52 : /* HD DVD-RW */
blockingnr = 32; /* SCSI definition */
break;
default:
@@ -637,7 +683,7 @@ udf_do_newfs_prefix(void)
* media report their own free/used space; no free/used space tables
* should be recorded for these.
*/
- if ((format_flags & FORMAT_SEQUENTIAL) == 0) {
+ if ((format_flags & (FORMAT_SEQUENTIAL | FORMAT_READONLY)) == 0) {
error = udf_create_space_bitmap(
layout.alloc_bitmap_dscr_size,
layout.part_size_lba,
@@ -697,6 +743,15 @@ udf_do_newfs_prefix(void)
if (error)
return error;
+ /* create VAT if needed */
+ if (format_flags & FORMAT_VAT) {
+ context.vat_allocated = context.sector_size;
+ context.vat_contents = malloc(context.vat_allocated);
+ assert(context.vat_contents);
+
+ udf_prepend_VAT_file();
+ }
+
/* create FSD and writeout */
if ((error = udf_create_fsd()))
return error;
@@ -722,9 +777,9 @@ udf_do_rootdir(void) {
return error;
udf_mark_allocated(layout.rootdir, context.metadata_part, 1);
- error = udf_write_dscr_virt(root_dscr, 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;
}
@@ -734,7 +789,8 @@ udf_do_newfs_postfix(void)
{
union dscrptr *vat_dscr;
union dscrptr *dscr;
- uint32_t loc, len;
+ struct long_ad vatdata_pos;
+ uint32_t loc, len, phys, sects;
int data_part, metadata_part;
int error;
@@ -761,7 +817,7 @@ udf_do_newfs_postfix(void)
}
/* write out unallocated space bitmap on non sequential media */
- if ((format_flags & FORMAT_SEQUENTIAL) == 0) {
+ if ((format_flags & (FORMAT_SEQUENTIAL | FORMAT_READONLY)) == 0) {
/* writeout unallocated space bitmap */
loc = layout.unalloc_space;
dscr = (union dscrptr *) (context.part_unalloc_bits[data_part]);
@@ -792,7 +848,8 @@ udf_do_newfs_postfix(void)
/* writeout unallocated space bitmap */
loc = layout.meta_bitmap_space;
- dscr = (union dscrptr *) (context.part_unalloc_bits[metadata_part]);
+ 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)
@@ -805,11 +862,31 @@ udf_do_newfs_postfix(void)
/* update lvint to reflect the newest values (no writeout) */
udf_update_lvintd(UDF_INTEGRITY_CLOSED);
- error = udf_create_new_VAT(&vat_dscr);
+ error = udf_append_VAT_file();
+ if (error)
+ return error;
+
+ /* write out VAT data */
+ sects = UDF_ROUNDUP(context.vat_size, context.sector_size) /
+ context.sector_size;
+ layout.vat = context.data_alloc_pos;
+ udf_data_alloc(sects, &vatdata_pos);
+
+ loc = udf_rw32(vatdata_pos.loc.lb_num);
+ phys = context.vtop_offset[context.data_part] + loc;
+
+ error = udf_write_phys(context.vat_contents, phys, sects);
if (error)
return error;
+ loc += sects;
+
+ /* create new VAT descriptor */
+ error = udf_create_VAT(&vat_dscr);
+ if (error)
+ return error;
+ context.data_alloc_pos++;
+ loc++;
- loc = layout.vat;
error = udf_write_dscr_virt(vat_dscr, loc, metadata_part, 1);
if (error)
return error;
Index: src/sbin/newfs_udf/udf_write.h
diff -u src/sbin/newfs_udf/udf_write.h:1.1 src/sbin/newfs_udf/udf_write.h:1.2
--- src/sbin/newfs_udf/udf_write.h:1.1 Thu Jul 18 12:44:21 2013
+++ src/sbin/newfs_udf/udf_write.h Mon Aug 5 14:11:30 2013
@@ -32,6 +32,11 @@
/* prototypes */
+int udf_write_dscr_virt(union dscrptr *dscr, uint32_t location, uint32_t vpart,
+ uint32_t sects);
+void udf_metadata_alloc(int nblk, struct long_ad *pos);
+void udf_data_alloc(int nblk, struct long_ad *pos);
+
int udf_derive_format(int req_enable, int req_disable, int force);
int udf_proces_names(void);
Added files:
Index: src/sbin/newfs_udf/unicode.h
diff -u /dev/null src/sbin/newfs_udf/unicode.h:1.1
--- /dev/null Mon Aug 5 14:11:30 2013
+++ src/sbin/newfs_udf/unicode.h Mon Aug 5 14:11:30 2013
@@ -0,0 +1,161 @@
+/* $NetBSD: unicode.h,v 1.1 2013/08/05 14:11:30 reinoud Exp $ */
+
+/*-
+ * Copyright (c) 2001, 2004 The NetBSD Foundation, Inc.
+ * 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 NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``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 FOUNDATION OR CONTRIBUTORS
+ * 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.
+ */
+
+/*-
+ * Copyright (c) 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Paul Borman at Krystal Technologies.
+ *
+ * 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.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``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 REGENTS OR CONTRIBUTORS 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.
+ */
+
+/*
+ * Routines for handling Unicode encoded in UTF-8 form, code derived from
+ * src/lib/libc/locale/utf2.c.
+ */
+static u_int16_t wget_utf8(const char **, size_t *) __unused;
+static int wput_utf8(char *, size_t, u_int16_t) __unused;
+
+/*
+ * Read one UTF8-encoded character off the string, shift the string pointer
+ * and return the character.
+ */
+static u_int16_t
+wget_utf8(const char **str, size_t *sz)
+{
+ unsigned int c;
+ u_int16_t rune = 0;
+ const char *s = *str;
+ static const int _utf_count[16] = {
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 0, 0, 0, 0, 2, 2, 3, 0,
+ };
+
+ /* must be called with at least one byte remaining */
+ assert(*sz > 0);
+
+ c = _utf_count[(s[0] & 0xf0) >> 4];
+ if (c == 0 || c > *sz) {
+ decoding_error:
+ /*
+ * The first character is in range 128-255 and doesn't
+ * mark valid a valid UTF-8 sequence. There is not much
+ * we can do with this, so handle by returning
+ * the first character as if it would be a correctly
+ * encoded ISO-8859-1 character.
+ */
+ c = 1;
+ }
+
+ switch (c) {
+ case 1:
+ rune = s[0] & 0xff;
+ break;
+ case 2:
+ if ((s[1] & 0xc0) != 0x80)
+ goto decoding_error;
+ rune = ((s[0] & 0x1F) << 6) | (s[1] & 0x3F);
+ break;
+ case 3:
+ if ((s[1] & 0xC0) != 0x80 || (s[2] & 0xC0) != 0x80)
+ goto decoding_error;
+ rune = ((s[0] & 0x0F) << 12) | ((s[1] & 0x3F) << 6)
+ | (s[2] & 0x3F);
+ break;
+ }
+
+ *str += c;
+ *sz -= c;
+ return rune;
+}
+
+/*
+ * Encode wide character and write it to the string. 'n' specifies
+ * how much buffer space remains in 's'. Returns number of bytes written
+ * to the target string 's'.
+ */
+static int
+wput_utf8(char *s, size_t n, u_int16_t wc)
+{
+ if (wc & 0xf800) {
+ if (n < 3) {
+ /* bound check failure */
+ return 0;
+ }
+
+ s[0] = 0xE0 | (wc >> 12);
+ s[1] = 0x80 | ((wc >> 6) & 0x3F);
+ s[2] = 0x80 | ((wc) & 0x3F);
+ return 3;
+ } else if (wc & 0x0780) {
+ if (n < 2) {
+ /* bound check failure */
+ return 0;
+ }
+
+ s[0] = 0xC0 | (wc >> 6);
+ s[1] = 0x80 | ((wc) & 0x3F);
+ return 2;
+ } else {
+ if (n < 1) {
+ /* bound check failure */
+ return 0;
+ }
+
+ s[0] = wc;
+ return 1;
+ }
+}