[BACK]Return to udf_subr.c CVS log [TXT][DIR] Up to [cvs.NetBSD.org] / src / sys / fs / udf

Annotation of src/sys/fs/udf/udf_subr.c, Revision 1.166

1.166   ! andvar      1: /* $NetBSD: udf_subr.c,v 1.165 2022/01/25 22:01:35 andvar Exp $ */
1.1       reinoud     2:
                      3: /*
1.45      reinoud     4:  * Copyright (c) 2006, 2008 Reinoud Zandijk
1.1       reinoud     5:  * All rights reserved.
1.152     skrll       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.152     skrll      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.152     skrll      26:  *
1.1       reinoud    27:  */
                     28:
                     29:
                     30: #include <sys/cdefs.h>
                     31: #ifndef lint
1.166   ! andvar     32: __KERNEL_RCSID(0, "$NetBSD: udf_subr.c,v 1.165 2022/01/25 22:01:35 andvar Exp $");
1.1       reinoud    33: #endif /* not lint */
                     34:
                     35:
                     36: #if defined(_KERNEL_OPT)
                     37: #include "opt_compat_netbsd.h"
                     38: #endif
                     39:
                     40: #include <sys/param.h>
                     41: #include <sys/systm.h>
                     42: #include <sys/sysctl.h>
                     43: #include <sys/namei.h>
                     44: #include <sys/proc.h>
                     45: #include <sys/kernel.h>
                     46: #include <sys/vnode.h>
                     47: #include <miscfs/genfs/genfs_node.h>
                     48: #include <sys/mount.h>
                     49: #include <sys/buf.h>
                     50: #include <sys/file.h>
                     51: #include <sys/device.h>
                     52: #include <sys/disklabel.h>
                     53: #include <sys/ioctl.h>
                     54: #include <sys/malloc.h>
                     55: #include <sys/dirent.h>
                     56: #include <sys/stat.h>
                     57: #include <sys/conf.h>
1.8       christos   58: #include <sys/kauth.h>
1.48      reinoud    59: #include <fs/unicode.h>
1.30      reinoud    60: #include <dev/clock_subr.h>
1.1       reinoud    61:
                     62: #include <fs/udf/ecma167-udf.h>
                     63: #include <fs/udf/udf_mount.h>
1.73      reinoud    64: #include <sys/dirhash.h>
1.1       reinoud    65:
                     66: #include "udf.h"
                     67: #include "udf_subr.h"
                     68: #include "udf_bswap.h"
                     69:
                     70:
1.45      reinoud    71: #define VTOI(vnode) ((struct udf_node *) (vnode)->v_data)
                     72:
                     73: #define UDF_SET_SYSTEMFILE(vp) \
                     74:        /* XXXAD Is the vnode locked? */        \
                     75:        (vp)->v_vflag |= VV_SYSTEM;             \
1.109     reinoud    76:        vref((vp));                     \
                     77:        vput((vp));                     \
1.1       reinoud    78:
1.45      reinoud    79: extern int syncer_maxdelay;     /* maximum delay time */
                     80: extern int (**udf_vnodeop_p)(void *);
1.1       reinoud    81:
1.45      reinoud    82: /* --------------------------------------------------------------------- */
1.1       reinoud    83:
1.45      reinoud    84: //#ifdef DEBUG
                     85: #if 1
1.1       reinoud    86:
                     87: #if 0
1.45      reinoud    88: static void
                     89: udf_dumpblob(boid *blob, uint32_t dlen)
1.1       reinoud    90: {
1.45      reinoud    91:        int i, j;
1.1       reinoud    92:
                     93:        printf("blob = %p\n", blob);
                     94:        printf("dump of %d bytes\n", dlen);
                     95:
                     96:        for (i = 0; i < dlen; i+ = 16) {
                     97:                printf("%04x ", i);
                     98:                for (j = 0; j < 16; j++) {
                     99:                        if (i+j < dlen) {
                    100:                                printf("%02x ", blob[i+j]);
                    101:                        } else {
                    102:                                printf("   ");
1.9       christos  103:                        }
                    104:                }
1.1       reinoud   105:                for (j = 0; j < 16; j++) {
                    106:                        if (i+j < dlen) {
                    107:                                if (blob[i+j]>32 && blob[i+j]! = 127) {
                    108:                                        printf("%c", blob[i+j]);
                    109:                                } else {
                    110:                                        printf(".");
1.9       christos  111:                                }
                    112:                        }
                    113:                }
1.1       reinoud   114:                printf("\n");
1.9       christos  115:        }
1.1       reinoud   116:        printf("\n");
1.45      reinoud   117:        Debugger();
1.9       christos  118: }
1.1       reinoud   119: #endif
                    120:
                    121: static void
                    122: udf_dump_discinfo(struct udf_mount *ump)
                    123: {
                    124:        char   bits[128];
                    125:        struct mmc_discinfo *di = &ump->discinfo;
                    126:
                    127:        if ((udf_verbose & UDF_DEBUG_VOLUMES) == 0)
                    128:                return;
                    129:
                    130:        printf("Device/media info  :\n");
                    131:        printf("\tMMC profile        0x%02x\n", di->mmc_profile);
                    132:        printf("\tderived class      %d\n", di->mmc_class);
                    133:        printf("\tsector size        %d\n", di->sector_size);
                    134:        printf("\tdisc state         %d\n", di->disc_state);
                    135:        printf("\tlast ses state     %d\n", di->last_session_state);
                    136:        printf("\tbg format state    %d\n", di->bg_format_state);
                    137:        printf("\tfrst track         %d\n", di->first_track);
                    138:        printf("\tfst on last ses    %d\n", di->first_track_last_session);
                    139:        printf("\tlst on last ses    %d\n", di->last_track_last_session);
                    140:        printf("\tlink block penalty %d\n", di->link_block_penalty);
1.80      christos  141:        snprintb(bits, sizeof(bits), MMC_DFLAGS_FLAGBITS, di->disc_flags);
1.1       reinoud   142:        printf("\tdisc flags         %s\n", bits);
                    143:        printf("\tdisc id            %x\n", di->disc_id);
                    144:        printf("\tdisc barcode       %"PRIx64"\n", di->disc_barcode);
                    145:
                    146:        printf("\tnum sessions       %d\n", di->num_sessions);
                    147:        printf("\tnum tracks         %d\n", di->num_tracks);
                    148:
1.80      christos  149:        snprintb(bits, sizeof(bits), MMC_CAP_FLAGBITS, di->mmc_cur);
1.1       reinoud   150:        printf("\tcapabilities cur   %s\n", bits);
1.80      christos  151:        snprintb(bits, sizeof(bits), MMC_CAP_FLAGBITS, di->mmc_cap);
1.1       reinoud   152:        printf("\tcapabilities cap   %s\n", bits);
                    153: }
1.85      reinoud   154:
                    155: static void
                    156: udf_dump_trackinfo(struct mmc_trackinfo *trackinfo)
                    157: {
                    158:        char   bits[128];
                    159:
                    160:        if ((udf_verbose & UDF_DEBUG_VOLUMES) == 0)
                    161:                return;
                    162:
                    163:        printf("Trackinfo for track %d:\n", trackinfo->tracknr);
                    164:        printf("\tsessionnr           %d\n", trackinfo->sessionnr);
                    165:        printf("\ttrack mode          %d\n", trackinfo->track_mode);
                    166:        printf("\tdata mode           %d\n", trackinfo->data_mode);
                    167:        snprintb(bits, sizeof(bits), MMC_TRACKINFO_FLAGBITS, trackinfo->flags);
                    168:        printf("\tflags               %s\n", bits);
                    169:
                    170:        printf("\ttrack start         %d\n", trackinfo->track_start);
                    171:        printf("\tnext_writable       %d\n", trackinfo->next_writable);
                    172:        printf("\tfree_blocks         %d\n", trackinfo->free_blocks);
                    173:        printf("\tpacket_size         %d\n", trackinfo->packet_size);
                    174:        printf("\ttrack size          %d\n", trackinfo->track_size);
                    175:        printf("\tlast recorded block %d\n", trackinfo->last_recorded);
                    176: }
                    177:
1.1       reinoud   178: #else
                    179: #define udf_dump_discinfo(a);
1.85      reinoud   180: #define udf_dump_trackinfo(a);
1.1       reinoud   181: #endif
                    182:
1.45      reinoud   183:
                    184: /* --------------------------------------------------------------------- */
                    185:
1.1       reinoud   186: /* not called often */
                    187: int
                    188: udf_update_discinfo(struct udf_mount *ump)
                    189: {
                    190:        struct vnode *devvp = ump->devvp;
1.118     christos  191:        uint64_t psize;
                    192:        unsigned secsize;
1.1       reinoud   193:        struct mmc_discinfo *di;
                    194:        int error;
                    195:
                    196:        DPRINTF(VOLUMES, ("read/update disc info\n"));
                    197:        di = &ump->discinfo;
                    198:        memset(di, 0, sizeof(struct mmc_discinfo));
                    199:
                    200:        /* check if we're on a MMC capable device, i.e. CD/DVD */
1.41      pooka     201:        error = VOP_IOCTL(devvp, MMCGETDISCINFO, di, FKIOCTL, NOCRED);
1.1       reinoud   202:        if (error == 0) {
                    203:                udf_dump_discinfo(ump);
                    204:                return 0;
1.9       christos  205:        }
1.1       reinoud   206:
                    207:        /* disc partition support */
1.118     christos  208:        error = getdisksize(devvp, &psize, &secsize);
1.1       reinoud   209:        if (error)
1.118     christos  210:                return error;
1.1       reinoud   211:
                    212:        /* set up a disc info profile for partitions */
                    213:        di->mmc_profile         = 0x01; /* disc type */
                    214:        di->mmc_class           = MMC_CLASS_DISC;
                    215:        di->disc_state          = MMC_STATE_CLOSED;
                    216:        di->last_session_state  = MMC_STATE_CLOSED;
                    217:        di->bg_format_state     = MMC_BGFSTATE_COMPLETED;
                    218:        di->link_block_penalty  = 0;
                    219:
                    220:        di->mmc_cur     = MMC_CAP_RECORDABLE | MMC_CAP_REWRITABLE |
1.4       reinoud   221:                MMC_CAP_ZEROLINKBLK | MMC_CAP_HW_DEFECTFREE;
1.1       reinoud   222:        di->mmc_cap    = di->mmc_cur;
                    223:        di->disc_flags = MMC_DFLAGS_UNRESTRICTED;
                    224:
                    225:        /* TODO problem with last_possible_lba on resizable VND; request */
1.118     christos  226:        di->last_possible_lba = psize;
                    227:        di->sector_size       = secsize;
1.1       reinoud   228:
                    229:        di->num_sessions = 1;
                    230:        di->num_tracks   = 1;
                    231:
                    232:        di->first_track  = 1;
                    233:        di->first_track_last_session = di->last_track_last_session = 1;
                    234:
                    235:        udf_dump_discinfo(ump);
                    236:        return 0;
                    237: }
                    238:
                    239:
                    240: int
                    241: udf_update_trackinfo(struct udf_mount *ump, struct mmc_trackinfo *ti)
                    242: {
                    243:        struct vnode *devvp = ump->devvp;
                    244:        struct mmc_discinfo *di = &ump->discinfo;
                    245:        int error, class;
                    246:
                    247:        DPRINTF(VOLUMES, ("read track info\n"));
                    248:
                    249:        class = di->mmc_class;
                    250:        if (class != MMC_CLASS_DISC) {
                    251:                /* tracknr specified in struct ti */
1.41      pooka     252:                error = VOP_IOCTL(devvp, MMCGETTRACKINFO, ti, FKIOCTL, NOCRED);
1.1       reinoud   253:                return error;
1.9       christos  254:        }
1.1       reinoud   255:
                    256:        /* disc partition support */
                    257:        if (ti->tracknr != 1)
                    258:                return EIO;
                    259:
                    260:        /* create fake ti (TODO check for resized vnds) */
                    261:        ti->sessionnr  = 1;
                    262:
                    263:        ti->track_mode = 0;     /* XXX */
                    264:        ti->data_mode  = 0;     /* XXX */
                    265:        ti->flags = MMC_TRACKINFO_LRA_VALID | MMC_TRACKINFO_NWA_VALID;
                    266:
                    267:        ti->track_start    = 0;
                    268:        ti->packet_size    = 1;
                    269:
                    270:        /* TODO support for resizable vnd */
                    271:        ti->track_size    = di->last_possible_lba;
                    272:        ti->next_writable = di->last_possible_lba;
                    273:        ti->last_recorded = ti->next_writable;
                    274:        ti->free_blocks   = 0;
                    275:
                    276:        return 0;
                    277: }
                    278:
                    279:
1.45      reinoud   280: int
                    281: udf_setup_writeparams(struct udf_mount *ump)
1.1       reinoud   282: {
1.45      reinoud   283:        struct mmc_writeparams mmc_writeparams;
                    284:        int error;
                    285:
                    286:        if (ump->discinfo.mmc_class == MMC_CLASS_DISC)
                    287:                return 0;
                    288:
                    289:        /*
                    290:         * only CD burning normally needs setting up, but other disc types
                    291:         * might need other settings to be made. The MMC framework will set up
1.155     andvar    292:         * the necessary recording parameters according to the disc
1.45      reinoud   293:         * characteristics read in. Modifications can be made in the discinfo
                    294:         * structure passed to change the nature of the disc.
                    295:         */
                    296:
                    297:        memset(&mmc_writeparams, 0, sizeof(struct mmc_writeparams));
                    298:        mmc_writeparams.mmc_class  = ump->discinfo.mmc_class;
                    299:        mmc_writeparams.mmc_cur    = ump->discinfo.mmc_cur;
                    300:
                    301:        /*
                    302:         * UDF dictates first track to determine track mode for the whole
                    303:         * disc. [UDF 1.50/6.10.1.1, UDF 1.50/6.10.2.1]
                    304:         * To prevent problems with a `reserved' track in front we start with
                    305:         * the 2nd track and if that is not valid, go for the 1st.
                    306:         */
                    307:        mmc_writeparams.tracknr = 2;
                    308:        mmc_writeparams.data_mode  = MMC_DATAMODE_DEFAULT;      /* XA disc */
                    309:        mmc_writeparams.track_mode = MMC_TRACKMODE_DEFAULT;     /* data */
                    310:
                    311:        error = VOP_IOCTL(ump->devvp, MMCSETUPWRITEPARAMS, &mmc_writeparams,
                    312:                        FKIOCTL, NOCRED);
                    313:        if (error) {
                    314:                mmc_writeparams.tracknr = 1;
                    315:                error = VOP_IOCTL(ump->devvp, MMCSETUPWRITEPARAMS,
                    316:                                &mmc_writeparams, FKIOCTL, NOCRED);
                    317:        }
                    318:        return error;
                    319: }
                    320:
                    321:
1.138     reinoud   322: void
                    323: udf_mmc_synchronise_caches(struct udf_mount *ump)
1.45      reinoud   324: {
                    325:        struct mmc_op mmc_op;
                    326:
1.138     reinoud   327:        DPRINTF(CALL, ("udf_mcc_synchronise_caches()\n"));
1.45      reinoud   328:
                    329:        if (ump->vfs_mountp->mnt_flag & MNT_RDONLY)
1.138     reinoud   330:                return;
1.45      reinoud   331:
                    332:        /* discs are done now */
                    333:        if (ump->discinfo.mmc_class == MMC_CLASS_DISC)
1.138     reinoud   334:                return;
1.45      reinoud   335:
1.87      cegger    336:        memset(&mmc_op, 0, sizeof(struct mmc_op));
1.45      reinoud   337:        mmc_op.operation = MMC_OP_SYNCHRONISECACHE;
                    338:
                    339:        /* ignore return code */
                    340:        (void) VOP_IOCTL(ump->devvp, MMCOP, &mmc_op, FKIOCTL, NOCRED);
                    341: }
                    342:
                    343: /* --------------------------------------------------------------------- */
                    344:
                    345: /* track/session searching for mounting */
                    346: int
                    347: udf_search_tracks(struct udf_mount *ump, struct udf_args *args,
                    348:                  int *first_tracknr, int *last_tracknr)
                    349: {
                    350:        struct mmc_trackinfo trackinfo;
                    351:        uint32_t tracknr, start_track, num_tracks;
1.1       reinoud   352:        int error;
                    353:
                    354:        /* if negative, sessionnr is relative to last session */
                    355:        if (args->sessionnr < 0) {
                    356:                args->sessionnr += ump->discinfo.num_sessions;
1.9       christos  357:        }
1.1       reinoud   358:
                    359:        /* sanity */
1.45      reinoud   360:        if (args->sessionnr < 0)
                    361:                args->sessionnr = 0;
1.1       reinoud   362:        if (args->sessionnr > ump->discinfo.num_sessions)
                    363:                args->sessionnr = ump->discinfo.num_sessions;
                    364:
                    365:        /* search the tracks for this session, zero session nr indicates last */
1.42      reinoud   366:        if (args->sessionnr == 0)
1.1       reinoud   367:                args->sessionnr = ump->discinfo.num_sessions;
1.42      reinoud   368:        if (ump->discinfo.last_session_state == MMC_STATE_EMPTY)
                    369:                args->sessionnr--;
                    370:
1.45      reinoud   371:        /* sanity again */
                    372:        if (args->sessionnr < 0)
                    373:                args->sessionnr = 0;
1.1       reinoud   374:
                    375:        /* search the first and last track of the specified session */
                    376:        num_tracks  = ump->discinfo.num_tracks;
                    377:        start_track = ump->discinfo.first_track;
                    378:
                    379:        /* search for first track of this session */
                    380:        for (tracknr = start_track; tracknr <= num_tracks; tracknr++) {
                    381:                /* get track info */
                    382:                trackinfo.tracknr = tracknr;
                    383:                error = udf_update_trackinfo(ump, &trackinfo);
                    384:                if (error)
                    385:                        return error;
                    386:
                    387:                if (trackinfo.sessionnr == args->sessionnr)
                    388:                        break;
                    389:        }
                    390:        *first_tracknr = tracknr;
                    391:
                    392:        /* search for last track of this session */
                    393:        for (;tracknr <= num_tracks; tracknr++) {
                    394:                /* get track info */
                    395:                trackinfo.tracknr = tracknr;
                    396:                error = udf_update_trackinfo(ump, &trackinfo);
                    397:                if (error || (trackinfo.sessionnr != args->sessionnr)) {
                    398:                        tracknr--;
                    399:                        break;
1.9       christos  400:                }
                    401:        }
1.1       reinoud   402:        if (tracknr > num_tracks)
                    403:                tracknr--;
                    404:
                    405:        *last_tracknr = tracknr;
                    406:
1.45      reinoud   407:        if (*last_tracknr < *first_tracknr) {
                    408:                printf( "udf_search_tracks: sanity check on drive+disc failed, "
                    409:                        "drive returned garbage\n");
                    410:                return EINVAL;
                    411:        }
                    412:
1.1       reinoud   413:        assert(*last_tracknr >= *first_tracknr);
                    414:        return 0;
                    415: }
                    416:
                    417:
1.45      reinoud   418: /*
                    419:  * NOTE: this is the only routine in this file that directly peeks into the
                    420:  * metadata file but since its at a larval state of the mount it can't hurt.
                    421:  *
                    422:  * XXX candidate for udf_allocation.c
                    423:  * XXX clean me up!, change to new node reading code.
                    424:  */
                    425:
                    426: static void
                    427: udf_check_track_metadata_overlap(struct udf_mount *ump,
                    428:        struct mmc_trackinfo *trackinfo)
1.1       reinoud   429: {
1.45      reinoud   430:        struct part_desc *part;
                    431:        struct file_entry      *fe;
                    432:        struct extfile_entry   *efe;
                    433:        struct short_ad        *s_ad;
                    434:        struct long_ad         *l_ad;
                    435:        uint32_t track_start, track_end;
                    436:        uint32_t phys_part_start, phys_part_end, part_start, part_end;
                    437:        uint32_t sector_size, len, alloclen, plb_num;
                    438:        uint8_t *pos;
1.121     christos  439:        int addr_type, icblen, icbflags;
1.1       reinoud   440:
1.45      reinoud   441:        /* get our track extents */
                    442:        track_start = trackinfo->track_start;
                    443:        track_end   = track_start + trackinfo->track_size;
                    444:
                    445:        /* get our base partition extent */
1.71      reinoud   446:        KASSERT(ump->node_part == ump->fids_part);
1.112     reinoud   447:        part = ump->partitions[ump->vtop[ump->node_part]];
1.45      reinoud   448:        phys_part_start = udf_rw32(part->start_loc);
                    449:        phys_part_end   = phys_part_start + udf_rw32(part->part_len);
1.1       reinoud   450:
1.45      reinoud   451:        /* no use if its outside the physical partition */
                    452:        if ((phys_part_start >= track_end) || (phys_part_end < track_start))
                    453:                return;
1.1       reinoud   454:
1.45      reinoud   455:        /*
                    456:         * now follow all extents in the fe/efe to see if they refer to this
                    457:         * track
                    458:         */
1.1       reinoud   459:
1.45      reinoud   460:        sector_size = ump->discinfo.sector_size;
1.1       reinoud   461:
1.45      reinoud   462:        /* XXX should we claim exclusive access to the metafile ? */
                    463:        /* TODO: move to new node read code */
                    464:        fe  = ump->metadata_node->fe;
                    465:        efe = ump->metadata_node->efe;
                    466:        if (fe) {
                    467:                alloclen = udf_rw32(fe->l_ad);
                    468:                pos      = &fe->data[0] + udf_rw32(fe->l_ea);
                    469:                icbflags = udf_rw16(fe->icbtag.flags);
                    470:        } else {
                    471:                assert(efe);
                    472:                alloclen = udf_rw32(efe->l_ad);
                    473:                pos      = &efe->data[0] + udf_rw32(efe->l_ea);
                    474:                icbflags = udf_rw16(efe->icbtag.flags);
1.9       christos  475:        }
1.45      reinoud   476:        addr_type = icbflags & UDF_ICB_TAG_FLAGS_ALLOC_MASK;
                    477:
                    478:        while (alloclen) {
                    479:                if (addr_type == UDF_ICB_SHORT_ALLOC) {
                    480:                        icblen = sizeof(struct short_ad);
                    481:                        s_ad   = (struct short_ad *) pos;
                    482:                        len        = udf_rw32(s_ad->len);
                    483:                        plb_num    = udf_rw32(s_ad->lb_num);
                    484:                } else {
                    485:                        /* should not be present, but why not */
                    486:                        icblen = sizeof(struct long_ad);
                    487:                        l_ad   = (struct long_ad *) pos;
                    488:                        len        = udf_rw32(l_ad->len);
                    489:                        plb_num    = udf_rw32(l_ad->loc.lb_num);
                    490:                        /* pvpart_num = udf_rw16(l_ad->loc.part_num); */
                    491:                }
                    492:                /* process extent */
                    493:                len     = UDF_EXT_LEN(len);
1.1       reinoud   494:
1.45      reinoud   495:                part_start = phys_part_start + plb_num;
                    496:                part_end   = part_start + (len / sector_size);
1.1       reinoud   497:
1.45      reinoud   498:                if ((part_start >= track_start) && (part_end <= track_end)) {
                    499:                        /* extent is enclosed within this track */
                    500:                        ump->metadata_track = *trackinfo;
                    501:                        return;
                    502:                }
1.1       reinoud   503:
1.45      reinoud   504:                pos        += icblen;
                    505:                alloclen   -= icblen;
1.9       christos  506:        }
1.45      reinoud   507: }
                    508:
1.1       reinoud   509:
1.45      reinoud   510: int
                    511: udf_search_writing_tracks(struct udf_mount *ump)
                    512: {
1.82      reinoud   513:        struct vnode *devvp = ump->devvp;
1.45      reinoud   514:        struct mmc_trackinfo trackinfo;
1.85      reinoud   515:        struct mmc_op        mmc_op;
1.45      reinoud   516:        struct part_desc *part;
                    517:        uint32_t tracknr, start_track, num_tracks;
                    518:        uint32_t track_start, track_end, part_start, part_end;
1.71      reinoud   519:        int node_alloc, error;
1.1       reinoud   520:
1.45      reinoud   521:        /*
                    522:         * in the CD/(HD)DVD/BD recordable device model a few tracks within
                    523:         * the last session might be open but in the UDF device model at most
                    524:         * three tracks can be open: a reserved track for delayed ISO VRS
                    525:         * writing, a data track and a metadata track. We search here for the
                    526:         * data track and the metadata track. Note that the reserved track is
                    527:         * troublesome but can be detected by its small size of < 512 sectors.
                    528:         */
1.1       reinoud   529:
1.85      reinoud   530:        /* update discinfo since it might have changed */
                    531:        error = udf_update_discinfo(ump);
                    532:        if (error)
                    533:                return error;
                    534:
1.45      reinoud   535:        num_tracks  = ump->discinfo.num_tracks;
                    536:        start_track = ump->discinfo.first_track;
1.1       reinoud   537:
1.45      reinoud   538:        /* fetch info on first and possibly only track */
                    539:        trackinfo.tracknr = start_track;
                    540:        error = udf_update_trackinfo(ump, &trackinfo);
                    541:        if (error)
                    542:                return error;
1.13      reinoud   543:
1.45      reinoud   544:        /* copy results to our mount point */
                    545:        ump->data_track     = trackinfo;
                    546:        ump->metadata_track = trackinfo;
1.1       reinoud   547:
1.45      reinoud   548:        /* if not sequential, we're done */
                    549:        if (num_tracks == 1)
                    550:                return 0;
1.1       reinoud   551:
1.45      reinoud   552:        for (tracknr = start_track;tracknr <= num_tracks; tracknr++) {
                    553:                /* get track info */
                    554:                trackinfo.tracknr = tracknr;
                    555:                error = udf_update_trackinfo(ump, &trackinfo);
                    556:                if (error)
                    557:                        return error;
1.1       reinoud   558:
1.82      reinoud   559:                /*
                    560:                 * If this track is marked damaged, ask for repair. This is an
                    561:                 * optional command, so ignore its error but report warning.
                    562:                 */
                    563:                if (trackinfo.flags & MMC_TRACKINFO_DAMAGED) {
1.85      reinoud   564:                        memset(&mmc_op, 0, sizeof(mmc_op));
                    565:                        mmc_op.operation   = MMC_OP_REPAIRTRACK;
                    566:                        mmc_op.mmc_profile = ump->discinfo.mmc_profile;
                    567:                        mmc_op.tracknr     = tracknr;
                    568:                        error = VOP_IOCTL(devvp, MMCOP, &mmc_op, FKIOCTL, NOCRED);
1.82      reinoud   569:                        if (error)
                    570:                                (void)printf("Drive can't explicitly repair "
                    571:                                        "damaged track %d, but it might "
                    572:                                        "autorepair\n", tracknr);
                    573:
                    574:                        /* reget track info */
                    575:                        error = udf_update_trackinfo(ump, &trackinfo);
                    576:                        if (error)
                    577:                                return error;
                    578:                }
1.45      reinoud   579:                if ((trackinfo.flags & MMC_TRACKINFO_NWA_VALID) == 0)
                    580:                        continue;
1.85      reinoud   581:
1.45      reinoud   582:                track_start = trackinfo.track_start;
                    583:                track_end   = track_start + trackinfo.track_size;
1.1       reinoud   584:
1.45      reinoud   585:                /* check for overlap on data partition */
                    586:                part = ump->partitions[ump->data_part];
                    587:                part_start = udf_rw32(part->start_loc);
                    588:                part_end   = part_start + udf_rw32(part->part_len);
                    589:                if ((part_start < track_end) && (part_end > track_start)) {
                    590:                        ump->data_track = trackinfo;
                    591:                        /* TODO check if UDF partition data_part is writable */
                    592:                }
                    593:
                    594:                /* check for overlap on metadata partition */
1.71      reinoud   595:                node_alloc = ump->vtop_alloc[ump->node_part];
                    596:                if ((node_alloc == UDF_ALLOC_METASEQUENTIAL) ||
                    597:                    (node_alloc == UDF_ALLOC_METABITMAP)) {
1.45      reinoud   598:                        udf_check_track_metadata_overlap(ump, &trackinfo);
                    599:                } else {
                    600:                        ump->metadata_track = trackinfo;
1.9       christos  601:                }
1.45      reinoud   602:        }
1.1       reinoud   603:
1.45      reinoud   604:        if ((ump->data_track.flags & MMC_TRACKINFO_NWA_VALID) == 0)
                    605:                return EROFS;
1.1       reinoud   606:
1.45      reinoud   607:        if ((ump->metadata_track.flags & MMC_TRACKINFO_NWA_VALID) == 0)
                    608:                return EROFS;
1.1       reinoud   609:
                    610:        return 0;
                    611: }
                    612:
                    613: /* --------------------------------------------------------------------- */
                    614:
1.45      reinoud   615: /*
                    616:  * Check if the blob starts with a good UDF tag. Tags are protected by a
1.162     reinoud   617:  * checksum over the header except one byte at position 4 that is the checksum
1.45      reinoud   618:  * itself.
                    619:  */
                    620:
                    621: int
                    622: udf_check_tag(void *blob)
1.1       reinoud   623: {
1.45      reinoud   624:        struct desc_tag *tag = blob;
                    625:        uint8_t *pos, sum, cnt;
1.1       reinoud   626:
1.45      reinoud   627:        /* check TAG header checksum */
                    628:        pos = (uint8_t *) tag;
                    629:        sum = 0;
                    630:
                    631:        for(cnt = 0; cnt < 16; cnt++) {
                    632:                if (cnt != 4)
                    633:                        sum += *pos;
                    634:                pos++;
                    635:        }
                    636:        if (sum != tag->cksum) {
                    637:                /* bad tag header checksum; this is not a valid tag */
                    638:                return EINVAL;
                    639:        }
                    640:
                    641:        return 0;
                    642: }
                    643:
                    644:
                    645: /*
                    646:  * check tag payload will check descriptor CRC as specified.
                    647:  * If the descriptor is too long, it will return EIO otherwise EINVAL.
                    648:  */
1.1       reinoud   649:
1.45      reinoud   650: int
                    651: udf_check_tag_payload(void *blob, uint32_t max_length)
                    652: {
                    653:        struct desc_tag *tag = blob;
                    654:        uint16_t crc, crc_len;
1.1       reinoud   655:
1.45      reinoud   656:        crc_len = udf_rw16(tag->desc_crc_len);
1.1       reinoud   657:
1.45      reinoud   658:        /* check payload CRC if applicable */
                    659:        if (crc_len == 0)
                    660:                return 0;
1.1       reinoud   661:
1.45      reinoud   662:        if (crc_len > max_length)
                    663:                return EIO;
1.1       reinoud   664:
1.45      reinoud   665:        crc = udf_cksum(((uint8_t *) tag) + UDF_DESC_TAG_LENGTH, crc_len);
                    666:        if (crc != udf_rw16(tag->desc_crc)) {
                    667:                /* bad payload CRC; this is a broken tag */
                    668:                return EINVAL;
1.9       christos  669:        }
1.1       reinoud   670:
1.45      reinoud   671:        return 0;
1.1       reinoud   672: }
                    673:
                    674:
1.45      reinoud   675: void
                    676: udf_validate_tag_sum(void *blob)
1.1       reinoud   677: {
1.45      reinoud   678:        struct desc_tag *tag = blob;
                    679:        uint8_t *pos, sum, cnt;
1.1       reinoud   680:
1.45      reinoud   681:        /* calculate TAG header checksum */
                    682:        pos = (uint8_t *) tag;
                    683:        sum = 0;
1.1       reinoud   684:
1.45      reinoud   685:        for(cnt = 0; cnt < 16; cnt++) {
                    686:                if (cnt != 4) sum += *pos;
                    687:                pos++;
                    688:        }
                    689:        tag->cksum = sum;       /* 8 bit */
                    690: }
1.1       reinoud   691:
                    692:
1.45      reinoud   693: /* assumes sector number of descriptor to be saved already present */
                    694: void
                    695: udf_validate_tag_and_crc_sums(void *blob)
                    696: {
                    697:        struct desc_tag *tag  = blob;
                    698:        uint8_t         *btag = (uint8_t *) tag;
                    699:        uint16_t crc, crc_len;
1.1       reinoud   700:
1.45      reinoud   701:        crc_len = udf_rw16(tag->desc_crc_len);
1.1       reinoud   702:
1.45      reinoud   703:        /* check payload CRC if applicable */
                    704:        if (crc_len > 0) {
                    705:                crc = udf_cksum(btag + UDF_DESC_TAG_LENGTH, crc_len);
                    706:                tag->desc_crc = udf_rw16(crc);
1.9       christos  707:        }
1.1       reinoud   708:
1.45      reinoud   709:        /* calculate TAG header checksum */
                    710:        udf_validate_tag_sum(blob);
1.1       reinoud   711: }
                    712:
                    713: /* --------------------------------------------------------------------- */
                    714:
                    715: /*
1.45      reinoud   716:  * XXX note the different semantics from udfclient: for FIDs it still rounds
                    717:  * up to sectors. Use udf_fidsize() for a correct length.
1.1       reinoud   718:  */
                    719:
1.45      reinoud   720: int
                    721: udf_tagsize(union dscrptr *dscr, uint32_t lb_size)
1.1       reinoud   722: {
1.45      reinoud   723:        uint32_t size, tag_id, num_lb, elmsz;
1.1       reinoud   724:
1.45      reinoud   725:        tag_id = udf_rw16(dscr->tag.id);
1.1       reinoud   726:
1.45      reinoud   727:        switch (tag_id) {
                    728:        case TAGID_LOGVOL :
                    729:                size  = sizeof(struct logvol_desc) - 1;
                    730:                size += udf_rw32(dscr->lvd.mt_l);
                    731:                break;
                    732:        case TAGID_UNALLOC_SPACE :
                    733:                elmsz = sizeof(struct extent_ad);
                    734:                size  = sizeof(struct unalloc_sp_desc) - elmsz;
                    735:                size += udf_rw32(dscr->usd.alloc_desc_num) * elmsz;
                    736:                break;
                    737:        case TAGID_FID :
                    738:                size = UDF_FID_SIZE + dscr->fid.l_fi + udf_rw16(dscr->fid.l_iu);
                    739:                size = (size + 3) & ~3;
                    740:                break;
                    741:        case TAGID_LOGVOL_INTEGRITY :
                    742:                size  = sizeof(struct logvol_int_desc) - sizeof(uint32_t);
                    743:                size += udf_rw32(dscr->lvid.l_iu);
                    744:                size += (2 * udf_rw32(dscr->lvid.num_part) * sizeof(uint32_t));
                    745:                break;
                    746:        case TAGID_SPACE_BITMAP :
                    747:                size  = sizeof(struct space_bitmap_desc) - 1;
                    748:                size += udf_rw32(dscr->sbd.num_bytes);
                    749:                break;
                    750:        case TAGID_SPARING_TABLE :
                    751:                elmsz = sizeof(struct spare_map_entry);
                    752:                size  = sizeof(struct udf_sparing_table) - elmsz;
                    753:                size += udf_rw16(dscr->spt.rt_l) * elmsz;
                    754:                break;
                    755:        case TAGID_FENTRY :
                    756:                size  = sizeof(struct file_entry);
                    757:                size += udf_rw32(dscr->fe.l_ea) + udf_rw32(dscr->fe.l_ad)-1;
                    758:                break;
                    759:        case TAGID_EXTFENTRY :
                    760:                size  = sizeof(struct extfile_entry);
                    761:                size += udf_rw32(dscr->efe.l_ea) + udf_rw32(dscr->efe.l_ad)-1;
                    762:                break;
                    763:        case TAGID_FSD :
                    764:                size  = sizeof(struct fileset_desc);
                    765:                break;
                    766:        default :
                    767:                size = sizeof(union dscrptr);
                    768:                break;
                    769:        }
1.1       reinoud   770:
1.70      reinoud   771:        if ((size == 0) || (lb_size == 0))
                    772:                return 0;
                    773:
                    774:        if (lb_size == 1)
                    775:                return size;
1.1       reinoud   776:
1.45      reinoud   777:        /* round up in sectors */
                    778:        num_lb = (size + lb_size -1) / lb_size;
                    779:        return num_lb * lb_size;
                    780: }
1.1       reinoud   781:
                    782:
1.45      reinoud   783: int
                    784: udf_fidsize(struct fileid_desc *fid)
                    785: {
                    786:        uint32_t size;
1.3       reinoud   787:
1.45      reinoud   788:        if (udf_rw16(fid->tag.id) != TAGID_FID)
                    789:                panic("got udf_fidsize on non FID\n");
1.1       reinoud   790:
1.45      reinoud   791:        size = UDF_FID_SIZE + fid->l_fi + udf_rw16(fid->l_iu);
                    792:        size = (size + 3) & ~3;
1.1       reinoud   793:
1.45      reinoud   794:        return size;
1.1       reinoud   795: }
                    796:
                    797: /* --------------------------------------------------------------------- */
                    798:
1.45      reinoud   799: void
                    800: udf_lock_node(struct udf_node *udf_node, int flag, char const *fname, const int lineno)
                    801: {
                    802:        int ret;
                    803:
                    804:        mutex_enter(&udf_node->node_mutex);
                    805:        /* wait until free */
                    806:        while (udf_node->i_flags & IN_LOCKED) {
                    807:                ret = cv_timedwait(&udf_node->node_lock, &udf_node->node_mutex, hz/8);
                    808:                /* TODO check if we should return error; abort */
                    809:                if (ret == EWOULDBLOCK) {
                    810:                        DPRINTF(LOCKING, ( "udf_lock_node: udf_node %p would block "
                    811:                                "wanted at %s:%d, previously locked at %s:%d\n",
1.152     skrll     812:                                udf_node, fname, lineno,
1.45      reinoud   813:                                udf_node->lock_fname, udf_node->lock_lineno));
                    814:                }
                    815:        }
                    816:        /* grab */
                    817:        udf_node->i_flags |= IN_LOCKED | flag;
                    818:        /* debug */
                    819:        udf_node->lock_fname  = fname;
                    820:        udf_node->lock_lineno = lineno;
                    821:
                    822:        mutex_exit(&udf_node->node_mutex);
                    823: }
                    824:
1.1       reinoud   825:
1.45      reinoud   826: void
                    827: udf_unlock_node(struct udf_node *udf_node, int flag)
1.22      christos  828: {
1.45      reinoud   829:        mutex_enter(&udf_node->node_mutex);
                    830:        udf_node->i_flags &= ~(IN_LOCKED | flag);
                    831:        cv_broadcast(&udf_node->node_lock);
                    832:        mutex_exit(&udf_node->node_mutex);
                    833: }
1.1       reinoud   834:
                    835:
1.45      reinoud   836: /* --------------------------------------------------------------------- */
1.1       reinoud   837:
1.45      reinoud   838: static int
                    839: udf_read_anchor(struct udf_mount *ump, uint32_t sector, struct anchor_vdp **dst)
                    840: {
                    841:        int error;
                    842:
                    843:        error = udf_read_phys_dscr(ump, sector, M_UDFVOLD,
                    844:                        (union dscrptr **) dst);
                    845:        if (!error) {
                    846:                /* blank terminator blocks are not allowed here */
                    847:                if (*dst == NULL)
                    848:                        return ENOENT;
                    849:                if (udf_rw16((*dst)->tag.id) != TAGID_ANCHOR) {
                    850:                        error = ENOENT;
                    851:                        free(*dst, M_UDFVOLD);
                    852:                        *dst = NULL;
                    853:                        DPRINTF(VOLUMES, ("Not an anchor\n"));
                    854:                }
                    855:        }
                    856:
                    857:        return error;
                    858: }
                    859:
                    860:
                    861: int
                    862: udf_read_anchors(struct udf_mount *ump)
                    863: {
                    864:        struct udf_args *args = &ump->mount_args;
                    865:        struct mmc_trackinfo first_track;
                    866:        struct mmc_trackinfo second_track;
                    867:        struct mmc_trackinfo last_track;
                    868:        struct anchor_vdp **anchorsp;
                    869:        uint32_t track_start;
                    870:        uint32_t track_end;
                    871:        uint32_t positions[4];
                    872:        int first_tracknr, last_tracknr;
                    873:        int error, anch, ok, first_anchor;
                    874:
                    875:        /* search the first and last track of the specified session */
                    876:        error = udf_search_tracks(ump, args, &first_tracknr, &last_tracknr);
                    877:        if (!error) {
                    878:                first_track.tracknr = first_tracknr;
                    879:                error = udf_update_trackinfo(ump, &first_track);
                    880:        }
                    881:        if (!error) {
                    882:                last_track.tracknr = last_tracknr;
                    883:                error = udf_update_trackinfo(ump, &last_track);
                    884:        }
                    885:        if ((!error) && (first_tracknr != last_tracknr)) {
                    886:                second_track.tracknr = first_tracknr+1;
                    887:                error = udf_update_trackinfo(ump, &second_track);
                    888:        }
                    889:        if (error) {
                    890:                printf("UDF mount: reading disc geometry failed\n");
                    891:                return 0;
                    892:        }
                    893:
                    894:        track_start = first_track.track_start;
1.1       reinoud   895:
1.45      reinoud   896:        /* `end' is not as straitforward as start. */
                    897:        track_end =   last_track.track_start
                    898:                    + last_track.track_size - last_track.free_blocks - 1;
1.1       reinoud   899:
1.45      reinoud   900:        if (ump->discinfo.mmc_cur & MMC_CAP_SEQUENTIAL) {
                    901:                /* end of track is not straitforward here */
                    902:                if (last_track.flags & MMC_TRACKINFO_LRA_VALID)
                    903:                        track_end = last_track.last_recorded;
                    904:                else if (last_track.flags & MMC_TRACKINFO_NWA_VALID)
                    905:                        track_end = last_track.next_writable
                    906:                                    - ump->discinfo.link_block_penalty;
1.9       christos  907:        }
1.1       reinoud   908:
1.45      reinoud   909:        /* its no use reading a blank track */
                    910:        first_anchor = 0;
                    911:        if (first_track.flags & MMC_TRACKINFO_BLANK)
                    912:                first_anchor = 1;
                    913:
                    914:        /* get our packet size */
                    915:        ump->packet_size = first_track.packet_size;
                    916:        if (first_track.flags & MMC_TRACKINFO_BLANK)
                    917:                ump->packet_size = second_track.packet_size;
                    918:
                    919:        if (ump->packet_size <= 1) {
                    920:                /* take max, but not bigger than 64 */
                    921:                ump->packet_size = MAXPHYS / ump->discinfo.sector_size;
                    922:                ump->packet_size = MIN(ump->packet_size, 64);
1.9       christos  923:        }
1.45      reinoud   924:        KASSERT(ump->packet_size >= 1);
1.1       reinoud   925:
1.45      reinoud   926:        /* read anchors start+256, start+512, end-256, end */
                    927:        positions[0] = track_start+256;
                    928:        positions[1] =   track_end-256;
                    929:        positions[2] =   track_end;
                    930:        positions[3] = track_start+512; /* [UDF 2.60/6.11.2] */
1.151     skrll     931:        /* XXX shouldn't +512 be preferred over +256 for compat with Roxio CD */
1.1       reinoud   932:
1.45      reinoud   933:        ok = 0;
                    934:        anchorsp = ump->anchors;
                    935:        for (anch = first_anchor; anch < 4; anch++) {
                    936:                DPRINTF(VOLUMES, ("Read anchor %d at sector %d\n", anch,
                    937:                    positions[anch]));
                    938:                error = udf_read_anchor(ump, positions[anch], anchorsp);
                    939:                if (!error) {
                    940:                        anchorsp++;
                    941:                        ok++;
                    942:                }
                    943:        }
1.1       reinoud   944:
1.45      reinoud   945:        /* VATs are only recorded on sequential media, but initialise */
                    946:        ump->first_possible_vat_location = track_start + 2;
1.137     reinoud   947:        ump->last_possible_vat_location  = track_end;
1.1       reinoud   948:
1.45      reinoud   949:        return ok;
                    950: }
1.1       reinoud   951:
1.45      reinoud   952: /* --------------------------------------------------------------------- */
1.1       reinoud   953:
1.95      reinoud   954: int
                    955: udf_get_c_type(struct udf_node *udf_node)
                    956: {
                    957:        int isdir, what;
                    958:
                    959:        isdir  = (udf_node->vnode->v_type == VDIR);
                    960:        what   = isdir ? UDF_C_FIDS : UDF_C_USERDATA;
                    961:
                    962:        if (udf_node->ump)
                    963:                if (udf_node == udf_node->ump->metadatabitmap_node)
                    964:                        what = UDF_C_METADATA_SBM;
                    965:
                    966:        return what;
                    967: }
                    968:
                    969:
                    970: int
                    971: udf_get_record_vpart(struct udf_mount *ump, int udf_c_type)
                    972: {
                    973:        int vpart_num;
                    974:
                    975:        vpart_num = ump->data_part;
                    976:        if (udf_c_type == UDF_C_NODE)
                    977:                vpart_num = ump->node_part;
                    978:        if (udf_c_type == UDF_C_FIDS)
                    979:                vpart_num = ump->fids_part;
                    980:
                    981:        return vpart_num;
                    982: }
                    983:
1.111     reinoud   984:
1.152     skrll     985: /*
1.111     reinoud   986:  * BUGALERT: some rogue implementations use random physical partition
                    987:  * numbers to break other implementations so lookup the number.
                    988:  */
                    989:
                    990: static uint16_t
                    991: udf_find_raw_phys(struct udf_mount *ump, uint16_t raw_phys_part)
                    992: {
                    993:        struct part_desc *part;
                    994:        uint16_t phys_part;
                    995:
                    996:        for (phys_part = 0; phys_part < UDF_PARTITIONS; phys_part++) {
                    997:                part = ump->partitions[phys_part];
                    998:                if (part == NULL)
                    999:                        break;
                   1000:                if (udf_rw16(part->part_num) == raw_phys_part)
                   1001:                        break;
                   1002:        }
                   1003:        return phys_part;
                   1004: }
                   1005:
1.95      reinoud  1006: /* --------------------------------------------------------------------- */
                   1007:
1.45      reinoud  1008: /* we dont try to be smart; we just record the parts */
                   1009: #define UDF_UPDATE_DSCR(name, dscr) \
                   1010:        if (name) \
                   1011:                free(name, M_UDFVOLD); \
                   1012:        name = dscr;
1.1       reinoud  1013:
1.45      reinoud  1014: static int
                   1015: udf_process_vds_descriptor(struct udf_mount *ump, union dscrptr *dscr)
                   1016: {
                   1017:        uint16_t phys_part, raw_phys_part;
1.1       reinoud  1018:
1.45      reinoud  1019:        DPRINTF(VOLUMES, ("\tprocessing VDS descr %d\n",
                   1020:            udf_rw16(dscr->tag.id)));
                   1021:        switch (udf_rw16(dscr->tag.id)) {
                   1022:        case TAGID_PRI_VOL :            /* primary partition            */
                   1023:                UDF_UPDATE_DSCR(ump->primary_vol, &dscr->pvd);
                   1024:                break;
                   1025:        case TAGID_LOGVOL :             /* logical volume               */
                   1026:                UDF_UPDATE_DSCR(ump->logical_vol, &dscr->lvd);
                   1027:                break;
                   1028:        case TAGID_UNALLOC_SPACE :      /* unallocated space            */
                   1029:                UDF_UPDATE_DSCR(ump->unallocated, &dscr->usd);
                   1030:                break;
                   1031:        case TAGID_IMP_VOL :            /* implementation               */
                   1032:                /* XXX do we care about multiple impl. descr ? */
                   1033:                UDF_UPDATE_DSCR(ump->implementation, &dscr->ivd);
                   1034:                break;
                   1035:        case TAGID_PARTITION :          /* physical partition           */
                   1036:                /* not much use if its not allocated */
                   1037:                if ((udf_rw16(dscr->pd.flags) & UDF_PART_FLAG_ALLOCATED) == 0) {
                   1038:                        free(dscr, M_UDFVOLD);
1.1       reinoud  1039:                        break;
1.9       christos 1040:                }
1.1       reinoud  1041:
1.33      reinoud  1042:                /*
                   1043:                 * BUGALERT: some rogue implementations use random physical
1.100     mbalmer  1044:                 * partition numbers to break other implementations so lookup
1.33      reinoud  1045:                 * the number.
                   1046:                 */
1.45      reinoud  1047:                raw_phys_part = udf_rw16(dscr->pd.part_num);
1.111     reinoud  1048:                phys_part = udf_find_raw_phys(ump, raw_phys_part);
                   1049:
1.45      reinoud  1050:                if (phys_part == UDF_PARTITIONS) {
                   1051:                        free(dscr, M_UDFVOLD);
1.1       reinoud  1052:                        return EINVAL;
1.45      reinoud  1053:                }
1.1       reinoud  1054:
1.45      reinoud  1055:                UDF_UPDATE_DSCR(ump->partitions[phys_part], &dscr->pd);
                   1056:                break;
                   1057:        case TAGID_VOL :                /* volume space extender; rare  */
                   1058:                DPRINTF(VOLUMES, ("VDS extender ignored\n"));
                   1059:                free(dscr, M_UDFVOLD);
                   1060:                break;
                   1061:        default :
                   1062:                DPRINTF(VOLUMES, ("Unhandled VDS type %d\n",
                   1063:                    udf_rw16(dscr->tag.id)));
                   1064:                free(dscr, M_UDFVOLD);
1.9       christos 1065:        }
1.1       reinoud  1066:
1.45      reinoud  1067:        return 0;
                   1068: }
                   1069: #undef UDF_UPDATE_DSCR
1.1       reinoud  1070:
1.45      reinoud  1071: /* --------------------------------------------------------------------- */
1.1       reinoud  1072:
1.45      reinoud  1073: static int
                   1074: udf_read_vds_extent(struct udf_mount *ump, uint32_t loc, uint32_t len)
                   1075: {
                   1076:        union dscrptr *dscr;
                   1077:        uint32_t sector_size, dscr_size;
                   1078:        int error;
1.1       reinoud  1079:
1.45      reinoud  1080:        sector_size = ump->discinfo.sector_size;
1.1       reinoud  1081:
1.45      reinoud  1082:        /* loc is sectornr, len is in bytes */
                   1083:        error = EIO;
                   1084:        while (len) {
                   1085:                error = udf_read_phys_dscr(ump, loc, M_UDFVOLD, &dscr);
                   1086:                if (error)
                   1087:                        return error;
                   1088:
                   1089:                /* blank block is a terminator */
                   1090:                if (dscr == NULL)
                   1091:                        return 0;
                   1092:
                   1093:                /* TERM descriptor is a terminator */
                   1094:                if (udf_rw16(dscr->tag.id) == TAGID_TERM) {
                   1095:                        free(dscr, M_UDFVOLD);
                   1096:                        return 0;
                   1097:                }
                   1098:
                   1099:                /* process all others */
                   1100:                dscr_size = udf_tagsize(dscr, sector_size);
                   1101:                error = udf_process_vds_descriptor(ump, dscr);
                   1102:                if (error) {
                   1103:                        free(dscr, M_UDFVOLD);
                   1104:                        break;
                   1105:                }
                   1106:                assert((dscr_size % sector_size) == 0);
                   1107:
                   1108:                len -= dscr_size;
                   1109:                loc += dscr_size / sector_size;
                   1110:        }
                   1111:
                   1112:        return error;
                   1113: }
                   1114:
                   1115:
                   1116: int
                   1117: udf_read_vds_space(struct udf_mount *ump)
                   1118: {
                   1119:        /* struct udf_args *args = &ump->mount_args; */
                   1120:        struct anchor_vdp *anchor, *anchor2;
                   1121:        size_t size;
                   1122:        uint32_t main_loc, main_len;
                   1123:        uint32_t reserve_loc, reserve_len;
                   1124:        int error;
                   1125:
                   1126:        /*
                   1127:         * read in VDS space provided by the anchors; if one descriptor read
                   1128:         * fails, try the mirror sector.
                   1129:         *
                   1130:         * check if 2nd anchor is different from 1st; if so, go for 2nd. This
                   1131:         * avoids the `compatibility features' of DirectCD that may confuse
                   1132:         * stuff completely.
                   1133:         */
                   1134:
                   1135:        anchor  = ump->anchors[0];
                   1136:        anchor2 = ump->anchors[1];
                   1137:        assert(anchor);
                   1138:
                   1139:        if (anchor2) {
                   1140:                size = sizeof(struct extent_ad);
                   1141:                if (memcmp(&anchor->main_vds_ex, &anchor2->main_vds_ex, size))
                   1142:                        anchor = anchor2;
                   1143:                /* reserve is specified to be a literal copy of main */
                   1144:        }
                   1145:
                   1146:        main_loc    = udf_rw32(anchor->main_vds_ex.loc);
                   1147:        main_len    = udf_rw32(anchor->main_vds_ex.len);
                   1148:
                   1149:        reserve_loc = udf_rw32(anchor->reserve_vds_ex.loc);
                   1150:        reserve_len = udf_rw32(anchor->reserve_vds_ex.len);
                   1151:
                   1152:        error = udf_read_vds_extent(ump, main_loc, main_len);
                   1153:        if (error) {
                   1154:                printf("UDF mount: reading in reserve VDS extent\n");
                   1155:                error = udf_read_vds_extent(ump, reserve_loc, reserve_len);
                   1156:        }
                   1157:
                   1158:        return error;
                   1159: }
                   1160:
                   1161: /* --------------------------------------------------------------------- */
                   1162:
                   1163: /*
                   1164:  * Read in the logical volume integrity sequence pointed to by our logical
                   1165:  * volume descriptor. Its a sequence that can be extended using fields in the
                   1166:  * integrity descriptor itself. On sequential media only one is found, on
                   1167:  * rewritable media a sequence of descriptors can be found as a form of
                   1168:  * history keeping and on non sequential write-once media the chain is vital
                   1169:  * to allow more and more descriptors to be written. The last descriptor
                   1170:  * written in an extent needs to claim space for a new extent.
                   1171:  */
                   1172:
                   1173: static int
                   1174: udf_retrieve_lvint(struct udf_mount *ump)
                   1175: {
                   1176:        union dscrptr *dscr;
                   1177:        struct logvol_int_desc *lvint;
                   1178:        struct udf_lvintq *trace;
                   1179:        uint32_t lb_size, lbnum, len;
                   1180:        int dscr_type, error, trace_len;
                   1181:
                   1182:        lb_size = udf_rw32(ump->logical_vol->lb_size);
                   1183:        len     = udf_rw32(ump->logical_vol->integrity_seq_loc.len);
                   1184:        lbnum   = udf_rw32(ump->logical_vol->integrity_seq_loc.loc);
                   1185:
                   1186:        /* clean trace */
                   1187:        memset(ump->lvint_trace, 0,
                   1188:            UDF_LVDINT_SEGMENTS * sizeof(struct udf_lvintq));
                   1189:
                   1190:        trace_len    = 0;
                   1191:        trace        = ump->lvint_trace;
                   1192:        trace->start = lbnum;
                   1193:        trace->end   = lbnum + len/lb_size;
                   1194:        trace->pos   = 0;
                   1195:        trace->wpos  = 0;
                   1196:
                   1197:        lvint = NULL;
                   1198:        dscr  = NULL;
                   1199:        error = 0;
                   1200:        while (len) {
                   1201:                trace->pos  = lbnum - trace->start;
                   1202:                trace->wpos = trace->pos + 1;
                   1203:
                   1204:                /* read in our integrity descriptor */
                   1205:                error = udf_read_phys_dscr(ump, lbnum, M_UDFVOLD, &dscr);
                   1206:                if (!error) {
                   1207:                        if (dscr == NULL) {
                   1208:                                trace->wpos = trace->pos;
                   1209:                                break;          /* empty terminates */
                   1210:                        }
                   1211:                        dscr_type = udf_rw16(dscr->tag.id);
                   1212:                        if (dscr_type == TAGID_TERM) {
                   1213:                                trace->wpos = trace->pos;
                   1214:                                break;          /* clean terminator */
                   1215:                        }
                   1216:                        if (dscr_type != TAGID_LOGVOL_INTEGRITY) {
                   1217:                                /* fatal... corrupt disc */
                   1218:                                error = ENOENT;
                   1219:                                break;
                   1220:                        }
                   1221:                        if (lvint)
                   1222:                                free(lvint, M_UDFVOLD);
                   1223:                        lvint = &dscr->lvid;
                   1224:                        dscr = NULL;
                   1225:                } /* else hope for the best... maybe the next is ok */
                   1226:
                   1227:                DPRINTFIF(VOLUMES, lvint, ("logvol integrity read, state %s\n",
                   1228:                    udf_rw32(lvint->integrity_type) ? "CLOSED" : "OPEN"));
                   1229:
                   1230:                /* proceed sequential */
                   1231:                lbnum += 1;
                   1232:                len    -= lb_size;
                   1233:
                   1234:                /* are we linking to a new piece? */
                   1235:                if (dscr && lvint->next_extent.len) {
1.142     reinoud  1236:                        len   = udf_rw32(lvint->next_extent.len);
1.45      reinoud  1237:                        lbnum = udf_rw32(lvint->next_extent.loc);
                   1238:
                   1239:                        if (trace_len >= UDF_LVDINT_SEGMENTS-1) {
                   1240:                                /* IEK! segment link full... */
                   1241:                                DPRINTF(VOLUMES, ("lvdint segments full\n"));
                   1242:                                error = EINVAL;
                   1243:                        } else {
                   1244:                                trace++;
                   1245:                                trace_len++;
                   1246:
                   1247:                                trace->start = lbnum;
                   1248:                                trace->end   = lbnum + len/lb_size;
                   1249:                                trace->pos   = 0;
                   1250:                                trace->wpos  = 0;
                   1251:                        }
                   1252:                }
                   1253:        }
                   1254:
                   1255:        /* clean up the mess, esp. when there is an error */
                   1256:        if (dscr)
                   1257:                free(dscr, M_UDFVOLD);
                   1258:
                   1259:        if (error && lvint) {
                   1260:                free(lvint, M_UDFVOLD);
                   1261:                lvint = NULL;
                   1262:        }
                   1263:
                   1264:        if (!lvint)
                   1265:                error = ENOENT;
                   1266:
                   1267:        ump->logvol_integrity = lvint;
                   1268:        return error;
                   1269: }
                   1270:
                   1271:
                   1272: static int
                   1273: udf_loose_lvint_history(struct udf_mount *ump)
                   1274: {
                   1275:        union dscrptr **bufs, *dscr, *last_dscr;
                   1276:        struct udf_lvintq *trace, *in_trace, *out_trace;
                   1277:        struct logvol_int_desc *lvint;
                   1278:        uint32_t in_ext, in_pos, in_len;
                   1279:        uint32_t out_ext, out_wpos, out_len;
1.121     christos 1280:        uint32_t lb_num;
1.45      reinoud  1281:        uint32_t len, start;
1.142     reinoud  1282:        int ext, sumext, extlen, cnt, cpy_len, dscr_type;
1.45      reinoud  1283:        int losing;
                   1284:        int error;
                   1285:
                   1286:        DPRINTF(VOLUMES, ("need to lose some lvint history\n"));
                   1287:
                   1288:        /* search smallest extent */
                   1289:        trace = &ump->lvint_trace[0];
1.142     reinoud  1290:        sumext = trace->end - trace->start;
1.45      reinoud  1291:        for (ext = 1; ext < UDF_LVDINT_SEGMENTS; ext++) {
                   1292:                trace = &ump->lvint_trace[ext];
                   1293:                extlen = trace->end - trace->start;
                   1294:                if (extlen == 0)
                   1295:                        break;
1.142     reinoud  1296:                sumext += extlen;
1.45      reinoud  1297:        }
1.142     reinoud  1298:
                   1299:        /* just one element? its not legal but be bug compatible */
                   1300:        if (sumext == 1) {
                   1301:                /* overwrite the only entry */
                   1302:                DPRINTF(VOLUMES, ("\tLinux bugcompat overwriting sole entry\n"));
                   1303:                trace = &ump->lvint_trace[0];
                   1304:                trace->wpos = 0;
                   1305:                return 0;
                   1306:        }
                   1307:
                   1308:        losing = MIN(sumext, UDF_LVINT_LOSSAGE);
                   1309:
                   1310:        /* no sense wiping too much */
                   1311:        if (sumext == UDF_LVINT_LOSSAGE)
                   1312:                losing = UDF_LVINT_LOSSAGE/2;
1.45      reinoud  1313:
                   1314:        DPRINTF(VOLUMES, ("\tlosing %d entries\n", losing));
                   1315:
                   1316:        /* get buffer for pieces */
                   1317:        bufs = malloc(UDF_LVDINT_SEGMENTS * sizeof(void *), M_TEMP, M_WAITOK);
                   1318:
                   1319:        in_ext    = 0;
                   1320:        in_pos    = losing;
                   1321:        in_trace  = &ump->lvint_trace[in_ext];
                   1322:        in_len    = in_trace->end - in_trace->start;
                   1323:        out_ext   = 0;
                   1324:        out_wpos  = 0;
                   1325:        out_trace = &ump->lvint_trace[out_ext];
                   1326:        out_len   = out_trace->end - out_trace->start;
                   1327:
                   1328:        last_dscr = NULL;
                   1329:        for(;;) {
                   1330:                out_trace->pos  = out_wpos;
                   1331:                out_trace->wpos = out_trace->pos;
                   1332:                if (in_pos >= in_len) {
                   1333:                        in_ext++;
                   1334:                        in_pos = 0;
                   1335:                        in_trace = &ump->lvint_trace[in_ext];
                   1336:                        in_len   = in_trace->end - in_trace->start;
                   1337:                }
                   1338:                if (out_wpos >= out_len) {
                   1339:                        out_ext++;
                   1340:                        out_wpos = 0;
                   1341:                        out_trace = &ump->lvint_trace[out_ext];
                   1342:                        out_len   = out_trace->end - out_trace->start;
                   1343:                }
                   1344:                /* copy overlap contents */
                   1345:                cpy_len = MIN(in_len - in_pos, out_len - out_wpos);
                   1346:                cpy_len = MIN(cpy_len, in_len - in_trace->pos);
                   1347:                if (cpy_len == 0)
                   1348:                        break;
                   1349:
                   1350:                /* copy */
                   1351:                DPRINTF(VOLUMES, ("\treading %d lvid descriptors\n", cpy_len));
                   1352:                for (cnt = 0; cnt < cpy_len; cnt++) {
                   1353:                        /* read in our integrity descriptor */
                   1354:                        lb_num = in_trace->start + in_pos + cnt;
                   1355:                        error = udf_read_phys_dscr(ump, lb_num, M_UDFVOLD,
                   1356:                                &dscr);
                   1357:                        if (error) {
                   1358:                                /* copy last one */
                   1359:                                dscr = last_dscr;
                   1360:                        }
                   1361:                        bufs[cnt] = dscr;
                   1362:                        if (!error) {
                   1363:                                if (dscr == NULL) {
                   1364:                                        out_trace->pos  = out_wpos + cnt;
                   1365:                                        out_trace->wpos = out_trace->pos;
                   1366:                                        break;          /* empty terminates */
                   1367:                                }
                   1368:                                dscr_type = udf_rw16(dscr->tag.id);
                   1369:                                if (dscr_type == TAGID_TERM) {
                   1370:                                        out_trace->pos  = out_wpos + cnt;
                   1371:                                        out_trace->wpos = out_trace->pos;
                   1372:                                        break;          /* clean terminator */
                   1373:                                }
                   1374:                                if (dscr_type != TAGID_LOGVOL_INTEGRITY) {
                   1375:                                        panic(  "UDF integrity sequence "
                   1376:                                                "corrupted while mounted!\n");
                   1377:                                }
                   1378:                                last_dscr = dscr;
                   1379:                        }
                   1380:                }
                   1381:
                   1382:                /* patch up if first entry was on error */
                   1383:                if (bufs[0] == NULL) {
                   1384:                        for (cnt = 0; cnt < cpy_len; cnt++)
                   1385:                                if (bufs[cnt] != NULL)
                   1386:                                        break;
                   1387:                        last_dscr = bufs[cnt];
                   1388:                        for (; cnt > 0; cnt--) {
                   1389:                                bufs[cnt] = last_dscr;
                   1390:                        }
                   1391:                }
                   1392:
                   1393:                /* glue + write out */
                   1394:                DPRINTF(VOLUMES, ("\twriting %d lvid descriptors\n", cpy_len));
                   1395:                for (cnt = 0; cnt < cpy_len; cnt++) {
                   1396:                        lb_num = out_trace->start + out_wpos + cnt;
                   1397:                        lvint  = &bufs[cnt]->lvid;
                   1398:
                   1399:                        /* set continuation */
                   1400:                        len = 0;
                   1401:                        start = 0;
                   1402:                        if (out_wpos + cnt == out_len) {
                   1403:                                /* get continuation */
                   1404:                                trace = &ump->lvint_trace[out_ext+1];
                   1405:                                len   = trace->end - trace->start;
                   1406:                                start = trace->start;
                   1407:                        }
                   1408:                        lvint->next_extent.len = udf_rw32(len);
                   1409:                        lvint->next_extent.loc = udf_rw32(start);
                   1410:
                   1411:                        lb_num = trace->start + trace->wpos;
                   1412:                        error = udf_write_phys_dscr_sync(ump, NULL, UDF_C_DSCR,
                   1413:                                bufs[cnt], lb_num, lb_num);
                   1414:                        DPRINTFIF(VOLUMES, error,
                   1415:                                ("error writing lvint lb_num\n"));
                   1416:                }
                   1417:
                   1418:                /* free non repeating descriptors */
                   1419:                last_dscr = NULL;
                   1420:                for (cnt = 0; cnt < cpy_len; cnt++) {
                   1421:                        if (bufs[cnt] != last_dscr)
                   1422:                                free(bufs[cnt], M_UDFVOLD);
                   1423:                        last_dscr = bufs[cnt];
                   1424:                }
                   1425:
                   1426:                /* advance */
                   1427:                in_pos   += cpy_len;
                   1428:                out_wpos += cpy_len;
                   1429:        }
                   1430:
                   1431:        free(bufs, M_TEMP);
                   1432:
                   1433:        return 0;
                   1434: }
                   1435:
                   1436:
                   1437: static int
                   1438: udf_writeout_lvint(struct udf_mount *ump, int lvflag)
                   1439: {
                   1440:        struct udf_lvintq *trace;
                   1441:        struct timeval  now_v;
                   1442:        struct timespec now_s;
                   1443:        uint32_t sector;
                   1444:        int logvol_integrity;
                   1445:        int space, error;
                   1446:
                   1447:        DPRINTF(VOLUMES, ("writing out logvol integrity descriptor\n"));
                   1448:
                   1449:        /* get free space in last chunk */
                   1450:        trace = ump->lvint_trace;
                   1451:        while (trace->wpos > (trace->end - trace->start)) {
                   1452:                DPRINTF(VOLUMES, ("skip : start = %d, end = %d, pos = %d, "
                   1453:                                  "wpos = %d\n", trace->start, trace->end,
                   1454:                                  trace->pos, trace->wpos));
                   1455:                trace++;
                   1456:        }
                   1457:
                   1458:        /* check if there is space to append */
                   1459:        space = (trace->end - trace->start) - trace->wpos;
                   1460:        DPRINTF(VOLUMES, ("write start = %d, end = %d, pos = %d, wpos = %d, "
                   1461:                          "space = %d\n", trace->start, trace->end, trace->pos,
                   1462:                          trace->wpos, space));
                   1463:
                   1464:        /* get state */
                   1465:        logvol_integrity = udf_rw32(ump->logvol_integrity->integrity_type);
                   1466:        if (logvol_integrity == UDF_INTEGRITY_CLOSED) {
                   1467:                if ((space < 3) && (lvflag & UDF_APPENDONLY_LVINT)) {
                   1468:                        /* TODO extent LVINT space if possible */
                   1469:                        return EROFS;
                   1470:                }
                   1471:        }
                   1472:
                   1473:        if (space < 1) {
                   1474:                if (lvflag & UDF_APPENDONLY_LVINT)
                   1475:                        return EROFS;
1.142     reinoud  1476:
1.45      reinoud  1477:                /* loose history by re-writing extents */
                   1478:                error = udf_loose_lvint_history(ump);
                   1479:                if (error)
                   1480:                        return error;
1.142     reinoud  1481:
                   1482:                trace = ump->lvint_trace;
                   1483:                while (trace->wpos > (trace->end - trace->start))
                   1484:                        trace++;
                   1485:                space = (trace->end - trace->start) - trace->wpos;
                   1486:                DPRINTF(VOLUMES, ("new try: write start = %d, end = %d, "
                   1487:                                  "pos = %d, wpos = %d, "
                   1488:                                  "space = %d\n", trace->start, trace->end,
                   1489:                                  trace->pos, trace->wpos, space));
1.45      reinoud  1490:        }
                   1491:
                   1492:        /* update our integrity descriptor to identify us and timestamp it */
                   1493:        DPRINTF(VOLUMES, ("updating integrity descriptor\n"));
                   1494:        microtime(&now_v);
                   1495:        TIMEVAL_TO_TIMESPEC(&now_v, &now_s);
                   1496:        udf_timespec_to_timestamp(&now_s, &ump->logvol_integrity->time);
                   1497:        udf_set_regid(&ump->logvol_info->impl_id, IMPL_NAME);
                   1498:        udf_add_impl_regid(ump, &ump->logvol_info->impl_id);
                   1499:
                   1500:        /* writeout integrity descriptor */
                   1501:        sector = trace->start + trace->wpos;
                   1502:        error = udf_write_phys_dscr_sync(ump, NULL, UDF_C_DSCR,
                   1503:                        (union dscrptr *) ump->logvol_integrity,
                   1504:                        sector, sector);
                   1505:        DPRINTF(VOLUMES, ("writeout lvint : error = %d\n", error));
                   1506:        if (error)
                   1507:                return error;
                   1508:
                   1509:        /* advance write position */
                   1510:        trace->wpos++; space--;
                   1511:        if (space >= 1) {
                   1512:                /* append terminator */
                   1513:                sector = trace->start + trace->wpos;
                   1514:                error = udf_write_terminator(ump, sector);
                   1515:
                   1516:                DPRINTF(VOLUMES, ("write terminator : error = %d\n", error));
                   1517:        }
                   1518:
                   1519:        space = (trace->end - trace->start) - trace->wpos;
                   1520:        DPRINTF(VOLUMES, ("write start = %d, end = %d, pos = %d, wpos = %d, "
                   1521:                "space = %d\n", trace->start, trace->end, trace->pos,
                   1522:                trace->wpos, space));
                   1523:        DPRINTF(VOLUMES, ("finished writing out logvol integrity descriptor "
1.158     andvar   1524:                "successfully\n"));
1.45      reinoud  1525:
                   1526:        return error;
                   1527: }
                   1528:
                   1529: /* --------------------------------------------------------------------- */
                   1530:
                   1531: static int
1.68      reinoud  1532: udf_read_physical_partition_spacetables(struct udf_mount *ump)
1.45      reinoud  1533: {
                   1534:        union dscrptr        *dscr;
                   1535:        /* struct udf_args *args = &ump->mount_args; */
                   1536:        struct part_desc     *partd;
                   1537:        struct part_hdr_desc *parthdr;
                   1538:        struct udf_bitmap    *bitmap;
                   1539:        uint32_t phys_part;
                   1540:        uint32_t lb_num, len;
                   1541:        int error, dscr_type;
                   1542:
                   1543:        /* unallocated space map */
                   1544:        for (phys_part = 0; phys_part < UDF_PARTITIONS; phys_part++) {
                   1545:                partd = ump->partitions[phys_part];
                   1546:                if (partd == NULL)
                   1547:                        continue;
                   1548:                parthdr = &partd->_impl_use.part_hdr;
                   1549:
                   1550:                lb_num  = udf_rw32(partd->start_loc);
                   1551:                lb_num += udf_rw32(parthdr->unalloc_space_bitmap.lb_num);
                   1552:                len     = udf_rw32(parthdr->unalloc_space_bitmap.len);
                   1553:                if (len == 0)
                   1554:                        continue;
                   1555:
                   1556:                DPRINTF(VOLUMES, ("Read unalloc. space bitmap %d\n", lb_num));
                   1557:                error = udf_read_phys_dscr(ump, lb_num, M_UDFVOLD, &dscr);
                   1558:                if (!error && dscr) {
                   1559:                        /* analyse */
                   1560:                        dscr_type = udf_rw16(dscr->tag.id);
                   1561:                        if (dscr_type == TAGID_SPACE_BITMAP) {
                   1562:                                DPRINTF(VOLUMES, ("Accepting space bitmap\n"));
                   1563:                                ump->part_unalloc_dscr[phys_part] = &dscr->sbd;
                   1564:
                   1565:                                /* fill in ump->part_unalloc_bits */
                   1566:                                bitmap = &ump->part_unalloc_bits[phys_part];
                   1567:                                bitmap->blob  = (uint8_t *) dscr;
                   1568:                                bitmap->bits  = dscr->sbd.data;
                   1569:                                bitmap->max_offset = udf_rw32(dscr->sbd.num_bits);
                   1570:                                bitmap->pages = NULL;   /* TODO */
                   1571:                                bitmap->data_pos     = 0;
                   1572:                                bitmap->metadata_pos = 0;
                   1573:                        } else {
                   1574:                                free(dscr, M_UDFVOLD);
                   1575:
                   1576:                                printf( "UDF mount: error reading unallocated "
                   1577:                                        "space bitmap\n");
                   1578:                                return EROFS;
                   1579:                        }
                   1580:                } else {
                   1581:                        /* blank not allowed */
                   1582:                        printf("UDF mount: blank unallocated space bitmap\n");
                   1583:                        return EROFS;
                   1584:                }
                   1585:        }
                   1586:
                   1587:        /* unallocated space table (not supported) */
                   1588:        for (phys_part = 0; phys_part < UDF_PARTITIONS; phys_part++) {
                   1589:                partd = ump->partitions[phys_part];
                   1590:                if (partd == NULL)
                   1591:                        continue;
                   1592:                parthdr = &partd->_impl_use.part_hdr;
1.152     skrll    1593:
1.45      reinoud  1594:                len     = udf_rw32(parthdr->unalloc_space_table.len);
                   1595:                if (len) {
                   1596:                        printf("UDF mount: space tables not supported\n");
                   1597:                        return EROFS;
                   1598:                }
                   1599:        }
                   1600:
                   1601:        /* freed space map */
                   1602:        for (phys_part = 0; phys_part < UDF_PARTITIONS; phys_part++) {
                   1603:                partd = ump->partitions[phys_part];
                   1604:                if (partd == NULL)
                   1605:                        continue;
                   1606:                parthdr = &partd->_impl_use.part_hdr;
                   1607:
                   1608:                /* freed space map */
                   1609:                lb_num  = udf_rw32(partd->start_loc);
                   1610:                lb_num += udf_rw32(parthdr->freed_space_bitmap.lb_num);
                   1611:                len     = udf_rw32(parthdr->freed_space_bitmap.len);
                   1612:                if (len == 0)
                   1613:                        continue;
                   1614:
                   1615:                DPRINTF(VOLUMES, ("Read unalloc. space bitmap %d\n", lb_num));
                   1616:                error = udf_read_phys_dscr(ump, lb_num, M_UDFVOLD, &dscr);
                   1617:                if (!error && dscr) {
                   1618:                        /* analyse */
                   1619:                        dscr_type = udf_rw16(dscr->tag.id);
                   1620:                        if (dscr_type == TAGID_SPACE_BITMAP) {
                   1621:                                DPRINTF(VOLUMES, ("Accepting space bitmap\n"));
                   1622:                                ump->part_freed_dscr[phys_part] = &dscr->sbd;
                   1623:
                   1624:                                /* fill in ump->part_freed_bits */
                   1625:                                bitmap = &ump->part_unalloc_bits[phys_part];
                   1626:                                bitmap->blob  = (uint8_t *) dscr;
                   1627:                                bitmap->bits  = dscr->sbd.data;
                   1628:                                bitmap->max_offset = udf_rw32(dscr->sbd.num_bits);
                   1629:                                bitmap->pages = NULL;   /* TODO */
                   1630:                                bitmap->data_pos     = 0;
                   1631:                                bitmap->metadata_pos = 0;
                   1632:                        } else {
                   1633:                                free(dscr, M_UDFVOLD);
                   1634:
                   1635:                                printf( "UDF mount: error reading freed  "
                   1636:                                        "space bitmap\n");
                   1637:                                return EROFS;
                   1638:                        }
                   1639:                } else {
                   1640:                        /* blank not allowed */
                   1641:                        printf("UDF mount: blank freed space bitmap\n");
                   1642:                        return EROFS;
                   1643:                }
                   1644:        }
                   1645:
                   1646:        /* freed space table (not supported) */
                   1647:        for (phys_part = 0; phys_part < UDF_PARTITIONS; phys_part++) {
                   1648:                partd = ump->partitions[phys_part];
                   1649:                if (partd == NULL)
                   1650:                        continue;
                   1651:                parthdr = &partd->_impl_use.part_hdr;
1.152     skrll    1652:
1.45      reinoud  1653:                len     = udf_rw32(parthdr->freed_space_table.len);
                   1654:                if (len) {
                   1655:                        printf("UDF mount: space tables not supported\n");
                   1656:                        return EROFS;
                   1657:                }
                   1658:        }
                   1659:
                   1660:        return 0;
                   1661: }
                   1662:
                   1663:
                   1664: /* TODO implement async writeout */
                   1665: int
1.68      reinoud  1666: udf_write_physical_partition_spacetables(struct udf_mount *ump, int waitfor)
1.45      reinoud  1667: {
                   1668:        union dscrptr        *dscr;
                   1669:        /* struct udf_args *args = &ump->mount_args; */
                   1670:        struct part_desc     *partd;
                   1671:        struct part_hdr_desc *parthdr;
                   1672:        uint32_t phys_part;
                   1673:        uint32_t lb_num, len, ptov;
                   1674:        int error_all, error;
                   1675:
                   1676:        error_all = 0;
                   1677:        /* unallocated space map */
                   1678:        for (phys_part = 0; phys_part < UDF_PARTITIONS; phys_part++) {
                   1679:                partd = ump->partitions[phys_part];
                   1680:                if (partd == NULL)
                   1681:                        continue;
                   1682:                parthdr = &partd->_impl_use.part_hdr;
                   1683:
                   1684:                ptov   = udf_rw32(partd->start_loc);
                   1685:                lb_num = udf_rw32(parthdr->unalloc_space_bitmap.lb_num);
                   1686:                len    = udf_rw32(parthdr->unalloc_space_bitmap.len);
                   1687:                if (len == 0)
                   1688:                        continue;
                   1689:
                   1690:                DPRINTF(VOLUMES, ("Write unalloc. space bitmap %d\n",
                   1691:                        lb_num + ptov));
                   1692:                dscr = (union dscrptr *) ump->part_unalloc_dscr[phys_part];
1.142     reinoud  1693:
                   1694:                /* force a sane minimum for descriptors CRC length */
                   1695:                /* see UDF 2.3.1.2 and 2.3.8.1 */
                   1696:                KASSERT(udf_rw16(dscr->sbd.tag.id) == TAGID_SPACE_BITMAP);
                   1697:                if (udf_rw16(dscr->sbd.tag.desc_crc_len) == 0)
                   1698:                        dscr->sbd.tag.desc_crc_len = udf_rw16(8);
                   1699:
                   1700:                /* write out space bitmap */
1.45      reinoud  1701:                error = udf_write_phys_dscr_sync(ump, NULL, UDF_C_DSCR,
                   1702:                                (union dscrptr *) dscr,
                   1703:                                ptov + lb_num, lb_num);
                   1704:                if (error) {
                   1705:                        DPRINTF(VOLUMES, ("\tfailed!! (error %d)\n", error));
                   1706:                        error_all = error;
                   1707:                }
                   1708:        }
                   1709:
                   1710:        /* freed space map */
                   1711:        for (phys_part = 0; phys_part < UDF_PARTITIONS; phys_part++) {
                   1712:                partd = ump->partitions[phys_part];
                   1713:                if (partd == NULL)
                   1714:                        continue;
                   1715:                parthdr = &partd->_impl_use.part_hdr;
                   1716:
                   1717:                /* freed space map */
                   1718:                ptov   = udf_rw32(partd->start_loc);
                   1719:                lb_num = udf_rw32(parthdr->freed_space_bitmap.lb_num);
                   1720:                len    = udf_rw32(parthdr->freed_space_bitmap.len);
                   1721:                if (len == 0)
                   1722:                        continue;
                   1723:
                   1724:                DPRINTF(VOLUMES, ("Write freed space bitmap %d\n",
                   1725:                        lb_num + ptov));
                   1726:                dscr = (union dscrptr *) ump->part_freed_dscr[phys_part];
1.142     reinoud  1727:
                   1728:                /* force a sane minimum for descriptors CRC length */
                   1729:                /* see UDF 2.3.1.2 and 2.3.8.1 */
                   1730:                KASSERT(udf_rw16(dscr->sbd.tag.id) == TAGID_SPACE_BITMAP);
                   1731:                if (udf_rw16(dscr->sbd.tag.desc_crc_len) == 0)
                   1732:                        dscr->sbd.tag.desc_crc_len = udf_rw16(8);
                   1733:
                   1734:                /* write out space bitmap */
1.45      reinoud  1735:                error = udf_write_phys_dscr_sync(ump, NULL, UDF_C_DSCR,
                   1736:                                (union dscrptr *) dscr,
                   1737:                                ptov + lb_num, lb_num);
                   1738:                if (error) {
                   1739:                        DPRINTF(VOLUMES, ("\tfailed!! (error %d)\n", error));
                   1740:                        error_all = error;
                   1741:                }
                   1742:        }
                   1743:
                   1744:        return error_all;
                   1745: }
                   1746:
1.70      reinoud  1747:
                   1748: static int
                   1749: udf_read_metadata_partition_spacetable(struct udf_mount *ump)
                   1750: {
                   1751:        struct udf_node      *bitmap_node;
                   1752:        union dscrptr        *dscr;
                   1753:        struct udf_bitmap    *bitmap;
                   1754:        uint64_t inflen;
                   1755:        int error, dscr_type;
                   1756:
                   1757:        bitmap_node = ump->metadatabitmap_node;
                   1758:
                   1759:        /* only read in when metadata bitmap node is read in */
                   1760:        if (bitmap_node == NULL)
                   1761:                return 0;
                   1762:
                   1763:        if (bitmap_node->fe) {
                   1764:                inflen = udf_rw64(bitmap_node->fe->inf_len);
                   1765:        } else {
                   1766:                KASSERT(bitmap_node->efe);
                   1767:                inflen = udf_rw64(bitmap_node->efe->inf_len);
                   1768:        }
                   1769:
                   1770:        DPRINTF(VOLUMES, ("Reading metadata space bitmap for "
                   1771:                "%"PRIu64" bytes\n", inflen));
                   1772:
                   1773:        /* allocate space for bitmap */
1.144     jdolecek 1774:        dscr = malloc(inflen, M_UDFVOLD, M_WAITOK);
1.70      reinoud  1775:        if (!dscr)
                   1776:                return ENOMEM;
                   1777:
                   1778:        /* set vnode type to regular file or we can't read from it! */
                   1779:        bitmap_node->vnode->v_type = VREG;
                   1780:
                   1781:        /* read in complete metadata bitmap file */
                   1782:        error = vn_rdwr(UIO_READ, bitmap_node->vnode,
                   1783:                        dscr,
                   1784:                        inflen, 0,
                   1785:                        UIO_SYSSPACE,
1.109     reinoud  1786:                        IO_SYNC | IO_ALTSEMANTICS, FSCRED,
1.70      reinoud  1787:                        NULL, NULL);
                   1788:        if (error) {
                   1789:                DPRINTF(VOLUMES, ("Error reading metadata space bitmap\n"));
                   1790:                goto errorout;
                   1791:        }
                   1792:
                   1793:        /* analyse */
                   1794:        dscr_type = udf_rw16(dscr->tag.id);
                   1795:        if (dscr_type == TAGID_SPACE_BITMAP) {
                   1796:                DPRINTF(VOLUMES, ("Accepting metadata space bitmap\n"));
                   1797:                ump->metadata_unalloc_dscr = &dscr->sbd;
                   1798:
                   1799:                /* fill in bitmap bits */
                   1800:                bitmap = &ump->metadata_unalloc_bits;
                   1801:                bitmap->blob  = (uint8_t *) dscr;
                   1802:                bitmap->bits  = dscr->sbd.data;
                   1803:                bitmap->max_offset = udf_rw32(dscr->sbd.num_bits);
                   1804:                bitmap->pages = NULL;   /* TODO */
                   1805:                bitmap->data_pos     = 0;
                   1806:                bitmap->metadata_pos = 0;
                   1807:        } else {
                   1808:                DPRINTF(VOLUMES, ("No valid bitmap found!\n"));
                   1809:                goto errorout;
                   1810:        }
                   1811:
                   1812:        return 0;
                   1813:
                   1814: errorout:
                   1815:        free(dscr, M_UDFVOLD);
                   1816:        printf( "UDF mount: error reading unallocated "
                   1817:                "space bitmap for metadata partition\n");
                   1818:        return EROFS;
                   1819: }
                   1820:
                   1821:
                   1822: int
                   1823: udf_write_metadata_partition_spacetable(struct udf_mount *ump, int waitfor)
                   1824: {
                   1825:        struct udf_node      *bitmap_node;
                   1826:        union dscrptr        *dscr;
1.121     christos 1827:        uint64_t new_inflen;
1.70      reinoud  1828:        int dummy, error;
                   1829:
                   1830:        bitmap_node = ump->metadatabitmap_node;
                   1831:
                   1832:        /* only write out when metadata bitmap node is known */
                   1833:        if (bitmap_node == NULL)
                   1834:                return 0;
                   1835:
1.121     christos 1836:        if (!bitmap_node->fe) {
1.70      reinoud  1837:                KASSERT(bitmap_node->efe);
                   1838:        }
                   1839:
                   1840:        /* reduce length to zero */
                   1841:        dscr = (union dscrptr *) ump->metadata_unalloc_dscr;
                   1842:        new_inflen = udf_tagsize(dscr, 1);
                   1843:
1.125     reinoud  1844:        DPRINTF(VOLUMES, ("Resize and write out metadata space bitmap "
                   1845:                " for %"PRIu64" bytes\n", new_inflen));
1.70      reinoud  1846:
1.71      reinoud  1847:        error = udf_resize_node(bitmap_node, new_inflen, &dummy);
1.70      reinoud  1848:        if (error)
                   1849:                printf("Error resizing metadata space bitmap\n");
                   1850:
                   1851:        error = vn_rdwr(UIO_WRITE, bitmap_node->vnode,
                   1852:                        dscr,
                   1853:                        new_inflen, 0,
                   1854:                        UIO_SYSSPACE,
1.109     reinoud  1855:                        IO_ALTSEMANTICS, FSCRED,
1.70      reinoud  1856:                        NULL, NULL);
                   1857:
                   1858:        bitmap_node->i_flags |= IN_MODIFIED;
1.119     chs      1859:        error = vflushbuf(bitmap_node->vnode, FSYNC_WAIT);
1.114     hannken  1860:        if (error == 0)
                   1861:                error = VOP_FSYNC(bitmap_node->vnode,
                   1862:                                FSCRED, FSYNC_WAIT, 0, 0);
1.70      reinoud  1863:
                   1864:        if (error)
                   1865:                printf( "Error writing out metadata partition unalloced "
                   1866:                        "space bitmap!\n");
                   1867:
                   1868:        return error;
                   1869: }
                   1870:
                   1871:
                   1872: /* --------------------------------------------------------------------- */
                   1873:
1.45      reinoud  1874: /*
                   1875:  * Checks if ump's vds information is correct and complete
                   1876:  */
                   1877:
                   1878: int
                   1879: udf_process_vds(struct udf_mount *ump) {
                   1880:        union udf_pmap *mapping;
                   1881:        /* struct udf_args *args = &ump->mount_args; */
                   1882:        struct logvol_int_desc *lvint;
                   1883:        struct udf_logvol_info *lvinfo;
1.121     christos 1884:        uint32_t n_pm;
1.45      reinoud  1885:        uint8_t *pmap_pos;
                   1886:        char *domain_name, *map_name;
                   1887:        const char *check_name;
                   1888:        char bits[128];
                   1889:        int pmap_stype, pmap_size;
1.71      reinoud  1890:        int pmap_type, log_part, phys_part, raw_phys_part, maps_on;
1.45      reinoud  1891:        int n_phys, n_virt, n_spar, n_meta;
1.121     christos 1892:        int len;
1.45      reinoud  1893:
                   1894:        if (ump == NULL)
                   1895:                return ENOENT;
                   1896:
                   1897:        /* we need at least an anchor (trivial, but for safety) */
                   1898:        if (ump->anchors[0] == NULL)
                   1899:                return EINVAL;
                   1900:
                   1901:        /* we need at least one primary and one logical volume descriptor */
                   1902:        if ((ump->primary_vol == NULL) || (ump->logical_vol) == NULL)
                   1903:                return EINVAL;
                   1904:
                   1905:        /* we need at least one partition descriptor */
                   1906:        if (ump->partitions[0] == NULL)
                   1907:                return EINVAL;
                   1908:
                   1909:        /* check logical volume sector size verses device sector size */
                   1910:        if (udf_rw32(ump->logical_vol->lb_size) != ump->discinfo.sector_size) {
                   1911:                printf("UDF mount: format violation, lb_size != sector size\n");
                   1912:                return EINVAL;
                   1913:        }
                   1914:
                   1915:        /* check domain name */
                   1916:        domain_name = ump->logical_vol->domain_id.id;
                   1917:        if (strncmp(domain_name, "*OSTA UDF Compliant", 20)) {
                   1918:                printf("mount_udf: disc not OSTA UDF Compliant, aborting\n");
                   1919:                return EINVAL;
                   1920:        }
                   1921:
                   1922:        /* retrieve logical volume integrity sequence */
1.121     christos 1923:        (void)udf_retrieve_lvint(ump);
1.45      reinoud  1924:
                   1925:        /*
                   1926:         * We need at least one logvol integrity descriptor recorded.  Note
                   1927:         * that its OK to have an open logical volume integrity here. The VAT
                   1928:         * will close/update the integrity.
                   1929:         */
                   1930:        if (ump->logvol_integrity == NULL)
                   1931:                return EINVAL;
                   1932:
                   1933:        /* process derived structures */
                   1934:        n_pm   = udf_rw32(ump->logical_vol->n_pm);   /* num partmaps         */
                   1935:        lvint  = ump->logvol_integrity;
                   1936:        lvinfo = (struct udf_logvol_info *) (&lvint->tables[2 * n_pm]);
                   1937:        ump->logvol_info = lvinfo;
                   1938:
                   1939:        /* TODO check udf versions? */
                   1940:
                   1941:        /*
                   1942:         * check logvol mappings: effective virt->log partmap translation
                   1943:         * check and recording of the mapping results. Saves expensive
                   1944:         * strncmp() in tight places.
                   1945:         */
                   1946:        DPRINTF(VOLUMES, ("checking logvol mappings\n"));
                   1947:        n_pm = udf_rw32(ump->logical_vol->n_pm);   /* num partmaps         */
                   1948:        pmap_pos =  ump->logical_vol->maps;
                   1949:
                   1950:        if (n_pm > UDF_PMAPS) {
                   1951:                printf("UDF mount: too many mappings\n");
                   1952:                return EINVAL;
                   1953:        }
                   1954:
1.71      reinoud  1955:        /* count types and set partition numbers */
                   1956:        ump->data_part = ump->node_part = ump->fids_part = 0;
1.45      reinoud  1957:        n_phys = n_virt = n_spar = n_meta = 0;
                   1958:        for (log_part = 0; log_part < n_pm; log_part++) {
                   1959:                mapping = (union udf_pmap *) pmap_pos;
                   1960:                pmap_stype = pmap_pos[0];
                   1961:                pmap_size  = pmap_pos[1];
                   1962:                switch (pmap_stype) {
                   1963:                case 1: /* physical mapping */
                   1964:                        /* volseq    = udf_rw16(mapping->pm1.vol_seq_num); */
                   1965:                        raw_phys_part = udf_rw16(mapping->pm1.part_num);
                   1966:                        pmap_type = UDF_VTOP_TYPE_PHYS;
                   1967:                        n_phys++;
1.71      reinoud  1968:                        ump->data_part = log_part;
                   1969:                        ump->node_part = log_part;
                   1970:                        ump->fids_part = log_part;
1.45      reinoud  1971:                        break;
                   1972:                case 2: /* virtual/sparable/meta mapping */
                   1973:                        map_name  = mapping->pm2.part_id.id;
                   1974:                        /* volseq  = udf_rw16(mapping->pm2.vol_seq_num); */
                   1975:                        raw_phys_part = udf_rw16(mapping->pm2.part_num);
                   1976:                        pmap_type = UDF_VTOP_TYPE_UNKNOWN;
                   1977:                        len = UDF_REGID_ID_SIZE;
                   1978:
                   1979:                        check_name = "*UDF Virtual Partition";
                   1980:                        if (strncmp(map_name, check_name, len) == 0) {
                   1981:                                pmap_type = UDF_VTOP_TYPE_VIRT;
                   1982:                                n_virt++;
1.71      reinoud  1983:                                ump->node_part = log_part;
1.45      reinoud  1984:                                break;
                   1985:                        }
                   1986:                        check_name = "*UDF Sparable Partition";
                   1987:                        if (strncmp(map_name, check_name, len) == 0) {
                   1988:                                pmap_type = UDF_VTOP_TYPE_SPARABLE;
                   1989:                                n_spar++;
1.71      reinoud  1990:                                ump->data_part = log_part;
                   1991:                                ump->node_part = log_part;
                   1992:                                ump->fids_part = log_part;
1.45      reinoud  1993:                                break;
                   1994:                        }
                   1995:                        check_name = "*UDF Metadata Partition";
                   1996:                        if (strncmp(map_name, check_name, len) == 0) {
                   1997:                                pmap_type = UDF_VTOP_TYPE_META;
                   1998:                                n_meta++;
1.71      reinoud  1999:                                ump->node_part = log_part;
                   2000:                                ump->fids_part = log_part;
1.45      reinoud  2001:                                break;
                   2002:                        }
                   2003:                        break;
                   2004:                default:
                   2005:                        return EINVAL;
                   2006:                }
                   2007:
                   2008:                /*
                   2009:                 * BUGALERT: some rogue implementations use random physical
1.100     mbalmer  2010:                 * partition numbers to break other implementations so lookup
1.45      reinoud  2011:                 * the number.
                   2012:                 */
1.111     reinoud  2013:                phys_part = udf_find_raw_phys(ump, raw_phys_part);
1.45      reinoud  2014:
                   2015:                DPRINTF(VOLUMES, ("\t%d -> %d(%d) type %d\n", log_part,
                   2016:                    raw_phys_part, phys_part, pmap_type));
1.152     skrll    2017:
1.45      reinoud  2018:                if (phys_part == UDF_PARTITIONS)
                   2019:                        return EINVAL;
                   2020:                if (pmap_type == UDF_VTOP_TYPE_UNKNOWN)
                   2021:                        return EINVAL;
                   2022:
                   2023:                ump->vtop   [log_part] = phys_part;
                   2024:                ump->vtop_tp[log_part] = pmap_type;
                   2025:
                   2026:                pmap_pos += pmap_size;
                   2027:        }
                   2028:        /* not winning the beauty contest */
                   2029:        ump->vtop_tp[UDF_VTOP_RAWPART] = UDF_VTOP_TYPE_RAW;
                   2030:
                   2031:        /* test some basic UDF assertions/requirements */
                   2032:        if ((n_virt > 1) || (n_spar > 1) || (n_meta > 1))
                   2033:                return EINVAL;
                   2034:
                   2035:        if (n_virt) {
                   2036:                if ((n_phys == 0) || n_spar || n_meta)
                   2037:                        return EINVAL;
                   2038:        }
                   2039:        if (n_spar + n_phys == 0)
                   2040:                return EINVAL;
                   2041:
1.71      reinoud  2042:        /* select allocation type for each logical partition */
                   2043:        for (log_part = 0; log_part < n_pm; log_part++) {
                   2044:                maps_on = ump->vtop[log_part];
                   2045:                switch (ump->vtop_tp[log_part]) {
                   2046:                case UDF_VTOP_TYPE_PHYS :
                   2047:                        assert(maps_on == log_part);
                   2048:                        ump->vtop_alloc[log_part] = UDF_ALLOC_SPACEMAP;
                   2049:                        break;
                   2050:                case UDF_VTOP_TYPE_VIRT :
                   2051:                        ump->vtop_alloc[log_part] = UDF_ALLOC_VAT;
                   2052:                        ump->vtop_alloc[maps_on]  = UDF_ALLOC_SEQUENTIAL;
                   2053:                        break;
                   2054:                case UDF_VTOP_TYPE_SPARABLE :
                   2055:                        assert(maps_on == log_part);
                   2056:                        ump->vtop_alloc[log_part] = UDF_ALLOC_SPACEMAP;
                   2057:                        break;
                   2058:                case UDF_VTOP_TYPE_META :
                   2059:                        ump->vtop_alloc[log_part] = UDF_ALLOC_METABITMAP;
                   2060:                        if (ump->discinfo.mmc_cur & MMC_CAP_PSEUDOOVERWRITE) {
                   2061:                                /* special case for UDF 2.60 */
                   2062:                                ump->vtop_alloc[log_part] = UDF_ALLOC_METASEQUENTIAL;
                   2063:                                ump->vtop_alloc[maps_on]  = UDF_ALLOC_SEQUENTIAL;
                   2064:                        }
                   2065:                        break;
                   2066:                default:
1.159     msaitoh  2067:                        panic("bad allocation type in udf's ump->vtop\n");
1.45      reinoud  2068:                }
                   2069:        }
                   2070:
                   2071:        /* determine logical volume open/closure actions */
                   2072:        if (n_virt) {
                   2073:                ump->lvopen  = 0;
1.85      reinoud  2074:                if (ump->discinfo.last_session_state == MMC_STATE_EMPTY)
1.45      reinoud  2075:                        ump->lvopen |= UDF_OPEN_SESSION ;
                   2076:                ump->lvclose = UDF_WRITE_VAT;
                   2077:                if (ump->mount_args.udfmflags & UDFMNT_CLOSESESSION)
                   2078:                        ump->lvclose |= UDF_CLOSE_SESSION;
                   2079:        } else {
                   2080:                /* `normal' rewritable or non sequential media */
                   2081:                ump->lvopen  = UDF_WRITE_LVINT;
                   2082:                ump->lvclose = UDF_WRITE_LVINT;
                   2083:                if ((ump->discinfo.mmc_cur & MMC_CAP_REWRITABLE) == 0)
1.113     reinoud  2084:                        ump->lvopen  |=  UDF_APPENDONLY_LVINT;
                   2085:                if ((ump->discinfo.mmc_cur & MMC_CAP_PSEUDOOVERWRITE))
                   2086:                        ump->lvopen  &= ~UDF_APPENDONLY_LVINT;
1.45      reinoud  2087:        }
                   2088:
                   2089:        /*
1.100     mbalmer  2090:         * Determine sheduler error behaviour. For virtual partitions, update
1.45      reinoud  2091:         * the trackinfo; for sparable partitions replace a whole block on the
1.154     andvar   2092:         * sparable table. Always requeue.
1.45      reinoud  2093:         */
                   2094:        ump->lvreadwrite = 0;
                   2095:        if (n_virt)
                   2096:                ump->lvreadwrite = UDF_UPDATE_TRACKINFO;
                   2097:        if (n_spar)
                   2098:                ump->lvreadwrite = UDF_REMAP_BLOCK;
                   2099:
                   2100:        /*
                   2101:         * Select our sheduler
                   2102:         */
                   2103:        ump->strategy = &udf_strat_rmw;
                   2104:        if (n_virt || (ump->discinfo.mmc_cur & MMC_CAP_PSEUDOOVERWRITE))
                   2105:                ump->strategy = &udf_strat_sequential;
                   2106:        if ((ump->discinfo.mmc_class == MMC_CLASS_DISC) ||
                   2107:                (ump->discinfo.mmc_class == MMC_CLASS_UNKN))
                   2108:                        ump->strategy = &udf_strat_direct;
                   2109:        if (n_spar)
                   2110:                ump->strategy = &udf_strat_rmw;
                   2111:
1.75      reinoud  2112: #if 0
                   2113:        /* read-only access won't benefit from the other shedulers */
                   2114:        if (ump->vfs_mountp->mnt_flag & MNT_RDONLY)
                   2115:                ump->strategy = &udf_strat_direct;
                   2116: #endif
                   2117:
1.45      reinoud  2118:        /* print results */
1.71      reinoud  2119:        DPRINTF(VOLUMES, ("\tdata partition    %d\n", ump->data_part));
                   2120:        DPRINTF(VOLUMES, ("\t\talloc scheme %d\n", ump->vtop_alloc[ump->data_part]));
                   2121:        DPRINTF(VOLUMES, ("\tnode partition    %d\n", ump->node_part));
                   2122:        DPRINTF(VOLUMES, ("\t\talloc scheme %d\n", ump->vtop_alloc[ump->node_part]));
                   2123:        DPRINTF(VOLUMES, ("\tfids partition    %d\n", ump->fids_part));
                   2124:        DPRINTF(VOLUMES, ("\t\talloc scheme %d\n", ump->vtop_alloc[ump->fids_part]));
1.45      reinoud  2125:
1.80      christos 2126:        snprintb(bits, sizeof(bits), UDFLOGVOL_BITS, ump->lvopen);
1.45      reinoud  2127:        DPRINTF(VOLUMES, ("\tactions on logvol open  %s\n", bits));
1.80      christos 2128:        snprintb(bits, sizeof(bits), UDFLOGVOL_BITS, ump->lvclose);
1.45      reinoud  2129:        DPRINTF(VOLUMES, ("\tactions on logvol close %s\n", bits));
1.80      christos 2130:        snprintb(bits, sizeof(bits), UDFONERROR_BITS, ump->lvreadwrite);
1.45      reinoud  2131:        DPRINTF(VOLUMES, ("\tactions on logvol errors %s\n", bits));
                   2132:
1.152     skrll    2133:        DPRINTF(VOLUMES, ("\tselected sheduler `%s`\n",
1.45      reinoud  2134:                (ump->strategy == &udf_strat_direct) ? "Direct" :
                   2135:                (ump->strategy == &udf_strat_sequential) ? "Sequential" :
                   2136:                (ump->strategy == &udf_strat_rmw) ? "RMW" : "UNKNOWN!"));
                   2137:
                   2138:        /* signal its OK for now */
                   2139:        return 0;
                   2140: }
                   2141:
                   2142: /* --------------------------------------------------------------------- */
                   2143:
                   2144: /*
                   2145:  * Update logical volume name in all structures that keep a record of it. We
                   2146:  * use memmove since each of them might be specified as a source.
                   2147:  *
                   2148:  * Note that it doesn't update the VAT structure!
                   2149:  */
                   2150:
                   2151: static void
                   2152: udf_update_logvolname(struct udf_mount *ump, char *logvol_id)
                   2153: {
                   2154:        struct logvol_desc     *lvd = NULL;
                   2155:        struct fileset_desc    *fsd = NULL;
                   2156:        struct udf_lv_info     *lvi = NULL;
                   2157:
                   2158:        DPRINTF(VOLUMES, ("Updating logical volume name\n"));
                   2159:        lvd = ump->logical_vol;
                   2160:        fsd = ump->fileset_desc;
                   2161:        if (ump->implementation)
                   2162:                lvi = &ump->implementation->_impl_use.lv_info;
                   2163:
                   2164:        /* logvol's id might be specified as origional so use memmove here */
                   2165:        memmove(lvd->logvol_id, logvol_id, 128);
                   2166:        if (fsd)
                   2167:                memmove(fsd->logvol_id, logvol_id, 128);
                   2168:        if (lvi)
                   2169:                memmove(lvi->logvol_id, logvol_id, 128);
                   2170: }
                   2171:
                   2172: /* --------------------------------------------------------------------- */
                   2173:
1.55      reinoud  2174: void
1.51      reinoud  2175: udf_inittag(struct udf_mount *ump, struct desc_tag *tag, int tagid,
                   2176:        uint32_t sector)
                   2177: {
                   2178:        assert(ump->logical_vol);
                   2179:
                   2180:        tag->id                 = udf_rw16(tagid);
                   2181:        tag->descriptor_ver     = ump->logical_vol->tag.descriptor_ver;
                   2182:        tag->cksum              = 0;
                   2183:        tag->reserved           = 0;
                   2184:        tag->serial_num         = ump->logical_vol->tag.serial_num;
                   2185:        tag->tag_loc            = udf_rw32(sector);
                   2186: }
                   2187:
                   2188:
                   2189: uint64_t
                   2190: udf_advance_uniqueid(struct udf_mount *ump)
                   2191: {
                   2192:        uint64_t unique_id;
                   2193:
                   2194:        mutex_enter(&ump->logvol_mutex);
                   2195:        unique_id = udf_rw64(ump->logvol_integrity->lvint_next_unique_id);
                   2196:        if (unique_id < 0x10)
                   2197:                unique_id = 0x10;
                   2198:        ump->logvol_integrity->lvint_next_unique_id = udf_rw64(unique_id + 1);
                   2199:        mutex_exit(&ump->logvol_mutex);
                   2200:
                   2201:        return unique_id;
                   2202: }
                   2203:
                   2204:
                   2205: static void
                   2206: udf_adjust_filecount(struct udf_node *udf_node, int sign)
                   2207: {
                   2208:        struct udf_mount *ump = udf_node->ump;
                   2209:        uint32_t num_dirs, num_files;
                   2210:        int udf_file_type;
                   2211:
                   2212:        /* get file type */
                   2213:        if (udf_node->fe) {
                   2214:                udf_file_type = udf_node->fe->icbtag.file_type;
                   2215:        } else {
                   2216:                udf_file_type = udf_node->efe->icbtag.file_type;
                   2217:        }
                   2218:
                   2219:        /* adjust file count */
                   2220:        mutex_enter(&ump->allocate_mutex);
                   2221:        if (udf_file_type == UDF_ICB_FILETYPE_DIRECTORY) {
                   2222:                num_dirs = udf_rw32(ump->logvol_info->num_directories);
                   2223:                ump->logvol_info->num_directories =
                   2224:                        udf_rw32((num_dirs + sign));
                   2225:        } else {
                   2226:                num_files = udf_rw32(ump->logvol_info->num_files);
                   2227:                ump->logvol_info->num_files =
                   2228:                        udf_rw32((num_files + sign));
                   2229:        }
                   2230:        mutex_exit(&ump->allocate_mutex);
                   2231: }
                   2232:
                   2233:
                   2234: void
                   2235: udf_osta_charset(struct charspec *charspec)
                   2236: {
1.87      cegger   2237:        memset(charspec, 0, sizeof(struct charspec));
1.51      reinoud  2238:        charspec->type = 0;
                   2239:        strcpy((char *) charspec->inf, "OSTA Compressed Unicode");
                   2240: }
                   2241:
                   2242:
                   2243: /* first call udf_set_regid and then the suffix */
                   2244: void
                   2245: udf_set_regid(struct regid *regid, char const *name)
                   2246: {
1.87      cegger   2247:        memset(regid, 0, sizeof(struct regid));
1.51      reinoud  2248:        regid->flags    = 0;            /* not dirty and not protected */
                   2249:        strcpy((char *) regid->id, name);
                   2250: }
                   2251:
                   2252:
                   2253: void
                   2254: udf_add_domain_regid(struct udf_mount *ump, struct regid *regid)
                   2255: {
                   2256:        uint16_t *ver;
                   2257:
                   2258:        ver  = (uint16_t *) regid->id_suffix;
                   2259:        *ver = ump->logvol_info->min_udf_readver;
                   2260: }
                   2261:
                   2262:
                   2263: void
                   2264: udf_add_udf_regid(struct udf_mount *ump, struct regid *regid)
                   2265: {
                   2266:        uint16_t *ver;
                   2267:
                   2268:        ver  = (uint16_t *) regid->id_suffix;
                   2269:        *ver = ump->logvol_info->min_udf_readver;
                   2270:
                   2271:        regid->id_suffix[2] = 4;        /* unix */
                   2272:        regid->id_suffix[3] = 8;        /* NetBSD */
                   2273: }
                   2274:
                   2275:
                   2276: void
                   2277: udf_add_impl_regid(struct udf_mount *ump, struct regid *regid)
                   2278: {
                   2279:        regid->id_suffix[0] = 4;        /* unix */
                   2280:        regid->id_suffix[1] = 8;        /* NetBSD */
                   2281: }
                   2282:
                   2283:
                   2284: void
                   2285: udf_add_app_regid(struct udf_mount *ump, struct regid *regid)
                   2286: {
                   2287:        regid->id_suffix[0] = APP_VERSION_MAIN;
                   2288:        regid->id_suffix[1] = APP_VERSION_SUB;
                   2289: }
                   2290:
                   2291: static int
                   2292: udf_create_parentfid(struct udf_mount *ump, struct fileid_desc *fid,
                   2293:        struct long_ad *parent, uint64_t unique_id)
                   2294: {
                   2295:        /* the size of an empty FID is 38 but needs to be a multiple of 4 */
                   2296:        int fidsize = 40;
                   2297:
                   2298:        udf_inittag(ump, &fid->tag, TAGID_FID, udf_rw32(parent->loc.lb_num));
                   2299:        fid->file_version_num = udf_rw16(1);    /* UDF 2.3.4.1 */
                   2300:        fid->file_char = UDF_FILE_CHAR_DIR | UDF_FILE_CHAR_PAR;
                   2301:        fid->icb = *parent;
                   2302:        fid->icb.longad_uniqueid = udf_rw32((uint32_t) unique_id);
1.88      reinoud  2303:        fid->tag.desc_crc_len = udf_rw16(fidsize - UDF_DESC_TAG_LENGTH);
1.51      reinoud  2304:        (void) udf_validate_tag_and_crc_sums((union dscrptr *) fid);
                   2305:
                   2306:        return fidsize;
                   2307: }
                   2308:
                   2309: /* --------------------------------------------------------------------- */
                   2310:
1.45      reinoud  2311: /*
1.51      reinoud  2312:  * Extended attribute support. UDF knows of 3 places for extended attributes:
1.45      reinoud  2313:  *
1.51      reinoud  2314:  * (a) inside the file's (e)fe in the length of the extended attribute area
                   2315:  * before the allocation descriptors/filedata
1.45      reinoud  2316:  *
1.152     skrll    2317:  * (b) in a file referenced by (e)fe->ext_attr_icb and
1.45      reinoud  2318:  *
                   2319:  * (c) in the e(fe)'s associated stream directory that can hold various
                   2320:  * sub-files. In the stream directory a few fixed named subfiles are reserved
                   2321:  * for NT/Unix ACL's and OS/2 attributes.
1.152     skrll    2322:  *
1.154     andvar   2323:  * NOTE: Extended attributes are read randomly but always written
                   2324:  * *atomically*. For ACL's this interface is probably different but not known
1.45      reinoud  2325:  * to me yet.
1.51      reinoud  2326:  *
1.154     andvar   2327:  * Order of extended attributes in a space:
1.51      reinoud  2328:  *   ECMA 167 EAs
                   2329:  *   Non block aligned Implementation Use EAs
                   2330:  *   Block aligned Implementation Use EAs
                   2331:  *   Application Use EAs
1.45      reinoud  2332:  */
                   2333:
                   2334: static int
                   2335: udf_impl_extattr_check(struct impl_extattr_entry *implext)
                   2336: {
                   2337:        uint16_t   *spos;
                   2338:
                   2339:        if (strncmp(implext->imp_id.id, "*UDF", 4) == 0) {
                   2340:                /* checksum valid? */
                   2341:                DPRINTF(EXTATTR, ("checking UDF impl. attr checksum\n"));
                   2342:                spos = (uint16_t *) implext->data;
                   2343:                if (udf_rw16(*spos) != udf_ea_cksum((uint8_t *) implext))
                   2344:                        return EINVAL;
                   2345:        }
                   2346:        return 0;
                   2347: }
                   2348:
                   2349: static void
                   2350: udf_calc_impl_extattr_checksum(struct impl_extattr_entry *implext)
                   2351: {
                   2352:        uint16_t   *spos;
                   2353:
                   2354:        if (strncmp(implext->imp_id.id, "*UDF", 4) == 0) {
                   2355:                /* set checksum */
                   2356:                spos = (uint16_t *) implext->data;
                   2357:                *spos = udf_rw16(udf_ea_cksum((uint8_t *) implext));
                   2358:        }
                   2359: }
                   2360:
                   2361:
                   2362: int
                   2363: udf_extattr_search_intern(struct udf_node *node,
                   2364:        uint32_t sattr, char const *sattrname,
                   2365:        uint32_t *offsetp, uint32_t *lengthp)
                   2366: {
                   2367:        struct extattrhdr_desc    *eahdr;
                   2368:        struct extattr_entry      *attrhdr;
                   2369:        struct impl_extattr_entry *implext;
                   2370:        uint32_t    offset, a_l, sector_size;
                   2371:         int32_t    l_ea;
                   2372:        uint8_t    *pos;
                   2373:        int         error;
                   2374:
                   2375:        /* get mountpoint */
                   2376:        sector_size = node->ump->discinfo.sector_size;
                   2377:
                   2378:        /* get information from fe/efe */
                   2379:        if (node->fe) {
                   2380:                l_ea  = udf_rw32(node->fe->l_ea);
                   2381:                eahdr = (struct extattrhdr_desc *) node->fe->data;
                   2382:        } else {
                   2383:                assert(node->efe);
                   2384:                l_ea  = udf_rw32(node->efe->l_ea);
                   2385:                eahdr = (struct extattrhdr_desc *) node->efe->data;
                   2386:        }
                   2387:
                   2388:        /* something recorded here? */
                   2389:        if (l_ea == 0)
                   2390:                return ENOENT;
                   2391:
                   2392:        /* check extended attribute tag; what to do if it fails? */
                   2393:        error = udf_check_tag(eahdr);
                   2394:        if (error)
                   2395:                return EINVAL;
                   2396:        if (udf_rw16(eahdr->tag.id) != TAGID_EXTATTR_HDR)
                   2397:                return EINVAL;
                   2398:        error = udf_check_tag_payload(eahdr, sizeof(struct extattrhdr_desc));
                   2399:        if (error)
                   2400:                return EINVAL;
                   2401:
                   2402:        DPRINTF(EXTATTR, ("Found %d bytes of extended attributes\n", l_ea));
                   2403:
                   2404:        /* looking for Ecma-167 attributes? */
                   2405:        offset = sizeof(struct extattrhdr_desc);
                   2406:
1.163     msaitoh  2407:        /* looking for either implementation use or application use */
1.45      reinoud  2408:        if (sattr == 2048) {                            /* [4/48.10.8] */
                   2409:                offset = udf_rw32(eahdr->impl_attr_loc);
                   2410:                if (offset == UDF_IMPL_ATTR_LOC_NOT_PRESENT)
                   2411:                        return ENOENT;
                   2412:        }
                   2413:        if (sattr == 65536) {                           /* [4/48.10.9] */
                   2414:                offset = udf_rw32(eahdr->appl_attr_loc);
                   2415:                if (offset == UDF_APPL_ATTR_LOC_NOT_PRESENT)
                   2416:                        return ENOENT;
                   2417:        }
                   2418:
                   2419:        /* paranoia check offset and l_ea */
                   2420:        if (l_ea + offset >= sector_size - sizeof(struct extattr_entry))
                   2421:                return EINVAL;
                   2422:
                   2423:        DPRINTF(EXTATTR, ("Starting at offset %d\n", offset));
                   2424:
                   2425:        /* find our extended attribute  */
                   2426:        l_ea -= offset;
                   2427:        pos = (uint8_t *) eahdr + offset;
                   2428:
                   2429:        while (l_ea >= sizeof(struct extattr_entry)) {
                   2430:                DPRINTF(EXTATTR, ("%d extended attr bytes left\n", l_ea));
                   2431:                attrhdr = (struct extattr_entry *) pos;
                   2432:                implext = (struct impl_extattr_entry *) pos;
                   2433:
                   2434:                /* get complete attribute length and check for roque values */
                   2435:                a_l = udf_rw32(attrhdr->a_l);
                   2436:                DPRINTF(EXTATTR, ("attribute %d:%d, len %d/%d\n",
                   2437:                                udf_rw32(attrhdr->type),
                   2438:                                attrhdr->subtype, a_l, l_ea));
                   2439:                if ((a_l == 0) || (a_l > l_ea))
                   2440:                        return EINVAL;
                   2441:
                   2442:                if (attrhdr->type != sattr)
                   2443:                        goto next_attribute;
                   2444:
                   2445:                /* we might have found it! */
                   2446:                if (attrhdr->type < 2048) {     /* Ecma-167 attribute */
                   2447:                        *offsetp = offset;
                   2448:                        *lengthp = a_l;
                   2449:                        return 0;               /* success */
                   2450:                }
                   2451:
                   2452:                /*
                   2453:                 * Implementation use and application use extended attributes
                   2454:                 * have a name to identify. They share the same structure only
                   2455:                 * UDF implementation use extended attributes have a checksum
                   2456:                 * we need to check
                   2457:                 */
                   2458:
                   2459:                DPRINTF(EXTATTR, ("named attribute %s\n", implext->imp_id.id));
                   2460:                if (strcmp(implext->imp_id.id, sattrname) == 0) {
                   2461:                        /* we have found our appl/implementation attribute */
                   2462:                        *offsetp = offset;
                   2463:                        *lengthp = a_l;
                   2464:                        return 0;               /* success */
                   2465:                }
                   2466:
                   2467: next_attribute:
                   2468:                /* next attribute */
                   2469:                pos    += a_l;
                   2470:                l_ea   -= a_l;
                   2471:                offset += a_l;
                   2472:        }
                   2473:        /* not found */
                   2474:        return ENOENT;
                   2475: }
                   2476:
                   2477:
1.51      reinoud  2478: static void
                   2479: udf_extattr_insert_internal(struct udf_mount *ump, union dscrptr *dscr,
                   2480:        struct extattr_entry *extattr)
                   2481: {
                   2482:        struct file_entry      *fe;
                   2483:        struct extfile_entry   *efe;
                   2484:        struct extattrhdr_desc *extattrhdr;
                   2485:        struct impl_extattr_entry *implext;
                   2486:        uint32_t impl_attr_loc, appl_attr_loc, l_ea, a_l, exthdr_len;
                   2487:        uint32_t *l_eap, l_ad;
                   2488:        uint16_t *spos;
                   2489:        uint8_t *bpos, *data;
                   2490:
                   2491:        if (udf_rw16(dscr->tag.id) == TAGID_FENTRY) {
                   2492:                fe    = &dscr->fe;
                   2493:                data  = fe->data;
                   2494:                l_eap = &fe->l_ea;
                   2495:                l_ad  = udf_rw32(fe->l_ad);
                   2496:        } else if (udf_rw16(dscr->tag.id) == TAGID_EXTFENTRY) {
                   2497:                efe   = &dscr->efe;
                   2498:                data  = efe->data;
                   2499:                l_eap = &efe->l_ea;
                   2500:                l_ad  = udf_rw32(efe->l_ad);
                   2501:        } else {
                   2502:                panic("Bad tag passed to udf_extattr_insert_internal");
                   2503:        }
                   2504:
                   2505:        /* can't append already written to file descriptors yet */
                   2506:        assert(l_ad == 0);
1.124     christos 2507:        __USE(l_ad);
1.51      reinoud  2508:
                   2509:        /* should have a header! */
                   2510:        extattrhdr = (struct extattrhdr_desc *) data;
                   2511:        l_ea = udf_rw32(*l_eap);
                   2512:        if (l_ea == 0) {
                   2513:                /* create empty extended attribute header */
                   2514:                exthdr_len = sizeof(struct extattrhdr_desc);
                   2515:
                   2516:                udf_inittag(ump, &extattrhdr->tag, TAGID_EXTATTR_HDR,
                   2517:                        /* loc */ 0);
                   2518:                extattrhdr->impl_attr_loc = udf_rw32(exthdr_len);
                   2519:                extattrhdr->appl_attr_loc = udf_rw32(exthdr_len);
                   2520:                extattrhdr->tag.desc_crc_len = udf_rw16(8);
                   2521:
                   2522:                /* record extended attribute header length */
                   2523:                l_ea = exthdr_len;
                   2524:                *l_eap = udf_rw32(l_ea);
                   2525:        }
                   2526:
                   2527:        /* extract locations */
                   2528:        impl_attr_loc = udf_rw32(extattrhdr->impl_attr_loc);
                   2529:        appl_attr_loc = udf_rw32(extattrhdr->appl_attr_loc);
                   2530:        if (impl_attr_loc == UDF_IMPL_ATTR_LOC_NOT_PRESENT)
                   2531:                impl_attr_loc = l_ea;
                   2532:        if (appl_attr_loc == UDF_IMPL_ATTR_LOC_NOT_PRESENT)
                   2533:                appl_attr_loc = l_ea;
                   2534:
                   2535:        /* Ecma 167 EAs */
                   2536:        if (udf_rw32(extattr->type) < 2048) {
                   2537:                assert(impl_attr_loc == l_ea);
                   2538:                assert(appl_attr_loc == l_ea);
                   2539:        }
                   2540:
                   2541:        /* implementation use extended attributes */
                   2542:        if (udf_rw32(extattr->type) == 2048) {
                   2543:                assert(appl_attr_loc == l_ea);
                   2544:
                   2545:                /* calculate and write extended attribute header checksum */
                   2546:                implext = (struct impl_extattr_entry *) extattr;
                   2547:                assert(udf_rw32(implext->iu_l) == 4);   /* [UDF 3.3.4.5] */
                   2548:                spos = (uint16_t *) implext->data;
                   2549:                *spos = udf_rw16(udf_ea_cksum((uint8_t *) implext));
                   2550:        }
                   2551:
                   2552:        /* application use extended attributes */
                   2553:        assert(udf_rw32(extattr->type) != 65536);
                   2554:        assert(appl_attr_loc == l_ea);
                   2555:
                   2556:        /* append the attribute at the end of the current space */
                   2557:        bpos = data + udf_rw32(*l_eap);
                   2558:        a_l  = udf_rw32(extattr->a_l);
                   2559:
                   2560:        /* update impl. attribute locations */
                   2561:        if (udf_rw32(extattr->type) < 2048) {
                   2562:                impl_attr_loc = l_ea + a_l;
                   2563:                appl_attr_loc = l_ea + a_l;
                   2564:        }
                   2565:        if (udf_rw32(extattr->type) == 2048) {
                   2566:                appl_attr_loc = l_ea + a_l;
                   2567:        }
                   2568:
                   2569:        /* copy and advance */
                   2570:        memcpy(bpos, extattr, a_l);
                   2571:        l_ea += a_l;
                   2572:        *l_eap = udf_rw32(l_ea);
                   2573:
                   2574:        /* do the `dance` again backwards */
                   2575:        if (udf_rw16(ump->logical_vol->tag.descriptor_ver) != 2) {
                   2576:                if (impl_attr_loc == l_ea)
                   2577:                        impl_attr_loc = UDF_IMPL_ATTR_LOC_NOT_PRESENT;
                   2578:                if (appl_attr_loc == l_ea)
                   2579:                        appl_attr_loc = UDF_APPL_ATTR_LOC_NOT_PRESENT;
                   2580:        }
                   2581:
                   2582:        /* store offsets */
                   2583:        extattrhdr->impl_attr_loc = udf_rw32(impl_attr_loc);
                   2584:        extattrhdr->appl_attr_loc = udf_rw32(appl_attr_loc);
                   2585: }
                   2586:
1.45      reinoud  2587:
                   2588: /* --------------------------------------------------------------------- */
                   2589:
1.152     skrll    2590: static int
1.45      reinoud  2591: udf_update_lvid_from_vat_extattr(struct udf_node *vat_node)
                   2592: {
                   2593:        struct udf_mount       *ump;
                   2594:        struct udf_logvol_info *lvinfo;
                   2595:        struct impl_extattr_entry     *implext;
                   2596:        struct vatlvext_extattr_entry  lvext;
                   2597:        const char *extstr = "*UDF VAT LVExtension";
                   2598:        uint64_t    vat_uniqueid;
                   2599:        uint32_t    offset, a_l;
                   2600:        uint8_t    *ea_start, *lvextpos;
                   2601:        int         error;
                   2602:
                   2603:        /* get mountpoint and lvinfo */
                   2604:        ump    = vat_node->ump;
                   2605:        lvinfo = ump->logvol_info;
                   2606:
                   2607:        /* get information from fe/efe */
                   2608:        if (vat_node->fe) {
                   2609:                vat_uniqueid = udf_rw64(vat_node->fe->unique_id);
                   2610:                ea_start     = vat_node->fe->data;
                   2611:        } else {
                   2612:                vat_uniqueid = udf_rw64(vat_node->efe->unique_id);
                   2613:                ea_start     = vat_node->efe->data;
                   2614:        }
                   2615:
                   2616:        error = udf_extattr_search_intern(vat_node, 2048, extstr, &offset, &a_l);
                   2617:        if (error)
                   2618:                return error;
                   2619:
                   2620:        implext = (struct impl_extattr_entry *) (ea_start + offset);
                   2621:        error = udf_impl_extattr_check(implext);
                   2622:        if (error)
                   2623:                return error;
                   2624:
                   2625:        /* paranoia */
1.143     reinoud  2626:        if (a_l != sizeof(*implext) -2 + udf_rw32(implext->iu_l) + sizeof(lvext)) {
1.45      reinoud  2627:                DPRINTF(VOLUMES, ("VAT LVExtension size doesn't compute\n"));
                   2628:                return EINVAL;
                   2629:        }
                   2630:
                   2631:        /*
                   2632:         * we have found our "VAT LVExtension attribute. BUT due to a
                   2633:         * bug in the specification it might not be word aligned so
                   2634:         * copy first to avoid panics on some machines (!!)
                   2635:         */
                   2636:        DPRINTF(VOLUMES, ("Found VAT LVExtension attr\n"));
                   2637:        lvextpos = implext->data + udf_rw32(implext->iu_l);
                   2638:        memcpy(&lvext, lvextpos, sizeof(lvext));
                   2639:
                   2640:        /* check if it was updated the last time */
                   2641:        if (udf_rw64(lvext.unique_id_chk) == vat_uniqueid) {
                   2642:                lvinfo->num_files       = lvext.num_files;
                   2643:                lvinfo->num_directories = lvext.num_directories;
                   2644:                udf_update_logvolname(ump, lvext.logvol_id);
                   2645:        } else {
                   2646:                DPRINTF(VOLUMES, ("VAT LVExtension out of date\n"));
                   2647:                /* replace VAT LVExt by free space EA */
                   2648:                memset(implext->imp_id.id, 0, UDF_REGID_ID_SIZE);
                   2649:                strcpy(implext->imp_id.id, "*UDF FreeEASpace");
                   2650:                udf_calc_impl_extattr_checksum(implext);
                   2651:        }
                   2652:
                   2653:        return 0;
                   2654: }
                   2655:
                   2656:
1.152     skrll    2657: static int
1.45      reinoud  2658: udf_update_vat_extattr_from_lvid(struct udf_node *vat_node)
                   2659: {
                   2660:        struct udf_mount       *ump;
                   2661:        struct udf_logvol_info *lvinfo;
                   2662:        struct impl_extattr_entry     *implext;
                   2663:        struct vatlvext_extattr_entry  lvext;
                   2664:        const char *extstr = "*UDF VAT LVExtension";
                   2665:        uint64_t    vat_uniqueid;
                   2666:        uint32_t    offset, a_l;
1.153     mrg      2667:        uint8_t    *ea_start;
                   2668:        uintptr_t   lvextpos;
1.45      reinoud  2669:        int         error;
                   2670:
                   2671:        /* get mountpoint and lvinfo */
                   2672:        ump    = vat_node->ump;
                   2673:        lvinfo = ump->logvol_info;
                   2674:
                   2675:        /* get information from fe/efe */
                   2676:        if (vat_node->fe) {
                   2677:                vat_uniqueid = udf_rw64(vat_node->fe->unique_id);
                   2678:                ea_start     = vat_node->fe->data;
                   2679:        } else {
                   2680:                vat_uniqueid = udf_rw64(vat_node->efe->unique_id);
                   2681:                ea_start     = vat_node->efe->data;
                   2682:        }
                   2683:
                   2684:        error = udf_extattr_search_intern(vat_node, 2048, extstr, &offset, &a_l);
                   2685:        if (error)
                   2686:                return error;
                   2687:        /* found, it existed */
                   2688:
                   2689:        /* paranoia */
                   2690:        implext = (struct impl_extattr_entry *) (ea_start + offset);
                   2691:        error = udf_impl_extattr_check(implext);
                   2692:        if (error) {
                   2693:                DPRINTF(VOLUMES, ("VAT LVExtension bad on update\n"));
                   2694:                return error;
                   2695:        }
                   2696:        /* it is correct */
                   2697:
                   2698:        /*
                   2699:         * we have found our "VAT LVExtension attribute. BUT due to a
                   2700:         * bug in the specification it might not be word aligned so
                   2701:         * copy first to avoid panics on some machines (!!)
                   2702:         */
                   2703:        DPRINTF(VOLUMES, ("Updating VAT LVExtension attr\n"));
1.153     mrg      2704:        lvextpos = (uintptr_t)implext->data + udf_rw32(implext->iu_l);
1.45      reinoud  2705:
                   2706:        lvext.unique_id_chk   = vat_uniqueid;
                   2707:        lvext.num_files       = lvinfo->num_files;
                   2708:        lvext.num_directories = lvinfo->num_directories;
                   2709:        memmove(lvext.logvol_id, ump->logical_vol->logvol_id, 128);
                   2710:
1.153     mrg      2711:        memcpy((void *)lvextpos, &lvext, sizeof(lvext));
1.45      reinoud  2712:
                   2713:        return 0;
                   2714: }
                   2715:
                   2716: /* --------------------------------------------------------------------- */
                   2717:
                   2718: int
                   2719: udf_vat_read(struct udf_node *vat_node, uint8_t *blob, int size, uint32_t offset)
                   2720: {
                   2721:        struct udf_mount *ump = vat_node->ump;
                   2722:
                   2723:        if (offset + size > ump->vat_offset + ump->vat_entries * 4)
                   2724:                return EINVAL;
                   2725:
                   2726:        memcpy(blob, ump->vat_table + offset, size);
                   2727:        return 0;
                   2728: }
                   2729:
                   2730: int
                   2731: udf_vat_write(struct udf_node *vat_node, uint8_t *blob, int size, uint32_t offset)
                   2732: {
                   2733:        struct udf_mount *ump = vat_node->ump;
                   2734:        uint32_t offset_high;
                   2735:        uint8_t *new_vat_table;
                   2736:
                   2737:        /* extent VAT allocation if needed */
                   2738:        offset_high = offset + size;
                   2739:        if (offset_high >= ump->vat_table_alloc_len) {
                   2740:                /* realloc */
                   2741:                new_vat_table = realloc(ump->vat_table,
                   2742:                        ump->vat_table_alloc_len + UDF_VAT_CHUNKSIZE,
1.144     jdolecek 2743:                        M_UDFVOLD, M_WAITOK);
1.45      reinoud  2744:                if (!new_vat_table) {
                   2745:                        printf("udf_vat_write: can't extent VAT, out of mem\n");
                   2746:                        return ENOMEM;
                   2747:                }
                   2748:                ump->vat_table = new_vat_table;
                   2749:                ump->vat_table_alloc_len += UDF_VAT_CHUNKSIZE;
                   2750:        }
                   2751:        ump->vat_table_len = MAX(ump->vat_table_len, offset_high);
                   2752:
                   2753:        memcpy(ump->vat_table + offset, blob, size);
                   2754:        return 0;
                   2755: }
                   2756:
                   2757: /* --------------------------------------------------------------------- */
                   2758:
                   2759: /* TODO support previous VAT location writeout */
                   2760: static int
                   2761: udf_update_vat_descriptor(struct udf_mount *ump)
                   2762: {
                   2763:        struct udf_node *vat_node = ump->vat_node;
                   2764:        struct udf_logvol_info *lvinfo = ump->logvol_info;
                   2765:        struct icb_tag *icbtag;
                   2766:        struct udf_oldvat_tail *oldvat_tl;
                   2767:        struct udf_vat *vat;
1.161     reinoud  2768:        struct regid *regid;
1.45      reinoud  2769:        uint64_t unique_id;
                   2770:        uint32_t lb_size;
                   2771:        uint8_t *raw_vat;
1.161     reinoud  2772:        int vat_length, impl_use_len, filetype, error;
1.45      reinoud  2773:
                   2774:        KASSERT(vat_node);
                   2775:        KASSERT(lvinfo);
                   2776:        lb_size = udf_rw32(ump->logical_vol->lb_size);
                   2777:
                   2778:        /* get our new unique_id */
                   2779:        unique_id = udf_advance_uniqueid(ump);
                   2780:
                   2781:        /* get information from fe/efe */
                   2782:        if (vat_node->fe) {
                   2783:                icbtag    = &vat_node->fe->icbtag;
                   2784:                vat_node->fe->unique_id = udf_rw64(unique_id);
                   2785:        } else {
                   2786:                icbtag = &vat_node->efe->icbtag;
                   2787:                vat_node->efe->unique_id = udf_rw64(unique_id);
                   2788:        }
                   2789:
                   2790:        /* Check icb filetype! it has to be 0 or UDF_ICB_FILETYPE_VAT */
                   2791:        filetype = icbtag->file_type;
                   2792:        KASSERT((filetype == 0) || (filetype == UDF_ICB_FILETYPE_VAT));
                   2793:
                   2794:        /* allocate piece to process head or tail of VAT file */
                   2795:        raw_vat = malloc(lb_size, M_TEMP, M_WAITOK);
                   2796:
                   2797:        if (filetype == 0) {
                   2798:                /*
                   2799:                 * Update "*UDF VAT LVExtension" extended attribute from the
                   2800:                 * lvint if present.
                   2801:                 */
                   2802:                udf_update_vat_extattr_from_lvid(vat_node);
                   2803:
                   2804:                /* setup identifying regid */
                   2805:                oldvat_tl = (struct udf_oldvat_tail *) raw_vat;
                   2806:                memset(oldvat_tl, 0, sizeof(struct udf_oldvat_tail));
                   2807:
                   2808:                udf_set_regid(&oldvat_tl->id, "*UDF Virtual Alloc Tbl");
                   2809:                udf_add_udf_regid(ump, &oldvat_tl->id);
                   2810:                oldvat_tl->prev_vat = udf_rw32(0xffffffff);
                   2811:
                   2812:                /* write out new tail of virtual allocation table file */
                   2813:                error = udf_vat_write(vat_node, raw_vat,
                   2814:                        sizeof(struct udf_oldvat_tail), ump->vat_entries * 4);
                   2815:        } else {
                   2816:                /* compose the VAT2 header */
1.161     reinoud  2817:                vat_length = sizeof(struct udf_vat);
1.45      reinoud  2818:                vat = (struct udf_vat *) raw_vat;
                   2819:
1.161     reinoud  2820:                error = udf_vat_read(vat_node, raw_vat, vat_length, 0);
                   2821:                if (error)
                   2822:                        goto errout;
                   2823:
                   2824:                impl_use_len = udf_rw16(vat->impl_use_len);
                   2825:                vat_length += impl_use_len;
                   2826:
                   2827:                error = udf_vat_read(vat_node, raw_vat, vat_length, 0);
                   2828:                if (error)
                   2829:                        goto errout;
                   2830:
1.45      reinoud  2831:                memmove(vat->logvol_id, ump->logical_vol->logvol_id, 128);
                   2832:                vat->prev_vat         = udf_rw32(0xffffffff);
                   2833:                vat->num_files        = lvinfo->num_files;
                   2834:                vat->num_directories  = lvinfo->num_directories;
                   2835:                vat->min_udf_readver  = lvinfo->min_udf_readver;
                   2836:                vat->min_udf_writever = lvinfo->min_udf_writever;
                   2837:                vat->max_udf_writever = lvinfo->max_udf_writever;
                   2838:
1.161     reinoud  2839:                if (impl_use_len >= sizeof(struct regid)) {
                   2840:                        /* insert our implementation identification */
                   2841:                        memset(vat->data, 0, impl_use_len);
                   2842:                        regid = (struct regid *) vat->data;
                   2843:                        udf_set_regid(regid, IMPL_NAME);
                   2844:                        udf_add_app_regid(ump, regid);
                   2845:                } else {
                   2846:                        if (impl_use_len)
                   2847:                                memset(vat->data, 0, impl_use_len);
                   2848:                        vat->impl_use_len = 0;
                   2849:                }
                   2850:                error = udf_vat_write(vat_node, raw_vat, vat_length, 0);
1.45      reinoud  2851:        }
1.161     reinoud  2852: errout:
1.45      reinoud  2853:        free(raw_vat, M_TEMP);
                   2854:
                   2855:        return error;   /* success! */
                   2856: }
                   2857:
                   2858:
                   2859: int
                   2860: udf_writeout_vat(struct udf_mount *ump)
                   2861: {
                   2862:        struct udf_node *vat_node = ump->vat_node;
                   2863:        int error;
                   2864:
                   2865:        KASSERT(vat_node);
                   2866:
                   2867:        DPRINTF(CALL, ("udf_writeout_vat\n"));
                   2868:
1.95      reinoud  2869: //     mutex_enter(&ump->allocate_mutex);
1.45      reinoud  2870:        udf_update_vat_descriptor(ump);
                   2871:
                   2872:        /* write out the VAT contents ; TODO intelligent writing */
                   2873:        error = vn_rdwr(UIO_WRITE, vat_node->vnode,
                   2874:                ump->vat_table, ump->vat_table_len, 0,
1.109     reinoud  2875:                UIO_SYSSPACE, 0, FSCRED, NULL, NULL);
1.45      reinoud  2876:        if (error) {
                   2877:                printf("udf_writeout_vat: failed to write out VAT contents\n");
                   2878:                goto out;
                   2879:        }
                   2880:
1.95      reinoud  2881: //     mutex_exit(&ump->allocate_mutex);
1.45      reinoud  2882:
1.119     chs      2883:        error = vflushbuf(ump->vat_node->vnode, FSYNC_WAIT);
1.114     hannken  2884:        if (error)
                   2885:                goto out;
1.45      reinoud  2886:        error = VOP_FSYNC(ump->vat_node->vnode,
                   2887:                        FSCRED, FSYNC_WAIT, 0, 0);
                   2888:        if (error)
                   2889:                printf("udf_writeout_vat: error writing VAT node!\n");
                   2890: out:
                   2891:        return error;
                   2892: }
                   2893:
                   2894: /* --------------------------------------------------------------------- */
                   2895:
                   2896: /*
                   2897:  * Read in relevant pieces of VAT file and check if its indeed a VAT file
                   2898:  * descriptor. If OK, read in complete VAT file.
                   2899:  */
                   2900:
                   2901: static int
                   2902: udf_check_for_vat(struct udf_node *vat_node)
                   2903: {
                   2904:        struct udf_mount *ump;
                   2905:        struct icb_tag   *icbtag;
                   2906:        struct timestamp *mtime;
                   2907:        struct udf_vat   *vat;
                   2908:        struct udf_oldvat_tail *oldvat_tl;
                   2909:        struct udf_logvol_info *lvinfo;
                   2910:        uint64_t  unique_id;
                   2911:        uint32_t  vat_length;
                   2912:        uint32_t  vat_offset, vat_entries, vat_table_alloc_len;
                   2913:        uint32_t  sector_size;
                   2914:        uint32_t *raw_vat;
                   2915:        uint8_t  *vat_table;
                   2916:        char     *regid_name;
                   2917:        int filetype;
                   2918:        int error;
                   2919:
                   2920:        /* vat_length is really 64 bits though impossible */
                   2921:
                   2922:        DPRINTF(VOLUMES, ("Checking for VAT\n"));
                   2923:        if (!vat_node)
                   2924:                return ENOENT;
                   2925:
                   2926:        /* get mount info */
                   2927:        ump = vat_node->ump;
                   2928:        sector_size = udf_rw32(ump->logical_vol->lb_size);
                   2929:
                   2930:        /* check assertions */
                   2931:        assert(vat_node->fe || vat_node->efe);
                   2932:        assert(ump->logvol_integrity);
                   2933:
                   2934:        /* set vnode type to regular file or we can't read from it! */
                   2935:        vat_node->vnode->v_type = VREG;
                   2936:
                   2937:        /* get information from fe/efe */
                   2938:        if (vat_node->fe) {
                   2939:                vat_length = udf_rw64(vat_node->fe->inf_len);
                   2940:                icbtag    = &vat_node->fe->icbtag;
                   2941:                mtime     = &vat_node->fe->mtime;
                   2942:                unique_id = udf_rw64(vat_node->fe->unique_id);
                   2943:        } else {
                   2944:                vat_length = udf_rw64(vat_node->efe->inf_len);
                   2945:                icbtag = &vat_node->efe->icbtag;
                   2946:                mtime  = &vat_node->efe->mtime;
                   2947:                unique_id = udf_rw64(vat_node->efe->unique_id);
                   2948:        }
                   2949:
                   2950:        /* Check icb filetype! it has to be 0 or UDF_ICB_FILETYPE_VAT */
                   2951:        filetype = icbtag->file_type;
                   2952:        if ((filetype != 0) && (filetype != UDF_ICB_FILETYPE_VAT))
                   2953:                return ENOENT;
                   2954:
                   2955:        DPRINTF(VOLUMES, ("\tPossible VAT length %d\n", vat_length));
                   2956:
                   2957:        vat_table_alloc_len =
                   2958:                ((vat_length + UDF_VAT_CHUNKSIZE-1) / UDF_VAT_CHUNKSIZE)
                   2959:                        * UDF_VAT_CHUNKSIZE;
                   2960:
1.144     jdolecek 2961:        vat_table = malloc(vat_table_alloc_len, M_UDFVOLD, M_WAITOK);
1.45      reinoud  2962:        if (vat_table == NULL) {
                   2963:                printf("allocation of %d bytes failed for VAT\n",
                   2964:                        vat_table_alloc_len);
                   2965:                return ENOMEM;
                   2966:        }
                   2967:
                   2968:        /* allocate piece to read in head or tail of VAT file */
                   2969:        raw_vat = malloc(sector_size, M_TEMP, M_WAITOK);
                   2970:
                   2971:        /*
                   2972:         * check contents of the file if its the old 1.50 VAT table format.
                   2973:         * Its notoriously broken and allthough some implementations support an
1.157     andvar   2974:         * extension as defined in the UDF 1.50 errata document, its doubtful
1.45      reinoud  2975:         * to be useable since a lot of implementations don't maintain it.
                   2976:         */
                   2977:        lvinfo = ump->logvol_info;
                   2978:
                   2979:        if (filetype == 0) {
                   2980:                /* definition */
                   2981:                vat_offset  = 0;
                   2982:                vat_entries = (vat_length-36)/4;
                   2983:
                   2984:                /* read in tail of virtual allocation table file */
                   2985:                error = vn_rdwr(UIO_READ, vat_node->vnode,
                   2986:                                (uint8_t *) raw_vat,
                   2987:                                sizeof(struct udf_oldvat_tail),
                   2988:                                vat_entries * 4,
                   2989:                                UIO_SYSSPACE, IO_SYNC | IO_NODELOCKED, FSCRED,
                   2990:                                NULL, NULL);
                   2991:                if (error)
                   2992:                        goto out;
                   2993:
                   2994:                /* check 1.50 VAT */
                   2995:                oldvat_tl = (struct udf_oldvat_tail *) raw_vat;
                   2996:                regid_name = (char *) oldvat_tl->id.id;
                   2997:                error = strncmp(regid_name, "*UDF Virtual Alloc Tbl", 22);
                   2998:                if (error) {
                   2999:                        DPRINTF(VOLUMES, ("VAT format 1.50 rejected\n"));
                   3000:                        error = ENOENT;
                   3001:                        goto out;
                   3002:                }
                   3003:
                   3004:                /*
                   3005:                 * update LVID from "*UDF VAT LVExtension" extended attribute
                   3006:                 * if present.
                   3007:                 */
                   3008:                udf_update_lvid_from_vat_extattr(vat_node);
                   3009:        } else {
                   3010:                /* read in head of virtual allocation table file */
                   3011:                error = vn_rdwr(UIO_READ, vat_node->vnode,
                   3012:                                (uint8_t *) raw_vat,
                   3013:                                sizeof(struct udf_vat), 0,
                   3014:                                UIO_SYSSPACE, IO_SYNC | IO_NODELOCKED, FSCRED,
                   3015:                                NULL, NULL);
                   3016:                if (error)
                   3017:                        goto out;
                   3018:
                   3019:                /* definition */
                   3020:                vat = (struct udf_vat *) raw_vat;
1.161     reinoud  3021:                vat_offset  = udf_rw16(vat->header_len);
1.45      reinoud  3022:                vat_entries = (vat_length - vat_offset)/4;
                   3023:
                   3024:                assert(lvinfo);
                   3025:                lvinfo->num_files        = vat->num_files;
                   3026:                lvinfo->num_directories  = vat->num_directories;
                   3027:                lvinfo->min_udf_readver  = vat->min_udf_readver;
                   3028:                lvinfo->min_udf_writever = vat->min_udf_writever;
                   3029:                lvinfo->max_udf_writever = vat->max_udf_writever;
1.152     skrll    3030:
1.45      reinoud  3031:                udf_update_logvolname(ump, vat->logvol_id);
                   3032:        }
                   3033:
                   3034:        /* read in complete VAT file */
                   3035:        error = vn_rdwr(UIO_READ, vat_node->vnode,
                   3036:                        vat_table,
                   3037:                        vat_length, 0,
                   3038:                        UIO_SYSSPACE, IO_SYNC | IO_NODELOCKED, FSCRED,
                   3039:                        NULL, NULL);
                   3040:        if (error)
                   3041:                printf("read in of complete VAT file failed (error %d)\n",
                   3042:                        error);
                   3043:        if (error)
                   3044:                goto out;
                   3045:
                   3046:        DPRINTF(VOLUMES, ("VAT format accepted, marking it closed\n"));
1.90      reinoud  3047:        ump->logvol_integrity->lvint_next_unique_id = udf_rw64(unique_id);
1.45      reinoud  3048:        ump->logvol_integrity->integrity_type = udf_rw32(UDF_INTEGRITY_CLOSED);
                   3049:        ump->logvol_integrity->time           = *mtime;
                   3050:
1.137     reinoud  3051:        /* if we're updating, free old allocated space */
                   3052:        if (ump->vat_table)
                   3053:                free(ump->vat_table, M_UDFVOLD);
                   3054:
1.45      reinoud  3055:        ump->vat_table_len = vat_length;
                   3056:        ump->vat_table_alloc_len = vat_table_alloc_len;
                   3057:        ump->vat_table   = vat_table;
                   3058:        ump->vat_offset  = vat_offset;
                   3059:        ump->vat_entries = vat_entries;
                   3060:        ump->vat_last_free_lb = 0;              /* start at beginning */
                   3061:
                   3062: out:
                   3063:        if (error) {
                   3064:                if (vat_table)
                   3065:                        free(vat_table, M_UDFVOLD);
                   3066:        }
                   3067:        free(raw_vat, M_TEMP);
                   3068:
                   3069:        return error;
                   3070: }
                   3071:
                   3072: /* --------------------------------------------------------------------- */
                   3073:
                   3074: static int
                   3075: udf_search_vat(struct udf_mount *ump, union udf_pmap *mapping)
                   3076: {
1.137     reinoud  3077:        struct udf_node *vat_node, *accepted_vat_node;
1.45      reinoud  3078:        struct long_ad   icb_loc;
1.137     reinoud  3079:        uint32_t early_vat_loc, late_vat_loc, vat_loc;
1.45      reinoud  3080:        int error;
                   3081:
                   3082:        /* mapping info not needed */
                   3083:        mapping = mapping;
                   3084:
1.137     reinoud  3085:        DPRINTF(VOLUMES, ("Searching VAT\n"));
1.152     skrll    3086:
1.137     reinoud  3087:        /*
                   3088:         * Start reading forward in blocks from the first possible vat
                   3089:         * location. If not found in this block, start again a bit before
                   3090:         * until we get a hit.
                   3091:         */
                   3092:        late_vat_loc = ump->last_possible_vat_location;
                   3093:        early_vat_loc = MAX(late_vat_loc - 64, ump->first_possible_vat_location);
1.152     skrll    3094:
1.137     reinoud  3095:        DPRINTF(VOLUMES, ("\tfull range %d to %d\n", early_vat_loc, late_vat_loc));
                   3096:        accepted_vat_node = NULL;
                   3097:        do {
                   3098:                vat_loc = early_vat_loc;
                   3099:                DPRINTF(VOLUMES, ("\tchecking range %d to %d\n",
                   3100:                        early_vat_loc, late_vat_loc));
                   3101:                do {
                   3102:                        DPRINTF(VOLUMES, ("\t\tChecking for VAT at sector %d\n",
                   3103:                                vat_loc));
                   3104:                        icb_loc.loc.part_num = udf_rw16(UDF_VTOP_RAWPART);
                   3105:                        icb_loc.loc.lb_num   = udf_rw32(vat_loc);
1.45      reinoud  3106:
1.148     ad       3107:                        error = udf_get_node(ump, &icb_loc, &vat_node,
                   3108:                            LK_EXCLUSIVE);
1.137     reinoud  3109:                        if (!error) {
                   3110:                                error = udf_check_for_vat(vat_node);
                   3111:                                vat_node->i_flags = 0;  /* reset access */
                   3112:                        }
                   3113:                        if (!error) {
                   3114:                                DPRINTFIF(VOLUMES, !error,
                   3115:                                        ("VAT candidate accepted at %d\n",
                   3116:                                         vat_loc));
                   3117:                                if (accepted_vat_node)
                   3118:                                        vput(accepted_vat_node->vnode);
                   3119:                                accepted_vat_node = vat_node;
                   3120:                                accepted_vat_node->i_flags |= IN_NO_DELETE;
                   3121:                                vat_node = NULL;
                   3122:                        }
                   3123:                        if (vat_node)
                   3124:                                vput(vat_node->vnode);
                   3125:                        vat_loc++;      /* walk forward */
1.160     reinoud  3126:                } while (vat_loc <= late_vat_loc);
1.137     reinoud  3127:                if (accepted_vat_node)
                   3128:                        break;
                   3129:
                   3130:                early_vat_loc = MAX(early_vat_loc - 64, ump->first_possible_vat_location);
                   3131:                late_vat_loc = MIN(early_vat_loc + 64, ump->last_possible_vat_location);
                   3132:        } while (late_vat_loc > ump->first_possible_vat_location);
                   3133:
                   3134:        /* keep our last accepted VAT node around */
                   3135:        if (accepted_vat_node) {
                   3136:                /* revert no delete flag again to avoid potential side effects */
                   3137:                accepted_vat_node->i_flags &= ~IN_NO_DELETE;
1.45      reinoud  3138:
1.137     reinoud  3139:                UDF_SET_SYSTEMFILE(accepted_vat_node->vnode);
                   3140:                ump->vat_node = accepted_vat_node;
                   3141:                return 0;
1.45      reinoud  3142:        }
                   3143:
                   3144:        return error;
                   3145: }
                   3146:
                   3147: /* --------------------------------------------------------------------- */
                   3148:
                   3149: static int
                   3150: udf_read_sparables(struct udf_mount *ump, union udf_pmap *mapping)
                   3151: {
                   3152:        union dscrptr *dscr;
                   3153:        struct part_map_spare *pms = &mapping->pms;
                   3154:        uint32_t lb_num;
                   3155:        int spar, error;
                   3156:
                   3157:        /*
                   3158:         * The partition mapping passed on to us specifies the information we
                   3159:         * need to locate and initialise the sparable partition mapping
                   3160:         * information we need.
                   3161:         */
                   3162:
                   3163:        DPRINTF(VOLUMES, ("Read sparable table\n"));
                   3164:        ump->sparable_packet_size = udf_rw16(pms->packet_len);
                   3165:        KASSERT(ump->sparable_packet_size >= ump->packet_size); /* XXX */
                   3166:
                   3167:        for (spar = 0; spar < pms->n_st; spar++) {
                   3168:                lb_num = pms->st_loc[spar];
                   3169:                DPRINTF(VOLUMES, ("Checking for sparing table %d\n", lb_num));
                   3170:                error = udf_read_phys_dscr(ump, lb_num, M_UDFVOLD, &dscr);
                   3171:                if (!error && dscr) {
                   3172:                        if (udf_rw16(dscr->tag.id) == TAGID_SPARING_TABLE) {
                   3173:                                if (ump->sparing_table)
                   3174:                                        free(ump->sparing_table, M_UDFVOLD);
                   3175:                                ump->sparing_table = &dscr->spt;
                   3176:                                dscr = NULL;
                   3177:                                DPRINTF(VOLUMES,
                   3178:                                    ("Sparing table accepted (%d entries)\n",
                   3179:                                     udf_rw16(ump->sparing_table->rt_l)));
                   3180:                                break;  /* we're done */
                   3181:                        }
                   3182:                }
                   3183:                if (dscr)
                   3184:                        free(dscr, M_UDFVOLD);
                   3185:        }
                   3186:
                   3187:        if (ump->sparing_table)
                   3188:                return 0;
                   3189:
                   3190:        return ENOENT;
                   3191: }
                   3192:
                   3193: /* --------------------------------------------------------------------- */
                   3194:
                   3195: static int
                   3196: udf_read_metadata_nodes(struct udf_mount *ump, union udf_pmap *mapping)
                   3197: {
                   3198:        struct part_map_meta *pmm = &mapping->pmm;
                   3199:        struct long_ad   icb_loc;
                   3200:        struct vnode *vp;
1.111     reinoud  3201:        uint16_t raw_phys_part, phys_part;
1.45      reinoud  3202:        int error;
                   3203:
1.111     reinoud  3204:        /*
                   3205:         * BUGALERT: some rogue implementations use random physical
                   3206:         * partition numbers to break other implementations so lookup
                   3207:         * the number.
                   3208:         */
                   3209:
1.102     reinoud  3210:        /* extract our allocation parameters set up on format */
1.103     reinoud  3211:        ump->metadata_alloc_unit_size     = udf_rw32(mapping->pmm.alloc_unit_size);
                   3212:        ump->metadata_alignment_unit_size = udf_rw16(mapping->pmm.alignment_unit_size);
                   3213:        ump->metadata_flags = mapping->pmm.flags;
1.102     reinoud  3214:
1.45      reinoud  3215:        DPRINTF(VOLUMES, ("Reading in Metadata files\n"));
1.111     reinoud  3216:        raw_phys_part = udf_rw16(pmm->part_num);
                   3217:        phys_part = udf_find_raw_phys(ump, raw_phys_part);
                   3218:
                   3219:        icb_loc.loc.part_num = udf_rw16(phys_part);
                   3220:
                   3221:        DPRINTF(VOLUMES, ("Metadata file\n"));
1.45      reinoud  3222:        icb_loc.loc.lb_num   = pmm->meta_file_lbn;
1.148     ad       3223:        error = udf_get_node(ump, &icb_loc, &ump->metadata_node,
                   3224:            LK_EXCLUSIVE);
1.45      reinoud  3225:        if (ump->metadata_node) {
                   3226:                vp = ump->metadata_node->vnode;
                   3227:                UDF_SET_SYSTEMFILE(vp);
                   3228:        }
                   3229:
                   3230:        icb_loc.loc.lb_num   = pmm->meta_mirror_file_lbn;
                   3231:        if (icb_loc.loc.lb_num != -1) {
                   3232:                DPRINTF(VOLUMES, ("Metadata copy file\n"));
1.148     ad       3233:                error = udf_get_node(ump, &icb_loc, &ump->metadatamirror_node,
                   3234:                    LK_EXCLUSIVE);
1.45      reinoud  3235:                if (ump->metadatamirror_node) {
                   3236:                        vp = ump->metadatamirror_node->vnode;
                   3237:                        UDF_SET_SYSTEMFILE(vp);
                   3238:                }
                   3239:        }
                   3240:
                   3241:        icb_loc.loc.lb_num   = pmm->meta_bitmap_file_lbn;
                   3242:        if (icb_loc.loc.lb_num != -1) {
                   3243:                DPRINTF(VOLUMES, ("Metadata bitmap file\n"));
1.148     ad       3244:                error = udf_get_node(ump, &icb_loc, &ump->metadatabitmap_node,
                   3245:                    LK_EXCLUSIVE);
1.45      reinoud  3246:                if (ump->metadatabitmap_node) {
                   3247:                        vp = ump->metadatabitmap_node->vnode;
                   3248:                        UDF_SET_SYSTEMFILE(vp);
                   3249:                }
                   3250:        }
                   3251:
                   3252:        /* if we're mounting read-only we relax the requirements */
                   3253:        if (ump->vfs_mountp->mnt_flag & MNT_RDONLY) {
                   3254:                error = EFAULT;
                   3255:                if (ump->metadata_node)
                   3256:                        error = 0;
                   3257:                if ((ump->metadata_node == NULL) && (ump->metadatamirror_node)) {
                   3258:                        printf( "udf mount: Metadata file not readable, "
                   3259:                                "substituting Metadata copy file\n");
                   3260:                        ump->metadata_node = ump->metadatamirror_node;
                   3261:                        ump->metadatamirror_node = NULL;
                   3262:                        error = 0;
                   3263:                }
                   3264:        } else {
                   3265:                /* mounting read/write */
1.70      reinoud  3266:                /* XXX DISABLED! metadata writing is not working yet XXX */
1.71      reinoud  3267:                if (error)
1.53      reinoud  3268:                        error = EROFS;
1.45      reinoud  3269:        }
                   3270:        DPRINTFIF(VOLUMES, error, ("udf mount: failed to read "
                   3271:                                   "metadata files\n"));
                   3272:        return error;
                   3273: }
                   3274:
                   3275: /* --------------------------------------------------------------------- */
                   3276:
                   3277: int
                   3278: udf_read_vds_tables(struct udf_mount *ump)
                   3279: {
                   3280:        union udf_pmap *mapping;
                   3281:        /* struct udf_args *args = &ump->mount_args; */
1.121     christos 3282:        uint32_t n_pm;
1.45      reinoud  3283:        uint32_t log_part;
                   3284:        uint8_t *pmap_pos;
                   3285:        int pmap_size;
                   3286:        int error;
                   3287:
1.69      reinoud  3288:        /* Iterate (again) over the part mappings for locations   */
1.45      reinoud  3289:        n_pm = udf_rw32(ump->logical_vol->n_pm);   /* num partmaps         */
                   3290:        pmap_pos =  ump->logical_vol->maps;
                   3291:
                   3292:        for (log_part = 0; log_part < n_pm; log_part++) {
                   3293:                mapping = (union udf_pmap *) pmap_pos;
                   3294:                switch (ump->vtop_tp[log_part]) {
                   3295:                case UDF_VTOP_TYPE_PHYS :
                   3296:                        /* nothing */
                   3297:                        break;
                   3298:                case UDF_VTOP_TYPE_VIRT :
                   3299:                        /* search and load VAT */
                   3300:                        error = udf_search_vat(ump, mapping);
                   3301:                        if (error)
                   3302:                                return ENOENT;
                   3303:                        break;
                   3304:                case UDF_VTOP_TYPE_SPARABLE :
                   3305:                        /* load one of the sparable tables */
                   3306:                        error = udf_read_sparables(ump, mapping);
                   3307:                        if (error)
                   3308:                                return ENOENT;
                   3309:                        break;
                   3310:                case UDF_VTOP_TYPE_META :
                   3311:                        /* load the associated file descriptors */
                   3312:                        error = udf_read_metadata_nodes(ump, mapping);
                   3313:                        if (error)
                   3314:                                return ENOENT;
                   3315:                        break;
                   3316:                default:
                   3317:                        break;
                   3318:                }
                   3319:                pmap_size  = pmap_pos[1];
                   3320:                pmap_pos  += pmap_size;
                   3321:        }
                   3322:
1.70      reinoud  3323:        /* read in and check unallocated and free space info if writing */
                   3324:        if ((ump->vfs_mountp->mnt_flag & MNT_RDONLY) == 0) {
                   3325:                error = udf_read_physical_partition_spacetables(ump);
                   3326:                if (error)
                   3327:                        return error;
                   3328:
1.100     mbalmer  3329:                /* also read in metadata partition spacebitmap if defined */
1.70      reinoud  3330:                error = udf_read_metadata_partition_spacetable(ump);
                   3331:                        return error;
                   3332:        }
                   3333:
1.45      reinoud  3334:        return 0;
                   3335: }
                   3336:
                   3337: /* --------------------------------------------------------------------- */
                   3338:
                   3339: int
                   3340: udf_read_rootdirs(struct udf_mount *ump)
                   3341: {
                   3342:        union dscrptr *dscr;
                   3343:        /* struct udf_args *args = &ump->mount_args; */
                   3344:        struct udf_node *rootdir_node, *streamdir_node;
                   3345:        struct long_ad  fsd_loc, *dir_loc;
                   3346:        uint32_t lb_num, dummy;
                   3347:        uint32_t fsd_len;
                   3348:        int dscr_type;
                   3349:        int error;
                   3350:
                   3351:        /* TODO implement FSD reading in separate function like integrity? */
                   3352:        /* get fileset descriptor sequence */
                   3353:        fsd_loc = ump->logical_vol->lv_fsd_loc;
                   3354:        fsd_len = udf_rw32(fsd_loc.len);
                   3355:
                   3356:        dscr  = NULL;
                   3357:        error = 0;
                   3358:        while (fsd_len || error) {
                   3359:                DPRINTF(VOLUMES, ("fsd_len = %d\n", fsd_len));
                   3360:                /* translate fsd_loc to lb_num */
                   3361:                error = udf_translate_vtop(ump, &fsd_loc, &lb_num, &dummy);
                   3362:                if (error)
                   3363:                        break;
                   3364:                DPRINTF(VOLUMES, ("Reading FSD at lb %d\n", lb_num));
                   3365:                error = udf_read_phys_dscr(ump, lb_num, M_UDFVOLD, &dscr);
                   3366:                /* end markers */
                   3367:                if (error || (dscr == NULL))
                   3368:                        break;
                   3369:
                   3370:                /* analyse */
                   3371:                dscr_type = udf_rw16(dscr->tag.id);
                   3372:                if (dscr_type == TAGID_TERM)
                   3373:                        break;
                   3374:                if (dscr_type != TAGID_FSD) {
                   3375:                        free(dscr, M_UDFVOLD);
                   3376:                        return ENOENT;
                   3377:                }
                   3378:
                   3379:                /*
                   3380:                 * TODO check for multiple fileset descriptors; its only
                   3381:                 * picking the last now. Also check for FSD
                   3382:                 * correctness/interpretability
                   3383:                 */
                   3384:
                   3385:                /* update */
                   3386:                if (ump->fileset_desc) {
                   3387:                        free(ump->fileset_desc, M_UDFVOLD);
                   3388:                }
                   3389:                ump->fileset_desc = &dscr->fsd;
                   3390:                dscr = NULL;
                   3391:
                   3392:                /* continue to the next fsd */
                   3393:                fsd_len -= ump->discinfo.sector_size;
                   3394:                fsd_loc.loc.lb_num = udf_rw32(udf_rw32(fsd_loc.loc.lb_num)+1);
                   3395:
                   3396:                /* follow up to fsd->next_ex (long_ad) if its not null */
                   3397:                if (udf_rw32(ump->fileset_desc->next_ex.len)) {
                   3398:                        DPRINTF(VOLUMES, ("follow up FSD extent\n"));
                   3399:                        fsd_loc = ump->fileset_desc->next_ex;
                   3400:                        fsd_len = udf_rw32(ump->fileset_desc->next_ex.len);
                   3401:                }
                   3402:        }
                   3403:        if (dscr)
                   3404:                free(dscr, M_UDFVOLD);
                   3405:
                   3406:        /* there has to be one */
                   3407:        if (ump->fileset_desc == NULL)
                   3408:                return ENOENT;
                   3409:
                   3410:        DPRINTF(VOLUMES, ("FSD read in fine\n"));
                   3411:        DPRINTF(VOLUMES, ("Updating fsd logical volume id\n"));
                   3412:        udf_update_logvolname(ump, ump->logical_vol->logvol_id);
                   3413:
                   3414:        /*
                   3415:         * Now the FSD is known, read in the rootdirectory and if one exists,
                   3416:         * the system stream dir. Some files in the system streamdir are not
                   3417:         * wanted in this implementation since they are not maintained. If
                   3418:         * writing is enabled we'll delete these files if they exist.
                   3419:         */
                   3420:
                   3421:        rootdir_node = streamdir_node = NULL;
                   3422:        dir_loc = NULL;
                   3423:
                   3424:        /* try to read in the rootdir */
                   3425:        dir_loc = &ump->fileset_desc->rootdir_icb;
1.148     ad       3426:        error = udf_get_node(ump, dir_loc, &rootdir_node, LK_EXCLUSIVE);
1.45      reinoud  3427:        if (error)
                   3428:                return ENOENT;
                   3429:
1.166   ! andvar   3430:        /* apparently it reads in fine */
1.45      reinoud  3431:
                   3432:        /*
                   3433:         * Try the system stream directory; not very likely in the ones we
                   3434:         * test, but for completeness.
                   3435:         */
                   3436:        dir_loc = &ump->fileset_desc->streamdir_icb;
                   3437:        if (udf_rw32(dir_loc->len)) {
                   3438:                printf("udf_read_rootdirs: streamdir defined ");
1.148     ad       3439:                error = udf_get_node(ump, dir_loc, &streamdir_node,
                   3440:                    LK_EXCLUSIVE);
1.45      reinoud  3441:                if (error) {
                   3442:                        printf("but error in streamdir reading\n");
1.1       reinoud  3443:                } else {
1.45      reinoud  3444:                        printf("but ignored\n");
                   3445:                        /*
                   3446:                         * TODO process streamdir `baddies' i.e. files we dont
                   3447:                         * want if R/W
                   3448:                         */
                   3449:                }
                   3450:        }
                   3451:
                   3452:        DPRINTF(VOLUMES, ("Rootdir(s) read in fine\n"));
                   3453:
                   3454:        /* release the vnodes again; they'll be auto-recycled later */
                   3455:        if (streamdir_node) {
                   3456:                vput(streamdir_node->vnode);
                   3457:        }
                   3458:        if (rootdir_node) {
                   3459:                vput(rootdir_node->vnode);
                   3460:        }
                   3461:
                   3462:        return 0;
                   3463: }
                   3464:
                   3465: /* --------------------------------------------------------------------- */
                   3466:
                   3467: /* To make absolutely sure we are NOT returning zero, add one :) */
                   3468:
                   3469: long
1.98      reinoud  3470: udf_get_node_id(const struct long_ad *icbptr)
1.45      reinoud  3471: {
                   3472:        /* ought to be enough since each mountpoint has its own chain */
                   3473:        return udf_rw32(icbptr->loc.lb_num) + 1;
                   3474: }
                   3475:
                   3476:
1.96      reinoud  3477: int
1.98      reinoud  3478: udf_compare_icb(const struct long_ad *a, const struct long_ad *b)
1.96      reinoud  3479: {
1.98      reinoud  3480:        if (udf_rw16(a->loc.part_num) < udf_rw16(b->loc.part_num))
                   3481:                return -1;
                   3482:        if (udf_rw16(a->loc.part_num) > udf_rw16(b->loc.part_num))
                   3483:                return 1;
                   3484:
                   3485:        if (udf_rw32(a->loc.lb_num) < udf_rw32(b->loc.lb_num))
                   3486:                return -1;
                   3487:        if (udf_rw32(a->loc.lb_num) > udf_rw32(b->loc.lb_num))
                   3488:                return 1;
                   3489:
                   3490:        return 0;
1.96      reinoud  3491: }
                   3492:
                   3493:
1.98      reinoud  3494: static int
1.108     rmind    3495: udf_compare_rbnodes(void *ctx, const void *a, const void *b)
1.45      reinoud  3496: {
1.108     rmind    3497:        const struct udf_node *a_node = a;
                   3498:        const struct udf_node *b_node = b;
1.98      reinoud  3499:
                   3500:        return udf_compare_icb(&a_node->loc, &b_node->loc);
                   3501: }
1.45      reinoud  3502:
                   3503:
1.98      reinoud  3504: static int
1.108     rmind    3505: udf_compare_rbnode_icb(void *ctx, const void *a, const void *key)
1.98      reinoud  3506: {
1.108     rmind    3507:        const struct udf_node *a_node = a;
1.98      reinoud  3508:        const struct long_ad * const icb = key;
1.45      reinoud  3509:
1.98      reinoud  3510:        return udf_compare_icb(&a_node->loc, icb);
1.45      reinoud  3511: }
                   3512:
                   3513:
1.108     rmind    3514: static const rb_tree_ops_t udf_node_rbtree_ops = {
1.98      reinoud  3515:        .rbto_compare_nodes = udf_compare_rbnodes,
1.108     rmind    3516:        .rbto_compare_key = udf_compare_rbnode_icb,
                   3517:        .rbto_node_offset = offsetof(struct udf_node, rbnode),
                   3518:        .rbto_context = NULL
1.98      reinoud  3519: };
                   3520:
                   3521:
                   3522: void
                   3523: udf_init_nodes_tree(struct udf_mount *ump)
1.45      reinoud  3524: {
1.108     rmind    3525:
1.98      reinoud  3526:        rb_tree_init(&ump->udf_node_tree, &udf_node_rbtree_ops);
                   3527: }
1.45      reinoud  3528:
                   3529:
                   3530: /* --------------------------------------------------------------------- */
                   3531:
1.85      reinoud  3532: static int
                   3533: udf_validate_session_start(struct udf_mount *ump)
                   3534: {
                   3535:        struct mmc_trackinfo trackinfo;
                   3536:        struct vrs_desc *vrs;
                   3537:        uint32_t tracknr, sessionnr, sector, sector_size;
                   3538:        uint32_t iso9660_vrs, write_track_start;
                   3539:        uint8_t *buffer, *blank, *pos;
                   3540:        int blks, max_sectors, vrs_len;
                   3541:        int error;
                   3542:
                   3543:        /* disc appendable? */
                   3544:        if (ump->discinfo.disc_state == MMC_STATE_FULL)
                   3545:                return EROFS;
                   3546:
                   3547:        /* already written here? if so, there should be an ISO VDS */
                   3548:        if (ump->discinfo.last_session_state == MMC_STATE_INCOMPLETE)
                   3549:                return 0;
                   3550:
                   3551:        /*
                   3552:         * Check if the first track of the session is blank and if so, copy or
                   3553:         * create a dummy ISO descriptor so the disc is valid again.
                   3554:         */
                   3555:
                   3556:        tracknr = ump->discinfo.first_track_last_session;
                   3557:        memset(&trackinfo, 0, sizeof(struct mmc_trackinfo));
                   3558:        trackinfo.tracknr = tracknr;
                   3559:        error = udf_update_trackinfo(ump, &trackinfo);
                   3560:        if (error)
                   3561:                return error;
                   3562:
                   3563:        udf_dump_trackinfo(&trackinfo);
                   3564:        KASSERT(trackinfo.flags & (MMC_TRACKINFO_BLANK | MMC_TRACKINFO_RESERVED));
                   3565:        KASSERT(trackinfo.sessionnr > 1);
                   3566:
                   3567:        KASSERT(trackinfo.flags & MMC_TRACKINFO_NWA_VALID);
                   3568:        write_track_start = trackinfo.next_writable;
                   3569:
                   3570:        /* we have to copy the ISO VRS from a former session */
                   3571:        DPRINTF(VOLUMES, ("validate_session_start: "
                   3572:                        "blank or reserved track, copying VRS\n"));
                   3573:
                   3574:        /* sessionnr should be the session we're mounting */
                   3575:        sessionnr = ump->mount_args.sessionnr;
                   3576:
                   3577:        /* start at the first track */
                   3578:        tracknr   = ump->discinfo.first_track;
                   3579:        while (tracknr <= ump->discinfo.num_tracks) {
                   3580:                trackinfo.tracknr = tracknr;
                   3581:                error = udf_update_trackinfo(ump, &trackinfo);
                   3582:                if (error) {
                   3583:                        DPRINTF(VOLUMES, ("failed to get trackinfo; aborting\n"));
                   3584:                        return error;
                   3585:                }
                   3586:                if (trackinfo.sessionnr == sessionnr)
                   3587:                        break;
                   3588:                tracknr++;
                   3589:        }
                   3590:        if (trackinfo.sessionnr != sessionnr) {
                   3591:                DPRINTF(VOLUMES, ("failed to get trackinfo; aborting\n"));
                   3592:                return ENOENT;
                   3593:        }
                   3594:
                   3595:        DPRINTF(VOLUMES, ("found possible former ISO VRS at\n"));
                   3596:        udf_dump_trackinfo(&trackinfo);
                   3597:
                   3598:         /*
                   3599:          * location of iso9660 vrs is defined as first sector AFTER 32kb,
                   3600:          * minimum ISO `sector size' 2048
                   3601:          */
                   3602:        sector_size = ump->discinfo.sector_size;
                   3603:        iso9660_vrs = ((32*1024 + sector_size - 1) / sector_size)
                   3604:                 + trackinfo.track_start;
                   3605:
                   3606:        buffer = malloc(UDF_ISO_VRS_SIZE, M_TEMP, M_WAITOK);
                   3607:        max_sectors = UDF_ISO_VRS_SIZE / sector_size;
                   3608:        blks = MAX(1, 2048 / sector_size);
                   3609:
                   3610:        error = 0;
                   3611:        for (sector = 0; sector < max_sectors; sector += blks) {
                   3612:                pos = buffer + sector * sector_size;
                   3613:                error = udf_read_phys_sectors(ump, UDF_C_DSCR, pos,
                   3614:                        iso9660_vrs + sector, blks);
                   3615:                if (error)
                   3616:                        break;
                   3617:                /* check this ISO descriptor */
                   3618:                vrs = (struct vrs_desc *) pos;
                   3619:                DPRINTF(VOLUMES, ("got VRS id `%4s`\n", vrs->identifier));
                   3620:                if (strncmp(vrs->identifier, VRS_CD001, 5) == 0)
                   3621:                        continue;
                   3622:                if (strncmp(vrs->identifier, VRS_CDW02, 5) == 0)
                   3623:                        continue;
                   3624:                if (strncmp(vrs->identifier, VRS_BEA01, 5) == 0)
                   3625:                        continue;
                   3626:                if (strncmp(vrs->identifier, VRS_NSR02, 5) == 0)
                   3627:                        continue;
                   3628:                if (strncmp(vrs->identifier, VRS_NSR03, 5) == 0)
                   3629:                        continue;
                   3630:                if (strncmp(vrs->identifier, VRS_TEA01, 5) == 0)
                   3631:                        break;
                   3632:                /* now what? for now, end of sequence */
                   3633:                break;
                   3634:        }
                   3635:        vrs_len = sector + blks;
                   3636:        if (error) {
                   3637:                DPRINTF(VOLUMES, ("error reading old ISO VRS\n"));
                   3638:                DPRINTF(VOLUMES, ("creating minimal ISO VRS\n"));
                   3639:
                   3640:                memset(buffer, 0, UDF_ISO_VRS_SIZE);
                   3641:
                   3642:                vrs = (struct vrs_desc *) (buffer);
                   3643:                vrs->struct_type = 0;
                   3644:                vrs->version     = 1;
                   3645:                memcpy(vrs->identifier,VRS_BEA01, 5);
                   3646:
                   3647:                vrs = (struct vrs_desc *) (buffer + 2048);
                   3648:                vrs->struct_type = 0;
                   3649:                vrs->version     = 1;
1.90      reinoud  3650:                if (udf_rw16(ump->logical_vol->tag.descriptor_ver) == 2) {
1.85      reinoud  3651:                        memcpy(vrs->identifier,VRS_NSR02, 5);
                   3652:                } else {
                   3653:                        memcpy(vrs->identifier,VRS_NSR03, 5);
                   3654:                }
                   3655:
                   3656:                vrs = (struct vrs_desc *) (buffer + 4096);
                   3657:                vrs->struct_type = 0;
                   3658:                vrs->version     = 1;
                   3659:                memcpy(vrs->identifier, VRS_TEA01, 5);
                   3660:
                   3661:                vrs_len = 3*blks;
                   3662:        }
                   3663:
                   3664:        DPRINTF(VOLUMES, ("Got VRS of %d sectors long\n", vrs_len));
                   3665:
                   3666:         /*
                   3667:          * location of iso9660 vrs is defined as first sector AFTER 32kb,
                   3668:          * minimum ISO `sector size' 2048
                   3669:          */
                   3670:        sector_size = ump->discinfo.sector_size;
                   3671:        iso9660_vrs = ((32*1024 + sector_size - 1) / sector_size)
                   3672:                 + write_track_start;
                   3673:
                   3674:        /* write out 32 kb */
                   3675:        blank = malloc(sector_size, M_TEMP, M_WAITOK);
                   3676:        memset(blank, 0, sector_size);
                   3677:        error = 0;
                   3678:        for (sector = write_track_start; sector < iso9660_vrs; sector ++) {
                   3679:                error = udf_write_phys_sectors(ump, UDF_C_ABSOLUTE,
                   3680:                        blank, sector, 1);
                   3681:                if (error)
                   3682:                        break;
                   3683:        }
                   3684:        if (!error) {
                   3685:                /* write out our ISO VRS */
                   3686:                KASSERT(sector == iso9660_vrs);
                   3687:                error = udf_write_phys_sectors(ump, UDF_C_ABSOLUTE, buffer,
                   3688:                                sector, vrs_len);
                   3689:                sector += vrs_len;
                   3690:        }
                   3691:        if (!error) {
                   3692:                /* fill upto the first anchor at S+256 */
                   3693:                for (; sector < write_track_start+256; sector++) {
                   3694:                        error = udf_write_phys_sectors(ump, UDF_C_ABSOLUTE,
                   3695:                                blank, sector, 1);
                   3696:                        if (error)
                   3697:                                break;
                   3698:                }
                   3699:        }
                   3700:        if (!error) {
                   3701:                /* write out anchor; write at ABSOLUTE place! */
                   3702:                error = udf_write_phys_dscr_sync(ump, NULL, UDF_C_ABSOLUTE,
                   3703:                        (union dscrptr *) ump->anchors[0], sector, sector);
                   3704:                if (error)
                   3705:                        printf("writeout of anchor failed!\n");
                   3706:        }
                   3707:
                   3708:        free(blank, M_TEMP);
                   3709:        free(buffer, M_TEMP);
                   3710:
                   3711:        if (error)
                   3712:                printf("udf_open_session: error writing iso vrs! : "
                   3713:                                "leaving disc in compromised state!\n");
                   3714:
                   3715:        /* synchronise device caches */
                   3716:        (void) udf_synchronise_caches(ump);
                   3717:
                   3718:        return error;
                   3719: }
                   3720:
                   3721:
1.45      reinoud  3722: int
                   3723: udf_open_logvol(struct udf_mount *ump)
                   3724: {
                   3725:        int logvol_integrity;
                   3726:        int error;
                   3727:
                   3728:        /* already/still open? */
                   3729:        logvol_integrity = udf_rw32(ump->logvol_integrity->integrity_type);
                   3730:        if (logvol_integrity == UDF_INTEGRITY_OPEN)
                   3731:                return 0;
                   3732:
                   3733:        /* can we open it ? */
                   3734:        if (ump->vfs_mountp->mnt_flag & MNT_RDONLY)
                   3735:                return EROFS;
                   3736:
                   3737:        /* setup write parameters */
                   3738:        DPRINTF(VOLUMES, ("Setting up write parameters\n"));
                   3739:        if ((error = udf_setup_writeparams(ump)) != 0)
                   3740:                return error;
                   3741:
                   3742:        /* determine data and metadata tracks (most likely same) */
                   3743:        error = udf_search_writing_tracks(ump);
                   3744:        if (error) {
                   3745:                /* most likely lack of space */
                   3746:                printf("udf_open_logvol: error searching writing tracks\n");
                   3747:                return EROFS;
                   3748:        }
                   3749:
                   3750:        /* writeout/update lvint on disc or only in memory */
                   3751:        DPRINTF(VOLUMES, ("Opening logical volume\n"));
                   3752:        if (ump->lvopen & UDF_OPEN_SESSION) {
1.85      reinoud  3753:                /* TODO optional track reservation opening */
                   3754:                error = udf_validate_session_start(ump);
                   3755:                if (error)
                   3756:                        return error;
1.45      reinoud  3757:
                   3758:                /* determine data and metadata tracks again */
                   3759:                error = udf_search_writing_tracks(ump);
1.137     reinoud  3760:
                   3761:                if (ump->lvclose & UDF_WRITE_VAT) {
                   3762:                        /*
                   3763:                         * we writeout the VAT to get a self-sustained session
                   3764:                         * for fsck
                   3765:                         */
                   3766:                        DPRINTF(VOLUMES, ("lvclose & UDF_WRITE_VAT\n"));
                   3767:
                   3768:                        /* write out the VAT data and all its descriptors */
                   3769:                        DPRINTF(VOLUMES, ("writeout vat_node\n"));
                   3770:                        udf_writeout_vat(ump);
                   3771:
1.138     reinoud  3772:                        /* force everything to be synchronized on the device */
                   3773:                        (void) udf_synchronise_caches(ump);
1.137     reinoud  3774:                }
1.45      reinoud  3775:        }
                   3776:
                   3777:        /* mark it open */
                   3778:        ump->logvol_integrity->integrity_type = udf_rw32(UDF_INTEGRITY_OPEN);
                   3779:
                   3780:        /* do we need to write it out? */
                   3781:        if (ump->lvopen & UDF_WRITE_LVINT) {
                   3782:                error = udf_writeout_lvint(ump, ump->lvopen);
                   3783:                /* if we couldn't write it mark it closed again */
                   3784:                if (error) {
                   3785:                        ump->logvol_integrity->integrity_type =
                   3786:                                                udf_rw32(UDF_INTEGRITY_CLOSED);
                   3787:                        return error;
                   3788:                }
                   3789:        }
                   3790:
                   3791:        return 0;
                   3792: }
                   3793:
                   3794:
                   3795: int
                   3796: udf_close_logvol(struct udf_mount *ump, int mntflags)
                   3797: {
1.85      reinoud  3798:        struct vnode *devvp = ump->devvp;
                   3799:        struct mmc_op mmc_op;
1.45      reinoud  3800:        int logvol_integrity;
1.70      reinoud  3801:        int error = 0, error1 = 0, error2 = 0;
1.85      reinoud  3802:        int tracknr;
                   3803:        int nvats, n, nok;
1.45      reinoud  3804:
                   3805:        /* already/still closed? */
                   3806:        logvol_integrity = udf_rw32(ump->logvol_integrity->integrity_type);
                   3807:        if (logvol_integrity == UDF_INTEGRITY_CLOSED)
                   3808:                return 0;
                   3809:
                   3810:        /* writeout/update lvint or write out VAT */
1.85      reinoud  3811:        DPRINTF(VOLUMES, ("udf_close_logvol: closing logical volume\n"));
                   3812: #ifdef DIAGNOSTIC
                   3813:        if (ump->lvclose & UDF_CLOSE_SESSION)
                   3814:                KASSERT(ump->lvclose & UDF_WRITE_VAT);
                   3815: #endif
                   3816:
1.45      reinoud  3817:        if (ump->lvclose & UDF_WRITE_VAT) {
                   3818:                DPRINTF(VOLUMES, ("lvclose & UDF_WRITE_VAT\n"));
                   3819:
1.85      reinoud  3820:                /* write out the VAT data and all its descriptors */
1.45      reinoud  3821:                DPRINTF(VOLUMES, ("writeout vat_node\n"));
1.71      reinoud  3822:                udf_writeout_vat(ump);
1.85      reinoud  3823:
                   3824:                /* at least two DVD packets and 3 CD-R packets */
                   3825:                nvats = 32;
                   3826:
                   3827: #if notyet
                   3828:                /*
                   3829:                 * TODO calculate the available space and if the disc is
1.165     andvar   3830:                 * almost full, write out till end-256-1 with banks, write
1.85      reinoud  3831:                 * AVDP and fill up with VATs, then close session and close
                   3832:                 * disc.
                   3833:                 */
                   3834:                if (ump->lvclose & UDF_FINALISE_DISC) {
                   3835:                        error = udf_write_phys_dscr_sync(ump, NULL,
                   3836:                                        UDF_C_FLOAT_DSCR,
                   3837:                                        (union dscrptr *) ump->anchors[0],
                   3838:                                        0, 0);
                   3839:                        if (error)
                   3840:                                printf("writeout of anchor failed!\n");
                   3841:
                   3842:                        /* pad space with VAT ICBs */
                   3843:                        nvats = 256;
                   3844:                }
                   3845: #endif
                   3846:
                   3847:                /* write out a number of VAT nodes */
                   3848:                nok = 0;
                   3849:                for (n = 0; n < nvats; n++) {
                   3850:                        /* will now only write last FE/EFE */
1.45      reinoud  3851:                        ump->vat_node->i_flags |= IN_MODIFIED;
                   3852:                        error = VOP_FSYNC(ump->vat_node->vnode,
                   3853:                                        FSCRED, FSYNC_WAIT, 0, 0);
1.85      reinoud  3854:                        if (!error)
                   3855:                                nok++;
                   3856:                }
1.138     reinoud  3857:                /* force everything to be synchronized on the device */
                   3858:                (void) udf_synchronise_caches(ump);
                   3859:
1.85      reinoud  3860:                if (nok < 14) {
                   3861:                        /* arbitrary; but at least one or two CD frames */
                   3862:                        printf("writeout of at least 14 VATs failed\n");
                   3863:                        return error;
                   3864:                }
                   3865:        }
                   3866:
                   3867:        /* NOTE the disc is in a (minimal) valid state now; no erroring out */
                   3868:
                   3869:        /* finish closing of session */
                   3870:        if (ump->lvclose & UDF_CLOSE_SESSION) {
1.138     reinoud  3871:                DPRINTF(VOLUMES, ("udf_close_logvol: closing session "
                   3872:                        "as requested\n"));
1.85      reinoud  3873:                error = udf_validate_session_start(ump);
                   3874:                if (error)
                   3875:                        return error;
                   3876:
1.99      reinoud  3877:                (void) udf_synchronise_caches(ump);
                   3878:
1.85      reinoud  3879:                /* close all associated tracks */
                   3880:                tracknr = ump->discinfo.first_track_last_session;
                   3881:                error = 0;
                   3882:                while (tracknr <= ump->discinfo.last_track_last_session) {
                   3883:                        DPRINTF(VOLUMES, ("\tclosing possible open "
                   3884:                                "track %d\n", tracknr));
                   3885:                        memset(&mmc_op, 0, sizeof(mmc_op));
                   3886:                        mmc_op.operation   = MMC_OP_CLOSETRACK;
                   3887:                        mmc_op.mmc_profile = ump->discinfo.mmc_profile;
                   3888:                        mmc_op.tracknr     = tracknr;
                   3889:                        error = VOP_IOCTL(devvp, MMCOP, &mmc_op,
                   3890:                                        FKIOCTL, NOCRED);
                   3891:                        if (error)
                   3892:                                printf("udf_close_logvol: closing of "
                   3893:                                        "track %d failed\n", tracknr);
                   3894:                        tracknr ++;
                   3895:                }
                   3896:                if (!error) {
                   3897:                        DPRINTF(VOLUMES, ("closing session\n"));
                   3898:                        memset(&mmc_op, 0, sizeof(mmc_op));
                   3899:                        mmc_op.operation   = MMC_OP_CLOSESESSION;
                   3900:                        mmc_op.mmc_profile = ump->discinfo.mmc_profile;
                   3901:                        mmc_op.sessionnr   = ump->discinfo.num_sessions;
                   3902:                        error = VOP_IOCTL(devvp, MMCOP, &mmc_op,
                   3903:                                        FKIOCTL, NOCRED);
                   3904:                        if (error)
                   3905:                                printf("udf_close_logvol: closing of session"
                   3906:                                                "failed\n");
1.45      reinoud  3907:                }
1.85      reinoud  3908:                if (!error)
                   3909:                        ump->lvopen |= UDF_OPEN_SESSION;
1.45      reinoud  3910:                if (error) {
1.85      reinoud  3911:                        printf("udf_close_logvol: leaving disc as it is\n");
                   3912:                        ump->lvclose &= ~UDF_FINALISE_DISC;
1.45      reinoud  3913:                }
                   3914:        }
                   3915:
1.85      reinoud  3916:        if (ump->lvclose & UDF_FINALISE_DISC) {
                   3917:                memset(&mmc_op, 0, sizeof(mmc_op));
                   3918:                mmc_op.operation   = MMC_OP_FINALISEDISC;
                   3919:                mmc_op.mmc_profile = ump->discinfo.mmc_profile;
                   3920:                mmc_op.sessionnr   = ump->discinfo.num_sessions;
                   3921:                error = VOP_IOCTL(devvp, MMCOP, &mmc_op,
                   3922:                                FKIOCTL, NOCRED);
                   3923:                if (error)
                   3924:                        printf("udf_close_logvol: finalising disc"
                   3925:                                        "failed\n");
                   3926:        }
                   3927:
                   3928:        /* write out partition bitmaps if requested */
1.45      reinoud  3929:        if (ump->lvclose & UDF_WRITE_PART_BITMAPS) {
1.70      reinoud  3930:                /* sync writeout metadata spacetable if existing */
                   3931:                error1 = udf_write_metadata_partition_spacetable(ump, true);
                   3932:                if (error1)
                   3933:                        printf( "udf_close_logvol: writeout of metadata space "
                   3934:                                "bitmap failed\n");
                   3935:
1.68      reinoud  3936:                /* sync writeout partition spacetables */
1.70      reinoud  3937:                error2 = udf_write_physical_partition_spacetables(ump, true);
                   3938:                if (error2)
1.45      reinoud  3939:                        printf( "udf_close_logvol: writeout of space tables "
                   3940:                                "failed\n");
1.70      reinoud  3941:
                   3942:                if (error1 || error2)
                   3943:                        return (error1 | error2);
                   3944:
1.45      reinoud  3945:                ump->lvclose &= ~UDF_WRITE_PART_BITMAPS;
                   3946:        }
                   3947:
1.104     reinoud  3948:        /* write out metadata partition nodes if requested */
                   3949:        if (ump->lvclose & UDF_WRITE_METAPART_NODES) {
                   3950:                /* sync writeout metadata descriptor node */
                   3951:                error1 = udf_writeout_node(ump->metadata_node, FSYNC_WAIT);
                   3952:                if (error1)
                   3953:                        printf( "udf_close_logvol: writeout of metadata partition "
                   3954:                                "node failed\n");
                   3955:
                   3956:                /* duplicate metadata partition descriptor if needed */
                   3957:                udf_synchronise_metadatamirror_node(ump);
                   3958:
                   3959:                /* sync writeout metadatamirror descriptor node */
                   3960:                error2 = udf_writeout_node(ump->metadatamirror_node, FSYNC_WAIT);
                   3961:                if (error2)
                   3962:                        printf( "udf_close_logvol: writeout of metadata partition "
                   3963:                                "mirror node failed\n");
                   3964:
                   3965:                if (error1 || error2)
                   3966:                        return (error1 | error2);
                   3967:
                   3968:                ump->lvclose &= ~UDF_WRITE_METAPART_NODES;
                   3969:        }
                   3970:
1.45      reinoud  3971:        /* mark it closed */
                   3972:        ump->logvol_integrity->integrity_type = udf_rw32(UDF_INTEGRITY_CLOSED);
                   3973:
1.85      reinoud  3974:        /* do we need to write out the logical volume integrity? */
1.45      reinoud  3975:        if (ump->lvclose & UDF_WRITE_LVINT)
                   3976:                error = udf_writeout_lvint(ump, ump->lvopen);
                   3977:        if (error) {
                   3978:                /* HELP now what? mark it open again for now */
                   3979:                ump->logvol_integrity->integrity_type =
                   3980:                        udf_rw32(UDF_INTEGRITY_OPEN);
                   3981:                return error;
1.9       christos 3982:        }
1.1       reinoud  3983:
1.45      reinoud  3984:        (void) udf_synchronise_caches(ump);
1.1       reinoud  3985:
                   3986:        return 0;
                   3987: }
                   3988:
                   3989: /* --------------------------------------------------------------------- */
                   3990:
                   3991: /*
1.45      reinoud  3992:  * Genfs interfacing
                   3993:  *
                   3994:  * static const struct genfs_ops udf_genfsops = {
                   3995:  *     .gop_size = genfs_size,
                   3996:  *             size of transfers
                   3997:  *     .gop_alloc = udf_gop_alloc,
                   3998:  *             allocate len bytes at offset
                   3999:  *     .gop_write = genfs_gop_write,
                   4000:  *             putpages interface code
                   4001:  *     .gop_markupdate = udf_gop_markupdate,
                   4002:  *             set update/modify flags etc.
                   4003:  * }
                   4004:  */
                   4005:
                   4006: /*
                   4007:  * Genfs interface. These four functions are the only ones defined though not
                   4008:  * documented... great....
1.1       reinoud  4009:  */
                   4010:
1.45      reinoud  4011: /*
1.95      reinoud  4012:  * Called for allocating an extent of the file either by VOP_WRITE() or by
                   4013:  * genfs filling up gaps.
1.45      reinoud  4014:  */
1.1       reinoud  4015: static int
1.45      reinoud  4016: udf_gop_alloc(struct vnode *vp, off_t off,
                   4017:     off_t len, int flags, kauth_cred_t cred)
                   4018: {
                   4019:        struct udf_node *udf_node = VTOI(vp);
                   4020:        struct udf_mount *ump = udf_node->ump;
1.95      reinoud  4021:        uint64_t lb_start, lb_end;
1.45      reinoud  4022:        uint32_t lb_size, num_lb;
1.95      reinoud  4023:        int udf_c_type, vpart_num, can_fail;
                   4024:        int error;
                   4025:
                   4026:        DPRINTF(ALLOC, ("udf_gop_alloc called for offset %"PRIu64" for %"PRIu64" bytes, %s\n",
                   4027:                off, len, flags? "SYNC":"NONE"));
                   4028:
                   4029:        /*
                   4030:         * request the pages of our vnode and see how many pages will need to
                   4031:         * be allocated and reserve that space
                   4032:         */
                   4033:        lb_size  = udf_rw32(udf_node->ump->logical_vol->lb_size);
                   4034:        lb_start = off / lb_size;
                   4035:        lb_end   = (off + len + lb_size -1) / lb_size;
                   4036:        num_lb   = lb_end - lb_start;
                   4037:
                   4038:        udf_c_type = udf_get_c_type(udf_node);
                   4039:        vpart_num  = udf_get_record_vpart(ump, udf_c_type);
                   4040:
                   4041:        /* all requests can fail */
                   4042:        can_fail   = true;
                   4043:
                   4044:        /* fid's (directories) can't fail */
                   4045:        if (udf_c_type == UDF_C_FIDS)
                   4046:                can_fail   = false;
                   4047:
                   4048:        /* system files can't fail */
                   4049:        if (vp->v_vflag & VV_SYSTEM)
                   4050:                can_fail = false;
                   4051:
                   4052:        error = udf_reserve_space(ump, udf_node, udf_c_type,
                   4053:                vpart_num, num_lb, can_fail);
1.45      reinoud  4054:
1.95      reinoud  4055:        DPRINTF(ALLOC, ("\tlb_start %"PRIu64", lb_end %"PRIu64", num_lb %d\n",
                   4056:                lb_start, lb_end, num_lb));
1.45      reinoud  4057:
1.95      reinoud  4058:        return error;
1.45      reinoud  4059: }
                   4060:
                   4061:
                   4062: /*
                   4063:  * callback from genfs to update our flags
                   4064:  */
                   4065: static void
                   4066: udf_gop_markupdate(struct vnode *vp, int flags)
                   4067: {
                   4068:        struct udf_node *udf_node = VTOI(vp);
                   4069:        u_long mask = 0;
                   4070:
                   4071:        if ((flags & GOP_UPDATE_ACCESSED) != 0) {
                   4072:                mask = IN_ACCESS;
                   4073:        }
                   4074:        if ((flags & GOP_UPDATE_MODIFIED) != 0) {
                   4075:                if (vp->v_type == VREG) {
                   4076:                        mask |= IN_CHANGE | IN_UPDATE;
                   4077:                } else {
                   4078:                        mask |= IN_MODIFY;
                   4079:                }
                   4080:        }
                   4081:        if (mask) {
                   4082:                udf_node->i_flags |= mask;
                   4083:        }
                   4084: }
                   4085:
                   4086:
                   4087: static const struct genfs_ops udf_genfsops = {
                   4088:        .gop_size = genfs_size,
                   4089:        .gop_alloc = udf_gop_alloc,
                   4090:        .gop_write = genfs_gop_write_rwmap,
                   4091:        .gop_markupdate = udf_gop_markupdate,
1.140     chs      4092:        .gop_putrange = genfs_gop_putrange,
1.45      reinoud  4093: };
                   4094:
                   4095:
                   4096: /* --------------------------------------------------------------------- */
                   4097:
                   4098: int
                   4099: udf_write_terminator(struct udf_mount *ump, uint32_t sector)
1.1       reinoud  4100: {
1.45      reinoud  4101:        union dscrptr *dscr;
1.1       reinoud  4102:        int error;
                   4103:
1.83      cegger   4104:        dscr = malloc(ump->discinfo.sector_size, M_TEMP, M_WAITOK|M_ZERO);
1.45      reinoud  4105:        udf_inittag(ump, &dscr->tag, TAGID_TERM, sector);
                   4106:
                   4107:        /* CRC length for an anchor is 512 - tag length; defined in Ecma 167 */
                   4108:        dscr->tag.desc_crc_len = udf_rw16(512-UDF_DESC_TAG_LENGTH);
                   4109:        (void) udf_validate_tag_and_crc_sums(dscr);
                   4110:
                   4111:        error = udf_write_phys_dscr_sync(ump, NULL, UDF_C_DSCR,
                   4112:                        dscr, sector, sector);
                   4113:
                   4114:        free(dscr, M_TEMP);
                   4115:
                   4116:        return error;
                   4117: }
                   4118:
                   4119:
                   4120: /* --------------------------------------------------------------------- */
                   4121:
                   4122: /* UDF<->unix converters */
                   4123:
                   4124: /* --------------------------------------------------------------------- */
                   4125:
                   4126: static mode_t
                   4127: udf_perm_to_unix_mode(uint32_t perm)
                   4128: {
                   4129:        mode_t mode;
                   4130:
                   4131:        mode  = ((perm & UDF_FENTRY_PERM_USER_MASK)      );
                   4132:        mode |= ((perm & UDF_FENTRY_PERM_GRP_MASK  ) >> 2);
                   4133:        mode |= ((perm & UDF_FENTRY_PERM_OWNER_MASK) >> 4);
                   4134:
                   4135:        return mode;
                   4136: }
                   4137:
                   4138: /* --------------------------------------------------------------------- */
                   4139:
                   4140: static uint32_t
                   4141: unix_mode_to_udf_perm(mode_t mode)
                   4142: {
                   4143:        uint32_t perm;
1.152     skrll    4144:
1.45      reinoud  4145:        perm  = ((mode & S_IRWXO)     );
                   4146:        perm |= ((mode & S_IRWXG) << 2);
                   4147:        perm |= ((mode & S_IRWXU) << 4);
                   4148:        perm |= ((mode & S_IWOTH) << 3);
                   4149:        perm |= ((mode & S_IWGRP) << 5);
                   4150:        perm |= ((mode & S_IWUSR) << 7);
                   4151:
                   4152:        return perm;
                   4153: }
                   4154:
                   4155: /* --------------------------------------------------------------------- */
                   4156:
                   4157: static uint32_t
                   4158: udf_icb_to_unix_filetype(uint32_t icbftype)
                   4159: {
                   4160:        switch (icbftype) {
                   4161:        case UDF_ICB_FILETYPE_DIRECTORY :
                   4162:        case UDF_ICB_FILETYPE_STREAMDIR :
                   4163:                return S_IFDIR;
                   4164:        case UDF_ICB_FILETYPE_FIFO :
                   4165:                return S_IFIFO;
                   4166:        case UDF_ICB_FILETYPE_CHARDEVICE :
                   4167:                return S_IFCHR;
                   4168:        case UDF_ICB_FILETYPE_BLOCKDEVICE :
                   4169:                return S_IFBLK;
                   4170:        case UDF_ICB_FILETYPE_RANDOMACCESS :
                   4171:        case UDF_ICB_FILETYPE_REALTIME :
                   4172:                return S_IFREG;
                   4173:        case UDF_ICB_FILETYPE_SYMLINK :
                   4174:                return S_IFLNK;
                   4175:        case UDF_ICB_FILETYPE_SOCKET :
                   4176:                return S_IFSOCK;
                   4177:        }
                   4178:        /* no idea what this is */
                   4179:        return 0;
                   4180: }
1.1       reinoud  4181:
1.45      reinoud  4182: /* --------------------------------------------------------------------- */
1.1       reinoud  4183:
1.45      reinoud  4184: void
1.48      reinoud  4185: udf_to_unix_name(char *result, int result_len, char *id, int len,
                   4186:        struct charspec *chsp)
1.45      reinoud  4187: {
                   4188:        uint16_t   *raw_name, *unix_name;
                   4189:        uint16_t   *inchp, ch;
                   4190:        uint8_t    *outchp;
                   4191:        const char *osta_id = "OSTA Compressed Unicode";
1.48      reinoud  4192:        int         ucode_chars, nice_uchars, is_osta_typ0, nout;
1.1       reinoud  4193:
1.45      reinoud  4194:        raw_name = malloc(2048 * sizeof(uint16_t), M_UDFTEMP, M_WAITOK);
                   4195:        unix_name = raw_name + 1024;                    /* split space in half */
                   4196:        assert(sizeof(char) == sizeof(uint8_t));
                   4197:        outchp = (uint8_t *) result;
1.1       reinoud  4198:
1.45      reinoud  4199:        is_osta_typ0  = (chsp->type == 0);
                   4200:        is_osta_typ0 &= (strcmp((char *) chsp->inf, osta_id) == 0);
                   4201:        if (is_osta_typ0) {
1.48      reinoud  4202:                /* TODO clean up */
1.45      reinoud  4203:                *raw_name = *unix_name = 0;
                   4204:                ucode_chars = udf_UncompressUnicode(len, (uint8_t *) id, raw_name);
                   4205:                ucode_chars = MIN(ucode_chars, UnicodeLength((unicode_t *) raw_name));
                   4206:                nice_uchars = UDFTransName(unix_name, raw_name, ucode_chars);
1.48      reinoud  4207:                /* output UTF8 */
1.45      reinoud  4208:                for (inchp = unix_name; nice_uchars>0; inchp++, nice_uchars--) {
                   4209:                        ch = *inchp;
1.48      reinoud  4210:                        nout = wput_utf8(outchp, result_len, ch);
                   4211:                        outchp += nout; result_len -= nout;
1.45      reinoud  4212:                        if (!ch) break;
                   4213:                }
                   4214:                *outchp++ = 0;
1.1       reinoud  4215:        } else {
1.45      reinoud  4216:                /* assume 8bit char length byte latin-1 */
                   4217:                assert(*id == 8);
1.117     christos 4218:                assert(strlen((char *) (id+1)) <= NAME_MAX);
1.45      reinoud  4219:                strncpy((char *) result, (char *) (id+1), strlen((char *) (id+1)));
1.9       christos 4220:        }
1.45      reinoud  4221:        free(raw_name, M_UDFTEMP);
                   4222: }
                   4223:
                   4224: /* --------------------------------------------------------------------- */
1.1       reinoud  4225:
1.45      reinoud  4226: void
                   4227: unix_to_udf_name(char *result, uint8_t *result_len, char const *name, int name_len,
                   4228:        struct charspec *chsp)
                   4229: {
                   4230:        uint16_t   *raw_name;
                   4231:        uint16_t   *outchp;
                   4232:        const char *inchp;
                   4233:        const char *osta_id = "OSTA Compressed Unicode";
1.49      christos 4234:        int         udf_chars, is_osta_typ0, bits;
                   4235:        size_t      cnt;
1.1       reinoud  4236:
1.45      reinoud  4237:        /* allocate temporary unicode-16 buffer */
                   4238:        raw_name = malloc(1024, M_UDFTEMP, M_WAITOK);
1.1       reinoud  4239:
1.48      reinoud  4240:        /* convert utf8 to unicode-16 */
1.45      reinoud  4241:        *raw_name = 0;
                   4242:        inchp  = name;
                   4243:        outchp = raw_name;
1.48      reinoud  4244:        bits = 8;
                   4245:        for (cnt = name_len, udf_chars = 0; cnt;) {
                   4246:                *outchp = wget_utf8(&inchp, &cnt);
                   4247:                if (*outchp > 0xff)
                   4248:                        bits=16;
                   4249:                outchp++;
                   4250:                udf_chars++;
1.45      reinoud  4251:        }
1.48      reinoud  4252:        /* null terminate just in case */
                   4253:        *outchp++ = 0;
1.1       reinoud  4254:
1.45      reinoud  4255:        is_osta_typ0  = (chsp->type == 0);
                   4256:        is_osta_typ0 &= (strcmp((char *) chsp->inf, osta_id) == 0);
                   4257:        if (is_osta_typ0) {
1.48      reinoud  4258:                udf_chars = udf_CompressUnicode(udf_chars, bits,
1.45      reinoud  4259:                                (unicode_t *) raw_name,
                   4260:                                (byte *) result);
                   4261:        } else {
1.48      reinoud  4262:                printf("unix to udf name: no CHSP0 ?\n");
1.45      reinoud  4263:                /* XXX assume 8bit char length byte latin-1 */
                   4264:                *result++ = 8; udf_chars = 1;
                   4265:                strncpy(result, name + 1, name_len);
                   4266:                udf_chars += name_len;
1.9       christos 4267:        }
1.45      reinoud  4268:        *result_len = udf_chars;
                   4269:        free(raw_name, M_UDFTEMP);
                   4270: }
                   4271:
                   4272: /* --------------------------------------------------------------------- */
                   4273:
                   4274: void
                   4275: udf_timestamp_to_timespec(struct udf_mount *ump,
                   4276:                          struct timestamp *timestamp,
                   4277:                          struct timespec  *timespec)
                   4278: {
                   4279:        struct clock_ymdhms ymdhms;
                   4280:        uint32_t usecs, secs, nsecs;
                   4281:        uint16_t tz;
                   4282:
                   4283:        /* fill in ymdhms structure from timestamp */
                   4284:        memset(&ymdhms, 0, sizeof(ymdhms));
                   4285:        ymdhms.dt_year = udf_rw16(timestamp->year);
                   4286:        ymdhms.dt_mon  = timestamp->month;
                   4287:        ymdhms.dt_day  = timestamp->day;
                   4288:        ymdhms.dt_wday = 0; /* ? */
                   4289:        ymdhms.dt_hour = timestamp->hour;
                   4290:        ymdhms.dt_min  = timestamp->minute;
                   4291:        ymdhms.dt_sec  = timestamp->second;
                   4292:
                   4293:        secs = clock_ymdhms_to_secs(&ymdhms);
                   4294:        usecs = timestamp->usec +
                   4295:                100*timestamp->hund_usec + 10000*timestamp->centisec;
                   4296:        nsecs = usecs * 1000;
1.1       reinoud  4297:
                   4298:        /*
1.45      reinoud  4299:         * Calculate the time zone.  The timezone is 12 bit signed 2's
                   4300:         * compliment, so we gotta do some extra magic to handle it right.
1.1       reinoud  4301:         */
1.45      reinoud  4302:        tz  = udf_rw16(timestamp->type_tz);
                   4303:        tz &= 0x0fff;                   /* only lower 12 bits are significant */
1.157     andvar   4304:        if (tz & 0x0800)                /* sign extension */
1.45      reinoud  4305:                tz |= 0xf000;
1.1       reinoud  4306:
1.45      reinoud  4307:        /* TODO check timezone conversion */
                   4308:        /* check if we are specified a timezone to convert */
                   4309:        if (udf_rw16(timestamp->type_tz) & 0x1000) {
                   4310:                if ((int16_t) tz != -2047)
                   4311:                        secs -= (int16_t) tz * 60;
1.1       reinoud  4312:        } else {
1.45      reinoud  4313:                secs -= ump->mount_args.gmtoff;
                   4314:        }
1.1       reinoud  4315:
1.45      reinoud  4316:        timespec->tv_sec  = secs;
                   4317:        timespec->tv_nsec = nsecs;
                   4318: }
1.1       reinoud  4319:
                   4320:
1.45      reinoud  4321: void
                   4322: udf_timespec_to_timestamp(struct timespec *timespec, struct timestamp *timestamp)
                   4323: {
                   4324:        struct clock_ymdhms ymdhms;
                   4325:        uint32_t husec, usec, csec;
1.1       reinoud  4326:
1.45      reinoud  4327:        (void) clock_secs_to_ymdhms(timespec->tv_sec, &ymdhms);
1.1       reinoud  4328:
1.58      reinoud  4329:        usec   = timespec->tv_nsec / 1000;
                   4330:        husec  =  usec / 100;
                   4331:        usec  -= husec * 100;                           /* only 0-99 in usec  */
                   4332:        csec   = husec / 100;                           /* only 0-99 in csec  */
                   4333:        husec -=  csec * 100;                           /* only 0-99 in husec */
1.45      reinoud  4334:
                   4335:        /* set method 1 for CUT/GMT */
                   4336:        timestamp->type_tz      = udf_rw16((1<<12) + 0);
                   4337:        timestamp->year         = udf_rw16(ymdhms.dt_year);
                   4338:        timestamp->month        = ymdhms.dt_mon;
                   4339:        timestamp->day          = ymdhms.dt_day;
                   4340:        timestamp->hour         = ymdhms.dt_hour;
                   4341:        timestamp->minute       = ymdhms.dt_min;
                   4342:        timestamp->second       = ymdhms.dt_sec;
                   4343:        timestamp->centisec     = csec;
                   4344:        timestamp->hund_usec    = husec;
                   4345:        timestamp->usec         = usec;
1.1       reinoud  4346: }
                   4347:
                   4348: /* --------------------------------------------------------------------- */
                   4349:
1.45      reinoud  4350: /*
                   4351:  * Attribute and filetypes converters with get/set pairs
                   4352:  */
                   4353:
                   4354: uint32_t
                   4355: udf_getaccessmode(struct udf_node *udf_node)
1.1       reinoud  4356: {
1.101     mbalmer  4357:        struct file_entry     *fe = udf_node->fe;
1.45      reinoud  4358:        struct extfile_entry *efe = udf_node->efe;
                   4359:        uint32_t udf_perm, icbftype;
                   4360:        uint32_t mode, ftype;
                   4361:        uint16_t icbflags;
1.1       reinoud  4362:
1.45      reinoud  4363:        UDF_LOCK_NODE(udf_node, 0);
                   4364:        if (fe) {
                   4365:                udf_perm = udf_rw32(fe->perm);
                   4366:                icbftype = fe->icbtag.file_type;
                   4367:                icbflags = udf_rw16(fe->icbtag.flags);
                   4368:        } else {
                   4369:                assert(udf_node->efe);
                   4370:                udf_perm = udf_rw32(efe->perm);
                   4371:                icbftype = efe->icbtag.file_type;
                   4372:                icbflags = udf_rw16(efe->icbtag.flags);
                   4373:        }
1.1       reinoud  4374:
1.45      reinoud  4375:        mode  = udf_perm_to_unix_mode(udf_perm);
                   4376:        ftype = udf_icb_to_unix_filetype(icbftype);
1.1       reinoud  4377:
1.45      reinoud  4378:        /* set suid, sgid, sticky from flags in fe/efe */
                   4379:        if (icbflags & UDF_ICB_TAG_FLAGS_SETUID)
                   4380:                mode |= S_ISUID;
                   4381:        if (icbflags & UDF_ICB_TAG_FLAGS_SETGID)
                   4382:                mode |= S_ISGID;
                   4383:        if (icbflags & UDF_ICB_TAG_FLAGS_STICKY)
                   4384:                mode |= S_ISVTX;
1.1       reinoud  4385:
1.45      reinoud  4386:        UDF_UNLOCK_NODE(udf_node, 0);
1.1       reinoud  4387:
1.45      reinoud  4388:        return mode | ftype;
1.1       reinoud  4389: }
                   4390:
                   4391:
1.45      reinoud  4392: void
                   4393: udf_setaccessmode(struct udf_node *udf_node, mode_t mode)
1.1       reinoud  4394: {
1.45      reinoud  4395:        struct file_entry    *fe  = udf_node->fe;
                   4396:        struct extfile_entry *efe = udf_node->efe;
                   4397:        uint32_t udf_perm;
                   4398:        uint16_t icbflags;
                   4399:
                   4400:        UDF_LOCK_NODE(udf_node, 0);
                   4401:        udf_perm = unix_mode_to_udf_perm(mode & ALLPERMS);
                   4402:        if (fe) {
                   4403:                icbflags = udf_rw16(fe->icbtag.flags);
                   4404:        } else {
                   4405:                icbflags = udf_rw16(efe->icbtag.flags);
                   4406:        }
1.1       reinoud  4407:
1.45      reinoud  4408:        icbflags &= ~UDF_ICB_TAG_FLAGS_SETUID;
                   4409:        icbflags &= ~UDF_ICB_TAG_FLAGS_SETGID;
                   4410:        icbflags &= ~UDF_ICB_TAG_FLAGS_STICKY;
                   4411:        if (mode & S_ISUID)
                   4412:                icbflags |= UDF_ICB_TAG_FLAGS_SETUID;
                   4413:        if (mode & S_ISGID)
                   4414:                icbflags |= UDF_ICB_TAG_FLAGS_SETGID;
                   4415:        if (mode & S_ISVTX)
                   4416:                icbflags |= UDF_ICB_TAG_FLAGS_STICKY;
1.1       reinoud  4417:
1.45      reinoud  4418:        if (fe) {
                   4419:                fe->perm  = udf_rw32(udf_perm);
                   4420:                fe->icbtag.flags  = udf_rw16(icbflags);
                   4421:        } else {
                   4422:                efe->perm = udf_rw32(udf_perm);
                   4423:                efe->icbtag.flags = udf_rw16(icbflags);
1.9       christos 4424:        }
1.1       reinoud  4425:
1.45      reinoud  4426:        UDF_UNLOCK_NODE(udf_node, 0);
1.1       reinoud  4427: }
                   4428:
                   4429:
1.45      reinoud  4430: void
                   4431: udf_getownership(struct udf_node *udf_node, uid_t *uidp, gid_t *gidp)
1.26      reinoud  4432: {
1.45      reinoud  4433:        struct udf_mount     *ump = udf_node->ump;
                   4434:        struct file_entry    *fe  = udf_node->fe;
                   4435:        struct extfile_entry *efe = udf_node->efe;
                   4436:        uid_t uid;
                   4437:        gid_t gid;
1.26      reinoud  4438:
1.45      reinoud  4439:        UDF_LOCK_NODE(udf_node, 0);
                   4440:        if (fe) {
                   4441:                uid = (uid_t)udf_rw32(fe->uid);
                   4442:                gid = (gid_t)udf_rw32(fe->gid);
                   4443:        } else {
                   4444:                assert(udf_node->efe);
                   4445:                uid = (uid_t)udf_rw32(efe->uid);
                   4446:                gid = (gid_t)udf_rw32(efe->gid);
                   4447:        }
1.152     skrll    4448:
1.45      reinoud  4449:        /* do the uid/gid translation game */
1.76      reinoud  4450:        if (uid == (uid_t) -1)
1.45      reinoud  4451:                uid = ump->mount_args.anon_uid;
1.76      reinoud  4452:        if (gid == (gid_t) -1)
1.45      reinoud  4453:                gid = ump->mount_args.anon_gid;
1.76      reinoud  4454:
1.45      reinoud  4455:        *uidp = uid;
                   4456:        *gidp = gid;
                   4457:
                   4458:        UDF_UNLOCK_NODE(udf_node, 0);
                   4459: }
1.26      reinoud  4460:
                   4461:
1.45      reinoud  4462: void
                   4463: udf_setownership(struct udf_node *udf_node, uid_t uid, gid_t gid)
                   4464: {
                   4465:        struct udf_mount     *ump = udf_node->ump;
                   4466:        struct file_entry    *fe  = udf_node->fe;
                   4467:        struct extfile_entry *efe = udf_node->efe;
                   4468:        uid_t nobody_uid;
                   4469:        gid_t nobody_gid;
                   4470:
                   4471:        UDF_LOCK_NODE(udf_node, 0);
                   4472:
                   4473:        /* do the uid/gid translation game */
                   4474:        nobody_uid = ump->mount_args.nobody_uid;
                   4475:        nobody_gid = ump->mount_args.nobody_gid;
1.76      reinoud  4476:        if (uid == nobody_uid)
1.45      reinoud  4477:                uid = (uid_t) -1;
1.76      reinoud  4478:        if (gid == nobody_gid)
1.45      reinoud  4479:                gid = (gid_t) -1;
1.26      reinoud  4480:
1.45      reinoud  4481:        if (fe) {
                   4482:                fe->uid  = udf_rw32((uint32_t) uid);
                   4483:                fe->gid  = udf_rw32((uint32_t) gid);
1.26      reinoud  4484:        } else {
1.45      reinoud  4485:                efe->uid = udf_rw32((uint32_t) uid);
                   4486:                efe->gid = udf_rw32((uint32_t) gid);
1.26      reinoud  4487:        }
1.45      reinoud  4488:
                   4489:        UDF_UNLOCK_NODE(udf_node, 0);
1.26      reinoud  4490: }
1.45      reinoud  4491:
1.26      reinoud  4492:
                   4493: /* --------------------------------------------------------------------- */
                   4494:
1.59      reinoud  4495:
1.120     reinoud  4496: int
                   4497: udf_dirhash_fill(struct udf_node *dir_node)
1.1       reinoud  4498: {
1.59      reinoud  4499:        struct vnode *dvp = dir_node->vnode;
1.73      reinoud  4500:        struct dirhash *dirh;
1.45      reinoud  4501:        struct file_entry    *fe  = dir_node->fe;
                   4502:        struct extfile_entry *efe = dir_node->efe;
                   4503:        struct fileid_desc *fid;
                   4504:        struct dirent *dirent;
1.59      reinoud  4505:        uint64_t file_size, pre_diroffset, diroffset;
1.45      reinoud  4506:        uint32_t lb_size;
1.59      reinoud  4507:        int error;
                   4508:
1.66      reinoud  4509:        /* make sure we have a dirhash to work on */
                   4510:        dirh = dir_node->dir_hash;
                   4511:        KASSERT(dirh);
                   4512:        KASSERT(dirh->refcnt > 0);
                   4513:
1.73      reinoud  4514:        if (dirh->flags & DIRH_BROKEN)
1.59      reinoud  4515:                return EIO;
1.73      reinoud  4516:        if (dirh->flags & DIRH_COMPLETE)
1.59      reinoud  4517:                return 0;
                   4518:
1.66      reinoud  4519:        /* make sure we have a clean dirhash to add to */
1.73      reinoud  4520:        dirhash_purge_entries(dirh);
1.45      reinoud  4521:
                   4522:        /* get directory filesize */
                   4523:        if (fe) {
                   4524:                file_size = udf_rw64(fe->inf_len);
                   4525:        } else {
                   4526:                assert(efe);
                   4527:                file_size = udf_rw64(efe->inf_len);
                   4528:        }
                   4529:
                   4530:        /* allocate temporary space for fid */
                   4531:        lb_size = udf_rw32(dir_node->ump->logical_vol->lb_size);
                   4532:        fid = malloc(lb_size, M_UDFTEMP, M_WAITOK);
1.1       reinoud  4533:
1.59      reinoud  4534:        /* allocate temporary space for dirent */
                   4535:        dirent = malloc(sizeof(struct dirent), M_UDFTEMP, M_WAITOK);
                   4536:
                   4537:        error = 0;
                   4538:        diroffset = 0;
                   4539:        while (diroffset < file_size) {
                   4540:                /* transfer a new fid/dirent */
                   4541:                pre_diroffset = diroffset;
                   4542:                error = udf_read_fid_stream(dvp, &diroffset, fid, dirent);
                   4543:                if (error) {
                   4544:                        /* TODO what to do? continue but not add? */
1.73      reinoud  4545:                        dirh->flags |= DIRH_BROKEN;
                   4546:                        dirhash_purge_entries(dirh);
1.59      reinoud  4547:                        break;
                   4548:                }
1.1       reinoud  4549:
1.59      reinoud  4550:                if ((fid->file_char & UDF_FILE_CHAR_DEL)) {
                   4551:                        /* register deleted extent for reuse */
1.73      reinoud  4552:                        dirhash_enter_freed(dirh, pre_diroffset,
1.59      reinoud  4553:                                udf_fidsize(fid));
                   4554:                } else {
                   4555:                        /* append to the dirhash */
1.73      reinoud  4556:                        dirhash_enter(dirh, dirent, pre_diroffset,
1.59      reinoud  4557:                                udf_fidsize(fid), 0);
                   4558:                }
1.9       christos 4559:        }
1.73      reinoud  4560:        dirh->flags |= DIRH_COMPLETE;
1.59      reinoud  4561:
                   4562:        free(fid, M_UDFTEMP);
                   4563:        free(dirent, M_UDFTEMP);
                   4564:
                   4565:        return error;
                   4566: }
                   4567:
                   4568:
                   4569: /* --------------------------------------------------------------------- */
                   4570:
                   4571: /*
                   4572:  * Directory read and manipulation functions.
                   4573:  *
                   4574:  */
                   4575:
1.152     skrll    4576: int
1.59      reinoud  4577: udf_lookup_name_in_dir(struct vnode *vp, const char *name, int namelen,
                   4578:        struct long_ad *icb_loc, int *found)
                   4579: {
                   4580:        struct udf_node  *dir_node = VTOI(vp);
1.73      reinoud  4581:        struct dirhash       *dirh;
                   4582:        struct dirhash_entry *dirh_ep;
1.59      reinoud  4583:        struct fileid_desc *fid;
1.136     reinoud  4584:        struct dirent *dirent, *s_dirent;
                   4585:        struct charspec osta_charspec;
1.59      reinoud  4586:        uint64_t diroffset;
                   4587:        uint32_t lb_size;
                   4588:        int hit, error;
                   4589:
                   4590:        /* set default return */
                   4591:        *found = 0;
                   4592:
1.66      reinoud  4593:        /* get our dirhash and make sure its read in */
1.73      reinoud  4594:        dirhash_get(&dir_node->dir_hash);
1.120     reinoud  4595:        error = udf_dirhash_fill(dir_node);
1.66      reinoud  4596:        if (error) {
1.73      reinoud  4597:                dirhash_put(dir_node->dir_hash);
1.59      reinoud  4598:                return error;
1.66      reinoud  4599:        }
1.73      reinoud  4600:        dirh = dir_node->dir_hash;
1.1       reinoud  4601:
1.59      reinoud  4602:        /* allocate temporary space for fid */
1.136     reinoud  4603:        lb_size  = udf_rw32(dir_node->ump->logical_vol->lb_size);
                   4604:        fid      = malloc(lb_size, M_UDFTEMP, M_WAITOK);
                   4605:        dirent   = malloc(sizeof(struct dirent), M_UDFTEMP, M_WAITOK);
                   4606:        s_dirent = malloc(sizeof(struct dirent), M_UDFTEMP, M_WAITOK);
1.59      reinoud  4607:
                   4608:        DPRINTF(DIRHASH, ("dirhash_lookup looking for `%*.*s`\n",
                   4609:                namelen, namelen, name));
1.1       reinoud  4610:
1.136     reinoud  4611:        /* convert given unix name to canonical unix name */
                   4612:        udf_osta_charset(&osta_charspec);
                   4613:        unix_to_udf_name((char *) fid->data, &fid->l_fi,
                   4614:                name, namelen, &osta_charspec);
                   4615:        udf_to_unix_name(s_dirent->d_name, NAME_MAX,
                   4616:                (char *) fid->data, fid->l_fi,
                   4617:                &osta_charspec);
                   4618:        s_dirent->d_namlen = strlen(s_dirent->d_name);
                   4619:
1.59      reinoud  4620:        /* search our dirhash hits */
                   4621:        memset(icb_loc, 0, sizeof(*icb_loc));
                   4622:        dirh_ep = NULL;
                   4623:        for (;;) {
1.136     reinoud  4624:                hit = dirhash_lookup(dirh, s_dirent->d_name, s_dirent->d_namlen, &dirh_ep);
1.59      reinoud  4625:                /* if no hit, abort the search */
                   4626:                if (!hit)
                   4627:                        break;
1.1       reinoud  4628:
1.59      reinoud  4629:                /* check this hit */
                   4630:                diroffset = dirh_ep->offset;
1.1       reinoud  4631:
1.45      reinoud  4632:                /* transfer a new fid/dirent */
                   4633:                error = udf_read_fid_stream(vp, &diroffset, fid, dirent);
1.1       reinoud  4634:                if (error)
                   4635:                        break;
                   4636:
1.59      reinoud  4637:                DPRINTF(DIRHASH, ("dirhash_lookup\tchecking `%*.*s`\n",
                   4638:                        dirent->d_namlen, dirent->d_namlen, dirent->d_name));
1.1       reinoud  4639:
1.59      reinoud  4640:                /* see if its our entry */
1.136     reinoud  4641:                if (strncmp(dirent->d_name, s_dirent->d_name, s_dirent->d_namlen) == 0) {
1.59      reinoud  4642:                        *found = 1;
                   4643:                        *icb_loc = fid->icb;
1.45      reinoud  4644:                        break;
1.9       christos 4645:                }
1.45      reinoud  4646:        }
                   4647:        free(fid, M_UDFTEMP);
                   4648:        free(dirent, M_UDFTEMP);
1.136     reinoud  4649:        free(s_dirent, M_UDFTEMP);
1.1       reinoud  4650:
1.73      reinoud  4651:        dirhash_put(dir_node->dir_hash);
1.66      reinoud  4652:
1.59      reinoud  4653:        return error;
1.45      reinoud  4654: }
1.1       reinoud  4655:
1.45      reinoud  4656: /* --------------------------------------------------------------------- */
1.1       reinoud  4657:
1.45      reinoud  4658: static int
                   4659: udf_create_new_fe(struct udf_mount *ump, struct file_entry *fe, int file_type,
                   4660:        struct long_ad *node_icb, struct long_ad *parent_icb,
                   4661:        uint64_t parent_unique_id)
                   4662: {
                   4663:        struct timespec now;
                   4664:        struct icb_tag *icb;
1.51      reinoud  4665:        struct filetimes_extattr_entry *ft_extattr;
1.45      reinoud  4666:        uint64_t unique_id;
                   4667:        uint32_t fidsize, lb_num;
1.51      reinoud  4668:        uint8_t *bpos;
                   4669:        int crclen, attrlen;
1.45      reinoud  4670:
                   4671:        lb_num = udf_rw32(node_icb->loc.lb_num);
                   4672:        udf_inittag(ump, &fe->tag, TAGID_FENTRY, lb_num);
                   4673:        icb = &fe->icbtag;
1.1       reinoud  4674:
                   4675:        /*
1.45      reinoud  4676:         * Always use strategy type 4 unless on WORM wich we don't support
                   4677:         * (yet). Fill in defaults and set for internal allocation of data.
1.1       reinoud  4678:         */
1.45      reinoud  4679:        icb->strat_type      = udf_rw16(4);
                   4680:        icb->max_num_entries = udf_rw16(1);
                   4681:        icb->file_type       = file_type;       /* 8 bit */
                   4682:        icb->flags           = udf_rw16(UDF_ICB_INTERN_ALLOC);
                   4683:
                   4684:        fe->perm     = udf_rw32(0x7fff);        /* all is allowed   */
                   4685:        fe->link_cnt = udf_rw16(0);             /* explicit setting */
1.1       reinoud  4686:
1.45      reinoud  4687:        fe->ckpoint  = udf_rw32(1);             /* user supplied file version */
                   4688:
                   4689:        vfs_timestamp(&now);
                   4690:        udf_timespec_to_timestamp(&now, &fe->atime);
                   4691:        udf_timespec_to_timestamp(&now, &fe->attrtime);
                   4692:        udf_timespec_to_timestamp(&now, &fe->mtime);
1.1       reinoud  4693:
1.45      reinoud  4694:        udf_set_regid(&fe->imp_id, IMPL_NAME);
                   4695:        udf_add_impl_regid(ump, &fe->imp_id);
1.1       reinoud  4696:
1.45      reinoud  4697:        unique_id = udf_advance_uniqueid(ump);
                   4698:        fe->unique_id = udf_rw64(unique_id);
1.51      reinoud  4699:        fe->l_ea = udf_rw32(0);
                   4700:
                   4701:        /* create extended attribute to record our creation time */
                   4702:        attrlen = UDF_FILETIMES_ATTR_SIZE(1);
                   4703:        ft_extattr = malloc(attrlen, M_UDFTEMP, M_WAITOK);
                   4704:        memset(ft_extattr, 0, attrlen);
                   4705:        ft_extattr->hdr.type = udf_rw32(UDF_FILETIMES_ATTR_NO);
                   4706:        ft_extattr->hdr.subtype = 1;    /* [4/48.10.5] */
                   4707:        ft_extattr->hdr.a_l = udf_rw32(UDF_FILETIMES_ATTR_SIZE(1));
                   4708:        ft_extattr->d_l     = udf_rw32(UDF_TIMESTAMP_SIZE); /* one item */
                   4709:        ft_extattr->existence = UDF_FILETIMES_FILE_CREATION;
                   4710:        udf_timespec_to_timestamp(&now, &ft_extattr->times[0]);
                   4711:
                   4712:        udf_extattr_insert_internal(ump, (union dscrptr *) fe,
                   4713:                (struct extattr_entry *) ft_extattr);
                   4714:        free(ft_extattr, M_UDFTEMP);
1.1       reinoud  4715:
1.51      reinoud  4716:        /* if its a directory, create '..' */
                   4717:        bpos = (uint8_t *) fe->data + udf_rw32(fe->l_ea);
1.45      reinoud  4718:        fidsize = 0;
                   4719:        if (file_type == UDF_ICB_FILETYPE_DIRECTORY) {
                   4720:                fidsize = udf_create_parentfid(ump,
1.51      reinoud  4721:                        (struct fileid_desc *) bpos, parent_icb,
1.45      reinoud  4722:                        parent_unique_id);
1.9       christos 4723:        }
1.1       reinoud  4724:
1.45      reinoud  4725:        /* record fidlength information */
                   4726:        fe->inf_len = udf_rw64(fidsize);
                   4727:        fe->l_ad    = udf_rw32(fidsize);
                   4728:        fe->logblks_rec = udf_rw64(0);          /* intern */
                   4729:
                   4730:        crclen  = sizeof(struct file_entry) - 1 - UDF_DESC_TAG_LENGTH;
1.51      reinoud  4731:        crclen += udf_rw32(fe->l_ea) + fidsize;
1.45      reinoud  4732:        fe->tag.desc_crc_len = udf_rw16(crclen);
1.1       reinoud  4733:
1.45      reinoud  4734:        (void) udf_validate_tag_and_crc_sums((union dscrptr *) fe);
1.1       reinoud  4735:
1.45      reinoud  4736:        return fidsize;
1.1       reinoud  4737: }
                   4738:
                   4739: /* --------------------------------------------------------------------- */
                   4740:
1.45      reinoud  4741: static int
                   4742: udf_create_new_efe(struct udf_mount *ump, struct extfile_entry *efe,
                   4743:        int file_type, struct long_ad *node_icb, struct long_ad *parent_icb,
                   4744:        uint64_t parent_unique_id)
                   4745: {
                   4746:        struct timespec now;
                   4747:        struct icb_tag *icb;
                   4748:        uint64_t unique_id;
                   4749:        uint32_t fidsize, lb_num;
1.51      reinoud  4750:        uint8_t *bpos;
1.45      reinoud  4751:        int crclen;
                   4752:
                   4753:        lb_num = udf_rw32(node_icb->loc.lb_num);
                   4754:        udf_inittag(ump, &efe->tag, TAGID_EXTFENTRY, lb_num);
                   4755:        icb = &efe->icbtag;
                   4756:
                   4757:        /*
                   4758:         * Always use strategy type 4 unless on WORM wich we don't support
                   4759:         * (yet). Fill in defaults and set for internal allocation of data.
                   4760:         */
                   4761:        icb->strat_type      = udf_rw16(4);
                   4762:        icb->max_num_entries = udf_rw16(1);
                   4763:        icb->file_type       = file_type;       /* 8 bit */
                   4764:        icb->flags           = udf_rw16(UDF_ICB_INTERN_ALLOC);
1.1       reinoud  4765:
1.45      reinoud  4766:        efe->perm     = udf_rw32(0x7fff);       /* all is allowed   */
                   4767:        efe->link_cnt = udf_rw16(0);            /* explicit setting */
1.1       reinoud  4768:
1.45      reinoud  4769:        efe->ckpoint  = udf_rw32(1);            /* user supplied file version */
1.1       reinoud  4770:
1.45      reinoud  4771:        vfs_timestamp(&now);
                   4772:        udf_timespec_to_timestamp(&now, &efe->ctime);
                   4773:        udf_timespec_to_timestamp(&now, &efe->atime);
                   4774:        udf_timespec_to_timestamp(&now, &efe->attrtime);
                   4775:        udf_timespec_to_timestamp(&now, &efe->mtime);
1.26      reinoud  4776:
1.45      reinoud  4777:        udf_set_regid(&efe->imp_id, IMPL_NAME);
                   4778:        udf_add_impl_regid(ump, &efe->imp_id);
1.1       reinoud  4779:
1.45      reinoud  4780:        unique_id = udf_advance_uniqueid(ump);
                   4781:        efe->unique_id = udf_rw64(unique_id);
1.51      reinoud  4782:        efe->l_ea = udf_rw32(0);
1.1       reinoud  4783:
1.51      reinoud  4784:        /* if its a directory, create '..' */
                   4785:        bpos = (uint8_t *) efe->data + udf_rw32(efe->l_ea);
1.45      reinoud  4786:        fidsize = 0;
                   4787:        if (file_type == UDF_ICB_FILETYPE_DIRECTORY) {
                   4788:                fidsize = udf_create_parentfid(ump,
1.51      reinoud  4789:                        (struct fileid_desc *) bpos, parent_icb,
1.45      reinoud  4790:                        parent_unique_id);
                   4791:        }
1.1       reinoud  4792:
1.45      reinoud  4793:        /* record fidlength information */
                   4794:        efe->obj_size = udf_rw64(fidsize);
                   4795:        efe->inf_len  = udf_rw64(fidsize);
                   4796:        efe->l_ad     = udf_rw32(fidsize);
                   4797:        efe->logblks_rec = udf_rw64(0);         /* intern */
1.1       reinoud  4798:
1.45      reinoud  4799:        crclen  = sizeof(struct extfile_entry) - 1 - UDF_DESC_TAG_LENGTH;
1.51      reinoud  4800:        crclen += udf_rw32(efe->l_ea) + fidsize;
1.45      reinoud  4801:        efe->tag.desc_crc_len = udf_rw16(crclen);
1.1       reinoud  4802:
1.45      reinoud  4803:        (void) udf_validate_tag_and_crc_sums((union dscrptr *) efe);
1.1       reinoud  4804:
1.45      reinoud  4805:        return fidsize;
1.1       reinoud  4806: }
                   4807:
                   4808: /* --------------------------------------------------------------------- */
                   4809:
1.45      reinoud  4810: int
                   4811: udf_dir_detach(struct udf_mount *ump, struct udf_node *dir_node,
                   4812:        struct udf_node *udf_node, struct componentname *cnp)
1.1       reinoud  4813: {
1.59      reinoud  4814:        struct vnode *dvp = dir_node->vnode;
1.73      reinoud  4815:        struct dirhash       *dirh;
                   4816:        struct dirhash_entry *dirh_ep;
1.45      reinoud  4817:        struct file_entry    *fe  = dir_node->fe;
                   4818:        struct fileid_desc *fid;
1.136     reinoud  4819:        struct dirent *dirent, *s_dirent;
                   4820:        struct charspec osta_charspec;
1.121     christos 4821:        uint64_t diroffset;
1.45      reinoud  4822:        uint32_t lb_size, fidsize;
                   4823:        int found, error;
1.59      reinoud  4824:        int hit, refcnt;
1.1       reinoud  4825:
1.66      reinoud  4826:        /* get our dirhash and make sure its read in */
1.73      reinoud  4827:        dirhash_get(&dir_node->dir_hash);
1.120     reinoud  4828:        error = udf_dirhash_fill(dir_node);
1.66      reinoud  4829:        if (error) {
1.73      reinoud  4830:                dirhash_put(dir_node->dir_hash);
1.66      reinoud  4831:                return error;
                   4832:        }
1.73      reinoud  4833:        dirh = dir_node->dir_hash;
1.66      reinoud  4834:
1.45      reinoud  4835:        /* get directory filesize */
1.121     christos 4836:        if (!fe) {
1.122     riz      4837:                assert(dir_node->efe);
1.45      reinoud  4838:        }
1.1       reinoud  4839:
1.136     reinoud  4840:        /* allocate temporary space for fid and dirents */
                   4841:        lb_size  = udf_rw32(dir_node->ump->logical_vol->lb_size);
                   4842:        fid      = malloc(lb_size, M_UDFTEMP, M_WAITOK);
                   4843:        dirent   = malloc(sizeof(struct dirent), M_UDFTEMP, M_WAITOK);
                   4844:        s_dirent = malloc(sizeof(struct dirent), M_UDFTEMP, M_WAITOK);
                   4845:
                   4846:        /* convert given unix name to canonical unix name */
                   4847:        udf_osta_charset(&osta_charspec);
                   4848:        unix_to_udf_name((char *) fid->data, &fid->l_fi,
                   4849:                cnp->cn_nameptr, cnp->cn_namelen, &osta_charspec);
                   4850:        udf_to_unix_name(s_dirent->d_name, NAME_MAX,
                   4851:                (char *) fid->data, fid->l_fi,
                   4852:                &osta_charspec);
                   4853:        s_dirent->d_namlen = strlen(s_dirent->d_name);
1.1       reinoud  4854:
1.59      reinoud  4855:        /* search our dirhash hits */
1.45      reinoud  4856:        found = 0;
1.59      reinoud  4857:        dirh_ep = NULL;
                   4858:        for (;;) {
1.136     reinoud  4859:                hit = dirhash_lookup(dirh, s_dirent->d_name, s_dirent->d_namlen, &dirh_ep);
1.59      reinoud  4860:                /* if no hit, abort the search */
                   4861:                if (!hit)
                   4862:                        break;
1.1       reinoud  4863:
1.59      reinoud  4864:                /* check this hit */
                   4865:                diroffset = dirh_ep->offset;
1.1       reinoud  4866:
1.45      reinoud  4867:                /* transfer a new fid/dirent */
1.59      reinoud  4868:                error = udf_read_fid_stream(dvp, &diroffset, fid, dirent);
1.45      reinoud  4869:                if (error)
                   4870:                        break;
1.1       reinoud  4871:
1.59      reinoud  4872:                /* see if its our entry */
1.136     reinoud  4873:                KASSERT(dirent->d_namlen == s_dirent->d_namlen);
                   4874:                if (strncmp(dirent->d_name, s_dirent->d_name, s_dirent->d_namlen) == 0) {
1.59      reinoud  4875:                        found = 1;
1.45      reinoud  4876:                        break;
                   4877:                }
                   4878:        }
1.59      reinoud  4879:
                   4880:        if (!found)
                   4881:                error = ENOENT;
                   4882:        if (error)
                   4883:                goto error_out;
1.1       reinoud  4884:
1.45      reinoud  4885:        /* mark deleted */
                   4886:        fid->file_char |= UDF_FILE_CHAR_DEL;
                   4887: #ifdef UDF_COMPLETE_DELETE
                   4888:        memset(&fid->icb, 0, sizeof(fid->icb));
                   4889: #endif
                   4890:        (void) udf_validate_tag_and_crc_sums((union dscrptr *) fid);
1.1       reinoud  4891:
1.59      reinoud  4892:        /* get size of fid and compensate for the read_fid_stream advance */
1.45      reinoud  4893:        fidsize = udf_fidsize(fid);
                   4894:        diroffset -= fidsize;
                   4895:
                   4896:        /* write out */
                   4897:        error = vn_rdwr(UIO_WRITE, dir_node->vnode,
1.152     skrll    4898:                        fid, fidsize, diroffset,
1.45      reinoud  4899:                        UIO_SYSSPACE, IO_ALTSEMANTICS | IO_NODELOCKED,
                   4900:                        FSCRED, NULL, NULL);
1.59      reinoud  4901:        if (error)
                   4902:                goto error_out;
                   4903:
                   4904:        /* get reference count of attached node */
                   4905:        if (udf_node->fe) {
                   4906:                refcnt = udf_rw16(udf_node->fe->link_cnt);
                   4907:        } else {
                   4908:                KASSERT(udf_node->efe);
                   4909:                refcnt = udf_rw16(udf_node->efe->link_cnt);
                   4910:        }
1.45      reinoud  4911: #ifdef UDF_COMPLETE_DELETE
1.59      reinoud  4912:        /* substract reference counter in attached node */
                   4913:        refcnt -= 1;
                   4914:        if (udf_node->fe) {
                   4915:                udf_node->fe->link_cnt = udf_rw16(refcnt);
                   4916:        } else {
                   4917:                udf_node->efe->link_cnt = udf_rw16(refcnt);
                   4918:        }
                   4919:
                   4920:        /* prevent writeout when refcnt == 0 */
                   4921:        if (refcnt == 0)
                   4922:                udf_node->i_flags |= IN_DELETED;
                   4923:
                   4924:        if (fid->file_char & UDF_FILE_CHAR_DIR) {
                   4925:                int drefcnt;
                   4926:
                   4927:                /* substract reference counter in directory node */
                   4928:                /* note subtract 2 (?) for its was also backreferenced */
                   4929:                if (dir_node->fe) {
                   4930:                        drefcnt  = udf_rw16(dir_node->fe->link_cnt);
                   4931:                        drefcnt -= 1;
                   4932:                        dir_node->fe->link_cnt = udf_rw16(drefcnt);
1.45      reinoud  4933:                } else {
1.59      reinoud  4934:                        KASSERT(dir_node->efe);
                   4935:                        drefcnt  = udf_rw16(dir_node->efe->link_cnt);
                   4936:                        drefcnt -= 1;
                   4937:                        dir_node->efe->link_cnt = udf_rw16(drefcnt);
1.45      reinoud  4938:                }
1.59      reinoud  4939:        }
1.1       reinoud  4940:
1.59      reinoud  4941:        udf_node->i_flags |= IN_MODIFIED;
                   4942:        dir_node->i_flags |= IN_MODIFIED;
1.45      reinoud  4943: #endif
1.59      reinoud  4944:        /* if it is/was a hardlink adjust the file count */
                   4945:        if (refcnt > 0)
                   4946:                udf_adjust_filecount(udf_node, -1);
                   4947:
                   4948:        /* remove from the dirhash */
1.73      reinoud  4949:        dirhash_remove(dirh, dirent, diroffset,
1.59      reinoud  4950:                udf_fidsize(fid));
1.1       reinoud  4951:
1.59      reinoud  4952: error_out:
1.45      reinoud  4953:        free(fid, M_UDFTEMP);
                   4954:        free(dirent, M_UDFTEMP);
1.136     reinoud  4955:        free(s_dirent, M_UDFTEMP);
1.1       reinoud  4956:
1.73      reinoud  4957:        dirhash_put(dir_node->dir_hash);
1.66      reinoud  4958:
1.45      reinoud  4959:        return error;
1.1       reinoud  4960: }
                   4961:
                   4962: /* --------------------------------------------------------------------- */
                   4963:
1.94      reinoud  4964: int
                   4965: udf_dir_update_rootentry(struct udf_mount *ump, struct udf_node *dir_node,
                   4966:        struct udf_node *new_parent_node)
                   4967: {
                   4968:        struct vnode *dvp = dir_node->vnode;
                   4969:        struct dirhash       *dirh;
                   4970:        struct dirhash_entry *dirh_ep;
                   4971:        struct file_entry    *fe;
                   4972:        struct extfile_entry *efe;
                   4973:        struct fileid_desc *fid;
                   4974:        struct dirent *dirent;
1.121     christos 4975:        uint64_t diroffset;
1.94      reinoud  4976:        uint64_t new_parent_unique_id;
                   4977:        uint32_t lb_size, fidsize;
                   4978:        int found, error;
                   4979:        char const *name  = "..";
                   4980:        int namelen = 2;
                   4981:        int hit;
                   4982:
                   4983:        /* get our dirhash and make sure its read in */
                   4984:        dirhash_get(&dir_node->dir_hash);
1.120     reinoud  4985:        error = udf_dirhash_fill(dir_node);
1.94      reinoud  4986:        if (error) {
                   4987:                dirhash_put(dir_node->dir_hash);
                   4988:                return error;
                   4989:        }
                   4990:        dirh = dir_node->dir_hash;
                   4991:
                   4992:        /* get new parent's unique ID */
                   4993:        fe  = new_parent_node->fe;
                   4994:        efe = new_parent_node->efe;
                   4995:        if (fe) {
                   4996:                new_parent_unique_id = udf_rw64(fe->unique_id);
                   4997:        } else {
                   4998:                assert(efe);
                   4999:                new_parent_unique_id = udf_rw64(efe->unique_id);
                   5000:        }
                   5001:
                   5002:        /* get directory filesize */
                   5003:        fe  = dir_node->fe;
                   5004:        efe = dir_node->efe;
1.121     christos 5005:        if (!fe) {
1.94      reinoud  5006:                assert(efe);
                   5007:        }
                   5008:
                   5009:        /* allocate temporary space for fid */
                   5010:        lb_size = udf_rw32(dir_node->ump->logical_vol->lb_size);
                   5011:        fid     = malloc(lb_size, M_UDFTEMP, M_WAITOK);
                   5012:        dirent  = malloc(sizeof(struct dirent), M_UDFTEMP, M_WAITOK);
                   5013:
                   5014:        /*
                   5015:         * NOTE the standard does not dictate the FID entry '..' should be
                   5016:         * first, though in practice it will most likely be.
                   5017:         */
                   5018:
                   5019:        /* search our dirhash hits */
                   5020:        found = 0;
                   5021:        dirh_ep = NULL;
                   5022:        for (;;) {
                   5023:                hit = dirhash_lookup(dirh, name, namelen, &dirh_ep);
                   5024:                /* if no hit, abort the search */
                   5025:                if (!hit)
                   5026:                        break;
                   5027:
                   5028:                /* check this hit */
                   5029:                diroffset = dirh_ep->offset;
                   5030:
                   5031:                /* transfer a new fid/dirent */
                   5032:                error = udf_read_fid_stream(dvp, &diroffset, fid, dirent);
                   5033:                if (error)
                   5034:                        break;
                   5035:
                   5036:                /* see if its our entry */
                   5037:                KASSERT(dirent->d_namlen == namelen);
                   5038:                if (strncmp(dirent->d_name, name, namelen) == 0) {
                   5039:                        found = 1;
                   5040:                        break;
                   5041:                }
                   5042:        }
                   5043:
                   5044:        if (!found)
                   5045:                error = ENOENT;
                   5046:        if (error)
                   5047:                goto error_out;
                   5048:
                   5049:        /* update our ICB to the new parent, hit of lower 32 bits of uniqueid */
                   5050:        fid->icb = new_parent_node->write_loc;
                   5051:        fid->icb.longad_uniqueid = udf_rw32(new_parent_unique_id);
                   5052:
                   5053:        (void) udf_validate_tag_and_crc_sums((union dscrptr *) fid);
                   5054:
                   5055:        /* get size of fid and compensate for the read_fid_stream advance */
                   5056:        fidsize = udf_fidsize(fid);
                   5057:        diroffset -= fidsize;
                   5058:
                   5059:        /* write out */
                   5060:        error = vn_rdwr(UIO_WRITE, dir_node->vnode,
1.152     skrll    5061:                        fid, fidsize, diroffset,
1.94      reinoud  5062:                        UIO_SYSSPACE, IO_ALTSEMANTICS | IO_NODELOCKED,
                   5063:                        FSCRED, NULL, NULL);
                   5064:
                   5065:        /* nothing to be done in the dirhash */
                   5066:
                   5067: error_out:
                   5068:        free(fid, M_UDFTEMP);
                   5069:        free(dirent, M_UDFTEMP);
                   5070:
                   5071:        dirhash_put(dir_node->dir_hash);
                   5072:
                   5073:        return error;
                   5074: }
                   5075:
                   5076: /* --------------------------------------------------------------------- */
                   5077:
1.45      reinoud  5078: /*
                   5079:  * We are not allowed to split the fid tag itself over an logical block so
                   5080:  * check the space remaining in the logical block.
                   5081:  *
                   5082:  * We try to select the smallest candidate for recycling or when none is
                   5083:  * found, append a new one at the end of the directory.
                   5084:  */
                   5085:
1.1       reinoud  5086: int
1.45      reinoud  5087: udf_dir_attach(struct udf_mount *ump, struct udf_node *dir_node,
                   5088:        struct udf_node *udf_node, struct vattr *vap, struct componentname *cnp)
1.1       reinoud  5089: {
1.45      reinoud  5090:        struct vnode *dvp = dir_node->vnode;
1.73      reinoud  5091:        struct dirhash       *dirh;
                   5092:        struct dirhash_entry *dirh_ep;
1.45      reinoud  5093:        struct fileid_desc   *fid;
                   5094:        struct icb_tag       *icbtag;
                   5095:        struct charspec osta_charspec;
                   5096:        struct dirent   dirent;
1.74      reinoud  5097:        uint64_t unique_id, dir_size;
1.45      reinoud  5098:        uint64_t fid_pos, end_fid_pos, chosen_fid_pos;
                   5099:        uint32_t chosen_size, chosen_size_diff;
                   5100:        int lb_size, lb_rest, fidsize, this_fidsize, size_diff;
1.59      reinoud  5101:        int file_char, refcnt, icbflags, addr_type, hit, error;
1.45      reinoud  5102:
1.66      reinoud  5103:        /* get our dirhash and make sure its read in */
1.73      reinoud  5104:        dirhash_get(&dir_node->dir_hash);
1.120     reinoud  5105:        error = udf_dirhash_fill(dir_node);
1.66      reinoud  5106:        if (error) {
1.73      reinoud  5107:                dirhash_put(dir_node->dir_hash);
1.66      reinoud  5108:                return error;
                   5109:        }
1.73      reinoud  5110:        dirh = dir_node->dir_hash;
1.66      reinoud  5111:
                   5112:        /* get info */
1.45      reinoud  5113:        lb_size = udf_rw32(ump->logical_vol->lb_size);
                   5114:        udf_osta_charset(&osta_charspec);
                   5115:
                   5116:        if (dir_node->fe) {
                   5117:                dir_size = udf_rw64(dir_node->fe->inf_len);
1.59      reinoud  5118:                icbtag   = &dir_node->fe->icbtag;
1.45      reinoud  5119:        } else {
                   5120:                dir_size = udf_rw64(dir_node->efe->inf_len);
1.59      reinoud  5121:                icbtag   = &dir_node->efe->icbtag;
1.45      reinoud  5122:        }
1.1       reinoud  5123:
1.45      reinoud  5124:        icbflags   = udf_rw16(icbtag->flags);
                   5125:        addr_type  = icbflags & UDF_ICB_TAG_FLAGS_ALLOC_MASK;
1.1       reinoud  5126:
1.45      reinoud  5127:        if (udf_node->fe) {
                   5128:                unique_id = udf_rw64(udf_node->fe->unique_id);
1.59      reinoud  5129:                refcnt    = udf_rw16(udf_node->fe->link_cnt);
1.45      reinoud  5130:        } else {
                   5131:                unique_id = udf_rw64(udf_node->efe->unique_id);
1.59      reinoud  5132:                refcnt    = udf_rw16(udf_node->efe->link_cnt);
1.45      reinoud  5133:        }
1.1       reinoud  5134:
1.45      reinoud  5135:        if (refcnt > 0) {
                   5136:                unique_id = udf_advance_uniqueid(ump);
                   5137:                udf_adjust_filecount(udf_node, 1);
1.9       christos 5138:        }
1.1       reinoud  5139:
1.45      reinoud  5140:        /* determine file characteristics */
                   5141:        file_char = 0;  /* visible non deleted file and not stream metadata */
                   5142:        if (vap->va_type == VDIR)
                   5143:                file_char = UDF_FILE_CHAR_DIR;
                   5144:
                   5145:        /* malloc scrap buffer */
1.83      cegger   5146:        fid = malloc(lb_size, M_TEMP, M_WAITOK|M_ZERO);
1.45      reinoud  5147:
                   5148:        /* calculate _minimum_ fid size */
                   5149:        unix_to_udf_name((char *) fid->data, &fid->l_fi,
                   5150:                cnp->cn_nameptr, cnp->cn_namelen, &osta_charspec);
                   5151:        fidsize = UDF_FID_SIZE + fid->l_fi;
                   5152:        fidsize = (fidsize + 3) & ~3;           /* multiple of 4 */
1.1       reinoud  5153:
1.45      reinoud  5154:        /* find position that will fit the FID */
1.59      reinoud  5155:        chosen_fid_pos   = dir_size;
1.45      reinoud  5156:        chosen_size      = 0;
                   5157:        chosen_size_diff = UINT_MAX;
1.1       reinoud  5158:
1.59      reinoud  5159:        /* shut up gcc */
                   5160:        dirent.d_namlen = 0;
                   5161:
                   5162:        /* search our dirhash hits */
                   5163:        error = 0;
                   5164:        dirh_ep = NULL;
1.45      reinoud  5165:        for (;;) {
1.73      reinoud  5166:                hit = dirhash_lookup_freed(dirh, fidsize, &dirh_ep);
1.59      reinoud  5167:                /* if no hit, abort the search */
                   5168:                if (!hit)
1.45      reinoud  5169:                        break;
1.1       reinoud  5170:
1.59      reinoud  5171:                /* check this hit for size */
1.73      reinoud  5172:                this_fidsize = dirh_ep->entry_size;
1.1       reinoud  5173:
1.59      reinoud  5174:                /* check this hit */
                   5175:                fid_pos     = dirh_ep->offset;
                   5176:                end_fid_pos = fid_pos + this_fidsize;
                   5177:                size_diff   = this_fidsize - fidsize;
                   5178:                lb_rest = lb_size - (end_fid_pos % lb_size);
1.45      reinoud  5179:
                   5180: #ifndef UDF_COMPLETE_DELETE
1.59      reinoud  5181:                /* transfer a new fid/dirent */
                   5182:                error = udf_read_fid_stream(vp, &fid_pos, fid, dirent);
                   5183:                if (error)
                   5184:                        goto error_out;
                   5185:
                   5186:                /* only reuse entries that are wiped */
                   5187:                /* check if the len + loc are marked zero */
1.88      reinoud  5188:                if (udf_rw32(fid->icb.len) != 0)
1.59      reinoud  5189:                        continue;
                   5190:                if (udf_rw32(fid->icb.loc.lb_num) != 0)
                   5191:                        continue;
1.88      reinoud  5192:                if (udf_rw16(fid->icb.loc.part_num) != 0)
1.59      reinoud  5193:                        continue;
                   5194: #endif /* UDF_COMPLETE_DELETE */
                   5195:
                   5196:                /* select if not splitting the tag and its smaller */
                   5197:                if ((size_diff >= 0)  &&
                   5198:                        (size_diff < chosen_size_diff) &&
                   5199:                        (lb_rest >= sizeof(struct desc_tag)))
                   5200:                {
                   5201:                        /* UDF 2.3.4.2+3 specifies rules for iu size */
                   5202:                        if ((size_diff == 0) || (size_diff >= 32)) {
                   5203:                                chosen_fid_pos   = fid_pos;
                   5204:                                chosen_size      = this_fidsize;
                   5205:                                chosen_size_diff = size_diff;
1.45      reinoud  5206:                        }
                   5207:                }
1.59      reinoud  5208:        }
1.1       reinoud  5209:
                   5210:
1.45      reinoud  5211:        /* extend directory if no other candidate found */
                   5212:        if (chosen_size == 0) {
                   5213:                chosen_fid_pos   = dir_size;
                   5214:                chosen_size      = fidsize;
                   5215:                chosen_size_diff = 0;
1.1       reinoud  5216:
1.45      reinoud  5217:                /* special case UDF 2.00+ 2.3.4.4, no splitting up fid tag */
                   5218:                if (addr_type == UDF_ICB_INTERN_ALLOC) {
                   5219:                        /* pre-grow directory to see if we're to switch */
                   5220:                        udf_grow_node(dir_node, dir_size + chosen_size);
1.1       reinoud  5221:
1.45      reinoud  5222:                        icbflags   = udf_rw16(icbtag->flags);
                   5223:                        addr_type  = icbflags & UDF_ICB_TAG_FLAGS_ALLOC_MASK;
                   5224:                }
1.1       reinoud  5225:
1.156     andvar   5226:                /* make sure the next fid desc_tag won't be split */
1.45      reinoud  5227:                if (addr_type != UDF_ICB_INTERN_ALLOC) {
                   5228:                        end_fid_pos = chosen_fid_pos + chosen_size;
                   5229:                        lb_rest = lb_size - (end_fid_pos % lb_size);
1.1       reinoud  5230:
1.45      reinoud  5231:                        /* pad with implementation use regid if needed */
                   5232:                        if (lb_rest < sizeof(struct desc_tag))
                   5233:                                chosen_size += 32;
                   5234:                }
1.1       reinoud  5235:        }
1.45      reinoud  5236:        chosen_size_diff = chosen_size - fidsize;
                   5237:
                   5238:        /* populate the FID */
                   5239:        memset(fid, 0, lb_size);
                   5240:        udf_inittag(ump, &fid->tag, TAGID_FID, 0);
                   5241:        fid->file_version_num    = udf_rw16(1); /* UDF 2.3.4.1 */
                   5242:        fid->file_char           = file_char;
                   5243:        fid->icb                 = udf_node->loc;
                   5244:        fid->icb.longad_uniqueid = udf_rw32((uint32_t) unique_id);
                   5245:        fid->l_iu                = udf_rw16(0);
                   5246:
                   5247:        if (chosen_size > fidsize) {
                   5248:                /* insert implementation-use regid to space it correctly */
                   5249:                fid->l_iu = udf_rw16(chosen_size_diff);
                   5250:
                   5251:                /* set implementation use */
                   5252:                udf_set_regid((struct regid *) fid->data, IMPL_NAME);
                   5253:                udf_add_impl_regid(ump, (struct regid *) fid->data);
                   5254:        }
                   5255:
                   5256:        /* fill in name */
                   5257:        unix_to_udf_name((char *) fid->data + udf_rw16(fid->l_iu),
                   5258:                &fid->l_fi, cnp->cn_nameptr, cnp->cn_namelen, &osta_charspec);
                   5259:
1.88      reinoud  5260:        fid->tag.desc_crc_len = udf_rw16(chosen_size - UDF_DESC_TAG_LENGTH);
1.45      reinoud  5261:        (void) udf_validate_tag_and_crc_sums((union dscrptr *) fid);
                   5262:
                   5263:        /* writeout FID/update parent directory */
                   5264:        error = vn_rdwr(UIO_WRITE, dvp,
1.152     skrll    5265:                        fid, chosen_size, chosen_fid_pos,
1.45      reinoud  5266:                        UIO_SYSSPACE, IO_ALTSEMANTICS | IO_NODELOCKED,
                   5267:                        FSCRED, NULL, NULL);
                   5268:
1.59      reinoud  5269:        if (error)
                   5270:                goto error_out;
1.45      reinoud  5271:
                   5272:        /* add reference counter in attached node */
                   5273:        if (udf_node->fe) {
                   5274:                refcnt = udf_rw16(udf_node->fe->link_cnt);
                   5275:                udf_node->fe->link_cnt = udf_rw16(refcnt+1);
                   5276:        } else {
                   5277:                KASSERT(udf_node->efe);
                   5278:                refcnt = udf_rw16(udf_node->efe->link_cnt);
                   5279:                udf_node->efe->link_cnt = udf_rw16(refcnt+1);
                   5280:        }
                   5281:
                   5282:        /* mark not deleted if it was... just in case, but do warn */
                   5283:        if (udf_node->i_flags & IN_DELETED) {
                   5284:                printf("udf: warning, marking a file undeleted\n");
                   5285:                udf_node->i_flags &= ~IN_DELETED;
                   5286:        }
                   5287:
                   5288:        if (file_char & UDF_FILE_CHAR_DIR) {
                   5289:                /* add reference counter in directory node for '..' */
                   5290:                if (dir_node->fe) {
                   5291:                        refcnt = udf_rw16(dir_node->fe->link_cnt);
                   5292:                        refcnt++;
                   5293:                        dir_node->fe->link_cnt = udf_rw16(refcnt);
                   5294:                } else {
                   5295:                        KASSERT(dir_node->efe);
                   5296:                        refcnt = udf_rw16(dir_node->efe->link_cnt);
                   5297:                        refcnt++;
                   5298:                        dir_node->efe->link_cnt = udf_rw16(refcnt);
                   5299:                }
1.1       reinoud  5300:        }
                   5301:
1.59      reinoud  5302:        /* append to the dirhash */
1.110     reinoud  5303:        /* NOTE do not use dirent anymore or it won't match later! */
1.117     christos 5304:        udf_to_unix_name(dirent.d_name, NAME_MAX,
1.110     reinoud  5305:                (char *) fid->data + udf_rw16(fid->l_iu), fid->l_fi, &osta_charspec);
                   5306:        dirent.d_namlen = strlen(dirent.d_name);
1.73      reinoud  5307:        dirhash_enter(dirh, &dirent, chosen_fid_pos,
1.59      reinoud  5308:                udf_fidsize(fid), 1);
1.45      reinoud  5309:
1.59      reinoud  5310:        /* note updates */
1.45      reinoud  5311:        udf_node->i_flags |= IN_CHANGE | IN_MODIFY; /* | IN_CREATE? */
                   5312:        /* VN_KNOTE(udf_node,  ...) */
1.50      reinoud  5313:        udf_update(udf_node->vnode, NULL, NULL, NULL, 0);
1.45      reinoud  5314:
1.59      reinoud  5315: error_out:
1.45      reinoud  5316:        free(fid, M_TEMP);
1.1       reinoud  5317:
1.73      reinoud  5318:        dirhash_put(dir_node->dir_hash);
1.66      reinoud  5319:
1.59      reinoud  5320:        return error;
1.45      reinoud  5321: }
1.1       reinoud  5322:
                   5323: /* --------------------------------------------------------------------- */
                   5324:
                   5325: /*
1.45      reinoud  5326:  * Each node can have an attached streamdir node though not recursively. These
                   5327:  * are otherwise known as named substreams/named extended attributes that have
                   5328:  * no size limitations.
1.1       reinoud  5329:  *
                   5330:  * `Normal' extended attributes are indicated with a number and are recorded
                   5331:  * in either the fe/efe descriptor itself for small descriptors or recorded in
1.45      reinoud  5332:  * the attached extended attribute file. Since these spaces can get
                   5333:  * fragmented, care ought to be taken.
                   5334:  *
                   5335:  * Since the size of the space reserved for allocation descriptors is limited,
                   5336:  * there is a mechanim provided for extending this space; this is done by a
                   5337:  * special extent to allow schrinking of the allocations without breaking the
                   5338:  * linkage to the allocation extent descriptor.
1.1       reinoud  5339:  */
                   5340:
                   5341: int
1.129     hannken  5342: udf_loadvnode(struct mount *mp, struct vnode *vp,
                   5343:      const void *key, size_t key_len, const void **new_key)
1.1       reinoud  5344: {
1.45      reinoud  5345:        union dscrptr   *dscr;
1.129     hannken  5346:        struct udf_mount *ump;
1.45      reinoud  5347:        struct udf_node *udf_node;
1.129     hannken  5348:        struct long_ad node_icb_loc, icb_loc, next_icb_loc, last_fe_icb_loc;
1.1       reinoud  5349:        uint64_t file_size;
                   5350:        uint32_t lb_size, sector, dummy;
                   5351:        int udf_file_type, dscr_type, strat, strat4096, needs_indirect;
1.45      reinoud  5352:        int slot, eof, error;
1.126     reinoud  5353:        int num_indir_followed = 0;
1.1       reinoud  5354:
1.129     hannken  5355:        DPRINTF(NODE, ("udf_loadvnode called\n"));
                   5356:        udf_node = NULL;
                   5357:        ump = VFSTOUDF(mp);
                   5358:
                   5359:        KASSERT(key_len == sizeof(node_icb_loc.loc));
                   5360:        memset(&node_icb_loc, 0, sizeof(node_icb_loc));
                   5361:        node_icb_loc.len = ump->logical_vol->lb_size;
                   5362:        memcpy(&node_icb_loc.loc, key, key_len);
1.1       reinoud  5363:
1.45      reinoud  5364:        /* garbage check: translate udf_node_icb_loc to sectornr */
1.129     hannken  5365:        error = udf_translate_vtop(ump, &node_icb_loc, &sector, &dummy);
1.1       reinoud  5366:        if (error) {
1.111     reinoud  5367:                DPRINTF(NODE, ("\tcan't translate icb address!\n"));
1.1       reinoud  5368:                /* no use, this will fail anyway */
                   5369:                return EINVAL;
1.9       christos 5370:        }
1.1       reinoud  5371:
1.45      reinoud  5372:        /* build udf_node (do initialise!) */
                   5373:        udf_node = pool_get(&udf_node_pool, PR_WAITOK);
                   5374:        memset(udf_node, 0, sizeof(struct udf_node));
1.1       reinoud  5375:
1.129     hannken  5376:        vp->v_tag = VT_UDF;
                   5377:        vp->v_op = udf_vnodeop_p;
                   5378:        vp->v_data = udf_node;
1.1       reinoud  5379:
                   5380:        /* initialise crosslinks, note location of fe/efe for hashing */
1.45      reinoud  5381:        udf_node->ump    =  ump;
1.129     hannken  5382:        udf_node->vnode  =  vp;
                   5383:        udf_node->loc    =  node_icb_loc;
1.45      reinoud  5384:        udf_node->lockf  =  0;
                   5385:        mutex_init(&udf_node->node_mutex, MUTEX_DEFAULT, IPL_NONE);
                   5386:        cv_init(&udf_node->node_lock, "udf_nlk");
1.129     hannken  5387:        genfs_node_init(vp, &udf_genfsops);     /* inititise genfs */
1.45      reinoud  5388:        udf_node->outstanding_bufs = 0;
                   5389:        udf_node->outstanding_nodedscr = 0;
1.95      reinoud  5390:        udf_node->uncommitted_lbs = 0;
1.1       reinoud  5391:
1.81      reinoud  5392:        /* check if we're fetching the root */
                   5393:        if (ump->fileset_desc)
                   5394:                if (memcmp(&udf_node->loc, &ump->fileset_desc->rootdir_icb,
                   5395:                    sizeof(struct long_ad)) == 0)
1.129     hannken  5396:                        vp->v_vflag |= VV_ROOT;
1.79      reinoud  5397:
1.129     hannken  5398:        icb_loc = node_icb_loc;
1.1       reinoud  5399:        needs_indirect = 0;
                   5400:        strat4096 = 0;
                   5401:        udf_file_type = UDF_ICB_FILETYPE_UNKNOWN;
                   5402:        file_size = 0;
                   5403:        lb_size = udf_rw32(ump->logical_vol->lb_size);
                   5404:
1.45      reinoud  5405:        DPRINTF(NODE, ("\tstart reading descriptors\n"));
1.1       reinoud  5406:        do {
                   5407:                /* try to read in fe/efe */
1.45      reinoud  5408:                error = udf_read_logvol_dscr(ump, &icb_loc, &dscr);
1.1       reinoud  5409:
                   5410:                /* blank sector marks end of sequence, check this */
1.45      reinoud  5411:                if ((dscr == NULL) &&  (!strat4096))
1.1       reinoud  5412:                        error = ENOENT;
                   5413:
                   5414:                /* break if read error or blank sector */
1.45      reinoud  5415:                if (error || (dscr == NULL))
1.1       reinoud  5416:                        break;
                   5417:
                   5418:                /* process descriptor based on the descriptor type */
1.45      reinoud  5419:                dscr_type = udf_rw16(dscr->tag.id);
                   5420:                DPRINTF(NODE, ("\tread descriptor %d\n", dscr_type));
1.1       reinoud  5421:
                   5422:                /* if dealing with an indirect entry, follow the link */
1.45      reinoud  5423:                if (dscr_type == TAGID_INDIRECTENTRY) {
1.1       reinoud  5424:                        needs_indirect = 0;
1.127     reinoud  5425:                        next_icb_loc = dscr->inde.indirect_icb;
1.45      reinoud  5426:                        udf_free_logvol_dscr(ump, &icb_loc, dscr);
1.127     reinoud  5427:                        icb_loc = next_icb_loc;
1.126     reinoud  5428:                        if (++num_indir_followed > UDF_MAX_INDIRS_FOLLOW) {
                   5429:                                error = EMLINK;
                   5430:                                break;
                   5431:                        }
1.1       reinoud  5432:                        continue;
1.9       christos 5433:                }
1.1       reinoud  5434:
                   5435:                /* only file entries and extended file entries allowed here */
                   5436:                if ((dscr_type != TAGID_FENTRY) &&
                   5437:                    (dscr_type != TAGID_EXTFENTRY)) {
1.45      reinoud  5438:                        udf_free_logvol_dscr(ump, &icb_loc, dscr);
1.1       reinoud  5439:                        error = ENOENT;
                   5440:                        break;
1.9       christos 5441:                }
1.1       reinoud  5442:
1.45      reinoud  5443:                KASSERT(udf_tagsize(dscr, lb_size) == lb_size);
1.1       reinoud  5444:
1.45      reinoud  5445:                /* choose this one */
                   5446:                last_fe_icb_loc = icb_loc;
1.152     skrll    5447:
1.1       reinoud  5448:                /* record and process/update (ext)fentry */
                   5449:                if (dscr_type == TAGID_FENTRY) {
1.45      reinoud  5450:                        if (udf_node->fe)
                   5451:                                udf_free_logvol_dscr(ump, &last_fe_icb_loc,
                   5452:                                        udf_node->fe);
                   5453:                        udf_node->fe  = &dscr->fe;
                   5454:                        strat = udf_rw16(udf_node->fe->icbtag.strat_type);
                   5455:                        udf_file_type = udf_node->fe->icbtag.file_type;
                   5456:                        file_size = udf_rw64(udf_node->fe->inf_len);
1.1       reinoud  5457:                } else {
1.45      reinoud  5458:                        if (udf_node->efe)
                   5459:                                udf_free_logvol_dscr(ump, &last_fe_icb_loc,
                   5460:                                        udf_node->efe);
                   5461:                        udf_node->efe = &dscr->efe;
                   5462:                        strat = udf_rw16(udf_node->efe->icbtag.strat_type);
                   5463:                        udf_file_type = udf_node->efe->icbtag.file_type;
                   5464:                        file_size = udf_rw64(udf_node->efe->inf_len);
1.9       christos 5465:                }
1.1       reinoud  5466:
                   5467:                /* check recording strategy (structure) */
                   5468:
                   5469:                /*
                   5470:                 * Strategy 4096 is a daisy linked chain terminating with an
                   5471:                 * unrecorded sector or a TERM descriptor. The next
                   5472:                 * descriptor is to be found in the sector that follows the
                   5473:                 * current sector.
                   5474:                 */
                   5475:                if (strat == 4096) {
                   5476:                        strat4096 = 1;
                   5477:                        needs_indirect = 1;
                   5478:
                   5479:                        icb_loc.loc.lb_num = udf_rw32(icb_loc.loc.lb_num) + 1;
1.9       christos 5480:                }
1.1       reinoud  5481:
                   5482:                /*
                   5483:                 * Strategy 4 is the normal strategy and terminates, but if
                   5484:                 * we're in strategy 4096, we can't have strategy 4 mixed in
                   5485:                 */
                   5486:
                   5487:                if (strat == 4) {
                   5488:                        if (strat4096) {
                   5489:                                error = EINVAL;
                   5490:                                break;
1.9       christos 5491:                        }
1.1       reinoud  5492:                        break;          /* done */
1.9       christos 5493:                }
1.1       reinoud  5494:        } while (!error);
                   5495:
1.45      reinoud  5496:        /* first round of cleanup code */
1.1       reinoud  5497:        if (error) {
1.45      reinoud  5498:                DPRINTF(NODE, ("\tnode fe/efe failed!\n"));
1.1       reinoud  5499:                /* recycle udf_node */
1.45      reinoud  5500:                udf_dispose_node(udf_node);
1.1       reinoud  5501:
                   5502:                return EINVAL;          /* error code ok? */
1.9       christos 5503:        }
1.45      reinoud  5504:        DPRINTF(NODE, ("\tnode fe/efe read in fine\n"));
1.1       reinoud  5505:
                   5506:        /* assert no references to dscr anymore beyong this point */
1.45      reinoud  5507:        assert((udf_node->fe) || (udf_node->efe));
1.1       reinoud  5508:        dscr = NULL;
                   5509:
                   5510:        /*
1.45      reinoud  5511:         * Remember where to record an updated version of the descriptor. If
1.1       reinoud  5512:         * there is a sequence of indirect entries, icb_loc will have been
                   5513:         * updated. Its the write disipline to allocate new space and to make
                   5514:         * sure the chain is maintained.
                   5515:         *
                   5516:         * `needs_indirect' flags if the next location is to be filled with
1.164     andvar   5517:         * an indirect entry.
1.1       reinoud  5518:         */
1.45      reinoud  5519:        udf_node->write_loc = icb_loc;
                   5520:        udf_node->needs_indirect = needs_indirect;
                   5521:
                   5522:        /*
                   5523:         * Go trough all allocations extents of this descriptor and when
                   5524:         * encountering a redirect read in the allocation extension. These are
                   5525:         * daisy-chained.
                   5526:         */
                   5527:        UDF_LOCK_NODE(udf_node, 0);
                   5528:        udf_node->num_extensions = 0;
                   5529:
                   5530:        error   = 0;
                   5531:        slot    = 0;
                   5532:        for (;;) {
                   5533:                udf_get_adslot(udf_node, slot, &icb_loc, &eof);
1.52      reinoud  5534:                DPRINTF(ADWLK, ("slot %d, eof = %d, flags = %d, len = %d, "
                   5535:                        "lb_num = %d, part = %d\n", slot, eof,
                   5536:                        UDF_EXT_FLAGS(udf_rw32(icb_loc.len)),
                   5537:                        UDF_EXT_LEN(udf_rw32(icb_loc.len)),
                   5538:                        udf_rw32(icb_loc.loc.lb_num),
                   5539:                        udf_rw16(icb_loc.loc.part_num)));
1.45      reinoud  5540:                if (eof)
                   5541:                        break;
1.52      reinoud  5542:                slot++;
1.45      reinoud  5543:
1.52      reinoud  5544:                if (UDF_EXT_FLAGS(udf_rw32(icb_loc.len)) != UDF_EXT_REDIRECT)
1.45      reinoud  5545:                        continue;
                   5546:
                   5547:                DPRINTF(NODE, ("\tgot redirect extent\n"));
                   5548:                if (udf_node->num_extensions >= UDF_MAX_ALLOC_EXTENTS) {
                   5549:                        DPRINTF(ALLOC, ("udf_get_node: implementation limit, "
                   5550:                                        "too many allocation extensions on "
                   5551:                                        "udf_node\n"));
                   5552:                        error = EINVAL;
                   5553:                        break;
                   5554:                }
                   5555:
                   5556:                /* length can only be *one* lb : UDF 2.50/2.3.7.1 */
1.52      reinoud  5557:                if (UDF_EXT_LEN(udf_rw32(icb_loc.len)) != lb_size) {
1.45      reinoud  5558:                        DPRINTF(ALLOC, ("udf_get_node: bad allocation "
                   5559:                                        "extension size in udf_node\n"));
                   5560:                        error = EINVAL;
                   5561:                        break;
                   5562:                }
                   5563:
1.52      reinoud  5564:                DPRINTF(NODE, ("read allocation extent at lb_num %d\n",
                   5565:                        UDF_EXT_LEN(udf_rw32(icb_loc.loc.lb_num))));
1.45      reinoud  5566:                /* load in allocation extent */
                   5567:                error = udf_read_logvol_dscr(ump, &icb_loc, &dscr);
                   5568:                if (error || (dscr == NULL))
                   5569:                        break;
                   5570:
                   5571:                /* process read-in descriptor */
                   5572:                dscr_type = udf_rw16(dscr->tag.id);
                   5573:
                   5574:                if (dscr_type != TAGID_ALLOCEXTENT) {
                   5575:                        udf_free_logvol_dscr(ump, &icb_loc, dscr);
                   5576:                        error = ENOENT;
                   5577:                        break;
                   5578:                }
                   5579:
                   5580:                DPRINTF(NODE, ("\trecording redirect extent\n"));
                   5581:                udf_node->ext[udf_node->num_extensions] = &dscr->aee;
                   5582:                udf_node->ext_loc[udf_node->num_extensions] = icb_loc;
                   5583:
                   5584:                udf_node->num_extensions++;
                   5585:
                   5586:        } /* while */
                   5587:        UDF_UNLOCK_NODE(udf_node, 0);
                   5588:
                   5589:        /* second round of cleanup code */
                   5590:        if (error) {
                   5591:                /* recycle udf_node */
                   5592:                udf_dispose_node(udf_node);
                   5593:
                   5594:                return EINVAL;          /* error code ok? */
                   5595:        }
                   5596:
                   5597:        DPRINTF(NODE, ("\tnode read in fine\n"));
1.1       reinoud  5598:
                   5599:        /*
                   5600:         * Translate UDF filetypes into vnode types.
                   5601:         *
                   5602:         * Systemfiles like the meta main and mirror files are not treated as
                   5603:         * normal files, so we type them as having no type. UDF dictates that
                   5604:         * they are not allowed to be visible.
                   5605:         */
                   5606:
1.45      reinoud  5607:        switch (udf_file_type) {
                   5608:        case UDF_ICB_FILETYPE_DIRECTORY :
                   5609:        case UDF_ICB_FILETYPE_STREAMDIR :
1.129     hannken  5610:                vp->v_type = VDIR;
1.45      reinoud  5611:                break;
                   5612:        case UDF_ICB_FILETYPE_BLOCKDEVICE :
1.129     hannken  5613:                vp->v_type = VBLK;
1.45      reinoud  5614:                break;
                   5615:        case UDF_ICB_FILETYPE_CHARDEVICE :
1.129     hannken  5616:                vp->v_type = VCHR;
1.45      reinoud  5617:                break;
                   5618:        case UDF_ICB_FILETYPE_SOCKET :
1.129     hannken  5619:                vp->v_type = VSOCK;
1.45      reinoud  5620:                break;
                   5621:        case UDF_ICB_FILETYPE_FIFO :
1.129     hannken  5622:                vp->v_type = VFIFO;
1.45      reinoud  5623:                break;
                   5624:        case UDF_ICB_FILETYPE_SYMLINK :
1.129     hannken  5625:                vp->v_type = VLNK;
1.45      reinoud  5626:                break;
                   5627:        case UDF_ICB_FILETYPE_VAT :
                   5628:        case UDF_ICB_FILETYPE_META_MAIN :
                   5629:        case UDF_ICB_FILETYPE_META_MIRROR :
1.129     hannken  5630:                vp->v_type = VNON;
1.45      reinoud  5631:                break;
                   5632:        case UDF_ICB_FILETYPE_RANDOMACCESS :
                   5633:        case UDF_ICB_FILETYPE_REALTIME :
1.129     hannken  5634:                vp->v_type = VREG;
1.45      reinoud  5635:                break;
                   5636:        default:
                   5637:                /* YIKES, something else */
1.129     hannken  5638:                vp->v_type = VNON;
1.45      reinoud  5639:        }
                   5640:
1.1       reinoud  5641:        /* TODO specfs, fifofs etc etc. vnops setting */
1.45      reinoud  5642:
                   5643:        /* don't forget to set vnode's v_size */
1.129     hannken  5644:        uvm_vnp_setsize(vp, file_size);
1.45      reinoud  5645:
                   5646:        /* TODO ext attr and streamdir udf_nodes */
                   5647:
1.129     hannken  5648:        *new_key = &udf_node->loc.loc;
1.45      reinoud  5649:
                   5650:        return 0;
                   5651: }
                   5652:
1.129     hannken  5653: int
                   5654: udf_get_node(struct udf_mount *ump, struct long_ad *node_icb_loc,
1.148     ad       5655:             struct udf_node **udf_noderes, int lktype)
1.129     hannken  5656: {
                   5657:        int error;
                   5658:        struct vnode *vp;
                   5659:
1.137     reinoud  5660:        *udf_noderes = NULL;
                   5661:
1.129     hannken  5662:        error = vcache_get(ump->vfs_mountp, &node_icb_loc->loc,
                   5663:            sizeof(node_icb_loc->loc), &vp);
                   5664:        if (error)
                   5665:                return error;
1.150     hannken  5666:        error = vn_lock(vp, lktype);
1.129     hannken  5667:        if (error) {
                   5668:                vrele(vp);
                   5669:                return error;
                   5670:        }
                   5671:        *udf_noderes = VTOI(vp);
                   5672:        return 0;
                   5673: }
                   5674:
1.45      reinoud  5675: /* --------------------------------------------------------------------- */
                   5676:
                   5677: int
                   5678: udf_writeout_node(struct udf_node *udf_node, int waitfor)
                   5679: {
                   5680:        union dscrptr *dscr;
                   5681:        struct long_ad *loc;
1.91      reinoud  5682:        int extnr, error;
1.45      reinoud  5683:
                   5684:        DPRINTF(NODE, ("udf_writeout_node called\n"));
                   5685:
                   5686:        KASSERT(udf_node->outstanding_bufs == 0);
                   5687:        KASSERT(udf_node->outstanding_nodedscr == 0);
                   5688:
                   5689:        KASSERT(LIST_EMPTY(&udf_node->vnode->v_dirtyblkhd));
                   5690:
                   5691:        if (udf_node->i_flags & IN_DELETED) {
                   5692:                DPRINTF(NODE, ("\tnode deleted; not writing out\n"));
1.95      reinoud  5693:                udf_cleanup_reservation(udf_node);
1.45      reinoud  5694:                return 0;
                   5695:        }
                   5696:
1.93      reinoud  5697:        /* lock node; unlocked in callback */
1.91      reinoud  5698:        UDF_LOCK_NODE(udf_node, 0);
1.55      reinoud  5699:
1.95      reinoud  5700:        /* remove pending reservations, we're written out */
                   5701:        udf_cleanup_reservation(udf_node);
                   5702:
1.55      reinoud  5703:        /* at least one descriptor writeout */
                   5704:        udf_node->outstanding_nodedscr = 1;
                   5705:
1.45      reinoud  5706:        /* we're going to write out the descriptor so clear the flags */
                   5707:        udf_node->i_flags &= ~(IN_MODIFIED | IN_ACCESSED);
                   5708:
1.55      reinoud  5709:        /* if we were rebuild, write out the allocation extents */
                   5710:        if (udf_node->i_flags & IN_NODE_REBUILD) {
1.71      reinoud  5711:                /* mark outstanding node descriptors and issue them */
1.55      reinoud  5712:                udf_node->outstanding_nodedscr += udf_node->num_extensions;
                   5713:                for (extnr = 0; extnr < udf_node->num_extensions; extnr++) {
                   5714:                        loc = &udf_node->ext_loc[extnr];
                   5715:                        dscr = (union dscrptr *) udf_node->ext[extnr];
                   5716:                        error = udf_write_logvol_dscr(udf_node, dscr, loc, 0);
                   5717:                        if (error)
                   5718:                                return error;
                   5719:                }
                   5720:                /* mark allocation extents written out */
                   5721:                udf_node->i_flags &= ~(IN_NODE_REBUILD);
                   5722:        }
                   5723:
1.45      reinoud  5724:        if (udf_node->fe) {
1.71      reinoud  5725:                KASSERT(udf_node->efe == NULL);
1.45      reinoud  5726:                dscr = (union dscrptr *) udf_node->fe;
                   5727:        } else {
                   5728:                KASSERT(udf_node->efe);
1.71      reinoud  5729:                KASSERT(udf_node->fe == NULL);
1.45      reinoud  5730:                dscr = (union dscrptr *) udf_node->efe;
                   5731:        }
                   5732:        KASSERT(dscr);
                   5733:
                   5734:        loc = &udf_node->write_loc;
                   5735:        error = udf_write_logvol_dscr(udf_node, dscr, loc, waitfor);
1.95      reinoud  5736:
1.45      reinoud  5737:        return error;
                   5738: }
                   5739:
                   5740: /* --------------------------------------------------------------------- */
                   5741:
                   5742: int
                   5743: udf_dispose_node(struct udf_node *udf_node)
                   5744: {
                   5745:        struct vnode *vp;
1.52      reinoud  5746:        int extnr;
1.45      reinoud  5747:
                   5748:        DPRINTF(NODE, ("udf_dispose_node called on node %p\n", udf_node));
                   5749:        if (!udf_node) {
                   5750:                DPRINTF(NODE, ("UDF: Dispose node on node NULL, ignoring\n"));
                   5751:                return 0;
                   5752:        }
                   5753:
                   5754:        vp  = udf_node->vnode;
                   5755: #ifdef DIAGNOSTIC
                   5756:        if (vp->v_numoutput)
                   5757:                panic("disposing UDF node with pending I/O's, udf_node = %p, "
                   5758:                                "v_numoutput = %d", udf_node, vp->v_numoutput);
                   5759: #endif
                   5760:
1.95      reinoud  5761:        udf_cleanup_reservation(udf_node);
1.45      reinoud  5762:
                   5763:        /* TODO extended attributes and streamdir */
                   5764:
1.59      reinoud  5765:        /* remove dirhash if present */
1.73      reinoud  5766:        dirhash_purge(&udf_node->dir_hash);
1.59      reinoud  5767:
1.45      reinoud  5768:        /* destroy our lock */
                   5769:        mutex_destroy(&udf_node->node_mutex);
                   5770:        cv_destroy(&udf_node->node_lock);
                   5771:
                   5772:        /* dissociate our udf_node from the vnode */
                   5773:        genfs_node_destroy(udf_node->vnode);
1.132     hannken  5774:        mutex_enter(vp->v_interlock);
1.45      reinoud  5775:        vp->v_data = NULL;
1.132     hannken  5776:        mutex_exit(vp->v_interlock);
1.45      reinoud  5777:
                   5778:        /* free associated memory and the node itself */
1.52      reinoud  5779:        for (extnr = 0; extnr < udf_node->num_extensions; extnr++) {
                   5780:                udf_free_logvol_dscr(udf_node->ump, &udf_node->ext_loc[extnr],
                   5781:                        udf_node->ext[extnr]);
                   5782:                udf_node->ext[extnr] = (void *) 0xdeadcccc;
                   5783:        }
                   5784:
1.45      reinoud  5785:        if (udf_node->fe)
1.52      reinoud  5786:                udf_free_logvol_dscr(udf_node->ump, &udf_node->loc,
                   5787:                        udf_node->fe);
1.45      reinoud  5788:        if (udf_node->efe)
1.52      reinoud  5789:                udf_free_logvol_dscr(udf_node->ump, &udf_node->loc,
                   5790:                        udf_node->efe);
1.45      reinoud  5791:
                   5792:        udf_node->fe  = (void *) 0xdeadaaaa;
                   5793:        udf_node->efe = (void *) 0xdeadbbbb;
                   5794:        udf_node->ump = (void *) 0xdeadbeef;
                   5795:        pool_put(&udf_node_pool, udf_node);
                   5796:
                   5797:        return 0;
                   5798: }
                   5799:
                   5800:
                   5801:
                   5802: /*
1.129     hannken  5803:  * create a new node using the specified dvp, vap and cnp.
                   5804:  * This allows special files to be created. Use with care.
1.45      reinoud  5805:  */
                   5806:
1.129     hannken  5807: int
                   5808: udf_newvnode(struct mount *mp, struct vnode *dvp, struct vnode *vp,
1.145     hannken  5809:     struct vattr *vap, kauth_cred_t cred, void *extra,
1.129     hannken  5810:     size_t *key_len, const void **new_key)
1.45      reinoud  5811: {
                   5812:        union dscrptr *dscr;
1.101     mbalmer  5813:        struct udf_node *dir_node = VTOI(dvp);
1.45      reinoud  5814:        struct udf_node *udf_node;
                   5815:        struct udf_mount *ump = dir_node->ump;
                   5816:        struct long_ad node_icb_loc;
                   5817:        uint64_t parent_unique_id;
1.70      reinoud  5818:        uint64_t lmapping;
1.45      reinoud  5819:        uint32_t lb_size, lb_num;
                   5820:        uint16_t vpart_num;
1.56      reinoud  5821:        uid_t uid;
                   5822:        gid_t gid, parent_gid;
1.129     hannken  5823:        int (**vnodeops)(void *);
                   5824:        int udf_file_type, fid_size, error;
                   5825:
                   5826:        vnodeops = udf_vnodeop_p;
                   5827:        udf_file_type = UDF_ICB_FILETYPE_RANDOMACCESS;
                   5828:
                   5829:        switch (vap->va_type) {
                   5830:        case VREG :
                   5831:                udf_file_type = UDF_ICB_FILETYPE_RANDOMACCESS;
                   5832:                break;
                   5833:        case VDIR :
                   5834:                udf_file_type = UDF_ICB_FILETYPE_DIRECTORY;
                   5835:                break;
                   5836:        case VLNK :
                   5837:                udf_file_type = UDF_ICB_FILETYPE_SYMLINK;
                   5838:                break;
                   5839:        case VBLK :
                   5840:                udf_file_type = UDF_ICB_FILETYPE_BLOCKDEVICE;
                   5841:                /* specfs */
                   5842:                return ENOTSUP;
                   5843:                break;
                   5844:        case VCHR :
                   5845:                udf_file_type = UDF_ICB_FILETYPE_CHARDEVICE;
                   5846:                /* specfs */
                   5847:                return ENOTSUP;
                   5848:                break;
                   5849:        case VFIFO :
                   5850:                udf_file_type = UDF_ICB_FILETYPE_FIFO;
                   5851:                /* fifofs */
                   5852:                return ENOTSUP;
                   5853:                break;
                   5854:        case VSOCK :
                   5855:                udf_file_type = UDF_ICB_FILETYPE_SOCKET;
                   5856:                return ENOTSUP;
                   5857:                break;
                   5858:        case VNON :
                   5859:        case VBAD :
                   5860:        default :
                   5861:                /* nothing; can we even create these? */
                   5862:                return EINVAL;
                   5863:        }
1.45      reinoud  5864:
                   5865:        lb_size = udf_rw32(ump->logical_vol->lb_size);
                   5866:
1.95      reinoud  5867:        /* reserve space for one logical block */
1.71      reinoud  5868:        vpart_num = ump->node_part;
1.95      reinoud  5869:        error = udf_reserve_space(ump, NULL, UDF_C_NODE,
                   5870:                vpart_num, 1, /* can_fail */ true);
                   5871:        if (error)
1.129     hannken  5872:                return error;
1.95      reinoud  5873:
                   5874:        /* allocate node */
                   5875:        error = udf_allocate_space(ump, NULL, UDF_C_NODE,
                   5876:                        vpart_num, 1, &lmapping);
1.129     hannken  5877:        if (error) {
                   5878:                udf_do_unreserve_space(ump, NULL, vpart_num, 1);
                   5879:                return error;
                   5880:        }
                   5881:
1.45      reinoud  5882:        lb_num = lmapping;
1.1       reinoud  5883:
1.45      reinoud  5884:        /* initialise pointer to location */
                   5885:        memset(&node_icb_loc, 0, sizeof(struct long_ad));
1.89      reinoud  5886:        node_icb_loc.len = udf_rw32(lb_size);
1.45      reinoud  5887:        node_icb_loc.loc.lb_num   = udf_rw32(lb_num);
                   5888:        node_icb_loc.loc.part_num = udf_rw16(vpart_num);
                   5889:
                   5890:        /* build udf_node (do initialise!) */
                   5891:        udf_node = pool_get(&udf_node_pool, PR_WAITOK);
                   5892:        memset(udf_node, 0, sizeof(struct udf_node));
                   5893:
                   5894:        /* initialise crosslinks, note location of fe/efe for hashing */
                   5895:        /* bugalert: synchronise with udf_get_node() */
                   5896:        udf_node->ump       = ump;
1.129     hannken  5897:        udf_node->vnode     = vp;
                   5898:        vp->v_data          = udf_node;
1.45      reinoud  5899:        udf_node->loc       = node_icb_loc;
                   5900:        udf_node->write_loc = node_icb_loc;
                   5901:        udf_node->lockf     = 0;
                   5902:        mutex_init(&udf_node->node_mutex, MUTEX_DEFAULT, IPL_NONE);
                   5903:        cv_init(&udf_node->node_lock, "udf_nlk");
                   5904:        udf_node->outstanding_bufs = 0;
                   5905:        udf_node->outstanding_nodedscr = 0;
1.95      reinoud  5906:        udf_node->uncommitted_lbs = 0;
1.45      reinoud  5907:
1.129     hannken  5908:        vp->v_tag = VT_UDF;
                   5909:        vp->v_op = vnodeops;
                   5910:
1.1       reinoud  5911:        /* initialise genfs */
1.129     hannken  5912:        genfs_node_init(vp, &udf_genfsops);
1.1       reinoud  5913:
1.45      reinoud  5914:        /* get parent's unique ID for refering '..' if its a directory */
                   5915:        if (dir_node->fe) {
                   5916:                parent_unique_id = udf_rw64(dir_node->fe->unique_id);
1.56      reinoud  5917:                parent_gid       = (gid_t) udf_rw32(dir_node->fe->gid);
1.45      reinoud  5918:        } else {
                   5919:                parent_unique_id = udf_rw64(dir_node->efe->unique_id);
1.56      reinoud  5920:                parent_gid       = (gid_t) udf_rw32(dir_node->efe->gid);
1.45      reinoud  5921:        }
1.1       reinoud  5922:
1.45      reinoud  5923:        /* get descriptor */
                   5924:        udf_create_logvol_dscr(ump, udf_node, &node_icb_loc, &dscr);
1.1       reinoud  5925:
1.45      reinoud  5926:        /* choose a fe or an efe for it */
1.90      reinoud  5927:        if (udf_rw16(ump->logical_vol->tag.descriptor_ver) == 2) {
1.45      reinoud  5928:                udf_node->fe = &dscr->fe;
                   5929:                fid_size = udf_create_new_fe(ump, udf_node->fe,
                   5930:                        udf_file_type, &udf_node->loc,
                   5931:                        &dir_node->loc, parent_unique_id);
                   5932:                /* TODO add extended attribute for creation time */
                   5933:        } else {
                   5934:                udf_node->efe = &dscr->efe;
                   5935:                fid_size = udf_create_new_efe(ump, udf_node->efe,
                   5936:                        udf_file_type, &udf_node->loc,
                   5937:                        &dir_node->loc, parent_unique_id);
                   5938:        }
                   5939:        KASSERT(dscr->tag.tag_loc == udf_node->loc.loc.lb_num);
1.1       reinoud  5940:
1.45      reinoud  5941:        /* update vnode's size and type */
1.129     hannken  5942:        vp->v_type = vap->va_type;
                   5943:        uvm_vnp_setsize(vp, fid_size);
1.1       reinoud  5944:
1.45      reinoud  5945:        /* set access mode */
                   5946:        udf_setaccessmode(udf_node, vap->va_mode);
1.1       reinoud  5947:
1.45      reinoud  5948:        /* set ownership */
1.129     hannken  5949:        uid = kauth_cred_geteuid(cred);
1.56      reinoud  5950:        gid = parent_gid;
                   5951:        udf_setownership(udf_node, uid, gid);
1.1       reinoud  5952:
1.141     maya     5953:        *key_len = sizeof(udf_node->loc.loc);
1.129     hannken  5954:        *new_key = &udf_node->loc.loc;
                   5955:
                   5956:        return 0;
                   5957: }
                   5958:
                   5959:
                   5960: int
                   5961: udf_create_node(struct vnode *dvp, struct vnode **vpp, struct vattr *vap,
                   5962:        struct componentname *cnp)
                   5963: {
                   5964:        struct udf_node *udf_node, *dir_node = VTOI(dvp);
                   5965:        struct udf_mount *ump = dir_node->ump;
                   5966:        int error;
                   5967:
1.145     hannken  5968:        error = vcache_new(dvp->v_mount, dvp, vap, cnp->cn_cred, NULL, vpp);
1.129     hannken  5969:        if (error)
                   5970:                return error;
                   5971:
                   5972:        udf_node = VTOI(*vpp);
1.45      reinoud  5973:        error = udf_dir_attach(ump, dir_node, udf_node, vap, cnp);
                   5974:        if (error) {
1.129     hannken  5975:                struct long_ad *node_icb_loc = &udf_node->loc;
                   5976:                uint32_t lb_num = udf_rw32(node_icb_loc->loc.lb_num);
                   5977:                uint16_t vpart_num = udf_rw16(node_icb_loc->loc.part_num);
                   5978:
1.45      reinoud  5979:                /* free disc allocation for node */
                   5980:                udf_free_allocated_space(ump, lb_num, vpart_num, 1);
1.1       reinoud  5981:
1.45      reinoud  5982:                /* recycle udf_node */
                   5983:                udf_dispose_node(udf_node);
1.129     hannken  5984:                vrele(*vpp);
1.1       reinoud  5985:
1.45      reinoud  5986:                *vpp = NULL;
                   5987:                return error;
                   5988:        }
1.1       reinoud  5989:
1.45      reinoud  5990:        /* adjust file count */
                   5991:        udf_adjust_filecount(udf_node, 1);
1.1       reinoud  5992:
1.147     christos 5993:        cache_enter(dvp, *vpp, cnp->cn_nameptr, cnp->cn_namelen, cnp->cn_flags);
1.45      reinoud  5994:        return 0;
1.1       reinoud  5995: }
                   5996:
                   5997: /* --------------------------------------------------------------------- */
                   5998:
1.45      reinoud  5999: static void
                   6000: udf_free_descriptor_space(struct udf_node *udf_node, struct long_ad *loc, void *mem)
                   6001: {
                   6002:        struct udf_mount *ump = udf_node->ump;
                   6003:        uint32_t lb_size, lb_num, len, num_lb;
                   6004:        uint16_t vpart_num;
                   6005:
                   6006:        /* is there really one? */
                   6007:        if (mem == NULL)
                   6008:                return;
1.1       reinoud  6009:
1.45      reinoud  6010:        /* got a descriptor here */
1.55      reinoud  6011:        len       = UDF_EXT_LEN(udf_rw32(loc->len));
1.45      reinoud  6012:        lb_num    = udf_rw32(loc->loc.lb_num);
                   6013:        vpart_num = udf_rw16(loc->loc.part_num);
1.1       reinoud  6014:
1.45      reinoud  6015:        lb_size = udf_rw32(ump->logical_vol->lb_size);
                   6016:        num_lb = (len + lb_size -1) / lb_size;
1.1       reinoud  6017:
1.45      reinoud  6018:        udf_free_allocated_space(ump, lb_num, vpart_num, num_lb);
1.1       reinoud  6019: }
                   6020:
                   6021: void
1.45      reinoud  6022: udf_delete_node(struct udf_node *udf_node)
1.1       reinoud  6023: {
1.45      reinoud  6024:        void *dscr;
                   6025:        struct long_ad *loc;
                   6026:        int extnr, lvint, dummy;
                   6027:
1.137     reinoud  6028:        if (udf_node->i_flags & IN_NO_DELETE)
                   6029:                return;
                   6030:
1.45      reinoud  6031:        /* paranoia check on integrity; should be open!; we could panic */
                   6032:        lvint = udf_rw32(udf_node->ump->logvol_integrity->integrity_type);
                   6033:        if (lvint == UDF_INTEGRITY_CLOSED)
                   6034:                printf("\tIntegrity was CLOSED!\n");
                   6035:
                   6036:        /* whatever the node type, change its size to zero */
                   6037:        (void) udf_resize_node(udf_node, 0, &dummy);
1.1       reinoud  6038:
1.45      reinoud  6039:        /* force it to be `clean'; no use writing it out */
                   6040:        udf_node->i_flags &= ~(IN_MODIFIED | IN_ACCESSED | IN_ACCESS |
                   6041:                IN_CHANGE | IN_UPDATE | IN_MODIFY);
1.1       reinoud  6042:
1.45      reinoud  6043:        /* adjust file count */
                   6044:        udf_adjust_filecount(udf_node, -1);
1.1       reinoud  6045:
                   6046:        /*
1.45      reinoud  6047:         * Free its allocated descriptors; memory will be released when
                   6048:         * vop_reclaim() is called.
1.1       reinoud  6049:         */
1.45      reinoud  6050:        loc = &udf_node->loc;
                   6051:
                   6052:        dscr = udf_node->fe;
                   6053:        udf_free_descriptor_space(udf_node, loc, dscr);
                   6054:        dscr = udf_node->efe;
                   6055:        udf_free_descriptor_space(udf_node, loc, dscr);
1.1       reinoud  6056:
1.45      reinoud  6057:        for (extnr = 0; extnr < UDF_MAX_ALLOC_EXTENTS; extnr++) {
                   6058:                dscr =  udf_node->ext[extnr];
                   6059:                loc  = &udf_node->ext_loc[extnr];
                   6060:                udf_free_descriptor_space(udf_node, loc, dscr);
1.9       christos 6061:        }
1.1       reinoud  6062: }
                   6063:
                   6064: /* --------------------------------------------------------------------- */
                   6065:
1.45      reinoud  6066: /* set new filesize; node but be LOCKED on entry and is locked on exit */
                   6067: int
                   6068: udf_resize_node(struct udf_node *udf_node, uint64_t new_size, int *extended)
1.1       reinoud  6069: {
1.45      reinoud  6070:        struct file_entry    *fe  = udf_node->fe;
                   6071:        struct extfile_entry *efe = udf_node->efe;
                   6072:        uint64_t file_size;
                   6073:        int error;
1.1       reinoud  6074:
1.45      reinoud  6075:        if (fe) {
                   6076:                file_size  = udf_rw64(fe->inf_len);
1.1       reinoud  6077:        } else {
                   6078:                assert(udf_node->efe);
1.45      reinoud  6079:                file_size  = udf_rw64(efe->inf_len);
1.9       christos 6080:        }
1.1       reinoud  6081:
1.45      reinoud  6082:        DPRINTF(ATTR, ("\tchanging file length from %"PRIu64" to %"PRIu64"\n",
                   6083:                        file_size, new_size));
                   6084:
                   6085:        /* if not changing, we're done */
                   6086:        if (file_size == new_size)
                   6087:                return 0;
1.1       reinoud  6088:
1.45      reinoud  6089:        *extended = (new_size > file_size);
                   6090:        if (*extended) {
                   6091:                error = udf_grow_node(udf_node, new_size);
                   6092:        } else {
                   6093:                error = udf_shrink_node(udf_node, new_size);
                   6094:        }
1.1       reinoud  6095:
1.45      reinoud  6096:        return error;
1.1       reinoud  6097: }
                   6098:
1.45      reinoud  6099:
1.1       reinoud  6100: /* --------------------------------------------------------------------- */
                   6101:
1.45      reinoud  6102: void
                   6103: udf_itimes(struct udf_node *udf_node, struct timespec *acc,
1.50      reinoud  6104:        struct timespec *mod, struct timespec *birth)
1.1       reinoud  6105: {
1.45      reinoud  6106:        struct timespec now;
1.1       reinoud  6107:        struct file_entry    *fe;
                   6108:        struct extfile_entry *efe;
1.51      reinoud  6109:        struct filetimes_extattr_entry *ft_extattr;
1.50      reinoud  6110:        struct timestamp *atime, *mtime, *attrtime, *ctime;
                   6111:        struct timestamp  fe_ctime;
                   6112:        struct timespec   cur_birth;
1.51      reinoud  6113:        uint32_t offset, a_l;
                   6114:        uint8_t *filedata;
                   6115:        int error;
1.45      reinoud  6116:
                   6117:        /* protect against rogue values */
                   6118:        if (!udf_node)
                   6119:                return;
                   6120:
                   6121:        fe  = udf_node->fe;
                   6122:        efe = udf_node->efe;
                   6123:
                   6124:        if (!(udf_node->i_flags & (IN_ACCESS|IN_CHANGE|IN_UPDATE|IN_MODIFY)))
                   6125:                return;
1.1       reinoud  6126:
1.45      reinoud  6127:        /* get descriptor information */
                   6128:        if (fe) {
                   6129:                atime    = &fe->atime;
                   6130:                mtime    = &fe->mtime;
                   6131:                attrtime = &fe->attrtime;
1.51      reinoud  6132:                filedata = fe->data;
                   6133:
                   6134:                /* initial save dummy setting */
1.50      reinoud  6135:                ctime    = &fe_ctime;
1.51      reinoud  6136:
                   6137:                /* check our extended attribute if present */
                   6138:                error = udf_extattr_search_intern(udf_node,
                   6139:                        UDF_FILETIMES_ATTR_NO, "", &offset, &a_l);
                   6140:                if (!error) {
                   6141:                        ft_extattr = (struct filetimes_extattr_entry *)
                   6142:                                (filedata + offset);
                   6143:                        if (ft_extattr->existence & UDF_FILETIMES_FILE_CREATION)
                   6144:                                ctime = &ft_extattr->times[0];
                   6145:                }
                   6146:                /* TODO create the extended attribute if not found ? */
1.1       reinoud  6147:        } else {
1.45      reinoud  6148:                assert(udf_node->efe);
                   6149:                atime    = &efe->atime;
                   6150:                mtime    = &efe->mtime;
                   6151:                attrtime = &efe->attrtime;
1.50      reinoud  6152:                ctime    = &efe->ctime;
1.45      reinoud  6153:        }
                   6154:
                   6155:        vfs_timestamp(&now);
                   6156:
                   6157:        /* set access time */
                   6158:        if (udf_node->i_flags & IN_ACCESS) {
                   6159:                if (acc == NULL)
                   6160:                        acc = &now;
                   6161:                udf_timespec_to_timestamp(acc, atime);
                   6162:        }
                   6163:
                   6164:        /* set modification time */
                   6165:        if (udf_node->i_flags & (IN_UPDATE | IN_MODIFY)) {
                   6166:                if (mod == NULL)
                   6167:                        mod = &now;
                   6168:                udf_timespec_to_timestamp(mod, mtime);
1.50      reinoud  6169:
                   6170:                /* ensure birthtime is older than set modification! */
                   6171:                udf_timestamp_to_timespec(udf_node->ump, ctime, &cur_birth);
                   6172:                if ((cur_birth.tv_sec > mod->tv_sec) ||
                   6173:                          ((cur_birth.tv_sec == mod->tv_sec) &&
                   6174:                             (cur_birth.tv_nsec > mod->tv_nsec))) {
                   6175:                        udf_timespec_to_timestamp(mod, ctime);
                   6176:                }
1.45      reinoud  6177:        }
                   6178:
1.50      reinoud  6179:        /* update birthtime if specified */
1.116     mbalmer  6180:        /* XXX we assume here that given birthtime is older than mod */
1.51      reinoud  6181:        if (birth && (birth->tv_sec != VNOVAL)) {
1.50      reinoud  6182:                udf_timespec_to_timestamp(birth, ctime);
1.51      reinoud  6183:        }
1.50      reinoud  6184:
1.45      reinoud  6185:        /* set change time */
1.50      reinoud  6186:        if (udf_node->i_flags & (IN_CHANGE | IN_MODIFY))
                   6187:                udf_timespec_to_timestamp(&now, attrtime);
1.1       reinoud  6188:
1.45      reinoud  6189:        /* notify updates to the node itself */
                   6190:        if (udf_node->i_flags & (IN_ACCESS | IN_MODIFY))
                   6191:                udf_node->i_flags |= IN_ACCESSED;
                   6192:        if (udf_node->i_flags & (IN_UPDATE | IN_CHANGE))
                   6193:                udf_node->i_flags |= IN_MODIFIED;
                   6194:
                   6195:        /* clear modification flags */
                   6196:        udf_node->i_flags &= ~(IN_ACCESS | IN_CHANGE | IN_UPDATE | IN_MODIFY);
                   6197: }
                   6198:
                   6199: /* --------------------------------------------------------------------- */
1.1       reinoud  6200:
1.45      reinoud  6201: int
                   6202: udf_update(struct vnode *vp, struct timespec *acc,
1.50      reinoud  6203:        struct timespec *mod, struct timespec *birth, int updflags)
1.45      reinoud  6204: {
1.71      reinoud  6205:        union dscrptr *dscrptr;
1.45      reinoud  6206:        struct udf_node  *udf_node = VTOI(vp);
                   6207:        struct udf_mount *ump = udf_node->ump;
                   6208:        struct regid     *impl_id;
                   6209:        int mnt_async = (vp->v_mount->mnt_flag & MNT_ASYNC);
                   6210:        int waitfor, flags;
1.31      reinoud  6211:
1.45      reinoud  6212: #ifdef DEBUG
                   6213:        char bits[128];
1.50      reinoud  6214:        DPRINTF(CALL, ("udf_update(node, %p, %p, %p, %d)\n", acc, mod, birth,
                   6215:                updflags));
1.80      christos 6216:        snprintb(bits, sizeof(bits), IN_FLAGBITS, udf_node->i_flags);
1.45      reinoud  6217:        DPRINTF(CALL, ("\tnode flags %s\n", bits));
                   6218:        DPRINTF(CALL, ("\t\tmnt_async = %d\n", mnt_async));
                   6219: #endif
1.31      reinoud  6220:
1.45      reinoud  6221:        /* set our times */
1.51      reinoud  6222:        udf_itimes(udf_node, acc, mod, birth);
1.37      rumble   6223:
1.45      reinoud  6224:        /* set our implementation id */
                   6225:        if (udf_node->fe) {
1.71      reinoud  6226:                dscrptr = (union dscrptr *) udf_node->fe;
1.45      reinoud  6227:                impl_id = &udf_node->fe->imp_id;
                   6228:        } else {
1.71      reinoud  6229:                dscrptr = (union dscrptr *) udf_node->efe;
1.45      reinoud  6230:                impl_id = &udf_node->efe->imp_id;
                   6231:        }
1.71      reinoud  6232:
                   6233:        /* set our ID */
1.45      reinoud  6234:        udf_set_regid(impl_id, IMPL_NAME);
                   6235:        udf_add_impl_regid(ump, impl_id);
1.18      reinoud  6236:
1.71      reinoud  6237:        /* update our crc! on RMW we are not allowed to change a thing */
                   6238:        udf_validate_tag_and_crc_sums(dscrptr);
                   6239:
1.45      reinoud  6240:        /* if called when mounted readonly, never write back */
                   6241:        if (vp->v_mount->mnt_flag & MNT_RDONLY)
                   6242:                return 0;
1.1       reinoud  6243:
1.45      reinoud  6244:        /* check if the node is dirty 'enough'*/
                   6245:        if (updflags & UPDATE_CLOSE) {
                   6246:                flags = udf_node->i_flags & (IN_MODIFIED | IN_ACCESSED);
                   6247:        } else {
                   6248:                flags = udf_node->i_flags & IN_MODIFIED;
                   6249:        }
                   6250:        if (flags == 0)
                   6251:                return 0;
1.19      reinoud  6252:
1.45      reinoud  6253:        /* determine if we need to write sync or async */
                   6254:        waitfor = 0;
                   6255:        if ((flags & IN_MODIFIED) && (mnt_async == 0)) {
                   6256:                /* sync mounted */
                   6257:                waitfor = updflags & UPDATE_WAIT;
                   6258:                if (updflags & UPDATE_DIROP)
                   6259:                        waitfor |= UPDATE_WAIT;
1.9       christos 6260:        }
1.45      reinoud  6261:        if (waitfor)
                   6262:                return VOP_FSYNC(vp, FSCRED, FSYNC_WAIT, 0,0);
1.1       reinoud  6263:
1.45      reinoud  6264:        return 0;
1.1       reinoud  6265: }
                   6266:
1.45      reinoud  6267:
1.1       reinoud  6268: /* --------------------------------------------------------------------- */
                   6269:
1.59      reinoud  6270:
1.1       reinoud  6271: /*
                   6272:  * Read one fid and process it into a dirent and advance to the next (*fid)
                   6273:  * has to be allocated a logical block in size, (*dirent) struct dirent length
                   6274:  */
                   6275:
                   6276: int
                   6277: udf_read_fid_stream(struct vnode *vp, uint64_t *offset,
1.97      reinoud  6278:                struct fileid_desc *fid, struct dirent *dirent)
1.1       reinoud  6279: {
                   6280:        struct udf_node  *dir_node = VTOI(vp);
                   6281:        struct udf_mount *ump = dir_node->ump;
1.45      reinoud  6282:        struct file_entry    *fe  = dir_node->fe;
                   6283:        struct extfile_entry *efe = dir_node->efe;
                   6284:        uint32_t      fid_size, lb_size;
1.1       reinoud  6285:        uint64_t      file_size;
                   6286:        char         *fid_name;
                   6287:        int           enough, error;
                   6288:
                   6289:        assert(fid);
                   6290:        assert(dirent);
                   6291:        assert(dir_node);
                   6292:        assert(offset);
                   6293:        assert(*offset != 1);
                   6294:
1.45      reinoud  6295:        DPRINTF(FIDS, ("read_fid_stream called at offset %"PRIu64"\n", *offset));
1.1       reinoud  6296:        /* check if we're past the end of the directory */
1.45      reinoud  6297:        if (fe) {
1.1       reinoud  6298:                file_size = udf_rw64(fe->inf_len);
                   6299:        } else {
                   6300:                assert(dir_node->efe);
                   6301:                file_size = udf_rw64(efe->inf_len);
1.9       christos 6302:        }
1.1       reinoud  6303:        if (*offset >= file_size)
                   6304:                return EINVAL;
                   6305:
                   6306:        /* get maximum length of FID descriptor */
                   6307:        lb_size = udf_rw32(ump->logical_vol->lb_size);
                   6308:
                   6309:        /* initialise return values */
1.45      reinoud  6310:        fid_size = 0;
1.1       reinoud  6311:        memset(dirent, 0, sizeof(struct dirent));
                   6312:        memset(fid, 0, lb_size);
                   6313:
1.45      reinoud  6314:        enough  = (file_size - (*offset) >= UDF_FID_SIZE);
                   6315:        if (!enough) {
                   6316:                /* short dir ... */
                   6317:                return EIO;
                   6318:        }
1.1       reinoud  6319:
1.45      reinoud  6320:        error = vn_rdwr(UIO_READ, vp,
                   6321:                        fid, MIN(file_size - (*offset), lb_size), *offset,
                   6322:                        UIO_SYSSPACE, IO_ALTSEMANTICS | IO_NODELOCKED, FSCRED,
                   6323:                        NULL, NULL);
1.1       reinoud  6324:        if (error)
                   6325:                return error;
                   6326:
1.45      reinoud  6327:        DPRINTF(FIDS, ("\tfid piece read in fine\n"));
1.1       reinoud  6328:        /*
                   6329:         * Check if we got a whole descriptor.
1.45      reinoud  6330:         * TODO Try to `resync' directory stream when something is very wrong.
1.1       reinoud  6331:         */
                   6332:
                   6333:        /* check if our FID header is OK */
                   6334:        error = udf_check_tag(fid);
1.45      reinoud  6335:        if (error) {
                   6336:                goto brokendir;
1.9       christos 6337:        }
1.45      reinoud  6338:        DPRINTF(FIDS, ("\ttag check ok\n"));
1.1       reinoud  6339:
1.45      reinoud  6340:        if (udf_rw16(fid->tag.id) != TAGID_FID) {
                   6341:                error = EIO;
                   6342:                goto brokendir;
1.9       christos 6343:        }
1.45      reinoud  6344:        DPRINTF(FIDS, ("\ttag checked ok: got TAGID_FID\n"));
1.1       reinoud  6345:
1.45      reinoud  6346:        /* check for length */
                   6347:        fid_size = udf_fidsize(fid);
                   6348:        enough = (file_size - (*offset) >= fid_size);
1.1       reinoud  6349:        if (!enough) {
1.45      reinoud  6350:                error = EIO;
                   6351:                goto brokendir;
1.9       christos 6352:        }
1.45      reinoud  6353:        DPRINTF(FIDS, ("\tthe complete fid is read in\n"));
1.1       reinoud  6354:
                   6355:        /* check FID contents */
1.45      reinoud  6356:        error = udf_check_tag_payload((union dscrptr *) fid, lb_size);
                   6357: brokendir:
1.1       reinoud  6358:        if (error) {
                   6359:                /* note that is sometimes a bit quick to report */
1.84      pooka    6360:                printf("UDF: BROKEN DIRECTORY ENTRY\n");
1.1       reinoud  6361:                /* RESYNC? */
                   6362:                /* TODO: use udf_resync_fid_stream */
                   6363:                return EIO;
1.9       christos 6364:        }
1.45      reinoud  6365:        DPRINTF(FIDS, ("\tpayload checked ok\n"));
1.1       reinoud  6366:
                   6367:        /* we got a whole and valid descriptor! */
1.45      reinoud  6368:        DPRINTF(FIDS, ("\tinterpret FID\n"));
1.1       reinoud  6369:
                   6370:        /* create resulting dirent structure */
                   6371:        fid_name = (char *) fid->data + udf_rw16(fid->l_iu);
1.117     christos 6372:        udf_to_unix_name(dirent->d_name, NAME_MAX,
1.1       reinoud  6373:                fid_name, fid->l_fi, &ump->logical_vol->desc_charset);
                   6374:
                   6375:        /* '..' has no name, so provide one */
                   6376:        if (fid->file_char & UDF_FILE_CHAR_PAR)
                   6377:                strcpy(dirent->d_name, "..");
                   6378:
1.98      reinoud  6379:        dirent->d_fileno = udf_get_node_id(&fid->icb);  /* inode hash XXX */
1.1       reinoud  6380:        dirent->d_namlen = strlen(dirent->d_name);
                   6381:        dirent->d_reclen = _DIRENT_SIZE(dirent);
                   6382:
                   6383:        /*
                   6384:         * Note that its not worth trying to go for the filetypes now... its
                   6385:         * too expensive too
                   6386:         */
                   6387:        dirent->d_type = DT_UNKNOWN;
                   6388:
                   6389:        /* initial guess for filetype we can make */
                   6390:        if (fid->file_char & UDF_FILE_CHAR_DIR)
                   6391:                dirent->d_type = DT_DIR;
                   6392:
                   6393:        /* advance */
1.45      reinoud  6394:        *offset += fid_size;
1.1       reinoud  6395:
                   6396:        return error;
                   6397: }
                   6398:
1.45      reinoud  6399:
                   6400: /* --------------------------------------------------------------------- */
                   6401:
                   6402: static void
1.132     hannken  6403: udf_sync_pass(struct udf_mount *ump, kauth_cred_t cred, int pass, int *ndirty)
1.45      reinoud  6404: {
                   6405:        struct udf_node *udf_node, *n_udf_node;
                   6406:        struct vnode *vp;
                   6407:        int vdirty, error;
                   6408:
1.132     hannken  6409:        KASSERT(mutex_owned(&ump->sync_lock));
1.45      reinoud  6410:
                   6411:        DPRINTF(SYNC, ("sync_pass %d\n", pass));
1.108     rmind    6412:        udf_node = RB_TREE_MIN(&ump->udf_node_tree);
1.45      reinoud  6413:        for (;udf_node; udf_node = n_udf_node) {
                   6414:                DPRINTF(SYNC, ("."));
                   6415:
                   6416:                vp = udf_node->vnode;
                   6417:
1.108     rmind    6418:                n_udf_node = rb_tree_iterate(&ump->udf_node_tree,
                   6419:                    udf_node, RB_DIR_RIGHT);
1.98      reinoud  6420:
1.130     riastrad 6421:                error = vn_lock(vp, LK_EXCLUSIVE | LK_NOWAIT);
                   6422:                if (error) {
                   6423:                        KASSERT(error == EBUSY);
                   6424:                        *ndirty += 1;
                   6425:                        continue;
                   6426:                }
1.45      reinoud  6427:
                   6428:                switch (pass) {
                   6429:                case 1:
                   6430:                        VOP_FSYNC(vp, cred, 0 | FSYNC_DATAONLY,0,0);
                   6431:                        break;
                   6432:                case 2:
                   6433:                        vdirty = vp->v_numoutput;
                   6434:                        if (vp->v_tag == VT_UDF)
                   6435:                                vdirty += udf_node->outstanding_bufs +
                   6436:                                        udf_node->outstanding_nodedscr;
                   6437:                        if (vdirty == 0)
                   6438:                                VOP_FSYNC(vp, cred, 0,0,0);
                   6439:                        *ndirty += vdirty;
                   6440:                        break;
                   6441:                case 3:
                   6442:                        vdirty = vp->v_numoutput;
                   6443:                        if (vp->v_tag == VT_UDF)
                   6444:                                vdirty += udf_node->outstanding_bufs +
                   6445:                                        udf_node->outstanding_nodedscr;
                   6446:                        *ndirty += vdirty;
                   6447:                        break;
                   6448:                }
                   6449:
1.132     hannken  6450:                VOP_UNLOCK(vp);
1.45      reinoud  6451:        }
                   6452:        DPRINTF(SYNC, ("END sync_pass %d\n", pass));
                   6453: }
                   6454:
                   6455:
1.132     hannken  6456: static bool
                   6457: udf_sync_selector(void *cl, struct vnode *vp)
                   6458: {
1.139     riastrad 6459:        struct udf_node *udf_node;
                   6460:
                   6461:        KASSERT(mutex_owned(vp->v_interlock));
                   6462:
                   6463:        udf_node = VTOI(vp);
1.132     hannken  6464:
                   6465:        if (vp->v_vflag & VV_SYSTEM)
                   6466:                return false;
                   6467:        if (vp->v_type == VNON)
                   6468:                return false;
                   6469:        if (udf_node == NULL)
                   6470:                return false;
                   6471:        if ((udf_node->i_flags & (IN_ACCESSED | IN_UPDATE | IN_MODIFIED)) == 0)
                   6472:                return false;
1.149     ad       6473:        if (LIST_EMPTY(&vp->v_dirtyblkhd) && (vp->v_iflag & VI_ONWORKLST) == 0)
1.132     hannken  6474:                return false;
                   6475:
                   6476:        return true;
                   6477: }
                   6478:
1.45      reinoud  6479: void
                   6480: udf_do_sync(struct udf_mount *ump, kauth_cred_t cred, int waitfor)
                   6481: {
1.132     hannken  6482:        struct vnode_iterator *marker;
                   6483:        struct vnode *vp;
                   6484:        struct udf_node *udf_node, *udf_next_node;
1.45      reinoud  6485:        int dummy, ndirty;
                   6486:
1.132     hannken  6487:        if (waitfor == MNT_LAZY)
                   6488:                return;
                   6489:
                   6490:        mutex_enter(&ump->sync_lock);
                   6491:
                   6492:        /* Fill the rbtree with nodes to sync. */
                   6493:        vfs_vnode_iterator_init(ump->vfs_mountp, &marker);
                   6494:        while ((vp = vfs_vnode_iterator_next(marker,
                   6495:            udf_sync_selector, NULL)) != NULL) {
                   6496:                udf_node = VTOI(vp);
                   6497:                udf_node->i_flags |= IN_SYNCED;
                   6498:                rb_tree_insert_node(&ump->udf_node_tree, udf_node);
                   6499:        }
                   6500:        vfs_vnode_iterator_destroy(marker);
                   6501:
1.45      reinoud  6502:        dummy = 0;
                   6503:        DPRINTF(CALL, ("issue VOP_FSYNC(DATA only) on all nodes\n"));
                   6504:        DPRINTF(SYNC, ("issue VOP_FSYNC(DATA only) on all nodes\n"));
1.132     hannken  6505:        udf_sync_pass(ump, cred, 1, &dummy);
1.45      reinoud  6506:
                   6507:        DPRINTF(CALL, ("issue VOP_FSYNC(COMPLETE) on all finished nodes\n"));
                   6508:        DPRINTF(SYNC, ("issue VOP_FSYNC(COMPLETE) on all finished nodes\n"));
1.132     hannken  6509:        udf_sync_pass(ump, cred, 2, &dummy);
1.45      reinoud  6510:
                   6511:        if (waitfor == MNT_WAIT) {
1.132     hannken  6512: recount:
1.45      reinoud  6513:                ndirty = ump->devvp->v_numoutput;
1.77      reinoud  6514:                DPRINTF(SYNC, ("counting pending blocks: on devvp %d\n",
1.45      reinoud  6515:                        ndirty));
1.132     hannken  6516:                udf_sync_pass(ump, cred, 3, &ndirty);
1.77      reinoud  6517:                DPRINTF(SYNC, ("counted num dirty pending blocks %d\n",
1.45      reinoud  6518:                        ndirty));
1.152     skrll    6519:
1.45      reinoud  6520:                if (ndirty) {
                   6521:                        /* 1/4 second wait */
1.131     hannken  6522:                        kpause("udfsync2", false, hz/4, NULL);
1.45      reinoud  6523:                        goto recount;
                   6524:                }
                   6525:        }
                   6526:
1.132     hannken  6527:        /* Clean the rbtree. */
                   6528:        for (udf_node = RB_TREE_MIN(&ump->udf_node_tree);
                   6529:            udf_node; udf_node = udf_next_node) {
                   6530:                udf_next_node = rb_tree_iterate(&ump->udf_node_tree,
                   6531:                    udf_node, RB_DIR_RIGHT);
                   6532:                rb_tree_remove_node(&ump->udf_node_tree, udf_node);
                   6533:                udf_node->i_flags &= ~IN_SYNCED;
                   6534:                vrele(udf_node->vnode);
                   6535:        }
                   6536:
                   6537:        mutex_exit(&ump->sync_lock);
1.45      reinoud  6538: }
                   6539:
1.1       reinoud  6540: /* --------------------------------------------------------------------- */
                   6541:
                   6542: /*
1.45      reinoud  6543:  * Read and write file extent in/from the buffer.
                   6544:  *
1.146     msaitoh  6545:  * The splitup of the extent into separate request-buffers is to minimise
1.45      reinoud  6546:  * copying around as much as possible.
                   6547:  *
1.1       reinoud  6548:  * block based file reading and writing
                   6549:  */
                   6550:
                   6551: static int
                   6552: udf_read_internal(struct udf_node *node, uint8_t *blob)
                   6553: {
                   6554:        struct udf_mount *ump;
1.45      reinoud  6555:        struct file_entry     *fe = node->fe;
                   6556:        struct extfile_entry *efe = node->efe;
1.1       reinoud  6557:        uint64_t inflen;
                   6558:        uint32_t sector_size;
1.135     dholland 6559:        uint8_t  *srcpos;
1.1       reinoud  6560:        int icbflags, addr_type;
                   6561:
                   6562:        /* get extent and do some paranoia checks */
                   6563:        ump = node->ump;
                   6564:        sector_size = ump->discinfo.sector_size;
                   6565:
1.135     dholland 6566:        /*
                   6567:         * XXX there should be real bounds-checking logic here,
                   6568:         * in case ->l_ea or ->inf_len contains nonsense.
                   6569:         */
                   6570:
1.1       reinoud  6571:        if (fe) {
                   6572:                inflen   = udf_rw64(fe->inf_len);
1.135     dholland 6573:                srcpos   = &fe->data[0] + udf_rw32(fe->l_ea);
1.1       reinoud  6574:                icbflags = udf_rw16(fe->icbtag.flags);
1.45      reinoud  6575:        } else {
                   6576:                assert(node->efe);
1.1       reinoud  6577:                inflen   = udf_rw64(efe->inf_len);
1.135     dholland 6578:                srcpos   = &efe->data[0] + udf_rw32(efe->l_ea);
1.1       reinoud  6579:                icbflags = udf_rw16(efe->icbtag.flags);
1.9       christos 6580:        }
1.1       reinoud  6581:        addr_type = icbflags & UDF_ICB_TAG_FLAGS_ALLOC_MASK;
                   6582:
                   6583:        assert(addr_type == UDF_ICB_INTERN_ALLOC);
1.124     christos 6584:        __USE(addr_type);
1.1       reinoud  6585:        assert(inflen < sector_size);
                   6586:
                   6587:        /* copy out info */
1.135     dholland 6588:        memcpy(blob, srcpos, inflen);
1.134     christos 6589:        memset(&blob[inflen], 0, sector_size - inflen);
1.1       reinoud  6590:
                   6591:        return 0;
                   6592: }
                   6593:
                   6594:
1.45      reinoud  6595: static int
                   6596: udf_write_internal(struct udf_node *node, uint8_t *blob)
1.1       reinoud  6597: {
1.45      reinoud  6598:        struct udf_mount *ump;
                   6599:        struct file_entry     *fe = node->fe;
                   6600:        struct extfile_entry *efe = node->efe;
                   6601:        uint64_t inflen;
1.1       reinoud  6602:        uint32_t sector_size;
1.45      reinoud  6603:        uint8_t  *pos;
                   6604:        int icbflags, addr_type;
                   6605:
                   6606:        /* get extent and do some paranoia checks */
                   6607:        ump = node->ump;
                   6608:        sector_size = ump->discinfo.sector_size;
1.1       reinoud  6609:
1.45      reinoud  6610:        if (fe) {
                   6611:                inflen   = udf_rw64(fe->inf_len);
                   6612:                pos      = &fe->data[0] + udf_rw32(fe->l_ea);
                   6613:                icbflags = udf_rw16(fe->icbtag.flags);
                   6614:        } else {
                   6615:                assert(node->efe);
                   6616:                inflen   = udf_rw64(efe->inf_len);
                   6617:                pos      = &efe->data[0] + udf_rw32(efe->l_ea);
                   6618:                icbflags = udf_rw16(efe->icbtag.flags);
                   6619:        }
                   6620:        addr_type = icbflags & UDF_ICB_TAG_FLAGS_ALLOC_MASK;
1.1       reinoud  6621:
1.45      reinoud  6622:        assert(addr_type == UDF_ICB_INTERN_ALLOC);
1.124     christos 6623:        __USE(addr_type);
1.45      reinoud  6624:        assert(inflen < sector_size);
1.124     christos 6625:        __USE(sector_size);
1.1       reinoud  6626:
1.45      reinoud  6627:        /* copy in blob */
                   6628:        /* memset(pos, 0, inflen); */
                   6629:        memcpy(pos, blob, inflen);
1.1       reinoud  6630:
1.45      reinoud  6631:        return 0;
1.1       reinoud  6632: }
                   6633:
                   6634:
                   6635: void
1.45      reinoud  6636: udf_read_filebuf(struct udf_node *udf_node, struct buf *buf)
1.1       reinoud  6637: {
                   6638:        struct buf *nestbuf;
1.45      reinoud  6639:        struct udf_mount *ump = udf_node->ump;
1.10      christos 6640:        uint64_t   *mapping;
1.1       reinoud  6641:        uint64_t    run_start;
                   6642:        uint32_t    sector_size;
                   6643:        uint32_t    buf_offset, sector, rbuflen, rblk;
1.45      reinoud  6644:        uint32_t    from, lblkno;
                   6645:        uint32_t    sectors;
1.1       reinoud  6646:        uint8_t    *buf_pos;
1.95      reinoud  6647:        int error, run_length, what;
1.1       reinoud  6648:
1.45      reinoud  6649:        sector_size = udf_node->ump->discinfo.sector_size;
1.1       reinoud  6650:
                   6651:        from    = buf->b_blkno;
                   6652:        sectors = buf->b_bcount / sector_size;
                   6653:
1.95      reinoud  6654:        what = udf_get_c_type(udf_node);
1.45      reinoud  6655:
1.1       reinoud  6656:        /* assure we have enough translation slots */
1.45      reinoud  6657:        KASSERT(buf->b_bcount / sector_size <= UDF_MAX_MAPPINGS);
                   6658:        KASSERT(MAXPHYS / sector_size <= UDF_MAX_MAPPINGS);
1.1       reinoud  6659:
1.45      reinoud  6660:        if (sectors > UDF_MAX_MAPPINGS) {
1.1       reinoud  6661:                printf("udf_read_filebuf: implementation limit on bufsize\n");
                   6662:                buf->b_error  = EIO;
                   6663:                biodone(buf);
                   6664:                return;
1.9       christos 6665:        }
1.1       reinoud  6666:
1.45      reinoud  6667:        mapping = malloc(sizeof(*mapping) * UDF_MAX_MAPPINGS, M_TEMP, M_WAITOK);
1.10      christos 6668:
1.1       reinoud  6669:        error = 0;
                   6670:        DPRINTF(READ, ("\ttranslate %d-%d\n", from, sectors));
1.45      reinoud  6671:        error = udf_translate_file_extent(udf_node, from, sectors, mapping);
1.1       reinoud  6672:        if (error) {
                   6673:                buf->b_error  = error;
                   6674:                biodone(buf);
1.10      christos 6675:                goto out;
1.9       christos 6676:        }
1.1       reinoud  6677:        DPRINTF(READ, ("\ttranslate extent went OK\n"));
                   6678:
1.45      reinoud  6679:        /* pre-check if its an internal */
1.1       reinoud  6680:        if (*mapping == UDF_TRANS_INTERN) {
1.45      reinoud  6681:                error = udf_read_internal(udf_node, (uint8_t *) buf->b_data);
                   6682:                if (error)
1.1       reinoud  6683:                        buf->b_error  = error;
                   6684:                biodone(buf);
1.10      christos 6685:                goto out;
1.9       christos 6686:        }
1.1       reinoud  6687:        DPRINTF(READ, ("\tnot intern\n"));
                   6688:
1.45      reinoud  6689: #ifdef DEBUG
                   6690:        if (udf_verbose & UDF_DEBUG_TRANSLATE) {
                   6691:                printf("Returned translation table:\n");
                   6692:                for (sector = 0; sector < sectors; sector++) {
                   6693:                        printf("%d : %"PRIu64"\n", sector, mapping[sector]);
                   6694:                }
                   6695:        }
                   6696: #endif
                   6697:
                   6698:        /* request read-in of data from disc sheduler */
1.1       reinoud  6699:        buf->b_resid = buf->b_bcount;
                   6700:        for (sector = 0; sector < sectors; sector++) {
                   6701:                buf_offset = sector * sector_size;
                   6702:                buf_pos    = (uint8_t *) buf->b_data + buf_offset;
                   6703:                DPRINTF(READ, ("\tprocessing rel sector %d\n", sector));
                   6704:
1.45      reinoud  6705:                /* check if its zero or unmapped to stop reading */
1.1       reinoud  6706:                switch (mapping[sector]) {
                   6707:                case UDF_TRANS_UNMAPPED:
                   6708:                case UDF_TRANS_ZERO:
1.45      reinoud  6709:                        /* copy zero sector TODO runlength like below */
1.1       reinoud  6710:                        memset(buf_pos, 0, sector_size);
                   6711:                        DPRINTF(READ, ("\treturning zero sector\n"));
                   6712:                        nestiobuf_done(buf, sector_size, 0);
                   6713:                        break;
                   6714:                default :
                   6715:                        DPRINTF(READ, ("\tread sector "
                   6716:                            "%"PRIu64"\n", mapping[sector]));
                   6717:
1.45      reinoud  6718:                        lblkno = from + sector;
1.1       reinoud  6719:                        run_start  = mapping[sector];
                   6720:                        run_length = 1;
                   6721:                        while (sector < sectors-1) {
                   6722:                                if (mapping[sector+1] != mapping[sector]+1)
                   6723:                                        break;
                   6724:                                run_length++;
                   6725:                                sector++;
1.9       christos 6726:                        }
1.1       reinoud  6727:
                   6728:                        /*
                   6729:                         * nest an iobuf and mark it for async reading. Since
                   6730:                         * we're using nested buffers, they can't be cached by
                   6731:                         * design.
                   6732:                         */
                   6733:                        rbuflen = run_length * sector_size;
                   6734:                        rblk    = run_start  * (sector_size/DEV_BSIZE);
                   6735:
1.44      ad       6736:                        nestbuf = getiobuf(NULL, true);
1.1       reinoud  6737:                        nestiobuf_setup(buf, nestbuf, buf_offset, rbuflen);
                   6738:                        /* nestbuf is B_ASYNC */
                   6739:
1.45      reinoud  6740:                        /* identify this nestbuf */
                   6741:                        nestbuf->b_lblkno   = lblkno;
                   6742:                        assert(nestbuf->b_vp == udf_node->vnode);
                   6743:
                   6744:                        /* CD shedules on raw blkno */
                   6745:                        nestbuf->b_blkno      = rblk;
                   6746:                        nestbuf->b_proc       = NULL;
                   6747:                        nestbuf->b_rawblkno   = rblk;
                   6748:                        nestbuf->b_udf_c_type = what;
                   6749:
                   6750:                        udf_discstrat_queuebuf(ump, nestbuf);
1.9       christos 6751:                }
                   6752:        }
1.10      christos 6753: out:
1.45      reinoud  6754:        /* if we're synchronously reading, wait for the completion */
                   6755:        if ((buf->b_flags & B_ASYNC) == 0)
                   6756:                biowait(buf);
                   6757:
1.1       reinoud  6758:        DPRINTF(READ, ("\tend of read_filebuf\n"));
1.45      reinoud  6759:        free(mapping, M_TEMP);
1.10      christos 6760:        return;
1.1       reinoud  6761: }
                   6762:
                   6763:
1.45      reinoud  6764: void
                   6765: udf_write_filebuf(struct udf_node *udf_node, struct buf *buf)
                   6766: {
                   6767:        struct buf *nestbuf;
                   6768:        struct udf_mount *ump = udf_node->ump;
                   6769:        uint64_t   *mapping;
                   6770:        uint64_t    run_start;
                   6771:        uint32_t    lb_size;
                   6772:        uint32_t    buf_offset, lb_num, rbuflen, rblk;
                   6773:        uint32_t    from, lblkno;
                   6774:        uint32_t    num_lb;
1.95      reinoud  6775:        int error, run_length, what, s;
1.45      reinoud  6776:
                   6777:        lb_size = udf_rw32(udf_node->ump->logical_vol->lb_size);
                   6778:
                   6779:        from   = buf->b_blkno;
                   6780:        num_lb = buf->b_bcount / lb_size;
1.1       reinoud  6781:
1.95      reinoud  6782:        what = udf_get_c_type(udf_node);
1.70      reinoud  6783:
1.45      reinoud  6784:        /* assure we have enough translation slots */
                   6785:        KASSERT(buf->b_bcount / lb_size <= UDF_MAX_MAPPINGS);
                   6786:        KASSERT(MAXPHYS / lb_size <= UDF_MAX_MAPPINGS);
1.1       reinoud  6787:
1.45      reinoud  6788:        if (num_lb > UDF_MAX_MAPPINGS) {
                   6789:                printf("udf_write_filebuf: implementation limit on bufsize\n");
                   6790:                buf->b_error  = EIO;
                   6791:                biodone(buf);
                   6792:                return;
                   6793:        }
1.1       reinoud  6794:
1.45      reinoud  6795:        mapping = malloc(sizeof(*mapping) * UDF_MAX_MAPPINGS, M_TEMP, M_WAITOK);
1.1       reinoud  6796:
1.45      reinoud  6797:        error = 0;
                   6798:        DPRINTF(WRITE, ("\ttranslate %d-%d\n", from, num_lb));
                   6799:        error = udf_translate_file_extent(udf_node, from, num_lb, mapping);
                   6800:        if (error) {
                   6801:                buf->b_error  = error;
                   6802:                biodone(buf);
                   6803:                goto out;
1.9       christos 6804:        }
1.45      reinoud  6805:        DPRINTF(WRITE, ("\ttranslate extent went OK\n"));
                   6806:
                   6807:        /* if its internally mapped, we can write it in the descriptor itself */
                   6808:        if (*mapping == UDF_TRANS_INTERN) {
                   6809:                /* TODO paranoia check if we ARE going to have enough space */
                   6810:                error = udf_write_internal(udf_node, (uint8_t *) buf->b_data);
                   6811:                if (error)
                   6812:                        buf->b_error  = error;
                   6813:                biodone(buf);
                   6814:                goto out;
1.9       christos 6815:        }
1.45      reinoud  6816:        DPRINTF(WRITE, ("\tnot intern\n"));
                   6817:
                   6818:        /* request write out of data to disc sheduler */
                   6819:        buf->b_resid = buf->b_bcount;
                   6820:        for (lb_num = 0; lb_num < num_lb; lb_num++) {
                   6821:                buf_offset = lb_num * lb_size;
                   6822:                DPRINTF(WRITE, ("\tprocessing rel lb_num %d\n", lb_num));
                   6823:
                   6824:                /*
                   6825:                 * Mappings are not that important here. Just before we write
                   6826:                 * the lb_num we late-allocate them when needed and update the
                   6827:                 * mapping in the udf_node.
                   6828:                 */
                   6829:
                   6830:                /* XXX why not ignore the mapping altogether ? */
                   6831:                DPRINTF(WRITE, ("\twrite lb_num "
                   6832:                    "%"PRIu64, mapping[lb_num]));
                   6833:
                   6834:                lblkno = from + lb_num;
                   6835:                run_start  = mapping[lb_num];
                   6836:                run_length = 1;
                   6837:                while (lb_num < num_lb-1) {
                   6838:                        if (mapping[lb_num+1] != mapping[lb_num]+1)
                   6839:                                if (mapping[lb_num+1] != mapping[lb_num])
                   6840:                                        break;
                   6841:                        run_length++;
                   6842:                        lb_num++;
                   6843:                }
                   6844:                DPRINTF(WRITE, ("+ %d\n", run_length));
1.1       reinoud  6845:
1.45      reinoud  6846:                /* nest an iobuf on the master buffer for the extent */
                   6847:                rbuflen = run_length * lb_size;
                   6848:                rblk = run_start * (lb_size/DEV_BSIZE);
1.1       reinoud  6849:
1.45      reinoud  6850:                nestbuf = getiobuf(NULL, true);
                   6851:                nestiobuf_setup(buf, nestbuf, buf_offset, rbuflen);
                   6852:                /* nestbuf is B_ASYNC */
                   6853:
                   6854:                /* identify this nestbuf */
                   6855:                nestbuf->b_lblkno   = lblkno;
                   6856:                KASSERT(nestbuf->b_vp == udf_node->vnode);
                   6857:
                   6858:                /* CD shedules on raw blkno */
                   6859:                nestbuf->b_blkno      = rblk;
                   6860:                nestbuf->b_proc       = NULL;
                   6861:                nestbuf->b_rawblkno   = rblk;
                   6862:                nestbuf->b_udf_c_type = what;
                   6863:
                   6864:                /* increment our outstanding bufs counter */
                   6865:                s = splbio();
                   6866:                        udf_node->outstanding_bufs++;
                   6867:                splx(s);
1.1       reinoud  6868:
1.45      reinoud  6869:                udf_discstrat_queuebuf(ump, nestbuf);
1.9       christos 6870:        }
1.45      reinoud  6871: out:
                   6872:        /* if we're synchronously writing, wait for the completion */
                   6873:        if ((buf->b_flags & B_ASYNC) == 0)
                   6874:                biowait(buf);
                   6875:
                   6876:        DPRINTF(WRITE, ("\tend of write_filebuf\n"));
                   6877:        free(mapping, M_TEMP);
                   6878:        return;
1.1       reinoud  6879: }
                   6880:
                   6881: /* --------------------------------------------------------------------- */

CVSweb <webmaster@jp.NetBSD.org>