First version.

Reviewed by:	David O'Brien <obrien@NUXI.com>
This commit is contained in:
semenu 1999-02-03 04:07:38 +00:00
parent 85b72afac3
commit bb91a31741
11 changed files with 4205 additions and 0 deletions

301
sys/ntfs/ntfs.h Normal file
View File

@ -0,0 +1,301 @@
/*-
* Copyright (c) 1998, 1999 Semen Ustimenko
* All rights reserved.
*
* 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.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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.
*
* $Id: ntfs.h,v 1.9 1999/02/02 01:54:54 semen Exp $
*/
#define DIAGNOSTIC
/*#define NTFS_DEBUG 1*/
typedef u_int64_t cn_t;
typedef u_int16_t wchar;
#pragma pack(1)
#define BBSIZE 1024
#define BBOFF ((off_t)(0))
#define BBLOCK ((daddr_t)(0))
#define NTFS_MFTINO 0
#define NTFS_VOLUMEINO 3
#define NTFS_ATTRDEFINO 4
#define NTFS_ROOTINO 5
#define NTFS_BITMAPINO 6
#define NTFS_BOOTINO 7
#define NTFS_BADCLUSINO 8
#define NTFS_UPCASEINO 10
#define NTFS_MAXFILENAME 255
struct fixuphdr {
u_int32_t fh_magic;
u_int16_t fh_foff;
u_int16_t fh_fnum;
};
#define NTFS_AF_INRUN 0x00000001
struct attrhdr {
u_int32_t a_type;
u_int32_t reclen;
u_int8_t a_flag;
u_int8_t a_namelen;
u_int8_t a_nameoff;
u_int8_t reserved1;
u_int8_t a_compression;
u_int8_t reserved2;
u_int16_t a_index;
};
#define NTFS_A_STD 0x10
#define NTFS_A_ATTRLIST 0x20
#define NTFS_A_NAME 0x30
#define NTFS_A_VOLUMENAME 0x60
#define NTFS_A_DATA 0x80
#define NTFS_A_INDXROOT 0x90
#define NTFS_A_INDX 0xA0
#define NTFS_A_INDXBITMAP 0xB0
#define NTFS_MAXATTRNAME 255
struct attr {
struct attrhdr a_hdr;
union {
struct {
u_int16_t a_datalen;
u_int16_t reserved1;
u_int16_t a_dataoff;
u_int16_t a_indexed;
} a_S_r;
struct {
cn_t a_vcnstart;
cn_t a_vcnend;
u_int16_t a_dataoff;
u_int16_t a_compressalg;
u_int32_t reserved1;
u_int64_t a_allocated;
u_int64_t a_datalen;
u_int64_t a_initialized;
} a_S_nr;
} a_S;
};
#define a_r a_S.a_S_r
#define a_nr a_S.a_S_nr
typedef struct {
u_int64_t t_create;
u_int64_t t_write;
u_int64_t t_mftwrite;
u_int64_t t_access;
} ntfs_times_t;
#define NTFS_FFLAG_RDONLY 0x01LL
#define NTFS_FFLAG_HIDDEN 0x02LL
#define NTFS_FFLAG_SYSTEM 0x04LL
#define NTFS_FFLAG_ARCHIVE 0x20LL
#define NTFS_FFLAG_COMPRESSED 0x0800LL
#define NTFS_FFLAG_DIR 0x10000000LL
struct attr_name {
u_int32_t n_pnumber; /* Parent ntnode */
u_int32_t reserved;
ntfs_times_t n_times;
u_int64_t n_size;
u_int64_t n_attrsz;
u_int64_t n_flag;
u_int8_t n_namelen;
u_int8_t n_nametype;
u_int16_t n_name[1];
};
#define NTFS_IRFLAG_INDXALLOC 0x00000001
struct attr_indexroot {
u_int32_t ir_unkn1; /* always 0x30 */
u_int32_t ir_unkn2; /* always 0x1 */
u_int32_t ir_size;/* ??? */
u_int32_t ir_unkn3; /* number of cluster */
u_int32_t ir_unkn4; /* always 0x10 */
u_int32_t ir_datalen; /* sizeof simething */
u_int32_t ir_allocated; /* same as above */
u_int16_t ir_flag;/* ?? always 1 */
u_int16_t ir_unkn7;
};
struct attr_attrlist {
u_int32_t al_type; /* Attribute type */
u_int16_t reclen; /* length of this entry */
u_int8_t al_namelen; /* Attribute name len */
u_int8_t al_nameoff; /* Name offset from entry start */
u_int64_t al_vcnstart; /* VCN number */
u_int32_t al_inumber; /* Parent ntnode */
u_int32_t reserved;
u_int16_t al_index; /* Attribute index in MFT record */
u_int16_t al_name[1]; /* Name */
};
#define NTFS_INDXMAGIC (u_int32_t)(0x58444E49)
struct attr_indexalloc {
struct fixuphdr ia_fixup;
u_int64_t unknown1;
cn_t ia_bufcn;
u_int16_t ia_hdrsize;
u_int16_t unknown2;
u_int32_t ia_inuse;
u_int32_t ia_allocated;
};
#define NTFS_IEFLAG_SUBNODE 0x00000001
#define NTFS_IEFLAG_LAST 0x00000002
struct attr_indexentry {
u_int32_t ie_number;
u_int32_t unknown1;
u_int16_t reclen;
u_int16_t ie_size;
u_int32_t ie_flag;/* 1 - has subnodes, 2 - last */
u_int32_t ie_fpnumber;
u_int32_t unknown2;
ntfs_times_t ie_ftimes;
u_int64_t ie_fallocated;
u_int64_t ie_fsize;
u_int64_t ie_fflag;
u_int8_t ie_fnamelen;
u_int8_t ie_fnametype;
wchar ie_fname[NTFS_MAXFILENAME];
/* cn_t ie_bufcn; buffer with subnodes */
};
#define NTFS_FILEMAGIC (u_int32_t)(0x454C4946)
struct filerec {
struct fixuphdr fr_fixup;
u_int8_t reserved[8];
u_int16_t fr_seqnum; /* Sequence number */
u_int16_t fr_nlink;
u_int16_t fr_attroff; /* offset to attributes */
u_int16_t fr_flags; /* 1-nonresident attr, 2-directory */
u_int32_t fr_size;/* hdr + attributes */
u_int32_t fr_allocated; /* allocated length of record */
u_int64_t fr_mainrec; /* main record */
u_int16_t fr_attrnum; /* maximum attr number + 1 ??? */
};
#define NTFS_ADFLAG_NONRES 0x0080 /* Attrib can be non resident */
#define NTFS_ADFLAG_INDEX 0x0002 /* Attrib can be indexed */
struct attrdef {
wchar ad_name[0x40];
u_int32_t ad_type;
u_int32_t reserved1[2];
u_int32_t ad_flag;
u_int64_t ad_minlen;
u_int64_t ad_maxlen; /* -1 for nonlimited */
};
struct ntvattrdef {
char ad_name[0x40];
int ad_namelen;
u_int32_t ad_type;
};
struct bootfile {
u_int8_t reserved1[3]; /* asm jmp near ... */
u_int8_t bf_sysid[8]; /* 'NTFS ' */
u_int16_t bf_bps; /* bytes per sector */
u_int8_t bf_spc; /* sectors per cluster */
u_int8_t reserved2[7]; /* unused (zeroed) */
u_int8_t bf_media; /* media desc. (0xF8) */
u_int8_t reserved3[2];
u_int16_t bf_spt; /* sectors per track */
u_int16_t bf_heads; /* number of heads */
u_int8_t reserver4[12];
u_int64_t bf_spv; /* sectors per volume */
cn_t bf_mftcn; /* $MFT cluster number */
cn_t bf_mftmirrcn; /* $MFTMirr cn */
u_int8_t bf_mftrecsz; /* MFT record size (clust) */
/* 0xF6 inducates 1/4 */
u_int32_t bf_ibsz; /* index buffer size */
u_int32_t bf_volsn; /* volume ser. num. */
};
#define NTFS_SYSNODESNUM 0x0B
struct ntfsmount {
struct mount *ntm_mountp;
struct bootfile ntm_bootfile;
dev_t ntm_dev;
struct vnode *ntm_devvp;
struct vnode *ntm_sysvn[NTFS_SYSNODESNUM];
wchar *ntm_upcase;
u_int32_t ntm_bpmftrec;
uid_t ntm_uid;
gid_t ntm_gid;
mode_t ntm_mode;
u_long ntm_flag;
struct ntvattrdef *ntm_ad;
int ntm_adnum;
};
#define ntm_mftcn ntm_bootfile.bf_mftcn
#define ntm_mftmirrcn ntm_bootfile.bf_mftmirrcn
#define ntm_mftrecsz ntm_bootfile.bf_mftrecsz
#define ntm_spc ntm_bootfile.bf_spc
#define ntm_bps ntm_bootfile.bf_bps
#pragma pack()
#define NTFS_NEXTREC(s, type) ((type)(((caddr_t) s) + (s)->reclen))
/* Convert mount ptr to ntfsmount ptr. */
#define VFSTONTFS(mp) ((struct ntfsmount *)((mp)->mnt_data))
#define VTONT(v) ((struct ntnode *)((struct vnode *)(v)->v_data))
#define NTTOV(i) (i->i_vnode)
#define ntfs_cntobn(cn) (daddr_t)((cn) * (ntmp->ntm_spc))
#define ntfs_cntob(cn) (off_t)((cn) * (ntmp)->ntm_spc * (ntmp)->ntm_bps)
#define ntfs_btocn(off) (cn_t)((off) / ((ntmp)->ntm_spc * (ntmp)->ntm_bps))
#define ntfs_btocl(off) (cn_t)((off + ntfs_cntob(1) - 1) / ((ntmp)->ntm_spc * (ntmp)->ntm_bps))
#define ntfs_btocnoff(off) (off_t)((off) % ((ntmp)->ntm_spc * (ntmp)->ntm_bps))
#define ntfs_bntob(bn) (daddr_t)((bn) * (ntmp)->ntm_bps)
#define ntfs_bpbl (daddr_t)((ntmp)->ntm_bps)
#if __FreeBSD_version >= 300000
MALLOC_DECLARE(M_NTFSMNT);
MALLOC_DECLARE(M_NTFSNODE);
MALLOC_DECLARE(M_NTFSDIR);
MALLOC_DECLARE(M_NTFSIHASH);
#endif
#if defined(NTFS_DEBUG)
#define dprintf(a) printf a
#if NTFS_DEBUG > 1
#define ddprintf(a) printf a
#else
#define ddprintf(a)
#endif
#else
#define dprintf(a)
#define ddprintf(a)
#endif
extern vop_t **ntfs_vnodeop_p;
struct ntnode;
void ntfs_ihashinit __P((void));
struct vnode *ntfs_ihashlookup __P((dev_t, ino_t));
struct vnode *ntfs_ihashget __P((dev_t, ino_t));
void ntfs_ihashins __P((struct ntnode *));
void ntfs_ihashrem __P((register struct ntnode *));

116
sys/ntfs/ntfs_compr.c Normal file
View File

@ -0,0 +1,116 @@
/*-
* Copyright (c) 1998, 1999 Semen Ustimenko
* All rights reserved.
*
* 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.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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.
*
* $Id: ntfs_compr.c,v 1.4 1999/02/02 01:54:54 semen Exp $
*/
#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 <sys/mount.h>
#include <sys/buf.h>
#include <sys/file.h>
#include <sys/malloc.h>
#include <machine/clock.h>
#include <miscfs/specfs/specdev.h>
#include <ntfs/ntfs.h>
#include <ntfs/ntfs_compr.h>
#define GET_UINT16(addr) (*((u_int16_t *)(addr)))
int
ntfs_uncompblock(
u_int8_t * buf,
const u_int8_t * cbuf)
{
u_int32_t ctag;
int len, dshift, lmask;
int blen, boff;
int i, j;
int pos, cpos;
len = GET_UINT16(cbuf) & 0xFFF;
dprintf(("ntfs_uncompblock: block length: %d + 3, 0x%x,0x%04x\n",
len, len, GET_UINT16(cbuf)));
if (!(GET_UINT16(cbuf) & 0x8000)) {
if ((len + 1) != NTFS_COMPBLOCK_SIZE) {
dprintf(("ntfs_uncompblock: len: %x instead of %d\n",
len, 0xfff));
}
memcpy(buf, cbuf + 2, len + 1);
bzero(buf + len + 1, NTFS_COMPBLOCK_SIZE - 1 - len);
return len + 3;
}
cpos = 2;
pos = 0;
while ((cpos < len + 3) && (pos < NTFS_COMPBLOCK_SIZE)) {
ctag = cbuf[cpos++];
for (i = 0; (i < 8) && (pos < NTFS_COMPBLOCK_SIZE); i++) {
if (ctag & 1) {
for (j = pos - 1, lmask = 0xFFF, dshift = 12;
j >= 0x10; j >>= 1) {
dshift--;
lmask >>= 1;
}
boff = -1 - (GET_UINT16(cbuf + cpos) >> dshift);
blen = 3 + (GET_UINT16(cbuf + cpos) & lmask);
for (j = 0; (j < blen) && (pos < NTFS_COMPBLOCK_SIZE); j++) {
buf[pos] = buf[pos + boff];
pos++;
}
cpos += 2;
} else {
buf[pos++] = cbuf[cpos++];
}
ctag >>= 1;
}
}
return len + 3;
}
int
ntfs_uncompunit(
struct ntfsmount * ntmp,
u_int8_t * uup,
const u_int8_t * cup)
{
int i;
int off = 0;
int new;
for (i = 0; i * NTFS_COMPBLOCK_SIZE < ntfs_cntob(NTFS_COMPUNIT_CL); i++) {
new = ntfs_uncompblock(uup + i * NTFS_COMPBLOCK_SIZE, cup + off);
if (new == 0)
return (EINVAL);
off += new;
}
return (0);
}

33
sys/ntfs/ntfs_compr.h Normal file
View File

@ -0,0 +1,33 @@
/*-
* Copyright (c) 1998, 1999 Semen Ustimenko
* All rights reserved.
*
* 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.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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.
*
* $Id: ntfs_compr.h,v 1.3 1999/01/28 03:56:06 semen Exp $
*/
#define NTFS_COMPBLOCK_SIZE 0x1000
#define NTFS_COMPUNIT_CL 16
int ntfs_uncompblock(u_int8_t *, const u_int8_t *);
int ntfs_uncompunit(struct ntfsmount *, u_int8_t *, const u_int8_t *);

29
sys/ntfs/ntfs_extern.h Normal file
View File

@ -0,0 +1,29 @@
/*-
* Copyright (c) 1998, 1999 Semen Ustimenko
* All rights reserved.
*
* 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.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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.
*
* $Id: ntfs_extern.h,v 1.3 1999/01/28 03:56:06 semen Exp $
*/
struct sockaddr;

157
sys/ntfs/ntfs_ihash.c Normal file
View File

@ -0,0 +1,157 @@
/*
* Copyright (c) 1982, 1986, 1989, 1991, 1993, 1995
* The Regents of the University of California. All rights reserved.
*
* 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.
*
* @(#)ufs_ihash.c 8.7 (Berkeley) 5/17/95
* $Id: ntfs_ihash.c,v 1.2 1999/01/02 01:17:38 semen Exp $
*/
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/kernel.h>
#include <sys/lock.h>
#include <sys/vnode.h>
#include <sys/malloc.h>
#include <sys/proc.h>
#include <ntfs/ntfs.h>
#include <ntfs/ntfs_inode.h>
MALLOC_DEFINE(M_NTFSIHASH, "NTFS ihash", "NTFS Inode hash tables");
/*
* Structures associated with inode cacheing.
*/
static LIST_HEAD(ihashhead, ntnode) *ntfs_ihashtbl;
static u_long ntfs_ihash; /* size of hash table - 1 */
#define NTNOHASH(device, inum) (&ntfs_ihashtbl[((device) + (inum)) & ntfs_ihash])
static struct simplelock ntfs_ihash_slock;
/*
* Initialize inode hash table.
*/
void
ntfs_ihashinit()
{
ntfs_ihashtbl = hashinit(desiredvnodes, M_NTFSIHASH, &ntfs_ihash);
simple_lock_init(&ntfs_ihash_slock);
}
/*
* Use the device/inum pair to find the incore inode, and return a pointer
* to it. If it is in core, return it, even if it is locked.
*/
struct vnode *
ntfs_ihashlookup(dev, inum)
dev_t dev;
ino_t inum;
{
struct ntnode *ip;
simple_lock(&ntfs_ihash_slock);
for (ip = NTNOHASH(dev, inum)->lh_first; ip; ip = ip->i_hash.le_next)
if (inum == ip->i_number && dev == ip->i_dev)
break;
simple_unlock(&ntfs_ihash_slock);
if (ip)
return (NTTOV(ip));
return (NULLVP);
}
/*
* 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 *
ntfs_ihashget(dev, inum)
dev_t dev;
ino_t inum;
{
struct proc *p = curproc; /* XXX */
struct ntnode *ip;
struct vnode *vp;
loop:
simple_lock(&ntfs_ihash_slock);
for (ip = NTNOHASH(dev, inum)->lh_first; ip; ip = ip->i_hash.le_next) {
if (inum == ip->i_number && dev == ip->i_dev) {
vp = NTTOV(ip);
simple_lock(&vp->v_interlock);
simple_unlock(&ntfs_ihash_slock);
if (vget(vp, LK_EXCLUSIVE | LK_INTERLOCK, p))
goto loop;
return (vp);
}
}
simple_unlock(&ntfs_ihash_slock);
return (NULL);
}
/*
* Insert the inode into the hash table, and return it locked.
*/
void
ntfs_ihashins(ip)
struct ntnode *ip;
{
struct proc *p = curproc; /* XXX */
struct ihashhead *ipp;
/* lock the inode, then put it on the appropriate hash list */
lockmgr(&ip->i_lock, LK_EXCLUSIVE, (struct simplelock *)0, p);
simple_lock(&ntfs_ihash_slock);
ipp = NTNOHASH(ip->i_dev, ip->i_number);
LIST_INSERT_HEAD(ipp, ip, i_hash);
ip->i_flag |= IN_HASHED;
simple_unlock(&ntfs_ihash_slock);
}
/*
* Remove the inode from the hash table.
*/
void
ntfs_ihashrem(ip)
struct ntnode *ip;
{
simple_lock(&ntfs_ihash_slock);
if (ip->i_flag & IN_HASHED) {
ip->i_flag &= ~IN_HASHED;
LIST_REMOVE(ip, i_hash);
#ifdef DIAGNOSTIC
ip->i_hash.le_next = NULL;
ip->i_hash.le_prev = NULL;
#endif
}
simple_unlock(&ntfs_ihash_slock);
}

100
sys/ntfs/ntfs_inode.h Normal file
View File

@ -0,0 +1,100 @@
/*-
* Copyright (c) 1998, 1999 Semen Ustimenko
* All rights reserved.
*
* 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.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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.
*
* $Id: ntfs_inode.h,v 1.8 1999/02/02 01:54:54 semen Exp $
*/
/* These flags are kept in i_flag. */
#if __FreeBSD_version >= 300000
#define IN_ACCESS 0x0001 /* Access time update request. */
#define IN_CHANGE 0x0002 /* Inode change time update request. */
#define IN_UPDATE 0x0004 /* Modification time update request. */
#define IN_MODIFIED 0x0008 /* Inode has been modified. */
#define IN_RENAME 0x0010 /* Inode is being renamed. */
#define IN_SHLOCK 0x0020 /* File has shared lock. */
#define IN_EXLOCK 0x0040 /* File has exclusive lock. */
#define IN_HASHED 0x0080 /* Inode is on hash list */
#define IN_LAZYMOD 0x0100 /* Modified, but don't write yet. */
#else
#define IN_ACCESS 0x0001 /* Access time update request. */
#define IN_CHANGE 0x0002 /* Inode change time update request. */
#define IN_EXLOCK 0x0004 /* File has exclusive lock. */
#define IN_LOCKED 0x0008 /* Inode lock. */
#define IN_LWAIT 0x0010 /* Process waiting on file lock. */
#define IN_MODIFIED 0x0020 /* Inode has been modified. */
#define IN_RENAME 0x0040 /* Inode is being renamed. */
#define IN_SHLOCK 0x0080 /* File has shared lock. */
#define IN_UPDATE 0x0100 /* Modification time update request. */
#define IN_WANTED 0x0200 /* Inode is wanted by a process. */
#define IN_RECURSE 0x0400 /* Recursion expected */
#endif
#define IN_LOADED 0x8000 /* ntvattrs loaded */
#define IN_PRELOADED 0x4000 /* loaded from directory entry */
#define IN_AATTRNAME 0x2000 /* spaec allocated for i_defattrname */
struct ntnode {
#if __FreeBSD_version >= 300000
struct lock i_lock; /* Must be first */
#endif
LIST_ENTRY(ntnode) i_hash;
struct ntnode *i_next;
struct ntnode **i_prev;
struct vnode *i_vnode;
struct vnode *i_devvp;
struct ntfsmount *i_mp;
enum vtype i_type;
dev_t i_dev;
ino_t i_number;
u_int32_t i_flag;
long i_nlink; /* MFR */
ino_t i_mainrec; /* MFR */
u_int32_t i_frflag; /* MFR */
ntfs_times_t i_times; /* $NAME/dirinfo */
ino_t i_pnumber; /* $NAME/dirinfo */
u_int32_t i_fflag; /* $NAME/dirinfo */
u_int64_t i_size; /* defattr/dirinfo: */
u_int64_t i_allocated; /* defattr/dirinfo */
u_int32_t i_lastdattr;
u_int32_t i_lastdblnum;
u_int32_t i_lastdoff;
u_int32_t i_lastdnum;
caddr_t i_dirblbuf;
u_int32_t i_dirblsz;
uid_t i_uid;
gid_t i_gid;
mode_t i_mode;
u_int32_t i_defattr;
char *i_defattrname;
struct ntvattr *i_vattrp;
int i_lockcount; /* Process lock count (recursion) */
pid_t i_lockholder; /* DEBUG: holder of ntnode lock. */
pid_t i_lockwaiter; /* DEBUG: waiter of ntnode lock. */
};

1450
sys/ntfs/ntfs_subr.c Normal file

File diff suppressed because it is too large Load Diff

96
sys/ntfs/ntfs_subr.h Normal file
View File

@ -0,0 +1,96 @@
/*-
* Copyright (c) 1998, 1999 Semen Ustimenko
* All rights reserved.
*
* 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.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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.
*
* $Id: ntfs_subr.h,v 1.3 1999/02/02 01:54:54 semen Exp $
*/
struct ntvattr {
struct ntvattr *va_nextp;
u_int32_t va_vflag;
struct ntnode *va_ip;
u_int32_t va_flag;
u_int32_t va_type;
u_int8_t va_namelen;
char va_name[NTFS_MAXATTRNAME];
u_int32_t va_compression;
u_int32_t va_compressalg;
u_int32_t va_datalen;
u_int32_t va_allocated;
cn_t va_vcnstart;
cn_t va_vcnend;
u_int16_t va_index;
union {
struct {
cn_t * cn;
cn_t * cl;
u_int32_t cnt;
} vrun;
caddr_t datap;
struct attr_name *name;
struct attr_indexroot *iroot;
struct attr_indexalloc *ialloc;
} va_d;
};
#define va_vruncn va_d.vrun.cn
#define va_vruncl va_d.vrun.cl
#define va_vruncnt va_d.vrun.cnt
#define va_datap va_d.datap
#define va_a_name va_d.name
#define va_a_iroot va_d.iroot
#define va_a_ialloc va_d.ialloc
#define uastrcmp(a,b,c,d) ntfs_uastrcmp(ntmp,a,b,c,d)
int ntfs_procfixups __P(( struct ntfsmount *, u_int32_t, caddr_t, size_t ));
int ntfs_parserun __P(( cn_t *, cn_t *, u_int8_t *, size_t, int *));
int ntfs_runtocn __P(( cn_t *, struct ntfsmount *, u_int8_t *, size_t, cn_t));
int ntfs_breadntvattr_plain __P(( struct ntfsmount *, struct ntnode *, struct ntvattr *, off_t, size_t, void *,size_t *));
int ntfs_breadattr_plain __P(( struct ntfsmount *, struct ntnode *, u_int32_t, char *, off_t, size_t, void *,size_t *));
int ntfs_breadattr __P(( struct ntfsmount *, struct ntnode *, u_int32_t, char *, off_t, size_t, void *));
int ntfs_filesize __P(( struct ntfsmount *, struct ntnode *, u_int64_t *, u_int64_t *));
int ntfs_times __P(( struct ntfsmount *, struct ntnode *, ntfs_times_t *));
struct timespec ntfs_nttimetounix __P(( u_int64_t ));
int ntfs_ntreaddir __P(( struct ntfsmount *, struct ntnode *, u_int32_t, struct attr_indexentry **));
wchar ntfs_toupper __P(( struct ntfsmount *, wchar ));
int ntfs_uustricmp __P(( struct ntfsmount *, wchar *, int, wchar *, int ));
int ntfs_uastricmp __P(( struct ntfsmount *, wchar *, int, char *, int ));
int ntfs_uastrcmp __P(( struct ntfsmount *, wchar *, int, char *, int ));
int ntfs_runtovrun __P(( cn_t **, cn_t **, u_int32_t *, u_int8_t *));
int ntfs_attrtontvattr __P(( struct ntfsmount *, struct ntvattr **, struct attr * ));
void ntfs_freentvattr __P(( struct ntvattr * ));
int ntfs_loadntvattrs __P(( struct ntfsmount *, struct vnode *, caddr_t, struct ntvattr **));
struct ntvattr * ntfs_findntvattr __P(( struct ntfsmount *, struct ntnode *, u_int32_t, cn_t ));
int ntfs_ntlookup __P(( struct ntfsmount *, struct ntnode *, struct componentname *, struct ntnode **));
int ntfs_isnamepermitted __P(( struct ntfsmount *, struct attr_indexentry * ));
int ntfs_ntvattrrele __P(( struct ntvattr * ));
int ntfs_ntvattrget __P(( struct ntfsmount *, struct ntnode *, u_int32_t, char *, cn_t , struct ntvattr **));
int ntfs_ntget __P(( struct ntfsmount *, ino_t, struct ntnode **));
void ntfs_ntrele __P(( struct ntnode *));
int ntfs_loadnode __P(( struct ntfsmount *, struct ntnode * ));
int ntfs_ntlookupattr __P(( struct ntfsmount *, char *, int, int *, char **));

800
sys/ntfs/ntfs_vfsops.c Normal file
View File

@ -0,0 +1,800 @@
/*-
* Copyright (c) 1998, 1999 Semen Ustimenko
* All rights reserved.
*
* 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.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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.
*
* $Id: ntfs_vfsops.c,v 1.9 1999/02/02 01:54:54 semen Exp $
*/
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/namei.h>
#include <sys/conf.h>
#include <sys/proc.h>
#include <sys/kernel.h>
#include <sys/vnode.h>
#include <sys/mount.h>
#include <sys/buf.h>
#include <sys/fcntl.h>
#include <sys/malloc.h>
#include <vm/vm.h>
#include <vm/vm_param.h>
#include <vm/vm_prot.h>
#include <vm/vm_page.h>
#include <vm/vm_object.h>
#include <vm/vm_extern.h>
#include <miscfs/specfs/specdev.h>
/*#define NTFS_DEBUG 1*/
#include <ntfs/ntfs.h>
#include <ntfs/ntfs_inode.h>
#include <ntfs/ntfs_subr.h>
#include <ntfs/ntfs_extern.h>
#include <ntfs/ntfsmount.h>
#if __FreeBSD_version >= 300000
MALLOC_DEFINE(M_NTFSMNT, "NTFS mount", "NTFS mount structure");
MALLOC_DEFINE(M_NTFSNODE,"NTFS node", "NTFS node information");
MALLOC_DEFINE(M_NTFSDIR,"NTFS dir", "NTFS dir buffer");
#endif
static int ntfs_mount __P((struct mount *, char *, caddr_t,
struct nameidata *, struct proc *));
static int ntfs_quotactl __P((struct mount *, int, uid_t, caddr_t,
struct proc *));
static int ntfs_root __P((struct mount *, struct vnode **));
static int ntfs_start __P((struct mount *, int, struct proc *));
static int ntfs_statfs __P((struct mount *, struct statfs *,
struct proc *));
static int ntfs_sync __P((struct mount *, int, struct ucred *,
struct proc *));
static int ntfs_unmount __P((struct mount *, int, struct proc *));
static int ntfs_vget __P((struct mount *mp, ino_t ino,
struct vnode **vpp));
static int ntfs_mountfs __P((register struct vnode *, struct mount *,
struct ntfs_args *, struct proc *));
static int ntfs_vptofh __P((struct vnode *, struct fid *));
#if __FreeBSD_version >= 300000
static int ntfs_init __P((struct vfsconf *));
static int ntfs_fhtovp __P((struct mount *, struct fid *,
struct sockaddr *, struct vnode **,
int *, struct ucred **));
#else
static int ntfs_init __P((void));
static int ntfs_fhtovp __P((struct mount *, struct fid *,
struct mbuf *, struct vnode **,
int *, struct ucred **));
#endif
#if __FreeBSD_version >= 300000
static int
ntfs_init (
struct vfsconf *vcp )
#else
static int
ntfs_init ()
#endif
{
static first=1;
if(!first) return (0);
first = 1;
printf("ntfs_init(): \n");
ntfs_ihashinit();
return 0;
}
static int
ntfs_mount (
struct mount *mp,
char *path,
caddr_t data,
struct nameidata *ndp,
struct proc *p )
{
u_int size;
int err = 0;
struct vnode *devvp;
struct ntfs_args args;
/*
* Use NULL path to flag a root mount
*/
if( path == NULL) {
/*
***
* Mounting root file system
***
*/
/* Get vnode for root device*/
if( bdevvp( rootdev, &rootvp))
panic("ffs_mountroot: can't setup bdevvp for root");
/*
* FS specific handling
*/
mp->mnt_flag |= MNT_RDONLY; /* XXX globally applicable?*/
/*
* Attempt mount
*/
if( ( err = ntfs_mountfs(rootvp, mp, &args, p)) != 0) {
/* fs specific cleanup (if any)*/
goto error_1;
}
goto dostatfs; /* success*/
}
/*
***
* Mounting non-root file system or updating a file system
***
*/
/* copy in user arguments*/
err = copyin(data, (caddr_t)&args, sizeof (struct ntfs_args));
if (err)
goto error_1; /* can't get arguments*/
/*
* 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) {
printf("ntfs_mount(): MNT_UPDATE not supported\n");
err = EINVAL;
goto error_1;
#if 0
ump = VFSTOUFS(mp);
fs = ump->um_fs;
err = 0;
if (fs->fs_ronly == 0 && (mp->mnt_flag & MNT_RDONLY)) {
flags = WRITECLOSE;
if (mp->mnt_flag & MNT_FORCE)
flags |= FORCECLOSE;
if (vfs_busy(mp)) {
err = EBUSY;
goto error_1;
}
err = ffs_flushfiles(mp, flags, p);
vfs_unbusy(mp);
}
if (!err && (mp->mnt_flag & MNT_RELOAD))
err = ffs_reload(mp, ndp->ni_cnd.cn_cred, p);
if (err) {
goto error_1;
}
if (fs->fs_ronly && (mp->mnt_flag & MNT_WANTRDWR)) {
if (!fs->fs_clean) {
if (mp->mnt_flag & MNT_FORCE) {
printf("WARNING: %s was not properly dismounted.\n",fs->fs_fsmnt);
} else {
printf("WARNING: R/W mount of %s denied. Filesystem is not clean - run fsck.\n",
fs->fs_fsmnt);
err = EPERM;
goto error_1;
}
}
fs->fs_ronly = 0;
}
if (fs->fs_ronly == 0) {
fs->fs_clean = 0;
ffs_sbupdate(ump, MNT_WAIT);
}
/* if not updating name...*/
if (args.fspec == 0) {
/*
* Process export requests. Jumping to "success"
* will return the vfs_export() error code.
*/
err = vfs_export(mp, &ump->um_export, &args.export);
goto success;
}
#endif
}
/*
* 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);
err = namei(ndp);
if (err) {
/* can't get devvp!*/
goto error_1;
}
devvp = ndp->ni_vp;
if (devvp->v_type != VBLK) {
err = ENOTBLK;
goto error_2;
}
if (major(devvp->v_rdev) >= nblkdev) {
err = ENXIO;
goto error_2;
}
if (mp->mnt_flag & MNT_UPDATE) {
#if 0
/*
********************
* UPDATE
********************
*/
if (devvp != ntmp->um_devvp)
err = EINVAL; /* needs translation */
else
vrele(devvp);
/*
* Update device name only on success
*/
if( !err) {
/* Save "mounted from" info for mount point (NULL pad)*/
copyinstr( args.fspec,
mp->mnt_stat.f_mntfromname,
MNAMELEN - 1,
&size);
bzero( mp->mnt_stat.f_mntfromname + size, MNAMELEN - size);
}
#endif
} else {
/*
********************
* NEW MOUNT
********************
*/
/*
* Since this is a new mount, we want the names for
* the device and the mount point copied in. If an
* error occurs, the mountpoint is discarded by the
* upper level code.
*/
/* Save "last mounted on" info for mount point (NULL pad)*/
copyinstr( path, /* mount point*/
mp->mnt_stat.f_mntonname, /* save area*/
MNAMELEN - 1, /* max size*/
&size); /* real size*/
bzero( mp->mnt_stat.f_mntonname + size, MNAMELEN - size);
/* Save "mounted from" info for mount point (NULL pad)*/
copyinstr( args.fspec, /* device name*/
mp->mnt_stat.f_mntfromname, /* save area*/
MNAMELEN - 1, /* max size*/
&size); /* real size*/
bzero( mp->mnt_stat.f_mntfromname + size, MNAMELEN - size);
err = ntfs_mountfs(devvp, mp, &args, p);
}
if (err) {
goto error_2;
}
dostatfs:
/*
* Initialize FS stat information in mount struct; uses both
* mp->mnt_stat.f_mntonname and mp->mnt_stat.f_mntfromname
*
* This code is common to root and non-root mounts
*/
(void)VFS_STATFS(mp, &mp->mnt_stat, p);
goto success;
error_2: /* error with devvp held*/
/* release devvp before failing*/
vrele(devvp);
error_1: /* no state to back out*/
success:
return( err);
}
/*
* Common code for mount and mountroot
*/
int
ntfs_mountfs(devvp, mp, argsp, p)
register struct vnode *devvp;
struct mount *mp;
struct ntfs_args *argsp;
struct proc *p;
{
struct buf *bp;
struct ntfsmount *ntmp;
dev_t dev = devvp->v_rdev;
int error, ronly, ncount, i;
struct vnode *vp;
/*
* 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.
*/
error = vfs_mountedon(devvp);
if (error)
return (error);
ncount = vcount(devvp);
if (devvp->v_object)
ncount -= 1;
if (ncount > 1 && devvp != rootvp)
return (EBUSY);
#if __FreeBSD_version >= 300000
vn_lock(devvp, LK_EXCLUSIVE | LK_RETRY, p);
error = vinvalbuf(devvp, V_SAVE, p->p_ucred, p, 0, 0);
VOP_UNLOCK(devvp, 0, p);
#else
error = vinvalbuf(devvp, V_SAVE, p->p_ucred, p, 0, 0);
#endif
if (error)
return (error);
ronly = (mp->mnt_flag & MNT_RDONLY) != 0;
error = VOP_OPEN(devvp, ronly ? FREAD : FREAD|FWRITE, FSCRED, p);
if (error)
return (error);
bp = NULL;
error = bread(devvp, BBLOCK, BBSIZE, NOCRED, &bp);
if (error)
goto out;
ntmp = malloc( sizeof *ntmp, M_NTFSMNT, M_WAITOK );
bzero( ntmp, sizeof *ntmp );
bcopy( bp->b_data, &ntmp->ntm_bootfile, sizeof(struct bootfile) );
brelse( bp );
bp = NULL;
{
int8_t cpr = ntmp->ntm_mftrecsz;
if( cpr > 0 )
ntmp->ntm_bpmftrec = ntmp->ntm_spc * cpr;
else
ntmp->ntm_bpmftrec = (1 << (-cpr)) / ntmp->ntm_bps;
}
printf("ntfs_mountfs(): bps: %d, spc: %d, media: %x, mftrecsz: %d (%d sects)\n",
ntmp->ntm_bps,ntmp->ntm_spc,ntmp->ntm_bootfile.bf_media,
ntmp->ntm_mftrecsz,ntmp->ntm_bpmftrec);
printf("ntfs_mountfs(): mftcn: 0x%x|0x%x\n",
(u_int32_t)ntmp->ntm_mftcn,(u_int32_t)ntmp->ntm_mftmirrcn);
ntmp->ntm_mountp = mp;
ntmp->ntm_dev = dev;
ntmp->ntm_devvp = devvp;
ntmp->ntm_uid = argsp->uid;
ntmp->ntm_gid = argsp->gid;
ntmp->ntm_mode = argsp->mode;
ntmp->ntm_flag = argsp->flag;
mp->mnt_data = (qaddr_t)ntmp;
printf("ntfs_mountfs(): case-%s,%s uid: %d, gid: %d, mode: %o\n",
(ntmp->ntm_flag & NTFS_MFLAG_CASEINS)?"insens.":"sens.",
(ntmp->ntm_flag & NTFS_MFLAG_ALLNAMES)?" allnames,":"",
ntmp->ntm_uid, ntmp->ntm_gid, ntmp->ntm_mode);
printf("ntfs_mountfs(): reading system nodes...\n");
{
i = NTFS_MFTINO;
error = VFS_VGET(mp, i, &ntmp->ntm_sysvn[i]);
if(error)
goto out1;
VREF(ntmp->ntm_sysvn[i]);
vput(ntmp->ntm_sysvn[i]);
}
MALLOC( ntmp->ntm_upcase, wchar *, 65536 * sizeof(wchar),
M_NTFSMNT, M_WAITOK);
printf("ntfs_mountfs(): opening $UpCase\n");
error = VFS_VGET(mp, NTFS_UPCASEINO, &vp );
if(error)
goto out1;
printf("ntfs_mountfs(): reading $UpCase\n");
error = ntfs_breadattr( ntmp, VTONT(vp), NTFS_A_DATA, NULL,
0, 65536*sizeof(wchar), ntmp->ntm_upcase);
printf("ntfs_mountfs(): closing $UpCase\n");
vput(vp);
if(error)
goto out1;
{
int num,j;
struct attrdef ad;
printf("ntfs_mountfs(): opening $AttrDef\n");
error = VFS_VGET(mp, NTFS_ATTRDEFINO, &vp );
if(error)
goto out1;
for(num=0;;num++) {
error = ntfs_breadattr(ntmp, VTONT(vp),
NTFS_A_DATA, NULL,
num * sizeof(ad), sizeof(ad),
&ad);
if (error)
goto out1;
if (ad.ad_name[0] == 0)
break;
}
printf("ntfs_mountfs(): reading %d attrdefs\n",num);
MALLOC(ntmp->ntm_ad, struct ntvattrdef *,
num * sizeof(struct ntvattrdef),
M_NTFSMNT, M_WAITOK);
ntmp->ntm_adnum = num;
for(i=0;i<num;i++){
error = ntfs_breadattr(ntmp, VTONT(vp),
NTFS_A_DATA, NULL,
i * sizeof(ad), sizeof(ad),
&ad);
if (error)
goto out1;
j = 0;
do {
ntmp->ntm_ad[i].ad_name[j] = ad.ad_name[j];
} while(ad.ad_name[j++]);
ntmp->ntm_ad[i].ad_namelen = j - 1;
ntmp->ntm_ad[i].ad_type = ad.ad_type;
printf("ntfs_mountfs(): attribute: %s, type: 0x%x\n",
ntmp->ntm_ad[i].ad_name,
ntmp->ntm_ad[i].ad_type);
}
printf("ntfs_mountfs(): closing $AttrDef\n");
vput(vp);
}
mp->mnt_stat.f_fsid.val[0] = (long)dev;
#if __FreeBSD_version >= 300000
mp->mnt_stat.f_fsid.val[1] = mp->mnt_vfc->vfc_typenum;
#else
mp->mnt_stat.f_fsid.val[1] = MOUNT_NTFS;
#endif
mp->mnt_maxsymlinklen = 0;
mp->mnt_flag |= MNT_LOCAL;
#if __FreeBSD_version >= 300000
devvp->v_specmountpoint = mp;
#else
devvp->v_specflags |= SI_MOUNTEDON;
#endif
return (0);
out1:
for(i=0;i<NTFS_SYSNODESNUM;i++)
if(ntmp->ntm_sysvn[i]) vrele(ntmp->ntm_sysvn[i]);
out:
#if __FreeBSD_version >= 300000
devvp->v_specmountpoint = NULL;
#else
devvp->v_specflags |= SI_MOUNTEDON;
#endif
if (bp)
brelse(bp);
(void)VOP_CLOSE(devvp, ronly ? FREAD : FREAD|FWRITE, NOCRED, p);
return (error);
}
static int
ntfs_start (
struct mount *mp,
int flags,
struct proc *p )
{
printf("\nntfs_start():\n");
return (0);
}
static int
ntfs_unmount(
struct mount *mp,
int mntflags,
struct proc *p)
{
register struct ntfsmount *ntmp;
int error, ronly = 0, flags, i;
printf("ntfs_unmount: unmounting...\n");
ntmp = VFSTONTFS(mp);
flags = 0;
if(mntflags & MNT_FORCE)
flags |= FORCECLOSE;
printf("ntfs_unmount: vflushing...\n");
for(i=0;i<NTFS_SYSNODESNUM;i++)
if(ntmp->ntm_sysvn[i]) vrele(ntmp->ntm_sysvn[i]);
error = vflush(mp,NULLVP,flags);
if (error) {
printf("ntfs_unmount: vflush failed: %d\n",error);
return (error);
}
#if __FreeBSD_version >= 300000
ntmp->ntm_devvp->v_specmountpoint = NULL;
#else
ntmp->ntm_devvp->v_specflags &= ~SI_MOUNTEDON;
VOP_LOCK(ntmp->ntm_devvp);
vnode_pager_uncache(ntmp->ntm_devvp);
VOP_UNLOCK(ntmp->ntm_devvp);
#endif
vinvalbuf(ntmp->ntm_devvp, V_SAVE, NOCRED, p, 0, 0);
error = VOP_CLOSE(ntmp->ntm_devvp, ronly ? FREAD : FREAD|FWRITE,
NOCRED, p);
vrele(ntmp->ntm_devvp);
printf("ntfs_umount: freeing memory...\n");
mp->mnt_data = (qaddr_t)0;
mp->mnt_flag &= ~MNT_LOCAL;
FREE(ntmp->ntm_ad, M_NTFSMNT);
FREE(ntmp->ntm_upcase, M_NTFSMNT);
FREE(ntmp, M_NTFSMNT);
return (error);
}
static int
ntfs_root(
struct mount *mp,
struct vnode **vpp )
{
struct vnode *nvp;
int error = 0;
dprintf(("ntfs_root():\n"));
error = VFS_VGET(mp, (ino_t)NTFS_ROOTINO, &nvp);
if(error) {
printf("ntfs_root: VFS_VGET failed: %d\n",error);
return (error);
}
*vpp = nvp;
return (0);
}
static int
ntfs_quotactl (
struct mount *mp,
int cmds,
uid_t uid,
caddr_t arg,
struct proc *p)
{
printf("\nntfs_quotactl():\n");
return EOPNOTSUPP;
}
static int
ntfs_statfs(
struct mount *mp,
struct statfs *sbp,
struct proc *p)
{
struct ntfsmount *ntmp = VFSTONTFS(mp);
u_int64_t mftsize,mftallocated,bmsize,bmallocated;
struct vnode *vp;
int error,j,i;
u_int8_t *tmp;
dprintf(("ntfs_statfs():"));
ntfs_filesize(ntmp, VTONT(ntmp->ntm_sysvn[NTFS_MFTINO]),
&mftsize, &mftallocated);
error = VFS_VGET(mp, NTFS_BITMAPINO, &vp);
if(error)
return (error);
ntfs_filesize(ntmp, VTONT(vp), &bmsize, &bmallocated);
MALLOC(tmp, u_int8_t *, bmsize,M_TEMP, M_WAITOK);
error = ntfs_breadattr(ntmp, VTONT(vp), NTFS_A_DATA, NULL,
0, bmsize, tmp);
if(error) {
FREE(tmp, M_TEMP);
vput(vp);
return (error);
}
vput(vp);
sbp->f_bfree = 0;
for(i=0;i<bmsize;i++)
for(j=0;j<8;j++)
if(~tmp[i] & (1 << j)) sbp->f_bfree++;
FREE(tmp, M_TEMP);
#if __FreeBSD_version >= 300000
sbp->f_type = mp->mnt_vfc->vfc_typenum;
#else
sbp->f_type = MOUNT_NTFS;
#endif
sbp->f_bsize = ntmp->ntm_bps;
sbp->f_iosize = ntmp->ntm_bps * ntmp->ntm_spc;
sbp->f_blocks = ntmp->ntm_bootfile.bf_spv;
sbp->f_bfree = sbp->f_bavail = ntfs_cntobn(sbp->f_bfree);
sbp->f_ffree = sbp->f_bfree / ntmp->ntm_bpmftrec;
sbp->f_files = mftallocated / ntfs_bntob(ntmp->ntm_bpmftrec) +
sbp->f_ffree;
if (sbp != &mp->mnt_stat) {
bcopy((caddr_t)mp->mnt_stat.f_mntonname,
(caddr_t)&sbp->f_mntonname[0], MNAMELEN);
bcopy((caddr_t)mp->mnt_stat.f_mntfromname,
(caddr_t)&sbp->f_mntfromname[0], MNAMELEN);
}
return (0);
}
static int
ntfs_sync (
struct mount *mp,
int waitfor,
struct ucred *cred,
struct proc *p)
{
/*dprintf(("ntfs_sync():\n"));*/
return (0);
}
#if __FreeBSD_version >= 300000
static int
ntfs_fhtovp(
struct mount *mp,
struct fid *fhp,
struct sockaddr *nam,
struct vnode **vpp,
int *exflagsp,
struct ucred **credanonp)
#else
static int
ntfs_fhtovp(
struct mount *mp,
struct fid *fhp,
struct mbuf *nam,
struct vnode **vpp,
int *exflagsp,
struct ucred **credanonp)
#endif
{
printf("\ntfs_fhtovp():\n");
return 0;
}
static int
ntfs_vptofh(
struct vnode *vp,
struct fid *fhp)
{
printf("ntfs_vptofh():\n");
return EOPNOTSUPP;
}
static int
ntfs_vget(
struct mount *mp,
ino_t ino,
struct vnode **vpp)
{
int error=0;
struct vnode *vp;
register struct ntfsmount *ntmp;
struct ntnode *ip;
dprintf(("ntfs_vget: ino: %d\n",ino));
ntmp = VFSTONTFS(mp);
*vpp = NULL;
dprintf(("ntfs_ntvget: ihashlookup\n"));
if( (*vpp = ntfs_ihashget(ntmp->ntm_dev, ino)) != NULL )
return (0);
error = ntfs_ntget(ntmp,ino,&ip);
if(error) {
printf("ntfs_vget: ntfs_ntget failed\n");
return (error);
}
error = getnewvnode(VT_NTFS, ntmp->ntm_mountp, ntfs_vnodeop_p, &vp);
if(error) {
/* XXX */
ntfs_ntrele(ip);
return (error);
}
ip->i_vnode = vp;
vp->v_data = ip;
vp->v_type = ip->i_type;
ntfs_ihashins(ip);
VREF(ip->i_devvp);
error = ntfs_loadnode(ntmp, ip);
if(error) {
printf("ntfs_vget: CAN'T LOAD ATTRIBUTES FOR INO: %d\n",
ip->i_number);
vput(vp);
return (error);
}
*vpp = vp;
return (0);
}
#if __FreeBSD_version >= 300000
static struct vfsops ntfs_vfsops = {
ntfs_mount,
ntfs_start,
ntfs_unmount,
ntfs_root,
ntfs_quotactl,
ntfs_statfs,
ntfs_sync,
ntfs_vget,
ntfs_fhtovp,
ntfs_vptofh,
ntfs_init,
NULL,
NULL
};
VFS_SET(ntfs_vfsops, ntfs, 0);
#else
static struct vfsops ntfs_vfsops = {
ntfs_mount,
ntfs_start,
ntfs_unmount,
ntfs_root,
ntfs_quotactl,
ntfs_statfs,
ntfs_sync,
ntfs_vget,
ntfs_fhtovp,
ntfs_vptofh,
ntfs_init,
};
VFS_SET(ntfs_vfsops, ntfs, MOUNT_NTFS, 0);
#endif

1084
sys/ntfs/ntfs_vnops.c Normal file

File diff suppressed because it is too large Load Diff

39
sys/ntfs/ntfsmount.h Normal file
View File

@ -0,0 +1,39 @@
/*-
* Copyright (c) 1998, 1999 Semen Ustimenko
* All rights reserved.
*
* 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.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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.
*
* $Id: ntfsmount.h,v 1.7 1999/01/28 03:56:07 semen Exp $
*/
#define NTFS_MFLAG_CASEINS 0x00000001
#define NTFS_MFLAG_ALLNAMES 0x00000002
struct ntfs_args {
char *fspec; /* block special device to mount */
struct export_args export; /* network export information */
uid_t uid; /* uid that owns ntfs files */
gid_t gid; /* gid that owns ntfs files */
mode_t mode; /* mask to be applied for ntfs perms */
u_long flag; /* additional flags */
};