LCOV - code coverage report
Current view: top level - isofs/udf - udf_subr.c (source / functions) Hit Total Coverage
Test: 6.4 Lines: 0 104 0.0 %
Date: 2018-10-19 03:25:38 Functions: 0 5 0.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /*      $OpenBSD: udf_subr.c,v 1.25 2014/12/16 18:30:03 tedu 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/lock.h>
      39             : #include <sys/dirent.h>
      40             : #include <sys/disklabel.h>
      41             : 
      42             : #include <crypto/siphash.h>
      43             : 
      44             : #include <isofs/udf/ecma167-udf.h>
      45             : #include <isofs/udf/udf.h>
      46             : #include <isofs/udf/udf_extern.h>
      47             : 
      48             : int udf_vat_read(struct umount *, uint32_t *);
      49             : 
      50             : /*
      51             :  * Convert a CS0 dstring to a 16-bit Unicode string.
      52             :  * Returns the length of the Unicode string, in unicode characters (not
      53             :  * bytes!), or -1 if an error arises.
      54             :  * Note that the transname destination buffer is expected to be large
      55             :  * enough to hold the result, and will not be terminated in any way.
      56             :  */
      57             : int
      58           0 : udf_rawnametounicode(u_int len, char *cs0string, unicode_t *transname)
      59             : {
      60             :         unicode_t *origname = transname;
      61             : 
      62           0 :         if (len-- == 0)
      63           0 :                 return (-1);
      64             : 
      65           0 :         switch (*cs0string++) {
      66             :         case 8:         /* bytes string */
      67           0 :                 while (len-- != 0)
      68           0 :                         *transname++ = (unicode_t)*cs0string++;
      69             :                 break;
      70             :         case 16:        /* 16 bit unicode string */
      71           0 :                 if (len & 1)
      72           0 :                         return (-1);
      73           0 :                 len >>= 1;
      74           0 :                 while (len-- != 0) {
      75             :                         unicode_t tmpchar;
      76             : 
      77           0 :                         tmpchar = (unicode_t)*cs0string++;
      78           0 :                         tmpchar = (tmpchar << 8) | (unicode_t)*cs0string++;
      79           0 :                         *transname++ = tmpchar;
      80             :                 }
      81             :                 break;
      82             :         default:
      83           0 :                 return (-1);
      84             :         }
      85             : 
      86           0 :         return (transname - origname);
      87           0 : }
      88             : 
      89             : /*
      90             :  * Do a lazy probe on the underlying media to check if it's a UDF volume, in
      91             :  * which case we fake a disk label for it.
      92             :  */
      93             : int
      94           0 : udf_disklabelspoof(dev_t dev, void (*strat)(struct buf *),
      95             :     struct disklabel *lp)
      96             : {
      97           0 :         char vid[32];
      98             :         int i, bsize = 2048, error = EINVAL;
      99             :         uint32_t sector = 256, mvds_start, mvds_end;
     100             :         struct buf *bp;
     101           0 :         struct anchor_vdp avdp;
     102             :         struct pri_vol_desc *pvd;
     103             : 
     104             :         /*
     105             :          * Get a buffer to work with.
     106             :          */
     107           0 :         bp = geteblk(bsize);
     108           0 :         bp->b_dev = dev;
     109             : 
     110             :         /*
     111             :          * Look for an Anchor Volume Descriptor at sector 256.
     112             :          */
     113           0 :         bp->b_blkno = sector * btodb(bsize);
     114           0 :         bp->b_bcount = bsize;
     115           0 :         CLR(bp->b_flags, B_READ | B_WRITE | B_DONE);
     116           0 :         SET(bp->b_flags, B_BUSY | B_READ | B_RAW);
     117           0 :         bp->b_resid = bp->b_blkno / lp->d_secpercyl;
     118             : 
     119           0 :         (*strat)(bp);
     120           0 :         if (biowait(bp))
     121             :                 goto out;
     122             : 
     123           0 :         if (udf_checktag((struct desc_tag *)bp->b_data, TAGID_ANCHOR))
     124             :                 goto out;
     125             : 
     126           0 :         bcopy(bp->b_data, &avdp, sizeof(avdp));
     127           0 :         mvds_start = letoh32(avdp.main_vds_ex.loc);
     128           0 :         mvds_end = mvds_start + (letoh32(avdp.main_vds_ex.len) - 1) / bsize;
     129             : 
     130             :         /*
     131             :          * Then try to find a reference to a Primary Volume Descriptor.
     132             :          */
     133           0 :         for (sector = mvds_start; sector < mvds_end; sector++) {
     134           0 :                 bp->b_blkno = sector * btodb(bsize);
     135           0 :                 bp->b_bcount = bsize;
     136           0 :                 CLR(bp->b_flags, B_READ | B_WRITE | B_DONE);
     137           0 :                 SET(bp->b_flags, B_BUSY | B_READ | B_RAW);
     138           0 :                 bp->b_resid = bp->b_blkno / lp->d_secpercyl;
     139             : 
     140           0 :                 (*strat)(bp);
     141           0 :                 if (biowait(bp))
     142             :                         goto out;
     143             : 
     144           0 :                 pvd = (struct pri_vol_desc *)bp->b_data;
     145           0 :                 if (!udf_checktag(&pvd->tag, TAGID_PRI_VOL))
     146             :                         break;
     147             :         }
     148             : 
     149             :         /*
     150             :          * If we couldn't find a reference, bail out.
     151             :          */
     152           0 :         if (sector == mvds_end)
     153             :                 goto out;
     154             : 
     155             :         /*
     156             :          * Okay, it's a UDF volume. Spoof a disk label for it.
     157             :          */
     158           0 :         if (udf_transname(pvd->vol_id, vid, sizeof(pvd->vol_id) - 1, NULL))
     159           0 :                 strlcpy(lp->d_typename, vid, sizeof(lp->d_typename));
     160             : 
     161           0 :         for (i = 0; i < MAXPARTITIONS; i++) {
     162           0 :                 DL_SETPSIZE(&lp->d_partitions[i], 0);
     163           0 :                 DL_SETPOFFSET(&lp->d_partitions[i], 0);
     164             :         }
     165             : 
     166             :         /*
     167             :          * Fake two partitions, 'a' and 'c'.
     168             :          */
     169           0 :         DL_SETPSIZE(&lp->d_partitions[0], DL_GETDSIZE(lp));
     170           0 :         lp->d_partitions[0].p_fstype = FS_UDF;
     171           0 :         DL_SETPSIZE(&lp->d_partitions[RAW_PART], DL_GETDSIZE(lp));
     172           0 :         lp->d_partitions[RAW_PART].p_fstype = FS_UDF;
     173           0 :         lp->d_npartitions = MAXPARTITIONS;
     174           0 :         lp->d_version = 1;
     175             : 
     176           0 :         lp->d_bbsize = 8192; /* Fake. */
     177           0 :         lp->d_sbsize = 64*1024;      /* Fake. */
     178           0 :         lp->d_magic = DISKMAGIC;
     179           0 :         lp->d_magic2 = DISKMAGIC;
     180           0 :         lp->d_checksum = dkcksum(lp);
     181             : 
     182           0 :         error = 0;
     183             : out:
     184           0 :         bp->b_flags |= B_INVAL;
     185           0 :         brelse(bp);
     186             : 
     187           0 :         return (error);
     188           0 : }
     189             : 
     190             : /* Get a vnode for the Virtual Allocation Table (VAT) */
     191             : int
     192           0 : udf_vat_get(struct umount *ump, uint32_t lb)
     193             : {
     194           0 :         struct vnode *vp;
     195             :         struct unode *up;
     196             :         int error;
     197             : 
     198           0 :         error = udf_vget(ump->um_mountp, lb - ump->um_start - 3, &vp);
     199           0 :         if (error)
     200           0 :                 return (error);
     201             : 
     202           0 :         up = VTOU(vp);
     203           0 :         up->u_vatlen = (letoh64(up->u_fentry->inf_len) - 36) >> 2;
     204             : 
     205           0 :         ump->um_vat = malloc(sizeof(struct unode), M_UDFMOUNT, M_WAITOK);
     206           0 :        *ump->um_vat = *up;
     207             : 
     208           0 :         ump->um_flags &= ~UDF_MNT_FIND_VAT;
     209           0 :         ump->um_flags |=  UDF_MNT_USES_VAT;
     210             : 
     211           0 :         vput(vp);
     212             : 
     213           0 :         return (0);
     214           0 : }
     215             : 
     216             : /* Look up a sector in the VAT */
     217             : int
     218           0 : udf_vat_map(struct umount *ump, uint32_t *sector)
     219             : {
     220             :         /* If there's no VAT, then it's easy */
     221           0 :         if (!(ump->um_flags & UDF_MNT_USES_VAT)) {
     222           0 :                 *sector += ump->um_start;
     223           0 :                 return (0);
     224             :         }
     225             : 
     226             :         /* Sanity check the given sector */
     227           0 :         if (*sector >= ump->um_vat->u_vatlen)
     228           0 :                 return (EINVAL);
     229             : 
     230           0 :         return (udf_vat_read(ump, sector));
     231           0 : }
     232             : 
     233             : /* Read from the VAT */
     234             : int
     235           0 : udf_vat_read(struct umount *ump, uint32_t *sector)
     236             : {
     237           0 :         struct buf *bp;
     238           0 :         uint8_t *data;
     239           0 :         int error, size;
     240             : 
     241           0 :         size = 4;
     242             : 
     243             :         /*
     244             :          * Note that we rely on the buffer cache to keep frequently accessed
     245             :          * buffers around to avoid reading them from the disk all the time.
     246             :          */
     247           0 :         error = udf_readatoffset(ump->um_vat, &size, *sector << 2, &bp, &data);
     248           0 :         if (error) {
     249           0 :                 if (bp != NULL)
     250           0 :                         brelse(bp);
     251             : 
     252           0 :                 return (error);
     253             :         }
     254             : 
     255             :         /* Make sure we read at least a whole entry */
     256           0 :         if (size < 4) {
     257           0 :                 if (bp != NULL)
     258           0 :                         brelse(bp);
     259             : 
     260           0 :                 return (EINVAL);
     261             :         }
     262             : 
     263             :         /* Map the sector */
     264           0 :         *sector = letoh32(*(uint32_t *)data) + ump->um_start;
     265             : 
     266           0 :         brelse(bp);
     267             : 
     268           0 :         return (0);
     269           0 : }

Generated by: LCOV version 1.13