[BACK]Return to udf_core.c CVS log [TXT][DIR] Up to [cvs.NetBSD.org] / src / sbin / newfs_udf

Annotation of src/sbin/newfs_udf/udf_core.c, Revision 1.4

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

CVSweb <webmaster@jp.NetBSD.org>