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

          Line data    Source code
       1             : /*      $OpenBSD: udf_vfsops.c,v 1.65 2018/05/02 02:24:55 visa Exp $    */
       2             : 
       3             : /*
       4             :  * Copyright (c) 2001, 2002 Scott Long <scottl@freebsd.org>
       5             :  * All rights reserved.
       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 AND CONTRIBUTORS ``AS IS'' AND
      17             :  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
      18             :  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
      19             :  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
      20             :  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
      21             :  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
      22             :  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
      23             :  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
      24             :  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
      25             :  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
      26             :  * SUCH DAMAGE.
      27             :  *
      28             :  * $FreeBSD: src/sys/fs/udf/udf_vfsops.c,v 1.25 2005/01/25 15:52:03 phk Exp $
      29             :  */
      30             : 
      31             : /*
      32             :  * Ported to OpenBSD by Pedro Martelletto in February 2005.
      33             :  */
      34             : 
      35             : /*
      36             :  * Ok, here's how it goes.  The UDF specs are pretty clear on how each data
      37             :  * structure is made up, but not very clear on how they relate to each other.
      38             :  * Here is the skinny... This demostrates a filesystem with one file in the
      39             :  * root directory.  Subdirectories are treated just as normal files, but they
      40             :  * have File Id Descriptors of their children as their file data.  As for the
      41             :  * Anchor Volume Descriptor Pointer, it can exist in two of the following three
      42             :  * places: sector 256, sector n (the max sector of the disk), or sector
      43             :  * n - 256.  It's a pretty good bet that one will exist at sector 256 though.
      44             :  * One caveat is unclosed CD media.  For that, sector 256 cannot be written,
      45             :  * so the Anchor Volume Descriptor Pointer can exist at sector 512 until the
      46             :  * media is closed.
      47             :  */
      48             : 
      49             : #include <sys/param.h>
      50             : #include <sys/systm.h>
      51             : #include <sys/uio.h>
      52             : #include <sys/buf.h>
      53             : #include <sys/dirent.h>
      54             : #include <sys/fcntl.h>
      55             : #include <sys/kernel.h>
      56             : #include <sys/malloc.h>
      57             : #include <sys/mutex.h>
      58             : #include <sys/mount.h>
      59             : #include <sys/namei.h>
      60             : #include <sys/pool.h>
      61             : #include <sys/proc.h>
      62             : #include <sys/lock.h>
      63             : #include <sys/queue.h>
      64             : #include <sys/vnode.h>
      65             : #include <sys/lock.h>
      66             : #include <sys/endian.h>
      67             : #include <sys/specdev.h>
      68             : 
      69             : #include <crypto/siphash.h>
      70             : 
      71             : #include <isofs/udf/ecma167-udf.h>
      72             : #include <isofs/udf/udf.h>
      73             : #include <isofs/udf/udf_extern.h>
      74             : 
      75             : struct pool udf_trans_pool;
      76             : struct pool unode_pool;
      77             : struct pool udf_ds_pool;
      78             : 
      79             : int udf_find_partmaps(struct umount *, struct logvol_desc *);
      80             : int udf_get_vpartmap(struct umount *, struct part_map_virt *);
      81             : int udf_get_spartmap(struct umount *, struct part_map_spare *);
      82             : int udf_get_mpartmap(struct umount *, struct part_map_meta *);
      83             : int udf_mountfs(struct vnode *, struct mount *, uint32_t, struct proc *);
      84             : 
      85             : const struct vfsops udf_vfsops = {
      86             :         .vfs_fhtovp =           udf_fhtovp,
      87             :         .vfs_init =             udf_init,
      88             :         .vfs_mount =            udf_mount,
      89             :         .vfs_start =            udf_start,
      90             :         .vfs_root =             udf_root,
      91             :         .vfs_quotactl =         udf_quotactl,
      92             :         .vfs_statfs =           udf_statfs,
      93             :         .vfs_sync =             udf_sync,
      94             :         .vfs_unmount =          udf_unmount,
      95             :         .vfs_vget =             udf_vget,
      96             :         .vfs_vptofh =           udf_vptofh,
      97             :         .vfs_sysctl =           udf_sysctl,
      98             :         .vfs_checkexp =         udf_checkexp,
      99             : };
     100             : 
     101             : int
     102           0 : udf_init(struct vfsconf *foo)
     103             : {
     104           0 :         pool_init(&udf_trans_pool, MAXNAMLEN * sizeof(unicode_t), 0, IPL_NONE,
     105             :             PR_WAITOK, "udftrpl", NULL);
     106           0 :         pool_init(&unode_pool, sizeof(struct unode), 0, IPL_NONE,
     107             :             PR_WAITOK, "udfndpl", NULL);
     108           0 :         pool_init(&udf_ds_pool, sizeof(struct udf_dirstream), 0, IPL_NONE,
     109             :             PR_WAITOK, "udfdspl", NULL);
     110             : 
     111           0 :         return (0);
     112             : }
     113             : 
     114             : int
     115           0 : udf_start(struct mount *mp, int flags, struct proc *p)
     116             : {
     117           0 :         return (0);
     118             : }
     119             : 
     120             : int
     121           0 : udf_mount(struct mount *mp, const char *path, void *data,
     122             :     struct nameidata *ndp,  struct proc *p)
     123             : {
     124             :         struct vnode *devvp;    /* vnode of the mount device */
     125           0 :         struct udf_args *args = data;
     126           0 :         char fspec[MNAMELEN];
     127             :         int error;
     128             : 
     129           0 :         if ((mp->mnt_flag & MNT_RDONLY) == 0) {
     130           0 :                 mp->mnt_flag |= MNT_RDONLY;
     131             : #ifdef UDF_DEBUG
     132             :                 printf("udf_mount: enforcing read-only mode\n");
     133             : #endif
     134           0 :         }
     135             : 
     136             :         /*
     137             :          * No root filesystem support.  Probably not a big deal, since the
     138             :          * bootloader doesn't understand UDF.
     139             :          */
     140           0 :         if (mp->mnt_flag & MNT_ROOTFS)
     141           0 :                 return (EOPNOTSUPP);
     142             : 
     143             :         /*
     144             :          * If updating, check whether changing from read-only to
     145             :          * read/write; if there is no device name, that's all we do.
     146             :          */
     147           0 :         if (mp->mnt_flag & MNT_UPDATE) {
     148           0 :                 return (0);
     149             :         }
     150             : 
     151           0 :         error = copyinstr(args->fspec, fspec, sizeof(fspec), NULL);
     152           0 :         if (error)
     153           0 :                 return (error);
     154             : 
     155           0 :         NDINIT(ndp, LOOKUP, FOLLOW, UIO_SYSSPACE, fspec, p);
     156           0 :         if ((error = namei(ndp)))
     157           0 :                 return (error);
     158             : 
     159           0 :         devvp = ndp->ni_vp;
     160           0 :         if (devvp->v_type != VBLK) {
     161           0 :                 vrele(devvp);
     162           0 :                 return (ENOTBLK);
     163             :         }
     164             : 
     165           0 :         if (major(devvp->v_rdev) >= nblkdev) {
     166           0 :                 vrele(devvp);
     167           0 :                 return (ENXIO);
     168             :         }
     169             : 
     170           0 :         if ((error = udf_mountfs(devvp, mp, args->lastblock, p))) {
     171           0 :                 vrele(devvp);
     172           0 :                 return (error);
     173             :         }
     174             : 
     175             :         /*
     176             :          * Keep a copy of the mount information.
     177             :          */
     178           0 :         bzero(mp->mnt_stat.f_mntonname, MNAMELEN);
     179           0 :         strlcpy(mp->mnt_stat.f_mntonname, path, MNAMELEN);
     180           0 :         bzero(mp->mnt_stat.f_mntfromname, MNAMELEN);
     181           0 :         strlcpy(mp->mnt_stat.f_mntfromname, fspec, MNAMELEN);
     182           0 :         bzero(mp->mnt_stat.f_mntfromspec, MNAMELEN);
     183           0 :         strlcpy(mp->mnt_stat.f_mntfromspec, fspec, MNAMELEN);
     184             : 
     185           0 :         return (0);
     186           0 : };
     187             : 
     188             : /*
     189             :  * Check the descriptor tag for both the correct id and correct checksum.
     190             :  * Return zero if all is good, EINVAL if not.
     191             :  */
     192             : int
     193           0 : udf_checktag(struct desc_tag *tag, uint16_t id)
     194             : {
     195             :         uint8_t *itag;
     196             :         uint8_t i, cksum = 0;
     197             : 
     198           0 :         itag = (uint8_t *)tag;
     199             : 
     200           0 :         if (letoh16(tag->id) != id)
     201           0 :                 return (EINVAL);
     202             : 
     203           0 :         for (i = 0; i < 15; i++)
     204           0 :                 cksum = cksum + itag[i];
     205           0 :         cksum = cksum - itag[4];
     206             : 
     207           0 :         if (cksum == tag->cksum)
     208           0 :                 return (0);
     209             : 
     210           0 :         return (EINVAL);
     211           0 : }
     212             : 
     213             : int
     214           0 : udf_mountfs(struct vnode *devvp, struct mount *mp, uint32_t lb, struct proc *p)
     215             : {
     216           0 :         struct buf *bp = NULL;
     217           0 :         struct anchor_vdp avdp;
     218             :         struct umount *ump = NULL;
     219             :         struct part_desc *pd;
     220             :         struct logvol_desc *lvd;
     221             :         struct fileset_desc *fsd;
     222             :         struct extfile_entry *xfentry;
     223             :         struct file_entry *fentry;
     224           0 :         uint32_t sector, size, mvds_start, mvds_end;
     225             :         uint32_t fsd_offset = 0;
     226             :         uint16_t part_num = 0, fsd_part = 0;
     227             :         int error = EINVAL;
     228             :         int logvol_found = 0, part_found = 0, fsd_found = 0;
     229             :         int bsize;
     230             : 
     231             :         /*
     232             :          * Disallow multiple mounts of the same device.
     233             :          * Disallow mounting of a device that is currently in use
     234             :          * (except for root, which might share swap device for miniroot).
     235             :          * Flush out any old buffers remaining from a previous use.
     236             :          */
     237           0 :         if ((error = vfs_mountedon(devvp)))
     238           0 :                 return (error);
     239           0 :         if (vcount(devvp) > 1 && devvp != rootvp)
     240           0 :                 return (EBUSY);
     241           0 :         vn_lock(devvp, LK_EXCLUSIVE | LK_RETRY);
     242           0 :         error = vinvalbuf(devvp, V_SAVE, p->p_ucred, p, 0, 0);
     243           0 :         VOP_UNLOCK(devvp);
     244           0 :         if (error)
     245           0 :                 return (error);
     246             : 
     247           0 :         error = VOP_OPEN(devvp, FREAD, FSCRED, p);
     248           0 :         if (error)
     249           0 :                 return (error);
     250             : 
     251           0 :         ump = malloc(sizeof(*ump), M_UDFMOUNT, M_WAITOK | M_ZERO);
     252             : 
     253           0 :         mp->mnt_data = ump;
     254           0 :         mp->mnt_stat.f_fsid.val[0] = devvp->v_rdev;
     255           0 :         mp->mnt_stat.f_fsid.val[1] = mp->mnt_vfc->vfc_typenum;
     256           0 :         mp->mnt_stat.f_namemax = NAME_MAX;
     257           0 :         mp->mnt_flag |= MNT_LOCAL;
     258             : 
     259           0 :         ump->um_mountp = mp;
     260           0 :         ump->um_dev = devvp->v_rdev;
     261           0 :         ump->um_devvp = devvp;
     262             : 
     263             :         bsize = 2048;   /* Should probe the media for its size. */
     264             : 
     265             :         /* 
     266             :          * Get the Anchor Volume Descriptor Pointer from sector 256.
     267             :          * Should also check sector n - 256, n, and 512.
     268             :          */
     269           0 :         sector = 256;
     270           0 :         if ((error = bread(devvp, sector * btodb(bsize), bsize, &bp)) != 0)
     271             :                 goto bail;
     272           0 :         if ((error = udf_checktag((struct desc_tag *)bp->b_data, TAGID_ANCHOR)))
     273             :                 goto bail;
     274             : 
     275           0 :         bcopy(bp->b_data, &avdp, sizeof(struct anchor_vdp));
     276           0 :         brelse(bp);
     277           0 :         bp = NULL;
     278             : 
     279             :         /*
     280             :          * Extract the Partition Descriptor and Logical Volume Descriptor
     281             :          * from the Volume Descriptor Sequence.
     282             :          * Should we care about the partition type right now?
     283             :          * What about multiple partitions?
     284             :          */
     285           0 :         mvds_start = letoh32(avdp.main_vds_ex.loc);
     286           0 :         mvds_end = mvds_start + (letoh32(avdp.main_vds_ex.len) - 1) / bsize;
     287           0 :         for (sector = mvds_start; sector < mvds_end; sector++) {
     288           0 :                 if ((error = bread(devvp, sector * btodb(bsize), bsize, 
     289           0 :                                    &bp)) != 0) {
     290           0 :                         printf("Can't read sector %d of VDS\n", sector);
     291           0 :                         goto bail;
     292             :                 }
     293           0 :                 lvd = (struct logvol_desc *)bp->b_data;
     294           0 :                 if (!udf_checktag(&lvd->tag, TAGID_LOGVOL)) {
     295           0 :                         ump->um_bsize = letoh32(lvd->lb_size);
     296           0 :                         ump->um_bmask = ump->um_bsize - 1;
     297           0 :                         ump->um_bshift = ffs(ump->um_bsize) - 1;
     298           0 :                         fsd_part = letoh16(lvd->_lvd_use.fsd_loc.loc.part_num);
     299           0 :                         fsd_offset = letoh32(lvd->_lvd_use.fsd_loc.loc.lb_num);
     300           0 :                         if (udf_find_partmaps(ump, lvd))
     301             :                                 break;
     302             :                         logvol_found = 1;
     303           0 :                 }
     304           0 :                 pd = (struct part_desc *)bp->b_data;
     305           0 :                 if (!udf_checktag(&pd->tag, TAGID_PARTITION)) {
     306             :                         part_found = 1;
     307           0 :                         part_num = letoh16(pd->part_num);
     308           0 :                         ump->um_len = ump->um_reallen = letoh32(pd->part_len);
     309           0 :                         ump->um_start = ump->um_realstart = letoh32(pd->start_loc);
     310           0 :                 }
     311             : 
     312           0 :                 brelse(bp); 
     313           0 :                 bp = NULL;
     314           0 :                 if ((part_found) && (logvol_found))
     315             :                         break;
     316             :         }
     317             : 
     318           0 :         if (!part_found || !logvol_found) {
     319             :                 error = EINVAL;
     320           0 :                 goto bail;
     321             :         }
     322             : 
     323           0 :         if (ISSET(ump->um_flags, UDF_MNT_USES_META)) {
     324             :                 /* Read Metadata File 'File Entry' to find Metadata file. */
     325             :                 struct long_ad *la;
     326           0 :                 sector = ump->um_start + ump->um_meta_start; /* Set in udf_get_mpartmap() */
     327           0 :                 if ((error = RDSECTOR(devvp, sector, ump->um_bsize, &bp)) != 0) {
     328           0 :                         printf("Cannot read sector %d for Metadata File Entry\n", sector);
     329             :                         error = EINVAL;
     330           0 :                         goto bail;
     331             :                 }
     332           0 :                 xfentry = (struct extfile_entry *)bp->b_data;
     333           0 :                 fentry = (struct file_entry *)bp->b_data;
     334           0 :                 if (udf_checktag(&xfentry->tag, TAGID_EXTFENTRY) == 0)
     335           0 :                         la = (struct long_ad *)&xfentry->data[letoh32(xfentry->l_ea)];
     336           0 :                 else if (udf_checktag(&fentry->tag, TAGID_FENTRY) == 0)
     337           0 :                         la = (struct long_ad *)&fentry->data[letoh32(fentry->l_ea)];
     338             :                 else {
     339           0 :                         printf("Invalid Metadata File FE @ sector %d! (tag.id %d)\n",
     340           0 :                             sector, fentry->tag.id);
     341             :                         error = EINVAL;
     342           0 :                         goto bail;
     343             :                 }
     344           0 :                 ump->um_meta_start = letoh32(la->loc.lb_num);
     345           0 :                 ump->um_meta_len = letoh32(la->len);
     346           0 :                 if (bp != NULL) {
     347           0 :                         brelse(bp);
     348           0 :                         bp = NULL;
     349           0 :                 }
     350           0 :         } else if (fsd_part != part_num) {
     351           0 :                 printf("FSD does not lie within the partition!\n");
     352             :                 error = EINVAL;
     353           0 :                 goto bail;
     354             :         }
     355             : 
     356           0 :         mtx_init(&ump->um_hashmtx, IPL_NONE);
     357           0 :         ump->um_hashtbl = hashinit(UDF_HASHTBLSIZE, M_UDFMOUNT, M_WAITOK,
     358           0 :             &ump->um_hashsz);
     359           0 :         arc4random_buf(&ump->um_hashkey, sizeof(ump->um_hashkey));
     360             : 
     361             :         /* Get the VAT, if needed */
     362           0 :         if (ump->um_flags & UDF_MNT_FIND_VAT) {
     363           0 :                 error = udf_vat_get(ump, lb);
     364           0 :                 if (error)
     365             :                         goto bail;
     366             :         }
     367             : 
     368             :         /*
     369             :          * Grab the Fileset Descriptor
     370             :          * Thanks to Chuck McCrobie <mccrobie@cablespeed.com> for pointing
     371             :          * me in the right direction here.
     372             :          */
     373             : 
     374           0 :         if (ISSET(ump->um_flags, UDF_MNT_USES_META))
     375           0 :                 sector = ump->um_meta_start; 
     376             :         else
     377           0 :                 sector = fsd_offset;
     378           0 :         udf_vat_map(ump, &sector);
     379           0 :         if ((error = RDSECTOR(devvp, sector, ump->um_bsize, &bp)) != 0) {
     380           0 :                 printf("Cannot read sector %d of FSD\n", sector);
     381           0 :                 goto bail;
     382             :         }
     383           0 :         fsd = (struct fileset_desc *)bp->b_data;
     384           0 :         if (!udf_checktag(&fsd->tag, TAGID_FSD)) {
     385             :                 fsd_found = 1;
     386           0 :                 bcopy(&fsd->rootdir_icb, &ump->um_root_icb,
     387             :                     sizeof(struct long_ad));
     388           0 :                 if (ISSET(ump->um_flags, UDF_MNT_USES_META)) {
     389           0 :                         ump->um_root_icb.loc.lb_num += ump->um_meta_start; 
     390           0 :                         ump->um_root_icb.loc.part_num = part_num;
     391           0 :                 }
     392             :         }
     393             : 
     394           0 :         brelse(bp);
     395           0 :         bp = NULL;
     396             : 
     397           0 :         if (!fsd_found) {
     398           0 :                 printf("Couldn't find the fsd\n");
     399             :                 error = EINVAL;
     400           0 :                 goto bail;
     401             :         }
     402             : 
     403             :         /*
     404             :          * Find the file entry for the root directory.
     405             :          */
     406           0 :         sector = letoh32(ump->um_root_icb.loc.lb_num);
     407           0 :         size = letoh32(ump->um_root_icb.len);
     408           0 :         udf_vat_map(ump, &sector);
     409           0 :         if ((error = udf_readlblks(ump, sector, size, &bp)) != 0) {
     410           0 :                 printf("Cannot read sector %d\n", sector);
     411           0 :                 goto bail;
     412             :         }
     413             : 
     414           0 :         xfentry = (struct extfile_entry *)bp->b_data;
     415           0 :         fentry = (struct file_entry *)bp->b_data;
     416           0 :         error = udf_checktag(&xfentry->tag, TAGID_EXTFENTRY);
     417           0 :         if (error) {
     418           0 :                 error = udf_checktag(&fentry->tag, TAGID_FENTRY);
     419           0 :                 if (error) {
     420           0 :                         printf("Invalid root file entry!\n");
     421           0 :                         goto bail;
     422             :                 }
     423             :         }
     424             : 
     425           0 :         brelse(bp);
     426           0 :         bp = NULL;
     427             : 
     428           0 :         devvp->v_specmountpoint = mp;
     429             : 
     430           0 :         return (0);
     431             : 
     432             : bail:
     433           0 :         if (ump != NULL) {
     434           0 :                 hashfree(ump->um_hashtbl, UDF_HASHTBLSIZE, M_UDFMOUNT);
     435           0 :                 free(ump, M_UDFMOUNT, 0);
     436           0 :                 mp->mnt_data = NULL;
     437           0 :                 mp->mnt_flag &= ~MNT_LOCAL;
     438           0 :         }
     439           0 :         if (devvp->v_specinfo)
     440           0 :                 devvp->v_specmountpoint = NULL;
     441           0 :         if (bp != NULL)
     442           0 :                 brelse(bp);
     443             : 
     444           0 :         vn_lock(devvp, LK_EXCLUSIVE|LK_RETRY);
     445           0 :         VOP_CLOSE(devvp, FREAD, FSCRED, p);
     446           0 :         VOP_UNLOCK(devvp);
     447             : 
     448           0 :         return (error);
     449           0 : }
     450             : 
     451             : int
     452           0 : udf_unmount(struct mount *mp, int mntflags, struct proc *p)
     453             : {
     454             :         struct umount *ump;
     455             :         struct vnode *devvp;
     456             :         int error, flags = 0;
     457             : 
     458           0 :         ump = VFSTOUDFFS(mp);
     459           0 :         devvp = ump->um_devvp;
     460             : 
     461           0 :         if (mntflags & MNT_FORCE)
     462           0 :                 flags |= FORCECLOSE;
     463             : 
     464           0 :         if ((error = vflush(mp, NULL, flags)))
     465           0 :                 return (error);
     466             : 
     467           0 :         vn_lock(devvp, LK_EXCLUSIVE | LK_RETRY);
     468           0 :         vinvalbuf(devvp, V_SAVE, NOCRED, p, 0, 0);
     469           0 :         (void)VOP_CLOSE(devvp, FREAD, NOCRED, p);
     470           0 :         VOP_UNLOCK(devvp);
     471             : 
     472           0 :         devvp->v_specmountpoint = NULL;
     473           0 :         vrele(devvp);
     474             : 
     475           0 :         if (ump->um_flags & UDF_MNT_USES_VAT)
     476           0 :                 free(ump->um_vat, M_UDFMOUNT, 0);
     477             : 
     478           0 :         if (ump->um_stbl != NULL)
     479           0 :                 free(ump->um_stbl, M_UDFMOUNT, 0);
     480             : 
     481           0 :         hashfree(ump->um_hashtbl, UDF_HASHTBLSIZE, M_UDFMOUNT);
     482           0 :         free(ump, M_UDFMOUNT, 0);
     483             : 
     484           0 :         mp->mnt_data = NULL;
     485           0 :         mp->mnt_flag &= ~MNT_LOCAL;
     486             : 
     487           0 :         return (0);
     488           0 : }
     489             : 
     490             : int
     491           0 : udf_root(struct mount *mp, struct vnode **vpp)
     492             : {
     493             :         struct umount *ump;
     494             :         struct vnode *vp;
     495             :         udfino_t id;
     496             :         int error;
     497             : 
     498           0 :         ump = VFSTOUDFFS(mp);
     499             : 
     500           0 :         id = udf_getid(&ump->um_root_icb);
     501             : 
     502           0 :         error = udf_vget(mp, id, vpp);
     503           0 :         if (error)
     504           0 :                 return (error);
     505             : 
     506           0 :         vp = *vpp;
     507           0 :         vp->v_flag |= VROOT;
     508             : 
     509           0 :         return (0);
     510           0 : }
     511             : 
     512             : int
     513           0 : udf_quotactl(struct mount *mp, int cmds, uid_t uid, caddr_t arg,
     514             :     struct proc *p)
     515             : {
     516           0 :         return (EOPNOTSUPP);
     517             : }
     518             : 
     519             : int
     520           0 : udf_statfs(struct mount *mp, struct statfs *sbp, struct proc *p)
     521             : {
     522             :         struct umount *ump;
     523             : 
     524           0 :         ump = VFSTOUDFFS(mp);
     525             : 
     526           0 :         sbp->f_bsize = ump->um_bsize;
     527           0 :         sbp->f_iosize = ump->um_bsize;
     528           0 :         sbp->f_blocks = ump->um_len;
     529           0 :         sbp->f_bfree = 0;
     530           0 :         sbp->f_bavail = 0;
     531           0 :         sbp->f_files = 0;
     532           0 :         sbp->f_ffree = 0;
     533           0 :         sbp->f_favail = 0;
     534           0 :         copy_statfs_info(sbp, mp);
     535             : 
     536           0 :         return (0);
     537             : }
     538             : 
     539             : int
     540           0 : udf_sync(struct mount *mp, int waitfor, int stall, struct ucred *cred, struct proc *p)
     541             : {
     542           0 :         return (0);
     543             : }
     544             : 
     545             : int
     546           0 : udf_vget(struct mount *mp, ino_t ino, struct vnode **vpp)
     547             : {
     548           0 :         struct buf *bp;
     549             :         struct vnode *devvp;
     550             :         struct umount *ump;
     551             :         struct proc *p;
     552           0 :         struct vnode *vp, *nvp;
     553             :         struct unode *up;
     554             :         struct extfile_entry *xfe;
     555             :         struct file_entry *fe;
     556           0 :         uint32_t sector;
     557             :         int error, size;
     558             : 
     559           0 :         if (ino > (udfino_t)-1)
     560           0 :                 panic("udf_vget: alien ino_t %llu", (unsigned long long)ino);
     561             : 
     562           0 :         p = curproc;
     563           0 :         bp = NULL;
     564           0 :         *vpp = NULL;
     565           0 :         ump = VFSTOUDFFS(mp);
     566             : 
     567             :         /* See if we already have this in the cache */
     568           0 :         if ((error = udf_hashlookup(ump, ino, LK_EXCLUSIVE, vpp)) != 0)
     569           0 :                 return (error);
     570           0 :         if (*vpp != NULL)
     571           0 :                 return (0);
     572             : 
     573             :         /*
     574             :          * Allocate memory and check the tag id's before grabbing a new
     575             :          * vnode, since it's hard to roll back if there is a problem.
     576             :          */
     577           0 :         up = pool_get(&unode_pool, PR_WAITOK | PR_ZERO);
     578             : 
     579             :         /*
     580             :          * Copy in the file entry.  Per the spec, the size can only be 1 block.
     581             :          */
     582           0 :         sector = ino;
     583           0 :         devvp = ump->um_devvp;
     584           0 :         udf_vat_map(ump, &sector);
     585           0 :         if ((error = RDSECTOR(devvp, sector, ump->um_bsize, &bp)) != 0) {
     586           0 :                 printf("Cannot read sector %d\n", sector);
     587           0 :                 pool_put(&unode_pool, up);
     588           0 :                 if (bp != NULL)
     589           0 :                         brelse(bp);
     590           0 :                 return (error);
     591             :         }
     592             : 
     593           0 :         xfe = (struct extfile_entry *)bp->b_data;
     594           0 :         fe = (struct file_entry *)bp->b_data;
     595           0 :         error = udf_checktag(&xfe->tag, TAGID_EXTFENTRY);
     596           0 :         if (error == 0) {
     597           0 :                 size = letoh32(xfe->l_ea) + letoh32(xfe->l_ad);
     598           0 :         } else {
     599           0 :                 error = udf_checktag(&fe->tag, TAGID_FENTRY);
     600           0 :                 if (error) {
     601           0 :                         printf("Invalid file entry!\n");
     602           0 :                         pool_put(&unode_pool, up);
     603           0 :                         if (bp != NULL)
     604           0 :                                 brelse(bp);
     605           0 :                         return (ENOMEM);
     606             :                 } else
     607           0 :                         size = letoh32(fe->l_ea) + letoh32(fe->l_ad);
     608             :         }
     609             : 
     610             :         /* Allocate max size of FE/XFE. */
     611           0 :         up->u_fentry = malloc(size + UDF_EXTFENTRY_SIZE, M_UDFFENTRY, M_NOWAIT | M_ZERO);
     612           0 :         if (up->u_fentry == NULL) {
     613           0 :                 pool_put(&unode_pool, up);
     614           0 :                 if (bp != NULL)
     615           0 :                         brelse(bp);
     616           0 :                 return (ENOMEM); /* Cannot allocate file entry block */
     617             :         }
     618             : 
     619           0 :         if (udf_checktag(&xfe->tag, TAGID_EXTFENTRY) == 0)
     620           0 :                 bcopy(bp->b_data, up->u_fentry, size + UDF_EXTFENTRY_SIZE);
     621             :         else
     622           0 :                 bcopy(bp->b_data, up->u_fentry, size + UDF_FENTRY_SIZE);
     623             :         
     624           0 :         brelse(bp);
     625           0 :         bp = NULL;
     626             : 
     627           0 :         if ((error = udf_allocv(mp, &vp, p))) {
     628           0 :                 free(up->u_fentry, M_UDFFENTRY, 0);
     629           0 :                 pool_put(&unode_pool, up);
     630           0 :                 return (error); /* Error from udf_allocv() */
     631             :         }
     632             : 
     633           0 :         up->u_vnode = vp;
     634           0 :         up->u_ino = ino;
     635           0 :         up->u_devvp = ump->um_devvp;
     636           0 :         up->u_dev = ump->um_dev;
     637           0 :         up->u_ump = ump;
     638           0 :         vp->v_data = up;
     639           0 :         vref(ump->um_devvp);
     640             : 
     641           0 :         rrw_init_flags(&up->u_lock, "unode", RWL_DUPOK | RWL_IS_VNODE);
     642             : 
     643             :         /*
     644             :          * udf_hashins() will lock the vnode for us.
     645             :          */
     646           0 :         udf_hashins(up);
     647             : 
     648           0 :         switch (up->u_fentry->icbtag.file_type) {
     649             :         default:
     650           0 :                 printf("Unrecognized file type (%d)\n", vp->v_type);
     651           0 :                 vp->v_type = VREG;
     652           0 :                 break;
     653             :         case UDF_ICB_FILETYPE_DIRECTORY:
     654           0 :                 vp->v_type = VDIR;
     655           0 :                 break;
     656             :         case UDF_ICB_FILETYPE_BLOCKDEVICE:
     657           0 :                 vp->v_type = VBLK;
     658           0 :                 break;
     659             :         case UDF_ICB_FILETYPE_CHARDEVICE:
     660           0 :                 vp->v_type = VCHR;
     661           0 :                 break;
     662             :         case UDF_ICB_FILETYPE_FIFO:
     663           0 :                 vp->v_type = VFIFO;
     664           0 :                 break;
     665             :         case UDF_ICB_FILETYPE_SOCKET:
     666           0 :                 vp->v_type = VSOCK;
     667           0 :                 break;
     668             :         case UDF_ICB_FILETYPE_SYMLINK:
     669           0 :                 vp->v_type = VLNK;
     670           0 :                 break;
     671             :         case UDF_ICB_FILETYPE_RANDOMACCESS:
     672             :         case UDF_ICB_FILETYPE_REALTIME:
     673             :         case UDF_ICB_FILETYPE_UNKNOWN:
     674           0 :                 vp->v_type = VREG;
     675           0 :                 break;
     676             :         }
     677             : 
     678             :         /* check if this is a vnode alias */
     679           0 :         if ((nvp = checkalias(vp, up->u_dev, ump->um_mountp)) != NULL) {
     680           0 :                 printf("found a vnode alias\n");
     681             :                 /*
     682             :                  * Discard unneeded vnode, but save its udf_node.
     683             :                  * Note that the lock is carried over in the udf_node
     684             :                  */
     685           0 :                 nvp->v_data = vp->v_data;
     686           0 :                 vp->v_data = NULL;
     687           0 :                 vp->v_op = &spec_vops;
     688           0 :                 vrele(vp);
     689           0 :                 vgone(vp);
     690             :                 /*
     691             :                  * Reinitialize aliased inode.
     692             :                  */
     693           0 :                 vp = nvp;
     694           0 :                 ump->um_devvp = vp;
     695           0 :         }
     696             : 
     697           0 :         *vpp = vp;
     698             : 
     699           0 :         return (0);
     700           0 : }
     701             : 
     702             : struct ifid {
     703             :         u_short ifid_len;
     704             :         u_short ifid_pad;
     705             :         int     ifid_ino;
     706             :         long    ifid_start;
     707             : };
     708             : 
     709             : int
     710           0 : udf_fhtovp(struct mount *mp, struct fid *fhp, struct vnode **vpp)
     711             : {
     712             :         struct ifid *ifhp;
     713           0 :         struct vnode *nvp;
     714             :         int error;
     715             : 
     716           0 :         ifhp = (struct ifid *)fhp;
     717             : 
     718           0 :         if ((error = VFS_VGET(mp, ifhp->ifid_ino, &nvp)) != 0) {
     719           0 :                 *vpp = NULLVP;
     720           0 :                 return (error);
     721             :         }
     722             : 
     723           0 :         *vpp = nvp;
     724             : 
     725           0 :         return (0);
     726           0 : }
     727             : 
     728             : int
     729           0 : udf_vptofh(struct vnode *vp, struct fid *fhp)
     730             : {
     731             :         struct unode *up;
     732             :         struct ifid *ifhp;
     733             : 
     734           0 :         up = VTOU(vp);
     735           0 :         ifhp = (struct ifid *)fhp;
     736           0 :         ifhp->ifid_len = sizeof(struct ifid);
     737           0 :         ifhp->ifid_ino = up->u_ino;
     738             : 
     739           0 :         return (0);
     740             : }
     741             : 
     742             : int
     743           0 : udf_sysctl(int *name, u_int namelen, void *oldp, size_t *oldlenp, void *newp,
     744             :     size_t newlen, struct proc *p)
     745             : {
     746           0 :         return (EINVAL);
     747             : }
     748             : 
     749             : int
     750           0 : udf_checkexp(struct mount *mp, struct mbuf *nam, int *exflagsp,
     751             :     struct ucred **credanonp)
     752             : {
     753           0 :         return (EACCES); /* For the time being */
     754             : }
     755             : 
     756             : /* Handle a virtual partition map */
     757             : int
     758           0 : udf_get_vpartmap(struct umount *ump, struct part_map_virt *pmv)
     759             : {
     760           0 :         ump->um_flags |= UDF_MNT_FIND_VAT; /* Should do more than this */
     761           0 :         return (0);
     762             : }
     763             : 
     764             : /* Handle a sparable partition map */
     765             : int
     766           0 : udf_get_spartmap(struct umount *ump, struct part_map_spare *pms)
     767             : {
     768           0 :         struct buf *bp;
     769             :         int i, error;
     770             : 
     771           0 :         ump->um_stbl = malloc(letoh32(pms->st_size), M_UDFMOUNT, M_NOWAIT);
     772           0 :         if (ump->um_stbl == NULL)
     773           0 :                 return (ENOMEM);
     774             : 
     775           0 :         bzero(ump->um_stbl, letoh32(pms->st_size));
     776             : 
     777             :         /* Calculate the number of sectors per packet */
     778           0 :         ump->um_psecs = letoh16(pms->packet_len) / ump->um_bsize;
     779             : 
     780           0 :         error = udf_readlblks(ump, letoh32(pms->st_loc[0]),
     781           0 :             letoh32(pms->st_size), &bp);
     782             : 
     783           0 :         if (error) {
     784           0 :                 if (bp != NULL)
     785           0 :                         brelse(bp);
     786           0 :                 free(ump->um_stbl, M_UDFMOUNT, 0);
     787           0 :                 return (error); /* Failed to read sparing table */
     788             :         }
     789             : 
     790           0 :         bcopy(bp->b_data, ump->um_stbl, letoh32(pms->st_size));
     791           0 :         brelse(bp);
     792           0 :         bp = NULL;
     793             : 
     794           0 :         if (udf_checktag(&ump->um_stbl->tag, 0)) {
     795           0 :                 free(ump->um_stbl, M_UDFMOUNT, 0);
     796           0 :                 return (EINVAL); /* Invalid sparing table found */
     797             :         }
     798             : 
     799             :         /*
     800             :          * See how many valid entries there are here. The list is
     801             :          * supposed to be sorted, 0xfffffff0 and higher are not valid.
     802             :          */
     803           0 :         for (i = 0; i < letoh16(ump->um_stbl->rt_l); i++) {
     804           0 :                 ump->um_stbl_len = i;
     805           0 :                 if (letoh32(ump->um_stbl->entries[i].org) >= 0xfffffff0)
     806             :                         break;
     807             :         }
     808             : 
     809           0 :         return (0);
     810           0 : }
     811             : 
     812             : /* Handle a metadata partition map */
     813             : int
     814           0 : udf_get_mpartmap(struct umount *ump, struct part_map_meta *pmm)
     815             : {
     816           0 :         ump->um_flags |= UDF_MNT_USES_META;
     817           0 :         ump->um_meta_start = pmm->meta_file_lbn;
     818           0 :         return (0);
     819             : }
     820             : 
     821             : /* Scan the partition maps */
     822             : int
     823           0 : udf_find_partmaps(struct umount *ump, struct logvol_desc *lvd)
     824             : {
     825             :         struct regid *pmap_id;
     826           0 :         unsigned char regid_id[UDF_REGID_ID_SIZE + 1];
     827             :         int i, ptype, psize, error;
     828           0 :         uint8_t *pmap = (uint8_t *) &lvd->maps[0];
     829             : 
     830           0 :         for (i = 0; i < letoh32(lvd->n_pm); i++) {
     831           0 :                 ptype = pmap[0];
     832           0 :                 psize = pmap[1];
     833             : 
     834           0 :                 if (ptype != 1 && ptype != 2)
     835           0 :                         return (EINVAL); /* Invalid partition map type */
     836             : 
     837           0 :                 if (psize != sizeof(struct part_map_1)  &&
     838           0 :                     psize != sizeof(struct part_map_2))
     839           0 :                         return (EINVAL); /* Invalid partition map size */
     840             : 
     841           0 :                 if (ptype == 1) {
     842           0 :                         pmap += sizeof(struct part_map_1);
     843           0 :                         continue;
     844             :                 }
     845             : 
     846             :                 /* Type 2 map. Find out the details */
     847           0 :                 pmap_id = (struct regid *) &pmap[4];
     848           0 :                 regid_id[UDF_REGID_ID_SIZE] = '\0';
     849           0 :                 bcopy(&pmap_id->id[0], &regid_id[0], UDF_REGID_ID_SIZE);
     850             : 
     851           0 :                 if (!bcmp(&regid_id[0], "*UDF Virtual Partition",
     852             :                     UDF_REGID_ID_SIZE))
     853           0 :                         error = udf_get_vpartmap(ump,
     854           0 :                             (struct part_map_virt *) pmap);
     855           0 :                 else if (!bcmp(&regid_id[0], "*UDF Sparable Partition",
     856             :                     UDF_REGID_ID_SIZE))
     857           0 :                         error = udf_get_spartmap(ump,
     858           0 :                             (struct part_map_spare *) pmap);
     859           0 :                 else if (!bcmp(&regid_id[0], "*UDF Metadata Partition",
     860             :                     UDF_REGID_ID_SIZE))
     861           0 :                         error = udf_get_mpartmap(ump,
     862           0 :                             (struct part_map_meta *) pmap);
     863             :                 else
     864           0 :                         return (EINVAL); /* Unsupported partition map */
     865             : 
     866           0 :                 if (error)
     867           0 :                         return (error); /* Error getting partition */
     868             : 
     869           0 :                 pmap += sizeof(struct part_map_2);
     870           0 :         }
     871             : 
     872           0 :         return (0);
     873           0 : }

Generated by: LCOV version 1.13