Module Name:    src
Committed By:   reinoud
Date:           Thu Dec 16 22:19:09 UTC 2021

Modified Files:
        src/sys/fs/udf: udf_subr.c

Log Message:
Fix serious issue with recordable media formatted with Win10. When closing it
after modification the VAT was written out corrupted making the disc
unreadable anymore on remount. Thanks for ig@ for spotting it in the wild!


To generate a diff of this commit:
cvs rdiff -u -r1.160 -r1.161 src/sys/fs/udf/udf_subr.c

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

Modified files:

Index: src/sys/fs/udf/udf_subr.c
diff -u src/sys/fs/udf/udf_subr.c:1.160 src/sys/fs/udf/udf_subr.c:1.161
--- src/sys/fs/udf/udf_subr.c:1.160	Wed Dec 15 22:02:30 2021
+++ src/sys/fs/udf/udf_subr.c	Thu Dec 16 22:19:08 2021
@@ -1,4 +1,4 @@
-/* $NetBSD: udf_subr.c,v 1.160 2021/12/15 22:02:30 reinoud Exp $ */
+/* $NetBSD: udf_subr.c,v 1.161 2021/12/16 22:19:08 reinoud Exp $ */
 
 /*
  * Copyright (c) 2006, 2008 Reinoud Zandijk
@@ -29,7 +29,7 @@
 
 #include <sys/cdefs.h>
 #ifndef lint
-__KERNEL_RCSID(0, "$NetBSD: udf_subr.c,v 1.160 2021/12/15 22:02:30 reinoud Exp $");
+__KERNEL_RCSID(0, "$NetBSD: udf_subr.c,v 1.161 2021/12/16 22:19:08 reinoud Exp $");
 #endif /* not lint */
 
 
@@ -2765,10 +2765,11 @@ udf_update_vat_descriptor(struct udf_mou
 	struct icb_tag *icbtag;
 	struct udf_oldvat_tail *oldvat_tl;
 	struct udf_vat *vat;
+	struct regid *regid;
 	uint64_t unique_id;
 	uint32_t lb_size;
 	uint8_t *raw_vat;
-	int filetype, error;
+	int vat_length, impl_use_len, filetype, error;
 
 	KASSERT(vat_node);
 	KASSERT(lvinfo);
@@ -2813,11 +2814,20 @@ udf_update_vat_descriptor(struct udf_mou
 			sizeof(struct udf_oldvat_tail), ump->vat_entries * 4);
 	} else {
 		/* compose the VAT2 header */
+		vat_length = sizeof(struct udf_vat);
 		vat = (struct udf_vat *) raw_vat;
-		memset(vat, 0, sizeof(struct udf_vat));
 
-		vat->header_len       = udf_rw16(152);	/* as per spec */
-		vat->impl_use_len     = udf_rw16(0);
+		error = udf_vat_read(vat_node, raw_vat, vat_length, 0);
+		if (error)
+			goto errout;
+
+		impl_use_len = udf_rw16(vat->impl_use_len);
+		vat_length += impl_use_len;
+
+		error = udf_vat_read(vat_node, raw_vat, vat_length, 0);
+		if (error)
+			goto errout;
+
 		memmove(vat->logvol_id, ump->logical_vol->logvol_id, 128);
 		vat->prev_vat         = udf_rw32(0xffffffff);
 		vat->num_files        = lvinfo->num_files;
@@ -2826,9 +2836,20 @@ udf_update_vat_descriptor(struct udf_mou
 		vat->min_udf_writever = lvinfo->min_udf_writever;
 		vat->max_udf_writever = lvinfo->max_udf_writever;
 
-		error = udf_vat_write(vat_node, raw_vat,
-			sizeof(struct udf_vat), 0);
+		if (impl_use_len >= sizeof(struct regid)) {
+			/* insert our implementation identification */
+			memset(vat->data, 0, impl_use_len);
+			regid = (struct regid *) vat->data;
+			udf_set_regid(regid, IMPL_NAME);
+			udf_add_app_regid(ump, regid);
+		} else {
+			if (impl_use_len)
+				memset(vat->data, 0, impl_use_len);
+			vat->impl_use_len = 0;
+		}
+		error = udf_vat_write(vat_node, raw_vat, vat_length, 0);
 	}
+errout:
 	free(raw_vat, M_TEMP);
 
 	return error;	/* success! */
@@ -2997,7 +3018,7 @@ udf_check_for_vat(struct udf_node *vat_n
 
 		/* definition */
 		vat = (struct udf_vat *) raw_vat;
-		vat_offset  = vat->header_len;
+		vat_offset  = udf_rw16(vat->header_len);
 		vat_entries = (vat_length - vat_offset)/4;
 
 		assert(lvinfo);

Reply via email to