[BACK]Return to udf_subr.c CVS log [TXT][DIR] Up to [local] / sys / isofs / udf

Annotation of sys/isofs/udf/udf_subr.c, Revision 1.1.1.1

1.1       nbrk        1: /*     $OpenBSD: udf_subr.c,v 1.13 2007/06/08 05:35:32 deraadt Exp $   */
                      2:
                      3: /*
                      4:  * Copyright (c) 2006, Miodrag Vallat
                      5:  * Copyright (c) 2006, Pedro Martelletto
                      6:  *
                      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.
                     15:  *
                     16:  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
                     17:  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
                     18:  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
                     19:  * DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
                     20:  * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
                     21:  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
                     22:  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
                     23:  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
                     24:  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
                     25:  * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
                     26:  * POSSIBILITY OF SUCH DAMAGE.
                     27:  */
                     28:
                     29: #include <sys/param.h>
                     30: #include <sys/systm.h>
                     31: #include <sys/buf.h>
                     32: #include <sys/kernel.h>
                     33: #include <sys/malloc.h>
                     34: #include <sys/mutex.h>
                     35: #include <sys/stat.h>
                     36: #include <sys/mount.h>
                     37: #include <sys/vnode.h>
                     38: #include <sys/dirent.h>
                     39: #include <sys/unistd.h>
                     40: #include <sys/disklabel.h>
                     41:
                     42: #include <isofs/udf/ecma167-udf.h>
                     43: #include <isofs/udf/udf.h>
                     44: #include <isofs/udf/udf_extern.h>
                     45:
                     46: int udf_vat_read(struct umount *, uint32_t *);
                     47:
                     48: /*
                     49:  * Convert a CS0 dstring to a 16-bit Unicode string.
                     50:  * Returns the length of the Unicode string, in unicode characters (not
                     51:  * bytes!), or -1 if an error arises.
                     52:  * Note that the transname destination buffer is expected to be large
                     53:  * enough to hold the result, and will not be terminated in any way.
                     54:  */
                     55: int
                     56: udf_rawnametounicode(u_int len, char *cs0string, unicode_t *transname)
                     57: {
                     58:        unicode_t *origname = transname;
                     59:
                     60:        if (len-- == 0)
                     61:                return (-1);
                     62:
                     63:        switch (*cs0string++) {
                     64:        case 8:         /* bytes string */
                     65:                while (len-- != 0)
                     66:                        *transname++ = (unicode_t)*cs0string++;
                     67:                break;
                     68:        case 16:        /* 16 bit unicode string */
                     69:                if (len & 1)
                     70:                        return (-1);
                     71:                len >>= 1;
                     72:                while (len-- != 0) {
                     73:                        unicode_t tmpchar;
                     74:
                     75:                        tmpchar = (unicode_t)*cs0string++;
                     76:                        tmpchar = (tmpchar << 8) | (unicode_t)*cs0string++;
                     77:                        *transname++ = tmpchar;
                     78:                }
                     79:                break;
                     80:        default:
                     81:                return (-1);
                     82:        }
                     83:
                     84:        return (transname - origname);
                     85: }
                     86:
                     87: /*
                     88:  * Do a lazy probe on the underlying media to check if it's a UDF volume, in
                     89:  * which case we fake a disk label for it.
                     90:  */
                     91: int
                     92: udf_disklabelspoof(dev_t dev, void (*strat)(struct buf *),
                     93:     struct disklabel *lp)
                     94: {
                     95:        char vid[32];
                     96:        int i, bsize = 2048, error = EINVAL;
                     97:        uint32_t sector = 256, mvds_start, mvds_end;
                     98:        struct buf *bp;
                     99:        struct anchor_vdp avdp;
                    100:        struct pri_vol_desc *pvd;
                    101:
                    102:        /*
                    103:         * Get a buffer to work with.
                    104:         */
                    105:        bp = geteblk(bsize);
                    106:        bp->b_dev = dev;
                    107:
                    108:        /*
                    109:         * Look for an Anchor Volume Descriptor at sector 256.
                    110:         */
                    111:        bp->b_blkno = sector * btodb(bsize);
                    112:        bp->b_bcount = bsize;
                    113:        bp->b_flags = B_BUSY | B_READ;
                    114:        bp->b_resid = bp->b_blkno / lp->d_secpercyl;
                    115:
                    116:        (*strat)(bp);
                    117:        if (biowait(bp))
                    118:                goto out;
                    119:
                    120:        if (udf_checktag((struct desc_tag *)bp->b_data, TAGID_ANCHOR))
                    121:                goto out;
                    122:
                    123:        bcopy(bp->b_data, &avdp, sizeof(avdp));
                    124:        mvds_start = letoh32(avdp.main_vds_ex.loc);
                    125:        mvds_end = mvds_start + (letoh32(avdp.main_vds_ex.len) - 1) / bsize;
                    126:
                    127:        /*
                    128:         * Then try to find a reference to a Primary Volume Descriptor.
                    129:         */
                    130:        for (sector = mvds_start; sector < mvds_end; sector++) {
                    131:                bp->b_blkno = sector * btodb(bsize);
                    132:                bp->b_bcount = bsize;
                    133:                bp->b_flags = B_BUSY | B_READ;
                    134:                bp->b_resid = bp->b_blkno / lp->d_secpercyl;
                    135:
                    136:                (*strat)(bp);
                    137:                if (biowait(bp))
                    138:                        goto out;
                    139:
                    140:                pvd = (struct pri_vol_desc *)bp->b_data;
                    141:                if (!udf_checktag(&pvd->tag, TAGID_PRI_VOL))
                    142:                        break;
                    143:        }
                    144:
                    145:        /*
                    146:         * If we couldn't find a reference, bail out.
                    147:         */
                    148:        if (sector == mvds_end)
                    149:                goto out;
                    150:
                    151:        /*
                    152:         * Okay, it's a UDF volume. Spoof a disk label for it.
                    153:         */
                    154:        if (udf_transname(pvd->vol_id, vid, sizeof(pvd->vol_id) - 1, NULL))
                    155:                strlcpy(lp->d_typename, vid, sizeof(lp->d_typename));
                    156:
                    157:        for (i = 0; i < MAXPARTITIONS; i++) {
                    158:                DL_SETPSIZE(&lp->d_partitions[i], 0);
                    159:                DL_SETPOFFSET(&lp->d_partitions[i], 0);
                    160:        }
                    161:
                    162:        /*
                    163:         * Fake two partitions, 'a' and 'c'.
                    164:         */
                    165:        DL_SETPSIZE(&lp->d_partitions[0], DL_GETDSIZE(lp));
                    166:        lp->d_partitions[0].p_fstype = FS_UDF;
                    167:        DL_SETPSIZE(&lp->d_partitions[RAW_PART], DL_GETDSIZE(lp));
                    168:        lp->d_partitions[RAW_PART].p_fstype = FS_UDF;
                    169:        lp->d_npartitions = RAW_PART + 1;
                    170:        lp->d_version = 1;
                    171:
                    172:        lp->d_bbsize = 8192;    /* Fake. */
                    173:        lp->d_sbsize = 64*1024; /* Fake. */
                    174:        lp->d_magic = DISKMAGIC;
                    175:        lp->d_magic2 = DISKMAGIC;
                    176:        lp->d_checksum = dkcksum(lp);
                    177:
                    178:        error = 0;
                    179: out:
                    180:        bp->b_flags |= B_INVAL;
                    181:        brelse(bp);
                    182:
                    183:        return (error);
                    184: }
                    185:
                    186: /* Get a vnode for the Virtual Allocation Table (VAT) */
                    187: int
                    188: udf_vat_get(struct umount *ump, uint32_t lb)
                    189: {
                    190:        struct vnode *vp;
                    191:        struct unode *up;
                    192:        int error;
                    193:
                    194:        error = udf_vget(ump->um_mountp, lb - ump->um_start - 3, &vp);
                    195:        if (error)
                    196:                return (error);
                    197:
                    198:        up = VTOU(vp);
                    199:        up->u_vatlen = (letoh64(up->u_fentry->inf_len) - 36) >> 2;
                    200:
                    201:        ump->um_vat = malloc(sizeof(struct unode), M_UDFMOUNT, M_WAITOK);
                    202:        *ump->um_vat = *up;
                    203:
                    204:        ump->um_flags &= ~UDF_MNT_FIND_VAT;
                    205:        ump->um_flags |=  UDF_MNT_USES_VAT;
                    206:
                    207:        vput(vp);
                    208:
                    209:        return (0);
                    210: }
                    211:
                    212: /* Look up a sector in the VAT */
                    213: int
                    214: udf_vat_map(struct umount *ump, uint32_t *sector)
                    215: {
                    216:        /* If there's no VAT, then it's easy */
                    217:        if (!(ump->um_flags & UDF_MNT_USES_VAT)) {
                    218:                *sector += ump->um_start;
                    219:                return (0);
                    220:        }
                    221:
                    222:        /* Sanity check the given sector */
                    223:        if (*sector >= ump->um_vat->u_vatlen)
                    224:                return (EINVAL);
                    225:
                    226:        return (udf_vat_read(ump, sector));
                    227: }
                    228:
                    229: /* Read from the VAT */
                    230: int
                    231: udf_vat_read(struct umount *ump, uint32_t *sector)
                    232: {
                    233:        struct buf *bp;
                    234:        uint8_t *data;
                    235:        int error, size;
                    236:
                    237:        size = 4;
                    238:
                    239:        /*
                    240:         * Note that we rely on the buffer cache to keep frequently accessed
                    241:         * buffers around to avoid reading them from the disk all the time.
                    242:         */
                    243:        error = udf_readatoffset(ump->um_vat, &size, *sector << 2, &bp, &data);
                    244:        if (error) {
                    245:                if (bp != NULL)
                    246:                        brelse(bp);
                    247:
                    248:                return (error);
                    249:        }
                    250:
                    251:        /* Make sure we read at least a whole entry */
                    252:        if (size < 4) {
                    253:                if (bp != NULL)
                    254:                        brelse(bp);
                    255:
                    256:                return (EINVAL);
                    257:        }
                    258:
                    259:        /* Map the sector */
                    260:        *sector = letoh32(*(uint32_t *)data) + ump->um_start;
                    261:
                    262:        brelse(bp);
                    263:
                    264:        return (0);
                    265: }

CVSweb