summaryrefslogtreecommitdiffstats
path: root/sys/ntfs
diff options
context:
space:
mode:
authorsemenu <semenu@FreeBSD.org>1999-12-03 20:37:40 +0000
committersemenu <semenu@FreeBSD.org>1999-12-03 20:37:40 +0000
commit39d5a6d9a112c694b6ddfe314cd3fabd50842d57 (patch)
tree9ce5b1cd13e28d4820c42a103ec4056e6905350a /sys/ntfs
parent97f1907fc7b23a0430fdd2761931127aee747ad5 (diff)
downloadFreeBSD-src-39d5a6d9a112c694b6ddfe314cd3fabd50842d57.zip
FreeBSD-src-39d5a6d9a112c694b6ddfe314cd3fabd50842d57.tar.gz
Merged NetBSD version, as they have done improvements:
1. ntfs_read*attr*() functions now accept uio structure to eliminate one data copying. 2. found and removed deadlock caused by 6 concurent ls -lR. 3. started implementation of nromal Unicode<->unix recodeing. Obtained from: NetBSD
Diffstat (limited to 'sys/ntfs')
-rw-r--r--sys/ntfs/ntfs.h49
-rw-r--r--sys/ntfs/ntfs_compr.c7
-rw-r--r--sys/ntfs/ntfs_compr.h2
-rw-r--r--sys/ntfs/ntfs_extern.h33
-rw-r--r--sys/ntfs/ntfs_ihash.c6
-rw-r--r--sys/ntfs/ntfs_ihash.h3
-rw-r--r--sys/ntfs/ntfs_inode.h39
-rw-r--r--sys/ntfs/ntfs_subr.c1048
-rw-r--r--sys/ntfs/ntfs_subr.h40
-rw-r--r--sys/ntfs/ntfs_vfsops.c398
-rw-r--r--sys/ntfs/ntfs_vfsops.h4
-rw-r--r--sys/ntfs/ntfs_vnops.c527
-rw-r--r--sys/ntfs/ntfsmount.h2
13 files changed, 1111 insertions, 1047 deletions
diff --git a/sys/ntfs/ntfs.h b/sys/ntfs/ntfs.h
index 7aa6528..42b17e4 100644
--- a/sys/ntfs/ntfs.h
+++ b/sys/ntfs/ntfs.h
@@ -1,4 +1,4 @@
-/* $NetBSD: ntfs.h,v 1.2 1999/05/06 15:43:17 christos Exp $ */
+/* $NetBSD: ntfs.h,v 1.9 1999/10/31 19:45:26 jdolecek Exp $ */
/*-
* Copyright (c) 1998, 1999 Semen Ustimenko
@@ -29,6 +29,9 @@
*/
/*#define NTFS_DEBUG 1*/
+#if defined(__NetBSD__) && defined(_KERNEL) && !defined(_LKM)
+#include "opt_ntfs.h"
+#endif
typedef u_int64_t cn_t;
typedef u_int16_t wchar;
@@ -239,12 +242,11 @@ struct bootfile {
#define NTFS_SYSNODESNUM 0x0B
struct ntfsmount {
- struct mount *ntm_mountp;
+ struct mount *ntm_mountp; /* filesystem vfs structure */
struct bootfile ntm_bootfile;
- dev_t ntm_dev;
- struct vnode *ntm_devvp;
+ dev_t ntm_dev; /* device mounted */
+ struct vnode *ntm_devvp; /* block device mounted vnode */
struct vnode *ntm_sysvn[NTFS_SYSNODESNUM];
- wchar *ntm_upcase;
u_int32_t ntm_bpmftrec;
uid_t ntm_uid;
gid_t ntm_gid;
@@ -253,6 +255,7 @@ struct ntfsmount {
cn_t ntm_cfree;
struct ntvattrdef *ntm_ad;
int ntm_adnum;
+ struct netexport ntm_export; /* export information */
};
#define ntm_mftcn ntm_bootfile.bf_mftcn
@@ -290,29 +293,33 @@ MALLOC_DECLARE(M_NTFSNTHASH);
#ifdef __NetBSD__
#define MALLOC_DEFINE(a, b, c)
-#define M_NTFSNTHASH M_TEMP
-#define M_NTFSNTVATTR M_TEMP
-#define M_NTFSRDATA M_TEMP
-#define M_NTFSRUN M_TEMP
-#define M_NTFSDECOMP M_TEMP
-#define M_NTFSMNT M_TEMP
-#define M_NTFSNTNODE M_TEMP
-#define M_NTFSFNODE M_TEMP
-#define M_NTFSDIR M_TEMP
+#define M_NTFSNTHASH M_NTFS
+#define M_NTFSNTVATTR M_NTFS
+#define M_NTFSRDATA M_NTFS
+#define M_NTFSRUN M_NTFS
+#define M_NTFSDECOMP M_NTFS
+#define M_NTFSMNT M_NTFS
+#define M_NTFSNTNODE M_NTFS
+#define M_NTFSFNODE M_NTFS
+#define M_NTFSDIR M_NTFS
typedef int (vop_t) __P((void *));
#define HASHINIT(a, b, c, d) hashinit((a), (b), (c), (d))
#define bqrelse(bp) brelse(bp)
-#define VOP__LOCK(a, b, c) VOP_LOCK((a), (b) ? LK_EXCLUSIVE : LK_SHARED)
-#define VOP__UNLOCK(a, b, c) VOP_UNLOCK((a), 0)
-#define VGET(a, b, c) vget((a), LK_EXCLUSIVE)
-#define VN_LOCK(a, b, c) vn_lock((a), LK_EXCLUSIVE)
-#else
+#define VOP__UNLOCK(a, b, c) VOP_UNLOCK((a), (b))
+#define VGET(a, b, c) vget((a), (b))
+#define VN_LOCK(a, b, c) vn_lock((a), (b))
+#define LOCKMGR(a, b, c) lockmgr((a), (b), (c))
+#else /* !NetBSD */
#define HASHINIT(a, b, c, d) hashinit((a), (b), (d))
-#define VOP__LOCK(a, b, c) VOP_LOCK((a), (b), (c))
#define VOP__UNLOCK(a, b, c) VOP_UNLOCK((a), (b), (c))
#define VGET(a, b, c) vget((a), (b), (c))
#define VN_LOCK(a, b, c) vn_lock((a), (b), (c))
-#endif
+#define LOCKMGR(a, b, c) lockmgr((a), (b), (c), NULL)
+
+/* PDIRUNLOCK is used by NetBSD to mark if vfs_lookup() unlocked parent dir;
+ * on FreeBSD, it's not defined and nothing similar exists */
+#define PDIRUNLOCK 0
+#endif /* NetBSD */
#if defined(NTFS_DEBUG)
#define dprintf(a) printf a
diff --git a/sys/ntfs/ntfs_compr.c b/sys/ntfs/ntfs_compr.c
index 412047b..114a6af 100644
--- a/sys/ntfs/ntfs_compr.c
+++ b/sys/ntfs/ntfs_compr.c
@@ -1,4 +1,4 @@
-/* $NetBSD: ntfs_compr.c,v 1.2 1999/05/06 15:43:18 christos Exp $ */
+/* $NetBSD: ntfs_compr.c,v 1.3 1999/07/26 14:02:31 jdolecek Exp $ */
/*-
* Copyright (c) 1998, 1999 Semen Ustimenko
@@ -38,8 +38,9 @@
#include <sys/buf.h>
#include <sys/file.h>
#include <sys/malloc.h>
-#ifdef __FreeBSD__
-#include <machine/clock.h>
+
+#if defined(__NetBSD__)
+#include <miscfs/specfs/specdev.h>
#endif
#include <ntfs/ntfs.h>
diff --git a/sys/ntfs/ntfs_compr.h b/sys/ntfs/ntfs_compr.h
index bdec08c..e51bc09 100644
--- a/sys/ntfs/ntfs_compr.h
+++ b/sys/ntfs/ntfs_compr.h
@@ -1,4 +1,4 @@
-/* $NetBSD: ntfs_compr.h,v 1.2 1999/05/06 15:43:18 christos Exp $ */
+/* $NetBSD: ntfs_compr.h,v 1.3 1999/07/26 14:02:31 jdolecek Exp $ */
/*-
* Copyright (c) 1998, 1999 Semen Ustimenko
diff --git a/sys/ntfs/ntfs_extern.h b/sys/ntfs/ntfs_extern.h
deleted file mode 100644
index 9f71438..0000000
--- a/sys/ntfs/ntfs_extern.h
+++ /dev/null
@@ -1,33 +0,0 @@
-/* $NetBSD: ntfs_extern.h,v 1.2 1999/05/06 15:43:18 christos Exp $ */
-
-/*-
- * 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.
- *
- * $FreeBSD$
- */
-
-struct sockaddr;
-int ntfs_fget(struct ntfsmount *, struct ntnode *, int, char *, struct fnode **);
-void ntfs_frele(struct fnode *);
diff --git a/sys/ntfs/ntfs_ihash.c b/sys/ntfs/ntfs_ihash.c
index 50ee7ac..0deecff 100644
--- a/sys/ntfs/ntfs_ihash.c
+++ b/sys/ntfs/ntfs_ihash.c
@@ -1,4 +1,4 @@
-/* $NetBSD: ntfs_ihash.c,v 1.2 1999/05/06 15:43:19 christos Exp $ */
+/* $NetBSD: ntfs_ihash.c,v 1.5 1999/09/30 16:56:40 jdolecek Exp $ */
/*
* Copyright (c) 1982, 1986, 1989, 1991, 1993, 1995
@@ -43,6 +43,7 @@
#include <sys/vnode.h>
#include <sys/malloc.h>
#include <sys/proc.h>
+#include <sys/mount.h>
#include <ntfs/ntfs.h>
#include <ntfs/ntfs_inode.h>
@@ -59,6 +60,7 @@ static u_long ntfs_nthash; /* size of hash table - 1 */
#ifndef NULL_SIMPLELOCKS
static struct simplelock ntfs_nthash_slock;
#endif
+struct lock ntfs_hashlock;
/*
* Initialize inode hash table.
@@ -66,7 +68,7 @@ static struct simplelock ntfs_nthash_slock;
void
ntfs_nthashinit()
{
-
+ lockinit(&ntfs_hashlock, PINOD, "ntfs_nthashlock", 0, 0);
ntfs_nthashtbl = HASHINIT(desiredvnodes, M_NTFSNTHASH, M_WAITOK,
&ntfs_nthash);
simple_lock_init(&ntfs_nthash_slock);
diff --git a/sys/ntfs/ntfs_ihash.h b/sys/ntfs/ntfs_ihash.h
index 16132a9..7b7143f 100644
--- a/sys/ntfs/ntfs_ihash.h
+++ b/sys/ntfs/ntfs_ihash.h
@@ -1,4 +1,4 @@
-/* $NetBSD: ntfs_ihash.h,v 1.2 1999/05/06 15:43:19 christos Exp $ */
+/* $NetBSD: ntfs_ihash.h,v 1.4 1999/09/30 16:56:40 jdolecek Exp $ */
/*-
* Copyright (c) 1998, 1999 Semen Ustimenko
@@ -28,6 +28,7 @@
* $FreeBSD$
*/
+extern struct lock ntfs_hashlock;
void ntfs_nthashinit __P((void));
struct ntnode *ntfs_nthashlookup __P((dev_t, ino_t));
struct ntnode *ntfs_nthashget __P((dev_t, ino_t));
diff --git a/sys/ntfs/ntfs_inode.h b/sys/ntfs/ntfs_inode.h
index a613385..a86d5f7 100644
--- a/sys/ntfs/ntfs_inode.h
+++ b/sys/ntfs/ntfs_inode.h
@@ -1,4 +1,4 @@
-/* $NetBSD: ntfs_inode.h,v 1.2 1999/05/06 15:43:19 christos Exp $ */
+/* $NetBSD: ntfs_inode.h,v 1.8 1999/10/31 19:45:26 jdolecek Exp $ */
/*-
* Copyright (c) 1998, 1999 Semen Ustimenko
@@ -57,46 +57,41 @@
#define IN_PRELOADED 0x4000 /* loaded from directory entry */
struct ntnode {
+ struct vnode *i_devvp; /* vnode of blk dev we live on */
+ dev_t i_dev; /* Device associated with the inode. */
+
LIST_ENTRY(ntnode) i_hash;
struct ntnode *i_next;
struct ntnode **i_prev;
struct ntfsmount *i_mp;
ino_t i_number;
- dev_t i_dev;
u_int32_t i_flag;
- int i_lock;
+
+ /* locking */
+ struct lock i_lock;
+ struct simplelock i_interlock;
int i_usecount;
-#if defined(__NetBSD__)
- pid_t i_lockholder;
- pid_t i_lockwaiter;
- int i_lockcount;
-#endif
+
LIST_HEAD(,fnode) i_fnlist;
LIST_HEAD(,ntvattr) i_valist;
long i_nlink; /* MFR */
ino_t i_mainrec; /* MFR */
u_int32_t i_frflag; /* MFR */
-
- uid_t i_uid;
- gid_t i_gid;
- mode_t i_mode;
};
#define FN_PRELOADED 0x0001
#define FN_VALID 0x0002
#define FN_AATTRNAME 0x0004 /* space allocated for f_attrname */
struct fnode {
- struct lock f_lock; /* Must be first */
+#ifdef __FreeBSD__
+ struct lock f_lock; /* fnode lock >Keep this first< */
+#endif
LIST_ENTRY(fnode) f_fnlist;
struct vnode *f_vp; /* Associatied vnode */
- struct ntnode *f_ip;
+ struct ntnode *f_ip; /* Associated ntnode */
u_long f_flag;
- struct vnode *f_devvp;
- struct ntfsmount *f_mp;
- dev_t f_dev;
- enum vtype f_type;
ntfs_times_t f_times; /* $NAME/dirinfo */
ino_t f_pnumber; /* $NAME/dirinfo */
@@ -115,3 +110,11 @@ struct fnode {
caddr_t f_dirblbuf;
u_int32_t f_dirblsz;
};
+
+/* This overlays the fid structure (see <sys/mount.h>) */
+struct ntfid {
+ u_int16_t ntfid_len; /* Length of structure. */
+ u_int16_t ntfid_pad; /* Force 32-bit alignment. */
+ ino_t ntfid_ino; /* File number (ino). */
+ int32_t ntfid_gen; /* Generation number. */
+};
diff --git a/sys/ntfs/ntfs_subr.c b/sys/ntfs/ntfs_subr.c
index b3e75b3..7a75972 100644
--- a/sys/ntfs/ntfs_subr.c
+++ b/sys/ntfs/ntfs_subr.c
@@ -1,4 +1,4 @@
-/* $NetBSD: ntfs_subr.c,v 1.2 1999/05/06 15:43:19 christos Exp $ */
+/* $NetBSD: ntfs_subr.c,v 1.23 1999/10/31 19:45:26 jdolecek Exp $ */
/*-
* Copyright (c) 1998, 1999 Semen Ustimenko (semenu@FreeBSD.org)
@@ -39,8 +39,10 @@
#include <sys/buf.h>
#include <sys/file.h>
#include <sys/malloc.h>
-#if defined(__FreeBSD__)
-#include <machine/clock.h>
+#include <sys/lock.h>
+
+#if defined(__NetBSD__)
+#include <miscfs/specfs/specdev.h>
#endif
/* #define NTFS_DEBUG 1 */
@@ -48,7 +50,6 @@
#include <ntfs/ntfsmount.h>
#include <ntfs/ntfs_inode.h>
#include <ntfs/ntfs_vfsops.h>
-#include <ntfs/ntfs_extern.h>
#include <ntfs/ntfs_subr.h>
#include <ntfs/ntfs_compr.h>
#include <ntfs/ntfs_ihash.h>
@@ -60,12 +61,30 @@ MALLOC_DEFINE(M_NTFSRUN, "NTFS vrun", "NTFS vrun storage");
MALLOC_DEFINE(M_NTFSDECOMP, "NTFS decomp", "NTFS decompression temporary");
#endif
+static int ntfs_ntlookupattr __P((struct ntfsmount *, const char *, int, int *, char **));
+static int ntfs_findvattr __P((struct ntfsmount *, struct ntnode *, struct ntvattr **, struct ntvattr **, u_int32_t, const char *, size_t, cn_t));
+static int ntfs_uastricmp __P((const wchar *, size_t, const char *, size_t));
+static int ntfs_uastrcmp __P((const wchar *, size_t, const char *, size_t));
+
+/* table for mapping Unicode chars into uppercase; it's filled upon first
+ * ntfs mount, freed upon last ntfs umount */
+static wchar *ntfs_toupper_tab;
+#define NTFS_U28(ch) ((((ch) & 0xFF) == 0) ? '_' : (ch) & 0xFF)
+#define NTFS_TOUPPER(ch) (ntfs_toupper_tab[(unsigned char)(ch)])
+static struct lock ntfs_toupper_lock;
+static signed int ntfs_toupper_usecount;
+
+/* support macro for ntfs_ntvattrget() */
+#define NTFS_AALPCMP(aalp,type,name,namelen) ( \
+ (aalp->al_type == type) && (aalp->al_namelen == namelen) && \
+ !ntfs_uastrcmp(aalp->al_name,aalp->al_namelen,name,namelen) )
+
/*
*
*/
int
-ntfs_ntvattrrele(
- struct ntvattr * vap)
+ntfs_ntvattrrele(vap)
+ struct ntvattr * vap;
{
dprintf(("ntfs_ntvattrrele: ino: %d, type: 0x%x\n",
vap->va_ip->i_number, vap->va_type));
@@ -76,6 +95,54 @@ ntfs_ntvattrrele(
}
/*
+ * find the attribute in the ntnode
+ */
+static int
+ntfs_findvattr(ntmp, ip, lvapp, vapp, type, name, namelen, vcn)
+ struct ntfsmount *ntmp;
+ struct ntnode *ip;
+ struct ntvattr **lvapp, **vapp;
+ u_int32_t type;
+ const char *name;
+ size_t namelen;
+ cn_t vcn;
+{
+ int error;
+ struct ntvattr *vap;
+
+ if((ip->i_flag & IN_LOADED) == 0) {
+ dprintf(("ntfs_findvattr: node not loaded, ino: %d\n",
+ ip->i_number));
+ error = ntfs_loadntnode(ntmp,ip);
+ if (error) {
+ printf("ntfs_findvattr: FAILED TO LOAD INO: %d\n",
+ ip->i_number);
+ return (error);
+ }
+ }
+
+ *lvapp = NULL;
+ *vapp = NULL;
+ for (vap = ip->i_valist.lh_first; vap; vap = vap->va_list.le_next) {
+ ddprintf(("ntfs_findvattr: type: 0x%x, vcn: %d - %d\n", \
+ vap->va_type, (u_int32_t) vap->va_vcnstart, \
+ (u_int32_t) vap->va_vcnend));
+ if ((vap->va_type == type) &&
+ (vap->va_vcnstart <= vcn) && (vap->va_vcnend >= vcn) &&
+ (vap->va_namelen == namelen) &&
+ (strncmp(name, vap->va_name, namelen) == 0)) {
+ *vapp = vap;
+ ntfs_ntref(vap->va_ip);
+ return (0);
+ }
+ if (vap->va_type == NTFS_A_ATTRLIST)
+ *lvapp = vap;
+ }
+
+ return (-1);
+}
+
+/*
* 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).
@@ -87,17 +154,18 @@ ntfs_ntvattrget(
struct ntfsmount * ntmp,
struct ntnode * ip,
u_int32_t type,
- char *name,
+ const char *name,
cn_t vcn,
struct ntvattr ** vapp)
{
- int error;
- struct ntvattr *vap;
struct ntvattr *lvap = NULL;
struct attr_attrlist *aalp;
struct attr_attrlist *nextaalp;
+ struct vnode *newvp;
+ struct ntnode *newip;
caddr_t alpool;
- int len, namelen;
+ size_t namelen, len;
+ int error;
*vapp = NULL;
@@ -114,32 +182,9 @@ ntfs_ntvattrget(
namelen = 0;
}
- if((ip->i_flag & IN_LOADED) == 0) {
- dprintf(("ntfs_ntvattrget: node not loaded, ino: %d\n",
- ip->i_number));
- error = ntfs_loadntnode(ntmp,ip);
- if(error) {
- printf("ntfs_ntvattrget: FAILED TO LOAD INO: %d\n",
- ip->i_number);
- return (error);
- }
- }
-
- 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));
- if ((vap->va_type == type) &&
- (vap->va_vcnstart <= vcn) && (vap->va_vcnend >= vcn) &&
- (vap->va_namelen == namelen) &&
- (!strncmp(name, vap->va_name, namelen))) {
- *vapp = vap;
- ntfs_ntref(vap->va_ip);
- return (0);
- }
- if (vap->va_type == NTFS_A_ATTRLIST)
- lvap = vap;
- }
+ error = ntfs_findvattr(ntmp, ip, &lvap, vapp, type, name, namelen, vcn);
+ if (error >= 0)
+ return (error);
if (!lvap) {
dprintf(("ntfs_ntvattrget: UNEXISTED ATTRIBUTE: " \
@@ -150,14 +195,15 @@ ntfs_ntvattrget(
/* Scan $ATTRIBUTE_LIST for requested attribute */
len = lvap->va_datalen;
MALLOC(alpool, caddr_t, len, M_TEMP, M_WAITOK);
- error = ntfs_readntvattr_plain(ntmp, ip, lvap, 0, len, alpool, &len);
+ error = ntfs_readntvattr_plain(ntmp, ip, lvap, 0, len, alpool, &len,
+ NULL);
if (error)
goto out;
aalp = (struct attr_attrlist *) alpool;
nextaalp = NULL;
- while (len > 0) {
+ for(; len > 0; aalp = nextaalp) {
dprintf(("ntfs_ntvattrget: " \
"attrlist: ino: %d, attr: 0x%x, vcn: %d\n", \
aalp->al_inumber, aalp->al_type, \
@@ -170,71 +216,39 @@ ntfs_ntvattrget(
}
len -= aalp->reclen;
-#define AALPCMP(aalp,type,name,namelen) ( \
- (aalp->al_type == type) && (aalp->al_namelen == namelen) && \
- !uastrcmp(aalp->al_name,aalp->al_namelen,name,namelen) )
+ if (!NTFS_AALPCMP(aalp, type, name, namelen) ||
+ (nextaalp && (nextaalp->al_vcnstart <= vcn) &&
+ NTFS_AALPCMP(nextaalp, type, name, namelen)))
+ continue;
- if (AALPCMP(aalp, type, name, namelen) &&
- (!nextaalp || (nextaalp->al_vcnstart > vcn) ||
- !AALPCMP(nextaalp, type, name, namelen))) {
- struct vnode *newvp;
- struct ntnode *newip;
-
- dprintf(("ntfs_ntvattrget: attrbute in ino: %d\n",
+ dprintf(("ntfs_ntvattrget: attribute 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));
- error = ntfs_loadntnode(ntmp,ip);
- if(error) {
- printf("ntfs_ntvattrget: CAN'T LOAD " \
- "INO: %d\n", newip->i_number);
- vput(newvp);
- goto out;
- }
- }
- 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) &&
- (vap->va_namelen == namelen) &&
- (!strncmp(name, vap->va_name, namelen))) {
- *vapp = vap;
- ntfs_ntref(vap->va_ip);
- vput(newvp);
- error = 0;
- goto out;
- }
- if (vap->va_type == NTFS_A_ATTRLIST)
- lvap = vap;
- }
- printf("ntfs_ntvattrget: ATTRLIST ERROR.\n");
- vput(newvp);
- break;
+ /* this is not a main record, so we can't use just plain
+ vget() */
+ 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;
}
-#undef AALPCMP
- aalp = nextaalp;
+ newip = VTONT(newvp);
+ /* XXX have to lock ntnode */
+ error = ntfs_findvattr(ntmp, newip, &lvap, vapp,
+ type, name, namelen, vcn);
+ vput(newvp);
+ if (error == 0)
+ goto out;
+ printf("ntfs_ntvattrget: ATTRLIST ERROR.\n");
+ break;
}
error = ENOENT;
dprintf(("ntfs_ntvattrget: UNEXISTED ATTRIBUTE: " \
- "ino: %d, type: 0x%x, name: %s, vcn: %d\n", \
- ip->i_number, type, name, (u_int32_t) vcn));
+ "ino: %d, type: 0x%x, name: %.*s, vcn: %d\n", \
+ ip->i_number, type, (int) namelen, name, (u_int32_t) vcn));
out:
FREE(alpool, M_TEMP);
return (error);
@@ -256,7 +270,7 @@ ntfs_loadntnode(
struct attr *ap;
struct ntvattr *nvap;
- dprintf(("ntfs_loadnode: loading ino: %d\n",ip->i_number));
+ dprintf(("ntfs_loadntnode: loading ino: %d\n",ip->i_number));
MALLOC(mfrp, struct filerec *, ntfs_bntob(ntmp->ntm_bpmftrec),
M_TEMP, M_WAITOK);
@@ -264,7 +278,7 @@ ntfs_loadntnode(
if (ip->i_number < NTFS_SYSNODESNUM) {
struct buf *bp;
- dprintf(("ntfs_loadnode: read system node\n"));
+ dprintf(("ntfs_loadntnode: read system node\n"));
bn = ntfs_cntobn(ntmp->ntm_mftcn) +
ntmp->ntm_bpmftrec * ip->i_number;
@@ -273,7 +287,7 @@ ntfs_loadntnode(
bn, ntfs_bntob(ntmp->ntm_bpmftrec),
NOCRED, &bp);
if (error) {
- printf("ntfs_loadnode: BREAD FAILED\n");
+ printf("ntfs_loadntnode: BREAD FAILED\n");
brelse(bp);
goto out;
}
@@ -285,9 +299,9 @@ ntfs_loadntnode(
vp = ntmp->ntm_sysvn[NTFS_MFTINO];
error = ntfs_readattr(ntmp, VTONT(vp), NTFS_A_DATA, NULL,
ip->i_number * ntfs_bntob(ntmp->ntm_bpmftrec),
- ntfs_bntob(ntmp->ntm_bpmftrec), mfrp);
+ ntfs_bntob(ntmp->ntm_bpmftrec), mfrp, NULL);
if (error) {
- printf("ntfs_loadnode: ntfs_readattr failed\n");
+ printf("ntfs_loadntnode: ntfs_readattr failed\n");
goto out;
}
}
@@ -296,12 +310,12 @@ ntfs_loadntnode(
error = ntfs_procfixups(ntmp, NTFS_FILEMAGIC, (caddr_t)mfrp,
ntfs_bntob(ntmp->ntm_bpmftrec));
if (error) {
- printf("ntfs_loadnode: BAD MFT RECORD %d\n",
+ printf("ntfs_loadntnode: BAD MFT RECORD %d\n",
(u_int32_t) ip->i_number);
goto out;
}
- dprintf(("ntfs_loadnode: load attrs for ino: %d\n",ip->i_number));
+ dprintf(("ntfs_loadntnode: load attrs for ino: %d\n",ip->i_number));
off = mfrp->fr_attroff;
ap = (struct attr *) ((caddr_t)mfrp + off);
@@ -319,7 +333,7 @@ ntfs_loadntnode(
ap = (struct attr *) ((caddr_t)mfrp + off);
}
if (error) {
- printf("ntfs_loadnode: failed to load attr ino: %d\n",
+ printf("ntfs_loadntnode: failed to load attr ino: %d\n",
ip->i_number);
goto out;
}
@@ -337,26 +351,18 @@ out:
/*
* Routine locks ntnode and increase usecount, just opposite of
- * ntfs_ntput.
+ * ntfs_ntput().
*/
int
-ntfs_ntget(
- struct ntnode *ip)
+ntfs_ntget(ip)
+ struct ntnode *ip;
{
dprintf(("ntfs_ntget: get ntnode %d: %p, usecount: %d\n",
ip->i_number, ip, ip->i_usecount));
+ simple_lock(&ip->i_interlock);
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;
+ LOCKMGR(&ip->i_lock, LK_EXCLUSIVE | LK_INTERLOCK, &ip->i_interlock);
return 0;
}
@@ -368,7 +374,6 @@ restart:
*
* ntnode returned locked
*/
-static int ntfs_ntnode_hash_lock;
int
ntfs_ntlookup(
struct ntfsmount * ntmp,
@@ -377,28 +382,17 @@ ntfs_ntlookup(
{
struct ntnode *ip;
- dprintf(("ntfs_ntlookup: for ntnode %d\n", ino));
- *ipp = NULL;
-
-restart:
- ip = ntfs_nthashlookup(ntmp->ntm_dev, ino); /* XXX */
- if (ip) {
- ntfs_ntget(ip);
- *ipp = ip;
- dprintf(("ntfs_ntlookup: ntnode %d: %p, usecount: %d\n",
- ino, ip, ip->i_usecount));
+ dprintf(("ntfs_ntlookup: looking for ntnode %d\n", ino));
- return (0);
- }
-
- if (ntfs_ntnode_hash_lock) {
- while(ntfs_ntnode_hash_lock) {
- ntfs_ntnode_hash_lock = -1;
- tsleep(&ntfs_ntnode_hash_lock, PVM, "ntfsntgt", 0);
+ do {
+ if ((ip = ntfs_nthashlookup(ntmp->ntm_dev, ino)) != NULL) {
+ ntfs_ntget(ip);
+ dprintf(("ntfs_ntlookup: ntnode %d: %p, usecount: %d\n",
+ ino, ip, ip->i_usecount));
+ *ipp = ip;
+ return (0);
}
- goto restart;
- }
- ntfs_ntnode_hash_lock = 1;
+ } while (LOCKMGR(&ntfs_hashlock, LK_EXCLUSIVE | LK_SLEEPFAIL, NULL));
MALLOC(ip, struct ntnode *, sizeof(struct ntnode),
M_NTFSNTNODE, M_WAITOK);
@@ -406,23 +400,21 @@ restart:
bzero((caddr_t) ip, sizeof(struct ntnode));
/* Generic initialization */
+ ip->i_devvp = ntmp->ntm_devvp;
+ ip->i_dev = ntmp->ntm_dev;
ip->i_number = ino;
ip->i_mp = ntmp;
- ip->i_dev = ntmp->ntm_dev;
- ip->i_uid = ntmp->ntm_uid;
- ip->i_gid = ntmp->ntm_gid;
- ip->i_mode = ntmp->ntm_mode;
- ip->i_usecount++;
-
- ip->i_lock = 1;
LIST_INIT(&ip->i_fnlist);
+ /* init lock and lock the newborn ntnode */
+ lockinit(&ip->i_lock, PINOD, "ntnode", 0, LK_EXCLUSIVE);
+ simple_lock_init(&ip->i_interlock);
+ ntfs_ntget(ip);
+
ntfs_nthashins(ip);
- if (ntfs_ntnode_hash_lock < 0)
- wakeup(&ntfs_ntnode_hash_lock);
- ntfs_ntnode_hash_lock = 0;
+ LOCKMGR(&ntfs_hashlock, LK_RELEASE, NULL);
*ipp = ip;
@@ -439,22 +431,25 @@ restart:
* ntnode should be locked on entry, and unlocked on return.
*/
void
-ntfs_ntput(
- struct ntnode *ip)
+ntfs_ntput(ip)
+ struct ntnode *ip;
{
struct ntvattr *vap;
- 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));
+ simple_lock(&ip->i_interlock);
ip->i_usecount--;
+#ifdef DIAGNOSTIC
if (ip->i_usecount < 0) {
panic("ntfs_ntput: ino: %d usecount: %d \n",
ip->i_number,ip->i_usecount);
- } else if (ip->i_usecount == 0) {
+ }
+#endif
+
+ if (ip->i_usecount == 0) {
dprintf(("ntfs_ntput: deallocating ntnode: %d\n",
ip->i_number));
@@ -470,36 +465,51 @@ ntfs_ntput(
}
FREE(ip, M_NTFSNTNODE);
} else {
- if (ip->i_lock < 0)
- wakeup(&ip->i_lock);
- ip->i_lock = 0;
+ LOCKMGR(&ip->i_lock, LK_RELEASE|LK_INTERLOCK, &ip->i_interlock);
}
}
/*
+ * increment usecount of ntnode
+ */
+void
+ntfs_ntref(ip)
+ struct ntnode *ip;
+{
+ simple_lock(&ip->i_interlock);
+ ip->i_usecount++;
+ simple_unlock(&ip->i_interlock);
+
+ dprintf(("ntfs_ntref: ino %d, usecount: %d\n",
+ ip->i_number, ip->i_usecount));
+
+}
+
+/*
* Decrement usecount of ntnode.
*/
void
-ntfs_ntrele(
- struct ntnode * ip)
+ntfs_ntrele(ip)
+ struct ntnode *ip;
{
dprintf(("ntfs_ntrele: rele ntnode %d: %p, usecount: %d\n",
ip->i_number, ip, ip->i_usecount));
+ simple_lock(&ip->i_interlock);
ip->i_usecount--;
if (ip->i_usecount < 0)
panic("ntfs_ntrele: ino: %d usecount: %d \n",
ip->i_number,ip->i_usecount);
+ simple_unlock(&ip->i_interlock);
}
/*
- * Deallocate all memory allocated for ntvattr by call to
- * ntfs_attrtontvattr and some other functions.
+ * Deallocate all memory allocated for ntvattr
*/
void
-ntfs_freentvattr(
- struct ntvattr * vap)
+ntfs_freentvattr(vap)
+ struct ntvattr * vap;
{
if (vap->va_flag & NTFS_AF_INRUN) {
if (vap->va_vruncn)
@@ -647,82 +657,46 @@ ntfs_runtovrun(
}
/*
- * Convert wchar to uppercase wchar, should be macros?
- */
-wchar
-ntfs_toupper(
- struct ntfsmount * ntmp,
- wchar wc)
-{
- return (ntmp->ntm_upcase[wc & 0xFF]);
-}
-
-/*
- * Compare to unicode strings case insensible.
- */
-int
-ntfs_uustricmp(
- struct ntfsmount * ntmp,
- wchar * str1,
- int str1len,
- wchar * str2,
- int str2len)
-{
- int i;
- int res;
-
- for (i = 0; i < str1len && i < str2len; i++) {
- res = (int) ntfs_toupper(ntmp, str1[i]) -
- (int) ntfs_toupper(ntmp, str2[i]);
- if (res)
- return res;
- }
- return (str1len - str2len);
-}
-
-/*
* Compare unicode and ascii string case insens.
*/
-int
-ntfs_uastricmp(
- struct ntfsmount * ntmp,
- const wchar *str1,
- int str1len,
- const char *str2,
- int str2len)
+static int
+ntfs_uastricmp(ustr, ustrlen, astr, astrlen)
+ const wchar *ustr;
+ size_t ustrlen;
+ const char *astr;
+ size_t astrlen;
{
- int i;
+ size_t i;
int res;
- for (i = 0; i < str1len && i < str2len; i++) {
- res = (int) ntfs_toupper(ntmp, str1[i]) -
- (int) ntfs_toupper(ntmp, (wchar) str2[i]);
+ for (i = 0; i < ustrlen && i < astrlen; i++) {
+ res = ((int) NTFS_TOUPPER(NTFS_U28(ustr[i]))) -
+ ((int)NTFS_TOUPPER(astr[i]));
if (res)
return res;
}
- return (str1len - str2len);
+ return (ustrlen - astrlen);
}
/*
* Compare unicode and ascii string case sens.
*/
-int
-ntfs_uastrcmp(
- struct ntfsmount *ntmp,
- const wchar *str1,
- int str1len,
- const char *str2,
- int str2len)
+static int
+ntfs_uastrcmp(ustr, ustrlen, astr, astrlen)
+ const wchar *ustr;
+ size_t ustrlen;
+ const char *astr;
+ size_t astrlen;
{
- int i;
+ size_t i;
int res;
- for (i = 0; (i < str1len) && (i < str2len); i++) {
- res = ((int) str1[i]) - ((int) str2[i]);
+ for (i = 0; (i < ustrlen) && (i < astrlen); i++) {
+ res = (int) (((char)NTFS_U28(ustr[i])) - astr[i]);
if (res)
return res;
}
- return (str1len - str2len);
+ return (ustrlen - astrlen);
}
/*
@@ -763,10 +737,6 @@ ntfs_fget(
bzero(fp, sizeof(struct fnode));
dprintf(("ntfs_fget: allocating fnode: %p\n",fp));
- fp->f_devvp = ntmp->ntm_devvp;
- fp->f_dev = ntmp->ntm_dev;
- fp->f_mp = ntmp;
-
fp->f_ip = ip;
fp->f_attrname = attrname;
if (fp->f_attrname) fp->f_flag |= FN_AATTRNAME;
@@ -809,7 +779,7 @@ ntfs_frele(
* $ATTR_TYPE is searched in attrdefs read from $AttrDefs.
* If $ATTR_TYPE nott specifed, ATTR_A_DATA assumed.
*/
-int
+static int
ntfs_ntlookupattr(
struct ntfsmount * ntmp,
const char * name,
@@ -837,24 +807,19 @@ ntfs_ntlookupattr(
namelen -= syslen;
adp = ntmp->ntm_ad;
- for (i = 0; i < ntmp->ntm_adnum; i++){
- if((syslen == adp->ad_namelen) &&
- (!strncmp(sys,adp->ad_name,syslen))) {
- *attrtype = adp->ad_type;
- if(namelen) {
- MALLOC((*attrname), char *, namelen,
- M_TEMP, M_WAITOK);
- memcpy((*attrname), name, namelen);
- (*attrname)[namelen] = '\0';
- }
- return (0);
- }
- adp++;
+ for (i = 0; i < ntmp->ntm_adnum; i++, adp++){
+ if (syslen != adp->ad_namelen ||
+ strncmp(sys, adp->ad_name, syslen) != 0)
+ continue;
+
+ *attrtype = adp->ad_type;
+ goto out;
}
return (ENOENT);
}
- if(namelen) {
+ out:
+ if (namelen) {
MALLOC((*attrname), char *, namelen, M_TEMP, M_WAITOK);
memcpy((*attrname), name, namelen);
(*attrname)[namelen] = '\0';
@@ -886,6 +851,11 @@ ntfs_ntlookupfile(
int error, res, anamelen, fnamelen;
const char *fname,*aname;
u_int32_t aoff;
+ int attrtype = NTFS_A_DATA;
+ char *attrname = NULL;
+ struct fnode *nfp;
+ struct vnode *nvp;
+ enum vtype f_type;
error = ntfs_ntget(ip);
if (error)
@@ -919,7 +889,7 @@ ntfs_ntlookupfile(
MALLOC(rdbuf, caddr_t, blsize, M_TEMP, M_WAITOK);
error = ntfs_readattr(ntmp, ip, NTFS_A_INDXROOT, "$I30",
- 0, rdsize, rdbuf);
+ 0, rdsize, rdbuf, NULL);
if (error)
goto fail;
@@ -928,105 +898,104 @@ ntfs_ntlookupfile(
do {
iep = (struct attr_indexentry *) (rdbuf + aoff);
- while (!(iep->ie_flag & NTFS_IEFLAG_LAST) && (rdsize > aoff)) {
+ for (; !(iep->ie_flag & NTFS_IEFLAG_LAST) && (rdsize > aoff);
+ aoff += iep->reclen,
+ iep = (struct attr_indexentry *) (rdbuf + aoff))
+ {
ddprintf(("scan: %d, %d\n",
(u_int32_t) iep->ie_number,
(u_int32_t) iep->ie_fnametype));
- res = ntfs_uastricmp(ntmp, iep->ie_fname,
- iep->ie_fnamelen, fname,
- fnamelen);
- if (res == 0) {
- /* Matched something (case ins.) */
- if (iep->ie_fnametype == 0 ||
- !(ntmp->ntm_flag & NTFS_MFLAG_CASEINS))
- res = ntfs_uastrcmp(ntmp,
- iep->ie_fname,
- iep->ie_fnamelen,
- fname,
- fnamelen);
- if (res == 0) {
- int attrtype = NTFS_A_DATA;
- char *attrname = NULL;
- struct fnode *nfp;
- struct vnode *nvp;
-
- if (aname) {
- error = ntfs_ntlookupattr(ntmp,
- aname, anamelen,
- &attrtype, &attrname);
- if (error)
- goto fail;
- }
- /* Check if we've found ourself */
- if ((iep->ie_number == ip->i_number) &&
- (attrtype == fp->f_attrtype) &&
- ((!attrname && !fp->f_attrname) ||
- (attrname && fp->f_attrname &&
- !strcmp(attrname, fp->f_attrname)))) {
- VREF(vp);
- *vpp = vp;
- goto fail;
- }
+ /* check the name - the case-insensitible check
+ * has to come first, to break from this for loop
+ * if needed, so we can dive correctly */
+ res = ntfs_uastricmp(iep->ie_fname, iep->ie_fnamelen,
+ fname, fnamelen);
+ if (res > 0) break;
+ if (res < 0) continue;
+
+ if (iep->ie_fnametype == 0 ||
+ !(ntmp->ntm_flag & NTFS_MFLAG_CASEINS))
+ {
+ res = ntfs_uastrcmp(iep->ie_fname,
+ iep->ie_fnamelen, fname, fnamelen);
+ if (res != 0) continue;
+ }
- /* vget node, but don't load it */
- error = ntfs_vgetex(ntmp->ntm_mountp,
- iep->ie_number,
- attrtype,
- attrname,
- LK_EXCLUSIVE,
- VG_DONTLOADIN |
- VG_DONTVALIDFN,
- curproc,
- &nvp);
- if(error)
- goto fail;
-
- nfp = VTOF(nvp);
-
- if (nfp->f_flag & FN_VALID) {
- *vpp = nvp;
- goto fail;
- }
+ if (aname) {
+ error = ntfs_ntlookupattr(ntmp,
+ aname, anamelen,
+ &attrtype, &attrname);
+ if (error)
+ goto fail;
+ }
- nfp->f_fflag = iep->ie_fflag;
- nfp->f_pnumber = iep->ie_fpnumber;
- nfp->f_times = iep->ie_ftimes;
-
- if((nfp->f_fflag & NTFS_FFLAG_DIR) &&
- (nfp->f_attrtype == NTFS_A_DATA) &&
- (nfp->f_attrname == NULL))
- nfp->f_type = VDIR;
- else
- nfp->f_type = VREG;
-
- nvp->v_type = nfp->f_type;
-
- if ((nfp->f_attrtype == NTFS_A_DATA) &&
- (nfp->f_attrname == NULL)) {
- /* Opening default attribute */
- 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;
- }
- }
+ /* Check if we've found ourself */
+ if ((iep->ie_number == ip->i_number) &&
+ (attrtype == fp->f_attrtype) &&
+ ((!attrname && !fp->f_attrname) ||
+ (attrname && fp->f_attrname &&
+ !strcmp(attrname, fp->f_attrname))))
+ {
+ VREF(vp);
+ *vpp = vp;
+ error = 0;
+ goto fail;
+ }
+
+ /* free the buffer returned by ntfs_ntlookupattr() */
+ if (attrname) {
+ FREE(attrname, M_TEMP);
+ attrname = NULL;
+ }
+
+ /* vget node, but don't load it */
+ error = ntfs_vgetex(ntmp->ntm_mountp,
+ iep->ie_number, attrtype, attrname,
+ LK_EXCLUSIVE, VG_DONTLOADIN | VG_DONTVALIDFN,
+ curproc, &nvp);
+ if (error)
+ goto fail;
+
+ 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;
+
+ if((nfp->f_fflag & NTFS_FFLAG_DIR) &&
+ (nfp->f_attrtype == NTFS_A_DATA) &&
+ (nfp->f_attrname == NULL))
+ f_type = VDIR;
+ else
+ f_type = VREG;
- nfp->f_flag &= ~FN_VALID;
- *vpp = nvp;
+ nvp->v_type = f_type;
+
+ if ((nfp->f_attrtype == NTFS_A_DATA) &&
+ (nfp->f_attrname == NULL))
+ {
+ /* Opening default attribute */
+ 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;
}
- } else if (res > 0)
- break;
+ }
- aoff += iep->reclen;
- iep = (struct attr_indexentry *) (rdbuf + aoff);
+ nfp->f_flag &= ~FN_VALID;
+ *vpp = nvp;
+ goto fail;
}
/* Dive if possible */
@@ -1038,7 +1007,7 @@ ntfs_ntlookupfile(
rdsize = blsize;
error = ntfs_readattr(ntmp, ip, NTFS_A_INDX, "$I30",
- ntfs_cntob(cn), rdsize, rdbuf);
+ ntfs_cntob(cn), rdsize, rdbuf, NULL);
if (error)
goto fail;
@@ -1059,6 +1028,7 @@ ntfs_ntlookupfile(
dprintf(("finish\n"));
fail:
+ if (attrname) FREE(attrname, M_TEMP);
ntfs_ntvattrrele(vap);
ntfs_ntput(ip);
FREE(rdbuf, M_TEMP);
@@ -1073,7 +1043,6 @@ ntfs_isnamepermitted(
struct ntfsmount * ntmp,
struct attr_indexentry * iep)
{
-
if (ntmp->ntm_flag & NTFS_MFLAG_ALLNAMES)
return 1;
@@ -1151,7 +1120,7 @@ ntfs_ntreaddir(
}
MALLOC(bmp, u_char *, bmvap->va_datalen, M_TEMP, M_WAITOK);
error = ntfs_readattr(ntmp, ip, NTFS_A_INDXBITMAP, "$I30", 0,
- bmvap->va_datalen, bmp);
+ bmvap->va_datalen, bmp, NULL);
if (error)
goto fail;
@@ -1188,7 +1157,7 @@ ntfs_ntreaddir(
attrnum, (u_int32_t) blnum, cnum, num, aoff));
rdsize = (attrnum == NTFS_A_INDXROOT) ? vap->va_datalen : blsize;
error = ntfs_readattr(ntmp, ip, attrnum, "$I30",
- ntfs_cntob(blnum * cpbl), rdsize, rdbuf);
+ ntfs_cntob(blnum * cpbl), rdsize, rdbuf, NULL);
if (error)
goto fail;
@@ -1204,23 +1173,24 @@ ntfs_ntreaddir(
sizeof(struct attr_indexroot);
iep = (struct attr_indexentry *) (rdbuf + aoff);
- while (!(iep->ie_flag & NTFS_IEFLAG_LAST) && (rdsize > aoff)) {
- if (ntfs_isnamepermitted(ntmp, iep)) {
- if (cnum >= num) {
- fp->f_lastdnum = cnum;
- fp->f_lastdoff = aoff;
- fp->f_lastdblnum = blnum;
- fp->f_lastdattr = attrnum;
+ for (; !(iep->ie_flag & NTFS_IEFLAG_LAST) && (rdsize > aoff);
+ aoff += iep->reclen,
+ iep = (struct attr_indexentry *) (rdbuf + aoff))
+ {
+ if (!ntfs_isnamepermitted(ntmp, iep)) continue;
- *riepp = iep;
+ if (cnum >= num) {
+ fp->f_lastdnum = cnum;
+ fp->f_lastdoff = aoff;
+ fp->f_lastdblnum = blnum;
+ fp->f_lastdattr = attrnum;
- error = 0;
- goto fail;
- }
- cnum++;
+ *riepp = iep;
+
+ error = 0;
+ goto fail;
}
- aoff += iep->reclen;
- iep = (struct attr_indexentry *) (rdbuf + aoff);
+ cnum++;
}
if (iavap) {
@@ -1349,19 +1319,18 @@ ntfs_filesize(
/*
* This is one of write routine.
- *
- * ntnode should be locked.
*/
int
ntfs_writeattr_plain(
- struct ntfsmount * ntmp,
- struct ntnode * ip,
- u_int32_t attrnum,
- char *attrname,
- off_t roff,
- size_t rsize,
- void *rdata,
- size_t * initp)
+ struct ntfsmount * ntmp,
+ struct ntnode * ip,
+ u_int32_t attrnum,
+ char *attrname,
+ off_t roff,
+ size_t rsize,
+ void *rdata,
+ size_t * initp,
+ struct uio *uio)
{
size_t init;
int error = 0;
@@ -1382,7 +1351,7 @@ ntfs_writeattr_plain(
(u_int32_t) vap->va_vcnend));
error = ntfs_writentvattr_plain(ntmp, ip, vap,
off - ntfs_cntob(vap->va_vcnstart),
- towrite, data, &init);
+ towrite, data, &init, uio);
if (error) {
printf("ntfs_writeattr_plain: " \
"ntfs_writentvattr_plain failed: o: %d, s: %d\n",
@@ -1410,101 +1379,104 @@ ntfs_writeattr_plain(
*/
int
ntfs_writentvattr_plain(
- struct ntfsmount * ntmp,
- struct ntnode * ip,
- struct ntvattr * vap,
- off_t roff,
- size_t rsize,
- void *rdata,
- size_t * initp)
+ struct ntfsmount * ntmp,
+ struct ntnode * ip,
+ struct ntvattr * vap,
+ off_t roff,
+ size_t rsize,
+ void *rdata,
+ size_t * initp,
+ struct uio *uio)
{
int error = 0;
int off;
+ int cnt;
+ cn_t ccn, ccl, cn, left, cl;
+ caddr_t data = rdata;
+ struct buf *bp;
+ size_t tocopy;
*initp = 0;
- if (vap->va_flag & NTFS_AF_INRUN) {
- int cnt;
- cn_t ccn, ccl, cn, left, cl;
- caddr_t data = rdata;
- struct buf *bp;
- size_t tocopy;
- ddprintf(("ntfs_writentvattr_plain: data in run: %d chains\n",
- vap->va_vruncnt));
+ if ((vap->va_flag & NTFS_AF_INRUN) == 0) {
+ printf("ntfs_writevattr_plain: CAN'T WRITE RES. ATTRIBUTE\n");
+ return ENOTTY;
+ }
- off = roff;
- left = rsize;
- ccl = 0;
- ccn = 0;
- cnt = 0;
- while (left && (cnt < vap->va_vruncnt)) {
- ccn = vap->va_vruncn[cnt];
- ccl = vap->va_vruncl[cnt];
+ ddprintf(("ntfs_writentvattr_plain: data in run: %d chains\n",
+ vap->va_vruncnt));
- ddprintf(("ntfs_writentvattr_plain: " \
- "left %d, cn: 0x%x, cl: %d, off: %d\n", \
- (u_int32_t) left, (u_int32_t) ccn, \
- (u_int32_t) ccl, (u_int32_t) off));
+ off = roff;
+ left = rsize;
+ ccl = 0;
+ ccn = 0;
+ cnt = 0;
+ for (; left && (cnt < vap->va_vruncnt); cnt++) {
+ ccn = vap->va_vruncn[cnt];
+ ccl = vap->va_vruncl[cnt];
- if (ntfs_cntob(ccl) < off) {
- off -= ntfs_cntob(ccl);
- cnt++;
- continue;
- }
- if (ccn || ip->i_number == NTFS_BOOTINO) { /* XXX */
- ccl -= ntfs_btocn(off);
- cn = ccn + ntfs_btocn(off);
- off = ntfs_btocnoff(off);
+ ddprintf(("ntfs_writentvattr_plain: " \
+ "left %d, cn: 0x%x, cl: %d, off: %d\n", \
+ (u_int32_t) left, (u_int32_t) ccn, \
+ (u_int32_t) ccl, (u_int32_t) off));
- while (left && ccl) {
- tocopy = min(left,
- min(ntfs_cntob(ccl) - off,
- MAXBSIZE - off));
- cl = ntfs_btocl(tocopy + off);
- ddprintf(("ntfs_writentvattr_plain: " \
- "write: cn: 0x%x cl: %d, " \
- "off: %d len: %d, left: %d\n",
- (u_int32_t) cn,
- (u_int32_t) cl,
- (u_int32_t) off,
- (u_int32_t) tocopy,
- (u_int32_t) left));
- if ((off == 0) &&
- (tocopy == ntfs_cntob(cl))) {
- bp = getblk(ntmp->ntm_devvp,
- ntfs_cntobn(cn),
- ntfs_cntob(cl),
- 0, 0);
- clrbuf(bp);
- } else {
- error = bread(ntmp->ntm_devvp,
- ntfs_cntobn(cn),
- ntfs_cntob(cl),
- NOCRED, &bp);
- if (error) {
- brelse(bp);
- return (error);
- }
- }
- memcpy(bp->b_data + off, data, tocopy);
- bawrite(bp);
- data = data + tocopy;
- *initp += tocopy;
- off = 0;
- left -= tocopy;
- cn += cl;
- ccl -= cl;
- }
- }
+ if (ntfs_cntob(ccl) < off) {
+ off -= ntfs_cntob(ccl);
cnt++;
+ continue;
}
- if (left) {
- printf("ntfs_writentvattr_plain: POSSIBLE RUN ERROR\n");
- error = EINVAL;
+ if (!ccn && ip->i_number != NTFS_BOOTINO)
+ continue; /* XXX */
+
+ ccl -= ntfs_btocn(off);
+ cn = ccn + ntfs_btocn(off);
+ off = ntfs_btocnoff(off);
+
+ while (left && ccl) {
+#if defined(__FreeBSD__)
+ tocopy = min(left,
+ min(ntfs_cntob(ccl) - off, MAXBSIZE - off));
+#else
+ /* under NetBSD, bread() can read
+ * maximum one block worth of data */
+ tocopy = min(left, ntmp->ntm_bps - off);
+#endif
+ cl = ntfs_btocl(tocopy + off);
+ ddprintf(("ntfs_writentvattr_plain: write: " \
+ "cn: 0x%x cl: %d, off: %d len: %d, left: %d\n",
+ (u_int32_t) cn, (u_int32_t) cl,
+ (u_int32_t) off, (u_int32_t) tocopy,
+ (u_int32_t) left));
+ if ((off == 0) && (tocopy == ntfs_cntob(cl)))
+ {
+ bp = getblk(ntmp->ntm_devvp, ntfs_cntobn(cn),
+ ntfs_cntob(cl), 0, 0);
+ clrbuf(bp);
+ } else {
+ error = bread(ntmp->ntm_devvp, ntfs_cntobn(cn),
+ ntfs_cntob(cl), NOCRED, &bp);
+ if (error) {
+ brelse(bp);
+ return (error);
+ }
+ }
+ if (uio)
+ uiomove(bp->b_data + off, tocopy, uio);
+ else
+ memcpy(bp->b_data + off, data, tocopy);
+ bawrite(bp);
+ data = data + tocopy;
+ *initp += tocopy;
+ off = 0;
+ left -= tocopy;
+ cn += cl;
+ ccl -= cl;
}
- } else {
- printf("ntfs_writevattr_plain: CAN'T WRITE RES. ATTRIBUTE\n");
- error = ENOTTY;
+ }
+
+ if (left) {
+ printf("ntfs_writentvattr_plain: POSSIBLE RUN ERROR\n");
+ error = EINVAL;
}
return (error);
@@ -1517,13 +1489,14 @@ ntfs_writentvattr_plain(
*/
int
ntfs_readntvattr_plain(
- struct ntfsmount * ntmp,
- struct ntnode * ip,
- struct ntvattr * vap,
- off_t roff,
- size_t rsize,
- void *rdata,
- size_t * initp)
+ struct ntfsmount * ntmp,
+ struct ntnode * ip,
+ struct ntvattr * vap,
+ off_t roff,
+ size_t rsize,
+ void *rdata,
+ size_t * initp,
+ struct uio *uio)
{
int error = 0;
int off;
@@ -1564,9 +1537,16 @@ ntfs_readntvattr_plain(
off = ntfs_btocnoff(off);
while (left && ccl) {
+#if defined(__FreeBSD__)
tocopy = min(left,
min(ntfs_cntob(ccl) - off,
MAXBSIZE - off));
+#else
+ /* under NetBSD, bread() can read
+ * maximum one block worth of data */
+ tocopy = min(left,
+ ntmp->ntm_bps - off);
+#endif
cl = ntfs_btocl(tocopy + off);
ddprintf(("ntfs_readntvattr_plain: " \
"read: cn: 0x%x cl: %d, " \
@@ -1584,7 +1564,13 @@ ntfs_readntvattr_plain(
brelse(bp);
return (error);
}
- memcpy(data, bp->b_data + off, tocopy);
+ if (uio) {
+ uiomove(bp->b_data + off,
+ tocopy, uio);
+ } else {
+ memcpy(data, bp->b_data + off,
+ tocopy);
+ }
brelse(bp);
data = data + tocopy;
*initp += tocopy;
@@ -1596,14 +1582,19 @@ ntfs_readntvattr_plain(
} else {
tocopy = min(left, ntfs_cntob(ccl) - off);
ddprintf(("ntfs_readntvattr_plain: "
- "sparce: ccn: 0x%x ccl: %d, off: %d, " \
+ "hole: ccn: 0x%x ccl: %d, off: %d, " \
" len: %d, left: %d\n",
(u_int32_t) ccn, (u_int32_t) ccl,
(u_int32_t) off, (u_int32_t) tocopy,
(u_int32_t) left));
left -= tocopy;
off = 0;
- bzero(data, tocopy);
+ if (uio) {
+ size_t remains = tocopy;
+ for(; remains; remains++)
+ uiomove("", 1, uio);
+ } else
+ bzero(data, tocopy);
data = data + tocopy;
}
cnt++;
@@ -1614,7 +1605,10 @@ ntfs_readntvattr_plain(
}
} else {
ddprintf(("ntfs_readnvattr_plain: data is in mft record\n"));
- memcpy(rdata, vap->va_datap + roff, rsize);
+ if (uio)
+ uiomove(vap->va_datap + roff, rsize, uio);
+ else
+ memcpy(rdata, vap->va_datap + roff, rsize);
*initp += rsize;
}
@@ -1623,19 +1617,18 @@ ntfs_readntvattr_plain(
/*
* This is one of read routines.
- *
- * ntnode should be locked.
*/
int
ntfs_readattr_plain(
- struct ntfsmount * ntmp,
- struct ntnode * ip,
- u_int32_t attrnum,
- char *attrname,
- off_t roff,
- size_t rsize,
- void *rdata,
- size_t * initp)
+ struct ntfsmount * ntmp,
+ struct ntnode * ip,
+ u_int32_t attrnum,
+ char *attrname,
+ off_t roff,
+ size_t rsize,
+ void *rdata,
+ size_t * initp,
+ struct uio *uio)
{
size_t init;
int error = 0;
@@ -1656,7 +1649,7 @@ ntfs_readattr_plain(
(u_int32_t) vap->va_vcnend));
error = ntfs_readntvattr_plain(ntmp, ip, vap,
off - ntfs_cntob(vap->va_vcnstart),
- toread, data, &init);
+ toread, data, &init, uio);
if (error) {
printf("ntfs_readattr_plain: " \
"ntfs_readntvattr_plain failed: o: %d, s: %d\n",
@@ -1679,18 +1672,17 @@ ntfs_readattr_plain(
/*
* This is one of read routines.
- *
- * ntnode should be locked.
*/
int
ntfs_readattr(
- struct ntfsmount * ntmp,
- struct ntnode * ip,
- u_int32_t attrnum,
- char *attrname,
- off_t roff,
- size_t rsize,
- void *rdata)
+ struct ntfsmount * ntmp,
+ struct ntnode * ip,
+ u_int32_t attrnum,
+ char *attrname,
+ off_t roff,
+ size_t rsize,
+ void *rdata,
+ struct uio *uio)
{
int error = 0;
struct ntvattr *vap;
@@ -1731,21 +1723,33 @@ ntfs_readattr(
error = ntfs_readattr_plain(ntmp, ip, attrnum,
attrname, ntfs_cntob(cn),
ntfs_cntob(NTFS_COMPUNIT_CL),
- cup, &init);
+ cup, &init, NULL);
if (error)
break;
tocopy = min(left, ntfs_cntob(NTFS_COMPUNIT_CL) - off);
if (init == ntfs_cntob(NTFS_COMPUNIT_CL)) {
- memcpy(data, cup + off, tocopy);
+ if (uio)
+ uiomove(cup + off, tocopy, uio);
+ else
+ memcpy(data, cup + off, tocopy);
} else if (init == 0) {
- bzero(data, tocopy);
+ if (uio) {
+ size_t remains = tocopy;
+ for(; remains; remains--)
+ uiomove("", 1, uio);
+ }
+ else
+ bzero(data, tocopy);
} else {
error = ntfs_uncompunit(ntmp, uup, cup);
if (error)
break;
- memcpy(data, uup + off, tocopy);
+ if (uio)
+ uiomove(uup + off, tocopy, uio);
+ else
+ memcpy(data, uup + off, tocopy);
}
left -= tocopy;
@@ -1758,7 +1762,7 @@ ntfs_readattr(
FREE(cup, M_NTFSDECOMP);
} else
error = ntfs_readattr_plain(ntmp, ip, attrnum, attrname,
- roff, rsize, rdata, &init);
+ roff, rsize, rdata, &init, uio);
ntfs_ntvattrrele(vap);
return (error);
}
@@ -1831,8 +1835,8 @@ ntfs_procfixups(
}
if ((fhp->fh_fnum - 1) * ntmp->ntm_bps != len) {
printf("ntfs_procfixups: " \
- "bad fixups number: %d for %d bytes block\n",
- fhp->fh_fnum, len);
+ "bad fixups number: %d for %ld bytes block\n",
+ fhp->fh_fnum, (long)len); /* XXX printf kludge */
return (EINVAL);
}
if (fhp->fh_foff >= ntmp->ntm_spc * ntmp->ntm_mftrecsz * ntmp->ntm_bps) {
@@ -1897,3 +1901,95 @@ ntfs_runtocn(
return (0);
}
#endif
+
+/*
+ * this initializes toupper table & dependant variables to be ready for
+ * later work
+ */
+void
+ntfs_toupper_init()
+{
+ ntfs_toupper_tab = (wchar *) NULL;
+ lockinit(&ntfs_toupper_lock, PVFS, "ntfs_toupper", 0, 0);
+ ntfs_toupper_usecount = 0;
+}
+
+/*
+ * if the ntfs_toupper_tab[] is filled already, just raise use count;
+ * otherwise read the data from the filesystem we are currently mounting
+ */
+int
+ntfs_toupper_use(mp, ntmp)
+ struct mount *mp;
+ struct ntfsmount *ntmp;
+{
+ int error = 0;
+ struct vnode *vp;
+
+ /* get exclusive access */
+ LOCKMGR(&ntfs_toupper_lock, LK_EXCLUSIVE, NULL);
+
+ /* only read the translation data from a file if it hasn't been
+ * read already */
+ if (ntfs_toupper_tab)
+ goto out;
+
+ /*
+ * Read in Unicode lowercase -> uppercase translation file.
+ * XXX for now, just the first 256 entries are used anyway,
+ * so don't bother reading more
+ */
+ MALLOC(ntfs_toupper_tab, wchar *, 256 * sizeof(wchar),
+ M_NTFSRDATA, M_WAITOK);
+
+ if ((error = VFS_VGET(mp, NTFS_UPCASEINO, &vp)))
+ goto out;
+ error = ntfs_readattr(ntmp, VTONT(vp), NTFS_A_DATA, NULL,
+ 0, 256*sizeof(wchar), (char *) ntfs_toupper_tab, NULL);
+ vput(vp);
+
+ out:
+ ntfs_toupper_usecount++;
+ LOCKMGR(&ntfs_toupper_lock, LK_RELEASE, NULL);
+ return (error);
+}
+
+/*
+ * lower the use count and if it reaches zero, free the memory
+ * tied by toupper table
+ */
+void
+ntfs_toupper_unuse()
+{
+ /* get exclusive access */
+ LOCKMGR(&ntfs_toupper_lock, LK_EXCLUSIVE, NULL);
+
+ ntfs_toupper_usecount--;
+ if (ntfs_toupper_usecount == 0) {
+ FREE(ntfs_toupper_tab, M_NTFSRDATA);
+ ntfs_toupper_tab = NULL;
+ }
+#ifdef DIAGNOSTIC
+ else if (ntfs_toupper_usecount < 0) {
+ panic("ntfs_toupper_unuse(): use count negative: %d\n",
+ ntfs_toupper_usecount);
+ }
+#endif
+
+ /* release the lock */
+ LOCKMGR(&ntfs_toupper_lock, LK_RELEASE, NULL);
+}
+
+/*
+ * maps the Unicode char to 8bit equivalent
+ * XXX currently only gets lower 8bit from the Unicode char
+ * and substitutes a '_' for it if the result would be '\0';
+ * something better has to be definitely though out
+ */
+char
+ntfs_u28(unichar)
+ wchar unichar;
+{
+ return (char) NTFS_U28(unichar);
+}
+
diff --git a/sys/ntfs/ntfs_subr.h b/sys/ntfs/ntfs_subr.h
index f0b9a8a..7f2d793 100644
--- a/sys/ntfs/ntfs_subr.h
+++ b/sys/ntfs/ntfs_subr.h
@@ -1,4 +1,4 @@
-/* $NetBSD: ntfs_subr.h,v 1.2 1999/05/06 15:43:20 christos Exp $ */
+/* $NetBSD: ntfs_subr.h,v 1.8 1999/10/10 14:48:37 jdolecek Exp $ */
/*-
* Copyright (c) 1998, 1999 Semen Ustimenko
@@ -70,34 +70,17 @@ struct ntvattr {
#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)
-
-#ifndef NTFS_DEBUG
-#define ntfs_ntref(i) (i)->i_usecount++
-#else
-#define ntfs_ntref(i) { \
- printf("ntfs_ntref: ino %d, usecount: %d\n", \
- (i)->i_number, (i)->i_usecount++); \
-}
-#endif
-
int ntfs_procfixups __P(( struct ntfsmount *, u_int32_t, caddr_t, size_t ));
int ntfs_parserun __P(( cn_t *, cn_t *, u_int8_t *, u_long, u_long *));
int ntfs_runtocn __P(( cn_t *, struct ntfsmount *, u_int8_t *, u_long, cn_t));
-int ntfs_readntvattr_plain __P(( struct ntfsmount *, struct ntnode *, struct ntvattr *, off_t, size_t, void *,size_t *));
-int ntfs_readattr_plain __P(( struct ntfsmount *, struct ntnode *, u_int32_t, char *, off_t, size_t, void *,size_t *));
-int ntfs_readattr __P(( struct ntfsmount *, struct ntnode *, u_int32_t, char *, off_t, size_t, void *));
+int ntfs_readntvattr_plain __P(( struct ntfsmount *, struct ntnode *, struct ntvattr *, off_t, size_t, void *,size_t *, struct uio *));
+int ntfs_readattr_plain __P(( struct ntfsmount *, struct ntnode *, u_int32_t, char *, off_t, size_t, void *,size_t *, struct uio *));
+int ntfs_readattr __P(( struct ntfsmount *, struct ntnode *, u_int32_t, char *, off_t, size_t, void *, struct uio *));
int ntfs_filesize __P(( struct ntfsmount *, struct fnode *, 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 fnode *, 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 *, const wchar *, int, const char *,
- int ));
-int ntfs_uastrcmp __P(( struct ntfsmount *, const wchar *, int, const char *,
- int ));
+char ntfs_u28 __P((wchar));
int ntfs_runtovrun __P(( cn_t **, cn_t **, u_long *, u_int8_t *));
int ntfs_attrtontvattr __P(( struct ntfsmount *, struct ntvattr **, struct attr * ));
void ntfs_freentvattr __P(( struct ntvattr * ));
@@ -106,12 +89,17 @@ struct ntvattr * ntfs_findntvattr __P(( struct ntfsmount *, struct ntnode *, u_i
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_ntvattrget __P((struct ntfsmount *, struct ntnode *, u_int32_t, const char *, cn_t , struct ntvattr **));
int ntfs_ntlookup __P((struct ntfsmount *, ino_t, struct ntnode **));
int ntfs_ntget __P((struct ntnode *));
+void ntfs_ntref __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 *, const char *, int, int *, char **);
-int ntfs_writentvattr_plain(struct ntfsmount *, struct ntnode *, struct ntvattr *, off_t, size_t, void *, size_t *);
-int ntfs_writeattr_plain(struct ntfsmount *, struct ntnode *, u_int32_t, char *, off_t, size_t, void *, size_t *);
+int ntfs_writentvattr_plain __P((struct ntfsmount *, struct ntnode *, struct ntvattr *, off_t, size_t, void *, size_t *, struct uio *));
+int ntfs_writeattr_plain __P((struct ntfsmount *, struct ntnode *, u_int32_t, char *, off_t, size_t, void *, size_t *, struct uio *));
+void ntfs_toupper_init __P((void));
+int ntfs_toupper_use __P((struct mount *, struct ntfsmount *));
+void ntfs_toupper_unuse __P((void));
+int ntfs_fget __P((struct ntfsmount *, struct ntnode *, int, char *, struct fnode **));
+void ntfs_frele __P((struct fnode *));
diff --git a/sys/ntfs/ntfs_vfsops.c b/sys/ntfs/ntfs_vfsops.c
index ffd2412..9ad0775 100644
--- a/sys/ntfs/ntfs_vfsops.c
+++ b/sys/ntfs/ntfs_vfsops.c
@@ -1,4 +1,4 @@
-/* $NetBSD: ntfs_vfsops.c,v 1.2 1999/05/06 15:43:20 christos Exp $ */
+/* $NetBSD: ntfs_vfsops.c,v 1.23 1999/11/15 19:38:14 jdolecek Exp $ */
/*-
* Copyright (c) 1998, 1999 Semen Ustimenko
@@ -40,20 +40,30 @@
#include <sys/buf.h>
#include <sys/fcntl.h>
#include <sys/malloc.h>
+#include <sys/systm.h>
+#if defined(__NetBSD__)
+#include <sys/device.h>
+#endif
#include <vm/vm.h>
#include <vm/vm_param.h>
+#if defined(__NetBSD__)
+#include <vm/vm_prot.h>
+#endif
#include <vm/vm_page.h>
#include <vm/vm_object.h>
#include <vm/vm_extern.h>
+#if defined(__NetBSD__)
+#include <miscfs/specfs/specdev.h>
+#endif
+
/*#define NTFS_DEBUG 1*/
#include <ntfs/ntfs.h>
#include <ntfs/ntfs_inode.h>
#include <ntfs/ntfs_subr.h>
#include <ntfs/ntfs_vfsops.h>
#include <ntfs/ntfs_ihash.h>
-#include <ntfs/ntfs_extern.h>
#include <ntfs/ntfsmount.h>
#if defined(__FreeBSD__)
@@ -63,13 +73,6 @@ MALLOC_DEFINE(M_NTFSFNODE,"NTFS fnode", "NTFS fnode information");
MALLOC_DEFINE(M_NTFSDIR,"NTFS dir", "NTFS dir buffer");
#endif
-#if defined(__FreeBSD__)
-static int ntfs_mount __P((struct mount *, char *, caddr_t,
- struct nameidata *, struct proc *));
-#else
-static int ntfs_mount __P((struct mount *, const char *, void *,
- struct nameidata *, struct proc *));
-#endif
static int ntfs_root __P((struct mount *, struct vnode **));
static int ntfs_statfs __P((struct mount *, struct statfs *,
struct proc *));
@@ -78,53 +81,70 @@ 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 *));
+static int ntfs_fhtovp __P((struct mount *, struct fid *,
+ struct vnode **));
-#if !defined(__FreeBSD__)
+#if !defined (__FreeBSD__)
static int ntfs_quotactl __P((struct mount *, int, uid_t, caddr_t,
struct proc *));
static int ntfs_start __P((struct mount *, int, struct proc *));
static int ntfs_sync __P((struct mount *, int, struct ucred *,
struct proc *));
-static int ntfs_vptofh __P((struct vnode *, struct fid *));
-#endif /* !defined(__FreeBSD__) */
+#endif
#if defined(__FreeBSD__)
+struct sockaddr;
+static int ntfs_mount __P((struct mount *, char *, caddr_t,
+ struct nameidata *, struct proc *));
static int ntfs_init __P((struct vfsconf *));
-#if 0 /* may be implemented at a later date */
-static int ntfs_fhtovp __P((struct mount *, struct fid *,
- struct vnode **));
-static int ntfs_checkexp __P((struct vnode *, struct mbuf *,
+static int ntfs_checkexp __P((struct mount *, struct sockaddr *,
int *, struct ucred **));
-#endif /* 0, default ops in FreeBSD */
#elif defined(__NetBSD__)
+static int ntfs_mount __P((struct mount *, const char *, void *,
+ struct nameidata *, struct proc *));
static void ntfs_init __P((void));
-static int ntfs_fhtovp __P((struct mount *, struct fid *,
- struct vnode **));
-static int ntfs_checkexp __P((struct mount *, struct mbuf *,
- int *, struct ucred **));
static int ntfs_mountroot __P((void));
static int ntfs_sysctl __P((int *, u_int, void *, size_t *, void *,
size_t, struct proc *));
-#else
-static int ntfs_init __P((void));
-static int ntfs_fhtovp __P((struct mount *, struct fid *,
- struct mbuf *, struct vnode **,
- int *, struct ucred **));
+static int ntfs_checkexp __P((struct mount *, struct mbuf *,
+ int *, struct ucred **));
#endif
-#ifdef __NetBSD__
-/*ARGSUSED*/
+/*
+ * Verify a remote client has export rights and return these rights via.
+ * exflagsp and credanonp.
+ */
static int
ntfs_checkexp(mp, nam, exflagsp, credanonp)
+#if defined(__FreeBSD__)
+ register struct mount *mp;
+ struct sockaddr *nam;
+ int *exflagsp;
+ struct ucred **credanonp;
+#else /* defined(__NetBSD__) */
register struct mount *mp;
struct mbuf *nam;
int *exflagsp;
struct ucred **credanonp;
+#endif
{
+ register struct netcred *np;
+ register struct ntfsmount *ntm = VFSTONTFS(mp);
- return (EINVAL);
+ /*
+ * Get the export permission structure for this <mp, client> tuple.
+ */
+ np = vfs_export_lookup(mp, &ntm->ntm_export, nam);
+ if (np == NULL)
+ return (EACCES);
+
+ *exflagsp = np->netc_exflags;
+ *credanonp = &np->netc_anon;
+ return (0);
}
+#if defined(__NetBSD__)
/*ARGSUSED*/
static int
ntfs_sysctl(name, namelen, oldp, oldlenp, newp, newlen, p)
@@ -142,28 +162,67 @@ ntfs_sysctl(name, namelen, oldp, oldlenp, newp, newlen, p)
static int
ntfs_mountroot()
{
- return (EINVAL);
+ struct mount *mp;
+ extern struct vnode *rootvp;
+ struct proc *p = curproc; /* XXX */
+ int error;
+ struct ntfs_args args;
+
+ if (root_device->dv_class != DV_DISK)
+ return (ENODEV);
+
+ /*
+ * Get vnodes for rootdev.
+ */
+ if (bdevvp(rootdev, &rootvp))
+ panic("ntfs_mountroot: can't setup rootvp");
+
+ if ((error = vfs_rootmountalloc(MOUNT_NTFS, "root_device", &mp))) {
+ vrele(rootvp);
+ return (error);
+ }
+
+ args.flag = 0;
+ args.uid = 0;
+ args.gid = 0;
+ args.mode = 0777;
+
+ if ((error = ntfs_mountfs(rootvp, mp, &args, p)) != 0) {
+ mp->mnt_op->vfs_refcount--;
+ vfs_unbusy(mp);
+ free(mp, M_MOUNT);
+ vrele(rootvp);
+ return (error);
+ }
+
+ simple_lock(&mountlist_slock);
+ CIRCLEQ_INSERT_TAIL(&mountlist, mp, mnt_list);
+ simple_unlock(&mountlist_slock);
+ (void)ntfs_statfs(mp, &mp->mnt_stat, p);
+ vfs_unbusy(mp);
+ return (0);
}
-#endif
-#if defined(__FreeBSD__)
-static int
-ntfs_init (
- struct vfsconf *vcp )
-#elif defined(__NetBSD__)
static void
ntfs_init ()
-#else
+{
+ ntfs_nthashinit();
+ ntfs_toupper_init();
+}
+
+#elif defined(__FreeBSD__)
+
static int
-ntfs_init ()
-#endif
+ntfs_init (
+ struct vfsconf *vcp )
{
ntfs_nthashinit();
-#if !defined(__NetBSD__)
+ ntfs_toupper_init();
return 0;
-#endif
}
+#endif /* NetBSD */
+
static int
ntfs_mount (
struct mount *mp,
@@ -177,11 +236,12 @@ ntfs_mount (
struct nameidata *ndp,
struct proc *p )
{
- u_int size;
+ size_t size;
int err = 0;
struct vnode *devvp;
struct ntfs_args args;
+#ifdef __FreeBSD__
/*
* Use NULL path to flag a root mount
*/
@@ -212,6 +272,7 @@ ntfs_mount (
goto dostatfs; /* success*/
}
+#endif /* FreeBSD */
/*
***
@@ -229,57 +290,20 @@ ntfs_mount (
* 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);
+ struct ntfsmount *ntm = VFSTONTFS(mp);
+ err = vfs_export(mp, &ntm->ntm_export, &args.export);
goto success;
}
-#endif
+
+ printf("ntfs_mount(): MNT_UPDATE not supported\n");
+ err = EINVAL;
+ goto error_1;
}
/*
@@ -295,10 +319,21 @@ ntfs_mount (
devvp = ndp->ni_vp;
+#if defined(__FreeBSD__)
if (!vn_isdisk(devvp)) {
err = ENOTBLK;
goto error_2;
}
+#else
+ if (devvp->v_type != VBLK) {
+ err = ENOTBLK;
+ goto error_2;
+ }
+ if (major(devvp->v_rdev) >= nblkdev) {
+ err = ENXIO;
+ goto error_2;
+ }
+#endif
if (mp->mnt_flag & MNT_UPDATE) {
#if 0
/*
@@ -356,7 +391,9 @@ ntfs_mount (
goto error_2;
}
+#ifdef __FreeBSD__
dostatfs:
+#endif
/*
* Initialize FS stat information in mount struct; uses both
* mp->mnt_stat.f_mntonname and mp->mnt_stat.f_mntfromname
@@ -376,7 +413,7 @@ error_2: /* error with devvp held*/
error_1: /* no state to back out*/
success:
- return( err);
+ return(err);
}
/*
@@ -412,9 +449,9 @@ ntfs_mountfs(devvp, mp, argsp, p)
if (ncount > 1 && devvp != rootvp)
return (EBUSY);
#if defined(__FreeBSD__)
- vn_lock(devvp, LK_EXCLUSIVE | LK_RETRY, p);
+ VN_LOCK(devvp, LK_EXCLUSIVE | LK_RETRY, p);
error = vinvalbuf(devvp, V_SAVE, p->p_ucred, p, 0, 0);
- VOP_UNLOCK(devvp, 0, p);
+ VOP__UNLOCK(devvp, 0, p);
#else
error = vinvalbuf(devvp, V_SAVE, p->p_ucred, p, 0, 0);
#endif
@@ -422,9 +459,9 @@ ntfs_mountfs(devvp, mp, argsp, p)
return (error);
ronly = (mp->mnt_flag & MNT_RDONLY) != 0;
- vn_lock(devvp, LK_EXCLUSIVE | LK_RETRY, p);
+ VN_LOCK(devvp, LK_EXCLUSIVE | LK_RETRY, p);
error = VOP_OPEN(devvp, ronly ? FREAD : FREAD|FWRITE, FSCRED, p);
- VOP_UNLOCK(devvp, 0, p);
+ VOP__UNLOCK(devvp, 0, p);
if (error)
return (error);
@@ -441,7 +478,7 @@ ntfs_mountfs(devvp, mp, argsp, p)
if (strncmp(ntmp->ntm_bootfile.bf_sysid, NTFS_BBID, NTFS_BBIDLEN)) {
error = EINVAL;
- printf("ntfs_mountfs: invalid boot block\n");
+ dprintf(("ntfs_mountfs: invalid boot block\n"));
goto out;
}
@@ -488,20 +525,9 @@ ntfs_mountfs(devvp, mp, argsp, p)
}
}
- /*
- * Read in WHOLE lowcase -> upcase translation
- * file.
- */
- MALLOC(ntmp->ntm_upcase, wchar *, 65536 * sizeof(wchar),
- M_NTFSMNT, M_WAITOK);
-
- error = VFS_VGET(mp, NTFS_UPCASEINO, &vp);
- if(error)
- goto out1;
- error = ntfs_readattr(ntmp, VTONT(vp), NTFS_A_DATA, NULL,
- 0, 65536*sizeof(wchar), ntmp->ntm_upcase);
- vput(vp);
- if(error)
+ /* read the Unicode lowercase --> uppercase translation table,
+ * if necessary */
+ if ((error = ntfs_toupper_use(mp, ntmp)))
goto out1;
/*
@@ -529,7 +555,7 @@ ntfs_mountfs(devvp, mp, argsp, p)
error = ntfs_readattr(ntmp, VTONT(vp),
NTFS_A_DATA, NULL,
num * sizeof(ad), sizeof(ad),
- &ad);
+ &ad, NULL);
if (error)
goto out1;
if (ad.ad_name[0] == 0)
@@ -548,7 +574,7 @@ ntfs_mountfs(devvp, mp, argsp, p)
error = ntfs_readattr(ntmp, VTONT(vp),
NTFS_A_DATA, NULL,
i * sizeof(ad), sizeof(ad),
- &ad);
+ &ad, NULL);
if (error)
goto out1;
j = 0;
@@ -562,19 +588,16 @@ ntfs_mountfs(devvp, mp, argsp, p)
vput(vp);
}
- mp->mnt_stat.f_fsid.val[0] = dev2udev(dev);
#if defined(__FreeBSD__)
+ mp->mnt_stat.f_fsid.val[0] = dev2udev(dev);
mp->mnt_stat.f_fsid.val[1] = mp->mnt_vfc->vfc_typenum;
#else
+ mp->mnt_stat.f_fsid.val[0] = dev;
mp->mnt_stat.f_fsid.val[1] = makefstype(MOUNT_NTFS);
#endif
mp->mnt_maxsymlinklen = 0;
mp->mnt_flag |= MNT_LOCAL;
-#if defined(__FreeBSD__)
devvp->v_specmountpoint = mp;
-#else
- devvp->v_specflags |= SI_MOUNTEDON;
-#endif
return (0);
out1:
@@ -582,17 +605,22 @@ out1:
if(ntmp->ntm_sysvn[i]) vrele(ntmp->ntm_sysvn[i]);
if (vflush(mp,NULLVP,0))
- printf("ntfs_mountfs: vflush failed\n");
+ dprintf(("ntfs_mountfs: vflush failed\n"));
out:
-#if defined(__FreeBSD__)
devvp->v_specmountpoint = NULL;
-#else
- devvp->v_specflags &= ~SI_MOUNTEDON;
-#endif
if (bp)
brelse(bp);
+
+#if defined __NetBSD__
+ /* lock the device vnode before calling VOP_CLOSE() */
+ VN_LOCK(devvp, LK_EXCLUSIVE | LK_RETRY, p);
+ (void)VOP_CLOSE(devvp, ronly ? FREAD : FREAD|FWRITE, NOCRED, p);
+ VOP__UNLOCK(devvp, 0, p);
+#else
(void)VOP_CLOSE(devvp, ronly ? FREAD : FREAD|FWRITE, NOCRED, p);
+#endif
+
return (error);
}
@@ -605,7 +633,7 @@ ntfs_start (
{
return (0);
}
-#endif /* !defined(__FreeBSD__) */
+#endif
static int
ntfs_unmount(
@@ -635,7 +663,7 @@ ntfs_unmount(
if((ntmp->ntm_sysvn[i]) &&
(ntmp->ntm_sysvn[i]->v_usecount > 1)) return (EBUSY);
- /* Derefernce all system vnodes */
+ /* Dereference all system vnodes */
for(i=0;i<NTFS_SYSNODESNUM;i++)
if(ntmp->ntm_sysvn[i]) vrele(ntmp->ntm_sysvn[i]);
@@ -644,23 +672,35 @@ ntfs_unmount(
if (error)
printf("ntfs_unmount: vflush failed(sysnodes): %d\n",error);
-#if defined(__FreeBSD__)
- ntmp->ntm_devvp->v_specmountpoint = NULL;
-#else
- ntmp->ntm_devvp->v_specflags &= ~SI_MOUNTEDON;
-#endif
+ /* Check if the type of device node isn't VBAD before
+ * touching v_specinfo. If the device vnode is revoked, the
+ * field is NULL and touching it causes null pointer derefercence.
+ */
+ if (ntmp->ntm_devvp->v_type != VBAD)
+ ntmp->ntm_devvp->v_specmountpoint = NULL;
vinvalbuf(ntmp->ntm_devvp, V_SAVE, NOCRED, p, 0, 0);
+
+#if defined(__NetBSD__)
+ /* lock the device vnode before calling VOP_CLOSE() */
+ VOP_LOCK(ntmp->ntm_devvp, LK_EXCLUSIVE | LK_RETRY);
+ error = VOP_CLOSE(ntmp->ntm_devvp, ronly ? FREAD : FREAD|FWRITE,
+ NOCRED, p);
+ VOP__UNLOCK(ntmp->ntm_devvp, 0, p);
+#else
error = VOP_CLOSE(ntmp->ntm_devvp, ronly ? FREAD : FREAD|FWRITE,
NOCRED, p);
+#endif
vrele(ntmp->ntm_devvp);
+ /* free the toupper table, if this has been last mounted ntfs volume */
+ ntfs_toupper_unuse();
+
dprintf(("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);
}
@@ -697,7 +737,7 @@ ntfs_quotactl (
printf("\nntfs_quotactl():\n");
return EOPNOTSUPP;
}
-#endif /* !defined(__FreeBSD__) */
+#endif
int
ntfs_calccfree(
@@ -717,21 +757,18 @@ ntfs_calccfree(
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);
- }
+ 0, bmsize, tmp, NULL);
+ if (error)
+ goto out;
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);
+ out:
+ FREE(tmp, M_TEMP);
+ return(error);
}
static int
@@ -769,6 +806,9 @@ ntfs_statfs(
(caddr_t)&sbp->f_mntfromname[0], MNAMELEN);
}
sbp->f_flags = mp->mnt_flag;
+#ifdef __NetBSD__
+ strncpy(sbp->f_fstypename, mp->mnt_op->vfs_name, MFSNAMELEN);
+#endif
return (0);
}
@@ -784,34 +824,31 @@ ntfs_sync (
/*dprintf(("ntfs_sync():\n"));*/
return (0);
}
-#endif /* !defined(__FreeBSD__) */
+#endif
-#if !defined(__FreeBSD__)
/*ARGSUSED*/
static int
ntfs_fhtovp(
-#if defined(__FreeBSD__)
- struct mount *mp,
- struct fid *fhp,
- struct sockaddr *nam,
- struct vnode **vpp,
- int *exflagsp,
- struct ucred **credanonp)
-#elif defined(__NetBSD__)
struct mount *mp,
struct fid *fhp,
struct vnode **vpp)
-#else
- struct mount *mp,
- struct fid *fhp,
- struct mbuf *nam,
- struct vnode **vpp,
- int *exflagsp,
- struct ucred **credanonp)
-#endif
{
- printf("\ntfs_fhtovp():\n");
- return 0;
+ struct vnode *nvp;
+ struct ntfid *ntfhp = (struct ntfid *)fhp;
+ int error;
+
+ ddprintf(("ntfs_fhtovp(): %s: %d\n", mp->mnt_stat->f_mntonname,
+ ntfhp->ntfid_ino));
+
+ if ((error = VFS_VGET(mp, ntfhp->ntfid_ino, &nvp)) != 0) {
+ *vpp = NULLVP;
+ return (error);
+ }
+ /* XXX as unlink/rmdir/mkdir/creat are not currently possible
+ * with NTFS, we don't need to check anything else for now */
+ *vpp = nvp;
+
+ return (0);
}
static int
@@ -819,10 +856,19 @@ ntfs_vptofh(
struct vnode *vp,
struct fid *fhp)
{
- printf("ntfs_vptofh():\n");
- return EOPNOTSUPP;
+ register struct ntnode *ntp;
+ register struct ntfid *ntfhp;
+
+ ddprintf(("ntfs_fhtovp(): %s: %p\n", vp->v_mount->mnt_stat->f_mntonname,
+ vp));
+
+ ntp = VTONT(vp);
+ ntfhp = (struct ntfid *)fhp;
+ ntfhp->ntfid_len = sizeof(struct ntfid);
+ ntfhp->ntfid_ino = ntp->i_number;
+ /* ntfhp->ntfid_gen = ntp->i_gen; */
+ return (0);
}
-#endif /* !defined(__FreeBSD__) */
int
ntfs_vgetex(
@@ -840,9 +886,11 @@ ntfs_vgetex(
struct ntnode *ip;
struct fnode *fp;
struct vnode *vp;
+ enum vtype f_type;
- dprintf(("ntfs_vgetex: ino: %d, attr: 0x%x:%s, lkf: 0x%x, f: 0x%x\n",
- ino, attrtype, attrname?attrname:"", lkflags, flags ));
+ dprintf(("ntfs_vgetex: ino: %d, attr: 0x%x:%s, lkf: 0x%lx, f: 0x%lx\n",
+ ino, attrtype, attrname?attrname:"", (u_long)lkflags,
+ (u_long)flags ));
ntmp = VFSTONTFS(mp);
*vpp = NULL;
@@ -872,16 +920,16 @@ ntfs_vgetex(
return (error);
}
+ f_type = VNON;
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;
+ (fp->f_attrtype == NTFS_A_DATA && fp->f_attrname == NULL)) {
+ f_type = VDIR;
+ } else if (flags & VG_EXT) {
+ f_type = VNON;
+ fp->f_size = fp->f_allocated = 0;
} else {
- fp->f_type = VREG;
+ f_type = VREG;
error = ntfs_filesize(ntmp, fp,
&fp->f_size, &fp->f_allocated);
@@ -909,10 +957,12 @@ ntfs_vgetex(
}
dprintf(("ntfs_vget: vnode: %p for ntnode: %d\n", vp,ino));
+#ifdef __FreeBSD__
lockinit(&fp->f_lock, PINOD, "fnode", 0, 0);
+#endif
fp->f_vp = vp;
vp->v_data = fp;
- vp->v_type = fp->f_type;
+ vp->v_type = f_type;
if (ino == NTFS_ROOTINO)
vp->v_flag |= VROOT;
@@ -927,7 +977,7 @@ ntfs_vgetex(
}
}
- VREF(fp->f_devvp);
+ VREF(ip->i_devvp);
*vpp = vp;
return (0);
@@ -940,7 +990,7 @@ ntfs_vget(
struct vnode **vpp)
{
return ntfs_vgetex(mp, ino, NTFS_A_DATA, NULL,
- LK_EXCLUSIVE, 0, curproc, vpp);
+ LK_EXCLUSIVE | LK_RETRY, 0, curproc, vpp);
}
#if defined(__FreeBSD__)
@@ -953,9 +1003,9 @@ static struct vfsops ntfs_vfsops = {
ntfs_statfs,
vfs_stdsync,
ntfs_vget,
- vfs_stdfhtovp,
- vfs_stdcheckexp,
- vfs_stdvptofh,
+ ntfs_fhtovp,
+ ntfs_checkexp,
+ ntfs_vptofh,
ntfs_init,
NULL
};
@@ -986,7 +1036,7 @@ struct vfsops ntfs_vfsops = {
ntfs_checkexp,
ntfs_vnodeopv_descs,
};
-#else
+#else /* !NetBSD && !FreeBSD */
static struct vfsops ntfs_vfsops = {
ntfs_mount,
ntfs_start,
diff --git a/sys/ntfs/ntfs_vfsops.h b/sys/ntfs/ntfs_vfsops.h
index d7f5f5d..f124c77 100644
--- a/sys/ntfs/ntfs_vfsops.h
+++ b/sys/ntfs/ntfs_vfsops.h
@@ -1,4 +1,4 @@
-/* $NetBSD: ntfs_vfsops.h,v 1.2 1999/05/06 15:43:20 christos Exp $ */
+/* $NetBSD: ntfs_vfsops.h,v 1.4 1999/10/10 14:20:33 jdolecek Exp $ */
/*-
* Copyright (c) 1998, 1999 Semen Ustimenko (semenu@FreeBSD.org)
@@ -28,7 +28,7 @@
* $FreeBSD$
*/
#define VG_DONTLOADIN 0x0001 /* Tells ntfs_vgetex to do not call */
- /* ntfs_loadnode on ntnode, even if */
+ /* ntfs_loadntnode() on ntnode, even if */
/* ntnode not loaded */
#define VG_DONTVALIDFN 0x0002 /* Tells ntfs_vgetex to do not validate */
/* fnode */
diff --git a/sys/ntfs/ntfs_vnops.c b/sys/ntfs/ntfs_vnops.c
index 9d3f6e5..381cb8f 100644
--- a/sys/ntfs/ntfs_vnops.c
+++ b/sys/ntfs/ntfs_vnops.c
@@ -1,4 +1,4 @@
-/* $NetBSD: ntfs_vnops.c,v 1.2 1999/05/06 15:43:20 christos Exp $ */
+/* $NetBSD: ntfs_vnops.c,v 1.23 1999/10/31 19:45:27 jdolecek Exp $ */
/*
* Copyright (c) 1992, 1993
@@ -42,7 +42,6 @@
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/kernel.h>
-#include <sys/proc.h>
#include <sys/time.h>
#include <sys/types.h>
#include <sys/stat.h>
@@ -55,6 +54,9 @@
#include <vm/vm.h>
#include <vm/vm_param.h>
+#if defined(__NetBSD__)
+#include <vm/vm_prot.h>
+#endif
#include <vm/vm_page.h>
#include <vm/vm_object.h>
#include <vm/vm_pager.h>
@@ -65,12 +67,16 @@
#include <sys/sysctl.h>
-
/*#define NTFS_DEBUG 1*/
#include <ntfs/ntfs.h>
#include <ntfs/ntfs_inode.h>
#include <ntfs/ntfs_subr.h>
-#include <ntfs/ntfs_extern.h>
+#if defined(__NetBSD__)
+#include <miscfs/specfs/specdev.h>
+#include <miscfs/genfs/genfs.h>
+#endif
+
+#include <sys/unistd.h> /* for pathconf(2) constants */
static int ntfs_bypass __P((struct vop_generic_args *ap));
static int ntfs_read __P((struct vop_read_args *));
@@ -80,11 +86,6 @@ static int ntfs_inactive __P((struct vop_inactive_args *ap));
static int ntfs_print __P((struct vop_print_args *ap));
static int ntfs_reclaim __P((struct vop_reclaim_args *ap));
static int ntfs_strategy __P((struct vop_strategy_args *ap));
-#if defined(__NetBSD__)
-static int ntfs_islocked __P((struct vop_islocked_args *ap));
-static int ntfs_unlock __P((struct vop_unlock_args *ap));
-static int ntfs_lock __P((struct vop_lock_args *ap));
-#endif
static int ntfs_access __P((struct vop_access_args *ap));
static int ntfs_open __P((struct vop_open_args *ap));
static int ntfs_close __P((struct vop_close_args *ap));
@@ -94,8 +95,9 @@ static int ntfs_bmap __P((struct vop_bmap_args *ap));
#if defined(__FreeBSD__)
static int ntfs_getpages __P((struct vop_getpages_args *ap));
static int ntfs_putpages __P((struct vop_putpages_args *));
-#endif
static int ntfs_fsync __P((struct vop_fsync_args *ap));
+#endif
+static int ntfs_pathconf __P((void *));
int ntfs_prtactive = 1; /* 1 => print out reclaim of active vnodes */
@@ -159,39 +161,31 @@ ntfs_read(ap)
register struct ntnode *ip = FTONT(fp);
struct uio *uio = ap->a_uio;
struct ntfsmount *ntmp = ip->i_mp;
- u_int8_t *data;
u_int64_t toread;
int error;
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));
- toread = fp->f_size;
-
- dprintf(("ntfs_read: filesize: %d",(u_int32_t)toread));
+ dprintf(("ntfs_read: filesize: %d",(u_int32_t)fp->f_size));
- toread = min( uio->uio_resid, toread - uio->uio_offset );
+ /* don't allow reading after end of file */
+ if (uio->uio_offset > fp->f_size)
+ toread = 0;
+ else
+ toread = min( uio->uio_resid, fp->f_size - uio->uio_offset );
dprintf((", toread: %d\n",(u_int32_t)toread));
- MALLOC(data, u_int8_t *, toread, M_TEMP,M_WAITOK);
+ if (toread == 0)
+ return (0);
error = ntfs_readattr(ntmp, ip, fp->f_attrtype,
- fp->f_attrname, uio->uio_offset, toread, data);
- if(error) {
+ fp->f_attrname, uio->uio_offset, toread, NULL, uio);
+ if (error) {
printf("ntfs_read: ntfs_readattr failed: %d\n",error);
- FREE(data, M_TEMP);
- return (error);
- }
-
- error = uiomove(data, (int) toread, uio);
- if(error) {
- printf("ntfs_read: uiomove failed: %d\n",error);
- FREE(data, M_TEMP);
return (error);
}
- FREE(data, M_TEMP);
-
return (0);
}
@@ -224,12 +218,16 @@ ntfs_getattr(ap)
dprintf(("ntfs_getattr: %d, flags: %d\n",ip->i_number,ip->i_flag));
- vap->va_fsid = dev2udev(fp->f_dev);
+#if defined(__FreeBSD__)
+ vap->va_fsid = dev2udev(ip->i_dev);
+#else /* NetBSD */
+ vap->va_fsid = ip->i_dev;
+#endif
vap->va_fileid = ip->i_number;
- vap->va_mode = ip->i_mode;
+ vap->va_mode = ip->i_mp->ntm_mode;
vap->va_nlink = ip->i_nlink;
- vap->va_uid = ip->i_uid;
- vap->va_gid = ip->i_gid;
+ vap->va_uid = ip->i_mp->ntm_uid;
+ vap->va_gid = ip->i_mp->ntm_gid;
vap->va_rdev = 0; /* XXX UNODEV ? */
vap->va_size = fp->f_size;
vap->va_bytes = fp->f_allocated;
@@ -239,7 +237,7 @@ ntfs_getattr(ap)
vap->va_flags = ip->i_flag;
vap->va_gen = 0;
vap->va_blocksize = ip->i_mp->ntm_spc * ip->i_mp->ntm_bps;
- vap->va_type = fp->f_type;
+ vap->va_type = vp->v_type;
vap->va_filerev = 0;
return (0);
}
@@ -255,33 +253,25 @@ ntfs_inactive(ap)
} */ *ap;
{
register struct vnode *vp = ap->a_vp;
+#ifdef NTFS_DEBUG
register struct ntnode *ip = VTONT(vp);
- int error;
+#endif
dprintf(("ntfs_inactive: vnode: %p, ntnode: %d\n", vp, ip->i_number));
if (ntfs_prtactive && vp->v_usecount != 0)
vprint("ntfs_inactive: pushing active", vp);
- error = 0;
-
- VOP__UNLOCK(vp,0,ap->a_p);
+ VOP__UNLOCK(vp, 0, ap->a_p);
- /*
- * If we are done with the ntnode, reclaim it
- * so that it can be reused immediately.
+ /* XXX since we don't support any filesystem changes
+ * right now, nothing more needs to be done
*/
- if (vp->v_usecount == 0 && ip->i_mode == 0)
-#if defined(__FreeBSD__)
- vrecycle(vp, (struct simplelock *)0, ap->a_p);
-#else /* defined(__NetBSD__) */
- vgone(vp);
-#endif
- return (error);
+ return (0);
}
/*
- * Reclaim an inode so that it can be used for other purposes.
+ * Reclaim an fnode/ntnode so that it can be used for other purposes.
*/
int
ntfs_reclaim(ap)
@@ -296,26 +286,22 @@ ntfs_reclaim(ap)
dprintf(("ntfs_reclaim: vnode: %p, ntnode: %d\n", vp, ip->i_number));
- error = ntfs_ntget(ip);
- if (error)
- return (error);
-
-#if defined(__FreeBSD__)
- VOP__UNLOCK(vp,0,ap->a_p);
-#endif
+ if (ntfs_prtactive && vp->v_usecount != 0)
+ vprint("ntfs_reclaim: pushing active", vp);
+ if ((error = ntfs_ntget(ip)) != 0)
+ return (error);
+
/* Purge old data structures associated with the inode. */
cache_purge(vp);
- if (fp->f_devvp) {
- vrele(fp->f_devvp);
- fp->f_devvp = NULL;
+ if (ip->i_devvp) {
+ vrele(ip->i_devvp);
+ ip->i_devvp = NULL;
}
ntfs_frele(fp);
-
- vp->v_data = NULL;
-
ntfs_ntput(ip);
+ vp->v_data = NULL;
return (0);
}
@@ -326,8 +312,6 @@ ntfs_print(ap)
struct vnode *a_vp;
} */ *ap;
{
-/* printf("[ntfs_print]");*/
-
return (0);
}
@@ -348,10 +332,17 @@ ntfs_strategy(ap)
struct ntfsmount *ntmp = ip->i_mp;
int error;
+#ifdef __FreeBSD__
dprintf(("ntfs_strategy: offset: %d, blkno: %d, lblkno: %d\n",
(u_int32_t)bp->b_offset,(u_int32_t)bp->b_blkno,
(u_int32_t)bp->b_lblkno));
- dprintf(("strategy: bcount: %d flags: 0x%x\n",
+#else
+ dprintf(("ntfs_strategy: blkno: %d, lblkno: %d\n",
+ (u_int32_t)bp->b_blkno,
+ (u_int32_t)bp->b_lblkno));
+#endif
+
+ dprintf(("strategy: bcount: %d flags: 0x%lx\n",
(u_int32_t)bp->b_bcount,bp->b_flags));
if (bp->b_flags & B_READ) {
@@ -368,7 +359,7 @@ ntfs_strategy(ap)
error = ntfs_readattr(ntmp, ip, fp->f_attrtype,
fp->f_attrname, ntfs_cntob(bp->b_blkno),
- toread, bp->b_data);
+ toread, bp->b_data, NULL);
if (error) {
printf("ntfs_strategy: ntfs_readattr failed\n");
@@ -394,7 +385,7 @@ ntfs_strategy(ap)
error = ntfs_writeattr_plain(ntmp, ip, fp->f_attrtype,
fp->f_attrname, ntfs_cntob(bp->b_blkno),towrite,
- bp->b_data, &tmp);
+ bp->b_data, &tmp, NULL);
if (error) {
printf("ntfs_strategy: ntfs_writeattr fail\n");
@@ -421,172 +412,31 @@ ntfs_write(ap)
register struct ntnode *ip = FTONT(fp);
struct uio *uio = ap->a_uio;
struct ntfsmount *ntmp = ip->i_mp;
- u_int8_t *data;
u_int64_t towrite;
- off_t off;
size_t written;
int error;
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));
+ dprintf(("ntfs_write: filesize: %d",(u_int32_t)fp->f_size));
- 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");
+ if (uio->uio_resid + uio->uio_offset > fp->f_size) {
+ printf("ntfs_write: CAN'T WRITE BEYOND END OF FILE\n");
return (EFBIG);
}
- towrite = min(uio->uio_resid, towrite - uio->uio_offset);
- off = uio->uio_offset;
+ towrite = min(uio->uio_resid, fp->f_size - uio->uio_offset);
dprintf((", towrite: %d\n",(u_int32_t)towrite));
- MALLOC(data, u_int8_t *, towrite, M_TEMP,M_WAITOK);
-
- error = uiomove(data, (int) towrite, uio);
- if(error) {
- FREE(data, M_TEMP);
- return (error);
- }
-
error = ntfs_writeattr_plain(ntmp, ip, fp->f_attrtype,
- fp->f_attrname, off, towrite, data, &written);
- if(error) {
- printf("ntfs_write: ntfs_writeattr failed: %d\n",error);
- FREE(data, M_TEMP);
- return (error);
- }
-
- FREE(data, M_TEMP);
-
- return (0);
-}
-
-#if defined(__NetBSD__)
-/*
- * Check for a locked ntnode.
- */
-int
-ntfs_islocked(ap)
- struct vop_islocked_args /* {
- struct vnode *a_vp;
- } */ *ap;
-{
- register struct ntnode *ip = VTONT(ap->a_vp);
-
- dprintf(("ntfs_islocked %d\n",ip->i_number));
-
- if (ip->i_flag & IN_LOCKED)
- return (1);
- return (0);
-}
-
-/*
- * Unlock an ntnode. If WANT bit is on, wakeup.
- */
-int ntfs_lockcount = 90;
-int
-ntfs_unlock(ap)
- struct vop_unlock_args /* {
- struct vnode *a_vp;
- } */ *ap;
-{
- register struct ntnode *ip = VTONT(ap->a_vp);
-#ifdef DIAGNOSTIC
- struct proc *p = curproc;
-#endif
-
- dprintf(("ntfs_unlock %d\n",ip->i_number));
-
-#ifdef DIAGNOSTIC
-
- if ((ip->i_flag & IN_LOCKED) == 0) {
- vprint("ntfs_unlock: unlocked ntnode", ap->a_vp);
- panic("ntfs_unlock NOT LOCKED");
- }
- if (p && p->p_pid != ip->i_lockholder && p->p_pid > -1 &&
- ip->i_lockholder > -1 && ntfs_lockcount++ < 100)
- panic("unlocker (%d) != lock holder (%d)",
- p->p_pid, ip->i_lockholder);
-#endif
-
- if (--ip->i_lockcount > 0) {
- if ((ip->i_flag & IN_RECURSE) == 0)
- panic("ntfs_unlock: recursive lock prematurely released, pid=%d\n", ip->i_lockholder);
- return (0);
- }
- ip->i_lockholder = 0;
- ip->i_flag &= ~(IN_LOCKED|IN_RECURSE);
- if (ip->i_flag & IN_WANTED) {
- ip->i_flag &= ~IN_WANTED;
- wakeup((caddr_t)ip);
- }
- return (0);
-}
-
-/*
- * Lock an ntnode. If its already locked, set the WANT bit and sleep.
- */
-int
-ntfs_lock(ap)
- struct vop_lock_args /* {
- struct vnode *a_vp;
- } */ *ap;
-{
- struct proc *p = curproc;
- register struct vnode *vp = ap->a_vp;
- register struct ntnode *ip = VTONT(vp);
-
- dprintf(("ntfs_lock %d (%d locks)\n",ip->i_number,ip->i_lockcount));
-
-start:
- while (vp->v_flag & VXLOCK) {
- vp->v_flag |= VXWANT;
- (void) tsleep((caddr_t)vp, PINOD, "ntflk1", 0);
- }
- if (vp->v_tag == VT_NON)
- return (ENOENT);
- ip = VTONT(vp);
- if (ip->i_flag & IN_LOCKED) {
- if (p->p_pid == ip->i_lockholder) {
- if( (ip->i_flag & IN_RECURSE) == 0)
- panic("ntfs_lock: recursive lock not expected, pid: %d\n",
- ip->i_lockholder);
- } else {
- ip->i_flag |= IN_WANTED;
-#ifdef DIAGNOSTIC
- if (p)
- ip->i_lockwaiter = p->p_pid;
- else
- ip->i_lockwaiter = -1;
-#endif
- (void) tsleep((caddr_t)ip, PINOD, "ntflk2", 0);
- goto start;
- }
- }
-#ifdef DIAGNOSTIC
- ip->i_lockwaiter = 0;
- if (((ip->i_flag & IN_RECURSE) == 0) && (ip->i_lockholder != 0))
- panic("lockholder (%d) != 0", ip->i_lockholder);
- if (p && p->p_pid == 0)
- printf("locking by process 0\n");
+ fp->f_attrname, uio->uio_offset, towrite, NULL, &written, uio);
+#ifdef NTFS_DEBUG
+ if (error)
+ printf("ntfs_write: ntfs_writeattr failed: %d\n", error);
#endif
- if ((ip->i_flag & IN_RECURSE) == 0)
- ip->i_lockcount = 1;
- else
- ++ip->i_lockcount;
-
- if (p)
- ip->i_lockholder = p->p_pid;
- else
- ip->i_lockholder = -1;
- ip->i_flag |= IN_LOCKED;
- return (0);
+ return (error);
}
-#endif
int
ntfs_access(ap)
@@ -629,12 +479,6 @@ ntfs_access(ap)
}
}
- /* If immutable bit set, nobody gets to write it. */
-/*
- if ((mode & VWRITE) && (ip->i_flags & IMMUTABLE))
- return (EPERM);
-*/
-
/* Otherwise, user id 0 always gets access. */
if (cred->cr_uid == 0)
return (0);
@@ -642,26 +486,26 @@ ntfs_access(ap)
mask = 0;
/* Otherwise, check the owner. */
- if (cred->cr_uid == ip->i_uid) {
+ if (cred->cr_uid == ip->i_mp->ntm_uid) {
if (mode & VEXEC)
mask |= S_IXUSR;
if (mode & VREAD)
mask |= S_IRUSR;
if (mode & VWRITE)
mask |= S_IWUSR;
- return ((ip->i_mode & mask) == mask ? 0 : EACCES);
+ return ((ip->i_mp->ntm_mode & mask) == mask ? 0 : EACCES);
}
/* Otherwise, check the groups. */
for (i = 0, gp = cred->cr_groups; i < cred->cr_ngroups; i++, gp++)
- if (ip->i_gid == *gp) {
+ if (ip->i_mp->ntm_gid == *gp) {
if (mode & VEXEC)
mask |= S_IXGRP;
if (mode & VREAD)
mask |= S_IRGRP;
if (mode & VWRITE)
mask |= S_IWGRP;
- return ((ip->i_mode & mask) == mask ? 0 : EACCES);
+ return ((ip->i_mp->ntm_mode&mask) == mask ? 0 : EACCES);
}
/* Otherwise, check everyone else. */
@@ -671,7 +515,7 @@ ntfs_access(ap)
mask |= S_IROTH;
if (mode & VWRITE)
mask |= S_IWOTH;
- return ((ip->i_mode & mask) == mask ? 0 : EACCES);
+ return ((ip->i_mp->ntm_mode & mask) == mask ? 0 : EACCES);
}
/*
@@ -794,31 +638,31 @@ ntfs_readdir(ap)
if( NULL == iep )
break;
- while( !(iep->ie_flag & NTFS_IEFLAG_LAST) && (uio->uio_resid >= sizeof(struct dirent)) ) {
-
- if( ntfs_isnamepermitted(ntmp,iep) ) {
- dprintf(("ntfs_readdir: elem: %d, fname:[",num));
- for(i=0;i<iep->ie_fnamelen;i++) {
- cde.d_name[i] = (char)iep->ie_fname[i];
- dprintf(("%c", cde.d_name[i]));
- }
- dprintf(("] type: %d, flag: %d, ",iep->ie_fnametype, iep->ie_flag));
- cde.d_name[i] = '\0';
- cde.d_namlen = iep->ie_fnamelen;
- cde.d_fileno = iep->ie_number;
- cde.d_type = (iep->ie_fflag & NTFS_FFLAG_DIR) ? DT_DIR : DT_REG;
- cde.d_reclen = sizeof(struct dirent);
- dprintf(("%s\n", (cde.d_type == DT_DIR) ? "dir":"reg"));
-
- error = uiomove((char *)&cde, sizeof(struct dirent), uio);
- if(error)
- return (error);
-
- ncookies++;
- num++;
+ for(; !(iep->ie_flag & NTFS_IEFLAG_LAST) && (uio->uio_resid >= sizeof(struct dirent));
+ iep = NTFS_NEXTREC(iep, struct attr_indexentry *))
+ {
+ if(!ntfs_isnamepermitted(ntmp,iep))
+ continue;
+
+ for(i=0; i<iep->ie_fnamelen; i++) {
+ cde.d_name[i] = ntfs_u28(iep->ie_fname[i]);
}
+ cde.d_name[i] = '\0';
+ dprintf(("ntfs_readdir: elem: %d, fname:[%s] type: %d, flag: %d, ",
+ num, cde.d_name, iep->ie_fnametype,
+ iep->ie_flag));
+ cde.d_namlen = iep->ie_fnamelen;
+ cde.d_fileno = iep->ie_number;
+ cde.d_type = (iep->ie_fflag & NTFS_FFLAG_DIR) ? DT_DIR : DT_REG;
+ cde.d_reclen = sizeof(struct dirent);
+ dprintf(("%s\n", (cde.d_type == DT_DIR) ? "dir":"reg"));
+
+ error = uiomove((char *)&cde, sizeof(struct dirent), uio);
+ if(error)
+ return (error);
- iep = NTFS_NEXTREC(iep,struct attr_indexentry *);
+ ncookies++;
+ num++;
}
}
@@ -838,7 +682,7 @@ ntfs_readdir(ap)
off_t *cookiep;
#endif
- printf("ntfs_readdir: %d cookies\n",ncookies);
+ ddprintf(("ntfs_readdir: %d cookies\n",ncookies));
if (uio->uio_segflg != UIO_SYSSPACE || uio->uio_iovcnt != 1)
panic("ntfs_readdir: unexpected uio from NFS server");
dpStart = (struct dirent *)
@@ -885,25 +729,40 @@ ntfs_lookup(ap)
#if NTFS_DEBUG
int wantparent = cnp->cn_flags & (LOCKPARENT|WANTPARENT);
#endif
- dprintf(("ntfs_lookup: %s (%ld bytes) in %d, lp: %d, wp: %d \n",
- cnp->cn_nameptr, cnp->cn_namelen,
- dip->i_number,lockparent, wantparent));
+ dprintf(("ntfs_lookup: \"%.*s\" (%ld bytes) in %d, lp: %d, wp: %d \n",
+ (int)cnp->cn_namelen, cnp->cn_nameptr, cnp->cn_namelen,
+ dip->i_number, lockparent, wantparent));
error = VOP_ACCESS(dvp, VEXEC, cred, cnp->cn_proc);
if(error)
return (error);
- if( (cnp->cn_namelen == 1) &&
- !strncmp(cnp->cn_nameptr,".",1) ) {
+ if ((cnp->cn_flags & ISLASTCN) &&
+ (dvp->v_mount->mnt_flag & MNT_RDONLY) &&
+ (cnp->cn_nameiop == DELETE || cnp->cn_nameiop == RENAME))
+ return (EROFS);
+
+#ifdef __NetBSD__
+ /*
+ * We now have a segment name to search for, and a directory
+ * to search.
+ *
+ * Before tediously performing a linear scan of the directory,
+ * check the name cache to see if the directory/name pair
+ * we are looking for is known already.
+ */
+ if ((error = cache_lookup(ap->a_dvp, ap->a_vpp, cnp)) >= 0)
+ return (error);
+#endif
+
+ if(cnp->cn_namelen == 1 && cnp->cn_nameptr[0] == '.') {
dprintf(("ntfs_lookup: faking . directory in %d\n",
dip->i_number));
VREF(dvp);
*ap->a_vpp = dvp;
- return (0);
- } else if( (cnp->cn_namelen == 2) &&
- !strncmp(cnp->cn_nameptr,"..",2) &&
- (cnp->cn_flags & ISDOTDOT) ) {
+ error = 0;
+ } else if (cnp->cn_flags & ISDOTDOT) {
struct ntvattr *vap;
dprintf(("ntfs_lookup: faking .. directory in %d\n",
@@ -914,40 +773,48 @@ ntfs_lookup(ap)
return (error);
VOP__UNLOCK(dvp,0,cnp->cn_proc);
+ cnp->cn_flags |= PDIRUNLOCK;
dprintf(("ntfs_lookup: parentdir: %d\n",
vap->va_a_name->n_pnumber));
error = VFS_VGET(ntmp->ntm_mountp,
vap->va_a_name->n_pnumber,ap->a_vpp);
ntfs_ntvattrrele(vap);
- if(error) {
- VOP__LOCK(dvp, 0, cnp->cn_proc);
- return(error);
+ if (error) {
+ if (VN_LOCK(dvp,LK_EXCLUSIVE|LK_RETRY,cnp->cn_proc)==0)
+ cnp->cn_flags &= ~PDIRUNLOCK;
+ return (error);
}
- if( lockparent && (cnp->cn_flags & ISLASTCN) &&
- (error = VOP__LOCK(dvp, 0, cnp->cn_proc)) ) {
- vput( *(ap->a_vpp) );
- return (error);
+ if (lockparent && (cnp->cn_flags & ISLASTCN)) {
+ error = VN_LOCK(dvp, LK_EXCLUSIVE, cnp->cn_proc);
+ if (error) {
+ vput( *(ap->a_vpp) );
+ return (error);
+ }
+ cnp->cn_flags &= ~PDIRUNLOCK;
}
- return (error);
} else {
error = ntfs_ntlookupfile(ntmp, dvp, cnp, ap->a_vpp);
- if(error)
+ if (error) {
+ dprintf(("ntfs_ntlookupfile: returned %d\n", error));
return (error);
+ }
dprintf(("ntfs_lookup: found ino: %d\n",
VTONT(*ap->a_vpp)->i_number));
if(!lockparent || !(cnp->cn_flags & ISLASTCN))
VOP__UNLOCK(dvp, 0, cnp->cn_proc);
- if (cnp->cn_flags & MAKEENTRY)
- cache_enter(dvp, *ap->a_vpp, cnp);
-
}
+
+ if (cnp->cn_flags & MAKEENTRY)
+ cache_enter(dvp, *ap->a_vpp, cnp);
+
return (error);
}
+#if defined(__FreeBSD__)
/*
* Flush the blocks of a file to disk.
*
@@ -965,6 +832,50 @@ ntfs_fsync(ap)
{
return (0);
}
+#endif
+
+/*
+ * Return POSIX pathconf information applicable to NTFS filesystem
+ */
+int
+ntfs_pathconf(v)
+ void *v;
+{
+ struct vop_pathconf_args /* {
+ struct vnode *a_vp;
+ int a_name;
+ register_t *a_retval;
+ } */ *ap = v;
+
+ switch (ap->a_name) {
+ case _PC_LINK_MAX:
+ *ap->a_retval = 1;
+ return (0);
+ case _PC_NAME_MAX:
+ *ap->a_retval = NTFS_MAXFILENAME;
+ return (0);
+ case _PC_PATH_MAX:
+ *ap->a_retval = PATH_MAX;
+ return (0);
+ case _PC_CHOWN_RESTRICTED:
+ *ap->a_retval = 1;
+ return (0);
+ case _PC_NO_TRUNC:
+ *ap->a_retval = 0;
+ return (0);
+#if defined(__NetBSD__)
+ case _PC_SYNC_IO:
+ *ap->a_retval = 1;
+ return (0);
+ case _PC_FILESIZEBITS:
+ *ap->a_retval = 64;
+ return (0);
+#endif
+ default:
+ return (EINVAL);
+ }
+ /* NOTREACHED */
+}
/*
* Global vfs data structures
@@ -972,7 +883,6 @@ ntfs_fsync(ap)
vop_t **ntfs_vnodeop_p;
#if defined(__FreeBSD__)
static
-#endif
struct vnodeopv_entry_desc ntfs_vnodeop_entries[] = {
{ &vop_default_desc, (vop_t *)ntfs_bypass },
@@ -980,19 +890,13 @@ struct vnodeopv_entry_desc ntfs_vnodeop_entries[] = {
{ &vop_inactive_desc, (vop_t *)ntfs_inactive },
{ &vop_reclaim_desc, (vop_t *)ntfs_reclaim },
{ &vop_print_desc, (vop_t *)ntfs_print },
+ { &vop_pathconf_desc, ntfs_pathconf },
-#if defined(__FreeBSD__)
{ &vop_islocked_desc, (vop_t *)vop_stdislocked },
{ &vop_unlock_desc, (vop_t *)vop_stdunlock },
{ &vop_lock_desc, (vop_t *)vop_stdlock },
{ &vop_cachedlookup_desc, (vop_t *)ntfs_lookup },
{ &vop_lookup_desc, (vop_t *)vfs_cache_lookup },
-#else
- { &vop_islocked_desc, (vop_t *)ntfs_islocked },
- { &vop_unlock_desc, (vop_t *)ntfs_unlock },
- { &vop_lock_desc, (vop_t *)ntfs_lock },
- { &vop_lookup_desc, (vop_t *)ntfs_lookup },
-#endif
{ &vop_access_desc, (vop_t *)ntfs_access },
{ &vop_close_desc, (vop_t *)ntfs_close },
@@ -1001,28 +905,73 @@ struct vnodeopv_entry_desc ntfs_vnodeop_entries[] = {
{ &vop_fsync_desc, (vop_t *)ntfs_fsync },
{ &vop_bmap_desc, (vop_t *)ntfs_bmap },
-#if defined(__FreeBSD__)
{ &vop_getpages_desc, (vop_t *) ntfs_getpages },
{ &vop_putpages_desc, (vop_t *) ntfs_putpages },
-#endif
{ &vop_strategy_desc, (vop_t *)ntfs_strategy },
-#if defined(__FreeBSD__)
{ &vop_bwrite_desc, (vop_t *)vop_stdbwrite },
-#else /* defined(__NetBSD__) */
- { &vop_bwrite_desc, (vop_t *)vn_bwrite },
-#endif
{ &vop_read_desc, (vop_t *)ntfs_read },
{ &vop_write_desc, (vop_t *)ntfs_write },
{ NULL, NULL }
};
-#if defined(__FreeBSD__)
static
-#endif
struct vnodeopv_desc ntfs_vnodeop_opv_desc =
{ &ntfs_vnodeop_p, ntfs_vnodeop_entries };
-#if defined(__FreeBSD__)
VNODEOP_SET(ntfs_vnodeop_opv_desc);
+
+#else /* !FreeBSD */
+
+struct vnodeopv_entry_desc ntfs_vnodeop_entries[] = {
+ { &vop_default_desc, (vop_t *) ntfs_bypass },
+ { &vop_lookup_desc, (vop_t *) ntfs_lookup }, /* lookup */
+ { &vop_create_desc, genfs_eopnotsupp }, /* create */
+ { &vop_mknod_desc, genfs_eopnotsupp }, /* mknod */
+ { &vop_open_desc, (vop_t *) ntfs_open }, /* open */
+ { &vop_close_desc,(vop_t *) ntfs_close }, /* close */
+ { &vop_access_desc, (vop_t *) ntfs_access }, /* access */
+ { &vop_getattr_desc, (vop_t *) ntfs_getattr }, /* getattr */
+ { &vop_setattr_desc, genfs_eopnotsupp }, /* setattr */
+ { &vop_read_desc, (vop_t *) ntfs_read }, /* read */
+ { &vop_write_desc, (vop_t *) ntfs_write }, /* write */
+ { &vop_lease_desc, genfs_lease_check }, /* lease */
+ { &vop_fcntl_desc, genfs_fcntl }, /* fcntl */
+ { &vop_ioctl_desc, genfs_enoioctl }, /* ioctl */
+ { &vop_poll_desc, genfs_poll }, /* poll */
+ { &vop_revoke_desc, genfs_revoke }, /* revoke */
+ { &vop_mmap_desc, genfs_eopnotsupp }, /* mmap */
+ { &vop_fsync_desc, genfs_fsync }, /* fsync */
+ { &vop_seek_desc, genfs_seek }, /* seek */
+ { &vop_remove_desc, genfs_eopnotsupp }, /* remove */
+ { &vop_link_desc, genfs_eopnotsupp }, /* link */
+ { &vop_rename_desc, genfs_eopnotsupp }, /* rename */
+ { &vop_mkdir_desc, genfs_eopnotsupp }, /* mkdir */
+ { &vop_rmdir_desc, genfs_eopnotsupp }, /* rmdir */
+ { &vop_symlink_desc, genfs_eopnotsupp }, /* symlink */
+ { &vop_readdir_desc, (vop_t *) ntfs_readdir }, /* readdir */
+ { &vop_readlink_desc, genfs_eopnotsupp }, /* readlink */
+ { &vop_abortop_desc, genfs_abortop }, /* abortop */
+ { &vop_inactive_desc, (vop_t *) ntfs_inactive }, /* inactive */
+ { &vop_reclaim_desc, (vop_t *) ntfs_reclaim }, /* reclaim */
+ { &vop_lock_desc, genfs_lock }, /* lock */
+ { &vop_unlock_desc, genfs_unlock }, /* unlock */
+ { &vop_bmap_desc, (vop_t *) ntfs_bmap }, /* bmap */
+ { &vop_strategy_desc, (vop_t *) ntfs_strategy }, /* strategy */
+ { &vop_print_desc, (vop_t *) ntfs_print }, /* print */
+ { &vop_islocked_desc, genfs_islocked }, /* islocked */
+ { &vop_pathconf_desc, ntfs_pathconf }, /* pathconf */
+ { &vop_advlock_desc, genfs_nullop }, /* advlock */
+ { &vop_blkatoff_desc, genfs_eopnotsupp }, /* blkatoff */
+ { &vop_valloc_desc, genfs_eopnotsupp }, /* valloc */
+ { &vop_reallocblks_desc, genfs_eopnotsupp }, /* reallocblks */
+ { &vop_vfree_desc, genfs_eopnotsupp }, /* vfree */
+ { &vop_truncate_desc, genfs_eopnotsupp }, /* truncate */
+ { &vop_update_desc, genfs_eopnotsupp }, /* update */
+ { &vop_bwrite_desc, vn_bwrite }, /* bwrite */
+ { (struct vnodeop_desc *)NULL, (int (*) __P((void *)))NULL }
+};
+struct vnodeopv_desc ntfs_vnodeop_opv_desc =
+ { &ntfs_vnodeop_p, ntfs_vnodeop_entries };
+
#endif
diff --git a/sys/ntfs/ntfsmount.h b/sys/ntfs/ntfsmount.h
index 0a1f791..f3a6d25 100644
--- a/sys/ntfs/ntfsmount.h
+++ b/sys/ntfs/ntfsmount.h
@@ -1,4 +1,4 @@
-/* $NetBSD: ntfsmount.h,v 1.2 1999/05/06 15:43:21 christos Exp $ */
+/* $NetBSD: ntfsmount.h,v 1.3 1999/07/26 14:02:32 jdolecek Exp $ */
/*-
* Copyright (c) 1998, 1999 Semen Ustimenko
OpenPOWER on IntegriCloud