1
0
mirror of https://git.FreeBSD.org/src.git synced 2025-01-06 13:09:50 +00:00

Import 4.4BSD-Lite2 onto the vendor branch, note that in the kernel, all

files are off the vendor branch, so this should not change anything.

A "U" marker generally means that the file was not changed in between
the 4.4Lite and Lite-2 releases, and does not need a merge.  "C" generally
means that there was a change.
[note, new file: cd9660_mount.h]
This commit is contained in:
Peter Wemm 1996-03-11 19:20:10 +00:00
parent c2f4655726
commit f1b74d01b3
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/vendor/CSRG/dist/; revision=14553
13 changed files with 4587 additions and 0 deletions

47
sys/isofs/cd9660/TODO Normal file
View File

@ -0,0 +1,47 @@
# $NetBSD: TODO,v 1.4 1994/07/19 11:34:48 mycroft Exp $
1) should understand "older", original High Sierra ("CDROM001") type
Not yet. ( I don't have this technical information, yet. )
2) should understand Rock Ridge
Yes, we have follows function.
o Symbolic Link
o Real Name(long name)
o File Attribute
o Time stamp
o uid, gid
o Devices
o Relocated directories
Except follows:
o POSIX device number mapping
There is some preliminary stuff in there that (ab-)uses the mknod
system call, but this needs a writable filesystem
5) should have name translation enabled by mount flag
Yes. we can disable the Rock Ridge Extension by follows option;
"mount -t isofs -o -norrip /dev/cd0d /cdrom"
6) should run as a user process, and not take up kernel space (cdroms
are slow)
Not yet.
7) ECMA support.
Not yet. we need not only a technical spec but also ECMA format
cd-rom itself!
8) Character set change by SVD ( multi SVD support )
Not yet. We should also hack the other part of system as 8 bit
clean. As far as I know, if you export the cdrom by NFS, the client
can access the 8 bit clean (ie. Solaris Japanese with EUC code )

View File

@ -0,0 +1,14 @@
1. Investiate making ISOFS another UFS shared filesystem (ala FFS/MFS/LFS).
Since it was modelled after the inode code, we might be able to merge
them back. It looks like a seperate (but very similar) lookup routine
will be needed due to the associated file stuff.
2. It would be nice to be able to use the vfs_cluster code.
Unfortunately, if the logical block size is smaller than the page size,
it won't work. Also, if throughtput is relatively constant for any
block size (as it is for the HP drive--150kbs) then clustering may not
buy much (or may even hurt when vfs_cluster comes up with a large sync
cluster).
3. Seems like there should be a "notrans" or some such mount option to show
filenames as they really are without lower-casing. Does this make sense?

View File

@ -0,0 +1,102 @@
/*-
* Copyright (c) 1994
* The Regents of the University of California. All rights reserved.
*
* This code is derived from software contributed to Berkeley
* by Pace Willisson (pace@blitz.com). The Rock Ridge Extension
* Support code is derived from software contributed to Berkeley
* by Atsushi Murai (amurai@spec.co.jp).
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the University of
* California, Berkeley and its contributors.
* 4. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* @(#)cd9660_bmap.c 8.4 (Berkeley) 12/5/94
*/
#include <sys/param.h>
#include <sys/namei.h>
#include <sys/buf.h>
#include <sys/file.h>
#include <sys/vnode.h>
#include <sys/mount.h>
#include <isofs/cd9660/iso.h>
#include <isofs/cd9660/cd9660_node.h>
/*
* Bmap converts a the logical block number of a file to its physical block
* number on the disk. The conversion is done by using the logical block
* number to index into the data block (extent) for the file.
*/
int
cd9660_bmap(ap)
struct vop_bmap_args /* {
struct vnode *a_vp;
daddr_t a_bn;
struct vnode **a_vpp;
daddr_t *a_bnp;
int *a_runp;
} */ *ap;
{
struct iso_node *ip = VTOI(ap->a_vp);
daddr_t lblkno = ap->a_bn;
int bshift;
/*
* Check for underlying vnode requests and ensure that logical
* to physical mapping is requested.
*/
if (ap->a_vpp != NULL)
*ap->a_vpp = ip->i_devvp;
if (ap->a_bnp == NULL)
return (0);
/*
* Compute the requested block number
*/
bshift = ip->i_mnt->im_bshift;
*ap->a_bnp = (ip->iso_start + lblkno) << (bshift - DEV_BSHIFT);
/*
* Determine maximum number of readahead blocks following the
* requested block.
*/
if (ap->a_runp) {
int nblk;
nblk = (ip->i_size >> bshift) - (lblkno + 1);
if (nblk <= 0)
*ap->a_runp = 0;
else if (nblk >= (MAXBSIZE >> bshift))
*ap->a_runp = (MAXBSIZE >> bshift) - 1;
else
*ap->a_runp = nblk;
}
return (0);
}

View File

@ -0,0 +1,488 @@
/*-
* Copyright (c) 1989, 1993, 1994
* The Regents of the University of California. All rights reserved.
*
* This code is derived from software contributed to Berkeley
* by Pace Willisson (pace@blitz.com). The Rock Ridge Extension
* Support code is derived from software contributed to Berkeley
* by Atsushi Murai (amurai@spec.co.jp).
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the University of
* California, Berkeley and its contributors.
* 4. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* from: @(#)ufs_lookup.c 7.33 (Berkeley) 5/19/91
*
* @(#)cd9660_lookup.c 8.7 (Berkeley) 5/27/95
*/
#include <sys/param.h>
#include <sys/namei.h>
#include <sys/buf.h>
#include <sys/file.h>
#include <sys/vnode.h>
#include <sys/mount.h>
#include <isofs/cd9660/iso.h>
#include <isofs/cd9660/cd9660_node.h>
#include <isofs/cd9660/iso_rrip.h>
#include <isofs/cd9660/cd9660_rrip.h>
struct nchstats iso_nchstats;
/*
* Convert a component of a pathname into a pointer to a locked inode.
* This is a very central and rather complicated routine.
* If the file system is not maintained in a strict tree hierarchy,
* this can result in a deadlock situation (see comments in code below).
*
* The flag argument is LOOKUP, CREATE, RENAME, or DELETE depending on
* whether the name is to be looked up, created, renamed, or deleted.
* When CREATE, RENAME, or DELETE is specified, information usable in
* creating, renaming, or deleting a directory entry may be calculated.
* If flag has LOCKPARENT or'ed into it and the target of the pathname
* exists, lookup returns both the target and its parent directory locked.
* When creating or renaming and LOCKPARENT is specified, the target may
* not be ".". When deleting and LOCKPARENT is specified, the target may
* be "."., but the caller must check to ensure it does an vrele and iput
* instead of two iputs.
*
* Overall outline of ufs_lookup:
*
* check accessibility of directory
* look for name in cache, if found, then if at end of path
* and deleting or creating, drop it, else return name
* search for name in directory, to found or notfound
* notfound:
* if creating, return locked directory, leaving info on available slots
* else return error
* found:
* if at end of path and deleting, return information to allow delete
* if at end of path and rewriting (RENAME and LOCKPARENT), lock target
* inode and return info to allow rewrite
* if not at end, add name to cache; if at end and neither creating
* nor deleting, add name to cache
*
* NOTE: (LOOKUP | LOCKPARENT) currently returns the parent inode unlocked.
*/
cd9660_lookup(ap)
struct vop_lookup_args /* {
struct vnode *a_dvp;
struct vnode **a_vpp;
struct componentname *a_cnp;
} */ *ap;
{
register struct vnode *vdp; /* vnode for directory being searched */
register struct iso_node *dp; /* inode for directory being searched */
register struct iso_mnt *imp; /* file system that directory is in */
struct buf *bp; /* a buffer of directory entries */
struct iso_directory_record *ep;/* the current directory entry */
int entryoffsetinblock; /* offset of ep in bp's buffer */
int saveoffset; /* offset of last directory entry in dir */
int numdirpasses; /* strategy for directory search */
doff_t endsearch; /* offset to end directory search */
struct vnode *pdp; /* saved dp during symlink work */
struct vnode *tdp; /* returned by cd9660_vget_internal */
u_long bmask; /* block offset mask */
int lockparent; /* 1 => lockparent flag is set */
int wantparent; /* 1 => wantparent or lockparent flag */
int error;
ino_t ino = 0;
int reclen;
u_short namelen;
char altname[NAME_MAX];
int res;
int assoc, len;
char *name;
struct vnode **vpp = ap->a_vpp;
struct componentname *cnp = ap->a_cnp;
struct ucred *cred = cnp->cn_cred;
int flags = cnp->cn_flags;
int nameiop = cnp->cn_nameiop;
struct proc *p = cnp->cn_proc;
bp = NULL;
*vpp = NULL;
vdp = ap->a_dvp;
dp = VTOI(vdp);
imp = dp->i_mnt;
lockparent = flags & LOCKPARENT;
wantparent = flags & (LOCKPARENT|WANTPARENT);
/*
* Check accessiblity of directory.
*/
if (vdp->v_type != VDIR)
return (ENOTDIR);
if (error = VOP_ACCESS(vdp, VEXEC, cred, cnp->cn_proc))
return (error);
if ((flags & ISLASTCN) && (vdp->v_mount->mnt_flag & MNT_RDONLY) &&
(cnp->cn_nameiop == DELETE || cnp->cn_nameiop == RENAME))
return (EROFS);
/*
* We now have a segment name to search for, and a directory to search.
*
* Before tediously performing a linear scan of the directory,
* check the name cache to see if the directory/name pair
* we are looking for is known already.
*/
if (error = cache_lookup(vdp, vpp, cnp)) {
int vpid; /* capability number of vnode */
if (error == ENOENT)
return (error);
#ifdef PARANOID
if ((vdp->v_flag & VROOT) && (flags & ISDOTDOT))
panic("cd9660_lookup: .. through root");
#endif
/*
* Get the next vnode in the path.
* See comment below starting `Step through' for
* an explaination of the locking protocol.
*/
pdp = vdp;
dp = VTOI(*vpp);
vdp = *vpp;
vpid = vdp->v_id;
if (pdp == vdp) {
VREF(vdp);
error = 0;
} else if (flags & ISDOTDOT) {
VOP_UNLOCK(pdp, 0, p);
error = vget(vdp, LK_EXCLUSIVE, p);
if (!error && lockparent && (flags & ISLASTCN))
error = vn_lock(pdp, LK_EXCLUSIVE, p);
} else {
error = vget(vdp, LK_EXCLUSIVE, p);
if (!lockparent || error || !(flags & ISLASTCN))
VOP_UNLOCK(pdp, 0, p);
}
/*
* Check that the capability number did not change
* while we were waiting for the lock.
*/
if (!error) {
if (vpid == vdp->v_id)
return (0);
vput(vdp);
if (lockparent && pdp != vdp && (flags & ISLASTCN))
VOP_UNLOCK(pdp, 0, p);
}
if (error = vn_lock(pdp, LK_EXCLUSIVE, p))
return (error);
vdp = pdp;
dp = VTOI(pdp);
*vpp = NULL;
}
len = cnp->cn_namelen;
name = cnp->cn_nameptr;
/*
* A leading `=' means, we are looking for an associated file
*/
if (assoc = (imp->iso_ftype != ISO_FTYPE_RRIP && *name == ASSOCCHAR)) {
len--;
name++;
}
/*
* If there is cached information on a previous search of
* this directory, pick up where we last left off.
* We cache only lookups as these are the most common
* and have the greatest payoff. Caching CREATE has little
* benefit as it usually must search the entire directory
* to determine that the entry does not exist. Caching the
* location of the last DELETE or RENAME has not reduced
* profiling time and hence has been removed in the interest
* of simplicity.
*/
bmask = imp->im_bmask;
if (nameiop != LOOKUP || dp->i_diroff == 0 ||
dp->i_diroff > dp->i_size) {
entryoffsetinblock = 0;
dp->i_offset = 0;
numdirpasses = 1;
} else {
dp->i_offset = dp->i_diroff;
if ((entryoffsetinblock = dp->i_offset & bmask) &&
(error = VOP_BLKATOFF(vdp, (off_t)dp->i_offset, NULL, &bp)))
return (error);
numdirpasses = 2;
iso_nchstats.ncs_2passes++;
}
endsearch = dp->i_size;
searchloop:
while (dp->i_offset < endsearch) {
/*
* If offset is on a block boundary,
* read the next directory block.
* Release previous if it exists.
*/
if ((dp->i_offset & bmask) == 0) {
if (bp != NULL)
brelse(bp);
if (error =
VOP_BLKATOFF(vdp, (off_t)dp->i_offset, NULL, &bp))
return (error);
entryoffsetinblock = 0;
}
/*
* Get pointer to next entry.
*/
ep = (struct iso_directory_record *)
((char *)bp->b_data + entryoffsetinblock);
reclen = isonum_711(ep->length);
if (reclen == 0) {
/* skip to next block, if any */
dp->i_offset =
(dp->i_offset & ~bmask) + imp->logical_block_size;
continue;
}
if (reclen < ISO_DIRECTORY_RECORD_SIZE)
/* illegal entry, stop */
break;
if (entryoffsetinblock + reclen > imp->logical_block_size)
/* entries are not allowed to cross boundaries */
break;
namelen = isonum_711(ep->name_len);
if (reclen < ISO_DIRECTORY_RECORD_SIZE + namelen)
/* illegal entry, stop */
break;
/*
* Check for a name match.
*/
switch (imp->iso_ftype) {
default:
if ((!(isonum_711(ep->flags)&4)) == !assoc) {
if ((len == 1
&& *name == '.')
|| (flags & ISDOTDOT)) {
if (namelen == 1
&& ep->name[0] == ((flags & ISDOTDOT) ? 1 : 0)) {
/*
* Save directory entry's inode number and
* release directory buffer.
*/
dp->i_ino = isodirino(ep, imp);
goto found;
}
if (namelen != 1
|| ep->name[0] != 0)
goto notfound;
} else if (!(res = isofncmp(name,len,
ep->name,namelen))) {
if (isonum_711(ep->flags)&2)
ino = isodirino(ep, imp);
else
ino = dbtob(bp->b_blkno)
+ entryoffsetinblock;
saveoffset = dp->i_offset;
} else if (ino)
goto foundino;
#ifdef NOSORTBUG /* On some CDs directory entries are not sorted correctly */
else if (res < 0)
goto notfound;
else if (res > 0 && numdirpasses == 2)
numdirpasses++;
#endif
}
break;
case ISO_FTYPE_RRIP:
if (isonum_711(ep->flags)&2)
ino = isodirino(ep, imp);
else
ino = dbtob(bp->b_blkno) + entryoffsetinblock;
dp->i_ino = ino;
cd9660_rrip_getname(ep,altname,&namelen,&dp->i_ino,imp);
if (namelen == cnp->cn_namelen
&& !bcmp(name,altname,namelen))
goto found;
ino = 0;
break;
}
dp->i_offset += reclen;
entryoffsetinblock += reclen;
}
if (ino) {
foundino:
dp->i_ino = ino;
if (saveoffset != dp->i_offset) {
if (lblkno(imp, dp->i_offset) !=
lblkno(imp, saveoffset)) {
if (bp != NULL)
brelse(bp);
if (error = VOP_BLKATOFF(vdp,
(off_t)saveoffset, NULL, &bp))
return (error);
}
entryoffsetinblock = saveoffset & bmask;
ep = (struct iso_directory_record *)
((char *)bp->b_data + entryoffsetinblock);
dp->i_offset = saveoffset;
}
goto found;
}
notfound:
/*
* If we started in the middle of the directory and failed
* to find our target, we must check the beginning as well.
*/
if (numdirpasses == 2) {
numdirpasses--;
dp->i_offset = 0;
endsearch = dp->i_diroff;
goto searchloop;
}
if (bp != NULL)
brelse(bp);
/*
* Insert name into cache (as non-existent) if appropriate.
*/
if (cnp->cn_flags & MAKEENTRY)
cache_enter(vdp, *vpp, cnp);
if (nameiop == CREATE || nameiop == RENAME)
return (EROFS);
return (ENOENT);
found:
if (numdirpasses == 2)
iso_nchstats.ncs_pass2++;
/*
* Found component in pathname.
* If the final component of path name, save information
* in the cache as to where the entry was found.
*/
if ((flags & ISLASTCN) && nameiop == LOOKUP)
dp->i_diroff = dp->i_offset;
/*
* Step through the translation in the name. We do not `iput' the
* directory because we may need it again if a symbolic link
* is relative to the current directory. Instead we save it
* unlocked as "pdp". We must get the target inode before unlocking
* the directory to insure that the inode will not be removed
* before we get it. We prevent deadlock by always fetching
* inodes from the root, moving down the directory tree. Thus
* when following backward pointers ".." we must unlock the
* parent directory before getting the requested directory.
* There is a potential race condition here if both the current
* and parent directories are removed before the `iget' for the
* inode associated with ".." returns. We hope that this occurs
* infrequently since we cannot avoid this race condition without
* implementing a sophisticated deadlock detection algorithm.
* Note also that this simple deadlock detection scheme will not
* work if the file system has any hard links other than ".."
* that point backwards in the directory structure.
*/
pdp = vdp;
/*
* If ino is different from dp->i_ino,
* it's a relocated directory.
*/
if (flags & ISDOTDOT) {
VOP_UNLOCK(pdp, 0, p); /* race to get the inode */
error = cd9660_vget_internal(vdp->v_mount, dp->i_ino, &tdp,
dp->i_ino != ino, ep);
brelse(bp);
if (error) {
vn_lock(pdp, LK_EXCLUSIVE | LK_RETRY, p);
return (error);
}
if (lockparent && (flags & ISLASTCN) &&
(error = vn_lock(pdp, LK_EXCLUSIVE, p))) {
vput(tdp);
return (error);
}
*vpp = tdp;
} else if (dp->i_number == dp->i_ino) {
brelse(bp);
VREF(vdp); /* we want ourself, ie "." */
*vpp = vdp;
} else {
error = cd9660_vget_internal(vdp->v_mount, dp->i_ino, &tdp,
dp->i_ino != ino, ep);
brelse(bp);
if (error)
return (error);
if (!lockparent || !(flags & ISLASTCN))
VOP_UNLOCK(pdp, 0, p);
*vpp = tdp;
}
/*
* Insert name into cache if appropriate.
*/
if (cnp->cn_flags & MAKEENTRY)
cache_enter(vdp, *vpp, cnp);
return (0);
}
/*
* Return buffer with the contents of block "offset" from the beginning of
* directory "ip". If "res" is non-zero, fill it in with a pointer to the
* remaining space in the directory.
*/
int
cd9660_blkatoff(ap)
struct vop_blkatoff_args /* {
struct vnode *a_vp;
off_t a_offset;
char **a_res;
struct buf **a_bpp;
} */ *ap;
{
struct iso_node *ip;
register struct iso_mnt *imp;
struct buf *bp;
daddr_t lbn;
int bsize, error;
ip = VTOI(ap->a_vp);
imp = ip->i_mnt;
lbn = lblkno(imp, ap->a_offset);
bsize = blksize(imp, ip, lbn);
if (error = bread(ap->a_vp, lbn, bsize, NOCRED, &bp)) {
brelse(bp);
*ap->a_bpp = NULL;
return (error);
}
if (ap->a_res)
*ap->a_res = (char *)bp->b_data + blkoff(imp, ap->a_offset);
*ap->a_bpp = bp;
return (0);
}

View File

@ -0,0 +1,51 @@
/*
* Copyright (c) 1995
* The Regents of the University of California. All rights reserved.
*
* This code is derived from software contributed to Berkeley
* by Pace Willisson (pace@blitz.com). The Rock Ridge Extension
* Support code is derived from software contributed to Berkeley
* by Atsushi Murai (amurai@spec.co.jp).
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the University of
* California, Berkeley and its contributors.
* 4. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* @(#)cd9660_mount.h 8.1 (Berkeley) 5/24/95
*/
/*
* Arguments to mount ISO 9660 filesystems.
*/
struct iso_args {
char *fspec; /* block special device to mount */
struct export_args export; /* network export info */
int flags; /* mounting flags, see below */
};
#define ISOFSMNT_NORRIP 0x00000001 /* disable Rock Ridge Ext.*/
#define ISOFSMNT_GENS 0x00000002 /* enable generation numbers */
#define ISOFSMNT_EXTATT 0x00000004 /* enable extended attributes */

View File

@ -0,0 +1,481 @@
/*-
* Copyright (c) 1982, 1986, 1989, 1994, 1995
* The Regents of the University of California. All rights reserved.
*
* This code is derived from software contributed to Berkeley
* by Pace Willisson (pace@blitz.com). The Rock Ridge Extension
* Support code is derived from software contributed to Berkeley
* by Atsushi Murai (amurai@spec.co.jp).
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the University of
* California, Berkeley and its contributors.
* 4. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* @(#)cd9660_node.c 8.8 (Berkeley) 5/22/95
*/
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/mount.h>
#include <sys/proc.h>
#include <sys/file.h>
#include <sys/buf.h>
#include <sys/vnode.h>
#include <sys/kernel.h>
#include <sys/malloc.h>
#include <sys/stat.h>
#include <isofs/cd9660/iso.h>
#include <isofs/cd9660/cd9660_node.h>
#include <isofs/cd9660/cd9660_mount.h>
#include <isofs/cd9660/iso_rrip.h>
/*
* Structures associated with iso_node caching.
*/
struct iso_node **isohashtbl;
u_long isohash;
#define INOHASH(device, inum) (((device) + ((inum)>>12)) & isohash)
struct simplelock cd9660_ihash_slock;
#ifdef ISODEVMAP
struct iso_node **idvhashtbl;
u_long idvhash;
#define DNOHASH(device, inum) (((device) + ((inum)>>12)) & idvhash)
#endif
int prtactive; /* 1 => print out reclaim of active vnodes */
/*
* Initialize hash links for inodes and dnodes.
*/
cd9660_init(vfsp)
struct vfsconf *vfsp;
{
isohashtbl = hashinit(desiredvnodes, M_ISOFSMNT, &isohash);
simple_lock_init(&cd9660_ihash_slock);
#ifdef ISODEVMAP
idvhashtbl = hashinit(desiredvnodes / 8, M_ISOFSMNT, &idvhash);
#endif
}
#ifdef ISODEVMAP
/*
* Enter a new node into the device hash list
*/
struct iso_dnode *
iso_dmap(device, inum, create)
dev_t device;
ino_t inum;
int create;
{
register struct iso_dnode **dpp, *dp, *dq;
dpp = &idvhashtbl[DNOHASH(device, inum)];
for (dp = *dpp;; dp = dp->d_next) {
if (dp == NULL)
return (NULL);
if (inum == dp->i_number && device == dp->i_dev)
return (dp);
if (!create)
return (NULL);
MALLOC(dp, struct iso_dnode *, sizeof(struct iso_dnode), M_CACHE,
M_WAITOK);
dp->i_dev = dev;
dp->i_number = ino;
if (dq = *dpp)
dq->d_prev = dp->d_next;
dp->d_next = dq;
dp->d_prev = dpp;
*dpp = dp;
return (dp);
}
void
iso_dunmap(device)
dev_t device;
{
struct iso_dnode **dpp, *dp, *dq;
for (dpp = idvhashtbl; dpp <= idvhashtbl + idvhash; dpp++) {
for (dp = *dpp; dp != NULL; dp = dq)
dq = dp->d_next;
if (device == dp->i_dev) {
if (dq)
dq->d_prev = dp->d_prev;
*dp->d_prev = dq;
FREE(dp, M_CACHE);
}
}
}
}
#endif
/*
* Use the device/inum pair to find the incore inode, and return a pointer
* to it. If it is in core, but locked, wait for it.
*/
struct vnode *
cd9660_ihashget(dev, inum)
dev_t dev;
ino_t inum;
{
struct proc *p = curproc; /* XXX */
struct iso_node *ip;
struct vnode *vp;
loop:
simple_lock(&cd9660_ihash_slock);
for (ip = isohashtbl[INOHASH(dev, inum)]; ip; ip = ip->i_next) {
if (inum == ip->i_number && dev == ip->i_dev) {
vp = ITOV(ip);
simple_lock(&vp->v_interlock);
simple_unlock(&cd9660_ihash_slock);
if (vget(vp, LK_EXCLUSIVE | LK_INTERLOCK, p))
goto loop;
return (vp);
}
}
simple_unlock(&cd9660_ihash_slock);
return (NULL);
}
/*
* Insert the inode into the hash table, and return it locked.
*/
void
cd9660_ihashins(ip)
struct iso_node *ip;
{
struct proc *p = curproc; /* XXX */
struct iso_node **ipp, *iq;
simple_lock(&cd9660_ihash_slock);
ipp = &isohashtbl[INOHASH(ip->i_dev, ip->i_number)];
if (iq = *ipp)
iq->i_prev = &ip->i_next;
ip->i_next = iq;
ip->i_prev = ipp;
*ipp = ip;
simple_unlock(&cd9660_ihash_slock);
lockmgr(&ip->i_lock, LK_EXCLUSIVE, (struct simplelock *)0, p);
}
/*
* Remove the inode from the hash table.
*/
void
cd9660_ihashrem(ip)
register struct iso_node *ip;
{
register struct iso_node *iq;
simple_lock(&cd9660_ihash_slock);
if (iq = ip->i_next)
iq->i_prev = ip->i_prev;
*ip->i_prev = iq;
#ifdef DIAGNOSTIC
ip->i_next = NULL;
ip->i_prev = NULL;
#endif
simple_unlock(&cd9660_ihash_slock);
}
/*
* Last reference to an inode, write the inode out and if necessary,
* truncate and deallocate the file.
*/
int
cd9660_inactive(ap)
struct vop_inactive_args /* {
struct vnode *a_vp;
struct proc *a_p;
} */ *ap;
{
struct vnode *vp = ap->a_vp;
struct proc *p = ap->a_p;
register struct iso_node *ip = VTOI(vp);
int mode, error = 0;
if (prtactive && vp->v_usecount != 0)
vprint("cd9660_inactive: pushing active", vp);
ip->i_flag = 0;
VOP_UNLOCK(vp, 0, p);
/*
* If we are done with the inode, reclaim it
* so that it can be reused immediately.
*/
if (ip->inode.iso_mode == 0)
vrecycle(vp, (struct simplelock *)0, p);
return error;
}
/*
* Reclaim an inode so that it can be used for other purposes.
*/
int
cd9660_reclaim(ap)
struct vop_reclaim_args /* {
struct vnode *a_vp;
struct proc *a_p;
} */ *ap;
{
register struct vnode *vp = ap->a_vp;
register struct iso_node *ip = VTOI(vp);
int i;
if (prtactive && vp->v_usecount != 0)
vprint("cd9660_reclaim: pushing active", vp);
/*
* Remove the inode from its hash chain.
*/
cd9660_ihashrem(ip);
/*
* Purge old data structures associated with the inode.
*/
cache_purge(vp);
if (ip->i_devvp) {
vrele(ip->i_devvp);
ip->i_devvp = 0;
}
FREE(vp->v_data, M_ISOFSNODE);
vp->v_data = NULL;
return (0);
}
/*
* File attributes
*/
void
cd9660_defattr(isodir, inop, bp)
struct iso_directory_record *isodir;
struct iso_node *inop;
struct buf *bp;
{
struct buf *bp2 = NULL;
struct iso_mnt *imp;
struct iso_extended_attributes *ap = NULL;
int off;
if (isonum_711(isodir->flags)&2) {
inop->inode.iso_mode = S_IFDIR;
/*
* If we return 2, fts() will assume there are no subdirectories
* (just links for the path and .), so instead we return 1.
*/
inop->inode.iso_links = 1;
} else {
inop->inode.iso_mode = S_IFREG;
inop->inode.iso_links = 1;
}
if (!bp
&& ((imp = inop->i_mnt)->im_flags & ISOFSMNT_EXTATT)
&& (off = isonum_711(isodir->ext_attr_length))) {
VOP_BLKATOFF(ITOV(inop), (off_t)-(off << imp->im_bshift), NULL,
&bp2);
bp = bp2;
}
if (bp) {
ap = (struct iso_extended_attributes *)bp->b_data;
if (isonum_711(ap->version) == 1) {
if (!(ap->perm[0]&0x40))
inop->inode.iso_mode |= VEXEC >> 6;
if (!(ap->perm[0]&0x10))
inop->inode.iso_mode |= VREAD >> 6;
if (!(ap->perm[0]&4))
inop->inode.iso_mode |= VEXEC >> 3;
if (!(ap->perm[0]&1))
inop->inode.iso_mode |= VREAD >> 3;
if (!(ap->perm[1]&0x40))
inop->inode.iso_mode |= VEXEC;
if (!(ap->perm[1]&0x10))
inop->inode.iso_mode |= VREAD;
inop->inode.iso_uid = isonum_723(ap->owner); /* what about 0? */
inop->inode.iso_gid = isonum_723(ap->group); /* what about 0? */
} else
ap = NULL;
}
if (!ap) {
inop->inode.iso_mode |= VREAD|VEXEC|(VREAD|VEXEC)>>3|(VREAD|VEXEC)>>6;
inop->inode.iso_uid = (uid_t)0;
inop->inode.iso_gid = (gid_t)0;
}
if (bp2)
brelse(bp2);
}
/*
* Time stamps
*/
void
cd9660_deftstamp(isodir,inop,bp)
struct iso_directory_record *isodir;
struct iso_node *inop;
struct buf *bp;
{
struct buf *bp2 = NULL;
struct iso_mnt *imp;
struct iso_extended_attributes *ap = NULL;
int off;
if (!bp
&& ((imp = inop->i_mnt)->im_flags & ISOFSMNT_EXTATT)
&& (off = isonum_711(isodir->ext_attr_length))) {
VOP_BLKATOFF(ITOV(inop), (off_t)-(off << imp->im_bshift), NULL,
&bp2);
bp = bp2;
}
if (bp) {
ap = (struct iso_extended_attributes *)bp->b_data;
if (isonum_711(ap->version) == 1) {
if (!cd9660_tstamp_conv17(ap->ftime,&inop->inode.iso_atime))
cd9660_tstamp_conv17(ap->ctime,&inop->inode.iso_atime);
if (!cd9660_tstamp_conv17(ap->ctime,&inop->inode.iso_ctime))
inop->inode.iso_ctime = inop->inode.iso_atime;
if (!cd9660_tstamp_conv17(ap->mtime,&inop->inode.iso_mtime))
inop->inode.iso_mtime = inop->inode.iso_ctime;
} else
ap = NULL;
}
if (!ap) {
cd9660_tstamp_conv7(isodir->date,&inop->inode.iso_ctime);
inop->inode.iso_atime = inop->inode.iso_ctime;
inop->inode.iso_mtime = inop->inode.iso_ctime;
}
if (bp2)
brelse(bp2);
}
int
cd9660_tstamp_conv7(pi,pu)
u_char *pi;
struct timespec *pu;
{
int i;
int crtime, days;
int y, m, d, hour, minute, second, tz;
y = pi[0] + 1900;
m = pi[1];
d = pi[2];
hour = pi[3];
minute = pi[4];
second = pi[5];
tz = pi[6];
if (y < 1970) {
pu->ts_sec = 0;
pu->ts_nsec = 0;
return 0;
} else {
#ifdef ORIGINAL
/* computes day number relative to Sept. 19th,1989 */
/* don't even *THINK* about changing formula. It works! */
days = 367*(y-1980)-7*(y+(m+9)/12)/4-3*((y+(m-9)/7)/100+1)/4+275*m/9+d-100;
#else
/*
* Changed :-) to make it relative to Jan. 1st, 1970
* and to disambiguate negative division
*/
days = 367*(y-1960)-7*(y+(m+9)/12)/4-3*((y+(m+9)/12-1)/100+1)/4+275*m/9+d-239;
#endif
crtime = ((((days * 24) + hour) * 60 + minute) * 60) + second;
/* timezone offset is unreliable on some disks */
if (-48 <= tz && tz <= 52)
crtime -= tz * 15 * 60;
}
pu->ts_sec = crtime;
pu->ts_nsec = 0;
return 1;
}
static u_int
cd9660_chars2ui(begin,len)
u_char *begin;
int len;
{
u_int rc;
for (rc = 0; --len >= 0;) {
rc *= 10;
rc += *begin++ - '0';
}
return rc;
}
int
cd9660_tstamp_conv17(pi,pu)
u_char *pi;
struct timespec *pu;
{
u_char buf[7];
/* year:"0001"-"9999" -> -1900 */
buf[0] = cd9660_chars2ui(pi,4) - 1900;
/* month: " 1"-"12" -> 1 - 12 */
buf[1] = cd9660_chars2ui(pi + 4,2);
/* day: " 1"-"31" -> 1 - 31 */
buf[2] = cd9660_chars2ui(pi + 6,2);
/* hour: " 0"-"23" -> 0 - 23 */
buf[3] = cd9660_chars2ui(pi + 8,2);
/* minute:" 0"-"59" -> 0 - 59 */
buf[4] = cd9660_chars2ui(pi + 10,2);
/* second:" 0"-"59" -> 0 - 59 */
buf[5] = cd9660_chars2ui(pi + 12,2);
/* difference of GMT */
buf[6] = pi[16];
return cd9660_tstamp_conv7(buf,pu);
}
ino_t
isodirino(isodir, imp)
struct iso_directory_record *isodir;
struct iso_mnt *imp;
{
ino_t ino;
ino = (isonum_733(isodir->extent) + isonum_711(isodir->ext_attr_length))
<< imp->im_bshift;
return (ino);
}

View File

@ -0,0 +1,145 @@
/*-
* Copyright (c) 1994
* The Regents of the University of California. All rights reserved.
*
* This code is derived from software contributed to Berkeley
* by Pace Willisson (pace@blitz.com). The Rock Ridge Extension
* Support code is derived from software contributed to Berkeley
* by Atsushi Murai (amurai@spec.co.jp).
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the University of
* California, Berkeley and its contributors.
* 4. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* @(#)cd9660_node.h 8.6 (Berkeley) 5/14/95
*/
/*
* Theoretically, directories can be more than 2Gb in length,
* however, in practice this seems unlikely. So, we define
* the type doff_t as a long to keep down the cost of doing
* lookup on a 32-bit machine. If you are porting to a 64-bit
* architecture, you should make doff_t the same as off_t.
*/
#define doff_t long
typedef struct {
struct timespec iso_atime; /* time of last access */
struct timespec iso_mtime; /* time of last modification */
struct timespec iso_ctime; /* time file changed */
u_short iso_mode; /* files access mode and type */
uid_t iso_uid; /* owner user id */
gid_t iso_gid; /* owner group id */
short iso_links; /* links of file */
dev_t iso_rdev; /* Major/Minor number for special */
} ISO_RRIP_INODE;
#ifdef ISODEVMAP
/*
* FOr device# (major,minor) translation table
*/
struct iso_dnode {
struct iso_dnode *d_next, **d_prev; /* hash chain */
dev_t i_dev; /* device where dnode resides */
ino_t i_number; /* the identity of the inode */
dev_t d_dev; /* device # for translation */
};
#endif
struct iso_node {
struct iso_node *i_next, **i_prev; /* hash chain */
struct vnode *i_vnode; /* vnode associated with this inode */
struct vnode *i_devvp; /* vnode for block I/O */
u_long i_flag; /* see below */
dev_t i_dev; /* device where inode resides */
ino_t i_number; /* the identity of the inode */
/* we use the actual starting block of the file */
struct iso_mnt *i_mnt; /* filesystem associated with this inode */
struct lockf *i_lockf; /* head of byte-level lock list */
doff_t i_endoff; /* end of useful stuff in directory */
doff_t i_diroff; /* offset in dir, where we found last entry */
doff_t i_offset; /* offset of free space in directory */
ino_t i_ino; /* inode number of found directory */
struct lock i_lock; /* node lock */
long iso_extent; /* extent of file */
long i_size;
long iso_start; /* actual start of data of file (may be different */
/* from iso_extent, if file has extended attributes) */
ISO_RRIP_INODE inode;
};
#define i_forw i_chain[0]
#define i_back i_chain[1]
/* flags */
#define IN_ACCESS 0x0020 /* inode access time to be updated */
#define VTOI(vp) ((struct iso_node *)(vp)->v_data)
#define ITOV(ip) ((ip)->i_vnode)
/*
* Prototypes for ISOFS vnode operations
*/
int cd9660_lookup __P((struct vop_lookup_args *));
int cd9660_open __P((struct vop_open_args *));
int cd9660_close __P((struct vop_close_args *));
int cd9660_access __P((struct vop_access_args *));
int cd9660_getattr __P((struct vop_getattr_args *));
int cd9660_read __P((struct vop_read_args *));
int cd9660_ioctl __P((struct vop_ioctl_args *));
int cd9660_select __P((struct vop_select_args *));
int cd9660_mmap __P((struct vop_mmap_args *));
int cd9660_seek __P((struct vop_seek_args *));
int cd9660_readdir __P((struct vop_readdir_args *));
int cd9660_abortop __P((struct vop_abortop_args *));
int cd9660_inactive __P((struct vop_inactive_args *));
int cd9660_reclaim __P((struct vop_reclaim_args *));
int cd9660_bmap __P((struct vop_bmap_args *));
int cd9660_lock __P((struct vop_lock_args *));
int cd9660_unlock __P((struct vop_unlock_args *));
int cd9660_strategy __P((struct vop_strategy_args *));
int cd9660_print __P((struct vop_print_args *));
int cd9660_islocked __P((struct vop_islocked_args *));
int cd9660_pathconf __P((struct vop_pathconf_args *));
int cd9660_blkatoff __P((struct vop_blkatoff_args *));
#define cd9660_revoke vop_revoke
void cd9660_defattr __P((struct iso_directory_record *,
struct iso_node *, struct buf *));
void cd9660_deftstamp __P((struct iso_directory_record *,
struct iso_node *, struct buf *));
struct vnode *cd9660_ihashget __P((dev_t, ino_t));
void cd9660_ihashins __P((struct iso_node *));
void cd9660_ihashrem __P((struct iso_node *));
int cd9660_tstamp_conv7 __P((u_char *, struct timespec *));
int cd9660_tstamp_conv17 __P((u_char *, struct timespec *));
ino_t isodirino __P((struct iso_directory_record *, struct iso_mnt *));
#ifdef ISODEVMAP
struct iso_dnode *iso_dmap __P((dev_t, ino_t, int));
void iso_dunmap __P((dev_t));
#endif

View File

@ -0,0 +1,690 @@
/*-
* Copyright (c) 1993, 1994
* The Regents of the University of California. All rights reserved.
*
* This code is derived from software contributed to Berkeley
* by Pace Willisson (pace@blitz.com). The Rock Ridge Extension
* Support code is derived from software contributed to Berkeley
* by Atsushi Murai (amurai@spec.co.jp).
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the University of
* California, Berkeley and its contributors.
* 4. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* @(#)cd9660_rrip.c 8.6 (Berkeley) 12/5/94
*/
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/namei.h>
#include <sys/buf.h>
#include <sys/file.h>
#include <sys/vnode.h>
#include <sys/mount.h>
#include <sys/kernel.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <sys/time.h>
#include <isofs/cd9660/iso.h>
#include <isofs/cd9660/cd9660_node.h>
#include <isofs/cd9660/cd9660_rrip.h>
#include <isofs/cd9660/iso_rrip.h>
/*
* POSIX file attribute
*/
static int
cd9660_rrip_attr(p,ana)
ISO_RRIP_ATTR *p;
ISO_RRIP_ANALYZE *ana;
{
ana->inop->inode.iso_mode = isonum_733(p->mode);
ana->inop->inode.iso_uid = isonum_733(p->uid);
ana->inop->inode.iso_gid = isonum_733(p->gid);
ana->inop->inode.iso_links = isonum_733(p->links);
ana->fields &= ~ISO_SUSP_ATTR;
return ISO_SUSP_ATTR;
}
static void
cd9660_rrip_defattr(isodir,ana)
struct iso_directory_record *isodir;
ISO_RRIP_ANALYZE *ana;
{
/* But this is a required field! */
printf("RRIP without PX field?\n");
cd9660_defattr(isodir,ana->inop,NULL);
}
/*
* Symbolic Links
*/
static int
cd9660_rrip_slink(p,ana)
ISO_RRIP_SLINK *p;
ISO_RRIP_ANALYZE *ana;
{
register ISO_RRIP_SLINK_COMPONENT *pcomp;
register ISO_RRIP_SLINK_COMPONENT *pcompe;
int len, wlen, cont;
char *outbuf, *inbuf;
pcomp = (ISO_RRIP_SLINK_COMPONENT *)p->component;
pcompe = (ISO_RRIP_SLINK_COMPONENT *)((char *)p + isonum_711(p->h.length));
len = *ana->outlen;
outbuf = ana->outbuf;
cont = ana->cont;
/*
* Gathering a Symbolic name from each component with path
*/
for (;
pcomp < pcompe;
pcomp = (ISO_RRIP_SLINK_COMPONENT *)((char *)pcomp + ISO_RRIP_SLSIZ
+ isonum_711(pcomp->clen))) {
if (!cont) {
if (len < ana->maxlen) {
len++;
*outbuf++ = '/';
}
}
cont = 0;
inbuf = "..";
wlen = 0;
switch (*pcomp->cflag) {
case ISO_SUSP_CFLAG_CURRENT:
/* Inserting Current */
wlen = 1;
break;
case ISO_SUSP_CFLAG_PARENT:
/* Inserting Parent */
wlen = 2;
break;
case ISO_SUSP_CFLAG_ROOT:
/* Inserting slash for ROOT */
/* start over from beginning(?) */
outbuf -= len;
len = 0;
break;
case ISO_SUSP_CFLAG_VOLROOT:
/* Inserting a mount point i.e. "/cdrom" */
/* same as above */
outbuf -= len;
len = 0;
inbuf = ana->imp->im_mountp->mnt_stat.f_mntonname;
wlen = strlen(inbuf);
break;
case ISO_SUSP_CFLAG_HOST:
/* Inserting hostname i.e. "kurt.tools.de" */
inbuf = hostname;
wlen = hostnamelen;
break;
case ISO_SUSP_CFLAG_CONTINUE:
cont = 1;
/* fall thru */
case 0:
/* Inserting component */
wlen = isonum_711(pcomp->clen);
inbuf = pcomp->name;
break;
default:
printf("RRIP with incorrect flags?");
wlen = ana->maxlen + 1;
break;
}
if (len + wlen > ana->maxlen) {
/* indicate error to caller */
ana->cont = 1;
ana->fields = 0;
ana->outbuf -= *ana->outlen;
*ana->outlen = 0;
return 0;
}
bcopy(inbuf,outbuf,wlen);
outbuf += wlen;
len += wlen;
}
ana->outbuf = outbuf;
*ana->outlen = len;
ana->cont = cont;
if (!isonum_711(p->flags)) {
ana->fields &= ~ISO_SUSP_SLINK;
return ISO_SUSP_SLINK;
}
return 0;
}
/*
* Alternate name
*/
static int
cd9660_rrip_altname(p,ana)
ISO_RRIP_ALTNAME *p;
ISO_RRIP_ANALYZE *ana;
{
char *inbuf;
int wlen;
int cont;
inbuf = "..";
wlen = 0;
cont = 0;
switch (*p->flags) {
case ISO_SUSP_CFLAG_CURRENT:
/* Inserting Current */
wlen = 1;
break;
case ISO_SUSP_CFLAG_PARENT:
/* Inserting Parent */
wlen = 2;
break;
case ISO_SUSP_CFLAG_HOST:
/* Inserting hostname i.e. "kurt.tools.de" */
inbuf = hostname;
wlen = hostnamelen;
break;
case ISO_SUSP_CFLAG_CONTINUE:
cont = 1;
/* fall thru */
case 0:
/* Inserting component */
wlen = isonum_711(p->h.length) - 5;
inbuf = (char *)p + 5;
break;
default:
printf("RRIP with incorrect NM flags?\n");
wlen = ana->maxlen + 1;
break;
}
if ((*ana->outlen += wlen) > ana->maxlen) {
/* treat as no name field */
ana->fields &= ~ISO_SUSP_ALTNAME;
ana->outbuf -= *ana->outlen - wlen;
*ana->outlen = 0;
return 0;
}
bcopy(inbuf,ana->outbuf,wlen);
ana->outbuf += wlen;
if (!cont) {
ana->fields &= ~ISO_SUSP_ALTNAME;
return ISO_SUSP_ALTNAME;
}
return 0;
}
static void
cd9660_rrip_defname(isodir,ana)
struct iso_directory_record *isodir;
ISO_RRIP_ANALYZE *ana;
{
strcpy(ana->outbuf,"..");
switch (*isodir->name) {
default:
isofntrans(isodir->name,isonum_711(isodir->name_len),
ana->outbuf,ana->outlen,
1,isonum_711(isodir->flags)&4);
break;
case 0:
*ana->outlen = 1;
break;
case 1:
*ana->outlen = 2;
break;
}
}
/*
* Parent or Child Link
*/
static int
cd9660_rrip_pclink(p,ana)
ISO_RRIP_CLINK *p;
ISO_RRIP_ANALYZE *ana;
{
*ana->inump = isonum_733(p->dir_loc) << ana->imp->im_bshift;
ana->fields &= ~(ISO_SUSP_CLINK|ISO_SUSP_PLINK);
return *p->h.type == 'C' ? ISO_SUSP_CLINK : ISO_SUSP_PLINK;
}
/*
* Relocated directory
*/
static int
cd9660_rrip_reldir(p,ana)
ISO_RRIP_RELDIR *p;
ISO_RRIP_ANALYZE *ana;
{
/* special hack to make caller aware of RE field */
*ana->outlen = 0;
ana->fields = 0;
return ISO_SUSP_RELDIR|ISO_SUSP_ALTNAME|ISO_SUSP_CLINK|ISO_SUSP_PLINK;
}
static int
cd9660_rrip_tstamp(p,ana)
ISO_RRIP_TSTAMP *p;
ISO_RRIP_ANALYZE *ana;
{
u_char *ptime;
ptime = p->time;
/* Check a format of time stamp (7bytes/17bytes) */
if (!(*p->flags&ISO_SUSP_TSTAMP_FORM17)) {
if (*p->flags&ISO_SUSP_TSTAMP_CREAT)
ptime += 7;
if (*p->flags&ISO_SUSP_TSTAMP_MODIFY) {
cd9660_tstamp_conv7(ptime,&ana->inop->inode.iso_mtime);
ptime += 7;
} else
bzero(&ana->inop->inode.iso_mtime,sizeof(struct timespec));
if (*p->flags&ISO_SUSP_TSTAMP_ACCESS) {
cd9660_tstamp_conv7(ptime,&ana->inop->inode.iso_atime);
ptime += 7;
} else
ana->inop->inode.iso_atime = ana->inop->inode.iso_mtime;
if (*p->flags&ISO_SUSP_TSTAMP_ATTR)
cd9660_tstamp_conv7(ptime,&ana->inop->inode.iso_ctime);
else
ana->inop->inode.iso_ctime = ana->inop->inode.iso_mtime;
} else {
if (*p->flags&ISO_SUSP_TSTAMP_CREAT)
ptime += 17;
if (*p->flags&ISO_SUSP_TSTAMP_MODIFY) {
cd9660_tstamp_conv17(ptime,&ana->inop->inode.iso_mtime);
ptime += 17;
} else
bzero(&ana->inop->inode.iso_mtime,sizeof(struct timespec));
if (*p->flags&ISO_SUSP_TSTAMP_ACCESS) {
cd9660_tstamp_conv17(ptime,&ana->inop->inode.iso_atime);
ptime += 17;
} else
ana->inop->inode.iso_atime = ana->inop->inode.iso_mtime;
if (*p->flags&ISO_SUSP_TSTAMP_ATTR)
cd9660_tstamp_conv17(ptime,&ana->inop->inode.iso_ctime);
else
ana->inop->inode.iso_ctime = ana->inop->inode.iso_mtime;
}
ana->fields &= ~ISO_SUSP_TSTAMP;
return ISO_SUSP_TSTAMP;
}
static void
cd9660_rrip_deftstamp(isodir,ana)
struct iso_directory_record *isodir;
ISO_RRIP_ANALYZE *ana;
{
cd9660_deftstamp(isodir,ana->inop,NULL);
}
/*
* POSIX device modes
*/
static int
cd9660_rrip_device(p,ana)
ISO_RRIP_DEVICE *p;
ISO_RRIP_ANALYZE *ana;
{
u_int high, low;
high = isonum_733(p->dev_t_high);
low = isonum_733(p->dev_t_low);
if (high == 0)
ana->inop->inode.iso_rdev = makedev(major(low), minor(low));
else
ana->inop->inode.iso_rdev = makedev(high, minor(low));
ana->fields &= ~ISO_SUSP_DEVICE;
return ISO_SUSP_DEVICE;
}
/*
* Flag indicating
*/
static int
cd9660_rrip_idflag(p,ana)
ISO_RRIP_IDFLAG *p;
ISO_RRIP_ANALYZE *ana;
{
ana->fields &= isonum_711(p->flags)|~0xff; /* don't touch high bits */
/* special handling of RE field */
if (ana->fields&ISO_SUSP_RELDIR)
return cd9660_rrip_reldir(p,ana);
return ISO_SUSP_IDFLAG;
}
/*
* Continuation pointer
*/
static int
cd9660_rrip_cont(p,ana)
ISO_RRIP_CONT *p;
ISO_RRIP_ANALYZE *ana;
{
ana->iso_ce_blk = isonum_733(p->location);
ana->iso_ce_off = isonum_733(p->offset);
ana->iso_ce_len = isonum_733(p->length);
return ISO_SUSP_CONT;
}
/*
* System Use end
*/
static int
cd9660_rrip_stop(p,ana)
ISO_SUSP_HEADER *p;
ISO_RRIP_ANALYZE *ana;
{
return ISO_SUSP_STOP;
}
/*
* Extension reference
*/
static int
cd9660_rrip_extref(p,ana)
ISO_RRIP_EXTREF *p;
ISO_RRIP_ANALYZE *ana;
{
if (isonum_711(p->len_id) != 10
|| bcmp((char *)p + 8,"RRIP_1991A",10)
|| isonum_711(p->version) != 1)
return 0;
ana->fields &= ~ISO_SUSP_EXTREF;
return ISO_SUSP_EXTREF;
}
typedef struct {
char type[2];
int (*func)();
void (*func2)();
int result;
} RRIP_TABLE;
static int
cd9660_rrip_loop(isodir,ana,table)
struct iso_directory_record *isodir;
ISO_RRIP_ANALYZE *ana;
RRIP_TABLE *table;
{
register RRIP_TABLE *ptable;
register ISO_SUSP_HEADER *phead;
register ISO_SUSP_HEADER *pend;
struct buf *bp = NULL;
int i;
char *pwhead;
int result;
/*
* Note: If name length is odd,
* it will be padding 1 byte after the name
*/
pwhead = isodir->name + isonum_711(isodir->name_len);
if (!(isonum_711(isodir->name_len)&1))
pwhead++;
/* If it's not the '.' entry of the root dir obey SP field */
if (*isodir->name != 0
|| isonum_733(isodir->extent) != ana->imp->root_extent)
pwhead += ana->imp->rr_skip;
else
pwhead += ana->imp->rr_skip0;
phead = (ISO_SUSP_HEADER *)pwhead;
pend = (ISO_SUSP_HEADER *)((char *)isodir + isonum_711(isodir->length));
result = 0;
while (1) {
ana->iso_ce_len = 0;
/*
* Note: "pend" should be more than one SUSP header
*/
while (pend >= phead + 1) {
if (isonum_711(phead->version) == 1) {
for (ptable = table; ptable->func; ptable++) {
if (*phead->type == *ptable->type
&& phead->type[1] == ptable->type[1]) {
result |= ptable->func(phead,ana);
break;
}
}
if (!ana->fields)
break;
}
if (result&ISO_SUSP_STOP) {
result &= ~ISO_SUSP_STOP;
break;
}
/* plausibility check */
if (isonum_711(phead->length) < sizeof(*phead))
break;
/*
* move to next SUSP
* Hopefully this works with newer versions, too
*/
phead = (ISO_SUSP_HEADER *)((char *)phead + isonum_711(phead->length));
}
if (ana->fields && ana->iso_ce_len) {
if (ana->iso_ce_blk >= ana->imp->volume_space_size
|| ana->iso_ce_off + ana->iso_ce_len > ana->imp->logical_block_size
|| bread(ana->imp->im_devvp,
ana->iso_ce_blk <<
(ana->imp->im_bshift - DEV_BSHIFT),
ana->imp->logical_block_size, NOCRED, &bp))
/* what to do now? */
break;
phead = (ISO_SUSP_HEADER *)(bp->b_data + ana->iso_ce_off);
pend = (ISO_SUSP_HEADER *) ((char *)phead + ana->iso_ce_len);
} else
break;
}
if (bp)
brelse(bp);
/*
* If we don't find the Basic SUSP stuffs, just set default value
* (attribute/time stamp)
*/
for (ptable = table; ptable->func2; ptable++)
if (!(ptable->result&result))
ptable->func2(isodir,ana);
return result;
}
/*
* Get Attributes.
*/
static RRIP_TABLE rrip_table_analyze[] = {
{ "PX", cd9660_rrip_attr, cd9660_rrip_defattr, ISO_SUSP_ATTR },
{ "TF", cd9660_rrip_tstamp, cd9660_rrip_deftstamp, ISO_SUSP_TSTAMP },
{ "PN", cd9660_rrip_device, 0, ISO_SUSP_DEVICE },
{ "RR", cd9660_rrip_idflag, 0, ISO_SUSP_IDFLAG },
{ "CE", cd9660_rrip_cont, 0, ISO_SUSP_CONT },
{ "ST", cd9660_rrip_stop, 0, ISO_SUSP_STOP },
{ "", 0, 0, 0 }
};
int
cd9660_rrip_analyze(isodir,inop,imp)
struct iso_directory_record *isodir;
struct iso_node *inop;
struct iso_mnt *imp;
{
ISO_RRIP_ANALYZE analyze;
analyze.inop = inop;
analyze.imp = imp;
analyze.fields = ISO_SUSP_ATTR|ISO_SUSP_TSTAMP|ISO_SUSP_DEVICE;
return cd9660_rrip_loop(isodir,&analyze,rrip_table_analyze);
}
/*
* Get Alternate Name.
*/
static RRIP_TABLE rrip_table_getname[] = {
{ "NM", cd9660_rrip_altname, cd9660_rrip_defname, ISO_SUSP_ALTNAME },
{ "CL", cd9660_rrip_pclink, 0, ISO_SUSP_CLINK|ISO_SUSP_PLINK },
{ "PL", cd9660_rrip_pclink, 0, ISO_SUSP_CLINK|ISO_SUSP_PLINK },
{ "RE", cd9660_rrip_reldir, 0, ISO_SUSP_RELDIR },
{ "RR", cd9660_rrip_idflag, 0, ISO_SUSP_IDFLAG },
{ "CE", cd9660_rrip_cont, 0, ISO_SUSP_CONT },
{ "ST", cd9660_rrip_stop, 0, ISO_SUSP_STOP },
{ "", 0, 0, 0 }
};
int
cd9660_rrip_getname(isodir,outbuf,outlen,inump,imp)
struct iso_directory_record *isodir;
char *outbuf;
u_short *outlen;
ino_t *inump;
struct iso_mnt *imp;
{
ISO_RRIP_ANALYZE analyze;
RRIP_TABLE *tab;
analyze.outbuf = outbuf;
analyze.outlen = outlen;
analyze.maxlen = NAME_MAX;
analyze.inump = inump;
analyze.imp = imp;
analyze.fields = ISO_SUSP_ALTNAME|ISO_SUSP_RELDIR|ISO_SUSP_CLINK|ISO_SUSP_PLINK;
*outlen = 0;
tab = rrip_table_getname;
if (*isodir->name == 0
|| *isodir->name == 1) {
cd9660_rrip_defname(isodir,&analyze);
analyze.fields &= ~ISO_SUSP_ALTNAME;
tab++;
}
return cd9660_rrip_loop(isodir,&analyze,tab);
}
/*
* Get Symbolic Link.
*/
static RRIP_TABLE rrip_table_getsymname[] = {
{ "SL", cd9660_rrip_slink, 0, ISO_SUSP_SLINK },
{ "RR", cd9660_rrip_idflag, 0, ISO_SUSP_IDFLAG },
{ "CE", cd9660_rrip_cont, 0, ISO_SUSP_CONT },
{ "ST", cd9660_rrip_stop, 0, ISO_SUSP_STOP },
{ "", 0, 0, 0 }
};
int
cd9660_rrip_getsymname(isodir,outbuf,outlen,imp)
struct iso_directory_record *isodir;
char *outbuf;
u_short *outlen;
struct iso_mnt *imp;
{
ISO_RRIP_ANALYZE analyze;
analyze.outbuf = outbuf;
analyze.outlen = outlen;
*outlen = 0;
analyze.maxlen = MAXPATHLEN;
analyze.cont = 1; /* don't start with a slash */
analyze.imp = imp;
analyze.fields = ISO_SUSP_SLINK;
return (cd9660_rrip_loop(isodir,&analyze,rrip_table_getsymname)&ISO_SUSP_SLINK);
}
static RRIP_TABLE rrip_table_extref[] = {
{ "ER", cd9660_rrip_extref, 0, ISO_SUSP_EXTREF },
{ "CE", cd9660_rrip_cont, 0, ISO_SUSP_CONT },
{ "ST", cd9660_rrip_stop, 0, ISO_SUSP_STOP },
{ "", 0, 0, 0 }
};
/*
* Check for Rock Ridge Extension and return offset of its fields.
* Note: We insist on the ER field.
*/
int
cd9660_rrip_offset(isodir,imp)
struct iso_directory_record *isodir;
struct iso_mnt *imp;
{
ISO_RRIP_OFFSET *p;
ISO_RRIP_ANALYZE analyze;
imp->rr_skip0 = 0;
p = (ISO_RRIP_OFFSET *)(isodir->name + 1);
if (bcmp(p,"SP\7\1\276\357",6)) {
/* Maybe, it's a CDROM XA disc? */
imp->rr_skip0 = 15;
p = (ISO_RRIP_OFFSET *)((char *)p + 15);
if (bcmp(p,"SP\7\1\276\357",6))
return -1;
}
analyze.imp = imp;
analyze.fields = ISO_SUSP_EXTREF;
if (!(cd9660_rrip_loop(isodir,&analyze,rrip_table_extref)&ISO_SUSP_EXTREF))
return -1;
return isonum_711(p->skip);
}

View File

@ -0,0 +1,140 @@
/*-
* Copyright (c) 1993, 1994
* The Regents of the University of California. All rights reserved.
*
* This code is derived from software contributed to Berkeley
* by Pace Willisson (pace@blitz.com). The Rock Ridge Extension
* Support code is derived from software contributed to Berkeley
* by Atsushi Murai (amurai@spec.co.jp).
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the University of
* California, Berkeley and its contributors.
* 4. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* @(#)cd9660_rrip.h 8.2 (Berkeley) 12/5/94
*/
typedef struct {
char type [ISODCL ( 0, 1)];
u_char length [ISODCL ( 2, 2)]; /* 711 */
u_char version [ISODCL ( 3, 3)];
} ISO_SUSP_HEADER;
typedef struct {
ISO_SUSP_HEADER h;
char mode [ISODCL ( 4, 11)]; /* 733 */
char links [ISODCL ( 12, 19)]; /* 733 */
char uid [ISODCL ( 20, 27)]; /* 733 */
char gid [ISODCL ( 28, 35)]; /* 733 */
} ISO_RRIP_ATTR;
typedef struct {
ISO_SUSP_HEADER h;
char dev_t_high [ISODCL ( 4, 11)]; /* 733 */
char dev_t_low [ISODCL ( 12, 19)]; /* 733 */
} ISO_RRIP_DEVICE;
#define ISO_SUSP_CFLAG_CONTINUE 0x01
#define ISO_SUSP_CFLAG_CURRENT 0x02
#define ISO_SUSP_CFLAG_PARENT 0x04
#define ISO_SUSP_CFLAG_ROOT 0x08
#define ISO_SUSP_CFLAG_VOLROOT 0x10
#define ISO_SUSP_CFLAG_HOST 0x20
typedef struct {
u_char cflag [ISODCL ( 1, 1)];
u_char clen [ISODCL ( 2, 2)];
u_char name [1]; /* XXX */
} ISO_RRIP_SLINK_COMPONENT;
#define ISO_RRIP_SLSIZ 2
typedef struct {
ISO_SUSP_HEADER h;
u_char flags [ISODCL ( 4, 4)];
u_char component [ISODCL ( 5, 5)];
} ISO_RRIP_SLINK;
typedef struct {
ISO_SUSP_HEADER h;
char flags [ISODCL ( 4, 4)];
} ISO_RRIP_ALTNAME;
typedef struct {
ISO_SUSP_HEADER h;
char dir_loc [ISODCL ( 4, 11)]; /* 733 */
} ISO_RRIP_CLINK;
typedef struct {
ISO_SUSP_HEADER h;
char dir_loc [ISODCL ( 4, 11)]; /* 733 */
} ISO_RRIP_PLINK;
typedef struct {
ISO_SUSP_HEADER h;
} ISO_RRIP_RELDIR;
#define ISO_SUSP_TSTAMP_FORM17 0x80
#define ISO_SUSP_TSTAMP_FORM7 0x00
#define ISO_SUSP_TSTAMP_CREAT 0x01
#define ISO_SUSP_TSTAMP_MODIFY 0x02
#define ISO_SUSP_TSTAMP_ACCESS 0x04
#define ISO_SUSP_TSTAMP_ATTR 0x08
#define ISO_SUSP_TSTAMP_BACKUP 0x10
#define ISO_SUSP_TSTAMP_EXPIRE 0x20
#define ISO_SUSP_TSTAMP_EFFECT 0x40
typedef struct {
ISO_SUSP_HEADER h;
u_char flags [ISODCL ( 4, 4)];
u_char time [ISODCL ( 5, 5)];
} ISO_RRIP_TSTAMP;
typedef struct {
ISO_SUSP_HEADER h;
u_char flags [ISODCL ( 4, 4)];
} ISO_RRIP_IDFLAG;
typedef struct {
ISO_SUSP_HEADER h;
char len_id [ISODCL ( 4, 4)];
char len_des [ISODCL ( 5, 5)];
char len_src [ISODCL ( 6, 6)];
char version [ISODCL ( 7, 7)];
} ISO_RRIP_EXTREF;
typedef struct {
ISO_SUSP_HEADER h;
char check [ISODCL ( 4, 5)];
char skip [ISODCL ( 6, 6)];
} ISO_RRIP_OFFSET;
typedef struct {
ISO_SUSP_HEADER h;
char location [ISODCL ( 4, 11)];
char offset [ISODCL ( 12, 19)];
char length [ISODCL ( 20, 27)];
} ISO_RRIP_CONT;

View File

@ -0,0 +1,150 @@
/*-
* Copyright (c) 1994
* The Regents of the University of California. All rights reserved.
*
* This code is derived from software contributed to Berkeley
* by Pace Willisson (pace@blitz.com). The Rock Ridge Extension
* Support code is derived from software contributed to Berkeley
* by Atsushi Murai (amurai@spec.co.jp).
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the University of
* California, Berkeley and its contributors.
* 4. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* @(#)cd9660_util.c 8.3 (Berkeley) 12/5/94
*/
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/namei.h>
#include <sys/resourcevar.h>
#include <sys/kernel.h>
#include <sys/file.h>
#include <sys/stat.h>
#include <sys/buf.h>
#include <sys/proc.h>
#include <sys/conf.h>
#include <sys/mount.h>
#include <sys/vnode.h>
#include <miscfs/specfs/specdev.h> /* XXX */
#include <miscfs/fifofs/fifo.h> /* XXX */
#include <sys/malloc.h>
#include <sys/dir.h>
#include <isofs/cd9660/iso.h>
/*
* translate and compare a filename
* Note: Version number plus ';' may be omitted.
*/
int
isofncmp(fn, fnlen, isofn, isolen)
u_char *fn, *isofn;
int fnlen, isolen;
{
int i, j;
char c;
while (--fnlen >= 0) {
if (--isolen < 0)
return *fn;
if ((c = *isofn++) == ';') {
switch (*fn++) {
default:
return *--fn;
case 0:
return 0;
case ';':
break;
}
for (i = 0; --fnlen >= 0; i = i * 10 + *fn++ - '0') {
if (*fn < '0' || *fn > '9') {
return -1;
}
}
for (j = 0; --isolen >= 0; j = j * 10 + *isofn++ - '0');
return i - j;
}
if (c != *fn) {
if (c >= 'A' && c <= 'Z') {
if (c + ('a' - 'A') != *fn) {
if (*fn >= 'a' && *fn <= 'z')
return *fn - ('a' - 'A') - c;
else
return *fn - c;
}
} else
return *fn - c;
}
fn++;
}
if (isolen > 0) {
switch (*isofn) {
default:
return -1;
case '.':
if (isofn[1] != ';')
return -1;
case ';':
return 0;
}
}
return 0;
}
/*
* translate a filename
*/
void
isofntrans(infn, infnlen, outfn, outfnlen, original, assoc)
u_char *infn, *outfn;
int infnlen;
u_short *outfnlen;
int original;
int assoc;
{
int fnidx = 0;
if (assoc) {
*outfn++ = ASSOCCHAR;
fnidx++;
infnlen++;
}
for (; fnidx < infnlen; fnidx++) {
char c = *infn++;
if (!original && c >= 'A' && c <= 'Z')
*outfn++ = c + ('a' - 'A');
else if (!original && c == '.' && *infn == ';')
break;
else if (!original && c == ';')
break;
else
*outfn++ = c;
}
*outfnlen = fnidx;
}

View File

@ -0,0 +1,800 @@
/*-
* Copyright (c) 1994
* The Regents of the University of California. All rights reserved.
*
* This code is derived from software contributed to Berkeley
* by Pace Willisson (pace@blitz.com). The Rock Ridge Extension
* Support code is derived from software contributed to Berkeley
* by Atsushi Murai (amurai@spec.co.jp).
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the University of
* California, Berkeley and its contributors.
* 4. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* @(#)cd9660_vfsops.c 8.18 (Berkeley) 5/22/95
*/
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/namei.h>
#include <sys/proc.h>
#include <sys/kernel.h>
#include <sys/vnode.h>
#include <miscfs/specfs/specdev.h>
#include <sys/mount.h>
#include <sys/buf.h>
#include <sys/file.h>
#include <sys/dkbad.h>
#include <sys/disklabel.h>
#include <sys/ioctl.h>
#include <sys/errno.h>
#include <sys/malloc.h>
#include <sys/stat.h>
#include <isofs/cd9660/iso.h>
#include <isofs/cd9660/cd9660_node.h>
#include <isofs/cd9660/cd9660_mount.h>
extern int enodev ();
struct vfsops cd9660_vfsops = {
cd9660_mount,
cd9660_start,
cd9660_unmount,
cd9660_root,
cd9660_quotactl,
cd9660_statfs,
cd9660_sync,
cd9660_vget,
cd9660_fhtovp,
cd9660_vptofh,
cd9660_init,
cd9660_sysctl
};
/*
* Called by vfs_mountroot when iso is going to be mounted as root.
*/
static iso_mountfs();
cd9660_mountroot()
{
struct mount *mp;
extern struct vnode *rootvp;
struct proc *p = curproc; /* XXX */
struct iso_args args;
int error;
/*
* Get vnodes for swapdev and rootdev.
*/
if ((error = bdevvp(swapdev, &swapdev_vp)) ||
(error = bdevvp(rootdev, &rootvp))) {
printf("cd9660_mountroot: can't setup bdevvp's");
return (error);
}
if (error = vfs_rootmountalloc("cd9660", "root_device", &mp))
return (error);
args.flags = ISOFSMNT_ROOT;
if (error = iso_mountfs(rootvp, mp, p, &args)) {
mp->mnt_vfc->vfc_refcount--;
vfs_unbusy(mp, p);
free(mp, M_MOUNT);
return (error);
}
simple_lock(&mountlist_slock);
CIRCLEQ_INSERT_TAIL(&mountlist, mp, mnt_list);
simple_unlock(&mountlist_slock);
(void)cd9660_statfs(mp, &mp->mnt_stat, p);
vfs_unbusy(mp, p);
return (0);
}
/*
* VFS Operations.
*
* mount system call
*/
cd9660_mount(mp, path, data, ndp, p)
register struct mount *mp;
char *path;
caddr_t data;
struct nameidata *ndp;
struct proc *p;
{
struct vnode *devvp;
struct iso_args args;
u_int size;
int error;
struct iso_mnt *imp;
if (error = copyin(data, (caddr_t)&args, sizeof (struct iso_args)))
return (error);
if ((mp->mnt_flag & MNT_RDONLY) == 0)
return (EROFS);
/*
* If updating, check whether changing from read-only to
* read/write; if there is no device name, that's all we do.
*/
if (mp->mnt_flag & MNT_UPDATE) {
imp = VFSTOISOFS(mp);
if (args.fspec == 0)
return (vfs_export(mp, &imp->im_export, &args.export));
}
/*
* Not an update, or updating the name: look up the name
* and verify that it refers to a sensible block device.
*/
NDINIT(ndp, LOOKUP, FOLLOW, UIO_USERSPACE, args.fspec, p);
if (error = namei(ndp))
return (error);
devvp = ndp->ni_vp;
if (devvp->v_type != VBLK) {
vrele(devvp);
return ENOTBLK;
}
if (major(devvp->v_rdev) >= nblkdev) {
vrele(devvp);
return ENXIO;
}
if ((mp->mnt_flag & MNT_UPDATE) == 0)
error = iso_mountfs(devvp, mp, p, &args);
else {
if (devvp != imp->im_devvp)
error = EINVAL; /* needs translation */
else
vrele(devvp);
}
if (error) {
vrele(devvp);
return error;
}
imp = VFSTOISOFS(mp);
(void) copyinstr(path, mp->mnt_stat.f_mntonname, MNAMELEN - 1, &size);
bzero(mp->mnt_stat.f_mntonname + size, MNAMELEN - size);
(void) copyinstr(args.fspec, mp->mnt_stat.f_mntfromname, MNAMELEN - 1,
&size);
bzero(mp->mnt_stat.f_mntfromname + size, MNAMELEN - size);
(void) cd9660_statfs(mp, &mp->mnt_stat, p);
return 0;
}
/*
* Common code for mount and mountroot
*/
static iso_mountfs(devvp, mp, p, argp)
register struct vnode *devvp;
struct mount *mp;
struct proc *p;
struct iso_args *argp;
{
register struct iso_mnt *isomp = (struct iso_mnt *)0;
struct buf *bp = NULL;
dev_t dev = devvp->v_rdev;
caddr_t base, space;
int havepart = 0, blks;
int error = EINVAL, i, size;
int needclose = 0;
int ronly = (mp->mnt_flag & MNT_RDONLY) != 0;
extern struct vnode *rootvp;
int j;
int iso_bsize;
int iso_blknum;
struct iso_volume_descriptor *vdp;
struct iso_primary_descriptor *pri;
struct iso_directory_record *rootp;
int logical_block_size;
if (!ronly)
return EROFS;
/*
* Disallow multiple mounts of the same device.
* Disallow mounting of a device that is currently in use
* (except for root, which might share swap device for miniroot).
* Flush out any old buffers remaining from a previous use.
*/
if (error = vfs_mountedon(devvp))
return error;
if (vcount(devvp) > 1 && devvp != rootvp)
return EBUSY;
if (error = vinvalbuf(devvp, V_SAVE, p->p_ucred, p, 0, 0))
return (error);
if (error = VOP_OPEN(devvp, ronly ? FREAD : FREAD|FWRITE, FSCRED, p))
return error;
needclose = 1;
/* This is the "logical sector size". The standard says this
* should be 2048 or the physical sector size on the device,
* whichever is greater. For now, we'll just use a constant.
*/
iso_bsize = ISO_DEFAULT_BLOCK_SIZE;
for (iso_blknum = 16; iso_blknum < 100; iso_blknum++) {
if (error = bread(devvp, iso_blknum * btodb(iso_bsize),
iso_bsize, NOCRED, &bp))
goto out;
vdp = (struct iso_volume_descriptor *)bp->b_data;
if (bcmp (vdp->id, ISO_STANDARD_ID, sizeof vdp->id) != 0) {
error = EINVAL;
goto out;
}
if (isonum_711 (vdp->type) == ISO_VD_END) {
error = EINVAL;
goto out;
}
if (isonum_711 (vdp->type) == ISO_VD_PRIMARY)
break;
brelse(bp);
}
if (isonum_711 (vdp->type) != ISO_VD_PRIMARY) {
error = EINVAL;
goto out;
}
pri = (struct iso_primary_descriptor *)vdp;
logical_block_size = isonum_723 (pri->logical_block_size);
if (logical_block_size < DEV_BSIZE || logical_block_size > MAXBSIZE
|| (logical_block_size & (logical_block_size - 1)) != 0) {
error = EINVAL;
goto out;
}
rootp = (struct iso_directory_record *)pri->root_directory_record;
isomp = malloc(sizeof *isomp, M_ISOFSMNT, M_WAITOK);
bzero((caddr_t)isomp, sizeof *isomp);
isomp->logical_block_size = logical_block_size;
isomp->volume_space_size = isonum_733 (pri->volume_space_size);
bcopy (rootp, isomp->root, sizeof isomp->root);
isomp->root_extent = isonum_733 (rootp->extent);
isomp->root_size = isonum_733 (rootp->size);
isomp->im_bmask = logical_block_size - 1;
isomp->im_bshift = 0;
while ((1 << isomp->im_bshift) < isomp->logical_block_size)
isomp->im_bshift++;
bp->b_flags |= B_AGE;
brelse(bp);
bp = NULL;
mp->mnt_data = (qaddr_t)isomp;
mp->mnt_stat.f_fsid.val[0] = (long)dev;
mp->mnt_stat.f_fsid.val[1] = mp->mnt_vfc->vfc_typenum;
mp->mnt_maxsymlinklen = 0;
mp->mnt_flag |= MNT_LOCAL;
isomp->im_mountp = mp;
isomp->im_dev = dev;
isomp->im_devvp = devvp;
devvp->v_specflags |= SI_MOUNTEDON;
/* Check the Rock Ridge Extention support */
if (!(argp->flags & ISOFSMNT_NORRIP)) {
if (error = bread(isomp->im_devvp,
(isomp->root_extent + isonum_711(rootp->ext_attr_length)) <<
(isomp->im_bshift - DEV_BSHIFT),
isomp->logical_block_size, NOCRED, &bp))
goto out;
rootp = (struct iso_directory_record *)bp->b_data;
if ((isomp->rr_skip = cd9660_rrip_offset(rootp,isomp)) < 0) {
argp->flags |= ISOFSMNT_NORRIP;
} else {
argp->flags &= ~ISOFSMNT_GENS;
}
/*
* The contents are valid,
* but they will get reread as part of another vnode, so...
*/
bp->b_flags |= B_AGE;
brelse(bp);
bp = NULL;
}
isomp->im_flags = argp->flags&(ISOFSMNT_NORRIP|ISOFSMNT_GENS|ISOFSMNT_EXTATT);
switch (isomp->im_flags&(ISOFSMNT_NORRIP|ISOFSMNT_GENS)) {
default:
isomp->iso_ftype = ISO_FTYPE_DEFAULT;
break;
case ISOFSMNT_GENS|ISOFSMNT_NORRIP:
isomp->iso_ftype = ISO_FTYPE_9660;
break;
case 0:
isomp->iso_ftype = ISO_FTYPE_RRIP;
break;
}
return 0;
out:
if (bp)
brelse(bp);
if (needclose)
(void)VOP_CLOSE(devvp, ronly ? FREAD : FREAD|FWRITE, NOCRED, p);
if (isomp) {
free((caddr_t)isomp, M_ISOFSMNT);
mp->mnt_data = (qaddr_t)0;
}
return error;
}
/*
* Make a filesystem operational.
* Nothing to do at the moment.
*/
/* ARGSUSED */
cd9660_start(mp, flags, p)
struct mount *mp;
int flags;
struct proc *p;
{
return 0;
}
/*
* unmount system call
*/
int
cd9660_unmount(mp, mntflags, p)
struct mount *mp;
int mntflags;
struct proc *p;
{
register struct iso_mnt *isomp;
int i, error, ronly, flags = 0;
if (mntflags & MNT_FORCE)
flags |= FORCECLOSE;
#if 0
mntflushbuf(mp, 0);
if (mntinvalbuf(mp))
return EBUSY;
#endif
if (error = vflush(mp, NULLVP, flags))
return (error);
isomp = VFSTOISOFS(mp);
#ifdef ISODEVMAP
if (isomp->iso_ftype == ISO_FTYPE_RRIP)
iso_dunmap(isomp->im_dev);
#endif
isomp->im_devvp->v_specflags &= ~SI_MOUNTEDON;
error = VOP_CLOSE(isomp->im_devvp, FREAD, NOCRED, p);
vrele(isomp->im_devvp);
free((caddr_t)isomp, M_ISOFSMNT);
mp->mnt_data = (qaddr_t)0;
mp->mnt_flag &= ~MNT_LOCAL;
return (error);
}
/*
* Return root of a filesystem
*/
cd9660_root(mp, vpp)
struct mount *mp;
struct vnode **vpp;
{
struct iso_mnt *imp = VFSTOISOFS(mp);
struct iso_directory_record *dp =
(struct iso_directory_record *)imp->root;
ino_t ino = isodirino(dp, imp);
/*
* With RRIP we must use the `.' entry of the root directory.
* Simply tell vget, that it's a relocated directory.
*/
return (cd9660_vget_internal(mp, ino, vpp,
imp->iso_ftype == ISO_FTYPE_RRIP, dp));
}
/*
* Do operations associated with quotas, not supported
*/
/* ARGSUSED */
int
cd9660_quotactl(mp, cmd, uid, arg, p)
struct mount *mp;
int cmd;
uid_t uid;
caddr_t arg;
struct proc *p;
{
return (EOPNOTSUPP);
}
/*
* Get file system statistics.
*/
cd9660_statfs(mp, sbp, p)
struct mount *mp;
register struct statfs *sbp;
struct proc *p;
{
register struct iso_mnt *isomp;
register struct fs *fs;
isomp = VFSTOISOFS(mp);
#ifdef COMPAT_09
sbp->f_type = 5;
#else
sbp->f_type = 0;
#endif
sbp->f_bsize = isomp->logical_block_size;
sbp->f_iosize = sbp->f_bsize; /* XXX */
sbp->f_blocks = isomp->volume_space_size;
sbp->f_bfree = 0; /* total free blocks */
sbp->f_bavail = 0; /* blocks free for non superuser */
sbp->f_files = 0; /* total files */
sbp->f_ffree = 0; /* free file nodes */
if (sbp != &mp->mnt_stat) {
bcopy(mp->mnt_stat.f_mntonname, sbp->f_mntonname, MNAMELEN);
bcopy(mp->mnt_stat.f_mntfromname, sbp->f_mntfromname, MNAMELEN);
}
/* Use the first spare for flags: */
sbp->f_spare[0] = isomp->im_flags;
return 0;
}
/* ARGSUSED */
int
cd9660_sync(mp, waitfor, cred, p)
struct mount *mp;
int waitfor;
struct ucred *cred;
struct proc *p;
{
return (0);
}
/*
* File handle to vnode
*
* Have to be really careful about stale file handles:
* - check that the inode number is in range
* - call iget() to get the locked inode
* - check for an unallocated inode (i_mode == 0)
* - check that the generation number matches
*/
struct ifid {
ushort ifid_len;
ushort ifid_pad;
int ifid_ino;
long ifid_start;
};
/* ARGSUSED */
int
cd9660_fhtovp(mp, fhp, nam, vpp, exflagsp, credanonp)
register struct mount *mp;
struct fid *fhp;
struct mbuf *nam;
struct vnode **vpp;
int *exflagsp;
struct ucred **credanonp;
{
struct ifid *ifhp = (struct ifid *)fhp;
register struct iso_node *ip;
register struct netcred *np;
register struct iso_mnt *imp = VFSTOISOFS(mp);
struct vnode *nvp;
int error;
#ifdef ISOFS_DBG
printf("fhtovp: ino %d, start %ld\n",
ifhp->ifid_ino, ifhp->ifid_start);
#endif
/*
* Get the export permission structure for this <mp, client> tuple.
*/
np = vfs_export_lookup(mp, &imp->im_export, nam);
if (np == NULL)
return (EACCES);
if (error = VFS_VGET(mp, ifhp->ifid_ino, &nvp)) {
*vpp = NULLVP;
return (error);
}
ip = VTOI(nvp);
if (ip->inode.iso_mode == 0) {
vput(nvp);
*vpp = NULLVP;
return (ESTALE);
}
*vpp = nvp;
*exflagsp = np->netc_exflags;
*credanonp = &np->netc_anon;
return (0);
}
int
cd9660_vget(mp, ino, vpp)
struct mount *mp;
ino_t ino;
struct vnode **vpp;
{
/*
* XXXX
* It would be nice if we didn't always set the `relocated' flag
* and force the extra read, but I don't want to think about fixing
* that right now.
*/
return (cd9660_vget_internal(mp, ino, vpp,
#if 0
VFSTOISOFS(mp)->iso_ftype == ISO_FTYPE_RRIP,
#else
0,
#endif
(struct iso_directory_entry *)0));
}
int
cd9660_vget_internal(mp, ino, vpp, relocated, isodir)
struct mount *mp;
ino_t ino;
struct vnode **vpp;
int relocated;
struct iso_directory_record *isodir;
{
struct proc *p = curproc; /* XXX */
struct iso_mnt *imp;
struct iso_node *ip;
struct buf *bp;
struct vnode *vp, *nvp;
dev_t dev;
int error;
imp = VFSTOISOFS(mp);
dev = imp->im_dev;
if ((*vpp = cd9660_ihashget(dev, ino)) != NULLVP)
return (0);
/* Allocate a new vnode/iso_node. */
if (error = getnewvnode(VT_ISOFS, mp, cd9660_vnodeop_p, &vp)) {
*vpp = NULLVP;
return (error);
}
MALLOC(ip, struct iso_node *, sizeof(struct iso_node), M_ISOFSNODE,
M_WAITOK);
bzero((caddr_t)ip, sizeof(struct iso_node));
lockinit(&ip->i_lock, PINOD, "isonode", 0, 0);
vp->v_data = ip;
ip->i_vnode = vp;
ip->i_dev = dev;
ip->i_number = ino;
/*
* Put it onto its hash chain and lock it so that other requests for
* this inode will block if they arrive while we are sleeping waiting
* for old data structures to be purged or for the contents of the
* disk portion of this inode to be read.
*/
cd9660_ihashins(ip);
if (isodir == 0) {
int lbn, off;
lbn = lblkno(imp, ino);
if (lbn >= imp->volume_space_size) {
vput(vp);
printf("fhtovp: lbn exceed volume space %d\n", lbn);
return (ESTALE);
}
off = blkoff(imp, ino);
if (off + ISO_DIRECTORY_RECORD_SIZE > imp->logical_block_size) {
vput(vp);
printf("fhtovp: crosses block boundary %d\n",
off + ISO_DIRECTORY_RECORD_SIZE);
return (ESTALE);
}
error = bread(imp->im_devvp,
lbn << (imp->im_bshift - DEV_BSHIFT),
imp->logical_block_size, NOCRED, &bp);
if (error) {
vput(vp);
brelse(bp);
printf("fhtovp: bread error %d\n",error);
return (error);
}
isodir = (struct iso_directory_record *)(bp->b_data + off);
if (off + isonum_711(isodir->length) >
imp->logical_block_size) {
vput(vp);
if (bp != 0)
brelse(bp);
printf("fhtovp: directory crosses block boundary %d[off=%d/len=%d]\n",
off +isonum_711(isodir->length), off,
isonum_711(isodir->length));
return (ESTALE);
}
#if 0
if (isonum_733(isodir->extent) +
isonum_711(isodir->ext_attr_length) != ifhp->ifid_start) {
if (bp != 0)
brelse(bp);
printf("fhtovp: file start miss %d vs %d\n",
isonum_733(isodir->extent) + isonum_711(isodir->ext_attr_length),
ifhp->ifid_start);
return (ESTALE);
}
#endif
} else
bp = 0;
ip->i_mnt = imp;
ip->i_devvp = imp->im_devvp;
VREF(ip->i_devvp);
if (relocated) {
/*
* On relocated directories we must
* read the `.' entry out of a dir.
*/
ip->iso_start = ino >> imp->im_bshift;
if (bp != 0)
brelse(bp);
if (error = VOP_BLKATOFF(vp, (off_t)0, NULL, &bp)) {
vput(vp);
return (error);
}
isodir = (struct iso_directory_record *)bp->b_data;
}
ip->iso_extent = isonum_733(isodir->extent);
ip->i_size = isonum_733(isodir->size);
ip->iso_start = isonum_711(isodir->ext_attr_length) + ip->iso_extent;
/*
* Setup time stamp, attribute
*/
vp->v_type = VNON;
switch (imp->iso_ftype) {
default: /* ISO_FTYPE_9660 */
{
struct buf *bp2;
int off;
if ((imp->im_flags & ISOFSMNT_EXTATT)
&& (off = isonum_711(isodir->ext_attr_length)))
VOP_BLKATOFF(vp, (off_t)-(off << imp->im_bshift), NULL,
&bp2);
else
bp2 = NULL;
cd9660_defattr(isodir, ip, bp2);
cd9660_deftstamp(isodir, ip, bp2);
if (bp2)
brelse(bp2);
break;
}
case ISO_FTYPE_RRIP:
cd9660_rrip_analyze(isodir, ip, imp);
break;
}
if (bp != 0)
brelse(bp);
/*
* Initialize the associated vnode
*/
switch (vp->v_type = IFTOVT(ip->inode.iso_mode)) {
case VFIFO:
#ifdef FIFO
vp->v_op = cd9660_fifoop_p;
break;
#else
vput(vp);
return (EOPNOTSUPP);
#endif /* FIFO */
case VCHR:
case VBLK:
/*
* if device, look at device number table for translation
*/
#ifdef ISODEVMAP
if (dp = iso_dmap(dev, ino, 0))
ip->inode.iso_rdev = dp->d_dev;
#endif
vp->v_op = cd9660_specop_p;
if (nvp = checkalias(vp, ip->inode.iso_rdev, mp)) {
/*
* Discard unneeded vnode, but save its iso_node.
* Note that the lock is carried over in the iso_node
* to the replacement vnode.
*/
nvp->v_data = vp->v_data;
vp->v_data = NULL;
vp->v_op = spec_vnodeop_p;
vrele(vp);
vgone(vp);
/*
* Reinitialize aliased inode.
*/
vp = nvp;
ip->i_vnode = vp;
}
break;
}
if (ip->iso_extent == imp->root_extent)
vp->v_flag |= VROOT;
/*
* XXX need generation number?
*/
*vpp = vp;
return (0);
}
/*
* Vnode pointer to File handle
*/
/* ARGSUSED */
cd9660_vptofh(vp, fhp)
struct vnode *vp;
struct fid *fhp;
{
register struct iso_node *ip = VTOI(vp);
register struct ifid *ifhp;
register struct iso_mnt *mp = ip->i_mnt;
ifhp = (struct ifid *)fhp;
ifhp->ifid_len = sizeof(struct ifid);
ifhp->ifid_ino = ip->i_number;
ifhp->ifid_start = ip->iso_start;
#ifdef ISOFS_DBG
printf("vptofh: ino %d, start %ld\n",
ifhp->ifid_ino,ifhp->ifid_start);
#endif
return 0;
}

File diff suppressed because it is too large Load Diff

268
sys/isofs/cd9660/iso.h Normal file
View File

@ -0,0 +1,268 @@
/*-
* Copyright (c) 1994
* The Regents of the University of California. All rights reserved.
*
* This code is derived from software contributed to Berkeley
* by Pace Willisson (pace@blitz.com). The Rock Ridge Extension
* Support code is derived from software contributed to Berkeley
* by Atsushi Murai (amurai@spec.co.jp).
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the University of
* California, Berkeley and its contributors.
* 4. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* @(#)iso.h 8.6 (Berkeley) 5/10/95
*/
#define ISODCL(from, to) (to - from + 1)
struct iso_volume_descriptor {
char type[ISODCL(1,1)]; /* 711 */
char id[ISODCL(2,6)];
char version[ISODCL(7,7)];
char data[ISODCL(8,2048)];
};
/* volume descriptor types */
#define ISO_VD_PRIMARY 1
#define ISO_VD_END 255
#define ISO_STANDARD_ID "CD001"
#define ISO_ECMA_ID "CDW01"
struct iso_primary_descriptor {
char type [ISODCL ( 1, 1)]; /* 711 */
char id [ISODCL ( 2, 6)];
char version [ISODCL ( 7, 7)]; /* 711 */
char unused1 [ISODCL ( 8, 8)];
char system_id [ISODCL ( 9, 40)]; /* achars */
char volume_id [ISODCL ( 41, 72)]; /* dchars */
char unused2 [ISODCL ( 73, 80)];
char volume_space_size [ISODCL ( 81, 88)]; /* 733 */
char unused3 [ISODCL ( 89, 120)];
char volume_set_size [ISODCL (121, 124)]; /* 723 */
char volume_sequence_number [ISODCL (125, 128)]; /* 723 */
char logical_block_size [ISODCL (129, 132)]; /* 723 */
char path_table_size [ISODCL (133, 140)]; /* 733 */
char type_l_path_table [ISODCL (141, 144)]; /* 731 */
char opt_type_l_path_table [ISODCL (145, 148)]; /* 731 */
char type_m_path_table [ISODCL (149, 152)]; /* 732 */
char opt_type_m_path_table [ISODCL (153, 156)]; /* 732 */
char root_directory_record [ISODCL (157, 190)]; /* 9.1 */
char volume_set_id [ISODCL (191, 318)]; /* dchars */
char publisher_id [ISODCL (319, 446)]; /* achars */
char preparer_id [ISODCL (447, 574)]; /* achars */
char application_id [ISODCL (575, 702)]; /* achars */
char copyright_file_id [ISODCL (703, 739)]; /* 7.5 dchars */
char abstract_file_id [ISODCL (740, 776)]; /* 7.5 dchars */
char bibliographic_file_id [ISODCL (777, 813)]; /* 7.5 dchars */
char creation_date [ISODCL (814, 830)]; /* 8.4.26.1 */
char modification_date [ISODCL (831, 847)]; /* 8.4.26.1 */
char expiration_date [ISODCL (848, 864)]; /* 8.4.26.1 */
char effective_date [ISODCL (865, 881)]; /* 8.4.26.1 */
char file_structure_version [ISODCL (882, 882)]; /* 711 */
char unused4 [ISODCL (883, 883)];
char application_data [ISODCL (884, 1395)];
char unused5 [ISODCL (1396, 2048)];
};
#define ISO_DEFAULT_BLOCK_SIZE 2048
struct iso_directory_record {
char length [ISODCL (1, 1)]; /* 711 */
char ext_attr_length [ISODCL (2, 2)]; /* 711 */
u_char extent [ISODCL (3, 10)]; /* 733 */
u_char size [ISODCL (11, 18)]; /* 733 */
char date [ISODCL (19, 25)]; /* 7 by 711 */
char flags [ISODCL (26, 26)];
char file_unit_size [ISODCL (27, 27)]; /* 711 */
char interleave [ISODCL (28, 28)]; /* 711 */
char volume_sequence_number [ISODCL (29, 32)]; /* 723 */
char name_len [ISODCL (33, 33)]; /* 711 */
char name [1]; /* XXX */
};
/* can't take sizeof(iso_directory_record), because of possible alignment
of the last entry (34 instead of 33) */
#define ISO_DIRECTORY_RECORD_SIZE 33
struct iso_extended_attributes {
u_char owner [ISODCL (1, 4)]; /* 723 */
u_char group [ISODCL (5, 8)]; /* 723 */
u_char perm [ISODCL (9, 10)]; /* 9.5.3 */
char ctime [ISODCL (11, 27)]; /* 8.4.26.1 */
char mtime [ISODCL (28, 44)]; /* 8.4.26.1 */
char xtime [ISODCL (45, 61)]; /* 8.4.26.1 */
char ftime [ISODCL (62, 78)]; /* 8.4.26.1 */
char recfmt [ISODCL (79, 79)]; /* 711 */
char recattr [ISODCL (80, 80)]; /* 711 */
u_char reclen [ISODCL (81, 84)]; /* 723 */
char system_id [ISODCL (85, 116)]; /* achars */
char system_use [ISODCL (117, 180)];
char version [ISODCL (181, 181)]; /* 711 */
char len_esc [ISODCL (182, 182)]; /* 711 */
char reserved [ISODCL (183, 246)];
u_char len_au [ISODCL (247, 250)]; /* 723 */
};
/* CD-ROM Format type */
enum ISO_FTYPE { ISO_FTYPE_DEFAULT, ISO_FTYPE_9660, ISO_FTYPE_RRIP, ISO_FTYPE_ECMA };
#ifndef ISOFSMNT_ROOT
#define ISOFSMNT_ROOT 0
#endif
struct iso_mnt {
int im_flags;
struct mount *im_mountp;
dev_t im_dev;
struct vnode *im_devvp;
int logical_block_size;
int im_bshift;
int im_bmask;
int volume_space_size;
struct netexport im_export;
char root[ISODCL (157, 190)];
int root_extent;
int root_size;
enum ISO_FTYPE iso_ftype;
int rr_skip;
int rr_skip0;
};
#define VFSTOISOFS(mp) ((struct iso_mnt *)((mp)->mnt_data))
#define blkoff(imp, loc) ((loc) & (imp)->im_bmask)
#define lblktosize(imp, blk) ((blk) << (imp)->im_bshift)
#define lblkno(imp, loc) ((loc) >> (imp)->im_bshift)
#define blksize(imp, ip, lbn) ((imp)->logical_block_size)
int cd9660_mount __P((struct mount *,
char *, caddr_t, struct nameidata *, struct proc *));
int cd9660_start __P((struct mount *, int, struct proc *));
int cd9660_unmount __P((struct mount *, int, struct proc *));
int cd9660_root __P((struct mount *, struct vnode **));
int cd9660_quotactl __P((struct mount *, int, uid_t, caddr_t, struct proc *));
int cd9660_statfs __P((struct mount *, struct statfs *, struct proc *));
int cd9660_sync __P((struct mount *, int, struct ucred *, struct proc *));
int cd9660_vget __P((struct mount *, ino_t, struct vnode **));
int cd9660_fhtovp __P((struct mount *, struct fid *, struct mbuf *,
struct vnode **, int *, struct ucred **));
int cd9660_vptofh __P((struct vnode *, struct fid *));
int cd9660_init __P((struct vfsconf *));
#define cd9660_sysctl ((int (*) __P((int *, u_int, void *, size_t *, void *, \
size_t, struct proc *)))eopnotsupp)
int cd9660_mountroot __P((void));
extern int (**cd9660_vnodeop_p)();
extern int (**cd9660_specop_p)();
#ifdef FIFO
extern int (**cd9660_fifoop_p)();
#endif
static __inline int
isonum_711(p)
u_char *p;
{
return *p;
}
static __inline int
isonum_712(p)
char *p;
{
return *p;
}
#ifndef UNALIGNED_ACCESS
static __inline int
isonum_723(p)
u_char *p;
{
return *p|(p[1] << 8);
}
static __inline int
isonum_733(p)
u_char *p;
{
return *p|(p[1] << 8)|(p[2] << 16)|(p[3] << 24);
}
#else /* UNALIGNED_ACCESS */
#if BYTE_ORDER == LITTLE_ENDIAN
static __inline int
isonum_723(p)
u_char *p
{
return *(u_int16t *)p;
}
static __inline int
isonum_733(p)
u_char *p;
{
return *(u_int32t *)p;
}
#endif
#if BYTE_ORDER == BIG_ENDIAN
static __inline int
isonum_723(p)
u_char *p
{
return *(u_int16t *)(p + 2);
}
static __inline int
isonum_733(p)
u_char *p;
{
return *(u_int32t *)(p + 4);
}
#endif
#endif /* UNALIGNED_ACCESS */
int isofncmp __P((u_char *, int, u_char *, int));
void isofntrans __P((u_char *, int, u_char *, u_short *, int, int));
ino_t isodirino __P((struct iso_directory_record *, struct iso_mnt *));
/*
* Associated files have a leading '='.
*/
#define ASSOCCHAR '='