diff options
author | semenu <semenu@FreeBSD.org> | 1999-12-03 20:37:40 +0000 |
---|---|---|
committer | semenu <semenu@FreeBSD.org> | 1999-12-03 20:37:40 +0000 |
commit | 39d5a6d9a112c694b6ddfe314cd3fabd50842d57 (patch) | |
tree | 9ce5b1cd13e28d4820c42a103ec4056e6905350a /sys/ntfs/ntfs_subr.c | |
parent | 97f1907fc7b23a0430fdd2761931127aee747ad5 (diff) | |
download | FreeBSD-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/ntfs_subr.c')
-rw-r--r-- | sys/ntfs/ntfs_subr.c | 1048 |
1 files changed, 572 insertions, 476 deletions
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); +} + |