Home | History | Annotate | Line # | Download | only in newfs_udf
      1  1.14    andvar /* $NetBSD: udf_core.c,v 1.14 2024/02/05 21:46:05 andvar Exp $ */
      2   1.1   reinoud 
      3   1.1   reinoud /*
      4   1.1   reinoud  * Copyright (c) 2006, 2008, 2021, 2022 Reinoud Zandijk
      5   1.1   reinoud  * All rights reserved.
      6   1.2  riastrad  *
      7   1.1   reinoud  * Redistribution and use in source and binary forms, with or without
      8   1.1   reinoud  * modification, are permitted provided that the following conditions
      9   1.1   reinoud  * are met:
     10   1.1   reinoud  * 1. Redistributions of source code must retain the above copyright
     11   1.1   reinoud  *    notice, this list of conditions and the following disclaimer.
     12   1.1   reinoud  * 2. Redistributions in binary form must reproduce the above copyright
     13   1.1   reinoud  *    notice, this list of conditions and the following disclaimer in the
     14   1.1   reinoud  *    documentation and/or other materials provided with the distribution.
     15   1.2  riastrad  *
     16   1.1   reinoud  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
     17   1.1   reinoud  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
     18   1.1   reinoud  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
     19   1.1   reinoud  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
     20   1.1   reinoud  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
     21   1.1   reinoud  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
     22   1.1   reinoud  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
     23   1.1   reinoud  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     24   1.1   reinoud  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
     25   1.1   reinoud  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     26   1.2  riastrad  *
     27   1.1   reinoud  */
     28   1.1   reinoud #if HAVE_NBTOOL_CONFIG_H
     29   1.1   reinoud #include "nbtool_config.h"
     30   1.1   reinoud #endif
     31   1.1   reinoud 
     32   1.1   reinoud #include <sys/cdefs.h>
     33  1.14    andvar __RCSID("$NetBSD: udf_core.c,v 1.14 2024/02/05 21:46:05 andvar Exp $");
     34   1.1   reinoud 
     35   1.1   reinoud #include <stdio.h>
     36   1.1   reinoud #include <stdlib.h>
     37   1.1   reinoud #include <stddef.h>
     38   1.1   reinoud #include <string.h>
     39   1.1   reinoud #include <strings.h>
     40   1.1   reinoud #include <unistd.h>
     41   1.1   reinoud #include <errno.h>
     42   1.1   reinoud #include <time.h>
     43   1.1   reinoud #include <assert.h>
     44   1.1   reinoud #include <err.h>
     45   1.1   reinoud #include <fcntl.h>
     46   1.1   reinoud #include <util.h>
     47   1.1   reinoud #include <sys/types.h>
     48   1.1   reinoud #include <sys/param.h>
     49   1.1   reinoud #include <sys/ioctl.h>
     50   1.1   reinoud #include <sys/queue.h>
     51   1.1   reinoud #include "newfs_udf.h"
     52   1.1   reinoud #include "unicode.h"
     53   1.1   reinoud #include "udf_core.h"
     54   1.1   reinoud 
     55   1.1   reinoud 
     56   1.1   reinoud /* disk partition support */
     57   1.1   reinoud #if !HAVE_NBTOOL_CONFIG_H
     58   1.1   reinoud #include "../fsck/partutil.h"
     59   1.1   reinoud #include "../fsck/partutil.c"
     60   1.1   reinoud #endif
     61   1.1   reinoud 
     62   1.1   reinoud 
     63   1.1   reinoud /* queue for temporary storage of sectors to be written out */
     64   1.1   reinoud struct wrpacket {
     65   1.1   reinoud 	uint64_t  start_sectornr;
     66   1.1   reinoud 	uint8_t	 *packet_data;
     67   1.1   reinoud 	uint64_t  present;
     68   1.1   reinoud 	TAILQ_ENTRY(wrpacket) next;
     69   1.1   reinoud };
     70   1.1   reinoud 
     71   1.1   reinoud 
     72   1.1   reinoud /* global variables describing disc and format requests */
     73   1.1   reinoud struct udf_create_context context;
     74   1.1   reinoud struct udf_disclayout     layout;
     75   1.1   reinoud 
     76   1.1   reinoud 
     77   1.1   reinoud int		 dev_fd_rdonly;		/* device: open readonly!	*/
     78   1.1   reinoud int		 dev_fd;		/* device: file descriptor	*/
     79   1.1   reinoud struct stat	 dev_fd_stat;	  	/* device: last stat info	*/
     80   1.1   reinoud char		*dev_name;		/* device: name			*/
     81   1.1   reinoud int	 	 emul_mmc_profile;	/* for files			*/
     82   1.1   reinoud int	 	 emul_packetsize;	/* for discs and files		*/
     83   1.1   reinoud int		 emul_sectorsize;	/* for files			*/
     84   1.1   reinoud off_t		 emul_size;		/* for files			*/
     85   1.1   reinoud 
     86   1.1   reinoud struct mmc_discinfo mmc_discinfo;	/* device: disc info		*/
     87   1.1   reinoud union dscrptr *terminator_dscr;		/* generic terminator descriptor*/
     88   1.1   reinoud 
     89   1.1   reinoud 
     90   1.1   reinoud /* write queue and track blocking skew */
     91   1.1   reinoud TAILQ_HEAD(wrpacket_list, wrpacket) write_queue;
     92   1.1   reinoud int	  write_queuelen;
     93   1.1   reinoud int	  write_queue_suspend;
     94   1.1   reinoud uint32_t  wrtrack_skew;			/* offset for writing sector0	*/
     95   1.1   reinoud 
     96   1.1   reinoud static void udf_init_writequeue(int write_strategy);
     97   1.1   reinoud static int  udf_writeout_writequeue(bool complete);
     98   1.1   reinoud 
     99   1.1   reinoud /*
    100   1.1   reinoud  * NOTE that there is some overlap between this code and the udf kernel fs.
    101   1.1   reinoud  * This is intentionally though it might better be factored out one day.
    102   1.1   reinoud  */
    103   1.1   reinoud 
    104   1.1   reinoud void
    105   1.1   reinoud udf_init_create_context(void)
    106   1.1   reinoud {
    107   1.1   reinoud 	/* clear */
    108   1.1   reinoud 	memset(&context, 0, sizeof(struct udf_create_context));
    109   1.1   reinoud 
    110   1.1   reinoud 	/* fill with defaults currently known */
    111   1.1   reinoud 	context.dscrver   = 3;
    112   1.1   reinoud 	context.min_udf   = 0x0102;
    113   1.1   reinoud 	context.max_udf   = 0x0250;
    114   1.1   reinoud 	context.serialnum = 1;		/* default */
    115   1.1   reinoud 
    116   1.1   reinoud 	context.gmtoff        = 0;
    117   1.1   reinoud 	context.meta_perc     = UDF_META_PERC;
    118   1.1   reinoud 	context.check_surface = 0;
    119   1.1   reinoud 	context.create_new_session  = 0;
    120   1.1   reinoud 
    121   1.1   reinoud 	context.sector_size      = 512;	/* minimum for UDF */
    122   1.1   reinoud 	context.media_accesstype = UDF_ACCESSTYPE_NOT_SPECIFIED;
    123   1.1   reinoud 	context.format_flags     = FORMAT_INVALID;
    124   1.1   reinoud 	context.write_strategy   = UDF_WRITE_PACKET;
    125   1.1   reinoud 
    126   1.1   reinoud 	context.logvol_name  = NULL;
    127   1.1   reinoud 	context.primary_name = NULL;
    128   1.1   reinoud 	context.volset_name  = NULL;
    129   1.1   reinoud 	context.fileset_name = NULL;
    130   1.1   reinoud 
    131   1.1   reinoud 	/* most basic identification */
    132   1.1   reinoud 	context.app_name	 = "*NetBSD";
    133   1.1   reinoud 	context.app_version_main = 0;
    134   1.1   reinoud 	context.app_version_sub  = 0;
    135   1.1   reinoud 	context.impl_name        = "*NetBSD";
    136   1.1   reinoud 
    137   1.1   reinoud 	context.vds_seq = 0;	/* first one starts with zero */
    138   1.1   reinoud 
    139   1.1   reinoud 	/* Minimum value of 16 : UDF 3.2.1.1, 3.3.3.4. */
    140   1.1   reinoud 	context.unique_id       = 0x10;
    141   1.1   reinoud 
    142   1.1   reinoud 	context.num_files       = 0;
    143   1.1   reinoud 	context.num_directories = 0;
    144   1.1   reinoud 
    145   1.1   reinoud 	context.data_part          = 0;
    146   1.1   reinoud 	context.metadata_part      = 0;
    147   1.1   reinoud }
    148   1.1   reinoud 
    149   1.1   reinoud 
    150   1.1   reinoud /* version can be specified as 0xabc or a.bc */
    151   1.1   reinoud static int
    152   1.1   reinoud parse_udfversion(const char *pos, uint32_t *version) {
    153   1.1   reinoud 	int hex = 0;
    154   1.1   reinoud 	char c1, c2, c3, c4;
    155   1.1   reinoud 
    156   1.1   reinoud 	*version = 0;
    157   1.1   reinoud 	if (*pos == '0') {
    158   1.1   reinoud 		pos++;
    159   1.1   reinoud 		/* expect hex format */
    160   1.1   reinoud 		hex = 1;
    161   1.1   reinoud 		if (*pos++ != 'x')
    162   1.1   reinoud 			return 1;
    163   1.1   reinoud 	}
    164   1.1   reinoud 
    165   1.1   reinoud 	c1 = *pos++;
    166   1.1   reinoud 	if (c1 < '0' || c1 > '9')
    167   1.1   reinoud 		return 1;
    168   1.1   reinoud 	c1 -= '0';
    169   1.1   reinoud 
    170   1.1   reinoud 	c2 = *pos++;
    171   1.1   reinoud 	if (!hex) {
    172   1.1   reinoud 		if (c2 != '.')
    173   1.1   reinoud 			return 1;
    174   1.1   reinoud 		c2 = *pos++;
    175   1.1   reinoud 	}
    176   1.1   reinoud 	if (c2 < '0' || c2 > '9')
    177   1.1   reinoud 		return 1;
    178   1.1   reinoud 	c2 -= '0';
    179   1.1   reinoud 
    180   1.1   reinoud 	c3 = *pos++;
    181   1.1   reinoud 	if (c3 < '0' || c3 > '9')
    182   1.1   reinoud 		return 1;
    183   1.1   reinoud 	c3 -= '0';
    184   1.1   reinoud 
    185   1.1   reinoud 	c4 = *pos++;
    186   1.1   reinoud 	if (c4 != 0)
    187   1.1   reinoud 		return 1;
    188   1.1   reinoud 
    189   1.1   reinoud 	*version = c1 * 0x100 + c2 * 0x10 + c3;
    190   1.1   reinoud 	return 0;
    191   1.1   reinoud }
    192   1.1   reinoud 
    193   1.1   reinoud 
    194   1.1   reinoud /*
    195   1.1   reinoud  * Parse a given string for an udf version.
    196   1.1   reinoud  * May exit.
    197   1.1   reinoud  */
    198   1.1   reinoud int
    199   1.1   reinoud a_udf_version(const char *s, const char *id_type)
    200   1.1   reinoud {
    201   1.1   reinoud 	uint32_t version;
    202   1.1   reinoud 
    203   1.1   reinoud 	if (parse_udfversion(s, &version))
    204   1.1   reinoud 		errx(1, "unknown %s version %s; specify as hex or float", id_type, s);
    205   1.1   reinoud 	switch (version) {
    206   1.1   reinoud 		case 0x102:
    207   1.1   reinoud 		case 0x150:
    208   1.1   reinoud 		case 0x200:
    209   1.1   reinoud 		case 0x201:
    210   1.1   reinoud 		case 0x250:
    211   1.1   reinoud 			break;
    212   1.1   reinoud 		case 0x260:
    213   1.1   reinoud 			/* we don't support this one */
    214   1.1   reinoud 			errx(1, "UDF version 0x260 is not supported");
    215   1.1   reinoud 			break;
    216   1.1   reinoud 		default:
    217   1.1   reinoud 			errx(1, "unknown %s version %s, choose from "
    218   1.1   reinoud 				"0x102, 0x150, 0x200, 0x201, 0x250",
    219   1.1   reinoud 				id_type, s);
    220   1.1   reinoud 	}
    221   1.1   reinoud 	return version;
    222   1.1   reinoud }
    223   1.1   reinoud 
    224   1.1   reinoud 
    225   1.1   reinoud static uint32_t
    226   1.1   reinoud udf_space_bitmap_len(uint32_t part_size)
    227   1.1   reinoud {
    228   1.1   reinoud 	return  sizeof(struct space_bitmap_desc)-1 +
    229   1.1   reinoud 		part_size/8;
    230   1.1   reinoud }
    231   1.1   reinoud 
    232   1.1   reinoud 
    233   1.1   reinoud uint32_t
    234   1.1   reinoud udf_bytes_to_sectors(uint64_t bytes)
    235   1.1   reinoud {
    236   1.1   reinoud 	uint32_t sector_size = context.sector_size;
    237   1.1   reinoud 	return (bytes + sector_size -1) / sector_size;
    238   1.1   reinoud }
    239   1.1   reinoud 
    240   1.1   reinoud 
    241   1.1   reinoud void
    242   1.1   reinoud udf_dump_layout(void) {
    243   1.1   reinoud #ifdef DEBUG
    244   1.1   reinoud 	int format_flags = context.format_flags;
    245   1.1   reinoud 	int sector_size  = context.sector_size;
    246   1.1   reinoud 
    247   1.1   reinoud 	printf("Summary so far\n");
    248   1.1   reinoud 	printf("\tiso9660_vrs\t\t%d\n", layout.iso9660_vrs);
    249   1.1   reinoud 	printf("\tanchor0\t\t\t%d\n", layout.anchors[0]);
    250   1.1   reinoud 	printf("\tanchor1\t\t\t%d\n", layout.anchors[1]);
    251   1.1   reinoud 	printf("\tanchor2\t\t\t%d\n", layout.anchors[2]);
    252   1.1   reinoud 	printf("\tvds1_size\t\t%d\n", layout.vds1_size);
    253   1.1   reinoud 	printf("\tvds2_size\t\t%d\n", layout.vds2_size);
    254   1.1   reinoud 	printf("\tvds1\t\t\t%d\n", layout.vds1);
    255   1.1   reinoud 	printf("\tvds2\t\t\t%d\n", layout.vds2);
    256   1.1   reinoud 	printf("\tlvis_size\t\t%d\n", layout.lvis_size);
    257   1.1   reinoud 	printf("\tlvis\t\t\t%d\n", layout.lvis);
    258   1.1   reinoud 	if (format_flags & FORMAT_SPAREABLE) {
    259   1.1   reinoud 		printf("\tspareable size\t\t%d\n", layout.spareable_area_size);
    260   1.1   reinoud 		printf("\tspareable\t\t%d\n", layout.spareable_area);
    261   1.1   reinoud 	}
    262   1.1   reinoud 	printf("\tpartition start lba\t%d\n", layout.part_start_lba);
    263   1.1   reinoud 	printf("\tpartition size\t\t%ld KiB, %ld MiB\n",
    264   1.1   reinoud 		((uint64_t) layout.part_size_lba * sector_size) / 1024,
    265   1.1   reinoud 		((uint64_t) layout.part_size_lba * sector_size) / (1024*1024));
    266   1.1   reinoud 	if ((format_flags & FORMAT_SEQUENTIAL) == 0) {
    267   1.1   reinoud 		printf("\tpart bitmap start\t%d\n",   layout.unalloc_space);
    268   1.1   reinoud 		printf("\t\tfor %d lba\n", layout.alloc_bitmap_dscr_size);
    269   1.1   reinoud 	}
    270   1.1   reinoud 	if (format_flags & FORMAT_META) {
    271   1.1   reinoud 		printf("\tmeta blockingnr\t\t%d\n", layout.meta_blockingnr);
    272   1.1   reinoud 		printf("\tmeta alignment\t\t%d\n",  layout.meta_alignment);
    273   1.1   reinoud 		printf("\tmeta size\t\t%ld KiB, %ld MiB\n",
    274   1.1   reinoud 			((uint64_t) layout.meta_part_size_lba * sector_size) / 1024,
    275   1.1   reinoud 			((uint64_t) layout.meta_part_size_lba * sector_size) / (1024*1024));
    276   1.1   reinoud 		printf("\tmeta file\t\t%d\n", layout.meta_file);
    277   1.1   reinoud 		printf("\tmeta mirror\t\t%d\n", layout.meta_mirror);
    278   1.1   reinoud 		printf("\tmeta bitmap\t\t%d\n", layout.meta_bitmap);
    279   1.1   reinoud 		printf("\tmeta bitmap start\t%d\n", layout.meta_bitmap_space);
    280   1.1   reinoud 		printf("\t\tfor %d lba\n", layout.meta_bitmap_dscr_size);
    281   1.1   reinoud 		printf("\tmeta space start\t%d\n",  layout.meta_part_start_lba);
    282   1.1   reinoud 		printf("\t\tfor %d lba\n", layout.meta_part_size_lba);
    283   1.1   reinoud 	}
    284   1.1   reinoud 	printf("\n");
    285   1.1   reinoud #endif
    286   1.1   reinoud }
    287   1.1   reinoud 
    288   1.1   reinoud 
    289   1.1   reinoud int
    290   1.1   reinoud udf_calculate_disc_layout(int min_udf,
    291   1.1   reinoud 	uint32_t first_lba, uint32_t last_lba,
    292   1.1   reinoud 	uint32_t sector_size, uint32_t blockingnr)
    293   1.1   reinoud {
    294   1.1   reinoud 	uint64_t kbsize, bytes;
    295   1.1   reinoud 	uint32_t spareable_blockingnr;
    296   1.1   reinoud 	uint32_t align_blockingnr;
    297   1.1   reinoud 	uint32_t pos, mpos;
    298   1.1   reinoud 	int	 format_flags = context.format_flags;
    299   1.1   reinoud 
    300   1.1   reinoud 	/* clear */
    301   1.1   reinoud 	memset(&layout, 0, sizeof(layout));
    302   1.1   reinoud 
    303   1.1   reinoud 	/* fill with parameters */
    304   1.1   reinoud 	layout.wrtrack_skew    = wrtrack_skew;
    305   1.1   reinoud 	layout.first_lba       = first_lba;
    306   1.1   reinoud 	layout.last_lba        = last_lba;
    307   1.1   reinoud 	layout.blockingnr      = blockingnr;
    308   1.1   reinoud 	layout.spareable_blocks = udf_spareable_blocks();
    309   1.1   reinoud 
    310   1.1   reinoud 	/* start disc layouting */
    311   1.1   reinoud 
    312   1.1   reinoud 	/*
    313   1.1   reinoud 	 * location of iso9660 vrs is defined as first sector AFTER 32kb,
    314   1.1   reinoud 	 * minimum `sector size' 2048
    315   1.1   reinoud 	 */
    316   1.1   reinoud 	layout.iso9660_vrs = ((32*1024 + sector_size - 1) / sector_size)
    317   1.1   reinoud 		+ first_lba;
    318   1.1   reinoud 
    319   1.1   reinoud 	/* anchor starts at specified offset in sectors */
    320   1.1   reinoud 	layout.anchors[0] = first_lba + 256;
    321   1.1   reinoud 	if (format_flags & FORMAT_TRACK512)
    322   1.1   reinoud 		layout.anchors[0] = first_lba + 512;
    323   1.1   reinoud 	layout.anchors[1] = last_lba - 256;
    324   1.1   reinoud 	layout.anchors[2] = last_lba;
    325   1.1   reinoud 
    326   1.1   reinoud 	/* update workable space */
    327   1.1   reinoud 	first_lba = layout.anchors[0] + blockingnr;
    328   1.1   reinoud 	last_lba  = layout.anchors[1] - 1;
    329   1.1   reinoud 
    330   1.1   reinoud 	/* XXX rest of anchor packet can be added to unallocated space descr */
    331   1.1   reinoud 
    332   1.1   reinoud 	/* reserve space for VRS and VRS copy and associated tables */
    333   1.1   reinoud 	layout.vds1_size = MAX(16, blockingnr);     /* UDF 2.2.3.1+2 */
    334   1.1   reinoud 	layout.vds1 = first_lba;
    335   1.1   reinoud 	first_lba += layout.vds1_size;              /* next packet */
    336   1.1   reinoud 
    337   1.1   reinoud 	layout.vds2_size = layout.vds1_size;
    338   1.1   reinoud 	if (format_flags & FORMAT_SEQUENTIAL) {
    339   1.1   reinoud 		/* for sequential, append them ASAP */
    340   1.1   reinoud 		layout.vds2 = first_lba;
    341   1.1   reinoud 		first_lba += layout.vds2_size;
    342   1.1   reinoud 	} else {
    343   1.1   reinoud 		layout.vds2 = layout.anchors[1] +1 - layout.vds2_size;
    344   1.1   reinoud 		last_lba = layout.vds2 - 1;
    345   1.1   reinoud 	}
    346   1.1   reinoud 
    347   1.1   reinoud 	/*
    348   1.1   reinoud 	 * Reserve space for logvol integrity sequence, at least 8192 bytes
    349   1.1   reinoud 	 * for overwritable and rewritable media UDF 2.2.4.6, ECMA 3/10.6.12.
    350   1.1   reinoud 	 */
    351   1.1   reinoud 	layout.lvis_size = MAX(8192.0/sector_size, 2 * blockingnr);
    352   1.1   reinoud 	if (layout.lvis_size * sector_size < 8192)
    353   1.1   reinoud 		layout.lvis_size++;
    354   1.1   reinoud 	if (format_flags & FORMAT_VAT)
    355   1.1   reinoud 		layout.lvis_size = 2;
    356   1.1   reinoud 	if (format_flags & FORMAT_WORM)
    357   1.1   reinoud 		layout.lvis_size = 64 * blockingnr;
    358   1.1   reinoud 
    359   1.1   reinoud 	/* TODO skip bad blocks in LVID sequence */
    360   1.1   reinoud 	layout.lvis = first_lba;
    361   1.1   reinoud 	first_lba += layout.lvis_size;
    362   1.1   reinoud 
    363   1.1   reinoud 	/* initial guess of UDF partition size */
    364   1.1   reinoud 	layout.part_start_lba = first_lba;
    365   1.1   reinoud 	layout.part_size_lba = last_lba - layout.part_start_lba;
    366   1.1   reinoud 
    367   1.1   reinoud 	/* all non sequential media needs an unallocated space bitmap */
    368   1.1   reinoud 	layout.alloc_bitmap_dscr_size = 0;
    369   1.1   reinoud 	if ((format_flags & (FORMAT_SEQUENTIAL | FORMAT_READONLY)) == 0) {
    370   1.1   reinoud 		bytes = udf_space_bitmap_len(layout.part_size_lba);
    371   1.1   reinoud 		layout.alloc_bitmap_dscr_size = udf_bytes_to_sectors(bytes);
    372   1.1   reinoud 
    373   1.1   reinoud 		/* XXX freed space map when applicable */
    374   1.1   reinoud 	}
    375   1.1   reinoud 
    376   1.1   reinoud 	spareable_blockingnr = udf_spareable_blockingnr();
    377   1.1   reinoud 	align_blockingnr = blockingnr;
    378   1.1   reinoud 
    379   1.1   reinoud 	if (format_flags & (FORMAT_SPAREABLE | FORMAT_META))
    380   1.1   reinoud 		align_blockingnr = spareable_blockingnr;
    381   1.1   reinoud 
    382   1.1   reinoud 	layout.align_blockingnr    = align_blockingnr;
    383   1.1   reinoud 	layout.spareable_blockingnr = spareable_blockingnr;
    384   1.1   reinoud 
    385   1.1   reinoud 	/*
    386   1.1   reinoud 	 * Align partition LBA space to blocking granularity. Not strictly
    387   1.1   reinoud 	 * necessary for non spareables but safer for the VRS data since it is
    388   1.1   reinoud 	 * updated sporadically
    389   1.1   reinoud 	 */
    390   1.1   reinoud 
    391   1.1   reinoud #ifdef DEBUG
    392   1.1   reinoud 	printf("Lost %lu slack sectors at start\n", UDF_ROUNDUP(
    393   1.1   reinoud 		first_lba, align_blockingnr) -
    394   1.1   reinoud 		first_lba);
    395   1.1   reinoud 	printf("Lost %lu slack sectors at end\n",
    396   1.1   reinoud 		last_lba - UDF_ROUNDDOWN(
    397   1.1   reinoud 		last_lba, align_blockingnr));
    398   1.1   reinoud #endif
    399   1.1   reinoud 
    400   1.1   reinoud 	first_lba = UDF_ROUNDUP(first_lba, align_blockingnr);
    401   1.1   reinoud 	last_lba  = UDF_ROUNDDOWN(last_lba, align_blockingnr);
    402   1.1   reinoud 
    403   1.1   reinoud 	if ((format_flags & FORMAT_SPAREABLE) == 0)
    404   1.1   reinoud 		layout.spareable_blocks = 0;
    405   1.1   reinoud 
    406   1.1   reinoud 	if (format_flags & FORMAT_SPAREABLE) {
    407   1.1   reinoud 		layout.spareable_area_size =
    408   1.1   reinoud 			layout.spareable_blocks * spareable_blockingnr;
    409   1.1   reinoud 
    410   1.1   reinoud 		/* a sparing table descriptor is a whole blockingnr sectors */
    411   1.1   reinoud 		layout.sparing_table_dscr_lbas = spareable_blockingnr;
    412   1.1   reinoud 
    413   1.1   reinoud 		/* place the descriptors at the start and end of the area */
    414   1.1   reinoud 		layout.spt_1 = first_lba;
    415   1.1   reinoud 		first_lba += layout.sparing_table_dscr_lbas;
    416   1.1   reinoud 
    417   1.1   reinoud 		layout.spt_2 = last_lba - layout.sparing_table_dscr_lbas;
    418   1.1   reinoud 		last_lba -= layout.sparing_table_dscr_lbas;
    419   1.1   reinoud 
    420   1.1   reinoud 		/* allocate spareable section */
    421   1.1   reinoud 		layout.spareable_area = first_lba;
    422   1.1   reinoud 		first_lba += layout.spareable_area_size;
    423   1.1   reinoud 	}
    424   1.1   reinoud 
    425   1.1   reinoud 	/* update guess of UDF partition size */
    426   1.1   reinoud 	layout.part_start_lba = first_lba;
    427   1.1   reinoud 	layout.part_size_lba = last_lba - layout.part_start_lba;
    428   1.1   reinoud 
    429   1.1   reinoud 	/* determine partition selection for data and metadata */
    430   1.1   reinoud 	context.data_part     = 0;
    431   1.1   reinoud 	context.metadata_part = context.data_part;
    432   1.1   reinoud 	if ((format_flags & FORMAT_VAT) || (format_flags & FORMAT_META))
    433   1.1   reinoud 		context.metadata_part = context.data_part + 1;
    434   1.1   reinoud 	context.fids_part = context.metadata_part;
    435   1.1   reinoud 	if (format_flags & FORMAT_VAT)
    436   1.1   reinoud 		context.fids_part = context.data_part;
    437   1.1   reinoud 
    438   1.1   reinoud 	/*
    439   1.1   reinoud 	 * Pick fixed logical space sector numbers for main FSD, rootdir and
    440   1.1   reinoud 	 * unallocated space. The reason for this pre-allocation is that they
    441   1.1   reinoud 	 * are referenced in the volume descriptor sequence and hence can't be
    442   1.1   reinoud 	 * allocated later.
    443   1.1   reinoud 	 */
    444   1.1   reinoud 	pos = 0;
    445   1.1   reinoud 	layout.unalloc_space = pos;
    446   1.1   reinoud 	pos += layout.alloc_bitmap_dscr_size;
    447   1.1   reinoud 
    448   1.1   reinoud 	/* claim metadata descriptors and partition space [UDF 2.2.10] */
    449   1.1   reinoud 	if (format_flags & FORMAT_META) {
    450   1.1   reinoud 		/* note: all in backing partition space */
    451   1.1   reinoud 		layout.meta_file   = pos++;
    452   1.1   reinoud 		layout.meta_bitmap = 0xffffffff;
    453   1.1   reinoud 		if (!(context.format_flags & FORMAT_READONLY))
    454   1.1   reinoud 			layout.meta_bitmap = pos++;
    455   1.1   reinoud 		layout.meta_mirror = layout.part_size_lba-1;
    456   1.1   reinoud 		layout.meta_alignment  = MAX(blockingnr, spareable_blockingnr);
    457   1.1   reinoud 		layout.meta_blockingnr = MAX(layout.meta_alignment, 32);
    458   1.1   reinoud 
    459   1.1   reinoud 		/* calculate our partition length and store in sectors */
    460   1.1   reinoud 		layout.meta_part_size_lba = layout.part_size_lba *
    461   1.1   reinoud 			((float) context.meta_perc / 100.0);
    462   1.1   reinoud 		layout.meta_part_size_lba = MAX(layout.meta_part_size_lba, 32);
    463   1.1   reinoud 		layout.meta_part_size_lba =
    464   1.1   reinoud 			UDF_ROUNDDOWN(layout.meta_part_size_lba, layout.meta_blockingnr);
    465   1.1   reinoud 
    466   1.1   reinoud 		if (!(context.format_flags & FORMAT_READONLY)) {
    467   1.1   reinoud 			/* metadata partition free space bitmap */
    468   1.1   reinoud 			bytes = udf_space_bitmap_len(layout.meta_part_size_lba);
    469   1.1   reinoud 			layout.meta_bitmap_dscr_size = udf_bytes_to_sectors(bytes);
    470   1.1   reinoud 
    471   1.1   reinoud 			layout.meta_bitmap_space = pos;
    472   1.1   reinoud 			pos += layout.meta_bitmap_dscr_size;
    473   1.1   reinoud 		}
    474   1.1   reinoud 
    475   1.1   reinoud 		layout.meta_part_start_lba  = UDF_ROUNDUP(pos, layout.meta_alignment);
    476   1.1   reinoud 		pos = layout.meta_part_start_lba + layout.meta_part_size_lba;
    477   1.1   reinoud 	}
    478   1.1   reinoud 
    479   1.1   reinoud 	if (context.metadata_part == context.data_part) {
    480   1.1   reinoud 		mpos = pos;
    481   1.1   reinoud 		layout.fsd           = mpos;	mpos += 1;
    482   1.1   reinoud 		layout.rootdir       = mpos;
    483   1.1   reinoud 		pos = mpos;
    484   1.1   reinoud 	} else {
    485   1.1   reinoud 		mpos = 0;
    486   1.1   reinoud 		layout.fsd           = mpos;	mpos += 1;
    487   1.1   reinoud 		layout.rootdir       = mpos;
    488   1.1   reinoud 	}
    489   1.1   reinoud 
    490   1.1   reinoud 	/* pos and mpos now refer to the rootdir block */
    491   1.1   reinoud 	context.alloc_pos[context.data_part] = pos;
    492   1.1   reinoud 	context.alloc_pos[context.metadata_part] = mpos;
    493   1.1   reinoud 
    494   1.1   reinoud 	udf_dump_layout();
    495   1.1   reinoud 
    496   1.1   reinoud 	kbsize = (uint64_t) last_lba * sector_size;
    497   1.1   reinoud 	printf("Total space on this medium approx. "
    498   1.1   reinoud 			"%"PRIu64" KiB, %"PRIu64" MiB\n",
    499   1.1   reinoud 			kbsize/1024, kbsize/(1024*1024));
    500   1.1   reinoud 	kbsize = (uint64_t)(layout.part_size_lba - layout.alloc_bitmap_dscr_size
    501   1.1   reinoud 		- layout.meta_bitmap_dscr_size) * sector_size;
    502   1.1   reinoud 	printf("Recordable free space on this volume approx.  "
    503   1.1   reinoud 			"%"PRIu64" KiB, %"PRIu64" MiB\n\n",
    504   1.1   reinoud 			kbsize/1024, kbsize/(1024*1024));
    505   1.1   reinoud 
    506   1.1   reinoud 	return 0;
    507   1.1   reinoud }
    508   1.1   reinoud 
    509   1.1   reinoud 
    510   1.1   reinoud /*
    511   1.1   reinoud  * Check if the blob starts with a good UDF tag. Tags are protected by a
    512   1.1   reinoud  * checksum over the header, except one byte at position 4 that is the
    513   1.1   reinoud  * checksum itself.
    514   1.1   reinoud  */
    515   1.1   reinoud int
    516   1.1   reinoud udf_check_tag(void *blob)
    517   1.1   reinoud {
    518   1.1   reinoud 	struct desc_tag *tag = blob;
    519   1.1   reinoud 	uint8_t *pos, sum, cnt;
    520   1.1   reinoud 
    521   1.1   reinoud 	/* check TAG header checksum */
    522   1.1   reinoud 	pos = (uint8_t *) tag;
    523   1.1   reinoud 	sum = 0;
    524   1.1   reinoud 
    525   1.1   reinoud 	for(cnt = 0; cnt < 16; cnt++) {
    526   1.1   reinoud 		if (cnt != 4)
    527   1.1   reinoud 			sum += *pos;
    528   1.1   reinoud 		pos++;
    529   1.1   reinoud 	}
    530   1.1   reinoud 	if (sum != tag->cksum) {
    531   1.1   reinoud 		/* bad tag header checksum; this is not a valid tag */
    532   1.1   reinoud 		return EINVAL;
    533   1.1   reinoud 	}
    534   1.1   reinoud 
    535   1.1   reinoud 	return 0;
    536   1.1   reinoud }
    537   1.1   reinoud 
    538   1.1   reinoud 
    539   1.1   reinoud /*
    540   1.1   reinoud  * check tag payload will check descriptor CRC as specified.
    541   1.1   reinoud  * If the descriptor is too long, it will return EIO otherwise EINVAL.
    542   1.1   reinoud  */
    543   1.1   reinoud int
    544   1.1   reinoud udf_check_tag_payload(void *blob, uint32_t max_length)
    545   1.1   reinoud {
    546   1.1   reinoud 	struct desc_tag *tag = blob;
    547   1.1   reinoud 	uint16_t crc, crc_len;
    548   1.1   reinoud 
    549   1.1   reinoud 	crc_len = udf_rw16(tag->desc_crc_len);
    550   1.1   reinoud 
    551   1.1   reinoud 	/* check payload CRC if applicable */
    552   1.1   reinoud 	if (crc_len == 0)
    553   1.1   reinoud 		return 0;
    554   1.1   reinoud 
    555   1.1   reinoud 	if (crc_len > max_length)
    556   1.1   reinoud 		return EIO;
    557   1.1   reinoud 
    558   1.1   reinoud 	crc = udf_cksum(((uint8_t *) tag) + UDF_DESC_TAG_LENGTH, crc_len);
    559   1.1   reinoud 	if (crc != udf_rw16(tag->desc_crc)) {
    560   1.1   reinoud 		/* bad payload CRC; this is a broken tag */
    561   1.1   reinoud 		return EINVAL;
    562   1.1   reinoud 	}
    563   1.1   reinoud 
    564   1.1   reinoud 	return 0;
    565   1.1   reinoud }
    566   1.1   reinoud 
    567   1.1   reinoud 
    568   1.1   reinoud int
    569   1.1   reinoud udf_check_tag_and_location(void *blob, uint32_t location)
    570   1.1   reinoud {
    571   1.1   reinoud 	struct desc_tag *tag = blob;
    572   1.1   reinoud 
    573   1.1   reinoud 	if (udf_check_tag(blob))
    574   1.1   reinoud 		return 1;
    575   1.1   reinoud 	if (udf_rw32(tag->tag_loc) != location)
    576   1.1   reinoud 		return 1;
    577   1.1   reinoud 	return 0;
    578   1.1   reinoud }
    579   1.1   reinoud 
    580   1.1   reinoud 
    581   1.1   reinoud int
    582   1.1   reinoud udf_validate_tag_sum(union dscrptr *dscr)
    583   1.1   reinoud {
    584   1.1   reinoud 	struct desc_tag *tag = &dscr->tag;
    585   1.1   reinoud 	uint8_t *pos, sum, cnt;
    586   1.1   reinoud 
    587   1.1   reinoud 	/* calculate TAG header checksum */
    588   1.1   reinoud 	pos = (uint8_t *) tag;
    589   1.1   reinoud 	sum = 0;
    590   1.1   reinoud 
    591   1.1   reinoud 	for (cnt = 0; cnt < 16; cnt++) {
    592   1.1   reinoud 		if (cnt != 4) sum += *pos;
    593   1.1   reinoud 		pos++;
    594   1.1   reinoud 	};
    595   1.1   reinoud 	tag->cksum = sum;	/* 8 bit */
    596   1.1   reinoud 
    597   1.1   reinoud 	return 0;
    598   1.1   reinoud }
    599   1.1   reinoud 
    600   1.1   reinoud 
    601   1.1   reinoud /* assumes sector number of descriptor to be already present */
    602   1.1   reinoud int
    603   1.1   reinoud udf_validate_tag_and_crc_sums(union dscrptr *dscr)
    604   1.1   reinoud {
    605   1.1   reinoud 	struct desc_tag *tag = &dscr->tag;
    606   1.1   reinoud 	uint16_t crc;
    607   1.1   reinoud 
    608   1.1   reinoud 	/* check payload CRC if applicable */
    609   1.1   reinoud 	if (udf_rw16(tag->desc_crc_len) > 0) {
    610   1.1   reinoud 		crc = udf_cksum(((uint8_t *) tag) + UDF_DESC_TAG_LENGTH,
    611   1.1   reinoud 			udf_rw16(tag->desc_crc_len));
    612   1.1   reinoud 		tag->desc_crc = udf_rw16(crc);
    613   1.1   reinoud 	};
    614   1.1   reinoud 
    615   1.1   reinoud 	/* calculate TAG header checksum */
    616   1.1   reinoud 	return udf_validate_tag_sum(dscr);
    617   1.1   reinoud }
    618   1.1   reinoud 
    619   1.1   reinoud 
    620   1.1   reinoud void
    621   1.1   reinoud udf_inittag(struct desc_tag *tag, int tagid, uint32_t loc)
    622   1.1   reinoud {
    623   1.1   reinoud 	tag->id 		= udf_rw16(tagid);
    624   1.1   reinoud 	tag->descriptor_ver	= udf_rw16(context.dscrver);
    625   1.1   reinoud 	tag->cksum		= 0;
    626   1.1   reinoud 	tag->reserved		= 0;
    627   1.1   reinoud 	tag->serial_num		= udf_rw16(context.serialnum);
    628   1.1   reinoud 	tag->tag_loc            = udf_rw32(loc);
    629   1.1   reinoud }
    630   1.1   reinoud 
    631   1.1   reinoud 
    632   1.1   reinoud int
    633   1.1   reinoud udf_create_anchor(int num)
    634   1.1   reinoud {
    635   1.1   reinoud 	struct anchor_vdp *avdp;
    636   1.1   reinoud 	uint32_t vds1_extent_len = layout.vds1_size * context.sector_size;
    637   1.1   reinoud 	uint32_t vds2_extent_len = layout.vds2_size * context.sector_size;
    638   1.1   reinoud 
    639   1.1   reinoud 	avdp = context.anchors[num];
    640   1.1   reinoud 	if (!avdp)
    641   1.1   reinoud 		if ((avdp = calloc(1, context.sector_size)) == NULL)
    642   1.1   reinoud 			return ENOMEM;
    643   1.1   reinoud 
    644   1.1   reinoud 	udf_inittag(&avdp->tag, TAGID_ANCHOR, layout.anchors[num]);
    645   1.1   reinoud 
    646   1.1   reinoud 	avdp->main_vds_ex.loc = udf_rw32(layout.vds1);
    647   1.1   reinoud 	avdp->main_vds_ex.len = udf_rw32(vds1_extent_len);
    648   1.1   reinoud 
    649   1.1   reinoud 	avdp->reserve_vds_ex.loc = udf_rw32(layout.vds2);
    650   1.1   reinoud 	avdp->reserve_vds_ex.len = udf_rw32(vds2_extent_len);
    651   1.1   reinoud 
    652   1.1   reinoud 	/* CRC length for an anchor is 512 - tag length; defined in Ecma 167 */
    653   1.1   reinoud 	avdp->tag.desc_crc_len = udf_rw16(512-UDF_DESC_TAG_LENGTH);
    654   1.1   reinoud 
    655   1.1   reinoud 	context.anchors[num] = avdp;
    656   1.1   reinoud 	return 0;
    657   1.1   reinoud }
    658   1.1   reinoud 
    659   1.1   reinoud 
    660   1.1   reinoud void
    661   1.1   reinoud udf_create_terminator(union dscrptr *dscr, uint32_t loc)
    662   1.1   reinoud {
    663   1.1   reinoud 	memset(dscr, 0, context.sector_size);
    664   1.1   reinoud 	udf_inittag(&dscr->tag, TAGID_TERM, loc);
    665   1.1   reinoud 
    666   1.1   reinoud 	/* CRC length for an anchor is 512 - tag length; defined in Ecma 167 */
    667   1.1   reinoud 	dscr->tag.desc_crc_len = udf_rw16(512-UDF_DESC_TAG_LENGTH);
    668   1.1   reinoud }
    669   1.1   reinoud 
    670   1.1   reinoud 
    671   1.1   reinoud void
    672   1.1   reinoud udf_osta_charset(struct charspec *charspec)
    673   1.1   reinoud {
    674   1.1   reinoud 	memset(charspec, 0, sizeof(*charspec));
    675   1.1   reinoud 	charspec->type = 0;
    676   1.1   reinoud 	strcpy((char *) charspec->inf, "OSTA Compressed Unicode");
    677   1.1   reinoud }
    678   1.1   reinoud 
    679   1.1   reinoud 
    680   1.1   reinoud /* ---- shared from kernel's udf_subr.c, slightly modified ---- */
    681   1.1   reinoud void
    682   1.1   reinoud udf_to_unix_name(char *result, int result_len, char *id, int len,
    683   1.1   reinoud 	struct charspec *chsp)
    684   1.1   reinoud {
    685   1.1   reinoud 	uint16_t   *raw_name, *unix_name;
    686   1.1   reinoud 	uint16_t   *inchp, ch;
    687   1.1   reinoud 	char	   *outchp;
    688   1.1   reinoud 	const char *osta_id = "OSTA Compressed Unicode";
    689   1.1   reinoud 	int         ucode_chars, nice_uchars, is_osta_typ0, nout;
    690   1.1   reinoud 
    691   1.1   reinoud 	raw_name = malloc(2048 * sizeof(uint16_t));
    692   1.1   reinoud 	assert(raw_name);
    693   1.1   reinoud 
    694   1.1   reinoud 	unix_name = raw_name + 1024;			/* split space in half */
    695   1.1   reinoud 	assert(sizeof(char) == sizeof(uint8_t));
    696   1.1   reinoud 	outchp = result;
    697   1.1   reinoud 
    698   1.1   reinoud 	is_osta_typ0  = (chsp->type == 0);
    699   1.1   reinoud 	is_osta_typ0 &= (strcmp((char *) chsp->inf, osta_id) == 0);
    700   1.1   reinoud 	if (is_osta_typ0) {
    701   1.1   reinoud 		/* TODO clean up */
    702   1.1   reinoud 		*raw_name = *unix_name = 0;
    703   1.1   reinoud 		ucode_chars = udf_UncompressUnicode(len, (uint8_t *) id, raw_name);
    704   1.1   reinoud 		ucode_chars = MIN(ucode_chars, UnicodeLength((unicode_t *) raw_name));
    705   1.1   reinoud 		nice_uchars = UDFTransName(unix_name, raw_name, ucode_chars);
    706   1.1   reinoud 		/* output UTF8 */
    707   1.1   reinoud 		for (inchp = unix_name; nice_uchars>0; inchp++, nice_uchars--) {
    708   1.1   reinoud 			ch = *inchp;
    709   1.1   reinoud 			nout = wput_utf8(outchp, result_len, ch);
    710   1.1   reinoud 			outchp += nout; result_len -= nout;
    711   1.1   reinoud 			if (!ch) break;
    712   1.1   reinoud 		}
    713   1.1   reinoud 		*outchp++ = 0;
    714   1.1   reinoud 	} else {
    715   1.1   reinoud 		/* assume 8bit char length byte latin-1 */
    716   1.1   reinoud 		assert(*id == 8);
    717   1.1   reinoud 		assert(strlen((char *) (id+1)) <= NAME_MAX);
    718   1.1   reinoud 		memcpy((char *) result, (char *) (id+1), strlen((char *) (id+1)));
    719   1.1   reinoud 	}
    720   1.1   reinoud 	free(raw_name);
    721   1.1   reinoud }
    722   1.1   reinoud 
    723   1.1   reinoud 
    724   1.1   reinoud void
    725   1.1   reinoud unix_to_udf_name(char *result, uint8_t *result_len, char const *name, int name_len,
    726   1.1   reinoud 	struct charspec *chsp)
    727   1.1   reinoud {
    728   1.1   reinoud 	uint16_t   *raw_name;
    729   1.1   reinoud 	uint16_t   *outchp;
    730   1.1   reinoud 	const char *inchp;
    731   1.1   reinoud 	const char *osta_id = "OSTA Compressed Unicode";
    732   1.1   reinoud 	int         udf_chars, is_osta_typ0, bits;
    733   1.1   reinoud 	size_t      cnt;
    734   1.1   reinoud 
    735   1.1   reinoud 	/* allocate temporary unicode-16 buffer */
    736   1.1   reinoud 	raw_name = malloc(1024);
    737   1.1   reinoud 	assert(raw_name);
    738   1.1   reinoud 
    739   1.1   reinoud 	/* convert utf8 to unicode-16 */
    740   1.1   reinoud 	*raw_name = 0;
    741   1.1   reinoud 	inchp  = name;
    742   1.1   reinoud 	outchp = raw_name;
    743   1.1   reinoud 	bits = 8;
    744   1.1   reinoud 	for (cnt = name_len, udf_chars = 0; cnt;) {
    745   1.1   reinoud 		*outchp = wget_utf8(&inchp, &cnt);
    746   1.1   reinoud 		if (*outchp > 0xff)
    747   1.1   reinoud 			bits=16;
    748   1.1   reinoud 		outchp++;
    749   1.1   reinoud 		udf_chars++;
    750   1.1   reinoud 	}
    751   1.1   reinoud 	/* null terminate just in case */
    752   1.1   reinoud 	*outchp++ = 0;
    753   1.1   reinoud 
    754   1.1   reinoud 	is_osta_typ0  = (chsp->type == 0);
    755   1.1   reinoud 	is_osta_typ0 &= (strcmp((char *) chsp->inf, osta_id) == 0);
    756   1.1   reinoud 	if (is_osta_typ0) {
    757   1.1   reinoud 		udf_chars = udf_CompressUnicode(udf_chars, bits,
    758   1.1   reinoud 				(unicode_t *) raw_name,
    759   1.1   reinoud 				(byte *) result);
    760   1.1   reinoud 	} else {
    761   1.1   reinoud 		printf("unix to udf name: no CHSP0 ?\n");
    762   1.1   reinoud 		/* XXX assume 8bit char length byte latin-1 */
    763   1.1   reinoud 		*result++ = 8; udf_chars = 1;
    764   1.1   reinoud 		strncpy(result, name + 1, name_len);
    765   1.1   reinoud 		udf_chars += name_len;
    766   1.1   reinoud 	}
    767   1.1   reinoud 	*result_len = udf_chars;
    768   1.1   reinoud 	free(raw_name);
    769   1.1   reinoud }
    770   1.1   reinoud 
    771   1.1   reinoud 
    772   1.1   reinoud /* first call udf_set_regid and then the suffix */
    773   1.1   reinoud void
    774   1.1   reinoud udf_set_regid(struct regid *regid, char const *name)
    775   1.1   reinoud {
    776   1.1   reinoud 	memset(regid, 0, sizeof(*regid));
    777   1.1   reinoud 	regid->flags    = 0;		/* not dirty and not protected */
    778   1.1   reinoud 	strcpy((char *) regid->id, name);
    779   1.1   reinoud }
    780   1.1   reinoud 
    781   1.1   reinoud 
    782   1.1   reinoud void
    783   1.1   reinoud udf_add_domain_regid(struct regid *regid)
    784   1.1   reinoud {
    785   1.1   reinoud 	uint16_t *ver;
    786   1.1   reinoud 
    787   1.1   reinoud 	ver  = (uint16_t *) regid->id_suffix;
    788   1.1   reinoud 	*ver = udf_rw16(context.min_udf);
    789   1.1   reinoud }
    790   1.1   reinoud 
    791   1.1   reinoud 
    792   1.1   reinoud void
    793   1.1   reinoud udf_add_udf_regid(struct regid *regid)
    794   1.1   reinoud {
    795   1.1   reinoud 	uint16_t *ver;
    796   1.1   reinoud 
    797   1.1   reinoud 	ver  = (uint16_t *) regid->id_suffix;
    798   1.1   reinoud 	*ver = udf_rw16(context.min_udf);
    799   1.1   reinoud 
    800   1.1   reinoud 	regid->id_suffix[2] = 4;	/* unix */
    801   1.1   reinoud 	regid->id_suffix[3] = 8;	/* NetBSD */
    802   1.1   reinoud }
    803   1.1   reinoud 
    804   1.1   reinoud 
    805   1.1   reinoud void
    806   1.1   reinoud udf_add_impl_regid(struct regid *regid)
    807   1.1   reinoud {
    808   1.1   reinoud 	regid->id_suffix[0] = 4;	/* unix */
    809   1.1   reinoud 	regid->id_suffix[1] = 8;	/* NetBSD */
    810   1.1   reinoud }
    811   1.1   reinoud 
    812   1.1   reinoud 
    813   1.1   reinoud void
    814   1.1   reinoud udf_add_app_regid(struct regid *regid)
    815   1.1   reinoud {
    816   1.1   reinoud 	regid->id_suffix[0] = context.app_version_main;
    817   1.1   reinoud 	regid->id_suffix[1] = context.app_version_sub;
    818   1.1   reinoud }
    819   1.1   reinoud 
    820   1.1   reinoud 
    821   1.2  riastrad /*
    822   1.1   reinoud  * Timestamp to timespec conversion code is taken with small modifications
    823   1.1   reinoud  * from FreeBSD /sys/fs/udf by Scott Long <scottl (at) freebsd.org>
    824   1.1   reinoud  */
    825   1.1   reinoud 
    826   1.1   reinoud static int mon_lens[2][12] = {
    827   1.1   reinoud 	{31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31},
    828   1.1   reinoud 	{31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}
    829   1.1   reinoud };
    830   1.1   reinoud 
    831   1.1   reinoud 
    832   1.1   reinoud static int
    833   1.1   reinoud udf_isaleapyear(int year)
    834   1.2  riastrad {
    835   1.1   reinoud 	int i;
    836   1.2  riastrad 
    837   1.1   reinoud 	i = (year % 4) ? 0 : 1;
    838   1.1   reinoud 	i &= (year % 100) ? 1 : 0;
    839   1.1   reinoud 	i |= (year % 400) ? 0 : 1;
    840   1.2  riastrad 
    841   1.1   reinoud 	return i;
    842   1.1   reinoud }
    843   1.1   reinoud 
    844   1.1   reinoud 
    845   1.1   reinoud void
    846   1.1   reinoud udf_timestamp_to_timespec(struct timestamp *timestamp, struct timespec *timespec)
    847   1.1   reinoud {
    848   1.1   reinoud 	uint32_t usecs, secs, nsecs;
    849   1.1   reinoud 	uint16_t tz;
    850   1.1   reinoud 	int i, lpyear, daysinyear, year;
    851   1.1   reinoud 
    852   1.1   reinoud 	timespec->tv_sec  = secs  = 0;
    853   1.1   reinoud 	timespec->tv_nsec = nsecs = 0;
    854   1.1   reinoud 
    855   1.1   reinoud        /*
    856   1.1   reinoud 	* DirectCD seems to like using bogus year values.
    857   1.1   reinoud 	* Distrust time->month especially, since it will be used for an array
    858   1.1   reinoud 	* index.
    859   1.1   reinoud 	*/
    860   1.1   reinoud 	year = udf_rw16(timestamp->year);
    861   1.1   reinoud 	if ((year < 1970) || (timestamp->month > 12)) {
    862   1.1   reinoud 		return;
    863   1.1   reinoud 	}
    864   1.2  riastrad 
    865   1.1   reinoud 	/* Calculate the time and day */
    866   1.1   reinoud 	usecs = timestamp->usec + 100*timestamp->hund_usec + 10000*timestamp->centisec;
    867   1.1   reinoud 	nsecs = usecs * 1000;
    868   1.2  riastrad 	secs  = timestamp->second;
    869   1.1   reinoud 	secs += timestamp->minute * 60;
    870   1.1   reinoud 	secs += timestamp->hour * 3600;
    871   1.1   reinoud 	secs += (timestamp->day-1) * 3600 * 24;			/* day : 1-31 */
    872   1.2  riastrad 
    873   1.1   reinoud 	/* Calclulate the month */
    874   1.1   reinoud 	lpyear = udf_isaleapyear(year);
    875   1.1   reinoud 	for (i = 1; i < timestamp->month; i++)
    876   1.1   reinoud 		secs += mon_lens[lpyear][i-1] * 3600 * 24;	/* month: 1-12 */
    877   1.2  riastrad 
    878   1.2  riastrad 	for (i = 1970; i < year; i++) {
    879   1.1   reinoud 		daysinyear = udf_isaleapyear(i) + 365 ;
    880   1.1   reinoud 		secs += daysinyear * 3600 * 24;
    881   1.1   reinoud 	}
    882   1.1   reinoud 
    883   1.1   reinoud 	/*
    884   1.1   reinoud 	 * Calculate the time zone.  The timezone is 12 bit signed 2's
    885   1.1   reinoud 	 * compliment, so we gotta do some extra magic to handle it right.
    886   1.1   reinoud 	 */
    887   1.1   reinoud 	tz  = udf_rw16(timestamp->type_tz);
    888   1.1   reinoud 	tz &= 0x0fff;				/* only lower 12 bits are significant */
    889  1.14    andvar 	if (tz & 0x0800)			/* sign extension */
    890   1.1   reinoud 		tz |= 0xf000;
    891   1.1   reinoud 
    892   1.1   reinoud 	/* TODO check timezone conversion */
    893   1.1   reinoud #if 1
    894   1.1   reinoud 	/* check if we are specified a timezone to convert */
    895   1.1   reinoud 	if (udf_rw16(timestamp->type_tz) & 0x1000)
    896   1.1   reinoud 		if ((int16_t) tz != -2047)
    897   1.1   reinoud 			secs -= (int16_t) tz * 60;
    898   1.1   reinoud #endif
    899   1.1   reinoud 	timespec->tv_sec  = secs;
    900   1.1   reinoud 	timespec->tv_nsec = nsecs;
    901   1.1   reinoud }
    902   1.1   reinoud 
    903   1.1   reinoud 
    904   1.1   reinoud /*
    905   1.1   reinoud  * Fill in timestamp structure based on clock_gettime(). Time is reported back
    906   1.1   reinoud  * as a time_t accompanied with a nano second field.
    907   1.1   reinoud  *
    908   1.1   reinoud  * The husec, usec and csec could be relaxed in type.
    909   1.1   reinoud  */
    910   1.1   reinoud void
    911   1.1   reinoud udf_timespec_to_timestamp(struct timespec *timespec, struct timestamp *timestamp)
    912   1.1   reinoud {
    913   1.1   reinoud 	struct tm tm;
    914   1.1   reinoud 	uint64_t husec, usec, csec;
    915   1.1   reinoud 
    916   1.1   reinoud 	memset(timestamp, 0, sizeof(*timestamp));
    917   1.1   reinoud 	gmtime_r(&timespec->tv_sec, &tm);
    918   1.1   reinoud 
    919   1.1   reinoud 	/*
    920   1.1   reinoud 	 * Time type and time zone : see ECMA 1/7.3, UDF 2., 2.1.4.1, 3.1.1.
    921   1.1   reinoud 	 *
    922   1.1   reinoud 	 * Lower 12 bits are two complement signed timezone offset if bit 12
    923   1.1   reinoud 	 * (method 1) is clear. Otherwise if bit 12 is set, specify timezone
    924   1.1   reinoud 	 * offset to -2047 i.e. unsigned `zero'
    925   1.1   reinoud 	 */
    926   1.1   reinoud 
    927   1.1   reinoud 	/* set method 1 for CUT/GMT */
    928   1.1   reinoud 	timestamp->type_tz	= udf_rw16((1<<12) + 0);
    929   1.1   reinoud 	timestamp->year		= udf_rw16(tm.tm_year + 1900);
    930   1.1   reinoud 	timestamp->month	= tm.tm_mon + 1;	/* `tm' uses 0..11 for months */
    931   1.1   reinoud 	timestamp->day		= tm.tm_mday;
    932   1.1   reinoud 	timestamp->hour		= tm.tm_hour;
    933   1.1   reinoud 	timestamp->minute	= tm.tm_min;
    934   1.1   reinoud 	timestamp->second	= tm.tm_sec;
    935   1.1   reinoud 
    936   1.1   reinoud 	usec   = (timespec->tv_nsec + 500) / 1000;	/* round */
    937   1.1   reinoud 	husec  =   usec / 100;
    938   1.1   reinoud 	usec  -=  husec * 100;				/* only 0-99 in usec  */
    939   1.1   reinoud 	csec   =  husec / 100;				/* only 0-99 in csec  */
    940   1.1   reinoud 	husec -=   csec * 100;				/* only 0-99 in husec */
    941   1.1   reinoud 
    942   1.1   reinoud 	/* in rare cases there is overflow in csec */
    943   1.1   reinoud 	csec  = MIN(99, csec);
    944   1.1   reinoud 	husec = MIN(99, husec);
    945   1.1   reinoud 	usec  = MIN(99, usec);
    946   1.1   reinoud 
    947   1.1   reinoud 	timestamp->centisec	= csec;
    948   1.1   reinoud 	timestamp->hund_usec	= husec;
    949   1.1   reinoud 	timestamp->usec		= usec;
    950   1.1   reinoud }
    951   1.1   reinoud 
    952   1.1   reinoud 
    953   1.1   reinoud static void
    954   1.1   reinoud udf_set_timestamp(struct timestamp *timestamp, time_t value)
    955   1.1   reinoud {
    956   1.1   reinoud 	struct timespec t;
    957   1.1   reinoud 
    958   1.1   reinoud 	memset(&t, 0, sizeof(struct timespec));
    959   1.1   reinoud 	t.tv_sec  = value;
    960   1.1   reinoud 	t.tv_nsec = 0;
    961   1.1   reinoud 	udf_timespec_to_timestamp(&t, timestamp);
    962   1.1   reinoud }
    963   1.1   reinoud 
    964   1.1   reinoud 
    965   1.1   reinoud static uint32_t
    966   1.1   reinoud unix_mode_to_udf_perm(mode_t mode)
    967   1.1   reinoud {
    968   1.1   reinoud 	uint32_t perm;
    969   1.2  riastrad 
    970   1.1   reinoud 	perm  = ((mode & S_IRWXO)     );
    971   1.1   reinoud 	perm |= ((mode & S_IRWXG) << 2);
    972   1.1   reinoud 	perm |= ((mode & S_IRWXU) << 4);
    973   1.1   reinoud 	perm |= ((mode & S_IWOTH) << 3);
    974   1.1   reinoud 	perm |= ((mode & S_IWGRP) << 5);
    975   1.1   reinoud 	perm |= ((mode & S_IWUSR) << 7);
    976   1.1   reinoud 
    977   1.1   reinoud 	return perm;
    978   1.1   reinoud }
    979   1.1   reinoud 
    980   1.1   reinoud /* end of copied code */
    981   1.1   reinoud 
    982   1.1   reinoud 
    983   1.1   reinoud void
    984   1.1   reinoud udf_encode_osta_id(char *osta_id, uint16_t len, char *text)
    985   1.1   reinoud {
    986   1.1   reinoud 	struct charspec osta_charspec;
    987   1.1   reinoud 	uint8_t result_len;
    988   1.1   reinoud 
    989   1.1   reinoud 	memset(osta_id, 0, len);
    990   1.1   reinoud 	if (!text || (strlen(text) == 0)) return;
    991   1.1   reinoud 
    992   1.1   reinoud 	udf_osta_charset(&osta_charspec);
    993   1.1   reinoud 	unix_to_udf_name(osta_id, &result_len, text, strlen(text),
    994   1.1   reinoud 		&osta_charspec);
    995   1.1   reinoud 
    996   1.1   reinoud 	/* Ecma 167/7.2.13 states that length is recorded in the last byte */
    997   1.1   reinoud 	osta_id[len-1] = strlen(text)+1;
    998   1.1   reinoud }
    999   1.1   reinoud 
   1000   1.1   reinoud 
   1001   1.1   reinoud void
   1002   1.1   reinoud udf_set_timestamp_now(struct timestamp *timestamp)
   1003   1.1   reinoud {
   1004   1.1   reinoud 	struct timespec now;
   1005   1.1   reinoud 
   1006   1.1   reinoud #ifdef CLOCK_REALTIME
   1007   1.1   reinoud 	(void)clock_gettime(CLOCK_REALTIME, &now);
   1008   1.1   reinoud #else
   1009   1.1   reinoud 	struct timeval time_of_day;
   1010   1.1   reinoud 
   1011   1.1   reinoud 	(void)gettimeofday(&time_of_day, NULL);
   1012   1.1   reinoud 	now.tv_sec = time_of_day.tv_sec;
   1013   1.1   reinoud 	now.tv_nsec = time_of_day.tv_usec * 1000;
   1014   1.1   reinoud #endif
   1015   1.1   reinoud 	udf_timespec_to_timestamp(&now, timestamp);
   1016   1.1   reinoud }
   1017   1.1   reinoud 
   1018   1.1   reinoud 
   1019   1.1   reinoud int
   1020   1.1   reinoud udf_create_primaryd(void)
   1021   1.1   reinoud {
   1022   1.1   reinoud 	struct pri_vol_desc *pri;
   1023   1.1   reinoud 	uint16_t crclen;
   1024   1.1   reinoud 
   1025   1.1   reinoud 	pri = calloc(1, context.sector_size);
   1026   1.1   reinoud 	if (pri == NULL)
   1027   1.1   reinoud 		return ENOMEM;
   1028   1.1   reinoud 
   1029   1.1   reinoud 	memset(pri, 0, context.sector_size);
   1030   1.1   reinoud 	udf_inittag(&pri->tag, TAGID_PRI_VOL, /* loc */ 0);
   1031   1.1   reinoud 	pri->seq_num = udf_rw32(context.vds_seq); context.vds_seq++;
   1032   1.1   reinoud 
   1033   1.1   reinoud 	pri->pvd_num = udf_rw32(0);		/* default serial */
   1034   1.1   reinoud 	udf_encode_osta_id(pri->vol_id, 32, context.primary_name);
   1035   1.1   reinoud 
   1036   1.1   reinoud 	/* set defaults for single disc volumes as UDF prescribes */
   1037   1.1   reinoud 	pri->vds_num      = udf_rw16(1);
   1038   1.1   reinoud 	pri->max_vol_seq  = udf_rw16(1);
   1039   1.1   reinoud 	pri->ichg_lvl     = udf_rw16(2);
   1040   1.1   reinoud 	pri->max_ichg_lvl = udf_rw16(3);
   1041   1.1   reinoud 	pri->flags        = udf_rw16(0);
   1042   1.1   reinoud 
   1043   1.1   reinoud 	pri->charset_list     = udf_rw32(1);	/* only CS0 */
   1044   1.1   reinoud 	pri->max_charset_list = udf_rw32(1);	/* only CS0 */
   1045   1.1   reinoud 
   1046   1.1   reinoud 	udf_encode_osta_id(pri->volset_id, 128, context.volset_name);
   1047   1.1   reinoud 	udf_osta_charset(&pri->desc_charset);
   1048   1.1   reinoud 	udf_osta_charset(&pri->explanatory_charset);
   1049   1.1   reinoud 
   1050   1.1   reinoud 	udf_set_regid(&pri->app_id, context.app_name);
   1051   1.1   reinoud 	udf_add_app_regid(&pri->app_id);
   1052   1.1   reinoud 
   1053   1.1   reinoud 	udf_set_regid(&pri->imp_id, context.impl_name);
   1054   1.1   reinoud 	udf_add_impl_regid(&pri->imp_id);
   1055   1.1   reinoud 
   1056   1.1   reinoud 	udf_set_timestamp_now(&pri->time);
   1057   1.1   reinoud 
   1058   1.1   reinoud 	crclen = sizeof(struct pri_vol_desc) - UDF_DESC_TAG_LENGTH;
   1059   1.1   reinoud 	pri->tag.desc_crc_len = udf_rw16(crclen);
   1060   1.1   reinoud 
   1061   1.1   reinoud 	context.primary_vol = pri;
   1062   1.1   reinoud 
   1063   1.1   reinoud 	return 0;
   1064   1.1   reinoud }
   1065   1.1   reinoud 
   1066   1.1   reinoud 
   1067   1.1   reinoud /*
   1068   1.1   reinoud  * BUGALERT: some rogue implementations use random physical partition
   1069   1.1   reinoud  * numbers to break other implementations so lookup the number.
   1070   1.1   reinoud  */
   1071   1.1   reinoud 
   1072   1.1   reinoud uint16_t
   1073   1.1   reinoud udf_find_raw_phys(uint16_t raw_phys_part)
   1074   1.1   reinoud {
   1075   1.1   reinoud 	struct part_desc *part;
   1076   1.1   reinoud 	uint16_t phys_part;
   1077   1.1   reinoud 
   1078   1.1   reinoud 	for (phys_part = 0; phys_part < UDF_PARTITIONS; phys_part++) {
   1079   1.1   reinoud 		part = context.partitions[phys_part];
   1080   1.1   reinoud 		if (part == NULL)
   1081   1.1   reinoud 			break;
   1082   1.1   reinoud 		if (udf_rw16(part->part_num) == raw_phys_part)
   1083   1.1   reinoud 			break;
   1084   1.1   reinoud 	}
   1085   1.1   reinoud 	return phys_part;
   1086   1.1   reinoud }
   1087   1.1   reinoud 
   1088   1.1   reinoud 
   1089   1.1   reinoud /* XXX no support for unallocated or freed space tables yet (!) */
   1090   1.1   reinoud int
   1091   1.1   reinoud udf_create_partitiond(int part_num)
   1092   1.1   reinoud {
   1093   1.1   reinoud 	struct part_desc     *pd;
   1094   1.1   reinoud 	struct part_hdr_desc *phd;
   1095   1.1   reinoud 	uint32_t sector_size, bitmap_bytes;
   1096   1.1   reinoud 	uint16_t crclen;
   1097   1.1   reinoud 	int part_accesstype = context.media_accesstype;
   1098   1.1   reinoud 
   1099   1.1   reinoud 	sector_size = context.sector_size;
   1100   1.1   reinoud 	bitmap_bytes = layout.alloc_bitmap_dscr_size * sector_size;
   1101   1.1   reinoud 
   1102   1.1   reinoud 	if (context.partitions[part_num])
   1103   1.1   reinoud 		errx(1, "internal error, partition %d already defined in %s",
   1104   1.1   reinoud 			part_num, __func__);
   1105   1.1   reinoud 
   1106   1.1   reinoud 	pd = calloc(1, context.sector_size);
   1107   1.1   reinoud 	if (pd == NULL)
   1108   1.1   reinoud 		return ENOMEM;
   1109   1.1   reinoud 	phd = &pd->_impl_use.part_hdr;
   1110   1.1   reinoud 
   1111   1.1   reinoud 	udf_inittag(&pd->tag, TAGID_PARTITION, /* loc */ 0);
   1112   1.1   reinoud 	pd->seq_num  = udf_rw32(context.vds_seq); context.vds_seq++;
   1113   1.1   reinoud 
   1114   1.1   reinoud 	pd->flags    = udf_rw16(1);		/* allocated */
   1115   1.1   reinoud 	pd->part_num = udf_rw16(part_num);	/* only one physical partition */
   1116   1.1   reinoud 
   1117   1.1   reinoud 	if (context.dscrver == 2) {
   1118   1.1   reinoud 		udf_set_regid(&pd->contents, "+NSR02");
   1119   1.1   reinoud 	} else {
   1120   1.1   reinoud 		udf_set_regid(&pd->contents, "+NSR03");
   1121   1.1   reinoud 	}
   1122   1.1   reinoud 	udf_add_app_regid(&pd->contents);
   1123   1.1   reinoud 
   1124   1.1   reinoud 	phd->unalloc_space_bitmap.len    = udf_rw32(bitmap_bytes);
   1125   1.1   reinoud 	phd->unalloc_space_bitmap.lb_num = udf_rw32(layout.unalloc_space);
   1126   1.1   reinoud 
   1127   1.1   reinoud 	if (layout.freed_space) {
   1128   1.1   reinoud 		phd->freed_space_bitmap.len    = udf_rw32(bitmap_bytes);
   1129   1.1   reinoud 		phd->freed_space_bitmap.lb_num = udf_rw32(layout.freed_space);
   1130   1.1   reinoud 	}
   1131   1.1   reinoud 
   1132   1.1   reinoud 	pd->access_type = udf_rw32(part_accesstype);
   1133   1.1   reinoud 	pd->start_loc   = udf_rw32(layout.part_start_lba);
   1134   1.1   reinoud 	pd->part_len    = udf_rw32(layout.part_size_lba);
   1135   1.1   reinoud 
   1136   1.1   reinoud 	udf_set_regid(&pd->imp_id, context.impl_name);
   1137   1.1   reinoud 	udf_add_impl_regid(&pd->imp_id);
   1138   1.1   reinoud 
   1139   1.1   reinoud 	crclen = sizeof(struct part_desc) - UDF_DESC_TAG_LENGTH;
   1140   1.1   reinoud 	pd->tag.desc_crc_len = udf_rw16(crclen);
   1141   1.1   reinoud 
   1142   1.1   reinoud 	context.partitions[part_num] = pd;
   1143   1.1   reinoud 
   1144   1.1   reinoud 	return 0;
   1145   1.1   reinoud }
   1146   1.1   reinoud 
   1147   1.1   reinoud 
   1148   1.1   reinoud int
   1149   1.1   reinoud udf_create_unalloc_spaced(void)
   1150   1.1   reinoud {
   1151   1.1   reinoud 	struct unalloc_sp_desc *usd;
   1152   1.1   reinoud 	uint16_t crclen;
   1153   1.1   reinoud 
   1154   1.1   reinoud 	usd = calloc(1, context.sector_size);
   1155   1.1   reinoud 	if (usd == NULL)
   1156   1.1   reinoud 		return ENOMEM;
   1157   1.1   reinoud 
   1158   1.1   reinoud 	udf_inittag(&usd->tag, TAGID_UNALLOC_SPACE, /* loc */ 0);
   1159   1.1   reinoud 	usd->seq_num  = udf_rw32(context.vds_seq); context.vds_seq++;
   1160   1.1   reinoud 
   1161   1.1   reinoud 	/* no default entries */
   1162   1.1   reinoud 	usd->alloc_desc_num = udf_rw32(0);		/* no entries */
   1163   1.1   reinoud 
   1164   1.1   reinoud 	crclen  = sizeof(struct unalloc_sp_desc) - sizeof(struct extent_ad);
   1165   1.1   reinoud 	crclen -= UDF_DESC_TAG_LENGTH;
   1166   1.1   reinoud 	usd->tag.desc_crc_len = udf_rw16(crclen);
   1167   1.1   reinoud 
   1168   1.1   reinoud 	context.unallocated = usd;
   1169   1.1   reinoud 
   1170   1.1   reinoud 	return 0;
   1171   1.1   reinoud }
   1172   1.1   reinoud 
   1173   1.1   reinoud 
   1174   1.1   reinoud static int
   1175   1.1   reinoud udf_create_base_logical_dscr(void)
   1176   1.1   reinoud {
   1177   1.1   reinoud 	struct logvol_desc *lvd;
   1178   1.1   reinoud 	uint32_t sector_size;
   1179   1.1   reinoud 	uint16_t crclen;
   1180   1.1   reinoud 
   1181   1.1   reinoud 	sector_size = context.sector_size;
   1182   1.1   reinoud 
   1183   1.1   reinoud 	lvd = calloc(1, sector_size);
   1184   1.1   reinoud 	if (lvd == NULL)
   1185   1.1   reinoud 		return ENOMEM;
   1186   1.1   reinoud 
   1187   1.1   reinoud 	udf_inittag(&lvd->tag, TAGID_LOGVOL, /* loc */ 0);
   1188   1.1   reinoud 	lvd->seq_num  = udf_rw32(context.vds_seq); context.vds_seq++;
   1189   1.1   reinoud 
   1190   1.1   reinoud 	udf_osta_charset(&lvd->desc_charset);
   1191   1.1   reinoud 	udf_encode_osta_id(lvd->logvol_id, 128, context.logvol_name);
   1192   1.1   reinoud 	lvd->lb_size = udf_rw32(sector_size);
   1193   1.1   reinoud 
   1194   1.1   reinoud 	udf_set_regid(&lvd->domain_id, "*OSTA UDF Compliant");
   1195   1.1   reinoud 	udf_add_domain_regid(&lvd->domain_id);
   1196   1.1   reinoud 
   1197   1.1   reinoud 	/* no partition mappings/entries yet */
   1198   1.1   reinoud 	lvd->mt_l = udf_rw32(0);
   1199   1.1   reinoud 	lvd->n_pm = udf_rw32(0);
   1200   1.1   reinoud 
   1201   1.1   reinoud 	udf_set_regid(&lvd->imp_id, context.impl_name);
   1202   1.1   reinoud 	udf_add_impl_regid(&lvd->imp_id);
   1203   1.1   reinoud 
   1204   1.1   reinoud 	lvd->integrity_seq_loc.loc = udf_rw32(layout.lvis);
   1205   1.1   reinoud 	lvd->integrity_seq_loc.len = udf_rw32(layout.lvis_size * sector_size);
   1206   1.1   reinoud 
   1207   1.1   reinoud 	/* just one fsd for now */
   1208   1.1   reinoud 	lvd->lv_fsd_loc.len = udf_rw32(sector_size);
   1209   1.5   reinoud 	lvd->lv_fsd_loc.loc.part_num = udf_rw16(context.metadata_part);
   1210   1.1   reinoud 	lvd->lv_fsd_loc.loc.lb_num   = udf_rw32(layout.fsd);
   1211   1.1   reinoud 
   1212   1.1   reinoud 	crclen  = sizeof(struct logvol_desc) - 1 - UDF_DESC_TAG_LENGTH;
   1213   1.1   reinoud 	lvd->tag.desc_crc_len = udf_rw16(crclen);
   1214   1.1   reinoud 
   1215   1.1   reinoud 	context.logical_vol = lvd;
   1216   1.1   reinoud 	context.vtop_tp[UDF_VTOP_RAWPART]     = UDF_VTOP_TYPE_RAW;
   1217   1.1   reinoud 
   1218   1.1   reinoud 	return 0;
   1219   1.1   reinoud }
   1220   1.1   reinoud 
   1221   1.1   reinoud 
   1222   1.2  riastrad static void
   1223   1.1   reinoud udf_add_logvol_part_physical(uint16_t phys_part)
   1224   1.1   reinoud {
   1225   1.1   reinoud 	struct logvol_desc *logvol = context.logical_vol;
   1226   1.1   reinoud 	union  udf_pmap *pmap;
   1227   1.1   reinoud 	uint8_t         *pmap_pos;
   1228   1.1   reinoud 	uint16_t crclen;
   1229   1.1   reinoud 	uint32_t pmap1_size, log_part;
   1230   1.1   reinoud 
   1231   1.1   reinoud 	log_part = udf_rw32(logvol->n_pm);
   1232   1.1   reinoud 	pmap_pos = logvol->maps + udf_rw32(logvol->mt_l);
   1233   1.1   reinoud 	pmap1_size = sizeof(struct part_map_1);
   1234   1.1   reinoud 
   1235   1.1   reinoud 	pmap = (union udf_pmap *) pmap_pos;
   1236   1.1   reinoud 	pmap->pm1.type        = 1;
   1237   1.1   reinoud 	pmap->pm1.len         = sizeof(struct part_map_1);
   1238   1.1   reinoud 	pmap->pm1.vol_seq_num = udf_rw16(1);		/* no multi-volume */
   1239   1.1   reinoud 	pmap->pm1.part_num    = udf_rw16(phys_part);
   1240   1.1   reinoud 
   1241   1.1   reinoud 	context.vtop       [log_part] = phys_part;
   1242   1.1   reinoud 	context.vtop_tp    [log_part] = UDF_VTOP_TYPE_PHYS;
   1243   1.1   reinoud 	context.part_size[log_part] = layout.part_size_lba;
   1244   1.1   reinoud 	context.part_free[log_part] = layout.part_size_lba;
   1245   1.1   reinoud 
   1246   1.1   reinoud 	/* increment number of partitions and length */
   1247   1.1   reinoud 	logvol->n_pm = udf_rw32(log_part + 1);
   1248   1.1   reinoud 	logvol->mt_l = udf_rw32(udf_rw32(logvol->mt_l) + pmap1_size);
   1249   1.1   reinoud 
   1250   1.1   reinoud 	crclen = udf_rw16(logvol->tag.desc_crc_len) + pmap1_size;
   1251   1.1   reinoud 	logvol->tag.desc_crc_len = udf_rw16(crclen);
   1252   1.1   reinoud }
   1253   1.1   reinoud 
   1254   1.1   reinoud 
   1255   1.1   reinoud static void
   1256   1.1   reinoud udf_add_logvol_part_virtual(uint16_t phys_part)
   1257   1.1   reinoud {
   1258   1.1   reinoud 	union  udf_pmap *pmap;
   1259   1.1   reinoud 	struct logvol_desc *logvol = context.logical_vol;
   1260   1.1   reinoud 	uint8_t *pmap_pos;
   1261   1.1   reinoud 	uint16_t crclen;
   1262   1.1   reinoud 	uint32_t pmapv_size, log_part;
   1263   1.1   reinoud 
   1264   1.1   reinoud 	log_part = udf_rw32(logvol->n_pm);
   1265   1.1   reinoud 	pmap_pos = logvol->maps + udf_rw32(logvol->mt_l);
   1266   1.1   reinoud 	pmapv_size = sizeof(struct part_map_2);
   1267   1.1   reinoud 
   1268   1.1   reinoud 	pmap = (union udf_pmap *) pmap_pos;
   1269   1.1   reinoud 	pmap->pmv.type        = 2;
   1270   1.1   reinoud 	pmap->pmv.len         = pmapv_size;
   1271   1.1   reinoud 
   1272   1.1   reinoud 	udf_set_regid(&pmap->pmv.id, "*UDF Virtual Partition");
   1273   1.1   reinoud 	udf_add_udf_regid(&pmap->pmv.id);
   1274   1.1   reinoud 
   1275   1.1   reinoud 	pmap->pmv.vol_seq_num = udf_rw16(1);		/* no multi-volume */
   1276   1.1   reinoud 	pmap->pmv.part_num    = udf_rw16(phys_part);
   1277   1.1   reinoud 
   1278   1.1   reinoud 	context.vtop       [log_part] = phys_part;
   1279   1.1   reinoud 	context.vtop_tp    [log_part] = UDF_VTOP_TYPE_VIRT;
   1280   1.1   reinoud 	context.part_size[log_part] = 0xffffffff;
   1281   1.1   reinoud 	context.part_free[log_part] = 0xffffffff;
   1282   1.1   reinoud 
   1283   1.1   reinoud 	/* increment number of partitions and length */
   1284   1.1   reinoud 	logvol->n_pm = udf_rw32(log_part + 1);
   1285   1.1   reinoud 	logvol->mt_l = udf_rw32(udf_rw32(logvol->mt_l) + pmapv_size);
   1286   1.1   reinoud 
   1287   1.1   reinoud 	crclen = udf_rw16(logvol->tag.desc_crc_len) + pmapv_size;
   1288   1.1   reinoud 	logvol->tag.desc_crc_len = udf_rw16(crclen);
   1289   1.1   reinoud }
   1290   1.1   reinoud 
   1291   1.1   reinoud 
   1292   1.1   reinoud /* sparing table size is in bytes */
   1293   1.1   reinoud static void
   1294   1.1   reinoud udf_add_logvol_part_spareable(uint16_t phys_part)
   1295   1.1   reinoud {
   1296   1.1   reinoud 	union  udf_pmap *pmap;
   1297   1.1   reinoud 	struct logvol_desc *logvol = context.logical_vol;
   1298   1.1   reinoud 	uint32_t *st_pos, spareable_bytes, pmaps_size;
   1299   1.1   reinoud 	uint8_t  *pmap_pos, num;
   1300   1.1   reinoud 	uint16_t crclen;
   1301   1.1   reinoud 	uint32_t log_part;
   1302   1.1   reinoud 
   1303   1.1   reinoud 	log_part = udf_rw32(logvol->n_pm);
   1304   1.1   reinoud 	pmap_pos = logvol->maps + udf_rw32(logvol->mt_l);
   1305   1.1   reinoud 	pmaps_size = sizeof(struct part_map_2);
   1306   1.1   reinoud 	spareable_bytes = layout.spareable_area_size * context.sector_size;
   1307   1.1   reinoud 
   1308   1.1   reinoud 	pmap = (union udf_pmap *) pmap_pos;
   1309   1.1   reinoud 	pmap->pms.type        = 2;
   1310   1.1   reinoud 	pmap->pms.len         = pmaps_size;
   1311   1.1   reinoud 
   1312   1.1   reinoud 	udf_set_regid(&pmap->pmv.id, "*UDF Sparable Partition");
   1313   1.1   reinoud 	udf_add_udf_regid(&pmap->pmv.id);
   1314   1.1   reinoud 
   1315   1.1   reinoud 	pmap->pms.vol_seq_num = udf_rw16(1);		/* no multi-volume */
   1316   1.1   reinoud 	pmap->pms.part_num    = udf_rw16(phys_part);
   1317   1.1   reinoud 
   1318   1.1   reinoud 	pmap->pms.packet_len  = udf_rw16(layout.spareable_blockingnr);
   1319   1.1   reinoud 	pmap->pms.st_size     = udf_rw32(spareable_bytes);
   1320   1.1   reinoud 
   1321   1.1   reinoud 	/* enter spare tables  */
   1322   1.1   reinoud 	st_pos = &pmap->pms.st_loc[0];
   1323   1.1   reinoud 	*st_pos++ = udf_rw32(layout.spt_1);
   1324   1.1   reinoud 	*st_pos++ = udf_rw32(layout.spt_2);
   1325   1.1   reinoud 
   1326   1.1   reinoud 	num = 2;
   1327   1.1   reinoud 	if (layout.spt_2 == 0) num--;
   1328   1.1   reinoud 	if (layout.spt_1 == 0) num--;
   1329   1.1   reinoud 	pmap->pms.n_st = num;		/* 8 bit */
   1330   1.1   reinoud 
   1331   1.1   reinoud 	context.vtop       [log_part] = phys_part;
   1332   1.1   reinoud 	context.vtop_tp    [log_part] = UDF_VTOP_TYPE_SPAREABLE;
   1333   1.1   reinoud 	context.part_size[log_part] = layout.part_size_lba;
   1334   1.1   reinoud 	context.part_free[log_part] = layout.part_size_lba;
   1335   1.1   reinoud 
   1336   1.1   reinoud 	/* increment number of partitions and length */
   1337   1.1   reinoud 	logvol->n_pm = udf_rw32(log_part + 1);
   1338   1.1   reinoud 	logvol->mt_l = udf_rw32(udf_rw32(logvol->mt_l) + pmaps_size);
   1339   1.1   reinoud 
   1340   1.1   reinoud 	crclen = udf_rw16(logvol->tag.desc_crc_len) + pmaps_size;
   1341   1.1   reinoud 	logvol->tag.desc_crc_len = udf_rw16(crclen);
   1342   1.1   reinoud }
   1343   1.1   reinoud 
   1344   1.1   reinoud 
   1345   1.1   reinoud int
   1346   1.1   reinoud udf_create_sparing_tabled(void)
   1347   1.1   reinoud {
   1348   1.1   reinoud 	struct udf_sparing_table *spt;
   1349   1.1   reinoud 	struct spare_map_entry   *sme;
   1350   1.1   reinoud 	uint32_t loc, cnt;
   1351   1.1   reinoud 	uint32_t crclen;	/* XXX: should be 16; need to detect overflow */
   1352   1.1   reinoud 
   1353   1.1   reinoud 	spt = calloc(context.sector_size, layout.sparing_table_dscr_lbas);
   1354   1.1   reinoud 	if (spt == NULL)
   1355   1.1   reinoud 		return ENOMEM;
   1356   1.1   reinoud 
   1357   1.1   reinoud 	/* a sparing table descriptor is a whole spareable_blockingnr sectors */
   1358   1.1   reinoud 	udf_inittag(&spt->tag, TAGID_SPARING_TABLE, /* loc */ 0);
   1359   1.1   reinoud 
   1360   1.1   reinoud 	udf_set_regid(&spt->id, "*UDF Sparing Table");
   1361   1.1   reinoud 	udf_add_udf_regid(&spt->id);
   1362   1.1   reinoud 
   1363   1.1   reinoud 	spt->rt_l    = udf_rw16(layout.spareable_blocks);
   1364   1.1   reinoud 	spt->seq_num = udf_rw32(0);			/* first generation */
   1365   1.1   reinoud 
   1366   1.1   reinoud 	for (cnt = 0; cnt < layout.spareable_blocks; cnt++) {
   1367   1.1   reinoud 		sme = &spt->entries[cnt];
   1368   1.1   reinoud 		loc = layout.spareable_area + cnt * layout.spareable_blockingnr;
   1369   1.1   reinoud 		sme->org = udf_rw32(0xffffffff);	/* open for reloc */
   1370   1.1   reinoud 		sme->map = udf_rw32(loc);
   1371   1.1   reinoud 	}
   1372   1.1   reinoud 
   1373   1.1   reinoud 	/* calculate crc len for actual size */
   1374   1.1   reinoud 	crclen  = sizeof(struct udf_sparing_table) - UDF_DESC_TAG_LENGTH;
   1375   1.1   reinoud 	crclen += (layout.spareable_blocks-1) * sizeof(struct spare_map_entry);
   1376   1.1   reinoud 
   1377   1.1   reinoud 	assert(crclen <= UINT16_MAX);
   1378   1.1   reinoud 	spt->tag.desc_crc_len = udf_rw16((uint16_t)crclen);
   1379   1.1   reinoud 
   1380   1.1   reinoud 	context.sparing_table = spt;
   1381   1.1   reinoud 
   1382   1.1   reinoud 	return 0;
   1383   1.1   reinoud }
   1384   1.1   reinoud 
   1385   1.1   reinoud 
   1386   1.1   reinoud static void
   1387   1.1   reinoud udf_add_logvol_part_meta(uint16_t phys_part)
   1388   1.1   reinoud {
   1389   1.1   reinoud 	union  udf_pmap *pmap;
   1390   1.1   reinoud 	struct logvol_desc *logvol = context.logical_vol;
   1391   1.1   reinoud 	uint8_t *pmap_pos;
   1392   1.1   reinoud 	uint32_t pmapv_size, log_part;
   1393   1.1   reinoud 	uint16_t crclen;
   1394   1.1   reinoud 
   1395   1.1   reinoud 	log_part = udf_rw32(logvol->n_pm);
   1396   1.1   reinoud 	pmap_pos = logvol->maps + udf_rw32(logvol->mt_l);
   1397   1.1   reinoud 	pmapv_size = sizeof(struct part_map_2);
   1398   1.1   reinoud 
   1399   1.1   reinoud 	pmap = (union udf_pmap *) pmap_pos;
   1400   1.1   reinoud 	pmap->pmm.type        = 2;
   1401   1.1   reinoud 	pmap->pmm.len         = pmapv_size;
   1402   1.1   reinoud 
   1403   1.1   reinoud 	udf_set_regid(&pmap->pmm.id, "*UDF Metadata Partition");
   1404   1.1   reinoud 	udf_add_udf_regid(&pmap->pmm.id);
   1405   1.1   reinoud 
   1406   1.1   reinoud 	pmap->pmm.vol_seq_num = udf_rw16(1);		/* no multi-volume */
   1407   1.1   reinoud 	pmap->pmm.part_num    = udf_rw16(phys_part);
   1408   1.1   reinoud 
   1409   1.1   reinoud 	/* fill in meta data file(s) and alloc/alignment unit sizes */
   1410   1.1   reinoud 	pmap->pmm.meta_file_lbn        = udf_rw32(layout.meta_file);
   1411   1.1   reinoud 	pmap->pmm.meta_mirror_file_lbn = udf_rw32(layout.meta_mirror);
   1412   1.1   reinoud 	pmap->pmm.meta_bitmap_file_lbn = udf_rw32(layout.meta_bitmap);
   1413   1.1   reinoud 	pmap->pmm.alloc_unit_size      = udf_rw32(layout.meta_blockingnr);
   1414   1.1   reinoud 	pmap->pmm.alignment_unit_size  = udf_rw16(layout.meta_alignment);
   1415   1.1   reinoud 	pmap->pmm.flags                = 0; /* METADATA_DUPLICATED */
   1416   1.1   reinoud 
   1417   1.1   reinoud 	context.vtop       [log_part] = phys_part;
   1418   1.1   reinoud 	context.vtop_tp    [log_part] = UDF_VTOP_TYPE_META;
   1419   1.1   reinoud 	context.part_size[log_part] = layout.meta_part_size_lba;
   1420   1.1   reinoud 	context.part_free[log_part] = layout.meta_part_size_lba;
   1421   1.1   reinoud 
   1422   1.1   reinoud 	/* increment number of partitions and length */
   1423   1.1   reinoud 	logvol->n_pm = udf_rw32(log_part + 1);
   1424   1.1   reinoud 	logvol->mt_l = udf_rw32(udf_rw32(logvol->mt_l) + pmapv_size);
   1425   1.1   reinoud 
   1426   1.1   reinoud 	crclen = udf_rw16(logvol->tag.desc_crc_len) + pmapv_size;
   1427   1.1   reinoud 	logvol->tag.desc_crc_len = udf_rw16(crclen);
   1428   1.1   reinoud }
   1429   1.1   reinoud 
   1430   1.1   reinoud 
   1431   1.1   reinoud int
   1432   1.1   reinoud udf_create_logical_dscr(void)
   1433   1.1   reinoud {
   1434   1.1   reinoud 	int error;
   1435   1.1   reinoud 
   1436   1.1   reinoud 	if ((error = udf_create_base_logical_dscr()))
   1437   1.1   reinoud 		return error;
   1438   1.1   reinoud 
   1439   1.1   reinoud 	/* we pass data_part for there might be a read-only part one day */
   1440   1.1   reinoud 	if (context.format_flags & FORMAT_SPAREABLE) {
   1441   1.1   reinoud 		/* spareable partition mapping has no physical mapping */
   1442   1.1   reinoud 		udf_add_logvol_part_spareable(context.data_part);
   1443   1.1   reinoud 	} else {
   1444   1.1   reinoud 		udf_add_logvol_part_physical(context.data_part);
   1445   1.1   reinoud 	}
   1446   1.1   reinoud 
   1447   1.1   reinoud 	if (context.format_flags & FORMAT_VAT) {
   1448   1.1   reinoud 		/* add VAT virtual mapping; reflects on datapart */
   1449   1.1   reinoud 		udf_add_logvol_part_virtual(context.data_part);
   1450   1.1   reinoud 	}
   1451   1.1   reinoud 	if (context.format_flags & FORMAT_META) {
   1452   1.1   reinoud 		/* add META data mapping; reflects on datapart */
   1453   1.1   reinoud 		udf_add_logvol_part_meta(context.data_part);
   1454   1.1   reinoud 	}
   1455   1.1   reinoud 
   1456   1.1   reinoud 	return 0;
   1457   1.1   reinoud }
   1458   1.1   reinoud 
   1459   1.1   reinoud 
   1460   1.1   reinoud int
   1461   1.1   reinoud udf_create_impvold(char *field1, char *field2, char *field3)
   1462   1.1   reinoud {
   1463   1.1   reinoud 	struct impvol_desc *ivd;
   1464   1.1   reinoud 	struct udf_lv_info *lvi;
   1465   1.1   reinoud 	uint16_t crclen;
   1466   1.1   reinoud 
   1467   1.1   reinoud 	ivd = calloc(1, context.sector_size);
   1468   1.1   reinoud 	if (ivd == NULL)
   1469   1.1   reinoud 		return ENOMEM;
   1470   1.1   reinoud 	lvi = &ivd->_impl_use.lv_info;
   1471   1.1   reinoud 
   1472   1.1   reinoud 	udf_inittag(&ivd->tag, TAGID_IMP_VOL, /* loc */ 0);
   1473   1.1   reinoud 	ivd->seq_num  = udf_rw32(context.vds_seq); context.vds_seq++;
   1474   1.1   reinoud 
   1475   1.1   reinoud 	udf_set_regid(&ivd->impl_id, "*UDF LV Info");
   1476   1.1   reinoud 	udf_add_udf_regid(&ivd->impl_id);
   1477   1.1   reinoud 
   1478   1.1   reinoud 	/* fill in UDF specific part */
   1479   1.1   reinoud 	udf_osta_charset(&lvi->lvi_charset);
   1480   1.1   reinoud 	udf_encode_osta_id(lvi->logvol_id, 128, context.logvol_name);
   1481   1.1   reinoud 
   1482   1.1   reinoud 	udf_encode_osta_id(lvi->lvinfo1, 36, field1);
   1483   1.1   reinoud 	udf_encode_osta_id(lvi->lvinfo2, 36, field2);
   1484   1.1   reinoud 	udf_encode_osta_id(lvi->lvinfo3, 36, field3);
   1485   1.1   reinoud 
   1486   1.1   reinoud 	udf_set_regid(&lvi->impl_id, context.impl_name);
   1487   1.1   reinoud 	udf_add_impl_regid(&lvi->impl_id);
   1488   1.1   reinoud 
   1489   1.1   reinoud 	crclen  = sizeof(struct impvol_desc) - UDF_DESC_TAG_LENGTH;
   1490   1.1   reinoud 	ivd->tag.desc_crc_len = udf_rw16(crclen);
   1491   1.1   reinoud 
   1492   1.1   reinoud 	context.implementation = ivd;
   1493   1.1   reinoud 
   1494   1.1   reinoud 	return 0;
   1495   1.1   reinoud }
   1496   1.1   reinoud 
   1497   1.1   reinoud 
   1498   1.1   reinoud /* XXX might need to be sanitised a bit */
   1499   1.1   reinoud void
   1500   1.1   reinoud udf_update_lvintd(int type)
   1501   1.1   reinoud {
   1502   1.1   reinoud 	struct logvol_int_desc *lvid;
   1503   1.1   reinoud 	struct udf_logvol_info *lvinfo;
   1504   1.1   reinoud 	struct logvol_desc     *logvol;
   1505   1.1   reinoud 	uint32_t *pos;
   1506   1.1   reinoud 	uint32_t cnt, num_partmappings;
   1507   1.1   reinoud 	uint32_t crclen;	/* XXX: should be 16; need to detect overflow */
   1508   1.1   reinoud 
   1509   1.1   reinoud 	lvid   = context.logvol_integrity;
   1510   1.1   reinoud 	logvol = context.logical_vol;
   1511   1.1   reinoud 	assert(lvid);
   1512   1.1   reinoud 	assert(logvol);
   1513   1.1   reinoud 
   1514   1.1   reinoud 	lvid->integrity_type = udf_rw32(type);
   1515   1.1   reinoud 	udf_set_timestamp_now(&lvid->time);
   1516   1.1   reinoud 
   1517   1.1   reinoud 	/* initialise lvinfo just in case its not set yet */
   1518   1.1   reinoud 	num_partmappings = udf_rw32(logvol->n_pm);
   1519   1.1   reinoud 	assert(num_partmappings > 0);
   1520   1.1   reinoud 
   1521   1.1   reinoud 	lvinfo = (struct udf_logvol_info *)
   1522   1.1   reinoud 		(lvid->tables + num_partmappings * 2);
   1523   1.1   reinoud 	context.logvol_info = lvinfo;
   1524   1.1   reinoud 
   1525   1.1   reinoud 	udf_set_regid(&lvinfo->impl_id, context.impl_name);
   1526   1.1   reinoud 	udf_add_impl_regid(&lvinfo->impl_id);
   1527   1.1   reinoud 
   1528   1.1   reinoud 	if (type == UDF_INTEGRITY_CLOSED) {
   1529   1.1   reinoud 		lvinfo->num_files          = udf_rw32(context.num_files);
   1530   1.1   reinoud 		lvinfo->num_directories    = udf_rw32(context.num_directories);
   1531   1.1   reinoud 
   1532   1.1   reinoud 		lvid->lvint_next_unique_id = udf_rw64(context.unique_id);
   1533   1.1   reinoud 	}
   1534   1.1   reinoud 
   1535   1.1   reinoud 	/* sane enough? */
   1536   1.1   reinoud 	if (udf_rw16(lvinfo->min_udf_readver) < context.min_udf)
   1537   1.1   reinoud 		lvinfo->min_udf_readver  = udf_rw16(context.min_udf);
   1538   1.1   reinoud 	if (udf_rw16(lvinfo->min_udf_writever) < context.min_udf)
   1539   1.1   reinoud 		lvinfo->min_udf_writever = udf_rw16(context.min_udf);
   1540   1.1   reinoud 	if (udf_rw16(lvinfo->max_udf_writever) < context.max_udf)
   1541   1.1   reinoud 		lvinfo->max_udf_writever = udf_rw16(context.max_udf);
   1542   1.1   reinoud 
   1543   1.1   reinoud 	lvid->num_part = udf_rw32(num_partmappings);
   1544   1.1   reinoud 
   1545   1.1   reinoud 	pos = &lvid->tables[0];
   1546   1.1   reinoud 	for (cnt = 0; cnt < num_partmappings; cnt++) {
   1547   1.1   reinoud 		*pos++ = udf_rw32(context.part_free[cnt]);
   1548   1.1   reinoud 	}
   1549   1.1   reinoud 	for (cnt = 0; cnt < num_partmappings; cnt++) {
   1550   1.1   reinoud 		*pos++ = udf_rw32(context.part_size[cnt]);
   1551   1.1   reinoud 	}
   1552   1.1   reinoud 
   1553   1.1   reinoud 	crclen  = sizeof(struct logvol_int_desc) -4 -UDF_DESC_TAG_LENGTH +
   1554   1.1   reinoud 		udf_rw32(lvid->l_iu);
   1555   1.1   reinoud 	crclen += num_partmappings * 2 * 4;
   1556   1.1   reinoud 
   1557   1.1   reinoud 	assert(crclen <= UINT16_MAX);
   1558   1.1   reinoud 	if (lvid->tag.desc_crc_len == 0)
   1559   1.1   reinoud 		lvid->tag.desc_crc_len = udf_rw16(crclen);
   1560   1.1   reinoud 
   1561   1.1   reinoud 	context.logvol_info = lvinfo;
   1562   1.1   reinoud }
   1563   1.1   reinoud 
   1564   1.1   reinoud 
   1565   1.1   reinoud int
   1566   1.1   reinoud udf_create_lvintd(int type)
   1567   1.1   reinoud {
   1568   1.1   reinoud 	struct logvol_int_desc *lvid;
   1569   1.1   reinoud 	int l_iu;
   1570   1.1   reinoud 
   1571   1.1   reinoud 	lvid = calloc(1, context.sector_size);
   1572   1.1   reinoud 	if (lvid == NULL)
   1573   1.1   reinoud 		return ENOMEM;
   1574   1.1   reinoud 
   1575   1.1   reinoud 	udf_inittag(&lvid->tag, TAGID_LOGVOL_INTEGRITY, /* loc */ 0);
   1576   1.1   reinoud 	context.logvol_integrity = lvid;
   1577   1.1   reinoud 
   1578   1.1   reinoud 	/* only set for standard UDF info, no extra impl. use needed */
   1579   1.1   reinoud 	l_iu = sizeof(struct udf_logvol_info);
   1580   1.1   reinoud 	lvid->l_iu = udf_rw32(l_iu);
   1581   1.1   reinoud 
   1582   1.1   reinoud 	udf_update_lvintd(type);
   1583   1.1   reinoud 
   1584   1.1   reinoud 	return 0;
   1585   1.1   reinoud }
   1586   1.1   reinoud 
   1587   1.1   reinoud 
   1588   1.1   reinoud int
   1589   1.1   reinoud udf_create_fsd(void)
   1590   1.1   reinoud {
   1591   1.1   reinoud 	struct fileset_desc *fsd;
   1592   1.1   reinoud 	uint16_t crclen;
   1593   1.1   reinoud 
   1594   1.1   reinoud 	fsd = calloc(1, context.sector_size);
   1595   1.1   reinoud 	if (fsd == NULL)
   1596   1.1   reinoud 		return ENOMEM;
   1597   1.1   reinoud 
   1598   1.1   reinoud 	udf_inittag(&fsd->tag, TAGID_FSD, /* loc */ 0);
   1599   1.1   reinoud 
   1600   1.1   reinoud 	udf_set_timestamp_now(&fsd->time);
   1601   1.1   reinoud 	fsd->ichg_lvl     = udf_rw16(3);		/* UDF 2.3.2.1 */
   1602   1.1   reinoud 	fsd->max_ichg_lvl = udf_rw16(3);		/* UDF 2.3.2.2 */
   1603   1.1   reinoud 
   1604   1.1   reinoud 	fsd->charset_list     = udf_rw32(1);		/* only CS0 */
   1605   1.1   reinoud 	fsd->max_charset_list = udf_rw32(1);		/* only CS0 */
   1606   1.1   reinoud 
   1607   1.1   reinoud 	fsd->fileset_num      = udf_rw32(0);		/* only one fsd */
   1608   1.1   reinoud 	fsd->fileset_desc_num = udf_rw32(0);		/* original    */
   1609   1.1   reinoud 
   1610   1.1   reinoud 	udf_osta_charset(&fsd->logvol_id_charset);
   1611   1.1   reinoud 	udf_encode_osta_id(fsd->logvol_id, 128, context.logvol_name);
   1612   1.1   reinoud 
   1613   1.1   reinoud 	udf_osta_charset(&fsd->fileset_charset);
   1614   1.1   reinoud 	udf_encode_osta_id(fsd->fileset_id, 32, context.fileset_name);
   1615   1.1   reinoud 
   1616   1.1   reinoud 	/* copyright file and abstract file names obmitted */
   1617   1.1   reinoud 
   1618   1.1   reinoud 	fsd->rootdir_icb.len	      = udf_rw32(context.sector_size);
   1619   1.1   reinoud 	fsd->rootdir_icb.loc.lb_num   = udf_rw32(layout.rootdir);
   1620   1.1   reinoud 	fsd->rootdir_icb.loc.part_num = udf_rw16(context.metadata_part);
   1621   1.1   reinoud 
   1622   1.1   reinoud 	udf_set_regid(&fsd->domain_id, "*OSTA UDF Compliant");
   1623   1.1   reinoud 	udf_add_domain_regid(&fsd->domain_id);
   1624   1.1   reinoud 
   1625   1.1   reinoud 	/* next_ex stays zero */
   1626   1.1   reinoud 	/* no system streamdirs yet */
   1627   1.1   reinoud 
   1628   1.1   reinoud 	crclen = sizeof(struct fileset_desc) - UDF_DESC_TAG_LENGTH;
   1629   1.1   reinoud 	fsd->tag.desc_crc_len = udf_rw16(crclen);
   1630   1.1   reinoud 
   1631   1.1   reinoud 	context.fileset_desc = fsd;
   1632   1.1   reinoud 
   1633   1.1   reinoud 	return 0;
   1634   1.1   reinoud }
   1635   1.1   reinoud 
   1636   1.1   reinoud 
   1637   1.1   reinoud int
   1638   1.1   reinoud udf_create_space_bitmap(uint32_t dscr_size, uint32_t part_size_lba,
   1639   1.1   reinoud 	struct space_bitmap_desc **sbdp)
   1640   1.1   reinoud {
   1641   1.1   reinoud 	struct space_bitmap_desc *sbd;
   1642   1.1   reinoud 	uint32_t cnt;
   1643   1.1   reinoud 	uint16_t crclen;
   1644   1.1   reinoud 
   1645   1.1   reinoud 	*sbdp = NULL;
   1646   1.1   reinoud 	sbd = calloc(context.sector_size, dscr_size);
   1647   1.1   reinoud 	if (sbd == NULL)
   1648   1.1   reinoud 		return ENOMEM;
   1649   1.1   reinoud 
   1650   1.1   reinoud 	udf_inittag(&sbd->tag, TAGID_SPACE_BITMAP, /* loc */ 0);
   1651   1.1   reinoud 
   1652   1.1   reinoud 	sbd->num_bits  = udf_rw32(part_size_lba);
   1653   1.1   reinoud 	sbd->num_bytes = udf_rw32((part_size_lba + 7)/8);
   1654   1.1   reinoud 
   1655   1.1   reinoud 	/* fill space with 0xff to indicate free */
   1656   1.1   reinoud 	for (cnt = 0; cnt < udf_rw32(sbd->num_bytes); cnt++)
   1657   1.1   reinoud 		sbd->data[cnt] = 0xff;
   1658   1.1   reinoud 
   1659   1.1   reinoud 	/* set crc to only cover the header (UDF 2.3.1.2, 2.3.8.1) */
   1660   1.1   reinoud 	crclen = sizeof(struct space_bitmap_desc) -1 - UDF_DESC_TAG_LENGTH;
   1661   1.1   reinoud 	sbd->tag.desc_crc_len = udf_rw16(crclen);
   1662   1.1   reinoud 
   1663   1.1   reinoud 	*sbdp = sbd;
   1664   1.1   reinoud 	return 0;
   1665   1.1   reinoud }
   1666   1.1   reinoud 
   1667   1.1   reinoud /* --------------------------------------------------------------------- */
   1668   1.1   reinoud 
   1669   1.2  riastrad int
   1670   1.1   reinoud udf_register_bad_block(uint32_t location)
   1671   1.1   reinoud {
   1672   1.1   reinoud 	struct udf_sparing_table *spt;
   1673   1.1   reinoud 	struct spare_map_entry   *sme, *free_sme;
   1674   1.1   reinoud 	uint32_t cnt;
   1675   1.1   reinoud 
   1676   1.1   reinoud 	spt = context.sparing_table;
   1677   1.1   reinoud 	if (spt == NULL)
   1678   1.1   reinoud 		errx(1, "internal error, adding bad block to "
   1679   1.1   reinoud 			"non spareable in %s", __func__);
   1680   1.1   reinoud 
   1681   1.1   reinoud 	/* find us a free spare map entry */
   1682   1.1   reinoud 	free_sme = NULL;
   1683   1.1   reinoud 	for (cnt = 0; cnt < layout.spareable_blocks; cnt++) {
   1684   1.1   reinoud 		sme = &spt->entries[cnt];
   1685  1.12    andvar 		/* if we are already in it, bail out */
   1686   1.1   reinoud 		if (udf_rw32(sme->org) == location)
   1687   1.1   reinoud 			return 0;
   1688   1.1   reinoud 		if (udf_rw32(sme->org) == 0xffffffff) {
   1689   1.1   reinoud 			free_sme = sme;
   1690   1.1   reinoud 			break;
   1691   1.1   reinoud 		}
   1692   1.1   reinoud 	}
   1693   1.1   reinoud 	if (free_sme == NULL) {
   1694   1.1   reinoud 		warnx("disc relocation blocks full; disc too damaged");
   1695   1.1   reinoud 		return EINVAL;
   1696   1.1   reinoud 	}
   1697   1.1   reinoud 	free_sme->org = udf_rw32(location);
   1698   1.1   reinoud 
   1699   1.1   reinoud 	return 0;
   1700   1.1   reinoud }
   1701   1.1   reinoud 
   1702   1.1   reinoud 
   1703   1.1   reinoud void
   1704   1.1   reinoud udf_mark_allocated(uint32_t start_lb, int partnr, uint32_t blocks)
   1705   1.1   reinoud {
   1706   1.1   reinoud 	union dscrptr *dscr;
   1707   1.1   reinoud 	uint8_t *bpos;
   1708   1.1   reinoud 	uint32_t cnt, bit;
   1709   1.1   reinoud 
   1710   1.1   reinoud 	/* account for space used on underlying partition */
   1711   1.1   reinoud #ifdef DEBUG
   1712   1.1   reinoud 	printf("mark allocated : partnr %d, start_lb %d for %d blocks\n",
   1713   1.1   reinoud 		partnr, start_lb, blocks);
   1714   1.1   reinoud #endif
   1715   1.1   reinoud 
   1716   1.1   reinoud 	switch (context.vtop_tp[partnr]) {
   1717   1.1   reinoud 	case UDF_VTOP_TYPE_VIRT:
   1718   1.1   reinoud 		/* nothing */
   1719   1.1   reinoud 		break;
   1720   1.1   reinoud 	case UDF_VTOP_TYPE_PHYS:
   1721   1.1   reinoud 	case UDF_VTOP_TYPE_SPAREABLE:
   1722   1.1   reinoud 	case UDF_VTOP_TYPE_META:
   1723   1.1   reinoud 		if (context.part_unalloc_bits[context.vtop[partnr]] == NULL) {
   1724   1.1   reinoud 			context.part_free[partnr] = 0;
   1725   1.1   reinoud 			break;
   1726   1.1   reinoud 		}
   1727   1.1   reinoud #ifdef DEBUG
   1728   1.1   reinoud 		printf("marking %d+%d as used\n", start_lb, blocks);
   1729   1.1   reinoud #endif
   1730   1.1   reinoud 		dscr = (union dscrptr *) (context.part_unalloc_bits[partnr]);
   1731   1.1   reinoud 		for (cnt = start_lb; cnt < start_lb + blocks; cnt++) {
   1732   1.1   reinoud 			 bpos  = &dscr->sbd.data[cnt / 8];
   1733   1.1   reinoud 			 bit   = cnt % 8;
   1734   1.1   reinoud 			 /* only account for bits marked free */
   1735   1.1   reinoud 			 if ((*bpos & (1 << bit)))
   1736   1.1   reinoud 				context.part_free[partnr] -= 1;
   1737   1.1   reinoud 			*bpos &= ~(1<< bit);
   1738   1.1   reinoud 		}
   1739   1.1   reinoud 		break;
   1740   1.1   reinoud 	default:
   1741   1.1   reinoud 		errx(1, "internal error: bad mapping type %d in %s",
   1742   1.1   reinoud 			context.vtop_tp[partnr], __func__);
   1743   1.1   reinoud 	}
   1744   1.1   reinoud }
   1745   1.1   reinoud 
   1746   1.1   reinoud 
   1747   1.1   reinoud void
   1748   1.1   reinoud udf_advance_uniqueid(void)
   1749   1.1   reinoud {
   1750   1.1   reinoud 	/* Minimum value of 16 : UDF 3.2.1.1, 3.3.3.4. */
   1751   1.1   reinoud 	context.unique_id++;
   1752   1.1   reinoud 	if (context.unique_id < 0x10)
   1753   1.1   reinoud 		context.unique_id = 0x10;
   1754   1.1   reinoud }
   1755   1.1   reinoud 
   1756   1.1   reinoud /* --------------------------------------------------------------------- */
   1757   1.1   reinoud 
   1758   1.1   reinoud /* XXX implement the using of the results */
   1759   1.1   reinoud int
   1760   1.1   reinoud udf_surface_check(void)
   1761   1.1   reinoud {
   1762   1.1   reinoud 	uint32_t loc, block_bytes;
   1763   1.1   reinoud 	uint32_t sector_size, blockingnr, bpos;
   1764   1.1   reinoud 	uint8_t *buffer;
   1765   1.1   reinoud 	int error, num_errors;
   1766   1.1   reinoud 
   1767   1.1   reinoud 	if (mmc_discinfo.mmc_class == MMC_CLASS_DISC)
   1768   1.1   reinoud 		return 0;
   1769   1.1   reinoud 
   1770   1.1   reinoud 	sector_size = context.sector_size;
   1771   1.1   reinoud 	blockingnr  = layout.blockingnr;
   1772   1.1   reinoud 
   1773   1.1   reinoud 	block_bytes = layout.blockingnr * sector_size;
   1774   1.1   reinoud 	if ((buffer = malloc(block_bytes)) == NULL)
   1775   1.1   reinoud 		return ENOMEM;
   1776   1.1   reinoud 
   1777   1.1   reinoud 	/* set all one to not kill Flash memory? */
   1778   1.1   reinoud 	for (bpos = 0; bpos < block_bytes; bpos++)
   1779   1.1   reinoud 		buffer[bpos] = 0x00;
   1780   1.1   reinoud 
   1781   1.1   reinoud 	printf("\nChecking disc surface : phase 1 - writing\n");
   1782   1.1   reinoud 	num_errors = 0;
   1783   1.1   reinoud 	loc = layout.first_lba;
   1784   1.1   reinoud 	while (loc <= layout.last_lba) {
   1785   1.1   reinoud 		/* write blockingnr sectors */
   1786   1.1   reinoud 		error = pwrite(dev_fd, buffer, block_bytes,
   1787   1.1   reinoud 				(uint64_t) loc*sector_size);
   1788   1.1   reinoud 		printf("   %08d + %d (%02d %%)\r", loc, blockingnr,
   1789   1.1   reinoud 			(int)((100.0 * loc)/layout.last_lba));
   1790   1.1   reinoud 		fflush(stdout);
   1791   1.1   reinoud 		if (error == -1) {
   1792   1.1   reinoud 			/* block is bad */
   1793   1.1   reinoud 			printf("BAD block at %08d + %d         \n",
   1794   1.1   reinoud 				loc, layout.blockingnr);
   1795   1.1   reinoud 			if ((error = udf_register_bad_block(loc))) {
   1796   1.1   reinoud 				free(buffer);
   1797   1.1   reinoud 				return error;
   1798   1.1   reinoud 			}
   1799   1.1   reinoud 			num_errors ++;
   1800   1.1   reinoud 		}
   1801   1.1   reinoud 		loc += layout.blockingnr;
   1802   1.1   reinoud 	}
   1803   1.1   reinoud 
   1804   1.1   reinoud 	printf("\nChecking disc surface : phase 2 - reading\n");
   1805   1.1   reinoud 	num_errors = 0;
   1806   1.1   reinoud 	loc = layout.first_lba;
   1807   1.1   reinoud 	while (loc <= layout.last_lba) {
   1808   1.1   reinoud 		/* read blockingnr sectors */
   1809   1.1   reinoud 		error = pread(dev_fd, buffer, block_bytes, loc*sector_size);
   1810   1.1   reinoud 		printf("   %08d + %d (%02d %%)\r", loc, blockingnr,
   1811   1.1   reinoud 			(int)((100.0 * loc)/layout.last_lba));
   1812   1.1   reinoud 		fflush(stdout);
   1813   1.1   reinoud 		if (error == -1) {
   1814   1.1   reinoud 			/* block is bad */
   1815   1.1   reinoud 			printf("BAD block at %08d + %d         \n",
   1816   1.1   reinoud 				loc, layout.blockingnr);
   1817   1.1   reinoud 			if ((error = udf_register_bad_block(loc))) {
   1818   1.1   reinoud 				free(buffer);
   1819   1.1   reinoud 				return error;
   1820   1.1   reinoud 			}
   1821   1.1   reinoud 			num_errors ++;
   1822   1.1   reinoud 		}
   1823   1.1   reinoud 		loc += layout.blockingnr;
   1824   1.1   reinoud 	}
   1825   1.1   reinoud 	printf("Scan complete : %d bad blocks found\n", num_errors);
   1826   1.1   reinoud 	free(buffer);
   1827   1.1   reinoud 
   1828   1.1   reinoud 	return 0;
   1829   1.1   reinoud }
   1830   1.1   reinoud 
   1831   1.1   reinoud /* --------------------------------------------------------------------- */
   1832   1.1   reinoud 
   1833   1.1   reinoud #define UDF_SYMLINKBUFLEN    (64*1024)               /* picked */
   1834   1.1   reinoud int
   1835   1.1   reinoud udf_encode_symlink(uint8_t **pathbufp, uint32_t *pathlenp, char *target)
   1836   1.1   reinoud {
   1837   1.1   reinoud 	struct charspec osta_charspec;
   1838   1.1   reinoud 	struct pathcomp pathcomp;
   1839   1.1   reinoud 	char *pathbuf, *pathpos, *compnamepos;
   1840   1.1   reinoud //	char *mntonname;
   1841   1.1   reinoud //	int   mntonnamelen;
   1842   1.1   reinoud 	int pathlen, len, compnamelen;
   1843   1.1   reinoud 	int error;
   1844   1.1   reinoud 
   1845   1.1   reinoud 	/* process `target' to an UDF structure */
   1846   1.1   reinoud 	pathbuf = malloc(UDF_SYMLINKBUFLEN);
   1847   1.1   reinoud 	assert(pathbuf);
   1848   1.1   reinoud 
   1849   1.1   reinoud 	*pathbufp = NULL;
   1850   1.1   reinoud 	*pathlenp = 0;
   1851   1.1   reinoud 
   1852   1.1   reinoud 	pathpos = pathbuf;
   1853   1.1   reinoud 	pathlen = 0;
   1854   1.1   reinoud 	udf_osta_charset(&osta_charspec);
   1855   1.1   reinoud 
   1856   1.1   reinoud 	if (*target == '/') {
   1857   1.1   reinoud 		/* symlink starts from the root */
   1858   1.1   reinoud 		len = UDF_PATH_COMP_SIZE;
   1859   1.1   reinoud 		memset(&pathcomp, 0, len);
   1860   1.1   reinoud 		pathcomp.type = UDF_PATH_COMP_ROOT;
   1861   1.1   reinoud 
   1862   1.1   reinoud #if 0
   1863   1.1   reinoud 		/* XXX how to check for in makefs? */
   1864   1.1   reinoud 		/* check if its mount-point relative! */
   1865   1.1   reinoud 		mntonname    = udf_node->ump->vfs_mountp->mnt_stat.f_mntonname;
   1866   1.1   reinoud 		mntonnamelen = strlen(mntonname);
   1867   1.1   reinoud 		if (strlen(target) >= mntonnamelen) {
   1868   1.1   reinoud 			if (strncmp(target, mntonname, mntonnamelen) == 0) {
   1869   1.1   reinoud 				pathcomp.type = UDF_PATH_COMP_MOUNTROOT;
   1870   1.1   reinoud 				target += mntonnamelen;
   1871   1.1   reinoud 			}
   1872   1.1   reinoud 		} else {
   1873   1.1   reinoud 			target++;
   1874   1.1   reinoud 		}
   1875   1.1   reinoud #else
   1876   1.1   reinoud 		target++;
   1877   1.1   reinoud #endif
   1878   1.1   reinoud 
   1879   1.1   reinoud 		memcpy(pathpos, &pathcomp, len);
   1880   1.1   reinoud 		pathpos += len;
   1881   1.1   reinoud 		pathlen += len;
   1882   1.1   reinoud 	}
   1883   1.1   reinoud 
   1884   1.1   reinoud 	error = 0;
   1885   1.1   reinoud 	while (*target) {
   1886   1.1   reinoud 		/* ignore multiple '/' */
   1887   1.1   reinoud 		while (*target == '/') {
   1888   1.1   reinoud 			target++;
   1889   1.1   reinoud 		}
   1890   1.1   reinoud 		if (!*target)
   1891   1.1   reinoud 			break;
   1892   1.1   reinoud 
   1893   1.1   reinoud 		/* extract component name */
   1894   1.1   reinoud 		compnamelen = 0;
   1895   1.1   reinoud 		compnamepos = target;
   1896   1.1   reinoud 		while ((*target) && (*target != '/')) {
   1897   1.1   reinoud 			target++;
   1898   1.1   reinoud 			compnamelen++;
   1899   1.1   reinoud 		}
   1900   1.1   reinoud 
   1901   1.1   reinoud 		/* just trunc if too long ?? (security issue) */
   1902   1.1   reinoud 		if (compnamelen >= 127) {
   1903   1.1   reinoud 			error = ENAMETOOLONG;
   1904   1.1   reinoud 			break;
   1905   1.1   reinoud 		}
   1906   1.1   reinoud 
   1907   1.1   reinoud 		/* convert unix name to UDF name */
   1908   1.1   reinoud 		len = sizeof(struct pathcomp);
   1909   1.1   reinoud 		memset(&pathcomp, 0, len);
   1910   1.1   reinoud 		pathcomp.type = UDF_PATH_COMP_NAME;
   1911   1.1   reinoud 		len = UDF_PATH_COMP_SIZE;
   1912   1.1   reinoud 
   1913   1.1   reinoud 		if ((compnamelen == 2) && (strncmp(compnamepos, "..", 2) == 0))
   1914   1.1   reinoud 			pathcomp.type = UDF_PATH_COMP_PARENTDIR;
   1915   1.1   reinoud 		if ((compnamelen == 1) && (*compnamepos == '.'))
   1916   1.1   reinoud 			pathcomp.type = UDF_PATH_COMP_CURDIR;
   1917   1.1   reinoud 
   1918   1.1   reinoud 		if (pathcomp.type == UDF_PATH_COMP_NAME) {
   1919   1.1   reinoud 			unix_to_udf_name(
   1920   1.1   reinoud 				(char *) &pathcomp.ident, &pathcomp.l_ci,
   1921   1.1   reinoud 				compnamepos, compnamelen,
   1922   1.1   reinoud 				&osta_charspec);
   1923   1.1   reinoud 			len = UDF_PATH_COMP_SIZE + pathcomp.l_ci;
   1924   1.1   reinoud 		}
   1925   1.1   reinoud 
   1926   1.1   reinoud 		if (pathlen + len >= UDF_SYMLINKBUFLEN) {
   1927   1.1   reinoud 			error = ENAMETOOLONG;
   1928   1.1   reinoud 			break;
   1929   1.1   reinoud 		}
   1930   1.1   reinoud 
   1931   1.1   reinoud 		memcpy(pathpos, &pathcomp, len);
   1932   1.1   reinoud 		pathpos += len;
   1933   1.1   reinoud 		pathlen += len;
   1934   1.1   reinoud 	}
   1935   1.1   reinoud 
   1936   1.1   reinoud 	if (error) {
   1937  1.12    andvar 		/* apparently too big */
   1938   1.1   reinoud 		free(pathbuf);
   1939   1.1   reinoud 		return error;
   1940   1.1   reinoud 	}
   1941   1.1   reinoud 
   1942   1.1   reinoud 	/* return status of symlink contents writeout */
   1943   1.1   reinoud 	*pathbufp = (uint8_t *) pathbuf;
   1944   1.1   reinoud 	*pathlenp = pathlen;
   1945   1.1   reinoud 
   1946   1.1   reinoud 	return 0;
   1947   1.1   reinoud 
   1948   1.1   reinoud }
   1949   1.1   reinoud #undef UDF_SYMLINKBUFLEN
   1950   1.1   reinoud 
   1951   1.1   reinoud 
   1952   1.1   reinoud /*
   1953   1.1   reinoud  * XXX note the different semantics from udfclient: for FIDs it still rounds
   1954   1.1   reinoud  * up to sectors. Use udf_fidsize() for a correct length.
   1955   1.1   reinoud  */
   1956   1.1   reinoud uint32_t
   1957   1.1   reinoud udf_tagsize(union dscrptr *dscr, uint32_t lb_size)
   1958   1.1   reinoud {
   1959   1.1   reinoud 	uint32_t size, tag_id, num_lb, elmsz;
   1960   1.1   reinoud 
   1961   1.1   reinoud 	tag_id = udf_rw16(dscr->tag.id);
   1962   1.1   reinoud 
   1963   1.1   reinoud 	switch (tag_id) {
   1964   1.1   reinoud 	case TAGID_LOGVOL :
   1965   1.1   reinoud 		size  = sizeof(struct logvol_desc) - 1;
   1966   1.1   reinoud 		size += udf_rw32(dscr->lvd.mt_l);
   1967   1.1   reinoud 		break;
   1968   1.1   reinoud 	case TAGID_UNALLOC_SPACE :
   1969   1.1   reinoud 		elmsz = sizeof(struct extent_ad);
   1970   1.1   reinoud 		size  = sizeof(struct unalloc_sp_desc) - elmsz;
   1971   1.1   reinoud 		size += udf_rw32(dscr->usd.alloc_desc_num) * elmsz;
   1972   1.1   reinoud 		break;
   1973   1.1   reinoud 	case TAGID_FID :
   1974   1.1   reinoud 		size = UDF_FID_SIZE + dscr->fid.l_fi + udf_rw16(dscr->fid.l_iu);
   1975   1.1   reinoud 		size = (size + 3) & ~3;
   1976   1.1   reinoud 		break;
   1977   1.1   reinoud 	case TAGID_LOGVOL_INTEGRITY :
   1978   1.1   reinoud 		size  = sizeof(struct logvol_int_desc) - sizeof(uint32_t);
   1979   1.1   reinoud 		size += udf_rw32(dscr->lvid.l_iu);
   1980   1.1   reinoud 		size += (2 * udf_rw32(dscr->lvid.num_part) * sizeof(uint32_t));
   1981   1.1   reinoud 		break;
   1982   1.1   reinoud 	case TAGID_SPACE_BITMAP :
   1983   1.1   reinoud 		size  = sizeof(struct space_bitmap_desc) - 1;
   1984   1.1   reinoud 		size += udf_rw32(dscr->sbd.num_bytes);
   1985   1.1   reinoud 		break;
   1986   1.1   reinoud 	case TAGID_SPARING_TABLE :
   1987   1.1   reinoud 		elmsz = sizeof(struct spare_map_entry);
   1988   1.1   reinoud 		size  = sizeof(struct udf_sparing_table) - elmsz;
   1989   1.1   reinoud 		size += udf_rw16(dscr->spt.rt_l) * elmsz;
   1990   1.1   reinoud 		break;
   1991   1.1   reinoud 	case TAGID_FENTRY :
   1992   1.1   reinoud 		size  = sizeof(struct file_entry);
   1993   1.1   reinoud 		size += udf_rw32(dscr->fe.l_ea) + udf_rw32(dscr->fe.l_ad)-1;
   1994   1.1   reinoud 		break;
   1995   1.1   reinoud 	case TAGID_EXTFENTRY :
   1996   1.1   reinoud 		size  = sizeof(struct extfile_entry);
   1997   1.1   reinoud 		size += udf_rw32(dscr->efe.l_ea) + udf_rw32(dscr->efe.l_ad)-1;
   1998   1.1   reinoud 		break;
   1999   1.1   reinoud 	case TAGID_FSD :
   2000   1.1   reinoud 		size  = sizeof(struct fileset_desc);
   2001   1.1   reinoud 		break;
   2002   1.1   reinoud 	default :
   2003   1.1   reinoud 		size = sizeof(union dscrptr);
   2004   1.1   reinoud 		break;
   2005   1.1   reinoud 	}
   2006   1.1   reinoud 
   2007   1.1   reinoud 	if ((size == 0) || (lb_size == 0))
   2008   1.1   reinoud 		return 0;
   2009   1.1   reinoud 
   2010   1.1   reinoud 	if (lb_size == 1)
   2011   1.1   reinoud 		return size;
   2012   1.1   reinoud 
   2013   1.1   reinoud 	/* round up in sectors */
   2014   1.1   reinoud 	num_lb = (size + lb_size -1) / lb_size;
   2015   1.1   reinoud 	return num_lb * lb_size;
   2016   1.1   reinoud }
   2017   1.1   reinoud 
   2018   1.1   reinoud 
   2019   1.1   reinoud int
   2020   1.1   reinoud udf_fidsize(struct fileid_desc *fid)
   2021   1.1   reinoud {
   2022   1.1   reinoud 	uint32_t size;
   2023   1.1   reinoud 
   2024   1.1   reinoud 	if (udf_rw16(fid->tag.id) != TAGID_FID)
   2025   1.1   reinoud 		errx(1, "internal error, bad tag in %s", __func__);
   2026   1.1   reinoud 
   2027   1.3   reinoud 	size = UDF_FID_SIZE + fid->l_fi + udf_rw16(fid->l_iu);
   2028   1.1   reinoud 	size = (size + 3) & ~3;
   2029   1.1   reinoud 
   2030   1.1   reinoud 	return size;
   2031   1.1   reinoud }
   2032   1.1   reinoud 
   2033   1.1   reinoud 
   2034   1.1   reinoud int
   2035   1.1   reinoud udf_create_parentfid(struct fileid_desc *fid, struct long_ad *parent)
   2036   1.1   reinoud {
   2037   1.1   reinoud 	/* the size of an empty FID is 38 but needs to be a multiple of 4 */
   2038   1.1   reinoud 	int fidsize = 40;
   2039   1.1   reinoud 
   2040   1.1   reinoud 	udf_inittag(&fid->tag, TAGID_FID, udf_rw32(parent->loc.lb_num));
   2041   1.1   reinoud 	fid->file_version_num = udf_rw16(1);	/* UDF 2.3.4.1 */
   2042   1.1   reinoud 	fid->file_char = UDF_FILE_CHAR_DIR | UDF_FILE_CHAR_PAR;
   2043   1.1   reinoud 	fid->icb = *parent;
   2044   1.1   reinoud 	fid->icb.longad_uniqueid = parent->longad_uniqueid;
   2045   1.1   reinoud 	fid->tag.desc_crc_len = udf_rw16(fidsize - UDF_DESC_TAG_LENGTH);
   2046   1.1   reinoud 
   2047   1.1   reinoud 	/* we have to do the fid here explicitly for simplicity */
   2048   1.1   reinoud 	udf_validate_tag_and_crc_sums((union dscrptr *) fid);
   2049   1.1   reinoud 
   2050   1.1   reinoud 	return fidsize;
   2051   1.1   reinoud }
   2052   1.1   reinoud 
   2053   1.1   reinoud 
   2054   1.1   reinoud void
   2055   1.1   reinoud udf_create_fid(uint32_t diroff, struct fileid_desc *fid, char *name,
   2056   1.1   reinoud 	int file_char, struct long_ad *ref)
   2057   1.1   reinoud {
   2058   1.1   reinoud 	struct charspec osta_charspec;
   2059   1.1   reinoud 	uint32_t endfid;
   2060   1.1   reinoud 	uint32_t fidsize, lb_rest;
   2061   1.1   reinoud 
   2062   1.1   reinoud 	memset(fid, 0, sizeof(*fid));
   2063   1.1   reinoud 	udf_inittag(&fid->tag, TAGID_FID, udf_rw32(ref->loc.lb_num));
   2064   1.1   reinoud 	fid->file_version_num = udf_rw16(1);	/* UDF 2.3.4.1 */
   2065   1.1   reinoud 	fid->file_char = file_char;
   2066   1.1   reinoud 	fid->l_iu = udf_rw16(0);
   2067   1.1   reinoud 	fid->icb = *ref;
   2068   1.1   reinoud 	fid->icb.longad_uniqueid = ref->longad_uniqueid;
   2069   1.1   reinoud 
   2070   1.1   reinoud 	udf_osta_charset(&osta_charspec);
   2071   1.1   reinoud 	unix_to_udf_name((char *) fid->data, &fid->l_fi, name, strlen(name),
   2072   1.1   reinoud 			&osta_charspec);
   2073   1.1   reinoud 
   2074   1.1   reinoud 	/*
   2075   1.1   reinoud 	 * OK, tricky part: we need to pad so the next descriptor header won't
   2076   1.1   reinoud 	 * cross the sector boundary
   2077   1.1   reinoud 	 */
   2078   1.1   reinoud 	endfid = diroff + udf_fidsize(fid);
   2079   1.1   reinoud 	lb_rest = context.sector_size - (endfid % context.sector_size);
   2080   1.1   reinoud 	if (lb_rest < sizeof(struct desc_tag)) {
   2081   1.1   reinoud 		/* add at least 32 */
   2082   1.1   reinoud 		fid->l_iu = udf_rw16(32);
   2083   1.1   reinoud 		udf_set_regid((struct regid *) fid->data, context.impl_name);
   2084   1.1   reinoud 		udf_add_impl_regid((struct regid *) fid->data);
   2085   1.1   reinoud 
   2086   1.1   reinoud 		unix_to_udf_name((char *) fid->data + udf_rw16(fid->l_iu),
   2087   1.1   reinoud 			&fid->l_fi, name, strlen(name), &osta_charspec);
   2088   1.1   reinoud 	}
   2089   1.1   reinoud 
   2090   1.1   reinoud 	fidsize = udf_fidsize(fid);
   2091   1.1   reinoud 	fid->tag.desc_crc_len = udf_rw16(fidsize - UDF_DESC_TAG_LENGTH);
   2092   1.1   reinoud 
   2093   1.1   reinoud 	/* make sure the header sums stays correct */
   2094   1.1   reinoud 	udf_validate_tag_and_crc_sums((union dscrptr *)fid);
   2095   1.1   reinoud }
   2096   1.1   reinoud 
   2097   1.1   reinoud 
   2098   1.1   reinoud static void
   2099   1.1   reinoud udf_append_parentfid(union dscrptr *dscr, struct long_ad *parent_icb)
   2100   1.1   reinoud {
   2101   1.1   reinoud 	struct file_entry      *fe;
   2102   1.1   reinoud 	struct extfile_entry   *efe;
   2103   1.1   reinoud 	struct fileid_desc     *fid;
   2104   1.1   reinoud 	uint32_t l_ea;
   2105   1.1   reinoud 	uint32_t fidsize, crclen;
   2106   1.1   reinoud 	uint8_t *bpos, *data;
   2107   1.1   reinoud 
   2108   1.1   reinoud 	fe = NULL;
   2109   1.1   reinoud 	efe = NULL;
   2110   1.1   reinoud 	if (udf_rw16(dscr->tag.id) == TAGID_FENTRY) {
   2111   1.1   reinoud 		fe    = &dscr->fe;
   2112   1.1   reinoud 		data  = fe->data;
   2113   1.1   reinoud 		l_ea  = udf_rw32(fe->l_ea);
   2114   1.1   reinoud 	} else if (udf_rw16(dscr->tag.id) == TAGID_EXTFENTRY) {
   2115   1.1   reinoud 		efe   = &dscr->efe;
   2116   1.1   reinoud 		data  = efe->data;
   2117   1.1   reinoud 		l_ea  = udf_rw32(efe->l_ea);
   2118   1.1   reinoud 	} else {
   2119   1.1   reinoud 		errx(1, "internal error, bad tag in %s", __func__);
   2120   1.1   reinoud 	}
   2121   1.1   reinoud 
   2122   1.1   reinoud 	/* create '..' */
   2123   1.1   reinoud 	bpos = data + l_ea;
   2124   1.1   reinoud 	fid  = (struct fileid_desc *) bpos;
   2125   1.1   reinoud 	fidsize = udf_create_parentfid(fid, parent_icb);
   2126   1.1   reinoud 
   2127   1.1   reinoud 	/* record fidlength information */
   2128   1.1   reinoud 	if (fe) {
   2129   1.1   reinoud 		fe->inf_len     = udf_rw64(fidsize);
   2130   1.1   reinoud 		fe->l_ad        = udf_rw32(fidsize);
   2131   1.1   reinoud 		fe->logblks_rec = udf_rw64(0);		/* intern */
   2132   1.1   reinoud 		crclen  = sizeof(struct file_entry);
   2133   1.1   reinoud 	} else {
   2134   1.1   reinoud 		efe->inf_len     = udf_rw64(fidsize);
   2135   1.1   reinoud 		efe->obj_size    = udf_rw64(fidsize);
   2136   1.1   reinoud 		efe->l_ad        = udf_rw32(fidsize);
   2137   1.1   reinoud 		efe->logblks_rec = udf_rw64(0);		/* intern */
   2138   1.1   reinoud 		crclen  = sizeof(struct extfile_entry);
   2139   1.1   reinoud 	}
   2140   1.1   reinoud 	crclen -= 1 + UDF_DESC_TAG_LENGTH;
   2141   1.1   reinoud 	crclen += l_ea + fidsize;
   2142   1.1   reinoud 	dscr->tag.desc_crc_len = udf_rw16(crclen);
   2143   1.1   reinoud 
   2144   1.1   reinoud 	/* make sure the header sums stays correct */
   2145   1.1   reinoud 	udf_validate_tag_and_crc_sums(dscr);
   2146   1.1   reinoud }
   2147   1.1   reinoud 
   2148   1.1   reinoud /* --------------------------------------------------------------------- */
   2149   1.1   reinoud 
   2150   1.1   reinoud /*
   2151   1.1   reinoud  * Extended attribute support. UDF knows of 3 places for extended attributes:
   2152   1.1   reinoud  *
   2153   1.1   reinoud  * (a) inside the file's (e)fe in the length of the extended attribute area
   2154   1.1   reinoud  * before the allocation descriptors/filedata
   2155   1.1   reinoud  *
   2156   1.1   reinoud  * (b) in a file referenced by (e)fe->ext_attr_icb and
   2157   1.1   reinoud  *
   2158   1.1   reinoud  * (c) in the e(fe)'s associated stream directory that can hold various
   2159   1.1   reinoud  * sub-files. In the stream directory a few fixed named subfiles are reserved
   2160   1.1   reinoud  * for NT/Unix ACL's and OS/2 attributes.
   2161   1.1   reinoud  *
   2162   1.1   reinoud  * NOTE: Extended attributes are read randomly but always written
   2163   1.1   reinoud  * *atomically*. For ACL's this interface is probably different but not known
   2164   1.1   reinoud  * to me yet.
   2165   1.1   reinoud  *
   2166   1.1   reinoud  * Order of extended attributes in a space:
   2167   1.1   reinoud  *   ECMA 167 EAs
   2168   1.1   reinoud  *   Non block aligned Implementation Use EAs
   2169   1.1   reinoud  *   Block aligned Implementation Use EAs
   2170   1.1   reinoud  *   Application Use EAs
   2171   1.1   reinoud  */
   2172   1.1   reinoud 
   2173   1.1   reinoud int
   2174   1.1   reinoud udf_impl_extattr_check(struct impl_extattr_entry *implext)
   2175   1.1   reinoud {
   2176   1.1   reinoud 	uint16_t   *spos;
   2177   1.1   reinoud 
   2178   1.1   reinoud 	if (strncmp((char *) implext->imp_id.id, "*UDF", 4) == 0) {
   2179   1.1   reinoud 		/* checksum valid? */
   2180   1.1   reinoud 		spos = (uint16_t *) implext->data;
   2181   1.1   reinoud 		if (udf_rw16(*spos) != udf_ea_cksum((uint8_t *) implext))
   2182   1.1   reinoud 			return EINVAL;
   2183   1.1   reinoud 	}
   2184   1.1   reinoud 	return 0;
   2185   1.1   reinoud }
   2186   1.1   reinoud 
   2187   1.1   reinoud void
   2188   1.1   reinoud udf_calc_impl_extattr_checksum(struct impl_extattr_entry *implext)
   2189   1.1   reinoud {
   2190   1.1   reinoud 	uint16_t   *spos;
   2191   1.1   reinoud 
   2192   1.1   reinoud 	if (strncmp((char *) implext->imp_id.id, "*UDF", 4) == 0) {
   2193   1.1   reinoud 		/* set checksum */
   2194   1.1   reinoud 		spos = (uint16_t *) implext->data;
   2195   1.1   reinoud 		*spos = udf_rw16(udf_ea_cksum((uint8_t *) implext));
   2196   1.1   reinoud 	}
   2197   1.1   reinoud }
   2198   1.1   reinoud 
   2199   1.1   reinoud 
   2200   1.1   reinoud int
   2201   1.1   reinoud udf_extattr_search_intern(union dscrptr *dscr,
   2202   1.1   reinoud 	uint32_t sattr, char const *sattrname,
   2203   1.1   reinoud 	uint32_t *offsetp, uint32_t *lengthp)
   2204   1.1   reinoud {
   2205   1.1   reinoud 	struct extattrhdr_desc    *eahdr;
   2206   1.1   reinoud 	struct extattr_entry      *attrhdr;
   2207   1.1   reinoud 	struct impl_extattr_entry *implext;
   2208   1.1   reinoud 	uint32_t    offset, a_l, sector_size;
   2209   1.1   reinoud 	uint32_t    l_ea;
   2210   1.1   reinoud 	uint8_t    *pos;
   2211   1.1   reinoud 	int         tag_id, error;
   2212   1.1   reinoud 
   2213   1.1   reinoud 	sector_size = context.sector_size;
   2214   1.1   reinoud 
   2215   1.1   reinoud 	/* get information from fe/efe */
   2216   1.1   reinoud 	tag_id = udf_rw16(dscr->tag.id);
   2217   1.1   reinoud 	if (tag_id == TAGID_FENTRY) {
   2218   1.1   reinoud 		l_ea  = udf_rw32(dscr->fe.l_ea);
   2219   1.1   reinoud 		eahdr = (struct extattrhdr_desc *) dscr->fe.data;
   2220   1.1   reinoud 	} else {
   2221   1.1   reinoud 		assert(tag_id == TAGID_EXTFENTRY);
   2222   1.1   reinoud 		l_ea  = udf_rw32(dscr->efe.l_ea);
   2223   1.1   reinoud 		eahdr = (struct extattrhdr_desc *) dscr->efe.data;
   2224   1.1   reinoud 	}
   2225   1.1   reinoud 
   2226   1.1   reinoud 	/* something recorded here? */
   2227   1.1   reinoud 	if (l_ea == 0)
   2228   1.1   reinoud 		return ENOENT;
   2229   1.1   reinoud 
   2230   1.1   reinoud 	/* check extended attribute tag; what to do if it fails? */
   2231   1.1   reinoud 	error = udf_check_tag(eahdr);
   2232   1.1   reinoud 	if (error)
   2233   1.1   reinoud 		return EINVAL;
   2234   1.1   reinoud 	if (udf_rw16(eahdr->tag.id) != TAGID_EXTATTR_HDR)
   2235   1.1   reinoud 		return EINVAL;
   2236   1.1   reinoud 	error = udf_check_tag_payload(eahdr, sizeof(struct extattrhdr_desc));
   2237   1.1   reinoud 	if (error)
   2238   1.1   reinoud 		return EINVAL;
   2239   1.1   reinoud 
   2240   1.1   reinoud 	/* looking for Ecma-167 attributes? */
   2241   1.1   reinoud 	offset = sizeof(struct extattrhdr_desc);
   2242   1.1   reinoud 
   2243   1.1   reinoud 	/* looking for either implementation use or application use */
   2244   1.1   reinoud 	if (sattr == 2048) {				/* [4/48.10.8] */
   2245   1.1   reinoud 		offset = udf_rw32(eahdr->impl_attr_loc);
   2246   1.1   reinoud 		if (offset == UDF_IMPL_ATTR_LOC_NOT_PRESENT)
   2247   1.1   reinoud 			return ENOENT;
   2248   1.1   reinoud 	}
   2249   1.1   reinoud 	if (sattr == 65536) {				/* [4/48.10.9] */
   2250   1.1   reinoud 		offset = udf_rw32(eahdr->appl_attr_loc);
   2251   1.1   reinoud 		if (offset == UDF_APPL_ATTR_LOC_NOT_PRESENT)
   2252   1.1   reinoud 			return ENOENT;
   2253   1.1   reinoud 	}
   2254   1.1   reinoud 
   2255   1.1   reinoud 	/* paranoia check offset and l_ea */
   2256   1.1   reinoud 	if (l_ea + offset >= sector_size - sizeof(struct extattr_entry))
   2257   1.1   reinoud 		return EINVAL;
   2258   1.1   reinoud 
   2259   1.1   reinoud 	/* find our extended attribute  */
   2260   1.1   reinoud 	l_ea -= offset;
   2261   1.1   reinoud 	pos = (uint8_t *) eahdr + offset;
   2262   1.1   reinoud 
   2263   1.1   reinoud 	while (l_ea >= sizeof(struct extattr_entry)) {
   2264   1.1   reinoud 		attrhdr = (struct extattr_entry *) pos;
   2265   1.1   reinoud 		implext = (struct impl_extattr_entry *) pos;
   2266   1.1   reinoud 
   2267   1.1   reinoud 		/* get complete attribute length and check for roque values */
   2268   1.1   reinoud 		a_l = udf_rw32(attrhdr->a_l);
   2269   1.1   reinoud 		if ((a_l == 0) || (a_l > l_ea))
   2270   1.1   reinoud 			return EINVAL;
   2271   1.1   reinoud 
   2272   1.4   reinoud 		if (udf_rw32(attrhdr->type) != sattr)
   2273   1.1   reinoud 			goto next_attribute;
   2274   1.1   reinoud 
   2275   1.1   reinoud 		/* we might have found it! */
   2276   1.4   reinoud 		if (udf_rw32(attrhdr->type) < 2048) {	/* Ecma-167 attribute */
   2277   1.1   reinoud 			*offsetp = offset;
   2278   1.1   reinoud 			*lengthp = a_l;
   2279   1.1   reinoud 			return 0;		/* success */
   2280   1.1   reinoud 		}
   2281   1.1   reinoud 
   2282   1.1   reinoud 		/*
   2283   1.1   reinoud 		 * Implementation use and application use extended attributes
   2284   1.1   reinoud 		 * have a name to identify. They share the same structure only
   2285   1.1   reinoud 		 * UDF implementation use extended attributes have a checksum
   2286   1.1   reinoud 		 * we need to check
   2287   1.1   reinoud 		 */
   2288   1.1   reinoud 
   2289   1.1   reinoud 		if (strcmp((char *) implext->imp_id.id, sattrname) == 0) {
   2290   1.1   reinoud 			/* we have found our appl/implementation attribute */
   2291   1.1   reinoud 			*offsetp = offset;
   2292   1.1   reinoud 			*lengthp = a_l;
   2293   1.1   reinoud 			return 0;		/* success */
   2294   1.1   reinoud 		}
   2295   1.1   reinoud 
   2296   1.1   reinoud next_attribute:
   2297   1.1   reinoud 		/* next attribute */
   2298   1.1   reinoud 		pos    += a_l;
   2299   1.1   reinoud 		l_ea   -= a_l;
   2300   1.1   reinoud 		offset += a_l;
   2301   1.1   reinoud 	}
   2302   1.1   reinoud 	/* not found */
   2303   1.1   reinoud 	return ENOENT;
   2304   1.1   reinoud }
   2305   1.1   reinoud 
   2306   1.1   reinoud 
   2307   1.1   reinoud static void
   2308   1.1   reinoud udf_extattr_insert_internal(union dscrptr *dscr, struct extattr_entry *extattr)
   2309   1.1   reinoud {
   2310   1.1   reinoud 	struct file_entry      *fe;
   2311   1.1   reinoud 	struct extfile_entry   *efe;
   2312   1.1   reinoud 	struct extattrhdr_desc *extattrhdr;
   2313   1.1   reinoud 	struct impl_extattr_entry *implext;
   2314   1.1   reinoud 	uint32_t impl_attr_loc, appl_attr_loc, l_ea, l_ad, a_l;
   2315   1.1   reinoud 	uint16_t *spos;
   2316   1.1   reinoud 	uint8_t *bpos, *data;
   2317   1.1   reinoud 	void *l_eap;
   2318   1.1   reinoud 
   2319   1.1   reinoud 	if (udf_rw16(dscr->tag.id) == TAGID_FENTRY) {
   2320   1.1   reinoud 		fe    = &dscr->fe;
   2321   1.1   reinoud 		data  = fe->data;
   2322   1.1   reinoud 		l_eap = &fe->l_ea;
   2323   1.1   reinoud 		l_ad  = udf_rw32(fe->l_ad);
   2324   1.1   reinoud 	} else if (udf_rw16(dscr->tag.id) == TAGID_EXTFENTRY) {
   2325   1.1   reinoud 		efe   = &dscr->efe;
   2326   1.1   reinoud 		data  = efe->data;
   2327   1.1   reinoud 		l_eap = &efe->l_ea;
   2328   1.1   reinoud 		l_ad  = udf_rw32(efe->l_ad);
   2329   1.1   reinoud 	} else {
   2330   1.1   reinoud 		errx(1, "internal error, bad tag in %s", __func__);
   2331   1.1   reinoud 	}
   2332   1.1   reinoud 
   2333   1.1   reinoud 	/* should have a header! */
   2334   1.1   reinoud 	extattrhdr = (struct extattrhdr_desc *) data;
   2335   1.1   reinoud 	memcpy(&l_ea, l_eap, sizeof(l_ea));
   2336   1.1   reinoud 	l_ea = udf_rw32(l_ea);
   2337   1.1   reinoud 	if (l_ea == 0) {
   2338   1.1   reinoud 		uint32_t exthdr_len;
   2339   1.1   reinoud 		assert(l_ad == 0);
   2340   1.1   reinoud 		/* create empty extended attribute header */
   2341   1.1   reinoud 		l_ea = sizeof(struct extattrhdr_desc);
   2342   1.1   reinoud 		exthdr_len = udf_rw32(l_ea);
   2343   1.1   reinoud 
   2344   1.1   reinoud 		udf_inittag(&extattrhdr->tag, TAGID_EXTATTR_HDR, /* loc */ 0);
   2345   1.1   reinoud 		extattrhdr->impl_attr_loc = exthdr_len;
   2346   1.1   reinoud 		extattrhdr->appl_attr_loc = exthdr_len;
   2347   1.1   reinoud 		extattrhdr->tag.desc_crc_len = udf_rw16(8);
   2348   1.1   reinoud 
   2349   1.1   reinoud 		/* record extended attribute header length */
   2350   1.1   reinoud 		memcpy(l_eap, &exthdr_len, sizeof(exthdr_len));
   2351   1.1   reinoud 	}
   2352   1.1   reinoud 
   2353   1.1   reinoud 	/* extract locations */
   2354   1.1   reinoud 	impl_attr_loc = udf_rw32(extattrhdr->impl_attr_loc);
   2355   1.1   reinoud 	appl_attr_loc = udf_rw32(extattrhdr->appl_attr_loc);
   2356   1.1   reinoud 	if (impl_attr_loc == UDF_IMPL_ATTR_LOC_NOT_PRESENT)
   2357   1.1   reinoud 		impl_attr_loc = l_ea;
   2358   1.1   reinoud 	if (appl_attr_loc == UDF_IMPL_ATTR_LOC_NOT_PRESENT)
   2359   1.1   reinoud 		appl_attr_loc = l_ea;
   2360   1.1   reinoud 
   2361   1.1   reinoud 	/* Ecma 167 EAs */
   2362   1.1   reinoud 	if (udf_rw32(extattr->type) < 2048) {
   2363   1.1   reinoud 		assert(impl_attr_loc == l_ea);
   2364   1.1   reinoud 		assert(appl_attr_loc == l_ea);
   2365   1.1   reinoud 	}
   2366   1.1   reinoud 
   2367   1.1   reinoud 	/* implementation use extended attributes */
   2368   1.1   reinoud 	if (udf_rw32(extattr->type) == 2048) {
   2369   1.1   reinoud 		assert(appl_attr_loc == l_ea);
   2370   1.1   reinoud 
   2371   1.1   reinoud 		/* calculate and write extended attribute header checksum */
   2372   1.1   reinoud 		implext = (struct impl_extattr_entry *) extattr;
   2373   1.1   reinoud 		assert(udf_rw32(implext->iu_l) == 4);	/* [UDF 3.3.4.5] */
   2374   1.1   reinoud 		spos = (uint16_t *) implext->data;
   2375   1.1   reinoud 		*spos = udf_rw16(udf_ea_cksum((uint8_t *) implext));
   2376   1.1   reinoud 	}
   2377   1.1   reinoud 
   2378   1.1   reinoud 	/* application use extended attributes */
   2379   1.1   reinoud 	assert(udf_rw32(extattr->type) != 65536);
   2380   1.1   reinoud 	assert(appl_attr_loc == l_ea);
   2381   1.1   reinoud 
   2382   1.1   reinoud 	/* append the attribute at the end of the current space */
   2383   1.1   reinoud 	bpos = data + l_ea;
   2384   1.1   reinoud 	a_l  = udf_rw32(extattr->a_l);
   2385   1.1   reinoud 
   2386   1.1   reinoud 	/* update impl. attribute locations */
   2387   1.1   reinoud 	if (udf_rw32(extattr->type) < 2048) {
   2388   1.1   reinoud 		impl_attr_loc = l_ea + a_l;
   2389   1.1   reinoud 		appl_attr_loc = l_ea + a_l;
   2390   1.1   reinoud 	}
   2391   1.1   reinoud 	if (udf_rw32(extattr->type) == 2048) {
   2392   1.1   reinoud 		appl_attr_loc = l_ea + a_l;
   2393   1.1   reinoud 	}
   2394   1.1   reinoud 
   2395   1.1   reinoud 	/* copy and advance */
   2396   1.1   reinoud 	memcpy(bpos, extattr, a_l);
   2397   1.1   reinoud 	l_ea += a_l;
   2398   1.1   reinoud 	l_ea = udf_rw32(l_ea);
   2399   1.1   reinoud 	memcpy(l_eap, &l_ea, sizeof(l_ea));
   2400   1.1   reinoud 
   2401   1.1   reinoud 	/* do the `dance` again backwards */
   2402   1.1   reinoud 	if (context.dscrver != 2) {
   2403   1.1   reinoud 		if (impl_attr_loc == l_ea)
   2404   1.1   reinoud 			impl_attr_loc = UDF_IMPL_ATTR_LOC_NOT_PRESENT;
   2405   1.1   reinoud 		if (appl_attr_loc == l_ea)
   2406   1.1   reinoud 			appl_attr_loc = UDF_APPL_ATTR_LOC_NOT_PRESENT;
   2407   1.1   reinoud 	}
   2408   1.1   reinoud 
   2409   1.1   reinoud 	/* store offsets */
   2410   1.1   reinoud 	extattrhdr->impl_attr_loc = udf_rw32(impl_attr_loc);
   2411   1.1   reinoud 	extattrhdr->appl_attr_loc = udf_rw32(appl_attr_loc);
   2412   1.1   reinoud 
   2413   1.1   reinoud 	/* make sure the header sums stays correct */
   2414   1.1   reinoud 	udf_validate_tag_and_crc_sums((union dscrptr *) extattrhdr);
   2415   1.1   reinoud }
   2416   1.1   reinoud 
   2417   1.1   reinoud /* --------------------------------------------------------------------- */
   2418   1.1   reinoud 
   2419   1.1   reinoud int
   2420   1.1   reinoud udf_create_new_fe(struct file_entry **fep, int file_type, struct stat *st)
   2421   1.1   reinoud {
   2422   1.1   reinoud 	struct file_entry      *fe;
   2423   1.1   reinoud 	struct icb_tag         *icb;
   2424   1.1   reinoud 	struct timestamp        birthtime;
   2425   1.1   reinoud 	struct filetimes_extattr_entry *ft_extattr;
   2426   1.1   reinoud 	uint32_t crclen;	/* XXX: should be 16; need to detect overflow */
   2427   1.1   reinoud 	uint16_t icbflags;
   2428   1.1   reinoud 
   2429   1.1   reinoud 	*fep = NULL;
   2430   1.1   reinoud 	fe = calloc(1, context.sector_size);
   2431   1.1   reinoud 	if (fe == NULL)
   2432   1.1   reinoud 		return ENOMEM;
   2433   1.1   reinoud 
   2434   1.1   reinoud 	udf_inittag(&fe->tag, TAGID_FENTRY, /* loc */ 0);
   2435   1.1   reinoud 	icb = &fe->icbtag;
   2436   1.1   reinoud 
   2437   1.1   reinoud 	/*
   2438  1.11    andvar 	 * Always use strategy type 4 unless on WORM which we don't support
   2439   1.1   reinoud 	 * (yet). Fill in defaults and set for internal allocation of data.
   2440   1.1   reinoud 	 */
   2441   1.1   reinoud 	icb->strat_type      = udf_rw16(4);
   2442   1.1   reinoud 	icb->max_num_entries = udf_rw16(1);
   2443   1.1   reinoud 	icb->file_type       = file_type;	/* 8 bit */
   2444   1.1   reinoud 	icb->flags           = udf_rw16(UDF_ICB_INTERN_ALLOC);
   2445   1.1   reinoud 
   2446   1.1   reinoud 	fe->perm     = udf_rw32(0x7fff);	/* all is allowed   */
   2447   1.1   reinoud 	fe->link_cnt = udf_rw16(0);		/* explicit setting */
   2448   1.1   reinoud 
   2449   1.1   reinoud 	fe->ckpoint  = udf_rw32(1);		/* user supplied file version */
   2450   1.1   reinoud 
   2451   1.1   reinoud 	udf_set_timestamp_now(&birthtime);
   2452   1.1   reinoud 	udf_set_timestamp_now(&fe->atime);
   2453   1.1   reinoud 	udf_set_timestamp_now(&fe->attrtime);
   2454   1.1   reinoud 	udf_set_timestamp_now(&fe->mtime);
   2455   1.1   reinoud 
   2456   1.1   reinoud 	/* set attributes */
   2457   1.1   reinoud 	if (st) {
   2458   1.1   reinoud #if !HAVE_NBTOOL_CONFIG_H
   2459   1.1   reinoud 		udf_set_timestamp(&birthtime,    st->st_birthtime);
   2460   1.1   reinoud #else
   2461   1.1   reinoud 		udf_set_timestamp(&birthtime,    0);
   2462   1.1   reinoud #endif
   2463   1.1   reinoud 		udf_set_timestamp(&fe->atime,    st->st_atime);
   2464   1.1   reinoud 		udf_set_timestamp(&fe->attrtime, st->st_ctime);
   2465   1.1   reinoud 		udf_set_timestamp(&fe->mtime,    st->st_mtime);
   2466   1.1   reinoud 		fe->uid  = udf_rw32(st->st_uid);
   2467   1.1   reinoud 		fe->gid  = udf_rw32(st->st_gid);
   2468   1.1   reinoud 
   2469   1.7   reinoud 		fe->perm = udf_rw32(unix_mode_to_udf_perm(st->st_mode));
   2470   1.1   reinoud 
   2471   1.1   reinoud 		icbflags = udf_rw16(fe->icbtag.flags);
   2472   1.1   reinoud 		icbflags &= ~UDF_ICB_TAG_FLAGS_SETUID;
   2473   1.1   reinoud 		icbflags &= ~UDF_ICB_TAG_FLAGS_SETGID;
   2474   1.1   reinoud 		icbflags &= ~UDF_ICB_TAG_FLAGS_STICKY;
   2475   1.1   reinoud 		if (st->st_mode & S_ISUID)
   2476   1.1   reinoud 			icbflags |= UDF_ICB_TAG_FLAGS_SETUID;
   2477   1.1   reinoud 		if (st->st_mode & S_ISGID)
   2478   1.1   reinoud 			icbflags |= UDF_ICB_TAG_FLAGS_SETGID;
   2479   1.1   reinoud 		if (st->st_mode & S_ISVTX)
   2480   1.1   reinoud 			icbflags |= UDF_ICB_TAG_FLAGS_STICKY;
   2481   1.1   reinoud 		fe->icbtag.flags  = udf_rw16(icbflags);
   2482   1.1   reinoud 	}
   2483   1.1   reinoud 
   2484   1.1   reinoud 	udf_set_regid(&fe->imp_id, context.impl_name);
   2485   1.1   reinoud 	udf_add_impl_regid(&fe->imp_id);
   2486   1.1   reinoud 	fe->unique_id = udf_rw64(context.unique_id);
   2487   1.1   reinoud 	udf_advance_uniqueid();
   2488   1.1   reinoud 
   2489   1.1   reinoud 	fe->l_ea = udf_rw32(0);
   2490   1.1   reinoud 
   2491   1.1   reinoud 	/* create extended attribute to record our creation time */
   2492   1.1   reinoud 	ft_extattr = calloc(1, UDF_FILETIMES_ATTR_SIZE(1));
   2493   1.1   reinoud 	ft_extattr->hdr.type = udf_rw32(UDF_FILETIMES_ATTR_NO);
   2494   1.1   reinoud 	ft_extattr->hdr.subtype = 1;	/* [4/48.10.5] */
   2495   1.1   reinoud 	ft_extattr->hdr.a_l = udf_rw32(UDF_FILETIMES_ATTR_SIZE(1));
   2496   1.1   reinoud 	ft_extattr->d_l     = udf_rw32(UDF_TIMESTAMP_SIZE); /* one item */
   2497   1.1   reinoud 	ft_extattr->existence = UDF_FILETIMES_FILE_CREATION;
   2498   1.1   reinoud 	ft_extattr->times[0]  = birthtime;
   2499   1.1   reinoud 
   2500   1.1   reinoud 	udf_extattr_insert_internal((union dscrptr *) fe,
   2501   1.1   reinoud 		(struct extattr_entry *) ft_extattr);
   2502   1.1   reinoud 	free(ft_extattr);
   2503   1.1   reinoud 
   2504   1.1   reinoud 	/* record fidlength information */
   2505   1.1   reinoud 	fe->inf_len = udf_rw64(0);
   2506   1.1   reinoud 	fe->l_ad    = udf_rw32(0);
   2507   1.1   reinoud 	fe->logblks_rec = udf_rw64(0);		/* intern */
   2508   1.1   reinoud 
   2509   1.1   reinoud 	crclen  = sizeof(struct file_entry) - 1 - UDF_DESC_TAG_LENGTH;
   2510   1.1   reinoud 	crclen += udf_rw32(fe->l_ea);
   2511   1.1   reinoud 
   2512   1.1   reinoud 	/* make sure the header sums stays correct */
   2513   1.1   reinoud 	fe->tag.desc_crc_len = udf_rw16(crclen);
   2514   1.1   reinoud 	udf_validate_tag_and_crc_sums((union dscrptr *) fe);
   2515   1.1   reinoud 
   2516   1.1   reinoud 	*fep = fe;
   2517   1.1   reinoud 	return 0;
   2518   1.1   reinoud }
   2519   1.1   reinoud 
   2520   1.1   reinoud 
   2521   1.1   reinoud int
   2522   1.1   reinoud udf_create_new_efe(struct extfile_entry **efep, int file_type, struct stat *st)
   2523   1.1   reinoud {
   2524   1.1   reinoud 	struct extfile_entry *efe;
   2525   1.1   reinoud 	struct icb_tag       *icb;
   2526   1.1   reinoud 	uint32_t crclen;	/* XXX: should be 16; need to detect overflow */
   2527   1.1   reinoud 	uint16_t icbflags;
   2528   1.1   reinoud 
   2529   1.1   reinoud 	*efep = NULL;
   2530   1.1   reinoud 	efe = calloc(1, context.sector_size);
   2531   1.1   reinoud 	if (efe == NULL)
   2532   1.1   reinoud 		return ENOMEM;
   2533   1.1   reinoud 
   2534   1.1   reinoud 	udf_inittag(&efe->tag, TAGID_EXTFENTRY, /* loc */ 0);
   2535   1.1   reinoud 	icb = &efe->icbtag;
   2536   1.1   reinoud 
   2537   1.1   reinoud 	/*
   2538  1.11    andvar 	 * Always use strategy type 4 unless on WORM which we don't support
   2539   1.1   reinoud 	 * (yet). Fill in defaults and set for internal allocation of data.
   2540   1.1   reinoud 	 */
   2541   1.1   reinoud 	icb->strat_type      = udf_rw16(4);
   2542   1.1   reinoud 	icb->max_num_entries = udf_rw16(1);
   2543   1.1   reinoud 	icb->file_type       = file_type;	/* 8 bit */
   2544   1.1   reinoud 	icb->flags = udf_rw16(UDF_ICB_INTERN_ALLOC);
   2545   1.1   reinoud 
   2546   1.1   reinoud 	efe->perm     = udf_rw32(0x7fff);	/* all is allowed   */
   2547   1.1   reinoud 	efe->link_cnt = udf_rw16(0);		/* explicit setting */
   2548   1.1   reinoud 
   2549   1.1   reinoud 	efe->ckpoint  = udf_rw32(1);		/* user supplied file version */
   2550   1.1   reinoud 
   2551   1.1   reinoud 	udf_set_timestamp_now(&efe->ctime);
   2552   1.1   reinoud 	udf_set_timestamp_now(&efe->atime);
   2553   1.1   reinoud 	udf_set_timestamp_now(&efe->attrtime);
   2554   1.1   reinoud 	udf_set_timestamp_now(&efe->mtime);
   2555   1.1   reinoud 
   2556   1.1   reinoud 	/* set attributes */
   2557   1.1   reinoud 	if (st) {
   2558   1.1   reinoud #if !HAVE_NBTOOL_CONFIG_H
   2559   1.1   reinoud 		udf_set_timestamp(&efe->ctime,    st->st_birthtime);
   2560   1.1   reinoud #else
   2561   1.1   reinoud 		udf_set_timestamp(&efe->ctime,    0);
   2562   1.1   reinoud #endif
   2563   1.1   reinoud 		udf_set_timestamp(&efe->atime,    st->st_atime);
   2564   1.1   reinoud 		udf_set_timestamp(&efe->attrtime, st->st_ctime);
   2565   1.1   reinoud 		udf_set_timestamp(&efe->mtime,    st->st_mtime);
   2566   1.1   reinoud 		efe->uid = udf_rw32(st->st_uid);
   2567   1.1   reinoud 		efe->gid = udf_rw32(st->st_gid);
   2568   1.1   reinoud 
   2569   1.7   reinoud 		efe->perm = udf_rw32(unix_mode_to_udf_perm(st->st_mode));
   2570   1.1   reinoud 
   2571   1.1   reinoud 		icbflags = udf_rw16(efe->icbtag.flags);
   2572   1.1   reinoud 		icbflags &= ~UDF_ICB_TAG_FLAGS_SETUID;
   2573   1.1   reinoud 		icbflags &= ~UDF_ICB_TAG_FLAGS_SETGID;
   2574   1.1   reinoud 		icbflags &= ~UDF_ICB_TAG_FLAGS_STICKY;
   2575   1.1   reinoud 		if (st->st_mode & S_ISUID)
   2576   1.1   reinoud 			icbflags |= UDF_ICB_TAG_FLAGS_SETUID;
   2577   1.1   reinoud 		if (st->st_mode & S_ISGID)
   2578   1.1   reinoud 			icbflags |= UDF_ICB_TAG_FLAGS_SETGID;
   2579   1.1   reinoud 		if (st->st_mode & S_ISVTX)
   2580   1.1   reinoud 			icbflags |= UDF_ICB_TAG_FLAGS_STICKY;
   2581   1.1   reinoud 		efe->icbtag.flags = udf_rw16(icbflags);
   2582   1.1   reinoud 	}
   2583   1.1   reinoud 
   2584   1.1   reinoud 	udf_set_regid(&efe->imp_id, context.impl_name);
   2585   1.1   reinoud 	udf_add_impl_regid(&efe->imp_id);
   2586   1.1   reinoud 
   2587   1.1   reinoud 	efe->unique_id = udf_rw64(context.unique_id);
   2588   1.1   reinoud 	udf_advance_uniqueid();
   2589   1.1   reinoud 
   2590   1.1   reinoud 	/* record fidlength information */
   2591   1.1   reinoud 	efe->inf_len  = udf_rw64(0);
   2592   1.1   reinoud 	efe->obj_size = udf_rw64(0);
   2593   1.1   reinoud 	efe->l_ad     = udf_rw32(0);
   2594   1.1   reinoud 	efe->logblks_rec = udf_rw64(0);
   2595   1.1   reinoud 
   2596   1.1   reinoud 	crclen  = sizeof(struct extfile_entry) - 1 - UDF_DESC_TAG_LENGTH;
   2597   1.1   reinoud 
   2598   1.1   reinoud 	/* make sure the header sums stays correct */
   2599   1.1   reinoud 	efe->tag.desc_crc_len = udf_rw16(crclen);
   2600   1.1   reinoud 	udf_validate_tag_and_crc_sums((union dscrptr *) efe);
   2601   1.1   reinoud 
   2602   1.1   reinoud 	*efep = efe;
   2603   1.1   reinoud 	return 0;
   2604   1.1   reinoud }
   2605   1.1   reinoud 
   2606   1.1   reinoud /* --------------------------------------------------------------------- */
   2607   1.1   reinoud 
   2608   1.1   reinoud /* for METADATA file appending only */
   2609   1.1   reinoud static void
   2610   1.1   reinoud udf_append_meta_mapping_part_to_efe(struct extfile_entry *efe,
   2611   1.1   reinoud 		struct short_ad *mapping)
   2612   1.1   reinoud {
   2613   1.1   reinoud 	struct icb_tag *icb;
   2614   1.1   reinoud 	uint64_t inf_len, obj_size, logblks_rec;
   2615   1.1   reinoud 	uint32_t l_ad, l_ea;
   2616   1.1   reinoud 	uint16_t crclen;
   2617   1.1   reinoud 	uintptr_t bpos;
   2618   1.1   reinoud 
   2619   1.1   reinoud 	inf_len     = udf_rw64(efe->inf_len);
   2620   1.1   reinoud 	obj_size    = udf_rw64(efe->obj_size);
   2621   1.1   reinoud 	logblks_rec = udf_rw64(efe->logblks_rec);
   2622   1.1   reinoud 	l_ad   = udf_rw32(efe->l_ad);
   2623   1.1   reinoud 	l_ea   = udf_rw32(efe->l_ea);
   2624   1.1   reinoud 	crclen = udf_rw16(efe->tag.desc_crc_len);
   2625   1.1   reinoud 	icb    = &efe->icbtag;
   2626   1.1   reinoud 
   2627   1.1   reinoud 	/* set our allocation to shorts if not already done */
   2628   1.1   reinoud 	icb->flags = udf_rw16(UDF_ICB_SHORT_ALLOC);
   2629   1.1   reinoud 
   2630   1.1   reinoud 	/* append short_ad */
   2631   1.1   reinoud 	bpos = (uintptr_t)efe->data + l_ea + l_ad;
   2632   1.1   reinoud 	memcpy((void *)bpos, mapping, sizeof(struct short_ad));
   2633   1.1   reinoud 
   2634   1.1   reinoud 	l_ad   += sizeof(struct short_ad);
   2635   1.1   reinoud 	crclen += sizeof(struct short_ad);
   2636   1.1   reinoud 	inf_len  += UDF_EXT_LEN(udf_rw32(mapping->len));
   2637   1.1   reinoud 	obj_size += UDF_EXT_LEN(udf_rw32(mapping->len));
   2638   1.1   reinoud 	logblks_rec = UDF_ROUNDUP(inf_len, context.sector_size) /
   2639   1.1   reinoud 				context.sector_size;
   2640   1.1   reinoud 
   2641   1.1   reinoud 	efe->l_ad = udf_rw32(l_ad);
   2642   1.1   reinoud 	efe->inf_len     = udf_rw64(inf_len);
   2643   1.1   reinoud 	efe->obj_size    = udf_rw64(obj_size);
   2644   1.1   reinoud 	efe->logblks_rec = udf_rw64(logblks_rec);
   2645   1.1   reinoud 	efe->tag.desc_crc_len = udf_rw16(crclen);
   2646   1.1   reinoud }
   2647   1.1   reinoud 
   2648   1.1   reinoud 
   2649   1.1   reinoud /* for METADATA file appending only */
   2650   1.1   reinoud static void
   2651   1.1   reinoud udf_append_meta_mapping_to_efe(struct extfile_entry *efe,
   2652   1.1   reinoud 	uint16_t partnr, uint32_t lb_num,
   2653   1.1   reinoud 	uint64_t len)
   2654   1.1   reinoud {
   2655   1.1   reinoud 	struct short_ad mapping;
   2656   1.1   reinoud 	uint64_t max_len, part_len;
   2657   1.1   reinoud 
   2658   1.1   reinoud 	/* calculate max length meta allocation sizes */
   2659   1.1   reinoud 	max_len = UDF_EXT_MAXLEN / context.sector_size; /* in sectors */
   2660   1.1   reinoud 	max_len = (max_len / layout.meta_blockingnr) * layout.meta_blockingnr;
   2661   1.1   reinoud 	max_len = max_len * context.sector_size;
   2662   1.1   reinoud 
   2663   1.1   reinoud 	memset(&mapping, 0, sizeof(mapping));
   2664   1.1   reinoud 	while (len) {
   2665   1.1   reinoud 		part_len = MIN(len, max_len);
   2666   1.1   reinoud 		mapping.lb_num   = udf_rw32(lb_num);
   2667   1.1   reinoud 		mapping.len      = udf_rw32(part_len);
   2668   1.1   reinoud 
   2669   1.1   reinoud 		udf_append_meta_mapping_part_to_efe(efe, &mapping);
   2670   1.1   reinoud 
   2671   1.1   reinoud 		lb_num += part_len / context.sector_size;
   2672   1.1   reinoud 		len    -= part_len;
   2673   1.1   reinoud 	}
   2674   1.1   reinoud }
   2675   1.1   reinoud 
   2676   1.1   reinoud 
   2677   1.1   reinoud int
   2678   1.1   reinoud udf_create_meta_files(void)
   2679   1.1   reinoud {
   2680   1.1   reinoud 	struct extfile_entry *efe;
   2681   1.1   reinoud 	struct long_ad meta_icb;
   2682   1.1   reinoud 	uint64_t bytes;
   2683   1.1   reinoud 	uint32_t sector_size;
   2684   1.1   reinoud 	int filetype, error;
   2685   1.1   reinoud 
   2686   1.1   reinoud 	sector_size = context.sector_size;
   2687   1.1   reinoud 
   2688   1.1   reinoud 	memset(&meta_icb, 0, sizeof(meta_icb));
   2689   1.1   reinoud 	meta_icb.len          = udf_rw32(sector_size);
   2690   1.1   reinoud 	meta_icb.loc.part_num = udf_rw16(context.data_part);
   2691   1.1   reinoud 
   2692   1.1   reinoud 	/* create metadata file */
   2693   1.1   reinoud 	meta_icb.loc.lb_num   = udf_rw32(layout.meta_file);
   2694   1.1   reinoud 	filetype = UDF_ICB_FILETYPE_META_MAIN;
   2695   1.1   reinoud 	error = udf_create_new_efe(&efe, filetype, NULL);
   2696   1.1   reinoud 	if (error)
   2697   1.1   reinoud 		return error;
   2698   1.1   reinoud 	context.meta_file = efe;
   2699   1.1   reinoud 	context.meta_file->unique_id   = udf_rw64(0);
   2700   1.1   reinoud 
   2701   1.1   reinoud 	/* create metadata mirror file */
   2702   1.1   reinoud 	meta_icb.loc.lb_num   = udf_rw32(layout.meta_mirror);
   2703   1.1   reinoud 	filetype = UDF_ICB_FILETYPE_META_MIRROR;
   2704   1.1   reinoud 	error = udf_create_new_efe(&efe, filetype, NULL);
   2705   1.1   reinoud 	if (error)
   2706   1.1   reinoud 		return error;
   2707   1.1   reinoud 	context.meta_mirror = efe;
   2708   1.1   reinoud 	context.meta_mirror->unique_id = udf_rw64(0);
   2709   1.1   reinoud 
   2710   1.1   reinoud 	if (!(context.format_flags & FORMAT_READONLY)) {
   2711   1.1   reinoud 		/* create metadata bitmap file */
   2712   1.1   reinoud 		meta_icb.loc.lb_num   = udf_rw32(layout.meta_bitmap);
   2713   1.1   reinoud 		filetype = UDF_ICB_FILETYPE_META_BITMAP;
   2714   1.1   reinoud 		error = udf_create_new_efe(&efe, filetype, NULL);
   2715   1.1   reinoud 		if (error)
   2716   1.1   reinoud 			return error;
   2717   1.1   reinoud 		context.meta_bitmap = efe;
   2718   1.1   reinoud 		context.meta_bitmap->unique_id = udf_rw64(0);
   2719   1.1   reinoud 	}
   2720   1.1   reinoud 
   2721   1.1   reinoud 	/* restart unique id */
   2722   1.1   reinoud 	context.unique_id = 0x10;
   2723   1.1   reinoud 
   2724   1.1   reinoud 	/* XXX no support for metadata mirroring yet */
   2725   1.1   reinoud 	/* insert extents */
   2726   1.1   reinoud 	efe = context.meta_file;
   2727   1.1   reinoud 	udf_append_meta_mapping_to_efe(efe, context.data_part,
   2728   1.1   reinoud 		layout.meta_part_start_lba,
   2729   1.1   reinoud 		(uint64_t) layout.meta_part_size_lba * sector_size);
   2730   1.1   reinoud 
   2731   1.1   reinoud 	efe = context.meta_mirror;
   2732   1.1   reinoud 	udf_append_meta_mapping_to_efe(efe, context.data_part,
   2733   1.1   reinoud 		layout.meta_part_start_lba,
   2734   1.1   reinoud 		(uint64_t) layout.meta_part_size_lba * sector_size);
   2735   1.1   reinoud 
   2736   1.1   reinoud 	if (context.meta_bitmap) {
   2737   1.1   reinoud 		efe = context.meta_bitmap;
   2738   1.1   reinoud 		bytes = udf_space_bitmap_len(layout.meta_part_size_lba);
   2739   1.1   reinoud 		udf_append_meta_mapping_to_efe(efe, context.data_part,
   2740   1.1   reinoud 			layout.meta_bitmap_space, bytes);
   2741   1.1   reinoud 	}
   2742   1.1   reinoud 
   2743   1.1   reinoud 	return 0;
   2744   1.1   reinoud }
   2745   1.1   reinoud 
   2746   1.1   reinoud 
   2747   1.1   reinoud /* --------------------------------------------------------------------- */
   2748   1.1   reinoud 
   2749   1.1   reinoud int
   2750   1.1   reinoud udf_create_new_rootdir(union dscrptr **dscr)
   2751   1.1   reinoud {
   2752   1.1   reinoud 	struct file_entry *fe;
   2753   1.1   reinoud 	struct extfile_entry *efe;
   2754   1.1   reinoud 	struct long_ad root_icb;
   2755   1.1   reinoud 	int filetype, error;
   2756   1.1   reinoud 
   2757   1.1   reinoud 	memset(&root_icb, 0, sizeof(root_icb));
   2758   1.1   reinoud 	root_icb.len          = udf_rw32(context.sector_size);
   2759   1.1   reinoud 	root_icb.loc.lb_num   = udf_rw32(layout.rootdir);
   2760   1.1   reinoud 	root_icb.loc.part_num = udf_rw16(context.metadata_part);
   2761   1.1   reinoud 
   2762   1.1   reinoud 	filetype = UDF_ICB_FILETYPE_DIRECTORY;
   2763   1.1   reinoud 	if (context.dscrver == 2) {
   2764   1.1   reinoud 		error = udf_create_new_fe(&fe, filetype, NULL);
   2765   1.1   reinoud 		*dscr = (union dscrptr *) fe;
   2766   1.1   reinoud 	} else {
   2767   1.1   reinoud 		error = udf_create_new_efe(&efe, filetype, NULL);
   2768   1.1   reinoud 		*dscr = (union dscrptr *) efe;
   2769   1.1   reinoud 	}
   2770   1.1   reinoud 	if (error)
   2771   1.1   reinoud 		return error;
   2772   1.1   reinoud 
   2773   1.1   reinoud 	/* append '..' */
   2774   1.1   reinoud 	udf_append_parentfid(*dscr, &root_icb);
   2775   1.1   reinoud 
   2776   1.1   reinoud 	/* rootdir has explicit only one link on creation; '..' is no link */
   2777   1.1   reinoud 	if (context.dscrver == 2) {
   2778   1.1   reinoud 		fe->link_cnt  = udf_rw16(1);
   2779   1.1   reinoud 	} else {
   2780   1.1   reinoud 		efe->link_cnt = udf_rw16(1);
   2781   1.1   reinoud 	}
   2782   1.1   reinoud 
   2783   1.1   reinoud 	context.num_directories++;
   2784   1.1   reinoud 	assert(context.num_directories == 1);
   2785   1.1   reinoud 
   2786   1.1   reinoud 	return 0;
   2787   1.1   reinoud }
   2788   1.1   reinoud 
   2789   1.1   reinoud 
   2790   1.1   reinoud void
   2791   1.1   reinoud udf_prepend_VAT_file(void)
   2792   1.1   reinoud {
   2793   1.1   reinoud 	/* old style VAT has no prepend */
   2794   1.1   reinoud 	if (context.dscrver == 2) {
   2795   1.1   reinoud 		context.vat_start = 0;
   2796   1.1   reinoud 		context.vat_size  = 0;
   2797   1.1   reinoud 		return;
   2798   1.1   reinoud 	}
   2799   1.1   reinoud 
   2800   1.1   reinoud 	context.vat_start = offsetof(struct udf_vat, data);
   2801   1.1   reinoud 	context.vat_size  = offsetof(struct udf_vat, data);
   2802   1.1   reinoud }
   2803   1.1   reinoud 
   2804   1.1   reinoud 
   2805   1.1   reinoud void
   2806   1.1   reinoud udf_vat_update(uint32_t virt, uint32_t phys)
   2807   1.1   reinoud {
   2808   1.1   reinoud 	uint32_t *vatpos;
   2809   1.1   reinoud 	uint32_t new_size;
   2810   1.1   reinoud 
   2811   1.1   reinoud 	if (context.vtop_tp[context.metadata_part] != UDF_VTOP_TYPE_VIRT)
   2812   1.1   reinoud 		return;
   2813   1.2  riastrad 
   2814   1.1   reinoud 	new_size = MAX(context.vat_size,
   2815   1.1   reinoud 		(context.vat_start + (virt+1)*sizeof(uint32_t)));
   2816   1.1   reinoud 
   2817   1.1   reinoud 	if (new_size > context.vat_allocated) {
   2818   1.2  riastrad 		context.vat_allocated =
   2819   1.1   reinoud 			UDF_ROUNDUP(new_size, context.sector_size);
   2820   1.1   reinoud 		context.vat_contents = realloc(context.vat_contents,
   2821   1.1   reinoud 			context.vat_allocated);
   2822   1.1   reinoud 		assert(context.vat_contents);
   2823   1.1   reinoud 		/* XXX could also report error */
   2824   1.1   reinoud 	}
   2825   1.1   reinoud 	vatpos  = (uint32_t *) (context.vat_contents + context.vat_start);
   2826   1.1   reinoud 	vatpos[virt] = udf_rw32(phys);
   2827   1.1   reinoud 
   2828   1.1   reinoud 	context.vat_size = MAX(context.vat_size,
   2829   1.1   reinoud 		(context.vat_start + (virt+1)*sizeof(uint32_t)));
   2830   1.1   reinoud }
   2831   1.1   reinoud 
   2832   1.1   reinoud 
   2833   1.1   reinoud int
   2834   1.1   reinoud udf_append_VAT_file(void)
   2835   1.1   reinoud {
   2836   1.1   reinoud 	struct udf_oldvat_tail *oldvat_tail;
   2837   1.1   reinoud 	struct udf_vat *vathdr;
   2838   1.1   reinoud 	int32_t len_diff;
   2839   1.1   reinoud 
   2840   1.1   reinoud 	/* new style VAT has VAT LVInt analog in front */
   2841   1.1   reinoud 	if (context.dscrver == 3) {
   2842   1.1   reinoud 		/* set up VATv2 descriptor */
   2843   1.1   reinoud 		vathdr = (struct udf_vat *) context.vat_contents;
   2844   1.1   reinoud 		vathdr->header_len      = udf_rw16(sizeof(struct udf_vat) - 1);
   2845   1.1   reinoud 		vathdr->impl_use_len    = udf_rw16(0);
   2846   1.1   reinoud 		memcpy(vathdr->logvol_id, context.logical_vol->logvol_id, 128);
   2847   1.1   reinoud 		vathdr->prev_vat        = udf_rw32(UDF_NO_PREV_VAT);
   2848   1.1   reinoud 		vathdr->num_files       = udf_rw32(context.num_files);
   2849   1.1   reinoud 		vathdr->num_directories = udf_rw32(context.num_directories);
   2850   1.1   reinoud 
   2851   1.1   reinoud 		vathdr->min_udf_readver  = udf_rw16(context.min_udf);
   2852   1.1   reinoud 		vathdr->min_udf_writever = udf_rw16(context.min_udf);
   2853   1.1   reinoud 		vathdr->max_udf_writever = udf_rw16(context.max_udf);
   2854   1.1   reinoud 
   2855   1.1   reinoud 		return 0;
   2856   1.1   reinoud 	}
   2857   1.1   reinoud 
   2858   1.1   reinoud 	/* old style VAT has identifier appended */
   2859   1.1   reinoud 
   2860   1.1   reinoud 	/* append "*UDF Virtual Alloc Tbl" id and prev. VAT location */
   2861   1.1   reinoud 	len_diff = context.vat_allocated - context.vat_size;
   2862   1.1   reinoud 	assert(len_diff >= 0);
   2863   1.1   reinoud 	if (len_diff < (int32_t) sizeof(struct udf_oldvat_tail)) {
   2864   1.1   reinoud 		context.vat_allocated += context.sector_size;
   2865   1.1   reinoud 		context.vat_contents = realloc(context.vat_contents,
   2866   1.1   reinoud 			context.vat_allocated);
   2867   1.1   reinoud 		assert(context.vat_contents);
   2868   1.1   reinoud 		/* XXX could also report error */
   2869   1.1   reinoud 	}
   2870   1.1   reinoud 
   2871   1.1   reinoud 	oldvat_tail = (struct udf_oldvat_tail *) (context.vat_contents +
   2872   1.1   reinoud 			context.vat_size);
   2873   1.1   reinoud 
   2874   1.1   reinoud 	udf_set_regid(&oldvat_tail->id, "*UDF Virtual Alloc Tbl");
   2875   1.1   reinoud 	udf_add_udf_regid(&oldvat_tail->id);
   2876   1.1   reinoud 	oldvat_tail->prev_vat = udf_rw32(UDF_NO_PREV_VAT);
   2877   1.1   reinoud 
   2878   1.1   reinoud 	context.vat_size += sizeof(struct udf_oldvat_tail);
   2879   1.1   reinoud 
   2880   1.1   reinoud 	return 0;
   2881   1.1   reinoud }
   2882   1.1   reinoud 
   2883   1.1   reinoud 
   2884   1.1   reinoud int
   2885   1.1   reinoud udf_create_VAT(union dscrptr **vat_dscr, struct long_ad *vatdata_loc)
   2886   1.1   reinoud {
   2887   1.1   reinoud 	struct impl_extattr_entry *implext;
   2888   1.1   reinoud 	struct vatlvext_extattr_entry *vatlvext;
   2889   1.1   reinoud 	struct long_ad *allocpos;
   2890   1.1   reinoud 	uint8_t *bpos, *extattr;
   2891   1.1   reinoud 	uint32_t ea_len, inf_len, vat_len, blks;
   2892   1.1   reinoud 	int filetype;
   2893   1.1   reinoud 	int error;
   2894   1.1   reinoud 
   2895   1.1   reinoud 	assert((layout.rootdir < 2) && (layout.fsd < 2));
   2896   1.1   reinoud 
   2897   1.1   reinoud 	if (context.dscrver == 2) {
   2898   1.1   reinoud 		struct file_entry *fe;
   2899   1.1   reinoud 
   2900   1.1   reinoud 		/* old style VAT */
   2901   1.1   reinoud 		filetype = UDF_ICB_FILETYPE_UNKNOWN;
   2902   1.1   reinoud 		error = udf_create_new_fe(&fe, filetype, NULL);
   2903   1.1   reinoud 		if (error)
   2904   1.1   reinoud 			return error;
   2905   1.1   reinoud 
   2906   1.1   reinoud 		/* append VAT LVExtension attribute */
   2907   1.1   reinoud 		ea_len = sizeof(struct impl_extattr_entry) - 2 + 4 +
   2908   1.1   reinoud 			 sizeof(struct vatlvext_extattr_entry);
   2909   1.1   reinoud 
   2910   1.1   reinoud 		extattr = calloc(1, ea_len);
   2911   1.1   reinoud 
   2912   1.1   reinoud 		implext  = (struct impl_extattr_entry *) extattr;
   2913   1.1   reinoud 		implext->hdr.type = udf_rw32(2048);	/* [4/48.10.8] */
   2914   1.1   reinoud 		implext->hdr.subtype = 1;		/* [4/48.10.8.2] */
   2915   1.1   reinoud 		implext->hdr.a_l = udf_rw32(ea_len);	/* VAT LVext EA size */
   2916   1.1   reinoud 		/* use 4 bytes of imp use for UDF checksum [UDF 3.3.4.5] */
   2917   1.1   reinoud 		implext->iu_l = udf_rw32(4);
   2918   1.1   reinoud 		udf_set_regid(&implext->imp_id, "*UDF VAT LVExtension");
   2919   1.1   reinoud 		udf_add_udf_regid(&implext->imp_id);
   2920   1.1   reinoud 
   2921   1.1   reinoud 		/* VAT LVExtension data follows UDF IU space */
   2922   1.1   reinoud 		bpos = ((uint8_t *) implext->data) + 4;
   2923   1.1   reinoud 		vatlvext = (struct vatlvext_extattr_entry *) bpos;
   2924   1.1   reinoud 
   2925   1.6   reinoud 		vatlvext->unique_id_chk = fe->unique_id;
   2926   1.1   reinoud 		vatlvext->num_files = udf_rw32(context.num_files);
   2927   1.1   reinoud 		vatlvext->num_directories = udf_rw32(context.num_directories);
   2928   1.1   reinoud 		memcpy(vatlvext->logvol_id, context.logical_vol->logvol_id,128);
   2929   1.1   reinoud 
   2930   1.1   reinoud 		udf_extattr_insert_internal((union dscrptr *) fe,
   2931   1.1   reinoud 			(struct extattr_entry *) extattr);
   2932   1.1   reinoud 
   2933   1.1   reinoud 		free(extattr);
   2934   1.1   reinoud 
   2935   1.1   reinoud 		fe->icbtag.flags = udf_rw16(UDF_ICB_LONG_ALLOC);
   2936   1.1   reinoud 
   2937   1.1   reinoud 		allocpos = (struct long_ad *) (fe->data + udf_rw32(fe->l_ea));
   2938   1.1   reinoud 		*allocpos = *vatdata_loc;
   2939   1.1   reinoud 
   2940   1.1   reinoud 		/* set length */
   2941   1.1   reinoud 		inf_len       = context.vat_size;
   2942   1.1   reinoud 		fe->inf_len   = udf_rw64(inf_len);
   2943   1.1   reinoud 		allocpos->len = udf_rw32(inf_len);
   2944   1.1   reinoud 		fe->l_ad      = udf_rw32(sizeof(struct long_ad));
   2945   1.1   reinoud 		blks = UDF_ROUNDUP(inf_len, context.sector_size) /
   2946   1.1   reinoud 			context.sector_size;
   2947   1.8   reinoud 		fe->logblks_rec = udf_rw64(blks);
   2948   1.1   reinoud 
   2949   1.1   reinoud 		/* update vat descriptor's CRC length */
   2950   1.1   reinoud 		vat_len  = sizeof(struct file_entry) - 1 - UDF_DESC_TAG_LENGTH;
   2951   1.1   reinoud 		vat_len += udf_rw32(fe->l_ad) + udf_rw32(fe->l_ea);
   2952   1.1   reinoud 		fe->tag.desc_crc_len = udf_rw16(vat_len);
   2953   1.1   reinoud 
   2954   1.1   reinoud 		*vat_dscr = (union dscrptr *) fe;
   2955   1.1   reinoud 	} else {
   2956   1.1   reinoud 		/* the choice is between an EFE or an FE as VAT */
   2957   1.1   reinoud #if 1
   2958   1.1   reinoud 		struct extfile_entry *efe;
   2959   1.1   reinoud 
   2960   1.1   reinoud 		/* new style VAT on FE */
   2961   1.1   reinoud 		filetype = UDF_ICB_FILETYPE_VAT;
   2962   1.1   reinoud 		error = udf_create_new_efe(&efe, filetype, NULL);
   2963   1.1   reinoud 		if (error)
   2964   1.1   reinoud 			return error;
   2965   1.1   reinoud 
   2966   1.1   reinoud 		efe->icbtag.flags = udf_rw16(UDF_ICB_LONG_ALLOC);
   2967   1.1   reinoud 
   2968   1.1   reinoud 		allocpos = (struct long_ad *) efe->data;
   2969   1.1   reinoud 		*allocpos = *vatdata_loc;
   2970   1.1   reinoud 
   2971   1.1   reinoud 		/* set length */
   2972   1.1   reinoud 		inf_len = context.vat_size;
   2973   1.1   reinoud 		efe->inf_len     = udf_rw64(inf_len);
   2974   1.1   reinoud 		allocpos->len    = udf_rw32(inf_len);
   2975   1.1   reinoud 		efe->obj_size    = udf_rw64(inf_len);
   2976   1.1   reinoud 		efe->l_ad        = udf_rw32(sizeof(struct long_ad));
   2977   1.1   reinoud 		blks = UDF_ROUNDUP(inf_len, context.sector_size) /
   2978   1.1   reinoud 			context.sector_size;
   2979   1.8   reinoud 		efe->logblks_rec = udf_rw64(blks);
   2980   1.1   reinoud 
   2981   1.1   reinoud 		vat_len  = sizeof(struct extfile_entry)-1 - UDF_DESC_TAG_LENGTH;
   2982   1.1   reinoud 		vat_len += udf_rw32(efe->l_ad);
   2983   1.1   reinoud 		efe->tag.desc_crc_len = udf_rw16(vat_len);
   2984   1.1   reinoud 
   2985   1.1   reinoud 		*vat_dscr = (union dscrptr *) efe;
   2986   1.1   reinoud #else
   2987   1.1   reinoud 		struct file_entry *fe;
   2988   1.1   reinoud 		uint32_t l_ea;
   2989   1.1   reinoud 
   2990   1.1   reinoud 		/* new style VAT on EFE */
   2991   1.1   reinoud 		filetype = UDF_ICB_FILETYPE_VAT;
   2992   1.1   reinoud 		error = udf_create_new_fe(&fe, filetype, NULL);
   2993   1.1   reinoud 		if (error)
   2994   1.1   reinoud 			return error;
   2995   1.1   reinoud 
   2996   1.1   reinoud 		fe->icbtag.flags = udf_rw16(UDF_ICB_LONG_ALLOC);
   2997   1.1   reinoud 
   2998   1.1   reinoud 		l_ea = udf_rw32(fe->l_ea);
   2999   1.1   reinoud 		allocpos  = (struct long_ad *) (fe->data + l_ea);
   3000   1.1   reinoud 		*allocpos = *vatdata_loc;
   3001   1.1   reinoud 
   3002   1.1   reinoud 		/* set length */
   3003   1.1   reinoud 		inf_len         = context.vat_size;
   3004   1.1   reinoud 		fe->inf_len     = udf_rw64(inf_len);
   3005   1.1   reinoud 		allocpos->len   = udf_rw32(inf_len);
   3006   1.1   reinoud 		fe->l_ad        = udf_rw32(sizeof(struct long_ad));
   3007   1.1   reinoud 		blks = UDF_ROUNDUP(inf_len, context.sector_size) /
   3008   1.1   reinoud 			context.sector_size;
   3009   1.9   reinoud 		fe->logblks_rec = udf_rw64(blks);
   3010   1.1   reinoud 
   3011   1.1   reinoud 		vat_len  = sizeof(struct file_entry)-1 - UDF_DESC_TAG_LENGTH;
   3012   1.1   reinoud 		vat_len += udf_rw32(fe->l_ad) + udf_rw32(fe->l_ea);
   3013   1.1   reinoud 		fe->tag.desc_crc_len = udf_rw16(vat_len);
   3014   1.1   reinoud 
   3015   1.1   reinoud 		*vat_dscr = (union dscrptr *) fe;
   3016   1.1   reinoud #endif
   3017   1.1   reinoud 	}
   3018   1.2  riastrad 
   3019   1.1   reinoud 	return 0;
   3020   1.1   reinoud }
   3021   1.1   reinoud 
   3022   1.1   reinoud 
   3023   1.1   reinoud int
   3024   1.1   reinoud udf_writeout_VAT(void)
   3025   1.1   reinoud {
   3026   1.1   reinoud 	union dscrptr *vat_dscr;
   3027   1.1   reinoud 	struct long_ad vatdata;
   3028   1.1   reinoud 	uint32_t loc, phys, ext, sects;
   3029   1.1   reinoud 	int rel_block, rest_block, error;
   3030   1.1   reinoud 
   3031   1.1   reinoud 	vat_dscr = NULL;
   3032   1.1   reinoud 	/* update lvint to reflect the newest values (no writeout) */
   3033   1.1   reinoud 	udf_update_lvintd(UDF_INTEGRITY_CLOSED);
   3034   1.1   reinoud 
   3035   1.1   reinoud 	error = udf_append_VAT_file();
   3036   1.1   reinoud 	if (error)
   3037   1.1   reinoud 		return error;
   3038   1.1   reinoud 
   3039   1.1   reinoud 	/* write out VAT data */
   3040   1.1   reinoud 	sects = UDF_ROUNDUP(context.vat_size, context.sector_size) /
   3041   1.1   reinoud 		context.sector_size;
   3042   1.1   reinoud 	layout.vat = context.alloc_pos[context.data_part];
   3043   1.1   reinoud 	udf_data_alloc(sects, &vatdata);
   3044   1.1   reinoud //printf("layout.vat %d\n", layout.vat + udf_rw32(context.partitions[context.data_part]->start_loc));
   3045   1.1   reinoud 
   3046   1.1   reinoud 	loc = udf_rw32(vatdata.loc.lb_num);
   3047   1.1   reinoud 	udf_translate_vtop(loc, context.data_part, &phys, &ext);
   3048   1.1   reinoud 
   3049   1.1   reinoud 	error = udf_write_phys(context.vat_contents, phys, sects);
   3050   1.1   reinoud 	if (error)
   3051   1.1   reinoud 		return error;
   3052   1.1   reinoud 	loc += sects;
   3053   1.1   reinoud 
   3054   1.1   reinoud 	/* create new VAT descriptor */
   3055   1.1   reinoud 	error = udf_create_VAT(&vat_dscr, &vatdata);
   3056   1.1   reinoud 	if (error)
   3057   1.1   reinoud 		return error;
   3058   1.1   reinoud 
   3059   1.1   reinoud //printf("VAT data at %d\n", vatdata.loc.lb_num);
   3060   1.1   reinoud //printf("VAT itself at %d\n", loc + udf_rw32(context.partitions[context.data_part]->start_loc));
   3061   1.1   reinoud 
   3062   1.1   reinoud 	/* at least one */
   3063   1.1   reinoud 	error = udf_write_dscr_virt(vat_dscr, loc, context.data_part, 1);
   3064   1.1   reinoud 	loc++;
   3065   1.1   reinoud 
   3066   1.1   reinoud 	error = udf_translate_vtop(loc, context.data_part, &phys, &ext);
   3067   1.1   reinoud 	assert(!error);
   3068   1.1   reinoud 
   3069   1.1   reinoud 	rel_block  = phys - (UDF_ROUNDDOWN(phys, layout.blockingnr) + wrtrack_skew);
   3070   1.1   reinoud 	rest_block = layout.blockingnr - rel_block;
   3071   1.1   reinoud 
   3072   1.1   reinoud 	for (int i = 0; i < rest_block; i++) {
   3073   1.1   reinoud 		error = udf_write_dscr_virt(vat_dscr, loc, context.data_part, 1);
   3074   1.1   reinoud 		loc++;
   3075   1.1   reinoud 	}
   3076   1.1   reinoud 	free(vat_dscr);
   3077   1.1   reinoud 
   3078   1.1   reinoud 	return error;
   3079   1.1   reinoud }
   3080   1.1   reinoud 
   3081   1.1   reinoud 
   3082   1.1   reinoud /* --------------------------------------------------------------------- */
   3083   1.1   reinoud /*
   3084  1.13    andvar  * mmc_discinfo and mmc_trackinfo readers modified from original in udf main
   3085   1.1   reinoud  * code in sys/fs/udf/
   3086   1.1   reinoud  */
   3087   1.1   reinoud 
   3088   1.1   reinoud void
   3089   1.1   reinoud udf_dump_discinfo(struct mmc_discinfo *di)
   3090   1.1   reinoud {
   3091   1.1   reinoud #ifdef DEBUG
   3092   1.1   reinoud 	char bits[128];
   3093   1.1   reinoud 
   3094   1.1   reinoud 	printf("Device/media info  :\n");
   3095   1.1   reinoud 	printf("\tMMC profile        0x%02x\n", di->mmc_profile);
   3096   1.1   reinoud 	printf("\tderived class      %d\n", di->mmc_class);
   3097   1.1   reinoud 	printf("\tsector size        %d\n", di->sector_size);
   3098   1.1   reinoud 	printf("\tdisc state         %d\n", di->disc_state);
   3099   1.1   reinoud 	printf("\tlast ses state     %d\n", di->last_session_state);
   3100   1.1   reinoud 	printf("\tbg format state    %d\n", di->bg_format_state);
   3101   1.1   reinoud 	printf("\tfrst track         %d\n", di->first_track);
   3102   1.1   reinoud 	printf("\tfst on last ses    %d\n", di->first_track_last_session);
   3103   1.1   reinoud 	printf("\tlst on last ses    %d\n", di->last_track_last_session);
   3104   1.1   reinoud 	printf("\tlink block penalty %d\n", di->link_block_penalty);
   3105   1.1   reinoud 	snprintb(bits, sizeof(bits), MMC_DFLAGS_FLAGBITS, (uint64_t) di->disc_flags);
   3106   1.1   reinoud 	printf("\tdisc flags         %s\n", bits);
   3107   1.1   reinoud 	printf("\tdisc id            %x\n", di->disc_id);
   3108   1.1   reinoud 	printf("\tdisc barcode       %"PRIx64"\n", di->disc_barcode);
   3109   1.1   reinoud 
   3110   1.1   reinoud 	printf("\tnum sessions       %d\n", di->num_sessions);
   3111   1.1   reinoud 	printf("\tnum tracks         %d\n", di->num_tracks);
   3112   1.1   reinoud 
   3113   1.1   reinoud 	snprintb(bits, sizeof(bits), MMC_CAP_FLAGBITS, di->mmc_cur);
   3114   1.1   reinoud 	printf("\tcapabilities cur   %s\n", bits);
   3115   1.1   reinoud 	snprintb(bits, sizeof(bits), MMC_CAP_FLAGBITS, di->mmc_cap);
   3116   1.1   reinoud 	printf("\tcapabilities cap   %s\n", bits);
   3117   1.1   reinoud 	printf("\n");
   3118   1.1   reinoud 	printf("\tlast_possible_lba  %d\n", di->last_possible_lba);
   3119   1.1   reinoud 	printf("\n");
   3120   1.1   reinoud #endif
   3121   1.1   reinoud }
   3122   1.1   reinoud 
   3123   1.1   reinoud 
   3124   1.1   reinoud void
   3125   1.1   reinoud udf_synchronise_caches(void)
   3126   1.1   reinoud {
   3127   1.1   reinoud #if !HAVE_NBTOOL_CONFIG_H
   3128   1.1   reinoud 	struct mmc_op mmc_op;
   3129   1.1   reinoud 
   3130   1.1   reinoud 	bzero(&mmc_op, sizeof(struct mmc_op));
   3131   1.1   reinoud 	mmc_op.operation = MMC_OP_SYNCHRONISECACHE;
   3132   1.1   reinoud 
   3133   1.1   reinoud 	/* this device might not know this ioct, so just be ignorant */
   3134   1.1   reinoud 	(void) ioctl(dev_fd, MMCOP, &mmc_op);
   3135   1.1   reinoud #endif
   3136   1.1   reinoud }
   3137   1.1   reinoud 
   3138   1.1   reinoud 
   3139   1.1   reinoud /*
   3140   1.1   reinoud  * General Idea:
   3141   1.1   reinoud  *
   3142   1.1   reinoud  * stat the dev_fd
   3143   1.1   reinoud  *
   3144   1.1   reinoud  * If a S_ISREG(), we emulate using the emul_* settings.
   3145   1.1   reinoud  *
   3146   1.1   reinoud  * If its a device :
   3147   1.1   reinoud  * 	try the MMCGETDISCINFO ioctl() and be done.
   3148   1.1   reinoud  *
   3149   1.1   reinoud  * If that fails, its a regular disc and set the type to disc media.
   3150   1.1   reinoud  *
   3151   1.1   reinoud  */
   3152   1.1   reinoud 
   3153   1.1   reinoud 
   3154   1.1   reinoud int
   3155   1.1   reinoud udf_update_discinfo(void)
   3156   1.1   reinoud {
   3157   1.1   reinoud 	off_t size, last_sector, secsize;
   3158   1.1   reinoud 	int error;
   3159   1.1   reinoud 
   3160   1.1   reinoud 	memset(&mmc_discinfo, 0, sizeof(struct mmc_discinfo));
   3161   1.1   reinoud 
   3162   1.1   reinoud #if !HAVE_NBTOOL_CONFIG_H
   3163   1.1   reinoud 	/* check if we're on a MMC capable device, i.e. CD/DVD */
   3164   1.1   reinoud 	error = ioctl(dev_fd, MMCGETDISCINFO, &mmc_discinfo);
   3165   1.1   reinoud 	if (error == 0) {
   3166   1.1   reinoud 		if ((emul_mmc_profile != -1) &&
   3167   1.1   reinoud 		   (emul_mmc_profile != mmc_discinfo.mmc_profile)) {
   3168   1.1   reinoud 			errno = EINVAL;
   3169   1.1   reinoud 			perror("media and specified disc type mismatch");
   3170   1.1   reinoud 			return errno;
   3171   1.1   reinoud 		}
   3172   1.1   reinoud 		emul_size = 0;
   3173   1.1   reinoud 		return 0;
   3174   1.1   reinoud 	}
   3175   1.1   reinoud #endif
   3176   1.1   reinoud 
   3177   1.1   reinoud 	if (S_ISREG(dev_fd_stat.st_mode)) {
   3178   1.1   reinoud 		/* file support; we pick the minimum sector size allowed */
   3179   1.1   reinoud 		if (emul_mmc_profile < 0)
   3180   1.1   reinoud 			emul_mmc_profile = 0x01;
   3181   1.1   reinoud 		if (emul_size == 0)
   3182   1.1   reinoud 			emul_size = dev_fd_stat.st_size;
   3183   1.1   reinoud 		size = emul_size;
   3184   1.1   reinoud 		secsize = emul_sectorsize;
   3185   1.1   reinoud 		last_sector = (size / secsize) - 1;
   3186   1.1   reinoud 		if (ftruncate(dev_fd, size)) {
   3187   1.1   reinoud 			perror("can't resize file");
   3188   1.1   reinoud 			return EXIT_FAILURE;
   3189   1.1   reinoud 		}
   3190   1.1   reinoud 	} else {
   3191   1.1   reinoud #if !HAVE_NBTOOL_CONFIG_H
   3192   1.1   reinoud 		struct disk_geom	geo;
   3193   1.1   reinoud 		struct dkwedge_info	dkw;
   3194   1.1   reinoud 
   3195   1.1   reinoud 		/* sanity */
   3196   1.1   reinoud 		if (emul_mmc_profile <= 0)
   3197   1.1   reinoud 			emul_mmc_profile = 0x01;
   3198   1.1   reinoud 		if (emul_mmc_profile != 0x01) {
   3199   1.1   reinoud 			warnx("format incompatible with disc partition");
   3200   1.2  riastrad 			return EXIT_FAILURE;
   3201   1.1   reinoud 		}
   3202   1.1   reinoud 
   3203   1.1   reinoud 		/* get our disc info */
   3204   1.1   reinoud 		error = getdiskinfo(dev_name, dev_fd, NULL, &geo, &dkw);
   3205   1.1   reinoud 		if (error) {
   3206   1.1   reinoud 			warn("retrieving disc info failed");
   3207   1.1   reinoud 			return EXIT_FAILURE;
   3208   1.1   reinoud 		}
   3209   1.1   reinoud 		secsize = emul_sectorsize;
   3210   1.1   reinoud 		last_sector = (dkw.dkw_size - 1) * geo.dg_secsize / secsize;
   3211   1.1   reinoud #else
   3212   1.1   reinoud 		warnx("disk partitions only usable outside tools");
   3213   1.1   reinoud 		return EIO;
   3214   1.1   reinoud #endif
   3215   1.1   reinoud 	}
   3216   1.1   reinoud 
   3217   1.1   reinoud 	/* commons */
   3218   1.1   reinoud 	mmc_discinfo.mmc_profile	= emul_mmc_profile;
   3219   1.1   reinoud 	mmc_discinfo.disc_state		= MMC_STATE_CLOSED;
   3220   1.1   reinoud 	mmc_discinfo.last_session_state	= MMC_STATE_CLOSED;
   3221   1.1   reinoud 	mmc_discinfo.bg_format_state	= MMC_BGFSTATE_COMPLETED;
   3222   1.1   reinoud 	mmc_discinfo.link_block_penalty	= 0;
   3223   1.1   reinoud 
   3224   1.1   reinoud 	mmc_discinfo.disc_flags = MMC_DFLAGS_UNRESTRICTED;
   3225   1.1   reinoud 
   3226   1.1   reinoud 	mmc_discinfo.last_possible_lba = last_sector;
   3227   1.1   reinoud 	mmc_discinfo.sector_size       = secsize;
   3228   1.1   reinoud 
   3229   1.1   reinoud 	mmc_discinfo.num_sessions = 1;
   3230   1.1   reinoud 	mmc_discinfo.num_tracks   = 1;
   3231   1.1   reinoud 
   3232   1.1   reinoud 	mmc_discinfo.first_track  = 1;
   3233   1.1   reinoud 	mmc_discinfo.first_track_last_session = mmc_discinfo.last_track_last_session = 1;
   3234   1.1   reinoud 
   3235   1.1   reinoud 	mmc_discinfo.mmc_cur = MMC_CAP_RECORDABLE | MMC_CAP_ZEROLINKBLK;
   3236   1.1   reinoud 	switch (emul_mmc_profile) {
   3237   1.1   reinoud 	case 0x00:	/* unknown, treat as CDROM */
   3238   1.1   reinoud 	case 0x08:	/* CDROM */
   3239   1.1   reinoud 	case 0x10:	/* DVDROM */
   3240   1.1   reinoud 	case 0x40:	/* BDROM */
   3241   1.1   reinoud 		/* FALLTHROUGH */
   3242   1.1   reinoud 	case 0x01:	/* disc */
   3243   1.1   reinoud 		/* set up a disc info profile for partitions/files */
   3244   1.1   reinoud 		mmc_discinfo.mmc_class	= MMC_CLASS_DISC;
   3245   1.1   reinoud 		mmc_discinfo.mmc_cur    |= MMC_CAP_REWRITABLE | MMC_CAP_HW_DEFECTFREE;
   3246   1.1   reinoud 		break;
   3247   1.1   reinoud 	case 0x09:	/* CD-R */
   3248   1.1   reinoud 		mmc_discinfo.mmc_class	= MMC_CLASS_CD;
   3249   1.1   reinoud 		mmc_discinfo.mmc_cur    |= MMC_CAP_SEQUENTIAL;
   3250   1.1   reinoud 		mmc_discinfo.disc_state  = MMC_STATE_EMPTY;
   3251   1.1   reinoud 		break;
   3252   1.1   reinoud 	case 0x0a:	/* CD-RW + CD-MRW (regretably) */
   3253   1.1   reinoud 		mmc_discinfo.mmc_class	= MMC_CLASS_CD;
   3254   1.1   reinoud 		mmc_discinfo.mmc_cur    |= MMC_CAP_REWRITABLE;
   3255   1.1   reinoud 		break;
   3256   1.1   reinoud 	case 0x13:	/* DVD-RW */
   3257   1.1   reinoud 	case 0x1a:	/* DVD+RW */
   3258   1.1   reinoud 		mmc_discinfo.mmc_class	= MMC_CLASS_DVD;
   3259   1.1   reinoud 		mmc_discinfo.mmc_cur    |= MMC_CAP_REWRITABLE;
   3260   1.1   reinoud 		break;
   3261   1.1   reinoud 	case 0x11:	/* DVD-R */
   3262   1.1   reinoud 	case 0x14:	/* DVD-RW sequential */
   3263   1.1   reinoud 	case 0x1b:	/* DVD+R */
   3264   1.1   reinoud 	case 0x2b:	/* DVD+R DL */
   3265   1.1   reinoud 	case 0x51:	/* HD DVD-R */
   3266   1.1   reinoud 		mmc_discinfo.mmc_class	= MMC_CLASS_DVD;
   3267   1.1   reinoud 		mmc_discinfo.mmc_cur    |= MMC_CAP_SEQUENTIAL;
   3268   1.1   reinoud 		mmc_discinfo.disc_state  = MMC_STATE_EMPTY;
   3269   1.1   reinoud 		break;
   3270   1.1   reinoud 	case 0x41:	/* BD-R */
   3271   1.1   reinoud 		mmc_discinfo.mmc_class   = MMC_CLASS_BD;
   3272   1.1   reinoud 		mmc_discinfo.mmc_cur    |= MMC_CAP_SEQUENTIAL | MMC_CAP_HW_DEFECTFREE;
   3273   1.1   reinoud 		mmc_discinfo.disc_state  = MMC_STATE_EMPTY;
   3274   1.1   reinoud 		break;
   3275   1.1   reinoud 	case 0x43:	/* BD-RE */
   3276   1.1   reinoud 		mmc_discinfo.mmc_class   = MMC_CLASS_BD;
   3277   1.1   reinoud 		mmc_discinfo.mmc_cur    |= MMC_CAP_REWRITABLE | MMC_CAP_HW_DEFECTFREE;
   3278   1.1   reinoud 		break;
   3279   1.1   reinoud 	default:
   3280   1.1   reinoud 		errno = EINVAL;
   3281   1.1   reinoud 		perror("unknown or unimplemented device type");
   3282   1.1   reinoud 		return errno;
   3283   1.1   reinoud 	}
   3284   1.1   reinoud 	mmc_discinfo.mmc_cap    = mmc_discinfo.mmc_cur;
   3285   1.1   reinoud 
   3286   1.1   reinoud 	return 0;
   3287   1.1   reinoud }
   3288   1.1   reinoud 
   3289   1.1   reinoud 
   3290   1.1   reinoud int
   3291   1.1   reinoud udf_update_trackinfo(struct mmc_trackinfo *ti)
   3292   1.1   reinoud {
   3293   1.1   reinoud 	int error, class;
   3294   1.1   reinoud 
   3295   1.1   reinoud #if !HAVE_NBTOOL_CONFIG_H
   3296   1.1   reinoud 	class = mmc_discinfo.mmc_class;
   3297   1.1   reinoud 	if (class != MMC_CLASS_DISC) {
   3298   1.1   reinoud 		/* tracknr specified in struct ti */
   3299   1.1   reinoud 		error = ioctl(dev_fd, MMCGETTRACKINFO, ti);
   3300   1.1   reinoud 		if (!error)
   3301   1.1   reinoud 			return 0;
   3302   1.1   reinoud 	}
   3303   1.1   reinoud #endif
   3304   1.1   reinoud 
   3305   1.1   reinoud 	/* discs partition support */
   3306   1.1   reinoud 	if (ti->tracknr != 1)
   3307   1.1   reinoud 		return EIO;
   3308   1.1   reinoud 
   3309   1.1   reinoud 	/* create fake ti (TODO check for resized vnds) */
   3310   1.1   reinoud 	ti->sessionnr  = 1;
   3311   1.1   reinoud 
   3312   1.1   reinoud 	ti->track_mode = 0;	/* XXX */
   3313   1.1   reinoud 	ti->data_mode  = 0;	/* XXX */
   3314   1.1   reinoud 	ti->flags = MMC_TRACKINFO_LRA_VALID | MMC_TRACKINFO_NWA_VALID;
   3315   1.1   reinoud 
   3316   1.1   reinoud 	ti->track_start    = 0;
   3317   1.1   reinoud 	ti->packet_size    = emul_packetsize;
   3318   1.1   reinoud 
   3319   1.1   reinoud 	/* TODO support for resizable vnd */
   3320   1.1   reinoud 	ti->track_size    = mmc_discinfo.last_possible_lba;
   3321   1.1   reinoud 	ti->next_writable = mmc_discinfo.last_possible_lba + 1; //0;
   3322   1.1   reinoud 	ti->last_recorded = ti->next_writable;
   3323   1.1   reinoud 	ti->free_blocks   = 0;
   3324   1.1   reinoud 
   3325   1.1   reinoud 	return 0;
   3326   1.1   reinoud }
   3327   1.1   reinoud 
   3328   1.1   reinoud 
   3329   1.1   reinoud int
   3330   1.1   reinoud udf_opendisc(const char *device, int open_flags)
   3331   1.1   reinoud {
   3332   1.1   reinoud 	/* set global variable to the passed name */
   3333   1.1   reinoud 	dev_name = strdup(device);
   3334   1.1   reinoud 
   3335   1.1   reinoud 	/* open device */
   3336   1.1   reinoud 	if (open_flags & O_RDONLY) {
   3337   1.1   reinoud 		dev_fd_rdonly = 1;
   3338   1.1   reinoud 		if ((dev_fd = open(dev_name, O_RDONLY, 0)) == -1) {
   3339   1.1   reinoud 			warn("device/image not found");
   3340   1.1   reinoud 			return EXIT_FAILURE;
   3341   1.1   reinoud 		}
   3342   1.1   reinoud 	} else {
   3343   1.1   reinoud 		dev_fd_rdonly = 0;
   3344   1.1   reinoud 		if ((dev_fd = open(dev_name, O_RDWR, 0)) == -1) {
   3345   1.1   reinoud 			/* check if we need to create a file */
   3346   1.1   reinoud 			dev_fd = open(dev_name, O_RDONLY, 0);
   3347   1.1   reinoud 			if (dev_fd > 0) {
   3348   1.1   reinoud 				warn("device is there but can't be opened for "
   3349   1.1   reinoud 					"read/write");
   3350   1.1   reinoud 				return EXIT_FAILURE;
   3351   1.1   reinoud 			}
   3352   1.1   reinoud 			if ((open_flags & O_CREAT) == 0) {
   3353   1.1   reinoud 				warnx("device/image not found");
   3354   1.1   reinoud 				return EXIT_FAILURE;
   3355   1.1   reinoud 			}
   3356   1.1   reinoud 			/* need to create a file */
   3357   1.1   reinoud 			dev_fd = open(dev_name, O_RDWR | O_CREAT | O_TRUNC, 0666);
   3358   1.1   reinoud 			if (dev_fd == -1) {
   3359   1.1   reinoud 				warn("can't create image file");
   3360   1.1   reinoud 				return EXIT_FAILURE;
   3361   1.1   reinoud 			}
   3362   1.1   reinoud 		}
   3363   1.1   reinoud 	}
   3364   1.1   reinoud 
   3365   1.1   reinoud 	/* stat the device/image */
   3366   1.1   reinoud 	if (fstat(dev_fd, &dev_fd_stat) != 0) {
   3367   1.1   reinoud 		warn("can't stat the disc image");
   3368   1.1   reinoud 		return EXIT_FAILURE;
   3369   1.1   reinoud 	}
   3370   1.1   reinoud 
   3371   1.1   reinoud 	/* sanity check and resizing of file */
   3372   1.1   reinoud 	if (S_ISREG(dev_fd_stat.st_mode)) {
   3373   1.1   reinoud 		if (emul_size == 0)
   3374   1.1   reinoud 			emul_size = dev_fd_stat.st_size;
   3375   1.1   reinoud 		/* sanitise arguments */
   3376   1.1   reinoud 		emul_sectorsize &= ~511;
   3377   1.1   reinoud 		if (emul_size & (emul_sectorsize-1)) {
   3378   1.1   reinoud 			warnx("size of file is not a multiple of sector size, "
   3379   1.1   reinoud 				"shrinking");
   3380   1.1   reinoud 			emul_size -= emul_size & (emul_sectorsize-1);
   3381   1.1   reinoud 		}
   3382   1.1   reinoud 
   3383   1.1   reinoud 		/* grow the image */
   3384   1.1   reinoud 		if (ftruncate(dev_fd, emul_size)) {
   3385   1.1   reinoud 			warn("can't resize file");
   3386   1.1   reinoud 			return EXIT_FAILURE;
   3387   1.1   reinoud 		}
   3388   1.1   reinoud 		/* restat the device/image */
   3389   1.1   reinoud 		if (fstat(dev_fd, &dev_fd_stat) != 0) {
   3390   1.1   reinoud 			warn("can't re-stat the disc image");
   3391   1.1   reinoud 			return EXIT_FAILURE;
   3392   1.1   reinoud 		}
   3393   1.1   reinoud 	} else {
   3394   1.1   reinoud 		if (!S_ISCHR(dev_fd_stat.st_mode)) {
   3395   1.1   reinoud 			warnx("%s is not a raw device", dev_name);
   3396   1.1   reinoud 			return EXIT_FAILURE;
   3397   1.1   reinoud 		}
   3398   1.1   reinoud 	}
   3399   1.1   reinoud 
   3400   1.1   reinoud 	/* just in case something went wrong, synchronise the drive's cache */
   3401   1.1   reinoud 	udf_synchronise_caches();
   3402   1.1   reinoud 	if (udf_update_discinfo()) {
   3403   1.1   reinoud 		warnx("update discinfo failed");
   3404   1.1   reinoud 		return EXIT_FAILURE;
   3405   1.1   reinoud 	}
   3406   1.1   reinoud 
   3407   1.1   reinoud 	/* honour minimum sector size of the device */
   3408   1.1   reinoud 	if (mmc_discinfo.sector_size > context.sector_size)
   3409   1.1   reinoud 		context.sector_size = mmc_discinfo.sector_size;
   3410   1.1   reinoud 
   3411   1.1   reinoud 	if (mmc_discinfo.mmc_cur & MMC_CAP_SEQUENTIAL)
   3412   1.1   reinoud 		udf_init_writequeue(UDF_WRITE_SEQUENTIAL);
   3413   1.1   reinoud 	else {
   3414   1.1   reinoud 		udf_init_writequeue(UDF_WRITE_PACKET);
   3415   1.1   reinoud 	}
   3416   1.1   reinoud 	return 0;
   3417   1.1   reinoud }
   3418   1.1   reinoud 
   3419   1.1   reinoud 
   3420   1.1   reinoud void
   3421   1.1   reinoud udf_closedisc(void)
   3422   1.1   reinoud {
   3423   1.1   reinoud 	if (!write_queue_suspend) {
   3424   1.1   reinoud 		udf_writeout_writequeue(true);
   3425   1.1   reinoud 		assert(write_queuelen == 0);
   3426   1.1   reinoud 	}
   3427   1.1   reinoud 
   3428   1.1   reinoud 	udf_synchronise_caches();
   3429   1.1   reinoud 	if (dev_fd)
   3430   1.1   reinoud 		close(dev_fd);
   3431   1.1   reinoud }
   3432   1.1   reinoud 
   3433   1.1   reinoud /* --------------------------------------------------------------------- */
   3434   1.1   reinoud 
   3435   1.1   reinoud static int
   3436   1.1   reinoud udf_setup_writeparams(void)
   3437   1.1   reinoud {
   3438   1.1   reinoud #if !HAVE_NBTOOL_CONFIG_H
   3439   1.1   reinoud 	struct mmc_writeparams mmc_writeparams;
   3440   1.1   reinoud 	int error;
   3441   1.1   reinoud 
   3442   1.1   reinoud 	if (mmc_discinfo.mmc_class == MMC_CLASS_DISC)
   3443   1.1   reinoud 		return 0;
   3444   1.1   reinoud 
   3445   1.1   reinoud 	if (S_ISREG(dev_fd_stat.st_mode))
   3446   1.1   reinoud 		return 0;
   3447   1.1   reinoud 
   3448   1.1   reinoud 	/*
   3449   1.1   reinoud 	 * only CD burning normally needs setting up, but other disc types
   3450   1.1   reinoud 	 * might need other settings to be made. The MMC framework will set up
   3451   1.1   reinoud 	 * the necessary recording parameters according to the disc
   3452   1.1   reinoud 	 * characteristics read in. Modifications can be made in the discinfo
   3453   1.1   reinoud 	 * structure passed to change the nature of the disc.
   3454   1.1   reinoud 	 */
   3455   1.1   reinoud 	memset(&mmc_writeparams, 0, sizeof(struct mmc_writeparams));
   3456   1.1   reinoud 	mmc_writeparams.mmc_class  = mmc_discinfo.mmc_class;
   3457   1.1   reinoud 	mmc_writeparams.mmc_cur    = mmc_discinfo.mmc_cur;
   3458   1.1   reinoud 
   3459   1.1   reinoud 	/*
   3460   1.1   reinoud 	 * UDF dictates first track to determine track mode for the whole
   3461   1.1   reinoud 	 * disc. [UDF 1.50/6.10.1.1, UDF 1.50/6.10.2.1]
   3462   1.1   reinoud 	 * To prevent problems with a `reserved' track in front we start with
   3463   1.1   reinoud 	 * the 2nd track and if that is not valid, go for the 1st.
   3464   1.1   reinoud 	 */
   3465   1.1   reinoud 	mmc_writeparams.tracknr = 2;
   3466   1.1   reinoud 	mmc_writeparams.data_mode  = MMC_DATAMODE_DEFAULT;	/* XA disc */
   3467   1.1   reinoud 	mmc_writeparams.track_mode = MMC_TRACKMODE_DEFAULT;	/* data */
   3468   1.1   reinoud 
   3469   1.1   reinoud 	error = ioctl(dev_fd, MMCSETUPWRITEPARAMS, &mmc_writeparams);
   3470   1.1   reinoud 	if (error) {
   3471   1.1   reinoud 		mmc_writeparams.tracknr = 1;
   3472   1.1   reinoud 		error = ioctl(dev_fd, MMCSETUPWRITEPARAMS, &mmc_writeparams);
   3473   1.1   reinoud 	}
   3474   1.1   reinoud 	return error;
   3475   1.1   reinoud #else
   3476   1.1   reinoud 	return 0;
   3477   1.1   reinoud #endif
   3478   1.1   reinoud }
   3479   1.1   reinoud 
   3480   1.1   reinoud 
   3481   1.1   reinoud /*
   3482   1.1   reinoud  * On sequential recordable media, we might need to close the last session to
   3483   1.1   reinoud  * be able to write new anchors/new fs.
   3484   1.1   reinoud  */
   3485   1.1   reinoud static int
   3486   1.1   reinoud udf_open_new_session(void)
   3487   1.1   reinoud {
   3488   1.1   reinoud #if !HAVE_NBTOOL_CONFIG_H
   3489   1.1   reinoud 	struct mmc_trackinfo ti;
   3490   1.1   reinoud 	struct mmc_op        op;
   3491   1.1   reinoud 	int tracknr, error;
   3492   1.1   reinoud 
   3493   1.1   reinoud 	/* if the drive is not sequential, we're done */
   3494   1.1   reinoud 	if ((mmc_discinfo.mmc_cur & MMC_CAP_SEQUENTIAL) == 0)
   3495   1.1   reinoud 		return 0;
   3496   1.1   reinoud 
   3497   1.1   reinoud 	/* close the last session if its still open */
   3498   1.1   reinoud 	if (mmc_discinfo.last_session_state == MMC_STATE_INCOMPLETE) {
   3499   1.1   reinoud 		/*
   3500   1.1   reinoud 		 * Leave the disc alone if force format is not set, it will
   3501   1.1   reinoud 		 * error out later
   3502   1.1   reinoud 		 */
   3503   1.1   reinoud 		if (!context.create_new_session)
   3504   1.1   reinoud 			return 0;
   3505   1.1   reinoud 
   3506   1.1   reinoud //		printf("Closing last open session if present\n");
   3507   1.1   reinoud 		/* close all associated tracks */
   3508   1.1   reinoud 		tracknr = mmc_discinfo.first_track_last_session;
   3509   1.1   reinoud 		while (tracknr <= mmc_discinfo.last_track_last_session) {
   3510   1.1   reinoud 			ti.tracknr = tracknr;
   3511   1.1   reinoud 			error = udf_update_trackinfo(&ti);
   3512   1.1   reinoud 			if (error)
   3513   1.1   reinoud 				return error;
   3514   1.1   reinoud //			printf("\tClosing open track %d\n", tracknr);
   3515   1.1   reinoud 			memset(&op, 0, sizeof(op));
   3516   1.1   reinoud 			op.operation   = MMC_OP_CLOSETRACK;
   3517   1.1   reinoud 			op.mmc_profile = mmc_discinfo.mmc_profile;
   3518   1.1   reinoud 			op.tracknr     = tracknr;
   3519   1.1   reinoud 			error = ioctl(dev_fd, MMCOP, &op);
   3520   1.1   reinoud 			if (error)
   3521   1.1   reinoud 				return error;
   3522   1.1   reinoud 			tracknr ++;
   3523   1.1   reinoud 		}
   3524   1.1   reinoud //		printf("Closing session\n");
   3525   1.1   reinoud 		memset(&op, 0, sizeof(op));
   3526   1.1   reinoud 		op.operation   = MMC_OP_CLOSESESSION;
   3527   1.1   reinoud 		op.mmc_profile = mmc_discinfo.mmc_profile;
   3528   1.1   reinoud 		op.sessionnr   = mmc_discinfo.num_sessions;
   3529   1.1   reinoud 		error = ioctl(dev_fd, MMCOP, &op);
   3530   1.1   reinoud 		if (error)
   3531   1.1   reinoud 			return error;
   3532   1.1   reinoud 
   3533   1.1   reinoud 		/* update discinfo since it changed by the operations */
   3534   1.1   reinoud 		error = udf_update_discinfo();
   3535   1.1   reinoud 		if (error)
   3536   1.1   reinoud 			return error;
   3537   1.1   reinoud 	}
   3538   1.1   reinoud #endif
   3539   1.1   reinoud 	return 0;
   3540   1.1   reinoud }
   3541   1.1   reinoud 
   3542   1.1   reinoud 
   3543   1.1   reinoud /* bit paranoid but tracks may need repair before they can be written to */
   3544   1.1   reinoud static void
   3545   1.1   reinoud udf_repair_tracks(void)
   3546   1.1   reinoud {
   3547   1.1   reinoud #if !HAVE_NBTOOL_CONFIG_H
   3548   1.1   reinoud 	struct mmc_trackinfo ti;
   3549   1.1   reinoud 	struct mmc_op        op;
   3550   1.1   reinoud 	int tracknr, error;
   3551   1.1   reinoud 
   3552   1.1   reinoud 	tracknr = mmc_discinfo.first_track_last_session;
   3553   1.1   reinoud 	while (tracknr <= mmc_discinfo.last_track_last_session) {
   3554   1.1   reinoud 		ti.tracknr = tracknr;
   3555   1.1   reinoud 		error = udf_update_trackinfo(&ti);
   3556   1.1   reinoud 		if (error) {
   3557   1.1   reinoud 			warnx("error updating track information for track %d",
   3558   1.1   reinoud 				tracknr);
   3559   1.1   reinoud 			/* resume */
   3560   1.1   reinoud 			tracknr++;
   3561   1.1   reinoud 			continue;
   3562   1.1   reinoud 		}
   3563   1.1   reinoud 
   3564   1.1   reinoud 		if (ti.flags & MMC_TRACKINFO_DAMAGED) {
   3565   1.1   reinoud 			/*
   3566   1.1   reinoud 			 * Need to repair last track before anything can be done.
   3567   1.1   reinoud 			 * this is an optional command, so ignore its error but report
   3568   1.1   reinoud 			 * warning.
   3569   1.1   reinoud 			 */
   3570   1.1   reinoud 			memset(&op, 0, sizeof(op));
   3571   1.1   reinoud 			op.operation   = MMC_OP_REPAIRTRACK;
   3572   1.1   reinoud 			op.mmc_profile = mmc_discinfo.mmc_profile;
   3573   1.1   reinoud 			op.tracknr     = ti.tracknr;
   3574   1.1   reinoud 			error = ioctl(dev_fd, MMCOP, &op);
   3575   1.1   reinoud 
   3576   1.1   reinoud 			if (error)
   3577   1.1   reinoud 				warnx("drive notifies it can't explicitly repair "
   3578   1.1   reinoud 					"damaged track, but it might autorepair\n");
   3579   1.1   reinoud 		}
   3580   1.1   reinoud 		tracknr++;
   3581   1.1   reinoud 	}
   3582   1.1   reinoud 	/* tracks (if any) might not be damaged now, operations are ok now */
   3583   1.1   reinoud #endif
   3584   1.1   reinoud }
   3585   1.1   reinoud 
   3586   1.1   reinoud 
   3587   1.1   reinoud int
   3588   1.1   reinoud udf_prepare_disc(void)
   3589   1.1   reinoud {
   3590   1.1   reinoud #if !HAVE_NBTOOL_CONFIG_H
   3591   1.1   reinoud 	int error;
   3592   1.1   reinoud 
   3593   1.1   reinoud 	/* setup write parameters from discinfo */
   3594   1.1   reinoud 	error = udf_setup_writeparams();
   3595   1.1   reinoud 	if (error)
   3596   1.1   reinoud 		return error;
   3597   1.1   reinoud 
   3598   1.1   reinoud 	udf_repair_tracks();
   3599   1.1   reinoud 
   3600   1.1   reinoud 	/* open new session if needed */
   3601   1.1   reinoud 	return udf_open_new_session();
   3602   1.1   reinoud #endif
   3603   1.1   reinoud 	return 0;
   3604   1.1   reinoud }
   3605   1.1   reinoud 
   3606   1.1   reinoud 
   3607   1.1   reinoud /* --------------------------------------------------------------------- */
   3608   1.1   reinoud 
   3609   1.1   reinoud /*
   3610   1.1   reinoud  * write queue implementation
   3611   1.1   reinoud  */
   3612   1.1   reinoud 
   3613   1.1   reinoud void
   3614   1.1   reinoud udf_suspend_writing(void)
   3615   1.1   reinoud {
   3616   1.1   reinoud 	write_queue_suspend = 1;
   3617   1.1   reinoud }
   3618   1.1   reinoud 
   3619   1.1   reinoud 
   3620   1.1   reinoud void
   3621   1.1   reinoud udf_allow_writing(void)
   3622   1.1   reinoud {
   3623   1.1   reinoud 	write_queue_suspend = 0;
   3624   1.1   reinoud }
   3625   1.1   reinoud 
   3626   1.1   reinoud 
   3627   1.1   reinoud static void
   3628   1.1   reinoud udf_init_writequeue(int write_strategy)
   3629   1.1   reinoud {
   3630   1.1   reinoud 	context.write_strategy = write_strategy;
   3631   1.1   reinoud 	write_queue_suspend = 0;
   3632   1.1   reinoud 
   3633   1.1   reinoud 	/* setup sector writeout queue's */
   3634   1.1   reinoud 	TAILQ_INIT(&write_queue);
   3635   1.1   reinoud 	write_queuelen = 0;
   3636   1.1   reinoud }
   3637   1.1   reinoud 
   3638   1.1   reinoud 
   3639   1.1   reinoud int
   3640   1.1   reinoud udf_write_sector(void *sector, uint64_t location)
   3641   1.1   reinoud {
   3642   1.1   reinoud 	struct wrpacket *packet, *found_packet;
   3643   1.1   reinoud 	uint64_t rel_loc;
   3644   1.1   reinoud 	uint64_t blockingnr = layout.blockingnr;
   3645   1.1   reinoud 	int error;
   3646   1.1   reinoud 
   3647   1.1   reinoud 	assert(!dev_fd_rdonly);
   3648   1.1   reinoud 	assert(blockingnr >= 1);
   3649   1.1   reinoud 	assert(blockingnr <= 64);
   3650   1.1   reinoud 
   3651   1.1   reinoud 	/*
   3652   1.1   reinoud 	 * We have a write strategy but in practice packet writing is
   3653   1.1   reinoud 	 * preferable for all media types.
   3654   1.1   reinoud 	 */
   3655   1.1   reinoud 
   3656   1.1   reinoud again:
   3657   1.1   reinoud 	/* search location */
   3658   1.1   reinoud 	found_packet = NULL;
   3659   1.1   reinoud 	TAILQ_FOREACH_REVERSE(packet, &write_queue, wrpacket_list, next) {
   3660   1.1   reinoud 		if (packet->start_sectornr <= location) {
   3661   1.1   reinoud 			found_packet = packet;
   3662   1.1   reinoud 			break;
   3663   1.1   reinoud 		}
   3664   1.1   reinoud 	}
   3665   1.1   reinoud 
   3666   1.1   reinoud 	/* are we in a current packet? */
   3667   1.1   reinoud 	if (found_packet) {
   3668   1.1   reinoud 		uint64_t base = found_packet->start_sectornr;
   3669   1.1   reinoud 		if ((location >= base) && (location -base < blockingnr)) {
   3670   1.1   reinoud 			/* fill in existing packet */
   3671   1.1   reinoud 			rel_loc = location - base;
   3672   1.1   reinoud 			memcpy(found_packet->packet_data +
   3673   1.1   reinoud 				rel_loc * context.sector_size,
   3674   1.1   reinoud 				sector, context.sector_size);
   3675   1.1   reinoud 			found_packet->present |= ((uint64_t) 1 << rel_loc);
   3676   1.1   reinoud 			return 0;
   3677   1.1   reinoud 		}
   3678   1.1   reinoud 	}
   3679   1.1   reinoud 
   3680   1.1   reinoud 	if ((write_queuelen > UDF_MAX_QUEUELEN) && !write_queue_suspend) {
   3681   1.1   reinoud 		/* we purge the queue and reset found_packet! */
   3682   1.1   reinoud 		error = udf_writeout_writequeue(false);
   3683   1.1   reinoud 		if (error)
   3684   1.1   reinoud 			return error;
   3685   1.1   reinoud 		goto again;
   3686   1.1   reinoud 	}
   3687   1.1   reinoud 
   3688   1.1   reinoud 	/* create new packet */
   3689   1.1   reinoud 	packet = calloc(1, sizeof(struct wrpacket));
   3690   1.1   reinoud 	if (packet == NULL)
   3691   1.1   reinoud 		return errno;
   3692   1.1   reinoud 	packet->packet_data = calloc(1, context.sector_size * blockingnr);
   3693   1.1   reinoud 	if (packet->packet_data == NULL) {
   3694   1.1   reinoud 		free(packet);
   3695   1.1   reinoud 		return errno;
   3696   1.1   reinoud 	}
   3697   1.1   reinoud 	packet->start_sectornr =
   3698   1.1   reinoud 		UDF_ROUNDDOWN(location, blockingnr) + wrtrack_skew;
   3699   1.1   reinoud 	rel_loc = location - packet->start_sectornr;
   3700   1.1   reinoud 
   3701   1.1   reinoud 	memcpy(packet->packet_data +
   3702   1.1   reinoud 		rel_loc * context.sector_size,
   3703   1.1   reinoud 		sector, context.sector_size);
   3704   1.1   reinoud 	packet->present = ((uint64_t) 1 << rel_loc);
   3705   1.1   reinoud 
   3706   1.1   reinoud 	if (found_packet) {
   3707   1.1   reinoud 		TAILQ_INSERT_AFTER(&write_queue, found_packet, packet, next);
   3708   1.1   reinoud 	} else {
   3709   1.1   reinoud 		TAILQ_INSERT_HEAD(&write_queue, packet, next);
   3710   1.1   reinoud 	}
   3711   1.1   reinoud 	write_queuelen++;
   3712   1.1   reinoud 
   3713   1.1   reinoud 	return 0;
   3714   1.1   reinoud }
   3715   1.1   reinoud 
   3716   1.1   reinoud 
   3717   1.1   reinoud int
   3718   1.1   reinoud udf_read_sector(void *sector, uint64_t location)
   3719   1.1   reinoud {
   3720   1.1   reinoud 	struct wrpacket *packet, *found_packet;
   3721   1.1   reinoud 	ssize_t ret;
   3722   1.1   reinoud 	uint64_t rpos, rel_loc;
   3723   1.1   reinoud 	uint64_t blockingnr = layout.blockingnr;
   3724   1.1   reinoud 
   3725   1.1   reinoud 	rpos = (uint64_t) location * context.sector_size;
   3726   1.1   reinoud 
   3727   1.1   reinoud 	/* search location */
   3728   1.1   reinoud 	found_packet = NULL;
   3729   1.1   reinoud 	TAILQ_FOREACH_REVERSE(packet, &write_queue, wrpacket_list, next) {
   3730   1.1   reinoud 		if (packet->start_sectornr <= location) {
   3731   1.1   reinoud 			found_packet = packet;
   3732   1.1   reinoud 			break;
   3733   1.1   reinoud 		}
   3734   1.1   reinoud 	}
   3735   1.1   reinoud 
   3736   1.1   reinoud 	/* are we in a current packet? */
   3737   1.1   reinoud 	if (found_packet) {
   3738   1.1   reinoud 		uint64_t base = found_packet->start_sectornr;
   3739   1.1   reinoud 		if ((location >= base) && (location -base < blockingnr)) {
   3740   1.1   reinoud 			/* fill in existing packet */
   3741   1.1   reinoud 			rel_loc = location - base;
   3742   1.1   reinoud 			if (found_packet->present & ((uint64_t) 1 << rel_loc)) {
   3743   1.1   reinoud 				memcpy(sector, found_packet->packet_data +
   3744   1.1   reinoud 					rel_loc * context.sector_size,
   3745   1.1   reinoud 					context.sector_size);
   3746   1.1   reinoud 			} else {
   3747   1.1   reinoud 				ret = pread(dev_fd, sector, context.sector_size, rpos);
   3748   1.1   reinoud 				if (ret == -1)
   3749   1.1   reinoud 					return errno;
   3750   1.1   reinoud 				if (ret < (int) context.sector_size)
   3751   1.1   reinoud 					return EIO;
   3752   1.1   reinoud 				memcpy(found_packet->packet_data +
   3753   1.1   reinoud 					rel_loc * context.sector_size,
   3754   1.1   reinoud 					sector, context.sector_size);
   3755   1.1   reinoud 				found_packet->present |= ((uint64_t) 1 << rel_loc);
   3756   1.1   reinoud 				return 0;
   3757   1.1   reinoud 			}
   3758   1.1   reinoud 		}
   3759   1.1   reinoud 	}
   3760   1.1   reinoud 	/* don't create a packet just for we read something */
   3761   1.1   reinoud 	ret = pread(dev_fd, sector, context.sector_size, rpos);
   3762   1.1   reinoud 	if (ret == -1)
   3763   1.1   reinoud 		return errno;
   3764   1.1   reinoud 	if (ret < (int) context.sector_size)
   3765   1.1   reinoud 		return EIO;
   3766   1.1   reinoud 	return 0;
   3767   1.1   reinoud }
   3768   1.1   reinoud 
   3769   1.1   reinoud 
   3770   1.1   reinoud /*
   3771   1.1   reinoud  * Now all write requests are queued in the TAILQ, write them out to the
   3772   1.1   reinoud  * disc/file image. Special care needs to be taken for devices that are only
   3773   1.1   reinoud  * strict overwritable i.e. only in packet size chunks
   3774   1.1   reinoud  *
   3775   1.1   reinoud  * XXX support for growing vnd?
   3776   1.1   reinoud  */
   3777   1.1   reinoud 
   3778   1.1   reinoud static int
   3779   1.1   reinoud udf_writeout_writequeue(bool complete)
   3780   1.1   reinoud {
   3781   1.1   reinoud 	struct wrpacket *packet, *next_packet;
   3782   1.1   reinoud 	int		 blockingnr = layout.blockingnr;
   3783   1.1   reinoud 	int		 linesize, offset, ret;
   3784   1.1   reinoud 	uint8_t		*linebuf;
   3785  1.10   reinoud 	int32_t		 wsects;
   3786   1.1   reinoud 	uint64_t	 present, all_present = -1;
   3787   1.1   reinoud 	uint64_t	 rpos, wpos;
   3788   1.1   reinoud 	static int	 t = 0;
   3789   1.1   reinoud 
   3790   1.1   reinoud 	if (write_queuelen == 0)
   3791   1.1   reinoud 		return 0;
   3792   1.1   reinoud 
   3793   1.1   reinoud 	if (blockingnr < 64)
   3794   1.1   reinoud 		all_present = ((uint64_t) 1 << blockingnr) -1;
   3795   1.1   reinoud 	linesize = blockingnr * context.sector_size;
   3796   1.1   reinoud 	linebuf = calloc(1, linesize);
   3797   1.1   reinoud 	assert(linebuf);
   3798   1.1   reinoud 
   3799   1.1   reinoud 	/* fill in blanks if needed */
   3800   1.1   reinoud 	if (complete && (context.write_strategy != UDF_WRITE_SEQUENTIAL)) {
   3801   1.1   reinoud 		TAILQ_FOREACH(packet, &write_queue, next) {
   3802   1.1   reinoud 			present = packet->present;
   3803   1.1   reinoud 			if (present != all_present) {
   3804   1.1   reinoud 				printf("%c", "\\|/-"[t++ % 4]); fflush(stdout);fflush(stderr);
   3805   1.1   reinoud //printf("%16lu : readin %08lx\n", packet->start_sectornr, packet->present ^ all_present);
   3806   1.1   reinoud 				rpos = (uint64_t)  packet->start_sectornr * context.sector_size;
   3807   1.1   reinoud 				ret = pread(dev_fd, linebuf, linesize, rpos);
   3808   1.1   reinoud 				if (ret == -1) {
   3809   1.1   reinoud 					printf("\b");
   3810   1.1   reinoud 					warn("error reading in blanks, "
   3811   1.1   reinoud 						"could indicate bad disc");
   3812   1.1   reinoud 					printf(" ");
   3813   1.1   reinoud 				}
   3814   1.1   reinoud 				for (int i = 0; i < blockingnr; i++) {
   3815   1.1   reinoud //printf("present %08lx, testing bit %08lx, value %08lx\n", present, ((uint64_t) 1 << i), (present & ((uint64_t) 1 << i)));
   3816   1.1   reinoud 					if ((present & ((uint64_t) 1 << i)) > 0)
   3817   1.1   reinoud 						continue;
   3818   1.1   reinoud //printf("NOT PRESENT\n");
   3819   1.1   reinoud 					offset = i * context.sector_size;
   3820   1.1   reinoud 					memcpy(packet->packet_data + offset,
   3821   1.1   reinoud 						linebuf + offset,
   3822   1.1   reinoud 						context.sector_size);
   3823   1.1   reinoud 					packet->present |= ((uint64_t) 1<<i);
   3824   1.1   reinoud 				}
   3825   1.1   reinoud 				printf("\b");
   3826   1.1   reinoud 			}
   3827   1.1   reinoud 			assert(packet->present == all_present);
   3828   1.1   reinoud 		}
   3829   1.1   reinoud 	}
   3830   1.1   reinoud 
   3831   1.1   reinoud 	/* writeout */
   3832   1.1   reinoud 	TAILQ_FOREACH(packet, &write_queue, next) {
   3833   1.1   reinoud 		if (complete || (packet->present == all_present)) {
   3834   1.1   reinoud 			printf("%c", "\\|/-"[t++ % 4]); fflush(stdout);fflush(stderr);
   3835   1.1   reinoud //printf("write %lu + %d\n", packet->start_sectornr, linesize / context.sector_size);
   3836  1.10   reinoud 
   3837  1.10   reinoud 			/* don't write past last possible lba */
   3838  1.10   reinoud 			wsects = (mmc_discinfo.last_possible_lba + 1 - packet->start_sectornr);
   3839  1.10   reinoud 			assert(wsects >= 0);
   3840  1.10   reinoud 			wsects = MIN(wsects, blockingnr);
   3841  1.10   reinoud 
   3842   1.1   reinoud 			wpos = (uint64_t) packet->start_sectornr * context.sector_size;
   3843  1.10   reinoud 			ret = pwrite(dev_fd,
   3844  1.10   reinoud 				packet->packet_data,
   3845  1.10   reinoud 				wsects * context.sector_size,
   3846  1.10   reinoud 				wpos);
   3847   1.1   reinoud 			printf("\b");
   3848   1.1   reinoud 			if (ret == -1)
   3849   1.1   reinoud 				warn("error writing packet, "
   3850   1.1   reinoud 					"could indicate bad disc");
   3851   1.1   reinoud 		}
   3852   1.1   reinoud 	}
   3853   1.1   reinoud 
   3854   1.1   reinoud 	/* removing completed packets */
   3855   1.1   reinoud 	TAILQ_FOREACH_SAFE(packet, &write_queue, next, next_packet) {
   3856   1.1   reinoud 		if (complete || (packet->present == all_present)) {
   3857   1.1   reinoud 			TAILQ_REMOVE(&write_queue, packet, next);
   3858   1.1   reinoud 			free(packet->packet_data);
   3859   1.1   reinoud 			free(packet);
   3860   1.1   reinoud 			write_queuelen--;
   3861   1.1   reinoud 		}
   3862   1.1   reinoud 	}
   3863   1.1   reinoud 	if (complete) {
   3864   1.1   reinoud 		assert(TAILQ_EMPTY(&write_queue));
   3865   1.1   reinoud 		write_queuelen = 0;
   3866   1.1   reinoud 	}
   3867   1.1   reinoud 
   3868   1.1   reinoud 	free(linebuf);
   3869   1.1   reinoud 	return 0;
   3870   1.1   reinoud }
   3871   1.1   reinoud 
   3872   1.1   reinoud 
   3873   1.1   reinoud /* --------------------------------------------------------------------- */
   3874   1.1   reinoud 
   3875   1.1   reinoud /* simplified version of kernel routine */
   3876   1.1   reinoud int
   3877   1.1   reinoud udf_translate_vtop(uint32_t lb_num, uint16_t vpart,
   3878   1.1   reinoud 		   uint32_t *lb_numres, uint32_t *extres)
   3879   1.1   reinoud {
   3880   1.1   reinoud 	struct part_desc       *pdesc;
   3881   1.1   reinoud 	struct spare_map_entry *sme;
   3882   1.1   reinoud 	struct short_ad        *short_ad;
   3883   1.1   reinoud 	struct extfile_entry   *efe;
   3884   1.1   reinoud 	uint32_t ext, len, lb_rel, lb_packet, vat_off;
   3885   1.1   reinoud 	uint32_t start_lb, lb_offset, end_lb_offset;
   3886   1.1   reinoud 	uint32_t udf_rw32_lbmap;
   3887   1.1   reinoud 	uint32_t flags;
   3888   1.1   reinoud 	uint8_t *vat_pos, *data_pos;
   3889   1.1   reinoud 	int dscr_size, l_ea, l_ad, icbflags, addr_type;
   3890   1.1   reinoud 	int rel, part;
   3891   1.1   reinoud 
   3892   1.1   reinoud 	if (vpart > UDF_VTOP_RAWPART)
   3893   1.1   reinoud 		return EINVAL;
   3894   1.1   reinoud 
   3895   1.1   reinoud 	ext = INT_MAX;
   3896   1.1   reinoud translate_again:
   3897   1.1   reinoud 	part = context.vtop[vpart];
   3898   1.1   reinoud 	pdesc = context.partitions[part];
   3899   1.1   reinoud 
   3900   1.1   reinoud 	switch (context.vtop_tp[vpart]) {
   3901   1.1   reinoud 	case UDF_VTOP_TYPE_RAW :
   3902   1.1   reinoud 		/* 1:1 to the end of the device */
   3903   1.1   reinoud 		*lb_numres = lb_num;
   3904   1.1   reinoud 		*extres = MIN(ext, INT_MAX);
   3905   1.1   reinoud 		return 0;
   3906   1.1   reinoud 	case UDF_VTOP_TYPE_PHYS :
   3907   1.1   reinoud 		/* transform into its disc logical block */
   3908   1.1   reinoud 		if (lb_num > udf_rw32(pdesc->part_len))
   3909   1.1   reinoud 			return EINVAL;
   3910   1.1   reinoud 		*lb_numres = lb_num + udf_rw32(pdesc->start_loc);
   3911   1.1   reinoud 
   3912   1.1   reinoud 		/* extent from here to the end of the partition */
   3913   1.1   reinoud 		*extres = MIN(ext, udf_rw32(pdesc->part_len) - lb_num);
   3914   1.1   reinoud 		if (*extres == 0)
   3915   1.1   reinoud 			return EINVAL;
   3916   1.1   reinoud 		return 0;
   3917   1.1   reinoud 	case UDF_VTOP_TYPE_VIRT :
   3918   1.1   reinoud 		/* only maps one logical block, lookup in VAT */
   3919   1.1   reinoud 		if (lb_num * 4 >= context.vat_size)
   3920   1.1   reinoud 			return EINVAL;
   3921   1.1   reinoud 		vat_off = context.vat_start + lb_num * 4;
   3922   1.1   reinoud 		vat_pos = context.vat_contents + vat_off;
   3923   1.1   reinoud 		udf_rw32_lbmap = *((uint32_t *) vat_pos);
   3924   1.1   reinoud 
   3925   1.1   reinoud 		if (vat_off >= context.vat_size)		/* XXX > or >= ? */
   3926   1.1   reinoud 			return EINVAL;
   3927   1.1   reinoud 		lb_num = udf_rw32(udf_rw32_lbmap);
   3928   1.1   reinoud 
   3929   1.1   reinoud 		/* transform into its disc logical block */
   3930   1.1   reinoud 		if (lb_num > udf_rw32(pdesc->part_len))
   3931   1.1   reinoud 			return EINVAL;
   3932   1.1   reinoud 		*lb_numres = lb_num + udf_rw32(pdesc->start_loc);
   3933   1.1   reinoud 
   3934   1.1   reinoud 		/* just one logical block */
   3935   1.1   reinoud 		*extres = 1;
   3936   1.1   reinoud 		return 0;
   3937   1.1   reinoud 	case UDF_VTOP_TYPE_SPAREABLE :
   3938   1.1   reinoud 		/* check if the packet containing the lb_num is remapped */
   3939   1.1   reinoud 		lb_packet = lb_num / layout.spareable_blockingnr;
   3940   1.1   reinoud 		lb_rel    = lb_num % layout.spareable_blockingnr;
   3941   1.1   reinoud 
   3942   1.1   reinoud 		for (rel = 0; rel < udf_rw16(context.sparing_table->rt_l); rel++) {
   3943   1.1   reinoud 			sme = &context.sparing_table->entries[rel];
   3944   1.1   reinoud 			if (lb_packet == udf_rw32(sme->org)) {
   3945   1.1   reinoud 				/* NOTE maps to absolute disc logical block! */
   3946   1.1   reinoud 				*lb_numres = udf_rw32(sme->map) + lb_rel;
   3947   1.1   reinoud 				*extres    = layout.spareable_blockingnr - lb_rel;
   3948   1.1   reinoud 				return 0;
   3949   1.1   reinoud 			}
   3950   1.1   reinoud 		}
   3951   1.1   reinoud 
   3952   1.1   reinoud 		/* transform into its disc logical block */
   3953   1.1   reinoud 		if (lb_num > udf_rw32(pdesc->part_len))
   3954   1.1   reinoud 			return EINVAL;
   3955   1.1   reinoud 		*lb_numres = lb_num + udf_rw32(pdesc->start_loc);
   3956   1.1   reinoud 
   3957   1.1   reinoud 		/* rest of block */
   3958   1.1   reinoud 		*extres = MIN(ext, layout.spareable_blockingnr - lb_rel);
   3959   1.1   reinoud 		return 0;
   3960   1.1   reinoud 	case UDF_VTOP_TYPE_META :
   3961   1.1   reinoud 		/* we have to look into the file's allocation descriptors */
   3962   1.1   reinoud 
   3963   1.1   reinoud 		/* get first overlapping extent */
   3964   1.1   reinoud 		efe = context.meta_file;
   3965   1.1   reinoud 		dscr_size = sizeof(struct extfile_entry) - 1;
   3966   1.1   reinoud 		l_ea = udf_rw32(efe->l_ea);
   3967   1.1   reinoud 		l_ad = udf_rw32(efe->l_ad);
   3968   1.1   reinoud 
   3969   1.1   reinoud 		icbflags = udf_rw16(efe->icbtag.flags);
   3970   1.1   reinoud 		addr_type = icbflags & UDF_ICB_TAG_FLAGS_ALLOC_MASK;
   3971   1.1   reinoud 		if (addr_type != UDF_ICB_SHORT_ALLOC) {
   3972   1.1   reinoud 			warnx("specification violation: metafile not using"
   3973   1.1   reinoud 				"short allocs");
   3974   1.1   reinoud 			return EINVAL;
   3975   1.1   reinoud 		}
   3976   1.1   reinoud 
   3977   1.1   reinoud 		data_pos = (uint8_t *) context.meta_file + dscr_size + l_ea;
   3978   1.1   reinoud 		short_ad = (struct short_ad *) data_pos;
   3979   1.1   reinoud 		lb_offset = 0;
   3980   1.1   reinoud 		while (l_ad > 0) {
   3981   1.1   reinoud 			len      = udf_rw32(short_ad->len);
   3982   1.1   reinoud 			start_lb = udf_rw32(short_ad->lb_num);
   3983   1.1   reinoud 			flags    = UDF_EXT_FLAGS(len);
   3984   1.1   reinoud 			len      = UDF_EXT_LEN(len);
   3985   1.1   reinoud 			if (flags == UDF_EXT_REDIRECT) {
   3986   1.1   reinoud 				warnx("implementation limit: no support for "
   3987   1.1   reinoud 				      "extent redirection in metadata file");
   3988   1.1   reinoud 				return EINVAL;
   3989   1.1   reinoud 			}
   3990   1.1   reinoud 			end_lb_offset = lb_offset + len / context.sector_size;
   3991   1.1   reinoud 			/* overlap? */
   3992   1.1   reinoud 			if (end_lb_offset > lb_num)
   3993   1.1   reinoud 				break;
   3994   1.1   reinoud 			short_ad++;
   3995   1.1   reinoud 			lb_offset = end_lb_offset;
   3996   1.1   reinoud 			l_ad -= sizeof(struct short_ad);
   3997   1.1   reinoud 		}
   3998   1.1   reinoud 		if (l_ad <= 0) {
   3999   1.1   reinoud 			warnx("looking up outside metadata partition!");
   4000   1.1   reinoud 			return EINVAL;
   4001   1.1   reinoud 		}
   4002   1.1   reinoud 		lb_num = start_lb + (lb_num - lb_offset);
   4003   1.1   reinoud 		vpart  = part;
   4004   1.1   reinoud 		ext = end_lb_offset - lb_num;
   4005   1.1   reinoud 		/*
   4006   1.1   reinoud 		 * vpart and lb_num are updated, translate again since we
   4007   1.1   reinoud 		 * might be mapped on spareable media
   4008   1.1   reinoud 		 */
   4009   1.1   reinoud 		goto translate_again;
   4010   1.1   reinoud 	default:
   4011   1.1   reinoud 		printf("UDF vtop translation scheme %d unimplemented yet\n",
   4012   1.1   reinoud 			context.vtop_tp[vpart]);
   4013   1.1   reinoud 	}
   4014   1.1   reinoud 
   4015   1.1   reinoud 	return EINVAL;
   4016   1.1   reinoud }
   4017   1.1   reinoud 
   4018   1.1   reinoud /* --------------------------------------------------------------------- */
   4019   1.1   reinoud 
   4020   1.1   reinoud int
   4021   1.1   reinoud udf_read_phys(void *blob, uint32_t location, uint32_t sects)
   4022   1.1   reinoud {
   4023   1.1   reinoud 	uint32_t phys, cnt;
   4024   1.1   reinoud 	uint8_t *bpos;
   4025   1.1   reinoud 	int error;
   4026   1.1   reinoud 
   4027   1.1   reinoud 	for (cnt = 0; cnt < sects; cnt++) {
   4028   1.1   reinoud 		bpos  = (uint8_t *) blob;
   4029   1.1   reinoud 		bpos += context.sector_size * cnt;
   4030   1.1   reinoud 
   4031   1.1   reinoud 		phys = location + cnt;
   4032   1.1   reinoud 		error = udf_read_sector(bpos, phys);
   4033   1.1   reinoud 		if (error)
   4034   1.1   reinoud 			return error;
   4035   1.1   reinoud 	}
   4036   1.1   reinoud 	return 0;
   4037   1.1   reinoud }
   4038   1.1   reinoud 
   4039   1.1   reinoud 
   4040   1.1   reinoud int
   4041   1.1   reinoud udf_write_phys(void *blob, uint32_t location, uint32_t sects)
   4042   1.1   reinoud {
   4043   1.1   reinoud 	uint32_t phys, cnt;
   4044   1.1   reinoud 	uint8_t *bpos;
   4045   1.1   reinoud 	int error;
   4046   1.1   reinoud 
   4047   1.1   reinoud 	for (cnt = 0; cnt < sects; cnt++) {
   4048   1.1   reinoud 		bpos  = (uint8_t *) blob;
   4049   1.1   reinoud 		bpos += context.sector_size * cnt;
   4050   1.1   reinoud 
   4051   1.1   reinoud 		phys = location + cnt;
   4052   1.1   reinoud 		error = udf_write_sector(bpos, phys);
   4053   1.1   reinoud 		if (error)
   4054   1.1   reinoud 			return error;
   4055   1.1   reinoud 	}
   4056   1.1   reinoud 	return 0;
   4057   1.1   reinoud }
   4058   1.1   reinoud 
   4059   1.1   reinoud 
   4060   1.1   reinoud int
   4061   1.1   reinoud udf_read_virt(void *blob, uint32_t location, uint16_t vpart,
   4062   1.1   reinoud 	uint32_t sectors)
   4063   1.1   reinoud {
   4064   1.1   reinoud 	uint32_t phys, ext;
   4065   1.1   reinoud 	uint8_t *data;
   4066   1.1   reinoud 	int error;
   4067   1.1   reinoud 
   4068   1.1   reinoud 	/* determine physical location */
   4069   1.1   reinoud 	data = (uint8_t *) blob;
   4070   1.1   reinoud 	while (sectors) {
   4071   1.1   reinoud 		if (udf_translate_vtop(location, vpart, &phys, &ext)) {
   4072   1.1   reinoud 			// warnx("internal error: bad translation");
   4073   1.1   reinoud 			return EINVAL;
   4074   1.1   reinoud 		}
   4075   1.1   reinoud 		ext = MIN(sectors, ext);
   4076   1.1   reinoud 		error = udf_read_phys(data, phys, ext);
   4077   1.1   reinoud 		if (error)
   4078   1.1   reinoud 			return error;
   4079   1.1   reinoud 		location += ext;
   4080   1.1   reinoud 		data     += ext * context.sector_size;
   4081   1.1   reinoud 		sectors  -= ext;
   4082   1.1   reinoud 	}
   4083   1.1   reinoud 	return 0;
   4084   1.1   reinoud }
   4085   1.1   reinoud 
   4086   1.1   reinoud 
   4087   1.1   reinoud int
   4088   1.1   reinoud udf_write_virt(void *blob, uint32_t location, uint16_t vpart,
   4089   1.1   reinoud 	uint32_t sectors)
   4090   1.1   reinoud {
   4091   1.1   reinoud 	uint32_t phys, ext, alloc_pos;
   4092   1.1   reinoud 	uint8_t *data;
   4093   1.1   reinoud 	int error;
   4094   1.1   reinoud 
   4095   1.1   reinoud 	/* determine physical location */
   4096   1.1   reinoud 	if (context.vtop_tp[vpart] == UDF_VTOP_TYPE_VIRT) {
   4097   1.1   reinoud 		assert(sectors == 1);
   4098   1.1   reinoud 		alloc_pos = context.alloc_pos[context.data_part];
   4099   1.1   reinoud 		udf_vat_update(location, alloc_pos);
   4100   1.1   reinoud 		udf_translate_vtop(alloc_pos, context.vtop[vpart], &phys, &ext);
   4101   1.1   reinoud 		context.alloc_pos[context.data_part]++;
   4102   1.1   reinoud 		return udf_write_phys(blob, phys, sectors);
   4103   1.1   reinoud 	}
   4104   1.1   reinoud 
   4105   1.1   reinoud 	data = (uint8_t *) blob;
   4106   1.1   reinoud 	while (sectors) {
   4107   1.1   reinoud 		if (udf_translate_vtop(location, vpart, &phys, &ext)) {
   4108   1.1   reinoud 			warnx("internal error: bad translation");
   4109   1.1   reinoud 			return EINVAL;
   4110   1.1   reinoud 		}
   4111   1.1   reinoud 		ext = MIN(sectors, ext);
   4112   1.1   reinoud 		error = udf_write_phys(data, phys, ext);
   4113   1.1   reinoud 		if (error)
   4114   1.1   reinoud 			return error;
   4115   1.1   reinoud 		location += ext;
   4116   1.1   reinoud 		data     += ext * context.sector_size;
   4117   1.1   reinoud 		sectors  -= ext;
   4118   1.1   reinoud 	}
   4119   1.1   reinoud 	return 0;
   4120   1.1   reinoud }
   4121   1.1   reinoud 
   4122   1.1   reinoud 
   4123   1.1   reinoud int
   4124   1.1   reinoud udf_read_dscr_phys(uint32_t sector, union dscrptr **dstp)
   4125   1.1   reinoud {
   4126   1.1   reinoud 	union dscrptr *dst, *new_dst;
   4127   1.1   reinoud 	uint8_t *pos;
   4128   1.1   reinoud 	uint32_t sectors, dscrlen, sector_size;
   4129   1.1   reinoud 	int error;
   4130   1.1   reinoud 
   4131   1.1   reinoud 	sector_size = context.sector_size;
   4132   1.1   reinoud 
   4133   1.1   reinoud 	*dstp = dst = NULL;
   4134   1.1   reinoud 	dscrlen = sector_size;
   4135   1.1   reinoud 
   4136   1.1   reinoud 	/* read initial piece */
   4137   1.1   reinoud 	dst = malloc(sector_size);
   4138   1.1   reinoud 	assert(dst);
   4139   1.1   reinoud 	error = udf_read_sector(dst, sector);
   4140   1.1   reinoud //	if (error)
   4141   1.1   reinoud //		warn("read error");
   4142   1.1   reinoud 
   4143   1.1   reinoud 	if (!error) {
   4144   1.1   reinoud 		/* check if its an empty block */
   4145   1.1   reinoud 		if (is_zero(dst, sector_size)) {
   4146   1.1   reinoud 			/* return no error but with no dscrptr */
   4147   1.1   reinoud 			/* dispose first block */
   4148   1.1   reinoud 			free(dst);
   4149   1.1   reinoud 			return 0;
   4150   1.1   reinoud 		}
   4151   1.1   reinoud 		/* check if its a valid tag */
   4152   1.1   reinoud 		error = udf_check_tag(dst);
   4153   1.1   reinoud 		if (error) {
   4154   1.1   reinoud 			free(dst);
   4155   1.1   reinoud 			return 0;
   4156   1.1   reinoud 		}
   4157   1.1   reinoud 		/* calculate descriptor size */
   4158   1.1   reinoud 		dscrlen = udf_tagsize(dst, sector_size);
   4159   1.1   reinoud 	}
   4160   1.1   reinoud 
   4161   1.1   reinoud 	if (!error && (dscrlen > sector_size)) {
   4162   1.1   reinoud 		/* read the rest of descriptor */
   4163   1.1   reinoud 
   4164   1.1   reinoud 		new_dst = realloc(dst, dscrlen);
   4165   1.1   reinoud 		if (new_dst == NULL) {
   4166   1.1   reinoud 			free(dst);
   4167   1.1   reinoud 			return ENOMEM;
   4168   1.1   reinoud 		}
   4169   1.1   reinoud 		dst = new_dst;
   4170   1.1   reinoud 
   4171   1.1   reinoud 		sectors = dscrlen / sector_size;
   4172   1.1   reinoud 		pos = (uint8_t *) dst + sector_size;
   4173   1.1   reinoud 		error = udf_read_phys(pos, sector + 1, sectors-1);
   4174   1.1   reinoud 		if (error)
   4175   1.1   reinoud 			warnx("read error");
   4176   1.1   reinoud 	}
   4177   1.1   reinoud 	if (!error)
   4178   1.1   reinoud 		error = udf_check_tag_payload(dst, dscrlen);
   4179   1.1   reinoud 	if (error && dst) {
   4180   1.1   reinoud 		free(dst);
   4181   1.1   reinoud 		dst = NULL;
   4182   1.1   reinoud 	}
   4183   1.1   reinoud 	*dstp = dst;
   4184   1.1   reinoud 
   4185   1.1   reinoud 	return error;
   4186   1.1   reinoud }
   4187   1.1   reinoud 
   4188   1.1   reinoud 
   4189   1.1   reinoud int
   4190   1.1   reinoud udf_write_dscr_phys(union dscrptr *dscr, uint32_t location,
   4191   1.1   reinoud 	uint32_t sectors)
   4192   1.1   reinoud {
   4193   1.1   reinoud 	dscr->tag.tag_loc = udf_rw32(location);
   4194   1.1   reinoud 	(void) udf_validate_tag_and_crc_sums(dscr);
   4195   1.1   reinoud 
   4196   1.1   reinoud 	assert(sectors == udf_tagsize(dscr, context.sector_size) / context.sector_size);
   4197   1.1   reinoud 	return udf_write_phys(dscr, location, sectors);
   4198   1.1   reinoud }
   4199   1.1   reinoud 
   4200   1.1   reinoud 
   4201   1.1   reinoud int
   4202   1.1   reinoud udf_read_dscr_virt(uint32_t sector, uint16_t vpart, union dscrptr **dstp)
   4203   1.1   reinoud {
   4204   1.1   reinoud 	union dscrptr *dst, *new_dst;
   4205   1.1   reinoud 	uint8_t *pos;
   4206   1.1   reinoud 	uint32_t sectors, dscrlen, sector_size;
   4207   1.1   reinoud 	int error;
   4208   1.1   reinoud 
   4209   1.1   reinoud 	sector_size = context.sector_size;
   4210   1.1   reinoud 
   4211   1.1   reinoud 	*dstp = dst = NULL;
   4212   1.1   reinoud 	dscrlen = sector_size;
   4213   1.1   reinoud 
   4214   1.1   reinoud 	/* read initial piece */
   4215   1.1   reinoud 	dst = calloc(1, sector_size);
   4216   1.1   reinoud 	assert(dst);
   4217   1.1   reinoud 	error = udf_read_virt(dst, sector, vpart, 1);
   4218   1.1   reinoud 	if (error)
   4219   1.1   reinoud 		return error;
   4220   1.1   reinoud 
   4221   1.1   reinoud 	if (!error) {
   4222   1.1   reinoud 		/* check if its a valid tag */
   4223   1.1   reinoud 		error = udf_check_tag(dst);
   4224   1.1   reinoud 		if (error) {
   4225   1.1   reinoud 			/* check if its an empty block */
   4226   1.1   reinoud 			if (is_zero(dst, sector_size)) {
   4227   1.1   reinoud 				/* return no error but with no dscrptr */
   4228   1.1   reinoud 				/* dispose first block */
   4229   1.1   reinoud 				free(dst);
   4230   1.1   reinoud 				return 0;
   4231   1.1   reinoud 			}
   4232   1.1   reinoud 		}
   4233   1.1   reinoud 		/* calculate descriptor size */
   4234   1.1   reinoud 		dscrlen = udf_tagsize(dst, sector_size);
   4235   1.1   reinoud 	}
   4236   1.1   reinoud 
   4237   1.1   reinoud 	if (!error && (dscrlen > sector_size)) {
   4238   1.1   reinoud 		/* read the rest of descriptor */
   4239   1.1   reinoud 
   4240   1.1   reinoud 		new_dst = realloc(dst, dscrlen);
   4241   1.1   reinoud 		if (new_dst == NULL) {
   4242   1.1   reinoud 			free(dst);
   4243   1.1   reinoud 			return ENOMEM;
   4244   1.1   reinoud 		}
   4245   1.1   reinoud 		dst = new_dst;
   4246   1.1   reinoud 
   4247   1.1   reinoud 		sectors = dscrlen / sector_size;
   4248   1.1   reinoud 		pos = (uint8_t *) dst + sector_size;
   4249   1.1   reinoud 		error = udf_read_virt(pos, sector + 1, vpart, sectors-1);
   4250   1.1   reinoud 		if (error)
   4251   1.1   reinoud 			warn("read error");
   4252   1.1   reinoud 	}
   4253   1.1   reinoud 	if (!error)
   4254   1.1   reinoud 		error = udf_check_tag_payload(dst, dscrlen);
   4255   1.1   reinoud 	if (error && dst) {
   4256   1.1   reinoud 		free(dst);
   4257   1.1   reinoud 		dst = NULL;
   4258   1.1   reinoud 	}
   4259   1.1   reinoud 	*dstp = dst;
   4260   1.1   reinoud 
   4261   1.1   reinoud 	return error;
   4262   1.1   reinoud }
   4263   1.1   reinoud 
   4264   1.1   reinoud 
   4265   1.1   reinoud int
   4266   1.1   reinoud udf_write_dscr_virt(union dscrptr *dscr, uint32_t location, uint16_t vpart,
   4267   1.1   reinoud 	uint32_t sectors)
   4268   1.1   reinoud {
   4269   1.1   reinoud 	struct file_entry *fe;
   4270   1.1   reinoud 	struct extfile_entry *efe;
   4271   1.1   reinoud 	struct extattrhdr_desc *extattrhdr;
   4272   1.1   reinoud 
   4273   1.1   reinoud 	extattrhdr = NULL;
   4274   1.1   reinoud 	if (udf_rw16(dscr->tag.id) == TAGID_FENTRY) {
   4275   1.1   reinoud 		fe = (struct file_entry *) dscr;
   4276   1.1   reinoud 		if (udf_rw32(fe->l_ea) > 0)
   4277   1.1   reinoud 			extattrhdr = (struct extattrhdr_desc *) fe->data;
   4278   1.1   reinoud 	}
   4279   1.1   reinoud 	if (udf_rw16(dscr->tag.id) == TAGID_EXTFENTRY) {
   4280   1.1   reinoud 		efe = (struct extfile_entry *) dscr;
   4281   1.1   reinoud 		if (udf_rw32(efe->l_ea) > 0)
   4282   1.1   reinoud 			extattrhdr = (struct extattrhdr_desc *) efe->data;
   4283   1.1   reinoud 	}
   4284   1.1   reinoud 	if (extattrhdr) {
   4285   1.1   reinoud 		extattrhdr->tag.tag_loc = udf_rw32(location);
   4286   1.1   reinoud 		udf_validate_tag_and_crc_sums((union dscrptr *) extattrhdr);
   4287   1.1   reinoud 	}
   4288   1.1   reinoud 
   4289   1.1   reinoud 	dscr->tag.tag_loc = udf_rw32(location);
   4290   1.1   reinoud 	udf_validate_tag_and_crc_sums(dscr);
   4291   1.1   reinoud 
   4292   1.1   reinoud 	assert(sectors >= (udf_tagsize(dscr, context.sector_size) / context.sector_size));
   4293   1.1   reinoud 	return udf_write_virt(dscr, location, vpart, sectors);
   4294   1.1   reinoud }
   4295   1.1   reinoud 
   4296   1.1   reinoud 
   4297   1.1   reinoud int
   4298   1.1   reinoud is_zero(void *blob, int size) {
   4299   1.1   reinoud 	uint8_t *p = blob;
   4300   1.1   reinoud 	for (int i = 0; i < size; i++, p++)
   4301   1.1   reinoud 		if (*p)
   4302   1.1   reinoud 			return 0;
   4303   1.1   reinoud 	return 1;
   4304   1.1   reinoud }
   4305   1.1   reinoud 
   4306   1.1   reinoud /* --------------------------------------------------------------------- */
   4307   1.1   reinoud 
   4308   1.1   reinoud static void
   4309   1.1   reinoud udf_partition_alloc(int nblk, int vpart, struct long_ad *pos)
   4310   1.1   reinoud {
   4311   1.1   reinoud 	memset(pos, 0, sizeof(*pos));
   4312   1.1   reinoud 	pos->len	  = udf_rw32(nblk * context.sector_size);
   4313   1.1   reinoud 	pos->loc.lb_num   = udf_rw32(context.alloc_pos[vpart]);
   4314   1.1   reinoud 	pos->loc.part_num = udf_rw16(vpart);
   4315   1.1   reinoud 
   4316   1.1   reinoud 	udf_mark_allocated(context.alloc_pos[vpart], vpart, nblk);
   4317   1.1   reinoud 	context.alloc_pos[vpart] += nblk;
   4318   1.1   reinoud }
   4319   1.1   reinoud 
   4320   1.1   reinoud 
   4321   1.1   reinoud void
   4322   1.1   reinoud udf_metadata_alloc(int nblk, struct long_ad *pos)
   4323   1.1   reinoud {
   4324   1.1   reinoud 	udf_partition_alloc(nblk, context.metadata_part, pos);
   4325   1.1   reinoud }
   4326   1.1   reinoud 
   4327   1.1   reinoud 
   4328   1.1   reinoud void
   4329   1.1   reinoud udf_data_alloc(int nblk, struct long_ad *pos)
   4330   1.1   reinoud {
   4331   1.1   reinoud 	udf_partition_alloc(nblk, context.data_part, pos);
   4332   1.1   reinoud }
   4333   1.1   reinoud 
   4334   1.1   reinoud 
   4335   1.1   reinoud void
   4336   1.1   reinoud udf_fids_alloc(int nblk, struct long_ad *pos)
   4337   1.1   reinoud {
   4338   1.1   reinoud 	udf_partition_alloc(nblk, context.fids_part, pos);
   4339   1.1   reinoud }
   4340   1.1   reinoud 
   4341   1.1   reinoud 
   4342   1.1   reinoud /* --------------------------------------------------------------------- */
   4343   1.1   reinoud 
   4344   1.1   reinoud /*
   4345   1.1   reinoud  * udf_derive_format derives the format_flags from the disc's mmc_discinfo.
   4346   1.1   reinoud  * The resulting flags uniquely define a disc format. Note there are at least
   4347   1.1   reinoud  * 7 distinct format types defined in UDF.
   4348   1.1   reinoud  */
   4349   1.1   reinoud 
   4350   1.1   reinoud #define UDF_VERSION(a) \
   4351   1.1   reinoud 	(((a) == 0x102) || ((a) == 0x150) || ((a) == 0x200) || \
   4352   1.1   reinoud 	 ((a) == 0x201) || ((a) == 0x250) || ((a) == 0x260))
   4353   1.1   reinoud 
   4354   1.1   reinoud int
   4355   1.1   reinoud udf_derive_format(int req_enable, int req_disable)
   4356   1.1   reinoud {
   4357   1.1   reinoud 	int format_flags;
   4358   1.1   reinoud 	int media_accesstype;
   4359   1.1   reinoud 
   4360   1.1   reinoud 	/* disc writability, formatted, appendable */
   4361   1.1   reinoud 	if ((mmc_discinfo.mmc_cur & MMC_CAP_RECORDABLE) == 0) {
   4362   1.1   reinoud 		warnx("can't newfs readonly device");
   4363   1.1   reinoud 		return EROFS;
   4364   1.1   reinoud 	}
   4365   1.1   reinoud 	if (mmc_discinfo.mmc_cur & MMC_CAP_SEQUENTIAL) {
   4366   1.1   reinoud 		/* sequentials need sessions appended */
   4367   1.1   reinoud 		if (mmc_discinfo.disc_state == MMC_STATE_CLOSED) {
   4368   1.1   reinoud 			warnx("can't append session to a closed disc");
   4369   1.1   reinoud 			return EROFS;
   4370   1.1   reinoud 		}
   4371   1.1   reinoud 		if ((mmc_discinfo.disc_state != MMC_STATE_EMPTY) &&
   4372   1.1   reinoud 				!context.create_new_session) {
   4373   1.1   reinoud 			warnx("disc not empty! Use -F to force "
   4374   1.1   reinoud 			    "initialisation");
   4375   1.1   reinoud 			return EROFS;
   4376   1.1   reinoud 		}
   4377   1.1   reinoud 	} else {
   4378   1.1   reinoud 		/* check if disc (being) formatted or has been started on */
   4379   1.1   reinoud 		if (mmc_discinfo.disc_state == MMC_STATE_EMPTY) {
   4380   1.1   reinoud 			warnx("disc is not formatted");
   4381   1.1   reinoud 			return EROFS;
   4382   1.1   reinoud 		}
   4383   1.1   reinoud 	}
   4384   1.1   reinoud 
   4385   1.1   reinoud 	/* determine UDF format */
   4386   1.1   reinoud 	format_flags = 0;
   4387   1.1   reinoud 	if (mmc_discinfo.mmc_cur & MMC_CAP_REWRITABLE) {
   4388   1.1   reinoud 		/* all rewritable media */
   4389   1.1   reinoud 		format_flags |= FORMAT_REWRITABLE;
   4390   1.1   reinoud 		if (context.min_udf >= 0x0250) {
   4391   1.1   reinoud 			/* standard dictates meta as default */
   4392   1.1   reinoud 			format_flags |= FORMAT_META;
   4393   1.1   reinoud 		}
   4394   1.1   reinoud 
   4395   1.1   reinoud 		if ((mmc_discinfo.mmc_cur & MMC_CAP_HW_DEFECTFREE) == 0) {
   4396   1.1   reinoud 			/* spareables for defect management */
   4397   1.1   reinoud 			if (context.min_udf >= 0x150)
   4398   1.1   reinoud 				format_flags |= FORMAT_SPAREABLE;
   4399   1.1   reinoud 		}
   4400   1.1   reinoud 	} else {
   4401   1.1   reinoud 		/* all once recordable media */
   4402   1.1   reinoud 		format_flags |= FORMAT_WRITEONCE;
   4403   1.1   reinoud 		if (mmc_discinfo.mmc_cur & MMC_CAP_SEQUENTIAL) {
   4404   1.1   reinoud 			format_flags |= FORMAT_SEQUENTIAL;
   4405   1.1   reinoud 
   4406   1.1   reinoud 			if (mmc_discinfo.mmc_cur & MMC_CAP_PSEUDOOVERWRITE) {
   4407   1.1   reinoud 				/* logical overwritable */
   4408   1.1   reinoud 				format_flags |= FORMAT_LOW;
   4409   1.1   reinoud 			} else {
   4410   1.1   reinoud 				/* have to use VAT for overwriting */
   4411   1.1   reinoud 				format_flags |= FORMAT_VAT;
   4412   1.1   reinoud 			}
   4413   1.1   reinoud 		} else {
   4414   1.1   reinoud 			/* rare WORM devices, but BluRay has one, strat4096 */
   4415   1.1   reinoud 			format_flags |= FORMAT_WORM;
   4416   1.1   reinoud 		}
   4417   1.1   reinoud 	}
   4418   1.1   reinoud 
   4419   1.1   reinoud 	/* enable/disable requests */
   4420   1.1   reinoud 	if (req_disable & FORMAT_META) {
   4421   1.1   reinoud 		format_flags &= ~(FORMAT_META | FORMAT_LOW);
   4422   1.1   reinoud 		req_disable  &= ~FORMAT_META;
   4423   1.1   reinoud 	}
   4424   1.1   reinoud 	if ((format_flags & FORMAT_VAT) & UDF_512_TRACK)
   4425   1.1   reinoud 		format_flags |= FORMAT_TRACK512;
   4426   1.1   reinoud 
   4427   1.1   reinoud 	if (req_enable & FORMAT_READONLY) {
   4428   1.1   reinoud 		format_flags |= FORMAT_READONLY;
   4429   1.1   reinoud 	}
   4430   1.1   reinoud 
   4431   1.1   reinoud 	/* determine partition/media access type */
   4432   1.1   reinoud 	media_accesstype = UDF_ACCESSTYPE_NOT_SPECIFIED;
   4433   1.1   reinoud 	if (mmc_discinfo.mmc_cur & MMC_CAP_REWRITABLE) {
   4434   1.1   reinoud 		media_accesstype = UDF_ACCESSTYPE_OVERWRITABLE;
   4435   1.1   reinoud 		if (mmc_discinfo.mmc_cur & MMC_CAP_ERASABLE)
   4436   1.1   reinoud 			media_accesstype = UDF_ACCESSTYPE_REWRITEABLE;
   4437   1.1   reinoud 	} else {
   4438   1.1   reinoud 		/* all once recordable media */
   4439   1.1   reinoud 		media_accesstype = UDF_ACCESSTYPE_WRITE_ONCE;
   4440   1.1   reinoud 	}
   4441   1.1   reinoud 	if (mmc_discinfo.mmc_cur & MMC_CAP_PSEUDOOVERWRITE)
   4442   1.1   reinoud 		media_accesstype = UDF_ACCESSTYPE_PSEUDO_OVERWITE;
   4443   1.1   reinoud 
   4444   1.1   reinoud 	/* patch up media accesstype */
   4445   1.1   reinoud 	if (req_enable & FORMAT_READONLY) {
   4446   1.1   reinoud 		/* better now */
   4447   1.1   reinoud 		media_accesstype = UDF_ACCESSTYPE_READ_ONLY;
   4448   1.1   reinoud 	}
   4449   1.1   reinoud 
   4450   1.1   reinoud 	/* adjust minimum version limits */
   4451   1.1   reinoud 	if (format_flags & FORMAT_VAT)
   4452   1.1   reinoud 		context.min_udf = MAX(context.min_udf, 0x0150);
   4453   1.1   reinoud 	if (format_flags & FORMAT_SPAREABLE)
   4454   1.1   reinoud 		context.min_udf = MAX(context.min_udf, 0x0150);
   4455   1.1   reinoud 	if (format_flags & FORMAT_META)
   4456   1.1   reinoud 		context.min_udf = MAX(context.min_udf, 0x0250);
   4457   1.1   reinoud 	if (format_flags & FORMAT_LOW)
   4458   1.1   reinoud 		context.min_udf = MAX(context.min_udf, 0x0260);
   4459   1.1   reinoud 
   4460   1.1   reinoud 	/* adjust maximum version limits not to tease or break things */
   4461   1.1   reinoud 	if (!(format_flags & (FORMAT_META | FORMAT_LOW | FORMAT_VAT)) &&
   4462   1.1   reinoud 	    (context.max_udf > 0x200))
   4463   1.1   reinoud 		context.max_udf = 0x201;
   4464   1.1   reinoud 
   4465   1.1   reinoud 	if ((format_flags & (FORMAT_VAT | FORMAT_SPAREABLE)) == 0)
   4466   1.1   reinoud 		if (context.max_udf <= 0x150)
   4467   1.1   reinoud 			context.min_udf = 0x102;
   4468   1.1   reinoud 
   4469   1.1   reinoud 	/* limit Ecma 167 descriptor if possible/needed */
   4470   1.1   reinoud 	context.dscrver = 3;
   4471   1.1   reinoud 	if ((context.min_udf < 0x200) || (context.max_udf < 0x200)) {
   4472   1.1   reinoud 		context.dscrver = 2;
   4473   1.1   reinoud 		context.max_udf = 0x150;	/* last version < 0x200 */
   4474   1.1   reinoud 	}
   4475   1.1   reinoud 
   4476   1.1   reinoud 	/* is it possible ? */
   4477   1.1   reinoud 	if (context.min_udf > context.max_udf) {
   4478   1.1   reinoud 		warnx("initialisation prohibited by specified maximum "
   4479   1.1   reinoud 		    "UDF version 0x%04x. Minimum version required 0x%04x",
   4480   1.1   reinoud 		    context.max_udf, context.min_udf);
   4481   1.1   reinoud 		return EPERM;
   4482   1.1   reinoud 	}
   4483   1.1   reinoud 
   4484   1.1   reinoud 	if (!UDF_VERSION(context.min_udf) || !UDF_VERSION(context.max_udf)) {
   4485   1.1   reinoud 		warnx("internal error, invalid min/max udf versionsi in %s",
   4486   1.1   reinoud 			__func__);
   4487   1.1   reinoud 		return EPERM;
   4488   1.1   reinoud 	}
   4489   1.1   reinoud 	context.format_flags = format_flags;
   4490   1.1   reinoud 	context.media_accesstype = media_accesstype;
   4491   1.1   reinoud 
   4492   1.1   reinoud 	return 0;
   4493   1.1   reinoud }
   4494   1.1   reinoud 
   4495   1.1   reinoud #undef UDF_VERSION
   4496   1.1   reinoud 
   4497   1.1   reinoud 
   4498   1.1   reinoud /* --------------------------------------------------------------------- */
   4499   1.1   reinoud 
   4500   1.1   reinoud int
   4501   1.1   reinoud udf_proces_names(void)
   4502   1.1   reinoud {
   4503   1.1   reinoud 	struct timeval time_of_day;
   4504   1.1   reinoud 	uint32_t primary_nr;
   4505   1.1   reinoud 	uint64_t volset_nr;
   4506   1.1   reinoud 
   4507   1.1   reinoud 	if (context.logvol_name == NULL)
   4508   1.1   reinoud 		context.logvol_name = strdup("anonymous");
   4509   1.1   reinoud 	if (context.primary_name == NULL) {
   4510   1.1   reinoud 		if (mmc_discinfo.disc_flags & MMC_DFLAGS_DISCIDVALID) {
   4511   1.1   reinoud 			primary_nr = mmc_discinfo.disc_id;
   4512   1.1   reinoud 		} else {
   4513   1.1   reinoud 			primary_nr = (uint32_t) random();
   4514   1.1   reinoud 		}
   4515   1.1   reinoud 		context.primary_name = calloc(32, 1);
   4516   1.1   reinoud 		sprintf(context.primary_name, "%08"PRIx32, primary_nr);
   4517   1.1   reinoud 	}
   4518   1.1   reinoud 	if (context.volset_name == NULL) {
   4519   1.1   reinoud 		if (mmc_discinfo.disc_flags & MMC_DFLAGS_BARCODEVALID) {
   4520   1.1   reinoud 			volset_nr = mmc_discinfo.disc_barcode;
   4521   1.1   reinoud 		} else {
   4522   1.1   reinoud 			(void)gettimeofday(&time_of_day, NULL);
   4523   1.1   reinoud 			volset_nr  =  (uint64_t) random();
   4524   1.1   reinoud 			volset_nr |= ((uint64_t) time_of_day.tv_sec) << 32;
   4525   1.1   reinoud 		}
   4526   1.1   reinoud 		context.volset_name = calloc(128,1);
   4527   1.1   reinoud 		sprintf(context.volset_name, "%016"PRIx64, volset_nr);
   4528   1.1   reinoud 	}
   4529   1.1   reinoud 	if (context.fileset_name == NULL)
   4530   1.1   reinoud 		context.fileset_name = strdup("anonymous");
   4531   1.1   reinoud 
   4532   1.1   reinoud 	/* check passed/created identifiers */
   4533   1.1   reinoud 	if (strlen(context.logvol_name)  > 128) {
   4534   1.1   reinoud 		warnx("logical volume name too long");
   4535   1.1   reinoud 		return EINVAL;
   4536   1.1   reinoud 	}
   4537   1.1   reinoud 	if (strlen(context.primary_name) >  32) {
   4538   1.1   reinoud 		warnx("primary volume name too long");
   4539   1.1   reinoud 		return EINVAL;
   4540   1.1   reinoud 	}
   4541   1.1   reinoud 	if (strlen(context.volset_name)  > 128) {
   4542   1.1   reinoud 		warnx("volume set name too long");
   4543   1.1   reinoud 		return EINVAL;
   4544   1.1   reinoud 	}
   4545   1.1   reinoud 	if (strlen(context.fileset_name) > 32) {
   4546   1.1   reinoud 		warnx("fileset name too long");
   4547   1.1   reinoud 		return EINVAL;
   4548   1.1   reinoud 	}
   4549   1.1   reinoud 
   4550   1.1   reinoud 	/* signal all OK */
   4551   1.1   reinoud 	return 0;
   4552   1.1   reinoud }
   4553   1.1   reinoud 
   4554   1.1   reinoud /* --------------------------------------------------------------------- */
   4555   1.1   reinoud 
   4556   1.1   reinoud int
   4557   1.1   reinoud udf_write_iso9660_vrs(void)
   4558   1.1   reinoud {
   4559   1.1   reinoud 	struct vrs_desc *iso9660_vrs_desc;
   4560   1.1   reinoud 	uint32_t pos;
   4561   1.1   reinoud 	int error, cnt, dpos;
   4562   1.1   reinoud 
   4563   1.1   reinoud 	/* create ISO/Ecma-167 identification descriptors */
   4564   1.1   reinoud 	if ((iso9660_vrs_desc = calloc(1, context.sector_size)) == NULL)
   4565   1.1   reinoud 		return ENOMEM;
   4566   1.1   reinoud 
   4567   1.1   reinoud 	/*
   4568   1.1   reinoud 	 * All UDF formats should have their ISO/Ecma-167 descriptors written
   4569   1.1   reinoud 	 * except when not possible due to track reservation in the case of
   4570   1.1   reinoud 	 * VAT
   4571   1.1   reinoud 	 */
   4572   1.1   reinoud 	if ((context.format_flags & FORMAT_TRACK512) == 0) {
   4573   1.1   reinoud 		dpos = (2048 + context.sector_size - 1) / context.sector_size;
   4574   1.1   reinoud 
   4575   1.1   reinoud 		/* wipe at least 6 times 2048 byte `sectors' */
   4576   1.1   reinoud 		for (cnt = 0; cnt < 6 *dpos; cnt++) {
   4577   1.1   reinoud 			pos = layout.iso9660_vrs + cnt;
   4578   1.1   reinoud 			if ((error = udf_write_sector(iso9660_vrs_desc, pos))) {
   4579   1.1   reinoud 				free(iso9660_vrs_desc);
   4580   1.1   reinoud 				return error;
   4581   1.1   reinoud 			}
   4582   1.1   reinoud 		}
   4583   1.1   reinoud 
   4584   1.1   reinoud 		/* common VRS fields in all written out ISO descriptors */
   4585   1.1   reinoud 		iso9660_vrs_desc->struct_type = 0;
   4586   1.1   reinoud 		iso9660_vrs_desc->version     = 1;
   4587   1.1   reinoud 		pos = layout.iso9660_vrs;
   4588   1.1   reinoud 
   4589   1.1   reinoud 		/* BEA01, NSR[23], TEA01 */
   4590   1.1   reinoud 		memcpy(iso9660_vrs_desc->identifier, "BEA01", 5);
   4591   1.1   reinoud 		if ((error = udf_write_sector(iso9660_vrs_desc, pos))) {
   4592   1.1   reinoud 			free(iso9660_vrs_desc);
   4593   1.1   reinoud 			return error;
   4594   1.1   reinoud 		}
   4595   1.1   reinoud 		pos += dpos;
   4596   1.1   reinoud 
   4597   1.1   reinoud 		if (context.dscrver == 2)
   4598   1.1   reinoud 			memcpy(iso9660_vrs_desc->identifier, "NSR02", 5);
   4599   1.1   reinoud 		else
   4600   1.1   reinoud 			memcpy(iso9660_vrs_desc->identifier, "NSR03", 5);
   4601   1.1   reinoud 		;
   4602   1.1   reinoud 		if ((error = udf_write_sector(iso9660_vrs_desc, pos))) {
   4603   1.1   reinoud 			free(iso9660_vrs_desc);
   4604   1.1   reinoud 			return error;
   4605   1.1   reinoud 		}
   4606   1.1   reinoud 		pos += dpos;
   4607   1.1   reinoud 
   4608   1.1   reinoud 		memcpy(iso9660_vrs_desc->identifier, "TEA01", 5);
   4609   1.1   reinoud 		if ((error = udf_write_sector(iso9660_vrs_desc, pos))) {
   4610   1.1   reinoud 			free(iso9660_vrs_desc);
   4611   1.1   reinoud 			return error;
   4612   1.1   reinoud 		}
   4613   1.1   reinoud 	}
   4614   1.1   reinoud 
   4615   1.1   reinoud 	free(iso9660_vrs_desc);
   4616   1.1   reinoud 	/* return success */
   4617   1.1   reinoud 	return 0;
   4618   1.1   reinoud }
   4619   1.1   reinoud 
   4620   1.1   reinoud 
   4621   1.1   reinoud /* --------------------------------------------------------------------- */
   4622   1.1   reinoud 
   4623   1.1   reinoud int
   4624   1.1   reinoud udf_get_blockingnr(struct mmc_trackinfo *ti)
   4625   1.1   reinoud {
   4626   1.1   reinoud 	int blockingnr;
   4627   1.1   reinoud 
   4628   1.1   reinoud 	/* determine blockingnr */
   4629   1.1   reinoud 	blockingnr = ti->packet_size;
   4630   1.1   reinoud 	if (blockingnr <= 1) {
   4631   1.1   reinoud 		/* paranoia on blockingnr */
   4632   1.1   reinoud 		switch (mmc_discinfo.mmc_profile) {
   4633   1.1   reinoud 		case 0x01 : /* DISC */
   4634   1.1   reinoud 			blockingnr = 64;
   4635   1.1   reinoud 			break;
   4636   1.1   reinoud 		case 0x08 : /* CDROM */
   4637   1.1   reinoud 		case 0x09 : /* CD-R    */
   4638   1.1   reinoud 		case 0x0a : /* CD-RW   */
   4639   1.1   reinoud 			blockingnr = 32;	/* UDF requirement */
   4640   1.1   reinoud 			break;
   4641   1.1   reinoud 		case 0x10 : /* DVDROM */
   4642   1.1   reinoud 		case 0x11 : /* DVD-R (DL) */
   4643   1.1   reinoud 		case 0x12 : /* DVD-RAM */
   4644   1.1   reinoud 		case 0x1b : /* DVD+R      */
   4645   1.1   reinoud 		case 0x2b : /* DVD+R Dual layer */
   4646   1.1   reinoud 		case 0x13 : /* DVD-RW restricted overwrite */
   4647   1.1   reinoud 		case 0x14 : /* DVD-RW sequential */
   4648   1.1   reinoud 		case 0x1a : /* DVD+RW */
   4649   1.1   reinoud 			blockingnr = 16;	/* SCSI definition */
   4650   1.1   reinoud 			break;
   4651   1.1   reinoud 		case 0x40 : /* BDROM */
   4652   1.1   reinoud 		case 0x41 : /* BD-R Sequential recording (SRM) */
   4653   1.1   reinoud 		case 0x42 : /* BD-R Random recording (RRM) */
   4654   1.1   reinoud 		case 0x43 : /* BD-RE */
   4655   1.1   reinoud 		case 0x51 : /* HD DVD-R   */
   4656   1.1   reinoud 		case 0x52 : /* HD DVD-RW  */
   4657   1.1   reinoud 			blockingnr = 32;	/* SCSI definition */
   4658   1.1   reinoud 			break;
   4659   1.1   reinoud 		default:
   4660   1.1   reinoud 			break;
   4661   1.1   reinoud 		}
   4662   1.1   reinoud 	}
   4663   1.1   reinoud 	return blockingnr;
   4664   1.1   reinoud }
   4665   1.1   reinoud 
   4666   1.1   reinoud 
   4667   1.1   reinoud int
   4668   1.1   reinoud udf_spareable_blocks(void)
   4669   1.1   reinoud {
   4670   1.1   reinoud 	if (mmc_discinfo.mmc_class == MMC_CLASS_CD) {
   4671   1.1   reinoud 		/* not too much for CD-RW, still 20MiB */
   4672   1.1   reinoud 		return 32;
   4673   1.1   reinoud 	} else {
   4674   1.1   reinoud 		/* take a value for DVD*RW mainly, BD is `defect free' */
   4675   1.1   reinoud 		return 512;
   4676   1.1   reinoud 	}
   4677   1.1   reinoud }
   4678   1.1   reinoud 
   4679   1.1   reinoud 
   4680   1.1   reinoud int
   4681   1.1   reinoud udf_spareable_blockingnr(void)
   4682   1.1   reinoud {
   4683   1.1   reinoud 	struct mmc_trackinfo ti;
   4684   1.1   reinoud 	int spareable_blockingnr;
   4685   1.1   reinoud 	int error;
   4686   1.1   reinoud 
   4687   1.1   reinoud 	/* determine span/size */
   4688   1.1   reinoud 	ti.tracknr = mmc_discinfo.first_track_last_session;
   4689   1.1   reinoud 	error = udf_update_trackinfo(&ti);
   4690   1.1   reinoud 	spareable_blockingnr = udf_get_blockingnr(&ti);
   4691   1.1   reinoud 	if (error)
   4692   1.1   reinoud 		spareable_blockingnr = 32;
   4693   1.1   reinoud 
   4694   1.1   reinoud 	/*
   4695   1.1   reinoud 	 * Note that for (bug) compatibility with version UDF 2.00
   4696   1.1   reinoud 	 * (fixed in 2.01 and higher) the blocking size needs to be 32
   4697   1.1   reinoud 	 * sectors otherwise the drive's blockingnr.
   4698   1.1   reinoud 	 */
   4699   1.1   reinoud 	if (context.min_udf <= 0x200)
   4700   1.1   reinoud 		spareable_blockingnr = 32;
   4701   1.1   reinoud 	return spareable_blockingnr;
   4702   1.1   reinoud }
   4703   1.1   reinoud 
   4704   1.1   reinoud 
   4705   1.1   reinoud /*
   4706   1.1   reinoud  * Main function that creates and writes out disc contents based on the
   4707   1.1   reinoud  * format_flags's that uniquely define the type of disc to create.
   4708   1.1   reinoud  */
   4709   1.1   reinoud 
   4710   1.1   reinoud int
   4711   1.1   reinoud udf_do_newfs_prefix(void)
   4712   1.1   reinoud {
   4713   1.1   reinoud 	union dscrptr *zero_dscr;
   4714   1.1   reinoud 	union dscrptr *dscr;
   4715   1.1   reinoud 	struct mmc_trackinfo ti;
   4716   1.1   reinoud 	uint32_t blockingnr;
   4717   1.1   reinoud 	uint32_t cnt, loc, len;
   4718   1.1   reinoud 	int sectcopy;
   4719   1.1   reinoud 	int error, integrity_type;
   4720   1.1   reinoud 	int data_part, metadata_part;
   4721   1.1   reinoud 	int format_flags;
   4722   1.1   reinoud 
   4723   1.1   reinoud 	/* init */
   4724   1.1   reinoud 	format_flags = context.format_flags;
   4725   1.1   reinoud 
   4726   1.1   reinoud 	/* determine span/size */
   4727   1.1   reinoud 	ti.tracknr = mmc_discinfo.first_track_last_session;
   4728   1.1   reinoud 	error = udf_update_trackinfo(&ti);
   4729   1.1   reinoud 	if (error)
   4730   1.1   reinoud 		return error;
   4731   1.1   reinoud 
   4732   1.1   reinoud 	if (mmc_discinfo.sector_size > context.sector_size) {
   4733   1.1   reinoud 		warnx("impossible to format: "
   4734   1.1   reinoud 			"sector size %d too small for media sector size %d",
   4735   1.1   reinoud 			context.sector_size, mmc_discinfo.sector_size);
   4736   1.1   reinoud 		return EIO;
   4737   1.1   reinoud 	}
   4738   1.1   reinoud 
   4739   1.1   reinoud 	/* determine blockingnr */
   4740   1.1   reinoud 	blockingnr = udf_get_blockingnr(&ti);
   4741   1.1   reinoud 	if (blockingnr <= 0) {
   4742   1.1   reinoud 		warnx("can't fixup blockingnumber for device "
   4743   1.1   reinoud 			"type %d", mmc_discinfo.mmc_profile);
   4744   1.1   reinoud 		warnx("device is not returning valid blocking"
   4745   1.1   reinoud 			" number and media type is unknown");
   4746   1.1   reinoud 		return EINVAL;
   4747   1.1   reinoud 	}
   4748   1.1   reinoud 
   4749   1.1   reinoud 	wrtrack_skew = 0;
   4750   1.1   reinoud 	if (mmc_discinfo.mmc_cur & MMC_CAP_SEQUENTIAL)
   4751   1.1   reinoud 		wrtrack_skew = ti.next_writable % blockingnr;
   4752   1.1   reinoud 
   4753   1.1   reinoud 	/* get layout */
   4754   1.1   reinoud 	error = udf_calculate_disc_layout(context.min_udf,
   4755   1.1   reinoud 		ti.track_start, mmc_discinfo.last_possible_lba,
   4756   1.1   reinoud 		context.sector_size, blockingnr);
   4757   1.1   reinoud 
   4758   1.1   reinoud 	/* cache partition for we need it often */
   4759   1.1   reinoud 	data_part     = context.data_part;
   4760   1.1   reinoud 	metadata_part = context.metadata_part;
   4761   1.1   reinoud 
   4762   1.1   reinoud 	/* Create sparing table descriptor if applicable */
   4763   1.1   reinoud 	if (format_flags & FORMAT_SPAREABLE) {
   4764   1.1   reinoud 		if ((error = udf_create_sparing_tabled()))
   4765   1.1   reinoud 			return error;
   4766   1.1   reinoud 
   4767   1.1   reinoud 		if (context.check_surface) {
   4768   1.1   reinoud 			if ((error = udf_surface_check()))
   4769   1.1   reinoud 				return error;
   4770   1.1   reinoud 		}
   4771   1.1   reinoud 	}
   4772   1.1   reinoud 
   4773   1.1   reinoud 	/* Create a generic terminator descriptor (later reused) */
   4774   1.1   reinoud 	terminator_dscr = calloc(1, context.sector_size);
   4775   1.1   reinoud 	if (terminator_dscr == NULL)
   4776   1.1   reinoud 		return ENOMEM;
   4777   1.1   reinoud 	udf_create_terminator(terminator_dscr, 0);
   4778   1.1   reinoud 
   4779   1.2  riastrad 	/*
   4780   1.1   reinoud 	 * Create the two Volume Descriptor Sets (VDS) each containing the
   4781   1.1   reinoud 	 * following descriptors : primary volume, partition space,
   4782   1.1   reinoud 	 * unallocated space, logical volume, implementation use and the
   4783   1.1   reinoud 	 * terminator
   4784   1.1   reinoud 	 */
   4785   1.1   reinoud 
   4786   1.1   reinoud 	/* start of volume recognition sequence building */
   4787   1.1   reinoud 	context.vds_seq = 0;
   4788   1.1   reinoud 
   4789   1.1   reinoud 	/* Create primary volume descriptor */
   4790   1.1   reinoud 	if ((error = udf_create_primaryd()))
   4791   1.1   reinoud 		return error;
   4792   1.1   reinoud 
   4793   1.1   reinoud 	/* Create partition descriptor */
   4794   1.1   reinoud 	if ((error = udf_create_partitiond(context.data_part)))
   4795   1.1   reinoud 		return error;
   4796   1.1   reinoud 
   4797   1.1   reinoud 	/* Create unallocated space descriptor */
   4798   1.1   reinoud 	if ((error = udf_create_unalloc_spaced()))
   4799   1.1   reinoud 		return error;
   4800   1.1   reinoud 
   4801   1.1   reinoud 	/* Create logical volume descriptor */
   4802   1.1   reinoud 	if ((error = udf_create_logical_dscr()))
   4803   1.1   reinoud 		return error;
   4804   1.1   reinoud 
   4805   1.1   reinoud 	/* Create implementation use descriptor */
   4806   1.1   reinoud 	/* TODO input of fields 1,2,3 and passing them */
   4807   1.1   reinoud 	if ((error = udf_create_impvold(NULL, NULL, NULL)))
   4808   1.1   reinoud 		return error;
   4809   1.1   reinoud 
   4810   1.1   reinoud 	/* Create anchors */
   4811   1.1   reinoud 	for (cnt = 0; cnt < 3; cnt++) {
   4812   1.1   reinoud 		if ((error = udf_create_anchor(cnt))) {
   4813   1.1   reinoud 			return error;
   4814   1.1   reinoud 		}
   4815   1.1   reinoud 	}
   4816   1.1   reinoud 
   4817   1.1   reinoud 	/*
   4818   1.1   reinoud 	 * Write out what we've created so far.
   4819   1.1   reinoud 	 *
   4820   1.1   reinoud 	 * Start with wipeout of VRS1 upto start of partition. This allows
   4821   1.2  riastrad 	 * formatting for sequentials with the track reservation and it
   4822   1.1   reinoud 	 * cleans old rubbish on rewritables. For sequentials without the
   4823   1.1   reinoud 	 * track reservation all is wiped from track start.
   4824   1.1   reinoud 	 */
   4825   1.1   reinoud 	if ((zero_dscr = calloc(1, context.sector_size)) == NULL)
   4826   1.1   reinoud 		return ENOMEM;
   4827   1.1   reinoud 
   4828   1.1   reinoud 	loc = (format_flags & FORMAT_TRACK512) ? layout.vds1 : ti.track_start;
   4829   1.1   reinoud 	for (; loc < layout.part_start_lba; loc++) {
   4830   1.1   reinoud 		if ((error = udf_write_sector(zero_dscr, loc))) {
   4831   1.1   reinoud 			free(zero_dscr);
   4832   1.1   reinoud 			return error;
   4833   1.1   reinoud 		}
   4834   1.1   reinoud 	}
   4835   1.1   reinoud 	free(zero_dscr);
   4836   1.1   reinoud 
   4837   1.1   reinoud 	/* writeout iso9660 vrs */
   4838   1.1   reinoud 	if ((error = udf_write_iso9660_vrs()))
   4839   1.1   reinoud 		return error;
   4840   1.1   reinoud 
   4841   1.1   reinoud 	/* Writeout anchors */
   4842   1.1   reinoud 	for (cnt = 0; cnt < 3; cnt++) {
   4843   1.1   reinoud 		dscr = (union dscrptr *) context.anchors[cnt];
   4844   1.1   reinoud 		loc  = layout.anchors[cnt];
   4845   1.1   reinoud 		if ((error = udf_write_dscr_phys(dscr, loc, 1))) {
   4846   1.1   reinoud 			err(1, "ERR!");
   4847   1.1   reinoud 			return error;
   4848   1.1   reinoud 		}
   4849   1.1   reinoud 
   4850   1.1   reinoud 		/* sequential media has only one anchor */
   4851   1.1   reinoud 		if (format_flags & FORMAT_SEQUENTIAL)
   4852   1.1   reinoud 			break;
   4853   1.1   reinoud 	}
   4854   1.1   reinoud 
   4855   1.1   reinoud 	/* write out main and secondary VRS */
   4856   1.1   reinoud 	for (sectcopy = 1; sectcopy <= 2; sectcopy++) {
   4857   1.1   reinoud 		loc = (sectcopy == 1) ? layout.vds1 : layout.vds2;
   4858   1.1   reinoud 
   4859   1.1   reinoud 		/* primary volume descriptor */
   4860   1.1   reinoud 		dscr = (union dscrptr *) context.primary_vol;
   4861   1.1   reinoud 		error = udf_write_dscr_phys(dscr, loc, 1);
   4862   1.1   reinoud 		if (error)
   4863   1.1   reinoud 			return error;
   4864   1.1   reinoud 		loc++;
   4865   1.1   reinoud 
   4866   1.1   reinoud 		/* partition descriptor(s) */
   4867   1.1   reinoud 		for (cnt = 0; cnt < UDF_PARTITIONS; cnt++) {
   4868   1.1   reinoud 			dscr = (union dscrptr *) context.partitions[cnt];
   4869   1.1   reinoud 			if (dscr) {
   4870   1.1   reinoud 				error = udf_write_dscr_phys(dscr, loc, 1);
   4871   1.1   reinoud 				if (error)
   4872   1.1   reinoud 					return error;
   4873   1.1   reinoud 				loc++;
   4874   1.1   reinoud 			}
   4875   1.1   reinoud 		}
   4876   1.1   reinoud 
   4877   1.1   reinoud 		/* unallocated space descriptor */
   4878   1.1   reinoud 		dscr = (union dscrptr *) context.unallocated;
   4879   1.1   reinoud 		error = udf_write_dscr_phys(dscr, loc, 1);
   4880   1.1   reinoud 		if (error)
   4881   1.1   reinoud 			return error;
   4882   1.1   reinoud 		loc++;
   4883   1.1   reinoud 
   4884   1.1   reinoud 		/* logical volume descriptor */
   4885   1.1   reinoud 		dscr = (union dscrptr *) context.logical_vol;
   4886   1.1   reinoud 		error = udf_write_dscr_phys(dscr, loc, 1);
   4887   1.1   reinoud 		if (error)
   4888   1.1   reinoud 			return error;
   4889   1.1   reinoud 		loc++;
   4890   1.1   reinoud 
   4891   1.1   reinoud 		/* implementation use descriptor */
   4892   1.1   reinoud 		dscr = (union dscrptr *) context.implementation;
   4893   1.1   reinoud 		error = udf_write_dscr_phys(dscr, loc, 1);
   4894   1.1   reinoud 		if (error)
   4895   1.1   reinoud 			return error;
   4896   1.1   reinoud 		loc++;
   4897   1.1   reinoud 
   4898   1.1   reinoud 		/* terminator descriptor */
   4899   1.1   reinoud 		error = udf_write_dscr_phys(terminator_dscr, loc, 1);
   4900   1.1   reinoud 		if (error)
   4901   1.1   reinoud 			return error;
   4902   1.1   reinoud 		loc++;
   4903   1.1   reinoud 	}
   4904   1.1   reinoud 
   4905   1.1   reinoud 	/* writeout the two spareable table descriptors (if needed) */
   4906   1.1   reinoud 	if (format_flags & FORMAT_SPAREABLE) {
   4907   1.1   reinoud 		for (sectcopy = 1; sectcopy <= 2; sectcopy++) {
   4908   1.1   reinoud 			loc  = (sectcopy == 1) ? layout.spt_1 : layout.spt_2;
   4909   1.1   reinoud 			dscr = (union dscrptr *) context.sparing_table;
   4910   1.1   reinoud 			len  = udf_tagsize(dscr, context.sector_size) /
   4911   1.1   reinoud 					context.sector_size;
   4912   1.1   reinoud 
   4913   1.1   reinoud 			/* writeout */
   4914   1.1   reinoud 			error = udf_write_dscr_phys(dscr, loc, len);
   4915   1.1   reinoud 			if (error)
   4916   1.1   reinoud 				return error;
   4917   1.1   reinoud 		}
   4918   1.1   reinoud 	}
   4919   1.1   reinoud 
   4920   1.1   reinoud 	/*
   4921   1.1   reinoud 	 * Create unallocated space bitmap descriptor. Sequential recorded
   4922   1.1   reinoud 	 * media report their own free/used space; no free/used space tables
   4923   1.1   reinoud 	 * should be recorded for these.
   4924   1.1   reinoud 	 */
   4925   1.1   reinoud 	if ((format_flags & (FORMAT_SEQUENTIAL | FORMAT_READONLY)) == 0) {
   4926   1.1   reinoud 		error = udf_create_space_bitmap(
   4927   1.1   reinoud 				layout.alloc_bitmap_dscr_size,
   4928   1.1   reinoud 				layout.part_size_lba,
   4929   1.1   reinoud 				&context.part_unalloc_bits[data_part]);
   4930   1.1   reinoud 		if (error)
   4931   1.1   reinoud 			return error;
   4932   1.1   reinoud 		/* TODO: freed space bitmap if applicable */
   4933   1.1   reinoud 
   4934   1.1   reinoud 		/* mark space allocated for the unallocated space bitmap */
   4935   1.1   reinoud 		udf_mark_allocated(layout.unalloc_space, data_part,
   4936   1.1   reinoud 			layout.alloc_bitmap_dscr_size);
   4937   1.1   reinoud 	}
   4938   1.1   reinoud 
   4939   1.1   reinoud 	/*
   4940   1.1   reinoud 	 * Create metadata partition file entries and allocate and init their
   4941   1.1   reinoud 	 * space and free space maps.
   4942   1.1   reinoud 	 */
   4943   1.1   reinoud 	if (format_flags & FORMAT_META) {
   4944   1.1   reinoud 		error = udf_create_meta_files();
   4945   1.1   reinoud 		if (error)
   4946   1.1   reinoud 			return error;
   4947   1.1   reinoud 
   4948   1.1   reinoud 		/* mark space allocated for meta partition and its bitmap */
   4949   1.1   reinoud 		udf_mark_allocated(layout.meta_file,   data_part, 1);
   4950   1.1   reinoud 		udf_mark_allocated(layout.meta_mirror, data_part, 1);
   4951   1.1   reinoud 		udf_mark_allocated(layout.meta_part_start_lba, data_part,
   4952   1.1   reinoud 			layout.meta_part_size_lba);
   4953   1.1   reinoud 
   4954   1.1   reinoud 		if (context.meta_bitmap) {
   4955   1.1   reinoud 			/* metadata bitmap creation and accounting */
   4956   1.1   reinoud 			error = udf_create_space_bitmap(
   4957   1.1   reinoud 					layout.meta_bitmap_dscr_size,
   4958   1.1   reinoud 					layout.meta_part_size_lba,
   4959   1.1   reinoud 					&context.part_unalloc_bits[metadata_part]);
   4960   1.1   reinoud 			if (error)
   4961   1.1   reinoud 				return error;
   4962   1.2  riastrad 
   4963   1.1   reinoud 			udf_mark_allocated(layout.meta_bitmap, data_part, 1);
   4964   1.1   reinoud 			/* mark space allocated for the unallocated space bitmap */
   4965   1.1   reinoud 			udf_mark_allocated(layout.meta_bitmap_space,
   4966   1.1   reinoud 					data_part,
   4967   1.1   reinoud 				layout.meta_bitmap_dscr_size);
   4968   1.1   reinoud 		}
   4969   1.1   reinoud 	}
   4970   1.1   reinoud 
   4971   1.1   reinoud 	/* create logical volume integrity descriptor */
   4972   1.1   reinoud 	context.num_files = 0;
   4973   1.1   reinoud 	context.num_directories = 0;
   4974   1.1   reinoud 	integrity_type = UDF_INTEGRITY_OPEN;
   4975   1.1   reinoud 	if ((error = udf_create_lvintd(integrity_type)))
   4976   1.1   reinoud 		return error;
   4977   1.1   reinoud 
   4978   1.1   reinoud 	/* writeout initial open integrity sequence + terminator */
   4979   1.1   reinoud 	loc = layout.lvis;
   4980   1.1   reinoud 	dscr = (union dscrptr *) context.logvol_integrity;
   4981   1.1   reinoud 	error = udf_write_dscr_phys(dscr, loc, 1);
   4982   1.1   reinoud 	if (error)
   4983   1.1   reinoud 		return error;
   4984   1.1   reinoud 	loc++;
   4985   1.1   reinoud 	error = udf_write_dscr_phys(terminator_dscr, loc, 1);
   4986   1.1   reinoud 	if (error)
   4987   1.1   reinoud 		return error;
   4988   1.1   reinoud 
   4989   1.1   reinoud 	/* create VAT if needed */
   4990   1.1   reinoud 	if (format_flags & FORMAT_VAT) {
   4991   1.1   reinoud 		context.vat_allocated = context.sector_size;
   4992   1.1   reinoud 		context.vat_contents  = malloc(context.vat_allocated);
   4993   1.1   reinoud 		assert(context.vat_contents);
   4994   1.1   reinoud 
   4995   1.1   reinoud 		udf_prepend_VAT_file();
   4996   1.1   reinoud 	}
   4997   1.1   reinoud 
   4998   1.1   reinoud 	/* create FSD and writeout */
   4999   1.1   reinoud 	if ((error = udf_create_fsd()))
   5000   1.1   reinoud 		return error;
   5001   1.1   reinoud 	udf_mark_allocated(layout.fsd, metadata_part, 1);
   5002   1.1   reinoud 
   5003   1.1   reinoud 	dscr = (union dscrptr *) context.fileset_desc;
   5004   1.1   reinoud 	error = udf_write_dscr_virt(dscr, layout.fsd, metadata_part, 1);
   5005   1.1   reinoud 
   5006   1.1   reinoud 	return error;
   5007   1.1   reinoud }
   5008   1.1   reinoud 
   5009   1.1   reinoud 
   5010   1.1   reinoud /* specific routine for newfs to create empty rootdirectory */
   5011   1.1   reinoud int
   5012   1.1   reinoud udf_do_rootdir(void)
   5013   1.1   reinoud {
   5014   1.1   reinoud 	union dscrptr *root_dscr;
   5015   1.1   reinoud 	int error;
   5016   1.1   reinoud 
   5017   1.1   reinoud 	/* create root directory and write out */
   5018   1.1   reinoud 	assert(context.unique_id == 0x10);
   5019   1.1   reinoud 	context.unique_id = 0;
   5020   1.1   reinoud 	if ((error = udf_create_new_rootdir(&root_dscr)))
   5021   1.1   reinoud 		return error;
   5022   1.1   reinoud 	udf_mark_allocated(layout.rootdir, context.metadata_part, 1);
   5023   1.1   reinoud 
   5024   1.1   reinoud 	error = udf_write_dscr_virt(root_dscr,
   5025   1.1   reinoud 		layout.rootdir, context.metadata_part, 1);
   5026   1.1   reinoud 
   5027   1.1   reinoud 	free(root_dscr);
   5028   1.1   reinoud 
   5029   1.1   reinoud 	return error;
   5030   1.1   reinoud }
   5031   1.1   reinoud 
   5032   1.1   reinoud 
   5033   1.1   reinoud int
   5034   1.1   reinoud udf_do_newfs_postfix(void)
   5035   1.1   reinoud {
   5036   1.1   reinoud 	union dscrptr *dscr;
   5037   1.1   reinoud 	uint32_t loc, len;
   5038   1.1   reinoud 	int data_part, metadata_part;
   5039   1.1   reinoud 	int format_flags = context.format_flags;
   5040   1.1   reinoud 	int error;
   5041   1.1   reinoud 
   5042   1.1   reinoud 	/* cache partition for we need it often */
   5043   1.1   reinoud 	data_part     = context.data_part;
   5044   1.1   reinoud 	metadata_part = context.metadata_part;
   5045   1.1   reinoud 
   5046   1.1   reinoud 	if ((format_flags & FORMAT_SEQUENTIAL) == 0) {
   5047   1.1   reinoud 		/* update lvint and mark it closed */
   5048   1.1   reinoud 		udf_update_lvintd(UDF_INTEGRITY_CLOSED);
   5049   1.1   reinoud 
   5050   1.1   reinoud 		/* overwrite initial terminator */
   5051   1.1   reinoud 		loc = layout.lvis+1;
   5052   1.1   reinoud 		dscr = (union dscrptr *) context.logvol_integrity;
   5053   1.1   reinoud 		error = udf_write_dscr_phys(dscr, loc, 1);
   5054   1.1   reinoud 		if (error)
   5055   1.1   reinoud 			return error;
   5056   1.1   reinoud 		loc++;
   5057   1.1   reinoud 
   5058   1.1   reinoud 		/* mark end of integrity descriptor sequence again */
   5059   1.1   reinoud 		error = udf_write_dscr_phys(terminator_dscr, loc, 1);
   5060   1.1   reinoud 		if (error)
   5061   1.1   reinoud 			return error;
   5062   1.1   reinoud 	}
   5063   1.1   reinoud 
   5064   1.1   reinoud 	/* write out unallocated space bitmap on non sequential media */
   5065   1.1   reinoud 	if ((format_flags & (FORMAT_SEQUENTIAL | FORMAT_READONLY)) == 0) {
   5066   1.1   reinoud 		/* writeout unallocated space bitmap */
   5067   1.1   reinoud 		loc  = layout.unalloc_space;
   5068   1.1   reinoud 		dscr = (union dscrptr *) (context.part_unalloc_bits[data_part]);
   5069   1.1   reinoud 		len  = layout.alloc_bitmap_dscr_size;
   5070   1.1   reinoud 		error = udf_write_dscr_virt(dscr, loc, data_part, len);
   5071   1.1   reinoud 		if (error)
   5072   1.1   reinoud 			return error;
   5073   1.1   reinoud 	}
   5074   1.1   reinoud 
   5075   1.1   reinoud 	if (format_flags & FORMAT_META) {
   5076   1.1   reinoud 		loc = layout.meta_file;
   5077   1.1   reinoud 		dscr = (union dscrptr *) context.meta_file;
   5078   1.1   reinoud 		error = udf_write_dscr_virt(dscr, loc, data_part, 1);
   5079   1.1   reinoud 		if (error)
   5080   1.1   reinoud 			return error;
   5081   1.2  riastrad 
   5082   1.1   reinoud 		loc = layout.meta_mirror;
   5083   1.1   reinoud 		dscr = (union dscrptr *) context.meta_mirror;
   5084   1.1   reinoud 		error = udf_write_dscr_virt(dscr, loc, data_part, 1);
   5085   1.1   reinoud 		if (error)
   5086   1.1   reinoud 			return error;
   5087   1.1   reinoud 
   5088   1.1   reinoud 		if (context.meta_bitmap) {
   5089   1.1   reinoud 			loc = layout.meta_bitmap;
   5090   1.1   reinoud 			dscr = (union dscrptr *) context.meta_bitmap;
   5091   1.1   reinoud 			error = udf_write_dscr_virt(dscr, loc, data_part, 1);
   5092   1.1   reinoud 			if (error)
   5093   1.1   reinoud 				return error;
   5094   1.1   reinoud 
   5095   1.1   reinoud 			/* writeout unallocated space bitmap */
   5096   1.1   reinoud 			loc  = layout.meta_bitmap_space;
   5097   1.1   reinoud 			dscr = (union dscrptr *)
   5098   1.1   reinoud 				(context.part_unalloc_bits[metadata_part]);
   5099   1.1   reinoud 			len  = layout.meta_bitmap_dscr_size;
   5100   1.1   reinoud 			error = udf_write_dscr_virt(dscr, loc, data_part, len);
   5101   1.1   reinoud 			if (error)
   5102   1.1   reinoud 				return error;
   5103   1.1   reinoud 		}
   5104   1.1   reinoud 	}
   5105   1.1   reinoud 
   5106   1.1   reinoud 	/* create and writeout a VAT */
   5107   1.1   reinoud 	if (format_flags & FORMAT_VAT)
   5108   1.1   reinoud 		udf_writeout_VAT();
   5109   1.1   reinoud 
   5110   1.1   reinoud 	/* done */
   5111   1.1   reinoud 	return 0;
   5112   1.1   reinoud }
   5113