Removed annoying messaged during boot,added some check

before mounting (should help to do not mount extended partitions:-).
Fixed problem with hanging while unmounting busy fs.

And (the most important) added some locks to prevent
simulaneous access to kernel structures!
This commit is contained in:
semenu 1999-04-20 21:06:44 +00:00
parent c8cbbb76c7
commit 42e01703dc
14 changed files with 890 additions and 376 deletions

View File

@ -23,7 +23,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* $Id: ntfs.h,v 1.2 1999/02/19 12:31:02 semenu Exp $
* $Id: ntfs.h,v 1.9 1999/02/02 01:54:54 semen Exp $
*/
/*#define NTFS_DEBUG 1*/
@ -213,6 +213,8 @@ struct ntvattrdef {
u_int32_t ad_type;
};
#define NTFS_BBID "NTFS "
#define NTFS_BBIDLEN 8
struct bootfile {
u_int8_t reserved1[3]; /* asm jmp near ... */
u_int8_t bf_sysid[8]; /* 'NTFS ' */
@ -246,6 +248,7 @@ struct ntfsmount {
gid_t ntm_gid;
mode_t ntm_mode;
u_long ntm_flag;
cn_t ntm_cfree;
struct ntvattrdef *ntm_ad;
int ntm_adnum;
};

View File

@ -55,17 +55,18 @@
#define IN_PRELOADED 0x4000 /* loaded from directory entry */
struct ntnode {
LIST_ENTRY(ntnode) i_hash;
LIST_ENTRY(ntnode) i_hash;
struct ntnode *i_next;
struct ntnode **i_prev;
struct ntfsmount *i_mp;
struct ntfsmount *i_mp;
ino_t i_number;
dev_t i_dev;
u_int32_t i_flag;
int i_lock;
int i_usecount;
LIST_HEAD(,fnode) i_fnlist;
struct ntvattr *i_vattrp; /* ntvattrs list */
LIST_HEAD(,fnode) i_fnlist;
LIST_HEAD(,ntvattr) i_valist;
long i_nlink; /* MFR */
ino_t i_mainrec; /* MFR */
@ -77,7 +78,7 @@ struct ntnode {
};
#define FN_PRELOADED 0x0001
#define FN_DEFAULT 0x0002
#define FN_VALID 0x0002
#define FN_AATTRNAME 0x0004 /* space allocated for f_attrname */
struct fnode {
struct lock f_lock; /* Must be first */

View File

@ -1,5 +1,5 @@
/*-
* Copyright (c) 1998, 1999 Semen Ustimenko
* Copyright (c) 1998, 1999 Semen Ustimenko (semenu@FreeBSD.org)
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@ -58,6 +58,9 @@ MALLOC_DEFINE(M_NTFSRUN, "NTFS vrun", "NTFS vrun storage");
MALLOC_DEFINE(M_NTFSDECOMP, "NTFS decomp", "NTFS decompression temporary");
#endif
/*
*
*/
int
ntfs_ntvattrrele(
struct ntvattr * vap)
@ -70,6 +73,13 @@ ntfs_ntvattrrele(
return (0);
}
/*
* Search attribute specifed in ntnode (load ntnode if nessecary).
* If not found but ATTR_A_ATTRLIST present, read it in and search throught.
* VOP_VGET node needed, and lookup througth it's ntnode (load if nessesary).
*
* ntnode should be locked
*/
int
ntfs_ntvattrget(
struct ntfsmount * ntmp,
@ -113,7 +123,7 @@ ntfs_ntvattrget(
}
}
for (vap = ip->i_vattrp; vap; vap = vap->va_nextp) {
for (vap = ip->i_valist.lh_first; vap; vap = vap->va_list.le_next) {
ddprintf(("type: 0x%x, vcn: %d - %d\n", \
vap->va_type, (u_int32_t) vap->va_vcnstart, \
(u_int32_t) vap->va_vcnend));
@ -171,14 +181,20 @@ ntfs_ntvattrget(
dprintf(("ntfs_ntvattrget: attrbute in ino: %d\n",
aalp->al_inumber));
/*
error = VFS_VGET(ntmp->ntm_mountp, aalp->al_inumber,
&newvp);
*/
error = ntfs_vgetex(ntmp->ntm_mountp, aalp->al_inumber,
NTFS_A_DATA, NULL, LK_EXCLUSIVE,
VG_EXT, curproc, &newvp);
if (error) {
printf("ntfs_ntvattrget: CAN'T VGET INO: %d\n",
aalp->al_inumber);
goto out;
}
newip = VTONT(newvp);
/* XXX have to lock ntnode */
if(~newip->i_flag & IN_LOADED) {
dprintf(("ntfs_ntvattrget: node not loaded," \
" ino: %d\n", newip->i_number));
@ -190,7 +206,7 @@ ntfs_ntvattrget(
goto out;
}
}
for (vap = newip->i_vattrp; vap; vap = vap->va_nextp) {
for (vap = newip->i_valist.lh_first; vap; vap = vap->va_list.le_next) {
if ((vap->va_type == type) &&
(vap->va_vcnstart <= vcn) &&
(vap->va_vcnend >= vcn) &&
@ -219,10 +235,14 @@ ntfs_ntvattrget(
ip->i_number, type, name, (u_int32_t) vcn));
out:
FREE(alpool, M_TEMP);
return (error);
}
/*
* Read ntnode from disk, make ntvattr list.
*
* ntnode should be locked
*/
int
ntfs_loadntnode(
struct ntfsmount * ntmp,
@ -232,7 +252,7 @@ ntfs_loadntnode(
daddr_t bn;
int error,off;
struct attr *ap;
struct ntvattr**vapp;
struct ntvattr *nvap;
dprintf(("ntfs_loadnode: loading ino: %d\n",ip->i_number));
@ -269,6 +289,7 @@ ntfs_loadntnode(
goto out;
}
}
/* Check if magic and fixups are correct */
error = ntfs_procfixups(ntmp, NTFS_FILEMAGIC, (caddr_t)mfrp,
ntfs_bntob(ntmp->ntm_bpmftrec));
@ -281,16 +302,16 @@ ntfs_loadntnode(
dprintf(("ntfs_loadnode: load attrs for ino: %d\n",ip->i_number));
off = mfrp->fr_attroff;
ap = (struct attr *) ((caddr_t)mfrp + off);
if (ip->i_vattrp)
printf("ntfs_ntloadnode: WARNING! already loaded?\n");
LIST_INIT(&ip->i_valist);
vapp = &ip->i_vattrp;
while (ap->a_hdr.a_type != -1) {
error = ntfs_attrtontvattr(ntmp, vapp, ap);
error = ntfs_attrtontvattr(ntmp, &nvap, ap);
if (error)
break;
(*vapp)->va_ip = ip;
vapp = &((*vapp)->va_nextp);
nvap->va_ip = ip;
LIST_INSERT_HEAD(&ip->i_valist, nvap, va_list);
off += ap->a_hdr.reclen;
ap = (struct attr *) ((caddr_t)mfrp + off);
@ -312,44 +333,74 @@ out:
return (error);
}
static int ntfs_ntnode_hash_lock;
/*
* Routine locks ntnode and increase usecount, just opposite of
* ntfs_ntput.
*/
int
ntfs_ntget(
struct ntnode *ip)
{
dprintf(("ntfs_ntget: get ntnode %d: %p, usecount: %d\n",
ip->i_number, ip, ip->i_usecount));
ip->i_usecount++;
restart:
if (ip->i_lock) {
while (ip->i_lock) {
ip->i_lock = -1;
tsleep(&ip->i_lock, PVM, "ntnode", 0);
}
goto restart;
}
ip->i_lock = 1;
return 0;
}
/*
* Routine search ntnode in hash, if found: lock, inc usecount and return.
* If not in hash allocate structure for ntnode, prefill it, lock,
* inc count and return.
*
* ntnode returned locked
*/
static int ntfs_ntnode_hash_lock;
int
ntfs_ntlookup(
struct ntfsmount * ntmp,
ino_t ino,
struct ntnode ** ipp)
{
struct ntnode *ip;
dprintf(("ntfs_ntget: ntget ntnode %d\n", ino));
dprintf(("ntfs_ntlookup: for ntnode %d\n", ino));
*ipp = NULL;
restart:
ip = ntfs_nthashlookup(ntmp->ntm_dev, ino);
ip = ntfs_nthashlookup(ntmp->ntm_dev, ino); /* XXX */
if (ip) {
ip->i_usecount++;
ntfs_ntget(ip);
*ipp = ip;
dprintf(("ntfs_ntget: ntnode %d: %p, usecount: %d\n",
dprintf(("ntfs_ntlookup: ntnode %d: %p, usecount: %d\n",
ino, ip, ip->i_usecount));
return (0);
}
if (ntfs_ntnode_hash_lock) {
printf("waiting for hash_lock to free...\n");
while(ntfs_ntnode_hash_lock) {
ntfs_ntnode_hash_lock = -1;
tsleep(&ntfs_ntnode_hash_lock, PVM, "ntfsntgt", 0);
}
printf("hash_lock freeed\n");
goto restart;
}
ntfs_ntnode_hash_lock = 1;
MALLOC(ip, struct ntnode *, sizeof(struct ntnode),
M_NTFSNTNODE, M_WAITOK);
ddprintf(("ntfs_ntget: allocating ntnode: %d: %p\n", ino, ip));
ddprintf(("ntfs_ntlookup: allocating ntnode: %d: %p\n", ino, ip));
bzero((caddr_t) ip, sizeof(struct ntnode));
/* Generic initialization */
@ -361,6 +412,8 @@ restart:
ip->i_mode = ntmp->ntm_mode;
ip->i_usecount++;
ip->i_lock = 1;
LIST_INIT(&ip->i_fnlist);
ntfs_nthashins(ip);
@ -371,45 +424,77 @@ restart:
*ipp = ip;
dprintf(("ntfs_ntget: ntnode %d: %p, usecount: %d\n",
dprintf(("ntfs_ntlookup: ntnode %d: %p, usecount: %d\n",
ino, ip, ip->i_usecount));
return (0);
}
/*
* Decrement usecount of ntnode and unlock it, if usecount reach zero,
* deallocate ntnode.
*
* ntnode should be locked on entry, and unlocked on return.
*/
void
ntfs_ntrele(
struct ntnode * ip)
ntfs_ntput(
struct ntnode *ip)
{
struct ntvattr *vap;
dprintf(("ntfs_ntrele: rele ntnode %d: %p, usecount: %d\n",
if (!ip->i_lock) printf("ntfs_ntput: NOT LOCKED");
dprintf(("ntfs_ntput: rele ntnode %d: %p, usecount: %d\n",
ip->i_number, ip, ip->i_usecount));
ip->i_usecount--;
if (ip->i_usecount < 0) {
panic("ntfs_ntrele: ino: %d usecount: %d \n",
panic("ntfs_ntput: ino: %d usecount: %d \n",
ip->i_number,ip->i_usecount);
} else if (ip->i_usecount == 0) {
dprintf(("ntfs_ntrele: deallocating ntnode: %d\n",
dprintf(("ntfs_ntput: deallocating ntnode: %d\n",
ip->i_number));
if (ip->i_fnlist.lh_first)
panic("ntfs_ntrele: ntnode has fnodes\n");
panic("ntfs_ntput: ntnode has fnodes\n");
ntfs_nthashrem(ip);
while (ip->i_vattrp) {
vap = ip->i_vattrp;
ip->i_vattrp = vap->va_nextp;
while (ip->i_valist.lh_first != NULL) {
vap = ip->i_valist.lh_first;
LIST_REMOVE(vap,va_list);
ntfs_freentvattr(vap);
}
FREE(ip, M_NTFSNTNODE);
} else {
if (ip->i_lock < 0)
wakeup(&ip->i_lock);
ip->i_lock = 0;
}
dprintf(("ntfs_ntrele: rele ok\n"));
}
/*
* Decrement usecount of ntnode.
*/
void
ntfs_ntrele(
struct ntnode * ip)
{
dprintf(("ntfs_ntrele: rele ntnode %d: %p, usecount: %d\n",
ip->i_number, ip, ip->i_usecount));
ip->i_usecount--;
if (ip->i_usecount < 0)
panic("ntfs_ntrele: ino: %d usecount: %d \n",
ip->i_number,ip->i_usecount);
}
/*
* Deallocate all memory allocated for ntvattr by call to
* ntfs_attrtontvattr and some other functions.
*/
void
ntfs_freentvattr(
struct ntvattr * vap)
@ -426,6 +511,10 @@ ntfs_freentvattr(
FREE(vap, M_NTFSNTVATTR);
}
/*
* Convert disk image of attribute into ntvattr structure,
* runs are expanded also.
*/
int
ntfs_attrtontvattr(
struct ntfsmount * ntmp,
@ -493,6 +582,9 @@ ntfs_attrtontvattr(
return (error);
}
/*
* Expand run into more utilizable and more memory eating format.
*/
int
ntfs_runtovrun(
cn_t ** rcnp,
@ -552,7 +644,9 @@ ntfs_runtovrun(
return (0);
}
/*
* Convert wchar to uppercase wchar, should be macros?
*/
wchar
ntfs_toupper(
struct ntfsmount * ntmp,
@ -561,6 +655,9 @@ ntfs_toupper(
return (ntmp->ntm_upcase[wc & 0xFF]);
}
/*
* Compare to unicode strings case insensible.
*/
int
ntfs_uustricmp(
struct ntfsmount * ntmp,
@ -581,6 +678,9 @@ ntfs_uustricmp(
return (str1len - str2len);
}
/*
* Compare unicode and ascii string case insens.
*/
int
ntfs_uastricmp(
struct ntfsmount * ntmp,
@ -601,6 +701,9 @@ ntfs_uastricmp(
return (str1len - str2len);
}
/*
* Compare unicode and ascii string case sens.
*/
int
ntfs_uastrcmp(
struct ntfsmount * ntmp,
@ -620,6 +723,11 @@ ntfs_uastrcmp(
return (str1len - str2len);
}
/*
* Search fnode in ntnode, if not found allocate and preinitialize.
*
* ntnode should be locked on entry.
*/
int
ntfs_fget(
struct ntfsmount *ntmp,
@ -628,7 +736,6 @@ ntfs_fget(
char *attrname,
struct fnode **fpp)
{
int error;
struct fnode *fp;
dprintf(("ntfs_fget: ino: %d, attrtype: 0x%x, attrname: %s\n",
@ -662,15 +769,6 @@ ntfs_fget(
fp->f_attrname = attrname;
if (fp->f_attrname) fp->f_flag |= FN_AATTRNAME;
fp->f_attrtype = attrtype;
if ((fp->f_attrtype == NTFS_A_DATA) && (fp->f_attrname == NULL))
fp->f_flag |= FN_DEFAULT;
else {
error = ntfs_filesize(ntmp, fp, &fp->f_size, &fp->f_allocated);
if (error) {
FREE(fp,M_NTFSFNODE);
return (error);
}
}
ntfs_ntref(ip);
@ -681,6 +779,11 @@ ntfs_fget(
return (0);
}
/*
* Deallocate fnode, remove it from ntnode's fnode list.
*
* ntnode should be locked.
*/
void
ntfs_frele(
struct fnode *fp)
@ -699,6 +802,11 @@ ntfs_frele(
ntfs_ntrele(ip);
}
/*
* Lookup attribute name in format: [[:$ATTR_TYPE]:$ATTR_NAME],
* $ATTR_TYPE is searched in attrdefs read from $AttrDefs.
* If $ATTR_TYPE nott specifed, ATTR_A_DATA assumed.
*/
int
ntfs_ntlookupattr(
struct ntfsmount * ntmp,
@ -753,12 +861,13 @@ ntfs_ntlookupattr(
return (0);
}
/*
* Lookup specifed node for filename, matching cnp,
* return fnode filled.
*/
int
ntfs_ntlookup(
ntfs_ntlookupfile(
struct ntfsmount * ntmp,
struct vnode * vp,
struct componentname * cnp,
@ -776,6 +885,10 @@ ntfs_ntlookup(
char *fname,*aname;
u_int32_t aoff;
error = ntfs_ntget(ip);
if (error)
return (error);
error = ntfs_ntvattrget(ntmp, ip, NTFS_A_INDXROOT, "$I30", 0, &vap);
if (error || (vap->va_flag & NTFS_AF_INRUN))
return (ENOTDIR);
@ -783,6 +896,10 @@ ntfs_ntlookup(
blsize = vap->va_a_iroot->ir_size;
rdsize = vap->va_datalen;
/*
* Divide file name into: foofilefoofilefoofile[:attrspec]
* Store like this: fname:fnamelen [aname:anamelen]
*/
fname = cnp->cn_nameptr;
aname = NULL;
anamelen = 0;
@ -790,12 +907,12 @@ ntfs_ntlookup(
if(fname[fnamelen] == ':') {
aname = fname + fnamelen + 1;
anamelen = cnp->cn_namelen - fnamelen - 1;
dprintf(("ntfs_ntlookup: file %s (%d), attr: %s (%d)\n",
dprintf(("ntfs_ntlookupfile: %s (%d), attr: %s (%d)\n",
fname, fnamelen, aname, anamelen));
break;
}
dprintf(("ntfs_ntlookup: blocksize: %d, rdsize: %d\n", blsize, rdsize));
dprintf(("ntfs_ntlookupfile: blksz: %d, rdsz: %d\n", blsize, rdsize));
MALLOC(rdbuf, caddr_t, blsize, M_TEMP, M_WAITOK);
@ -856,7 +973,8 @@ ntfs_ntlookup(
attrtype,
attrname,
LK_EXCLUSIVE,
VG_DONTLOAD,
VG_DONTLOADIN |
VG_DONTVALIDFN,
curproc,
&nvp);
if(error)
@ -864,6 +982,11 @@ ntfs_ntlookup(
nfp = VTOF(nvp);
if (nfp->f_flag & FN_VALID) {
*vpp = nvp;
goto fail;
}
nfp->f_fflag = iep->ie_fflag;
nfp->f_pnumber = iep->ie_fpnumber;
nfp->f_times = iep->ie_ftimes;
@ -883,7 +1006,17 @@ ntfs_ntlookup(
nfp->f_size = iep->ie_fsize;
nfp->f_allocated = iep->ie_fallocated;
nfp->f_flag |= FN_PRELOADED;
} else {
error = ntfs_filesize(ntmp, nfp,
&nfp->f_size,
&nfp->f_allocated);
if (error) {
vput(nvp);
goto fail;
}
}
nfp->f_flag &= ~FN_VALID;
*vpp = nvp;
goto fail;
}
@ -896,7 +1029,7 @@ ntfs_ntlookup(
/* Dive if possible */
if (iep->ie_flag & NTFS_IEFLAG_SUBNODE) {
dprintf(("ntfs_ntlookup: diving\n"));
dprintf(("ntfs_ntlookupfile: diving\n"));
cn = *(cn_t *) (rdbuf + aoff +
iep->reclen - sizeof(cn_t));
@ -915,7 +1048,7 @@ ntfs_ntlookup(
aoff = (((struct attr_indexalloc *) rdbuf)->ia_hdrsize +
0x18);
} else {
dprintf(("ntfs_ntlookup: nowhere to dive :-(\n"));
dprintf(("ntfs_ntlookupfile: nowhere to dive :-(\n"));
error = ENOENT;
break;
}
@ -925,10 +1058,14 @@ ntfs_ntlookup(
fail:
ntfs_ntvattrrele(vap);
ntfs_ntput(ip);
FREE(rdbuf, M_TEMP);
return (error);
}
/*
* Check if name type is permitted to show.
*/
int
ntfs_isnamepermitted(
struct ntfsmount * ntmp,
@ -942,9 +1079,7 @@ ntfs_isnamepermitted(
case 2:
ddprintf(("ntfs_isnamepermitted: skiped DOS name\n"));
return 0;
case 0:
case 1:
case 3:
case 0: case 1: case 3:
return 1;
default:
printf("ntfs_isnamepermitted: " \
@ -955,6 +1090,14 @@ ntfs_isnamepermitted(
return 0;
}
/*
* Read ntfs dir like stream of attr_indexentry, not like btree of them.
* This is done by scaning $BITMAP:$I30 for busy clusters and reading them.
* Ofcouse $INDEX_ROOT:$I30 is read before. Last read values are stored in
* fnode, so we can skip toward record number num almost immediatly.
* Anyway this is rather slow routine. The problem is that we don't know
* how many records are there in $INDEX_ALLOCATION:$I30 block.
*/
int
ntfs_ntreaddir(
struct ntfsmount * ntmp,
@ -978,6 +1121,10 @@ ntfs_ntreaddir(
u_int32_t aoff, cnum;
dprintf(("ntfs_ntreaddir: read ino: %d, num: %d\n", ip->i_number, num));
error = ntfs_ntget(ip);
if (error)
return (error);
error = ntfs_ntvattrget(ntmp, ip, NTFS_A_INDXROOT, "$I30", 0, &vap);
if (error)
return (ENOTDIR);
@ -1106,12 +1253,14 @@ fail:
ntfs_ntvattrrele(iavap);
if (bmp)
FREE(bmp, M_TEMP);
ntfs_ntput(ip);
return (error);
}
/*
* #undef dprintf #define dprintf(a)
*/
/*
* Convert NTFS times that are in 100 ns units and begins from
* 1601 Jan 1 into unix times.
*/
struct timespec
ntfs_nttimetounix(
u_int64_t nt)
@ -1126,6 +1275,9 @@ ntfs_nttimetounix(
return (t);
}
/*
* Get file times from NTFS_A_NAME attribute.
*/
int
ntfs_times(
struct ntfsmount * ntmp,
@ -1136,15 +1288,28 @@ ntfs_times(
int error;
dprintf(("ntfs_times: ino: %d...\n", ip->i_number));
error = ntfs_ntvattrget(ntmp, ip, NTFS_A_NAME, NULL, 0, &vap);
error = ntfs_ntget(ip);
if (error)
return (error);
error = ntfs_ntvattrget(ntmp, ip, NTFS_A_NAME, NULL, 0, &vap);
if (error) {
ntfs_ntput(ip);
return (error);
}
*tm = vap->va_a_name->n_times;
ntfs_ntvattrrele(vap);
ntfs_ntput(ip);
return (0);
}
/*
* Get file sizes from corresponding attribute.
*
* ntnode under fnode should be locked.
*/
int
ntfs_filesize(
struct ntfsmount * ntmp,
@ -1158,15 +1323,12 @@ ntfs_filesize(
int error;
dprintf(("ntfs_filesize: ino: %d\n", ip->i_number));
if (fp->f_flag & FN_DEFAULT) {
error = ntfs_ntvattrget(ntmp, ip,
NTFS_A_DATA, NULL, 0, &vap);
} else {
error = ntfs_ntvattrget(ntmp, ip,
fp->f_attrtype, fp->f_attrname, 0, &vap);
}
error = ntfs_ntvattrget(ntmp, ip,
fp->f_attrtype, fp->f_attrname, 0, &vap);
if (error)
return (error);
bn = vap->va_allocated;
sz = vap->va_datalen;
@ -1183,6 +1345,11 @@ ntfs_filesize(
return (0);
}
/*
* This is one of write routine.
*
* ntnode should be locked.
*/
int
ntfs_writeattr_plain(
struct ntfsmount * ntmp,
@ -1234,6 +1401,11 @@ ntfs_writeattr_plain(
return (error);
}
/*
* This is one of write routine.
*
* ntnode should be locked.
*/
int
ntfs_writentvattr_plain(
struct ntfsmount * ntmp,
@ -1313,7 +1485,7 @@ ntfs_writentvattr_plain(
}
}
memcpy(bp->b_data + off, data, tocopy);
bwrite(bp);
bawrite(bp);
data = data + tocopy;
*initp += tocopy;
off = 0;
@ -1336,6 +1508,11 @@ ntfs_writentvattr_plain(
return (error);
}
/*
* This is one of read routines.
*
* ntnode should be locked.
*/
int
ntfs_readntvattr_plain(
struct ntfsmount * ntmp,
@ -1379,7 +1556,7 @@ ntfs_readntvattr_plain(
cnt++;
continue;
}
if (ccn || ip->i_number == NTFS_BOOTINO) { /* XXX */
if (ccn || ip->i_number == NTFS_BOOTINO) {
ccl -= ntfs_btocn(off);
cn = ccn + ntfs_btocn(off);
off = ntfs_btocnoff(off);
@ -1442,6 +1619,11 @@ ntfs_readntvattr_plain(
return (error);
}
/*
* This is one of read routines.
*
* ntnode should be locked.
*/
int
ntfs_readattr_plain(
struct ntfsmount * ntmp,
@ -1493,6 +1675,11 @@ ntfs_readattr_plain(
return (error);
}
/*
* This is one of read routines.
*
* ntnode should be locked.
*/
int
ntfs_readattr(
struct ntfsmount * ntmp,
@ -1574,6 +1761,7 @@ ntfs_readattr(
return (error);
}
#if UNUSED_CODE
int
ntfs_parserun(
cn_t * cn,
@ -1616,7 +1804,11 @@ ntfs_parserun(
return (0);
}
#endif
/*
* Process fixup routine on given buffer.
*/
int
ntfs_procfixups(
struct ntfsmount * ntmp,
@ -1659,6 +1851,7 @@ ntfs_procfixups(
return (0);
}
#if UNUSED_CODE
int
ntfs_runtocn(
cn_t * cn,
@ -1701,3 +1894,4 @@ ntfs_runtocn(
*cn = ccn + vcn;
return (0);
}
#endif

View File

@ -30,7 +30,7 @@
#define VA_PRELOADED 0x0002
struct ntvattr {
struct ntvattr *va_nextp;
LIST_ENTRY(ntvattr) va_list;
u_int32_t va_vflag;
struct vnode *va_vp;
@ -99,12 +99,14 @@ 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 vnode *, struct componentname *, struct vnode **));
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_ntlookupfile __P((struct ntfsmount *, struct vnode *, struct componentname *, struct vnode **));
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_ntlookup __P((struct ntfsmount *, ino_t, struct ntnode **));
int ntfs_ntget __P((struct ntnode *));
void ntfs_ntrele __P((struct ntnode *));
void ntfs_ntput __P((struct ntnode *));
int ntfs_loadntnode __P(( struct ntfsmount *, struct ntnode * ));
int ntfs_ntlookupattr(struct ntfsmount *, char *, int, int *, char **);
int ntfs_writentvattr_plain(struct ntfsmount *, struct ntnode *, struct ntvattr *, off_t, size_t, void *, size_t *);

View File

@ -102,13 +102,6 @@ static int
ntfs_init ()
#endif
{
static first=1;
if(!first) return (0);
first = 1;
printf("ntfs_init(): \n");
ntfs_nthashinit();
return 0;
@ -384,6 +377,12 @@ ntfs_mountfs(devvp, mp, argsp, p)
brelse( bp );
bp = NULL;
if (strncmp(ntmp->ntm_bootfile.bf_sysid, NTFS_BBID, NTFS_BBIDLEN)) {
error = EINVAL;
printf("ntfs_mountfs: invalid boot block\n");
goto out;
}
{
int8_t cpr = ntmp->ntm_mftrecsz;
if( cpr > 0 )
@ -391,11 +390,11 @@ ntfs_mountfs(devvp, mp, argsp, p)
else
ntmp->ntm_bpmftrec = (1 << (-cpr)) / ntmp->ntm_bps;
}
printf("ntfs_mountfs(): bps: %d, spc: %d, media: %x, mftrecsz: %d (%d sects)\n",
dprintf(("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_mftrecsz,ntmp->ntm_bpmftrec));
dprintf(("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;
@ -406,51 +405,64 @@ ntfs_mountfs(devvp, mp, argsp, p)
ntmp->ntm_flag = argsp->flag;
mp->mnt_data = (qaddr_t)ntmp;
printf("ntfs_mountfs(): case-%s,%s uid: %d, gid: %d, mode: %o\n",
dprintf(("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);
ntmp->ntm_uid, ntmp->ntm_gid, ntmp->ntm_mode));
printf("ntfs_mountfs(): reading system nodes...\n");
/*
* We read in some system nodes to do not allow
* reclaim them and to have everytime access to them.
*/
{
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]);
i = NTFS_ROOTINO;
error = VFS_VGET(mp, i, &(ntmp->ntm_sysvn[i]));
if(error)
goto out1;
VREF(ntmp->ntm_sysvn[i]);
vput(ntmp->ntm_sysvn[i]);
int pi[3] = { NTFS_MFTINO, NTFS_ROOTINO, NTFS_BITMAPINO };
for (i=0; i<3; i++) {
error = VFS_VGET(mp, pi[i], &(ntmp->ntm_sysvn[pi[i]]));
if(error)
goto out1;
ntmp->ntm_sysvn[pi[i]]->v_flag |= VSYSTEM;
VREF(ntmp->ntm_sysvn[pi[i]]);
vput(ntmp->ntm_sysvn[pi[i]]);
}
}
MALLOC( ntmp->ntm_upcase, wchar *, 65536 * sizeof(wchar),
/*
* Read in WHOLE lowcase -> upcase translation
* file.
*/
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 );
error = VFS_VGET(mp, NTFS_UPCASEINO, &vp);
if(error)
goto out1;
printf("ntfs_mountfs(): reading $UpCase\n");
error = ntfs_readattr( ntmp, VTONT(vp), NTFS_A_DATA, NULL,
error = ntfs_readattr(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;
/*
* Scan $BitMap and count free clusters
*/
error = ntfs_calccfree(ntmp, &ntmp->ntm_cfree);
if(error)
goto out1;
/*
* Read and translate to internal format attribute
* definition file.
*/
{
int num,j;
struct attrdef ad;
printf("ntfs_mountfs(): opening $AttrDef\n");
/* Open $AttrDef */
error = VFS_VGET(mp, NTFS_ATTRDEFINO, &vp );
if(error)
goto out1;
/* Count valid entries */
for(num=0;;num++) {
error = ntfs_readattr(ntmp, VTONT(vp),
NTFS_A_DATA, NULL,
@ -461,14 +473,15 @@ ntfs_mountfs(devvp, mp, argsp, p)
if (ad.ad_name[0] == 0)
break;
}
printf("ntfs_mountfs(): reading %d attrdefs\n",num);
/* Alloc memory for attribute definitions */
MALLOC(ntmp->ntm_ad, struct ntvattrdef *,
num * sizeof(struct ntvattrdef),
M_NTFSMNT, M_WAITOK);
ntmp->ntm_adnum = num;
/* Read them and translate */
for(i=0;i<num;i++){
error = ntfs_readattr(ntmp, VTONT(vp),
NTFS_A_DATA, NULL,
@ -482,11 +495,8 @@ ntfs_mountfs(devvp, mp, argsp, p)
} 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);
}
@ -504,9 +514,14 @@ ntfs_mountfs(devvp, mp, argsp, p)
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]);
if (vflush(mp,NULLVP,0))
printf("ntfs_mountfs: vflush failed\n");
out:
#if __FreeBSD_version >= 300000
devvp->v_specmountpoint = NULL;
@ -525,7 +540,6 @@ ntfs_start (
int flags,
struct proc *p )
{
printf("\nntfs_start():\n");
return (0);
}
@ -538,24 +552,33 @@ ntfs_unmount(
register struct ntfsmount *ntmp;
int error, ronly = 0, flags, i;
printf("ntfs_unmount: unmounting...\n");
dprintf(("ntfs_unmount: unmounting...\n"));
ntmp = VFSTONTFS(mp);
flags = 0;
if(mntflags & MNT_FORCE)
flags |= FORCECLOSE;
printf("ntfs_unmount: vflushing...\n");
dprintf(("ntfs_unmount: vflushing...\n"));
error = vflush(mp,NULLVP,flags | SKIPSYSTEM);
if (error) {
printf("ntfs_unmount: vflush failed: %d\n",error);
return (error);
}
/* Check if only system vnodes are rest */
for(i=0;i<NTFS_SYSNODESNUM;i++)
if((ntmp->ntm_sysvn[i]) &&
(ntmp->ntm_sysvn[i]->v_usecount > 1)) return (EBUSY);
/* Derefernce all system vnodes */
for(i=0;i<NTFS_SYSNODESNUM;i++)
if(ntmp->ntm_sysvn[i]) vrele(ntmp->ntm_sysvn[i]);
/* vflush system vnodes */
error = vflush(mp,NULLVP,flags);
if (error)
printf("ntfs_unmount: vflush failed: %d\n",error);
printf("ntfs_unmount: vflush failed(sysnodes): %d\n",error);
#if __FreeBSD_version >= 300000
ntmp->ntm_devvp->v_specmountpoint = NULL;
@ -573,7 +596,7 @@ ntfs_unmount(
vrele(ntmp->ntm_devvp);
printf("ntfs_umount: freeing memory...\n");
dprintf(("ntfs_umount: freeing memory...\n"));
mp->mnt_data = (qaddr_t)0;
mp->mnt_flag &= ~MNT_LOCAL;
FREE(ntmp->ntm_ad, M_NTFSMNT);
@ -614,6 +637,41 @@ ntfs_quotactl (
return EOPNOTSUPP;
}
int
ntfs_calccfree(
struct ntfsmount *ntmp,
cn_t *cfreep)
{
struct vnode *vp;
u_int8_t *tmp;
int j, error;
long cfree = 0;
size_t bmsize, i;
vp = ntmp->ntm_sysvn[NTFS_BITMAPINO];
bmsize = VTOF(vp)->f_size;
MALLOC(tmp, u_int8_t *, bmsize, M_TEMP, M_WAITOK);
error = ntfs_readattr(ntmp, VTONT(vp), NTFS_A_DATA, NULL,
0, bmsize, tmp);
if(error) {
FREE(tmp, M_TEMP);
return (error);
}
for(i=0;i<bmsize;i++)
for(j=0;j<8;j++)
if(~tmp[i] & (1 << j)) cfree++;
FREE(tmp, M_TEMP);
*cfreep = cfree;
return(0);
}
static int
ntfs_statfs(
struct mount *mp,
@ -621,39 +679,12 @@ ntfs_statfs(
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;
u_int64_t mftsize,mftallocated;
dprintf(("ntfs_statfs():"));
dprintf(("ntfs_statfs():\n"));
ntfs_filesize(ntmp, VTOF(ntmp->ntm_sysvn[NTFS_MFTINO]),
&mftsize, &mftallocated);
error = VFS_VGET(mp, NTFS_BITMAPINO, &vp);
if(error)
return (error);
ntfs_filesize(ntmp, VTOF(vp), &bmsize, &bmallocated);
MALLOC(tmp, u_int8_t *, bmsize,M_TEMP, M_WAITOK);
error = ntfs_readattr(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);
mftsize = VTOF(ntmp->ntm_sysvn[NTFS_MFTINO])->f_size;
mftallocated = VTOF(ntmp->ntm_sysvn[NTFS_MFTINO])->f_allocated;
#if __FreeBSD_version >= 300000
sbp->f_type = mp->mnt_vfc->vfc_typenum;
@ -663,7 +694,7 @@ ntfs_statfs(
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_bfree = sbp->f_bavail = ntfs_cntobn(ntmp->ntm_cfree);
sbp->f_ffree = sbp->f_bfree / ntmp->ntm_bpmftrec;
sbp->f_files = mftallocated / ntfs_bntob(ntmp->ntm_bpmftrec) +
sbp->f_ffree;
@ -746,41 +777,63 @@ ntfs_vgetex(
*vpp = NULL;
/* Get ntnode */
error = ntfs_ntget(ntmp, ino, &ip);
error = ntfs_ntlookup(ntmp, ino, &ip);
if (error) {
printf("ntfs_vget: ntfs_ntget failed\n");
return (error);
}
/* It may be not initialized fully, so force load it */
if (!(flags & VG_DONTLOADIN) && !(ip->i_flag & IN_LOADED)) {
error = ntfs_loadntnode(ntmp, ip);
if(error) {
printf("ntfs_vget: CAN'T LOAD ATTRIBUTES FOR INO: %d\n",
ip->i_number);
ntfs_ntput(ip);
return (error);
}
}
error = ntfs_fget(ntmp, ip, attrtype, attrname, &fp);
if (error) {
printf("ntfs_vget: ntfs_fget failed\n");
ntfs_ntrele(ip);
ntfs_ntput(ip);
return (error);
}
if (!(flags & VG_DONTVALIDFN) && !(fp->f_flag & FN_VALID)) {
if ((ip->i_frflag & NTFS_FRFLAG_DIR) &&
(fp->f_attrtype == 0x80 && fp->f_attrname == NULL)) {
fp->f_type = VDIR;
} else if(flags & VG_EXT) {
fp->f_type = VNON;
fp->f_size =fp->f_allocated = 0;
} else {
fp->f_type = VREG;
error = ntfs_filesize(ntmp, fp,
&fp->f_size, &fp->f_allocated);
if (error) {
ntfs_ntput(ip);
return (error);
}
}
fp->f_flag |= FN_VALID;
}
if (FTOV(fp)) {
vget(FTOV(fp), lkflags, p);
*vpp = FTOV(fp);
ntfs_ntrele(ip);
ntfs_ntput(ip);
return (0);
}
/* It may be not initialized fully, so force load it */
if (!(flags & VG_DONTLOAD) && !(ip->i_flag & IN_LOADED)) {
error = ntfs_loadntnode(ntmp, ip);
if(error) {
printf("ntfs_vget: CAN'T LOAD ATTRIBUTES FOR INO: %d\n",
ip->i_number);
ntfs_ntrele(ip);
return (error);
}
}
error = getnewvnode(VT_NTFS, ntmp->ntm_mountp, ntfs_vnodeop_p, &vp);
if(error) {
ntfs_frele(fp);
ntfs_ntrele(ip);
ntfs_ntput(ip);
return (error);
}
dprintf(("ntfs_vget: vnode: %p for ntnode: %d\n", vp,ino));
@ -788,18 +841,12 @@ ntfs_vgetex(
lockinit(&fp->f_lock, PINOD, "fnode", 0, 0);
fp->f_vp = vp;
vp->v_data = fp;
if (ip->i_frflag & NTFS_FRFLAG_DIR)
vp->v_type = fp->f_type = VDIR;
else
vp->v_type = fp->f_type = VREG;
vp->v_type = fp->f_type;
if (ino == NTFS_ROOTINO)
vp->v_flag |= VROOT;
if (ino < NTFS_SYSNODESNUM)
vp->v_flag |= VSYSTEM;
ntfs_ntrele(ip);
ntfs_ntput(ip);
if (lkflags & LK_TYPE_MASK) {
error = vn_lock(vp, lkflags, p);

View File

@ -25,9 +25,13 @@
*
* $Id: ntfs_vfsops.h,v 1.1 1999/02/02 01:54:54 semen Exp $
*/
#define VG_DONTLOAD 0x0001 /* Tells ntfs_vgetex to do not call */
#define VG_DONTLOADIN 0x0001 /* Tells ntfs_vgetex to do not call */
/* ntfs_loadnode on ntnode, even if */
/* ntnode not loaded */
#define VG_DONTVALIDFN 0x0002 /* Tells ntfs_vgetex to do not validate */
/* fnode */
#define VG_EXT 0x0004 /* This is not main record */
int ntfs_vgetex(struct mount *, ino_t, u_int32_t, char *, u_long, u_long,
struct proc *, struct vnode **);
int ntfs_calccfree(struct ntfsmount *, cn_t *);

View File

@ -156,7 +156,8 @@ ntfs_read(ap)
dprintf(("ntfs_read: ino: %d, off: %d resid: %d, segflg: %d\n",ip->i_number,(u_int32_t)uio->uio_offset,uio->uio_resid,uio->uio_segflg));
ntfs_filesize(ntmp, fp, &toread, NULL);
toread = fp->f_size;
dprintf(("ntfs_read: filesize: %d",(u_int32_t)toread));
toread = min( uio->uio_resid, toread - uio->uio_offset );
@ -165,7 +166,7 @@ ntfs_read(ap)
MALLOC(data, u_int8_t *, toread, M_TEMP,M_WAITOK);
error = ntfs_readattr( ntmp, ip, fp->f_attrtype,
error = ntfs_readattr(ntmp, ip, fp->f_attrtype,
fp->f_attrname, uio->uio_offset, toread, data);
if(error) {
printf("ntfs_read: ntfs_readattr failed: %d\n",error);
@ -245,9 +246,7 @@ ntfs_inactive(ap)
} */ *ap;
{
register struct vnode *vp = ap->a_vp;
#if defined(NTFS_DEBUG) || defined(DISGNOSTIC)
register struct ntnode *ip = VTONT(vp);
#endif
int error;
dprintf(("ntfs_inactive: vnode: %p, ntnode: %d\n", vp, ip->i_number));
@ -262,7 +261,7 @@ ntfs_inactive(ap)
#else
#ifdef DIAGNOSTIC
if (VOP_ISLOCKED(vp))
panic("ntfs_inactive: locked ntnode");
panic("ntfs_inactive: locked vnode");
if (curproc)
ip->i_lockholder = curproc->p_pid;
else
@ -275,7 +274,7 @@ ntfs_inactive(ap)
* If we are done with the ntnode, reclaim it
* so that it can be reused immediately.
*/
if (vp->v_usecount == 0 /*&& ip->i_mode == 0*/)
if (vp->v_usecount == 0 && ip->i_mode == 0)
#if __FreeBSD_version >= 300000
vrecycle(vp, (struct simplelock *)0, ap->a_p);
#else
@ -295,12 +294,15 @@ ntfs_reclaim(ap)
{
register struct vnode *vp = ap->a_vp;
register struct fnode *fp = VTOF(vp);
#if NTFS_DEBUG
register struct ntnode *ip = FTONT(fp);
#endif
int error;
dprintf(("ntfs_reclaim: vnode: %p, ntnode: %d\n", vp, ip->i_number));
error = ntfs_ntget(ip);
if (error)
return (error);
#if __FreeBSD_version >= 300000
VOP_UNLOCK(vp,0,ap->a_p);
#endif
@ -316,6 +318,8 @@ ntfs_reclaim(ap)
vp->v_data = NULL;
ntfs_ntput(ip);
return (0);
}
@ -428,15 +432,15 @@ ntfs_write(ap)
dprintf(("ntfs_write: ino: %d, off: %d resid: %d, segflg: %d\n",ip->i_number,(u_int32_t)uio->uio_offset,uio->uio_resid,uio->uio_segflg));
ntfs_filesize(ntmp, fp, &towrite, NULL);
towrite = fp->f_size;
dprintf(("ntfs_write: filesize: %d",(u_int32_t)towrite));
if (uio->uio_resid + uio->uio_offset > towrite) {
printf("ntfs_write: CAN'T WRITE BEYOND OF FILE\n");
return (EFBIG);
}
dprintf(("ntfs_write: filesize: %d",(u_int32_t)towrite));
towrite = min(uio->uio_resid, towrite - uio->uio_offset);
off = uio->uio_offset;
@ -948,7 +952,7 @@ ntfs_lookup(ap)
}
return (error);
} else {
error = ntfs_ntlookup(ntmp, dvp, cnp, ap->a_vpp);
error = ntfs_ntlookupfile(ntmp, dvp, cnp, ap->a_vpp);
if(error)
return (error);
@ -961,6 +965,8 @@ ntfs_lookup(ap)
#else
VOP_UNLOCK(dvp);
#endif
if (cnp->cn_flags & MAKEENTRY)
cache_enter(dvp, *ap->a_vpp, cnp);
}
return (error);

View File

@ -23,7 +23,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* $Id: ntfs.h,v 1.2 1999/02/19 12:31:02 semenu Exp $
* $Id: ntfs.h,v 1.9 1999/02/02 01:54:54 semen Exp $
*/
/*#define NTFS_DEBUG 1*/
@ -213,6 +213,8 @@ struct ntvattrdef {
u_int32_t ad_type;
};
#define NTFS_BBID "NTFS "
#define NTFS_BBIDLEN 8
struct bootfile {
u_int8_t reserved1[3]; /* asm jmp near ... */
u_int8_t bf_sysid[8]; /* 'NTFS ' */
@ -246,6 +248,7 @@ struct ntfsmount {
gid_t ntm_gid;
mode_t ntm_mode;
u_long ntm_flag;
cn_t ntm_cfree;
struct ntvattrdef *ntm_ad;
int ntm_adnum;
};

View File

@ -55,17 +55,18 @@
#define IN_PRELOADED 0x4000 /* loaded from directory entry */
struct ntnode {
LIST_ENTRY(ntnode) i_hash;
LIST_ENTRY(ntnode) i_hash;
struct ntnode *i_next;
struct ntnode **i_prev;
struct ntfsmount *i_mp;
struct ntfsmount *i_mp;
ino_t i_number;
dev_t i_dev;
u_int32_t i_flag;
int i_lock;
int i_usecount;
LIST_HEAD(,fnode) i_fnlist;
struct ntvattr *i_vattrp; /* ntvattrs list */
LIST_HEAD(,fnode) i_fnlist;
LIST_HEAD(,ntvattr) i_valist;
long i_nlink; /* MFR */
ino_t i_mainrec; /* MFR */
@ -77,7 +78,7 @@ struct ntnode {
};
#define FN_PRELOADED 0x0001
#define FN_DEFAULT 0x0002
#define FN_VALID 0x0002
#define FN_AATTRNAME 0x0004 /* space allocated for f_attrname */
struct fnode {
struct lock f_lock; /* Must be first */

View File

@ -1,5 +1,5 @@
/*-
* Copyright (c) 1998, 1999 Semen Ustimenko
* Copyright (c) 1998, 1999 Semen Ustimenko (semenu@FreeBSD.org)
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@ -58,6 +58,9 @@ MALLOC_DEFINE(M_NTFSRUN, "NTFS vrun", "NTFS vrun storage");
MALLOC_DEFINE(M_NTFSDECOMP, "NTFS decomp", "NTFS decompression temporary");
#endif
/*
*
*/
int
ntfs_ntvattrrele(
struct ntvattr * vap)
@ -70,6 +73,13 @@ ntfs_ntvattrrele(
return (0);
}
/*
* Search attribute specifed in ntnode (load ntnode if nessecary).
* If not found but ATTR_A_ATTRLIST present, read it in and search throught.
* VOP_VGET node needed, and lookup througth it's ntnode (load if nessesary).
*
* ntnode should be locked
*/
int
ntfs_ntvattrget(
struct ntfsmount * ntmp,
@ -113,7 +123,7 @@ ntfs_ntvattrget(
}
}
for (vap = ip->i_vattrp; vap; vap = vap->va_nextp) {
for (vap = ip->i_valist.lh_first; vap; vap = vap->va_list.le_next) {
ddprintf(("type: 0x%x, vcn: %d - %d\n", \
vap->va_type, (u_int32_t) vap->va_vcnstart, \
(u_int32_t) vap->va_vcnend));
@ -171,14 +181,20 @@ ntfs_ntvattrget(
dprintf(("ntfs_ntvattrget: attrbute in ino: %d\n",
aalp->al_inumber));
/*
error = VFS_VGET(ntmp->ntm_mountp, aalp->al_inumber,
&newvp);
*/
error = ntfs_vgetex(ntmp->ntm_mountp, aalp->al_inumber,
NTFS_A_DATA, NULL, LK_EXCLUSIVE,
VG_EXT, curproc, &newvp);
if (error) {
printf("ntfs_ntvattrget: CAN'T VGET INO: %d\n",
aalp->al_inumber);
goto out;
}
newip = VTONT(newvp);
/* XXX have to lock ntnode */
if(~newip->i_flag & IN_LOADED) {
dprintf(("ntfs_ntvattrget: node not loaded," \
" ino: %d\n", newip->i_number));
@ -190,7 +206,7 @@ ntfs_ntvattrget(
goto out;
}
}
for (vap = newip->i_vattrp; vap; vap = vap->va_nextp) {
for (vap = newip->i_valist.lh_first; vap; vap = vap->va_list.le_next) {
if ((vap->va_type == type) &&
(vap->va_vcnstart <= vcn) &&
(vap->va_vcnend >= vcn) &&
@ -219,10 +235,14 @@ ntfs_ntvattrget(
ip->i_number, type, name, (u_int32_t) vcn));
out:
FREE(alpool, M_TEMP);
return (error);
}
/*
* Read ntnode from disk, make ntvattr list.
*
* ntnode should be locked
*/
int
ntfs_loadntnode(
struct ntfsmount * ntmp,
@ -232,7 +252,7 @@ ntfs_loadntnode(
daddr_t bn;
int error,off;
struct attr *ap;
struct ntvattr**vapp;
struct ntvattr *nvap;
dprintf(("ntfs_loadnode: loading ino: %d\n",ip->i_number));
@ -269,6 +289,7 @@ ntfs_loadntnode(
goto out;
}
}
/* Check if magic and fixups are correct */
error = ntfs_procfixups(ntmp, NTFS_FILEMAGIC, (caddr_t)mfrp,
ntfs_bntob(ntmp->ntm_bpmftrec));
@ -281,16 +302,16 @@ ntfs_loadntnode(
dprintf(("ntfs_loadnode: load attrs for ino: %d\n",ip->i_number));
off = mfrp->fr_attroff;
ap = (struct attr *) ((caddr_t)mfrp + off);
if (ip->i_vattrp)
printf("ntfs_ntloadnode: WARNING! already loaded?\n");
LIST_INIT(&ip->i_valist);
vapp = &ip->i_vattrp;
while (ap->a_hdr.a_type != -1) {
error = ntfs_attrtontvattr(ntmp, vapp, ap);
error = ntfs_attrtontvattr(ntmp, &nvap, ap);
if (error)
break;
(*vapp)->va_ip = ip;
vapp = &((*vapp)->va_nextp);
nvap->va_ip = ip;
LIST_INSERT_HEAD(&ip->i_valist, nvap, va_list);
off += ap->a_hdr.reclen;
ap = (struct attr *) ((caddr_t)mfrp + off);
@ -312,44 +333,74 @@ out:
return (error);
}
static int ntfs_ntnode_hash_lock;
/*
* Routine locks ntnode and increase usecount, just opposite of
* ntfs_ntput.
*/
int
ntfs_ntget(
struct ntnode *ip)
{
dprintf(("ntfs_ntget: get ntnode %d: %p, usecount: %d\n",
ip->i_number, ip, ip->i_usecount));
ip->i_usecount++;
restart:
if (ip->i_lock) {
while (ip->i_lock) {
ip->i_lock = -1;
tsleep(&ip->i_lock, PVM, "ntnode", 0);
}
goto restart;
}
ip->i_lock = 1;
return 0;
}
/*
* Routine search ntnode in hash, if found: lock, inc usecount and return.
* If not in hash allocate structure for ntnode, prefill it, lock,
* inc count and return.
*
* ntnode returned locked
*/
static int ntfs_ntnode_hash_lock;
int
ntfs_ntlookup(
struct ntfsmount * ntmp,
ino_t ino,
struct ntnode ** ipp)
{
struct ntnode *ip;
dprintf(("ntfs_ntget: ntget ntnode %d\n", ino));
dprintf(("ntfs_ntlookup: for ntnode %d\n", ino));
*ipp = NULL;
restart:
ip = ntfs_nthashlookup(ntmp->ntm_dev, ino);
ip = ntfs_nthashlookup(ntmp->ntm_dev, ino); /* XXX */
if (ip) {
ip->i_usecount++;
ntfs_ntget(ip);
*ipp = ip;
dprintf(("ntfs_ntget: ntnode %d: %p, usecount: %d\n",
dprintf(("ntfs_ntlookup: ntnode %d: %p, usecount: %d\n",
ino, ip, ip->i_usecount));
return (0);
}
if (ntfs_ntnode_hash_lock) {
printf("waiting for hash_lock to free...\n");
while(ntfs_ntnode_hash_lock) {
ntfs_ntnode_hash_lock = -1;
tsleep(&ntfs_ntnode_hash_lock, PVM, "ntfsntgt", 0);
}
printf("hash_lock freeed\n");
goto restart;
}
ntfs_ntnode_hash_lock = 1;
MALLOC(ip, struct ntnode *, sizeof(struct ntnode),
M_NTFSNTNODE, M_WAITOK);
ddprintf(("ntfs_ntget: allocating ntnode: %d: %p\n", ino, ip));
ddprintf(("ntfs_ntlookup: allocating ntnode: %d: %p\n", ino, ip));
bzero((caddr_t) ip, sizeof(struct ntnode));
/* Generic initialization */
@ -361,6 +412,8 @@ restart:
ip->i_mode = ntmp->ntm_mode;
ip->i_usecount++;
ip->i_lock = 1;
LIST_INIT(&ip->i_fnlist);
ntfs_nthashins(ip);
@ -371,45 +424,77 @@ restart:
*ipp = ip;
dprintf(("ntfs_ntget: ntnode %d: %p, usecount: %d\n",
dprintf(("ntfs_ntlookup: ntnode %d: %p, usecount: %d\n",
ino, ip, ip->i_usecount));
return (0);
}
/*
* Decrement usecount of ntnode and unlock it, if usecount reach zero,
* deallocate ntnode.
*
* ntnode should be locked on entry, and unlocked on return.
*/
void
ntfs_ntrele(
struct ntnode * ip)
ntfs_ntput(
struct ntnode *ip)
{
struct ntvattr *vap;
dprintf(("ntfs_ntrele: rele ntnode %d: %p, usecount: %d\n",
if (!ip->i_lock) printf("ntfs_ntput: NOT LOCKED");
dprintf(("ntfs_ntput: rele ntnode %d: %p, usecount: %d\n",
ip->i_number, ip, ip->i_usecount));
ip->i_usecount--;
if (ip->i_usecount < 0) {
panic("ntfs_ntrele: ino: %d usecount: %d \n",
panic("ntfs_ntput: ino: %d usecount: %d \n",
ip->i_number,ip->i_usecount);
} else if (ip->i_usecount == 0) {
dprintf(("ntfs_ntrele: deallocating ntnode: %d\n",
dprintf(("ntfs_ntput: deallocating ntnode: %d\n",
ip->i_number));
if (ip->i_fnlist.lh_first)
panic("ntfs_ntrele: ntnode has fnodes\n");
panic("ntfs_ntput: ntnode has fnodes\n");
ntfs_nthashrem(ip);
while (ip->i_vattrp) {
vap = ip->i_vattrp;
ip->i_vattrp = vap->va_nextp;
while (ip->i_valist.lh_first != NULL) {
vap = ip->i_valist.lh_first;
LIST_REMOVE(vap,va_list);
ntfs_freentvattr(vap);
}
FREE(ip, M_NTFSNTNODE);
} else {
if (ip->i_lock < 0)
wakeup(&ip->i_lock);
ip->i_lock = 0;
}
dprintf(("ntfs_ntrele: rele ok\n"));
}
/*
* Decrement usecount of ntnode.
*/
void
ntfs_ntrele(
struct ntnode * ip)
{
dprintf(("ntfs_ntrele: rele ntnode %d: %p, usecount: %d\n",
ip->i_number, ip, ip->i_usecount));
ip->i_usecount--;
if (ip->i_usecount < 0)
panic("ntfs_ntrele: ino: %d usecount: %d \n",
ip->i_number,ip->i_usecount);
}
/*
* Deallocate all memory allocated for ntvattr by call to
* ntfs_attrtontvattr and some other functions.
*/
void
ntfs_freentvattr(
struct ntvattr * vap)
@ -426,6 +511,10 @@ ntfs_freentvattr(
FREE(vap, M_NTFSNTVATTR);
}
/*
* Convert disk image of attribute into ntvattr structure,
* runs are expanded also.
*/
int
ntfs_attrtontvattr(
struct ntfsmount * ntmp,
@ -493,6 +582,9 @@ ntfs_attrtontvattr(
return (error);
}
/*
* Expand run into more utilizable and more memory eating format.
*/
int
ntfs_runtovrun(
cn_t ** rcnp,
@ -552,7 +644,9 @@ ntfs_runtovrun(
return (0);
}
/*
* Convert wchar to uppercase wchar, should be macros?
*/
wchar
ntfs_toupper(
struct ntfsmount * ntmp,
@ -561,6 +655,9 @@ ntfs_toupper(
return (ntmp->ntm_upcase[wc & 0xFF]);
}
/*
* Compare to unicode strings case insensible.
*/
int
ntfs_uustricmp(
struct ntfsmount * ntmp,
@ -581,6 +678,9 @@ ntfs_uustricmp(
return (str1len - str2len);
}
/*
* Compare unicode and ascii string case insens.
*/
int
ntfs_uastricmp(
struct ntfsmount * ntmp,
@ -601,6 +701,9 @@ ntfs_uastricmp(
return (str1len - str2len);
}
/*
* Compare unicode and ascii string case sens.
*/
int
ntfs_uastrcmp(
struct ntfsmount * ntmp,
@ -620,6 +723,11 @@ ntfs_uastrcmp(
return (str1len - str2len);
}
/*
* Search fnode in ntnode, if not found allocate and preinitialize.
*
* ntnode should be locked on entry.
*/
int
ntfs_fget(
struct ntfsmount *ntmp,
@ -628,7 +736,6 @@ ntfs_fget(
char *attrname,
struct fnode **fpp)
{
int error;
struct fnode *fp;
dprintf(("ntfs_fget: ino: %d, attrtype: 0x%x, attrname: %s\n",
@ -662,15 +769,6 @@ ntfs_fget(
fp->f_attrname = attrname;
if (fp->f_attrname) fp->f_flag |= FN_AATTRNAME;
fp->f_attrtype = attrtype;
if ((fp->f_attrtype == NTFS_A_DATA) && (fp->f_attrname == NULL))
fp->f_flag |= FN_DEFAULT;
else {
error = ntfs_filesize(ntmp, fp, &fp->f_size, &fp->f_allocated);
if (error) {
FREE(fp,M_NTFSFNODE);
return (error);
}
}
ntfs_ntref(ip);
@ -681,6 +779,11 @@ ntfs_fget(
return (0);
}
/*
* Deallocate fnode, remove it from ntnode's fnode list.
*
* ntnode should be locked.
*/
void
ntfs_frele(
struct fnode *fp)
@ -699,6 +802,11 @@ ntfs_frele(
ntfs_ntrele(ip);
}
/*
* Lookup attribute name in format: [[:$ATTR_TYPE]:$ATTR_NAME],
* $ATTR_TYPE is searched in attrdefs read from $AttrDefs.
* If $ATTR_TYPE nott specifed, ATTR_A_DATA assumed.
*/
int
ntfs_ntlookupattr(
struct ntfsmount * ntmp,
@ -753,12 +861,13 @@ ntfs_ntlookupattr(
return (0);
}
/*
* Lookup specifed node for filename, matching cnp,
* return fnode filled.
*/
int
ntfs_ntlookup(
ntfs_ntlookupfile(
struct ntfsmount * ntmp,
struct vnode * vp,
struct componentname * cnp,
@ -776,6 +885,10 @@ ntfs_ntlookup(
char *fname,*aname;
u_int32_t aoff;
error = ntfs_ntget(ip);
if (error)
return (error);
error = ntfs_ntvattrget(ntmp, ip, NTFS_A_INDXROOT, "$I30", 0, &vap);
if (error || (vap->va_flag & NTFS_AF_INRUN))
return (ENOTDIR);
@ -783,6 +896,10 @@ ntfs_ntlookup(
blsize = vap->va_a_iroot->ir_size;
rdsize = vap->va_datalen;
/*
* Divide file name into: foofilefoofilefoofile[:attrspec]
* Store like this: fname:fnamelen [aname:anamelen]
*/
fname = cnp->cn_nameptr;
aname = NULL;
anamelen = 0;
@ -790,12 +907,12 @@ ntfs_ntlookup(
if(fname[fnamelen] == ':') {
aname = fname + fnamelen + 1;
anamelen = cnp->cn_namelen - fnamelen - 1;
dprintf(("ntfs_ntlookup: file %s (%d), attr: %s (%d)\n",
dprintf(("ntfs_ntlookupfile: %s (%d), attr: %s (%d)\n",
fname, fnamelen, aname, anamelen));
break;
}
dprintf(("ntfs_ntlookup: blocksize: %d, rdsize: %d\n", blsize, rdsize));
dprintf(("ntfs_ntlookupfile: blksz: %d, rdsz: %d\n", blsize, rdsize));
MALLOC(rdbuf, caddr_t, blsize, M_TEMP, M_WAITOK);
@ -856,7 +973,8 @@ ntfs_ntlookup(
attrtype,
attrname,
LK_EXCLUSIVE,
VG_DONTLOAD,
VG_DONTLOADIN |
VG_DONTVALIDFN,
curproc,
&nvp);
if(error)
@ -864,6 +982,11 @@ ntfs_ntlookup(
nfp = VTOF(nvp);
if (nfp->f_flag & FN_VALID) {
*vpp = nvp;
goto fail;
}
nfp->f_fflag = iep->ie_fflag;
nfp->f_pnumber = iep->ie_fpnumber;
nfp->f_times = iep->ie_ftimes;
@ -883,7 +1006,17 @@ ntfs_ntlookup(
nfp->f_size = iep->ie_fsize;
nfp->f_allocated = iep->ie_fallocated;
nfp->f_flag |= FN_PRELOADED;
} else {
error = ntfs_filesize(ntmp, nfp,
&nfp->f_size,
&nfp->f_allocated);
if (error) {
vput(nvp);
goto fail;
}
}
nfp->f_flag &= ~FN_VALID;
*vpp = nvp;
goto fail;
}
@ -896,7 +1029,7 @@ ntfs_ntlookup(
/* Dive if possible */
if (iep->ie_flag & NTFS_IEFLAG_SUBNODE) {
dprintf(("ntfs_ntlookup: diving\n"));
dprintf(("ntfs_ntlookupfile: diving\n"));
cn = *(cn_t *) (rdbuf + aoff +
iep->reclen - sizeof(cn_t));
@ -915,7 +1048,7 @@ ntfs_ntlookup(
aoff = (((struct attr_indexalloc *) rdbuf)->ia_hdrsize +
0x18);
} else {
dprintf(("ntfs_ntlookup: nowhere to dive :-(\n"));
dprintf(("ntfs_ntlookupfile: nowhere to dive :-(\n"));
error = ENOENT;
break;
}
@ -925,10 +1058,14 @@ ntfs_ntlookup(
fail:
ntfs_ntvattrrele(vap);
ntfs_ntput(ip);
FREE(rdbuf, M_TEMP);
return (error);
}
/*
* Check if name type is permitted to show.
*/
int
ntfs_isnamepermitted(
struct ntfsmount * ntmp,
@ -942,9 +1079,7 @@ ntfs_isnamepermitted(
case 2:
ddprintf(("ntfs_isnamepermitted: skiped DOS name\n"));
return 0;
case 0:
case 1:
case 3:
case 0: case 1: case 3:
return 1;
default:
printf("ntfs_isnamepermitted: " \
@ -955,6 +1090,14 @@ ntfs_isnamepermitted(
return 0;
}
/*
* Read ntfs dir like stream of attr_indexentry, not like btree of them.
* This is done by scaning $BITMAP:$I30 for busy clusters and reading them.
* Ofcouse $INDEX_ROOT:$I30 is read before. Last read values are stored in
* fnode, so we can skip toward record number num almost immediatly.
* Anyway this is rather slow routine. The problem is that we don't know
* how many records are there in $INDEX_ALLOCATION:$I30 block.
*/
int
ntfs_ntreaddir(
struct ntfsmount * ntmp,
@ -978,6 +1121,10 @@ ntfs_ntreaddir(
u_int32_t aoff, cnum;
dprintf(("ntfs_ntreaddir: read ino: %d, num: %d\n", ip->i_number, num));
error = ntfs_ntget(ip);
if (error)
return (error);
error = ntfs_ntvattrget(ntmp, ip, NTFS_A_INDXROOT, "$I30", 0, &vap);
if (error)
return (ENOTDIR);
@ -1106,12 +1253,14 @@ fail:
ntfs_ntvattrrele(iavap);
if (bmp)
FREE(bmp, M_TEMP);
ntfs_ntput(ip);
return (error);
}
/*
* #undef dprintf #define dprintf(a)
*/
/*
* Convert NTFS times that are in 100 ns units and begins from
* 1601 Jan 1 into unix times.
*/
struct timespec
ntfs_nttimetounix(
u_int64_t nt)
@ -1126,6 +1275,9 @@ ntfs_nttimetounix(
return (t);
}
/*
* Get file times from NTFS_A_NAME attribute.
*/
int
ntfs_times(
struct ntfsmount * ntmp,
@ -1136,15 +1288,28 @@ ntfs_times(
int error;
dprintf(("ntfs_times: ino: %d...\n", ip->i_number));
error = ntfs_ntvattrget(ntmp, ip, NTFS_A_NAME, NULL, 0, &vap);
error = ntfs_ntget(ip);
if (error)
return (error);
error = ntfs_ntvattrget(ntmp, ip, NTFS_A_NAME, NULL, 0, &vap);
if (error) {
ntfs_ntput(ip);
return (error);
}
*tm = vap->va_a_name->n_times;
ntfs_ntvattrrele(vap);
ntfs_ntput(ip);
return (0);
}
/*
* Get file sizes from corresponding attribute.
*
* ntnode under fnode should be locked.
*/
int
ntfs_filesize(
struct ntfsmount * ntmp,
@ -1158,15 +1323,12 @@ ntfs_filesize(
int error;
dprintf(("ntfs_filesize: ino: %d\n", ip->i_number));
if (fp->f_flag & FN_DEFAULT) {
error = ntfs_ntvattrget(ntmp, ip,
NTFS_A_DATA, NULL, 0, &vap);
} else {
error = ntfs_ntvattrget(ntmp, ip,
fp->f_attrtype, fp->f_attrname, 0, &vap);
}
error = ntfs_ntvattrget(ntmp, ip,
fp->f_attrtype, fp->f_attrname, 0, &vap);
if (error)
return (error);
bn = vap->va_allocated;
sz = vap->va_datalen;
@ -1183,6 +1345,11 @@ ntfs_filesize(
return (0);
}
/*
* This is one of write routine.
*
* ntnode should be locked.
*/
int
ntfs_writeattr_plain(
struct ntfsmount * ntmp,
@ -1234,6 +1401,11 @@ ntfs_writeattr_plain(
return (error);
}
/*
* This is one of write routine.
*
* ntnode should be locked.
*/
int
ntfs_writentvattr_plain(
struct ntfsmount * ntmp,
@ -1313,7 +1485,7 @@ ntfs_writentvattr_plain(
}
}
memcpy(bp->b_data + off, data, tocopy);
bwrite(bp);
bawrite(bp);
data = data + tocopy;
*initp += tocopy;
off = 0;
@ -1336,6 +1508,11 @@ ntfs_writentvattr_plain(
return (error);
}
/*
* This is one of read routines.
*
* ntnode should be locked.
*/
int
ntfs_readntvattr_plain(
struct ntfsmount * ntmp,
@ -1379,7 +1556,7 @@ ntfs_readntvattr_plain(
cnt++;
continue;
}
if (ccn || ip->i_number == NTFS_BOOTINO) { /* XXX */
if (ccn || ip->i_number == NTFS_BOOTINO) {
ccl -= ntfs_btocn(off);
cn = ccn + ntfs_btocn(off);
off = ntfs_btocnoff(off);
@ -1442,6 +1619,11 @@ ntfs_readntvattr_plain(
return (error);
}
/*
* This is one of read routines.
*
* ntnode should be locked.
*/
int
ntfs_readattr_plain(
struct ntfsmount * ntmp,
@ -1493,6 +1675,11 @@ ntfs_readattr_plain(
return (error);
}
/*
* This is one of read routines.
*
* ntnode should be locked.
*/
int
ntfs_readattr(
struct ntfsmount * ntmp,
@ -1574,6 +1761,7 @@ ntfs_readattr(
return (error);
}
#if UNUSED_CODE
int
ntfs_parserun(
cn_t * cn,
@ -1616,7 +1804,11 @@ ntfs_parserun(
return (0);
}
#endif
/*
* Process fixup routine on given buffer.
*/
int
ntfs_procfixups(
struct ntfsmount * ntmp,
@ -1659,6 +1851,7 @@ ntfs_procfixups(
return (0);
}
#if UNUSED_CODE
int
ntfs_runtocn(
cn_t * cn,
@ -1701,3 +1894,4 @@ ntfs_runtocn(
*cn = ccn + vcn;
return (0);
}
#endif

View File

@ -30,7 +30,7 @@
#define VA_PRELOADED 0x0002
struct ntvattr {
struct ntvattr *va_nextp;
LIST_ENTRY(ntvattr) va_list;
u_int32_t va_vflag;
struct vnode *va_vp;
@ -99,12 +99,14 @@ 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 vnode *, struct componentname *, struct vnode **));
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_ntlookupfile __P((struct ntfsmount *, struct vnode *, struct componentname *, struct vnode **));
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_ntlookup __P((struct ntfsmount *, ino_t, struct ntnode **));
int ntfs_ntget __P((struct ntnode *));
void ntfs_ntrele __P((struct ntnode *));
void ntfs_ntput __P((struct ntnode *));
int ntfs_loadntnode __P(( struct ntfsmount *, struct ntnode * ));
int ntfs_ntlookupattr(struct ntfsmount *, char *, int, int *, char **);
int ntfs_writentvattr_plain(struct ntfsmount *, struct ntnode *, struct ntvattr *, off_t, size_t, void *, size_t *);

View File

@ -102,13 +102,6 @@ static int
ntfs_init ()
#endif
{
static first=1;
if(!first) return (0);
first = 1;
printf("ntfs_init(): \n");
ntfs_nthashinit();
return 0;
@ -384,6 +377,12 @@ ntfs_mountfs(devvp, mp, argsp, p)
brelse( bp );
bp = NULL;
if (strncmp(ntmp->ntm_bootfile.bf_sysid, NTFS_BBID, NTFS_BBIDLEN)) {
error = EINVAL;
printf("ntfs_mountfs: invalid boot block\n");
goto out;
}
{
int8_t cpr = ntmp->ntm_mftrecsz;
if( cpr > 0 )
@ -391,11 +390,11 @@ ntfs_mountfs(devvp, mp, argsp, p)
else
ntmp->ntm_bpmftrec = (1 << (-cpr)) / ntmp->ntm_bps;
}
printf("ntfs_mountfs(): bps: %d, spc: %d, media: %x, mftrecsz: %d (%d sects)\n",
dprintf(("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_mftrecsz,ntmp->ntm_bpmftrec));
dprintf(("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;
@ -406,51 +405,64 @@ ntfs_mountfs(devvp, mp, argsp, p)
ntmp->ntm_flag = argsp->flag;
mp->mnt_data = (qaddr_t)ntmp;
printf("ntfs_mountfs(): case-%s,%s uid: %d, gid: %d, mode: %o\n",
dprintf(("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);
ntmp->ntm_uid, ntmp->ntm_gid, ntmp->ntm_mode));
printf("ntfs_mountfs(): reading system nodes...\n");
/*
* We read in some system nodes to do not allow
* reclaim them and to have everytime access to them.
*/
{
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]);
i = NTFS_ROOTINO;
error = VFS_VGET(mp, i, &(ntmp->ntm_sysvn[i]));
if(error)
goto out1;
VREF(ntmp->ntm_sysvn[i]);
vput(ntmp->ntm_sysvn[i]);
int pi[3] = { NTFS_MFTINO, NTFS_ROOTINO, NTFS_BITMAPINO };
for (i=0; i<3; i++) {
error = VFS_VGET(mp, pi[i], &(ntmp->ntm_sysvn[pi[i]]));
if(error)
goto out1;
ntmp->ntm_sysvn[pi[i]]->v_flag |= VSYSTEM;
VREF(ntmp->ntm_sysvn[pi[i]]);
vput(ntmp->ntm_sysvn[pi[i]]);
}
}
MALLOC( ntmp->ntm_upcase, wchar *, 65536 * sizeof(wchar),
/*
* Read in WHOLE lowcase -> upcase translation
* file.
*/
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 );
error = VFS_VGET(mp, NTFS_UPCASEINO, &vp);
if(error)
goto out1;
printf("ntfs_mountfs(): reading $UpCase\n");
error = ntfs_readattr( ntmp, VTONT(vp), NTFS_A_DATA, NULL,
error = ntfs_readattr(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;
/*
* Scan $BitMap and count free clusters
*/
error = ntfs_calccfree(ntmp, &ntmp->ntm_cfree);
if(error)
goto out1;
/*
* Read and translate to internal format attribute
* definition file.
*/
{
int num,j;
struct attrdef ad;
printf("ntfs_mountfs(): opening $AttrDef\n");
/* Open $AttrDef */
error = VFS_VGET(mp, NTFS_ATTRDEFINO, &vp );
if(error)
goto out1;
/* Count valid entries */
for(num=0;;num++) {
error = ntfs_readattr(ntmp, VTONT(vp),
NTFS_A_DATA, NULL,
@ -461,14 +473,15 @@ ntfs_mountfs(devvp, mp, argsp, p)
if (ad.ad_name[0] == 0)
break;
}
printf("ntfs_mountfs(): reading %d attrdefs\n",num);
/* Alloc memory for attribute definitions */
MALLOC(ntmp->ntm_ad, struct ntvattrdef *,
num * sizeof(struct ntvattrdef),
M_NTFSMNT, M_WAITOK);
ntmp->ntm_adnum = num;
/* Read them and translate */
for(i=0;i<num;i++){
error = ntfs_readattr(ntmp, VTONT(vp),
NTFS_A_DATA, NULL,
@ -482,11 +495,8 @@ ntfs_mountfs(devvp, mp, argsp, p)
} 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);
}
@ -504,9 +514,14 @@ ntfs_mountfs(devvp, mp, argsp, p)
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]);
if (vflush(mp,NULLVP,0))
printf("ntfs_mountfs: vflush failed\n");
out:
#if __FreeBSD_version >= 300000
devvp->v_specmountpoint = NULL;
@ -525,7 +540,6 @@ ntfs_start (
int flags,
struct proc *p )
{
printf("\nntfs_start():\n");
return (0);
}
@ -538,24 +552,33 @@ ntfs_unmount(
register struct ntfsmount *ntmp;
int error, ronly = 0, flags, i;
printf("ntfs_unmount: unmounting...\n");
dprintf(("ntfs_unmount: unmounting...\n"));
ntmp = VFSTONTFS(mp);
flags = 0;
if(mntflags & MNT_FORCE)
flags |= FORCECLOSE;
printf("ntfs_unmount: vflushing...\n");
dprintf(("ntfs_unmount: vflushing...\n"));
error = vflush(mp,NULLVP,flags | SKIPSYSTEM);
if (error) {
printf("ntfs_unmount: vflush failed: %d\n",error);
return (error);
}
/* Check if only system vnodes are rest */
for(i=0;i<NTFS_SYSNODESNUM;i++)
if((ntmp->ntm_sysvn[i]) &&
(ntmp->ntm_sysvn[i]->v_usecount > 1)) return (EBUSY);
/* Derefernce all system vnodes */
for(i=0;i<NTFS_SYSNODESNUM;i++)
if(ntmp->ntm_sysvn[i]) vrele(ntmp->ntm_sysvn[i]);
/* vflush system vnodes */
error = vflush(mp,NULLVP,flags);
if (error)
printf("ntfs_unmount: vflush failed: %d\n",error);
printf("ntfs_unmount: vflush failed(sysnodes): %d\n",error);
#if __FreeBSD_version >= 300000
ntmp->ntm_devvp->v_specmountpoint = NULL;
@ -573,7 +596,7 @@ ntfs_unmount(
vrele(ntmp->ntm_devvp);
printf("ntfs_umount: freeing memory...\n");
dprintf(("ntfs_umount: freeing memory...\n"));
mp->mnt_data = (qaddr_t)0;
mp->mnt_flag &= ~MNT_LOCAL;
FREE(ntmp->ntm_ad, M_NTFSMNT);
@ -614,6 +637,41 @@ ntfs_quotactl (
return EOPNOTSUPP;
}
int
ntfs_calccfree(
struct ntfsmount *ntmp,
cn_t *cfreep)
{
struct vnode *vp;
u_int8_t *tmp;
int j, error;
long cfree = 0;
size_t bmsize, i;
vp = ntmp->ntm_sysvn[NTFS_BITMAPINO];
bmsize = VTOF(vp)->f_size;
MALLOC(tmp, u_int8_t *, bmsize, M_TEMP, M_WAITOK);
error = ntfs_readattr(ntmp, VTONT(vp), NTFS_A_DATA, NULL,
0, bmsize, tmp);
if(error) {
FREE(tmp, M_TEMP);
return (error);
}
for(i=0;i<bmsize;i++)
for(j=0;j<8;j++)
if(~tmp[i] & (1 << j)) cfree++;
FREE(tmp, M_TEMP);
*cfreep = cfree;
return(0);
}
static int
ntfs_statfs(
struct mount *mp,
@ -621,39 +679,12 @@ ntfs_statfs(
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;
u_int64_t mftsize,mftallocated;
dprintf(("ntfs_statfs():"));
dprintf(("ntfs_statfs():\n"));
ntfs_filesize(ntmp, VTOF(ntmp->ntm_sysvn[NTFS_MFTINO]),
&mftsize, &mftallocated);
error = VFS_VGET(mp, NTFS_BITMAPINO, &vp);
if(error)
return (error);
ntfs_filesize(ntmp, VTOF(vp), &bmsize, &bmallocated);
MALLOC(tmp, u_int8_t *, bmsize,M_TEMP, M_WAITOK);
error = ntfs_readattr(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);
mftsize = VTOF(ntmp->ntm_sysvn[NTFS_MFTINO])->f_size;
mftallocated = VTOF(ntmp->ntm_sysvn[NTFS_MFTINO])->f_allocated;
#if __FreeBSD_version >= 300000
sbp->f_type = mp->mnt_vfc->vfc_typenum;
@ -663,7 +694,7 @@ ntfs_statfs(
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_bfree = sbp->f_bavail = ntfs_cntobn(ntmp->ntm_cfree);
sbp->f_ffree = sbp->f_bfree / ntmp->ntm_bpmftrec;
sbp->f_files = mftallocated / ntfs_bntob(ntmp->ntm_bpmftrec) +
sbp->f_ffree;
@ -746,41 +777,63 @@ ntfs_vgetex(
*vpp = NULL;
/* Get ntnode */
error = ntfs_ntget(ntmp, ino, &ip);
error = ntfs_ntlookup(ntmp, ino, &ip);
if (error) {
printf("ntfs_vget: ntfs_ntget failed\n");
return (error);
}
/* It may be not initialized fully, so force load it */
if (!(flags & VG_DONTLOADIN) && !(ip->i_flag & IN_LOADED)) {
error = ntfs_loadntnode(ntmp, ip);
if(error) {
printf("ntfs_vget: CAN'T LOAD ATTRIBUTES FOR INO: %d\n",
ip->i_number);
ntfs_ntput(ip);
return (error);
}
}
error = ntfs_fget(ntmp, ip, attrtype, attrname, &fp);
if (error) {
printf("ntfs_vget: ntfs_fget failed\n");
ntfs_ntrele(ip);
ntfs_ntput(ip);
return (error);
}
if (!(flags & VG_DONTVALIDFN) && !(fp->f_flag & FN_VALID)) {
if ((ip->i_frflag & NTFS_FRFLAG_DIR) &&
(fp->f_attrtype == 0x80 && fp->f_attrname == NULL)) {
fp->f_type = VDIR;
} else if(flags & VG_EXT) {
fp->f_type = VNON;
fp->f_size =fp->f_allocated = 0;
} else {
fp->f_type = VREG;
error = ntfs_filesize(ntmp, fp,
&fp->f_size, &fp->f_allocated);
if (error) {
ntfs_ntput(ip);
return (error);
}
}
fp->f_flag |= FN_VALID;
}
if (FTOV(fp)) {
vget(FTOV(fp), lkflags, p);
*vpp = FTOV(fp);
ntfs_ntrele(ip);
ntfs_ntput(ip);
return (0);
}
/* It may be not initialized fully, so force load it */
if (!(flags & VG_DONTLOAD) && !(ip->i_flag & IN_LOADED)) {
error = ntfs_loadntnode(ntmp, ip);
if(error) {
printf("ntfs_vget: CAN'T LOAD ATTRIBUTES FOR INO: %d\n",
ip->i_number);
ntfs_ntrele(ip);
return (error);
}
}
error = getnewvnode(VT_NTFS, ntmp->ntm_mountp, ntfs_vnodeop_p, &vp);
if(error) {
ntfs_frele(fp);
ntfs_ntrele(ip);
ntfs_ntput(ip);
return (error);
}
dprintf(("ntfs_vget: vnode: %p for ntnode: %d\n", vp,ino));
@ -788,18 +841,12 @@ ntfs_vgetex(
lockinit(&fp->f_lock, PINOD, "fnode", 0, 0);
fp->f_vp = vp;
vp->v_data = fp;
if (ip->i_frflag & NTFS_FRFLAG_DIR)
vp->v_type = fp->f_type = VDIR;
else
vp->v_type = fp->f_type = VREG;
vp->v_type = fp->f_type;
if (ino == NTFS_ROOTINO)
vp->v_flag |= VROOT;
if (ino < NTFS_SYSNODESNUM)
vp->v_flag |= VSYSTEM;
ntfs_ntrele(ip);
ntfs_ntput(ip);
if (lkflags & LK_TYPE_MASK) {
error = vn_lock(vp, lkflags, p);

View File

@ -25,9 +25,13 @@
*
* $Id: ntfs_vfsops.h,v 1.1 1999/02/02 01:54:54 semen Exp $
*/
#define VG_DONTLOAD 0x0001 /* Tells ntfs_vgetex to do not call */
#define VG_DONTLOADIN 0x0001 /* Tells ntfs_vgetex to do not call */
/* ntfs_loadnode on ntnode, even if */
/* ntnode not loaded */
#define VG_DONTVALIDFN 0x0002 /* Tells ntfs_vgetex to do not validate */
/* fnode */
#define VG_EXT 0x0004 /* This is not main record */
int ntfs_vgetex(struct mount *, ino_t, u_int32_t, char *, u_long, u_long,
struct proc *, struct vnode **);
int ntfs_calccfree(struct ntfsmount *, cn_t *);

View File

@ -156,7 +156,8 @@ ntfs_read(ap)
dprintf(("ntfs_read: ino: %d, off: %d resid: %d, segflg: %d\n",ip->i_number,(u_int32_t)uio->uio_offset,uio->uio_resid,uio->uio_segflg));
ntfs_filesize(ntmp, fp, &toread, NULL);
toread = fp->f_size;
dprintf(("ntfs_read: filesize: %d",(u_int32_t)toread));
toread = min( uio->uio_resid, toread - uio->uio_offset );
@ -165,7 +166,7 @@ ntfs_read(ap)
MALLOC(data, u_int8_t *, toread, M_TEMP,M_WAITOK);
error = ntfs_readattr( ntmp, ip, fp->f_attrtype,
error = ntfs_readattr(ntmp, ip, fp->f_attrtype,
fp->f_attrname, uio->uio_offset, toread, data);
if(error) {
printf("ntfs_read: ntfs_readattr failed: %d\n",error);
@ -245,9 +246,7 @@ ntfs_inactive(ap)
} */ *ap;
{
register struct vnode *vp = ap->a_vp;
#if defined(NTFS_DEBUG) || defined(DISGNOSTIC)
register struct ntnode *ip = VTONT(vp);
#endif
int error;
dprintf(("ntfs_inactive: vnode: %p, ntnode: %d\n", vp, ip->i_number));
@ -262,7 +261,7 @@ ntfs_inactive(ap)
#else
#ifdef DIAGNOSTIC
if (VOP_ISLOCKED(vp))
panic("ntfs_inactive: locked ntnode");
panic("ntfs_inactive: locked vnode");
if (curproc)
ip->i_lockholder = curproc->p_pid;
else
@ -275,7 +274,7 @@ ntfs_inactive(ap)
* If we are done with the ntnode, reclaim it
* so that it can be reused immediately.
*/
if (vp->v_usecount == 0 /*&& ip->i_mode == 0*/)
if (vp->v_usecount == 0 && ip->i_mode == 0)
#if __FreeBSD_version >= 300000
vrecycle(vp, (struct simplelock *)0, ap->a_p);
#else
@ -295,12 +294,15 @@ ntfs_reclaim(ap)
{
register struct vnode *vp = ap->a_vp;
register struct fnode *fp = VTOF(vp);
#if NTFS_DEBUG
register struct ntnode *ip = FTONT(fp);
#endif
int error;
dprintf(("ntfs_reclaim: vnode: %p, ntnode: %d\n", vp, ip->i_number));
error = ntfs_ntget(ip);
if (error)
return (error);
#if __FreeBSD_version >= 300000
VOP_UNLOCK(vp,0,ap->a_p);
#endif
@ -316,6 +318,8 @@ ntfs_reclaim(ap)
vp->v_data = NULL;
ntfs_ntput(ip);
return (0);
}
@ -428,15 +432,15 @@ ntfs_write(ap)
dprintf(("ntfs_write: ino: %d, off: %d resid: %d, segflg: %d\n",ip->i_number,(u_int32_t)uio->uio_offset,uio->uio_resid,uio->uio_segflg));
ntfs_filesize(ntmp, fp, &towrite, NULL);
towrite = fp->f_size;
dprintf(("ntfs_write: filesize: %d",(u_int32_t)towrite));
if (uio->uio_resid + uio->uio_offset > towrite) {
printf("ntfs_write: CAN'T WRITE BEYOND OF FILE\n");
return (EFBIG);
}
dprintf(("ntfs_write: filesize: %d",(u_int32_t)towrite));
towrite = min(uio->uio_resid, towrite - uio->uio_offset);
off = uio->uio_offset;
@ -948,7 +952,7 @@ ntfs_lookup(ap)
}
return (error);
} else {
error = ntfs_ntlookup(ntmp, dvp, cnp, ap->a_vpp);
error = ntfs_ntlookupfile(ntmp, dvp, cnp, ap->a_vpp);
if(error)
return (error);
@ -961,6 +965,8 @@ ntfs_lookup(ap)
#else
VOP_UNLOCK(dvp);
#endif
if (cnp->cn_flags & MAKEENTRY)
cache_enter(dvp, *ap->a_vpp, cnp);
}
return (error);