ntfs_subr.c revision 50477
118334Speter/* $NetBSD: ntfs_subr.c,v 1.2 1999/05/06 15:43:19 christos Exp $ */ 290075Sobrien 3169689Skan/*- 4169689Skan * Copyright (c) 1998, 1999 Semen Ustimenko (semenu@FreeBSD.org) 518334Speter * All rights reserved. 690075Sobrien * 718334Speter * Redistribution and use in source and binary forms, with or without 890075Sobrien * modification, are permitted provided that the following conditions 990075Sobrien * are met: 1090075Sobrien * 1. Redistributions of source code must retain the above copyright 1190075Sobrien * notice, this list of conditions and the following disclaimer. 1218334Speter * 2. Redistributions in binary form must reproduce the above copyright 1390075Sobrien * notice, this list of conditions and the following disclaimer in the 1490075Sobrien * documentation and/or other materials provided with the distribution. 1590075Sobrien * 1690075Sobrien * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 1718334Speter * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 1818334Speter * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 1990075Sobrien * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 20169689Skan * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 21169689Skan * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 2218334Speter * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 2318334Speter * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 2418334Speter * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 2518334Speter * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 2618334Speter * SUCH DAMAGE. 2718334Speter * 2818334Speter * $FreeBSD: head/sys/fs/ntfs/ntfs_subr.c 50477 1999-08-28 01:08:13Z peter $ 2918334Speter */ 3018334Speter 31117395Skan#include <sys/param.h> 3218334Speter#include <sys/types.h> 3318334Speter#include <sys/systm.h> 3450397Sobrien#include <sys/namei.h> 35132718Skan#include <sys/proc.h> 36132718Skan#include <sys/kernel.h> 3750397Sobrien#include <sys/vnode.h> 3850397Sobrien#include <sys/mount.h> 39117395Skan#include <sys/buf.h> 4090075Sobrien#include <sys/file.h> 4150397Sobrien#include <sys/malloc.h> 4250397Sobrien#if defined(__FreeBSD__) 4350397Sobrien#include <machine/clock.h> 4490075Sobrien#endif 4590075Sobrien 4690075Sobrien/* #define NTFS_DEBUG 1 */ 4790075Sobrien#include <ntfs/ntfs.h> 4890075Sobrien#include <ntfs/ntfsmount.h> 49169689Skan#include <ntfs/ntfs_inode.h> 50169689Skan#include <ntfs/ntfs_vfsops.h> 51169689Skan#include <ntfs/ntfs_extern.h> 52169689Skan#include <ntfs/ntfs_subr.h> 53169689Skan#include <ntfs/ntfs_compr.h> 5418334Speter#include <ntfs/ntfs_ihash.h> 55169689Skan 56169689Skan#if defined(__FreeBSD__) 57169689SkanMALLOC_DEFINE(M_NTFSNTVATTR, "NTFS vattr", "NTFS file attribute information"); 58169689SkanMALLOC_DEFINE(M_NTFSRDATA, "NTFS res data", "NTFS resident data"); 59169689SkanMALLOC_DEFINE(M_NTFSRUN, "NTFS vrun", "NTFS vrun storage"); 60169689SkanMALLOC_DEFINE(M_NTFSDECOMP, "NTFS decomp", "NTFS decompression temporary"); 61169689Skan#endif 62169689Skan 63169689Skan/* 64169689Skan * 65169689Skan */ 66169689Skanint 67169689Skanntfs_ntvattrrele( 68169689Skan struct ntvattr * vap) 69169689Skan{ 70169689Skan dprintf(("ntfs_ntvattrrele: ino: %d, type: 0x%x\n", 71169689Skan vap->va_ip->i_number, vap->va_type)); 72260311Spfg 73260311Spfg ntfs_ntrele(vap->va_ip); 74260311Spfg 75260311Spfg return (0); 7690075Sobrien} 77132718Skan 7818334Speter/* 79117395Skan * Search attribute specifed in ntnode (load ntnode if nessecary). 8018334Speter * If not found but ATTR_A_ATTRLIST present, read it in and search throught. 8118334Speter * VOP_VGET node needed, and lookup througth it's ntnode (load if nessesary). 8290075Sobrien * 8390075Sobrien * ntnode should be locked 8418334Speter */ 85132718Skanint 8690075Sobrienntfs_ntvattrget( 8718334Speter struct ntfsmount * ntmp, 8818334Speter struct ntnode * ip, 8918334Speter u_int32_t type, 9018334Speter char *name, 9118334Speter cn_t vcn, 9218334Speter struct ntvattr ** vapp) 9318334Speter{ 9418334Speter int error; 9518334Speter struct ntvattr *vap; 9618334Speter struct ntvattr *lvap = NULL; 9718334Speter struct attr_attrlist *aalp; 98169689Skan struct attr_attrlist *nextaalp; 99169689Skan caddr_t alpool; 100169689Skan int len, namelen; 101169689Skan 10218334Speter *vapp = NULL; 10318334Speter 104169689Skan if (name) { 105169689Skan dprintf(("ntfs_ntvattrget: " \ 10618334Speter "ino: %d, type: 0x%x, name: %s, vcn: %d\n", \ 107117395Skan ip->i_number, type, name, (u_int32_t) vcn)); 10818334Speter namelen = strlen(name); 10918334Speter } else { 110132718Skan dprintf(("ntfs_ntvattrget: " \ 11118334Speter "ino: %d, type: 0x%x, vcn: %d\n", \ 112132718Skan ip->i_number, type, (u_int32_t) vcn)); 11318334Speter name = ""; 11490075Sobrien namelen = 0; 11590075Sobrien } 11650397Sobrien 117117395Skan if((ip->i_flag & IN_LOADED) == 0) { 11818334Speter dprintf(("ntfs_ntvattrget: node not loaded, ino: %d\n", 11990075Sobrien ip->i_number)); 12090075Sobrien error = ntfs_loadntnode(ntmp,ip); 12190075Sobrien if(error) { 12218334Speter printf("ntfs_ntvattrget: FAILED TO LOAD INO: %d\n", 12390075Sobrien ip->i_number); 12490075Sobrien return (error); 12518334Speter } 12690075Sobrien } 12790075Sobrien 12890075Sobrien for (vap = ip->i_valist.lh_first; vap; vap = vap->va_list.le_next) { 12990075Sobrien ddprintf(("type: 0x%x, vcn: %d - %d\n", \ 13090075Sobrien vap->va_type, (u_int32_t) vap->va_vcnstart, \ 13190075Sobrien (u_int32_t) vap->va_vcnend)); 13218334Speter if ((vap->va_type == type) && 133117395Skan (vap->va_vcnstart <= vcn) && (vap->va_vcnend >= vcn) && 134117395Skan (vap->va_namelen == namelen) && 13518334Speter (!strncmp(name, vap->va_name, namelen))) { 136169689Skan *vapp = vap; 137169689Skan ntfs_ntref(vap->va_ip); 138169689Skan return (0); 139169689Skan } 140169689Skan if (vap->va_type == NTFS_A_ATTRLIST) 141169689Skan lvap = vap; 142169689Skan } 143169689Skan 144169689Skan if (!lvap) { 145169689Skan dprintf(("ntfs_ntvattrget: UNEXISTED ATTRIBUTE: " \ 146169689Skan "ino: %d, type: 0x%x, name: %s, vcn: %d\n", \ 147169689Skan ip->i_number, type, name, (u_int32_t) vcn)); 148169689Skan return (ENOENT); 149169689Skan } 150169689Skan /* Scan $ATTRIBUTE_LIST for requested attribute */ 151169689Skan len = lvap->va_datalen; 152169689Skan MALLOC(alpool, caddr_t, len, M_TEMP, M_WAITOK); 153169689Skan error = ntfs_readntvattr_plain(ntmp, ip, lvap, 0, len, alpool, &len); 154169689Skan if (error) 155169689Skan goto out; 156169689Skan 157169689Skan aalp = (struct attr_attrlist *) alpool; 158169689Skan nextaalp = NULL; 159169689Skan 160169689Skan while (len > 0) { 161169689Skan dprintf(("ntfs_ntvattrget: " \ 162169689Skan "attrlist: ino: %d, attr: 0x%x, vcn: %d\n", \ 163169689Skan aalp->al_inumber, aalp->al_type, \ 164132718Skan (u_int32_t) aalp->al_vcnstart)); 165132718Skan 166132718Skan if (len > aalp->reclen) { 167169689Skan nextaalp = NTFS_NEXTREC(aalp, struct attr_attrlist *); 168169689Skan } else { 169132718Skan nextaalp = NULL; 170169689Skan } 171169689Skan len -= aalp->reclen; 172132718Skan 173169689Skan#define AALPCMP(aalp,type,name,namelen) ( \ 174169689Skan (aalp->al_type == type) && (aalp->al_namelen == namelen) && \ 17518334Speter !uastrcmp(aalp->al_name,aalp->al_namelen,name,namelen) ) 17690075Sobrien 17790075Sobrien if (AALPCMP(aalp, type, name, namelen) && 178169689Skan (!nextaalp || (nextaalp->al_vcnstart > vcn) || 179169689Skan !AALPCMP(nextaalp, type, name, namelen))) { 180169689Skan struct vnode *newvp; 181169689Skan struct ntnode *newip; 182169689Skan 183169689Skan dprintf(("ntfs_ntvattrget: attrbute in ino: %d\n", 184169689Skan aalp->al_inumber)); 185169689Skan 186169689Skan/* 187169689Skan error = VFS_VGET(ntmp->ntm_mountp, aalp->al_inumber, 188169689Skan &newvp); 189169689Skan*/ 190169689Skan error = ntfs_vgetex(ntmp->ntm_mountp, aalp->al_inumber, 191169689Skan NTFS_A_DATA, NULL, LK_EXCLUSIVE, 192169689Skan VG_EXT, curproc, &newvp); 193169689Skan if (error) { 194169689Skan printf("ntfs_ntvattrget: CAN'T VGET INO: %d\n", 195169689Skan aalp->al_inumber); 196169689Skan goto out; 197169689Skan } 198169689Skan newip = VTONT(newvp); 199169689Skan /* XXX have to lock ntnode */ 200169689Skan if(~newip->i_flag & IN_LOADED) { 201169689Skan dprintf(("ntfs_ntvattrget: node not loaded," \ 202169689Skan " ino: %d\n", newip->i_number)); 203169689Skan error = ntfs_loadntnode(ntmp,ip); 204169689Skan if(error) { 205169689Skan printf("ntfs_ntvattrget: CAN'T LOAD " \ 206169689Skan "INO: %d\n", newip->i_number); 207169689Skan vput(newvp); 208169689Skan goto out; 209169689Skan } 210169689Skan } 211169689Skan for (vap = newip->i_valist.lh_first; vap; vap = vap->va_list.le_next) { 212169689Skan if ((vap->va_type == type) && 213169689Skan (vap->va_vcnstart <= vcn) && 214169689Skan (vap->va_vcnend >= vcn) && 215169689Skan (vap->va_namelen == namelen) && 216169689Skan (!strncmp(name, vap->va_name, namelen))) { 21790075Sobrien *vapp = vap; 218117395Skan ntfs_ntref(vap->va_ip); 21918334Speter vput(newvp); 22018334Speter error = 0; 221132718Skan goto out; 22218334Speter } 22390075Sobrien if (vap->va_type == NTFS_A_ATTRLIST) 224132718Skan lvap = vap; 225132718Skan } 226169689Skan printf("ntfs_ntvattrget: ATTRLIST ERROR.\n"); 227169689Skan vput(newvp); 228169689Skan break; 229169689Skan } 230169689Skan#undef AALPCMP 231169689Skan aalp = nextaalp; 232169689Skan } 233169689Skan error = ENOENT; 234169689Skan 235169689Skan dprintf(("ntfs_ntvattrget: UNEXISTED ATTRIBUTE: " \ 236169689Skan "ino: %d, type: 0x%x, name: %s, vcn: %d\n", \ 237169689Skan ip->i_number, type, name, (u_int32_t) vcn)); 238169689Skanout: 239169689Skan FREE(alpool, M_TEMP); 240169689Skan return (error); 241169689Skan} 242169689Skan 243169689Skan/* 244169689Skan * Read ntnode from disk, make ntvattr list. 245169689Skan * 246169689Skan * ntnode should be locked 247169689Skan */ 248169689Skanint 249169689Skanntfs_loadntnode( 250169689Skan struct ntfsmount * ntmp, 251169689Skan struct ntnode * ip) 252169689Skan{ 253169689Skan struct filerec *mfrp; 254169689Skan daddr_t bn; 255169689Skan int error,off; 256169689Skan struct attr *ap; 257169689Skan struct ntvattr *nvap; 258169689Skan 259169689Skan dprintf(("ntfs_loadnode: loading ino: %d\n",ip->i_number)); 260169689Skan 261169689Skan MALLOC(mfrp, struct filerec *, ntfs_bntob(ntmp->ntm_bpmftrec), 262169689Skan M_TEMP, M_WAITOK); 263169689Skan 264169689Skan if (ip->i_number < NTFS_SYSNODESNUM) { 265169689Skan struct buf *bp; 266169689Skan 267169689Skan dprintf(("ntfs_loadnode: read system node\n")); 268169689Skan 269169689Skan bn = ntfs_cntobn(ntmp->ntm_mftcn) + 270169689Skan ntmp->ntm_bpmftrec * ip->i_number; 271169689Skan 272169689Skan error = bread(ntmp->ntm_devvp, 273169689Skan bn, ntfs_bntob(ntmp->ntm_bpmftrec), 274169689Skan NOCRED, &bp); 275169689Skan if (error) { 276169689Skan printf("ntfs_loadnode: BREAD FAILED\n"); 277169689Skan brelse(bp); 278169689Skan goto out; 279169689Skan } 280169689Skan memcpy(mfrp, bp->b_data, ntfs_bntob(ntmp->ntm_bpmftrec)); 281169689Skan bqrelse(bp); 282169689Skan } else { 283169689Skan struct vnode *vp; 284169689Skan 285169689Skan vp = ntmp->ntm_sysvn[NTFS_MFTINO]; 286169689Skan error = ntfs_readattr(ntmp, VTONT(vp), NTFS_A_DATA, NULL, 287169689Skan ip->i_number * ntfs_bntob(ntmp->ntm_bpmftrec), 288169689Skan ntfs_bntob(ntmp->ntm_bpmftrec), mfrp); 289169689Skan if (error) { 290169689Skan printf("ntfs_loadnode: ntfs_readattr failed\n"); 291169689Skan goto out; 292169689Skan } 293169689Skan } 294169689Skan 295169689Skan /* Check if magic and fixups are correct */ 296169689Skan error = ntfs_procfixups(ntmp, NTFS_FILEMAGIC, (caddr_t)mfrp, 297169689Skan ntfs_bntob(ntmp->ntm_bpmftrec)); 298169689Skan if (error) { 29918334Speter printf("ntfs_loadnode: BAD MFT RECORD %d\n", 30018334Speter (u_int32_t) ip->i_number); 30118334Speter goto out; 302117395Skan } 303117395Skan 304117395Skan dprintf(("ntfs_loadnode: load attrs for ino: %d\n",ip->i_number)); 305117395Skan off = mfrp->fr_attroff; 306132718Skan ap = (struct attr *) ((caddr_t)mfrp + off); 30718334Speter 308117395Skan LIST_INIT(&ip->i_valist); 309169689Skan 310169689Skan while (ap->a_hdr.a_type != -1) { 31118334Speter error = ntfs_attrtontvattr(ntmp, &nvap, ap); 31218334Speter if (error) 313169689Skan break; 314169689Skan nvap->va_ip = ip; 315169689Skan 31690075Sobrien LIST_INSERT_HEAD(&ip->i_valist, nvap, va_list); 317169689Skan 31818334Speter off += ap->a_hdr.reclen; 31990075Sobrien ap = (struct attr *) ((caddr_t)mfrp + off); 32090075Sobrien } 321169689Skan if (error) { 322169689Skan printf("ntfs_loadnode: failed to load attr ino: %d\n", 323169689Skan ip->i_number); 324169689Skan goto out; 325169689Skan } 326169689Skan 327169689Skan ip->i_mainrec = mfrp->fr_mainrec; 328169689Skan ip->i_nlink = mfrp->fr_nlink; 329169689Skan ip->i_frflag = mfrp->fr_flags; 330169689Skan 331169689Skan ip->i_flag |= IN_LOADED; 332169689Skan 333169689Skanout: 334169689Skan FREE(mfrp, M_TEMP); 335169689Skan return (error); 336169689Skan} 337169689Skan 338169689Skan/* 339169689Skan * Routine locks ntnode and increase usecount, just opposite of 340169689Skan * ntfs_ntput. 341169689Skan */ 342169689Skanint 343169689Skanntfs_ntget( 344169689Skan struct ntnode *ip) 345169689Skan{ 346169689Skan dprintf(("ntfs_ntget: get ntnode %d: %p, usecount: %d\n", 347169689Skan ip->i_number, ip, ip->i_usecount)); 348169689Skan 349169689Skan ip->i_usecount++; 35050397Sobrien 351169689Skanrestart: 35290075Sobrien if (ip->i_lock) { 35318334Speter while (ip->i_lock) { 354169689Skan ip->i_lock = -1; 355169689Skan tsleep(&ip->i_lock, PVM, "ntnode", 0); 356169689Skan } 357169689Skan goto restart; 358169689Skan } 359169689Skan ip->i_lock = 1; 36090075Sobrien 361169689Skan return 0; 36218334Speter} 363169689Skan 364132718Skan/* 365132718Skan * Routine search ntnode in hash, if found: lock, inc usecount and return. 366132718Skan * If not in hash allocate structure for ntnode, prefill it, lock, 367132718Skan * inc count and return. 368132718Skan * 369132718Skan * ntnode returned locked 370169689Skan */ 371132718Skanstatic int ntfs_ntnode_hash_lock; 372169689Skanint 373132718Skanntfs_ntlookup( 37418334Speter struct ntfsmount * ntmp, 375169689Skan ino_t ino, 376132718Skan struct ntnode ** ipp) 377132718Skan{ 378132718Skan struct ntnode *ip; 379132718Skan 38018334Speter dprintf(("ntfs_ntlookup: for ntnode %d\n", ino)); 381132718Skan *ipp = NULL; 382132718Skan 383132718Skanrestart: 384169689Skan ip = ntfs_nthashlookup(ntmp->ntm_dev, ino); /* XXX */ 385169689Skan if (ip) { 386169689Skan ntfs_ntget(ip); 387169689Skan *ipp = ip; 388169689Skan dprintf(("ntfs_ntlookup: ntnode %d: %p, usecount: %d\n", 389169689Skan ino, ip, ip->i_usecount)); 390169689Skan 391169689Skan return (0); 392169689Skan } 393169689Skan 394169689Skan if (ntfs_ntnode_hash_lock) { 395132718Skan while(ntfs_ntnode_hash_lock) { 396169689Skan ntfs_ntnode_hash_lock = -1; 397132718Skan tsleep(&ntfs_ntnode_hash_lock, PVM, "ntfsntgt", 0); 398132718Skan } 39990075Sobrien goto restart; 400169689Skan } 40190075Sobrien ntfs_ntnode_hash_lock = 1; 40218334Speter 40318334Speter MALLOC(ip, struct ntnode *, sizeof(struct ntnode), 404169689Skan M_NTFSNTNODE, M_WAITOK); 405169689Skan ddprintf(("ntfs_ntlookup: allocating ntnode: %d: %p\n", ino, ip)); 406169689Skan bzero((caddr_t) ip, sizeof(struct ntnode)); 407169689Skan 408169689Skan /* Generic initialization */ 409169689Skan ip->i_number = ino; 410169689Skan ip->i_mp = ntmp; 411169689Skan ip->i_dev = ntmp->ntm_dev; 412169689Skan ip->i_uid = ntmp->ntm_uid; 413169689Skan ip->i_gid = ntmp->ntm_gid; 414169689Skan ip->i_mode = ntmp->ntm_mode; 41518334Speter ip->i_usecount++; 416169689Skan 417169689Skan ip->i_lock = 1; 418169689Skan 419169689Skan LIST_INIT(&ip->i_fnlist); 420169689Skan 421169689Skan ntfs_nthashins(ip); 422169689Skan 423169689Skan if (ntfs_ntnode_hash_lock < 0) 424169689Skan wakeup(&ntfs_ntnode_hash_lock); 425169689Skan ntfs_ntnode_hash_lock = 0; 426169689Skan 427169689Skan *ipp = ip; 428169689Skan 429169689Skan dprintf(("ntfs_ntlookup: ntnode %d: %p, usecount: %d\n", 430169689Skan ino, ip, ip->i_usecount)); 431169689Skan 432169689Skan return (0); 433169689Skan} 434169689Skan 435169689Skan/* 436169689Skan * Decrement usecount of ntnode and unlock it, if usecount reach zero, 437169689Skan * deallocate ntnode. 438169689Skan * 439169689Skan * ntnode should be locked on entry, and unlocked on return. 440169689Skan */ 441169689Skanvoid 442169689Skanntfs_ntput( 44318334Speter struct ntnode *ip) 44418334Speter{ 44518334Speter struct ntvattr *vap; 446169689Skan 44718334Speter if (!ip->i_lock) printf("ntfs_ntput: NOT LOCKED"); 44890075Sobrien 449169689Skan dprintf(("ntfs_ntput: rele ntnode %d: %p, usecount: %d\n", 450169689Skan ip->i_number, ip, ip->i_usecount)); 45150397Sobrien 45290075Sobrien ip->i_usecount--; 453117395Skan 45418334Speter if (ip->i_usecount < 0) { 45518334Speter panic("ntfs_ntput: ino: %d usecount: %d \n", 456169689Skan ip->i_number,ip->i_usecount); 45718334Speter } else if (ip->i_usecount == 0) { 45818334Speter dprintf(("ntfs_ntput: deallocating ntnode: %d\n", 45918334Speter ip->i_number)); 460169689Skan 46118334Speter if (ip->i_fnlist.lh_first) 46218334Speter panic("ntfs_ntput: ntnode has fnodes\n"); 46318334Speter 464169689Skan ntfs_nthashrem(ip); 46518334Speter 46690075Sobrien while (ip->i_valist.lh_first != NULL) { 46790075Sobrien vap = ip->i_valist.lh_first; 468169689Skan LIST_REMOVE(vap,va_list); 46918334Speter ntfs_freentvattr(vap); 47090075Sobrien } 47190075Sobrien FREE(ip, M_NTFSNTNODE); 472169689Skan } else { 473169689Skan if (ip->i_lock < 0) 474169689Skan wakeup(&ip->i_lock); 475169689Skan ip->i_lock = 0; 47618334Speter } 47718334Speter} 47818334Speter 479169689Skan/* 48018334Speter * Decrement usecount of ntnode. 48118334Speter */ 48218334Spetervoid 483169689Skanntfs_ntrele( 484169689Skan struct ntnode * ip) 485169689Skan{ 486169689Skan dprintf(("ntfs_ntrele: rele ntnode %d: %p, usecount: %d\n", 487169689Skan ip->i_number, ip, ip->i_usecount)); 488169689Skan 489169689Skan ip->i_usecount--; 490169689Skan 491169689Skan if (ip->i_usecount < 0) 492169689Skan panic("ntfs_ntrele: ino: %d usecount: %d \n", 493169689Skan ip->i_number,ip->i_usecount); 494169689Skan} 495169689Skan 496169689Skan/* 497169689Skan * Deallocate all memory allocated for ntvattr by call to 498169689Skan * ntfs_attrtontvattr and some other functions. 499169689Skan */ 500169689Skanvoid 501169689Skanntfs_freentvattr( 502169689Skan struct ntvattr * vap) 503169689Skan{ 504169689Skan if (vap->va_flag & NTFS_AF_INRUN) { 505169689Skan if (vap->va_vruncn) 506169689Skan FREE(vap->va_vruncn, M_NTFSRUN); 507169689Skan if (vap->va_vruncl) 508169689Skan FREE(vap->va_vruncl, M_NTFSRUN); 509169689Skan } else { 510169689Skan if (vap->va_datap) 511169689Skan FREE(vap->va_datap, M_NTFSRDATA); 512169689Skan } 513169689Skan FREE(vap, M_NTFSNTVATTR); 514169689Skan} 515169689Skan 516169689Skan/* 517169689Skan * Convert disk image of attribute into ntvattr structure, 51818334Speter * runs are expanded also. 519169689Skan */ 52018334Speterint 521169689Skanntfs_attrtontvattr( 52218334Speter struct ntfsmount * ntmp, 52318334Speter struct ntvattr ** rvapp, 52490075Sobrien struct attr * rap) 52590075Sobrien{ 52618334Speter int error, i; 52718334Speter struct ntvattr *vap; 528169689Skan 529169689Skan error = 0; 530169689Skan *rvapp = NULL; 531169689Skan 53290075Sobrien MALLOC(vap, struct ntvattr *, sizeof(struct ntvattr), 533132718Skan M_NTFSNTVATTR, M_WAITOK); 53490075Sobrien bzero(vap, sizeof(struct ntvattr)); 53518334Speter vap->va_ip = NULL; 53618334Speter vap->va_flag = rap->a_hdr.a_flag; 53718334Speter vap->va_type = rap->a_hdr.a_type; 53818334Speter vap->va_compression = rap->a_hdr.a_compression; 539169689Skan vap->va_index = rap->a_hdr.a_index; 54018334Speter 54118334Speter ddprintf(("type: 0x%x, index: %d", vap->va_type, vap->va_index)); 54218334Speter 543169689Skan vap->va_namelen = rap->a_hdr.a_namelen; 544169689Skan if (rap->a_hdr.a_namelen) { 545169689Skan wchar *unp = (wchar *) ((caddr_t) rap + rap->a_hdr.a_nameoff); 546169689Skan ddprintf((", name:[")); 547169689Skan for (i = 0; i < vap->va_namelen; i++) { 548258748Spfg vap->va_name[i] = unp[i]; 549258748Spfg ddprintf(("%c", vap->va_name[i])); 550258748Spfg } 551258748Spfg ddprintf(("]")); 552258748Spfg } 553258748Spfg if (vap->va_flag & NTFS_AF_INRUN) { 554169689Skan ddprintf((", nonres.")); 555169689Skan vap->va_datalen = rap->a_nr.a_datalen; 556169689Skan vap->va_allocated = rap->a_nr.a_allocated; 557169689Skan vap->va_vcnstart = rap->a_nr.a_vcnstart; 558132718Skan vap->va_vcnend = rap->a_nr.a_vcnend; 55918334Speter vap->va_compressalg = rap->a_nr.a_compressalg; 56090075Sobrien error = ntfs_runtovrun(&(vap->va_vruncn), &(vap->va_vruncl), 56118334Speter &(vap->va_vruncnt), 56218334Speter (caddr_t) rap + rap->a_nr.a_dataoff); 563169689Skan } else { 56418334Speter vap->va_compressalg = 0; 565169689Skan ddprintf((", res.")); 56690075Sobrien vap->va_datalen = rap->a_r.a_datalen; 56718334Speter vap->va_allocated = rap->a_r.a_datalen; 56890075Sobrien vap->va_vcnstart = 0; 56990075Sobrien vap->va_vcnend = ntfs_btocn(vap->va_allocated); 57018334Speter MALLOC(vap->va_datap, caddr_t, vap->va_datalen, 571169689Skan M_NTFSRDATA, M_WAITOK); 57290075Sobrien memcpy(vap->va_datap, (caddr_t) rap + rap->a_r.a_dataoff, 57390075Sobrien rap->a_r.a_datalen); 57450397Sobrien } 57518334Speter ddprintf((", len: %d", vap->va_datalen)); 57618334Speter 577169689Skan if (error) 57818334Speter FREE(vap, M_NTFSNTVATTR); 579169689Skan else 58018334Speter *rvapp = vap; 58172562Sobrien 582169689Skan ddprintf(("\n")); 58372562Sobrien 58472562Sobrien return (error); 58572562Sobrien} 58672562Sobrien 58790075Sobrien/* 58872562Sobrien * Expand run into more utilizable and more memory eating format. 58972562Sobrien */ 59072562Sobrienint 59172562Sobrienntfs_runtovrun( 59272562Sobrien cn_t ** rcnp, 59372562Sobrien cn_t ** rclp, 59472562Sobrien u_long * rcntp, 59572562Sobrien u_int8_t * run) 59672562Sobrien{ 59772562Sobrien u_int32_t off; 59872562Sobrien u_int32_t sz, i; 59972562Sobrien cn_t *cn; 60072562Sobrien cn_t *cl; 601169689Skan u_long cnt; 602169689Skan cn_t prev; 603169689Skan cn_t tmp; 604169689Skan 60518334Speter off = 0; 60618334Speter cnt = 0; 60718334Speter i = 0; 60818334Speter while (run[off]) { 60918334Speter off += (run[off] & 0xF) + ((run[off] >> 4) & 0xF) + 1; 61090075Sobrien cnt++; 61190075Sobrien } 61218334Speter MALLOC(cn, cn_t *, cnt * sizeof(cn_t), M_NTFSRUN, M_WAITOK); 61318334Speter MALLOC(cl, cn_t *, cnt * sizeof(cn_t), M_NTFSRUN, M_WAITOK); 614169689Skan 61518334Speter off = 0; 61690075Sobrien cnt = 0; 61790075Sobrien prev = 0; 61890075Sobrien while (run[off]) { 61918334Speter 620169689Skan sz = run[off++]; 621169689Skan cl[cnt] = 0; 62290075Sobrien 623169689Skan for (i = 0; i < (sz & 0xF); i++) 62452284Sobrien cl[cnt] += (u_int32_t) run[off++] << (i << 3); 62518334Speter 62690075Sobrien sz >>= 4; 62750397Sobrien if (run[off + sz - 1] & 0x80) { 628169689Skan tmp = ((u_int64_t) - 1) << (sz << 3); 629169689Skan for (i = 0; i < sz; i++) 63018334Speter tmp |= (u_int64_t) run[off++] << (i << 3); 631169689Skan } else { 63218334Speter tmp = 0; 633169689Skan for (i = 0; i < sz; i++) 634169689Skan tmp |= (u_int64_t) run[off++] << (i << 3); 635169689Skan } 636169689Skan if (tmp) 637169689Skan prev = cn[cnt] = prev + tmp; 638169689Skan else 639169689Skan cn[cnt] = tmp; 640169689Skan 641169689Skan cnt++; 642169689Skan } 643169689Skan *rcnp = cn; 644169689Skan *rclp = cl; 645169689Skan *rcntp = cnt; 646169689Skan return (0); 647169689Skan} 648169689Skan 649169689Skan/* 650169689Skan * Convert wchar to uppercase wchar, should be macros? 651169689Skan */ 652169689Skanwchar 65318334Speterntfs_toupper( 65450397Sobrien struct ntfsmount * ntmp, 65550397Sobrien wchar wc) 65650397Sobrien{ 65750397Sobrien return (ntmp->ntm_upcase[wc & 0xFF]); 65850397Sobrien} 65950397Sobrien 66050397Sobrien/* 661169689Skan * Compare to unicode strings case insensible. 662169689Skan */ 663169689Skanint 664169689Skanntfs_uustricmp( 665169689Skan struct ntfsmount * ntmp, 666169689Skan wchar * str1, 667169689Skan int str1len, 66818334Speter wchar * str2, 66918334Speter int str2len) 67018334Speter{ 67118334Speter int i; 67218334Speter int res; 67318334Speter 67418334Speter for (i = 0; i < str1len && i < str2len; i++) { 67518334Speter res = (int) ntfs_toupper(ntmp, str1[i]) - 67618334Speter (int) ntfs_toupper(ntmp, str2[i]); 677132718Skan if (res) 67818334Speter return res; 67918334Speter } 68090075Sobrien return (str1len - str2len); 68118334Speter} 68218334Speter 68318334Speter/* 68418334Speter * Compare unicode and ascii string case insens. 68518334Speter */ 68618334Speterint 68718334Speterntfs_uastricmp( 68818334Speter struct ntfsmount * ntmp, 68918334Speter const wchar *str1, 69018334Speter int str1len, 69118334Speter const char *str2, 69218334Speter int str2len) 69318334Speter{ 69418334Speter int i; 69518334Speter int res; 69618334Speter 697169689Skan for (i = 0; i < str1len && i < str2len; i++) { 69818334Speter res = (int) ntfs_toupper(ntmp, str1[i]) - 699169689Skan (int) ntfs_toupper(ntmp, (wchar) str2[i]); 700169689Skan if (res) 701169689Skan return res; 702169689Skan } 703169689Skan return (str1len - str2len); 70418334Speter} 705169689Skan 706169689Skan/* 70718334Speter * Compare unicode and ascii string case sens. 708169689Skan */ 70918334Speterint 710169689Skanntfs_uastrcmp( 711169689Skan struct ntfsmount *ntmp, 71290075Sobrien const wchar *str1, 713169689Skan int str1len, 714169689Skan const char *str2, 715169689Skan int str2len) 716169689Skan{ 717169689Skan int i; 718169689Skan int res; 719169689Skan 720169689Skan for (i = 0; (i < str1len) && (i < str2len); i++) { 721169689Skan res = ((int) str1[i]) - ((int) str2[i]); 722169689Skan if (res) 723169689Skan return res; 724169689Skan } 725169689Skan return (str1len - str2len); 726169689Skan} 727169689Skan 728169689Skan/* 729169689Skan * Search fnode in ntnode, if not found allocate and preinitialize. 730169689Skan * 731169689Skan * ntnode should be locked on entry. 732169689Skan */ 733169689Skanint 734169689Skanntfs_fget( 735169689Skan struct ntfsmount *ntmp, 736169689Skan struct ntnode *ip, 737169689Skan int attrtype, 738169689Skan char *attrname, 739169689Skan struct fnode **fpp) 740169689Skan{ 741169689Skan struct fnode *fp; 742169689Skan 743169689Skan dprintf(("ntfs_fget: ino: %d, attrtype: 0x%x, attrname: %s\n", 744169689Skan ip->i_number,attrtype, attrname?attrname:"")); 745169689Skan *fpp = NULL; 746169689Skan for (fp = ip->i_fnlist.lh_first; fp != NULL; fp = fp->f_fnlist.le_next){ 747169689Skan dprintf(("ntfs_fget: fnode: attrtype: %d, attrname: %s\n", 748169689Skan fp->f_attrtype, fp->f_attrname?fp->f_attrname:"")); 749169689Skan 750169689Skan if ((attrtype == fp->f_attrtype) && 751169689Skan ((!attrname && !fp->f_attrname) || 752169689Skan (attrname && fp->f_attrname && 753169689Skan !strcmp(attrname,fp->f_attrname)))){ 754169689Skan dprintf(("ntfs_fget: found existed: %p\n",fp)); 755169689Skan *fpp = fp; 756169689Skan } 757169689Skan } 758169689Skan 759169689Skan if (*fpp) 760169689Skan return (0); 761169689Skan 762169689Skan MALLOC(fp, struct fnode *, sizeof(struct fnode), M_NTFSFNODE, M_WAITOK); 763169689Skan bzero(fp, sizeof(struct fnode)); 764169689Skan dprintf(("ntfs_fget: allocating fnode: %p\n",fp)); 765169689Skan 766169689Skan fp->f_devvp = ntmp->ntm_devvp; 767169689Skan fp->f_dev = ntmp->ntm_dev; 768169689Skan fp->f_mp = ntmp; 769169689Skan 770169689Skan fp->f_ip = ip; 771169689Skan fp->f_attrname = attrname; 772169689Skan if (fp->f_attrname) fp->f_flag |= FN_AATTRNAME; 773169689Skan fp->f_attrtype = attrtype; 774169689Skan 775169689Skan ntfs_ntref(ip); 776169689Skan 777169689Skan LIST_INSERT_HEAD(&ip->i_fnlist, fp, f_fnlist); 778169689Skan 779169689Skan *fpp = fp; 780169689Skan 781169689Skan return (0); 782169689Skan} 783169689Skan 784169689Skan/* 785169689Skan * Deallocate fnode, remove it from ntnode's fnode list. 786169689Skan * 787169689Skan * ntnode should be locked. 788169689Skan */ 789169689Skanvoid 790169689Skanntfs_frele( 791169689Skan struct fnode *fp) 792169689Skan{ 793169689Skan struct ntnode *ip = FTONT(fp); 794169689Skan 795169689Skan dprintf(("ntfs_frele: fnode: %p for %d: %p\n", fp, ip->i_number, ip)); 796169689Skan 797169689Skan dprintf(("ntfs_frele: deallocating fnode\n")); 798169689Skan LIST_REMOVE(fp,f_fnlist); 799169689Skan if (fp->f_flag & FN_AATTRNAME) 800169689Skan FREE(fp->f_attrname, M_TEMP); 801169689Skan if (fp->f_dirblbuf) 802169689Skan FREE(fp->f_dirblbuf, M_NTFSDIR); 803169689Skan FREE(fp, M_NTFSFNODE); 804169689Skan ntfs_ntrele(ip); 805169689Skan} 806169689Skan 807169689Skan/* 808169689Skan * Lookup attribute name in format: [[:$ATTR_TYPE]:$ATTR_NAME], 809169689Skan * $ATTR_TYPE is searched in attrdefs read from $AttrDefs. 810169689Skan * If $ATTR_TYPE nott specifed, ATTR_A_DATA assumed. 811169689Skan */ 812169689Skanint 813169689Skanntfs_ntlookupattr( 814169689Skan struct ntfsmount * ntmp, 815169689Skan const char * name, 816169689Skan int namelen, 817169689Skan int *attrtype, 818169689Skan char **attrname) 819169689Skan{ 820169689Skan const char *sys; 821169689Skan size_t syslen, i; 822169689Skan struct ntvattrdef *adp; 823169689Skan 824169689Skan if (namelen == 0) 825169689Skan return (0); 826169689Skan 827169689Skan if (name[0] == '$') { 828169689Skan sys = name; 829169689Skan for (syslen = 0; syslen < namelen; syslen++) { 830169689Skan if(sys[syslen] == ':') { 831169689Skan name++; 832169689Skan namelen--; 833169689Skan break; 834169689Skan } 835169689Skan } 836169689Skan name += syslen; 837169689Skan namelen -= syslen; 838169689Skan 839169689Skan adp = ntmp->ntm_ad; 840169689Skan for (i = 0; i < ntmp->ntm_adnum; i++){ 841169689Skan if((syslen == adp->ad_namelen) && 842169689Skan (!strncmp(sys,adp->ad_name,syslen))) { 843169689Skan *attrtype = adp->ad_type; 844169689Skan if(namelen) { 845169689Skan MALLOC((*attrname), char *, namelen, 846169689Skan M_TEMP, M_WAITOK); 847169689Skan memcpy((*attrname), name, namelen); 848169689Skan (*attrname)[namelen] = '\0'; 849169689Skan } 850169689Skan return (0); 851169689Skan } 852169689Skan adp++; 853169689Skan } 854169689Skan return (ENOENT); 855169689Skan } 856169689Skan 857169689Skan if(namelen) { 858169689Skan MALLOC((*attrname), char *, namelen, M_TEMP, M_WAITOK); 859169689Skan memcpy((*attrname), name, namelen); 860169689Skan (*attrname)[namelen] = '\0'; 861169689Skan *attrtype = NTFS_A_DATA; 862169689Skan } 863169689Skan 864169689Skan return (0); 865169689Skan} 866169689Skan 867169689Skan/* 868169689Skan * Lookup specifed node for filename, matching cnp, 869169689Skan * return fnode filled. 870169689Skan */ 871169689Skanint 872169689Skanntfs_ntlookupfile( 873169689Skan struct ntfsmount * ntmp, 874169689Skan struct vnode * vp, 875169689Skan struct componentname * cnp, 876169689Skan struct vnode ** vpp) 877169689Skan{ 878169689Skan struct fnode *fp = VTOF(vp); 879169689Skan struct ntnode *ip = FTONT(fp); 880169689Skan struct ntvattr *vap; /* Root attribute */ 881169689Skan cn_t cn; /* VCN in current attribute */ 882169689Skan caddr_t rdbuf; /* Buffer to read directory's blocks */ 883169689Skan u_int32_t blsize; 884169689Skan u_int32_t rdsize; /* Length of data to read from current block */ 885169689Skan struct attr_indexentry *iep; 886169689Skan int error, res, anamelen, fnamelen; 887169689Skan const char *fname,*aname; 888169689Skan u_int32_t aoff; 889169689Skan 890169689Skan error = ntfs_ntget(ip); 891169689Skan if (error) 892169689Skan return (error); 893169689Skan 894169689Skan error = ntfs_ntvattrget(ntmp, ip, NTFS_A_INDXROOT, "$I30", 0, &vap); 895169689Skan if (error || (vap->va_flag & NTFS_AF_INRUN)) 896169689Skan return (ENOTDIR); 897169689Skan 898169689Skan blsize = vap->va_a_iroot->ir_size; 899169689Skan rdsize = vap->va_datalen; 900169689Skan 901169689Skan /* 902169689Skan * Divide file name into: foofilefoofilefoofile[:attrspec] 903169689Skan * Store like this: fname:fnamelen [aname:anamelen] 904169689Skan */ 905169689Skan fname = cnp->cn_nameptr; 906169689Skan aname = NULL; 907169689Skan anamelen = 0; 908169689Skan for (fnamelen = 0; fnamelen < cnp->cn_namelen; fnamelen++) 90918334Speter if(fname[fnamelen] == ':') { 91018334Speter aname = fname + fnamelen + 1; 91118334Speter anamelen = cnp->cn_namelen - fnamelen - 1; 912169689Skan dprintf(("ntfs_ntlookupfile: %s (%d), attr: %s (%d)\n", 913169689Skan fname, fnamelen, aname, anamelen)); 914169689Skan break; 915169689Skan } 916169689Skan 917169689Skan dprintf(("ntfs_ntlookupfile: blksz: %d, rdsz: %d\n", blsize, rdsize)); 918169689Skan 919169689Skan MALLOC(rdbuf, caddr_t, blsize, M_TEMP, M_WAITOK); 920169689Skan 921169689Skan error = ntfs_readattr(ntmp, ip, NTFS_A_INDXROOT, "$I30", 922169689Skan 0, rdsize, rdbuf); 923169689Skan if (error) 924169689Skan goto fail; 925169689Skan 926169689Skan aoff = sizeof(struct attr_indexroot); 927169689Skan 928169689Skan do { 929169689Skan iep = (struct attr_indexentry *) (rdbuf + aoff); 930169689Skan 931169689Skan while (!(iep->ie_flag & NTFS_IEFLAG_LAST) && (rdsize > aoff)) { 932169689Skan ddprintf(("scan: %d, %d\n", 933169689Skan (u_int32_t) iep->ie_number, 934169689Skan (u_int32_t) iep->ie_fnametype)); 935169689Skan res = ntfs_uastricmp(ntmp, iep->ie_fname, 936169689Skan iep->ie_fnamelen, fname, 937169689Skan fnamelen); 938169689Skan if (res == 0) { 939169689Skan /* Matched something (case ins.) */ 940169689Skan if (iep->ie_fnametype == 0 || 941169689Skan !(ntmp->ntm_flag & NTFS_MFLAG_CASEINS)) 942169689Skan res = ntfs_uastrcmp(ntmp, 943169689Skan iep->ie_fname, 944169689Skan iep->ie_fnamelen, 945169689Skan fname, 946169689Skan fnamelen); 947169689Skan if (res == 0) { 948169689Skan int attrtype = NTFS_A_DATA; 949169689Skan char *attrname = NULL; 950169689Skan struct fnode *nfp; 951169689Skan struct vnode *nvp; 952169689Skan 953169689Skan if (aname) { 954169689Skan error = ntfs_ntlookupattr(ntmp, 955169689Skan aname, anamelen, 956169689Skan &attrtype, &attrname); 957169689Skan if (error) 958169689Skan goto fail; 959169689Skan } 960169689Skan 961169689Skan /* Check if we've found ourself */ 96296263Sobrien if ((iep->ie_number == ip->i_number) && 963169689Skan (attrtype == fp->f_attrtype) && 96496263Sobrien ((!attrname && !fp->f_attrname) || 96596263Sobrien (attrname && fp->f_attrname && 966132718Skan !strcmp(attrname, fp->f_attrname)))) { 96796263Sobrien VREF(vp); 96896263Sobrien *vpp = vp; 96996263Sobrien goto fail; 97096263Sobrien } 97196263Sobrien 97296263Sobrien /* vget node, but don't load it */ 97396263Sobrien error = ntfs_vgetex(ntmp->ntm_mountp, 97496263Sobrien iep->ie_number, 97596263Sobrien attrtype, 97696263Sobrien attrname, 97796263Sobrien LK_EXCLUSIVE, 97896263Sobrien VG_DONTLOADIN | 97996263Sobrien VG_DONTVALIDFN, 980169689Skan curproc, 981169689Skan &nvp); 982169689Skan if(error) 983169689Skan goto fail; 98496263Sobrien 98596263Sobrien nfp = VTOF(nvp); 98696263Sobrien 987117395Skan if (nfp->f_flag & FN_VALID) { 98896263Sobrien *vpp = nvp; 98996263Sobrien goto fail; 99096263Sobrien } 99196263Sobrien 99296263Sobrien nfp->f_fflag = iep->ie_fflag; 99396263Sobrien nfp->f_pnumber = iep->ie_fpnumber; 994169689Skan nfp->f_times = iep->ie_ftimes; 995169689Skan 996169689Skan if((nfp->f_fflag & NTFS_FFLAG_DIR) && 997169689Skan (nfp->f_attrtype == NTFS_A_DATA) && 998169689Skan (nfp->f_attrname == NULL)) 999169689Skan nfp->f_type = VDIR; 1000169689Skan else 1001169689Skan nfp->f_type = VREG; 1002169689Skan 1003169689Skan nvp->v_type = nfp->f_type; 1004169689Skan 1005169689Skan if ((nfp->f_attrtype == NTFS_A_DATA) && 1006169689Skan (nfp->f_attrname == NULL)) { 1007169689Skan /* Opening default attribute */ 1008169689Skan nfp->f_size = iep->ie_fsize; 1009132718Skan nfp->f_allocated = iep->ie_fallocated; 1010169689Skan nfp->f_flag |= FN_PRELOADED; 1011132718Skan } else { 1012169689Skan error = ntfs_filesize(ntmp, nfp, 1013132718Skan &nfp->f_size, 1014132718Skan &nfp->f_allocated); 1015132718Skan if (error) { 1016132718Skan vput(nvp); 1017169689Skan goto fail; 1018169689Skan } 1019132718Skan } 1020169689Skan 1021169689Skan nfp->f_flag &= ~FN_VALID; 1022169689Skan *vpp = nvp; 1023169689Skan goto fail; 1024169689Skan } 1025169689Skan } else if (res > 0) 1026169689Skan break; 1027169689Skan 1028169689Skan aoff += iep->reclen; 1029169689Skan iep = (struct attr_indexentry *) (rdbuf + aoff); 1030169689Skan } 1031169689Skan 1032169689Skan /* Dive if possible */ 1033169689Skan if (iep->ie_flag & NTFS_IEFLAG_SUBNODE) { 1034169689Skan dprintf(("ntfs_ntlookupfile: diving\n")); 1035169689Skan 1036169689Skan cn = *(cn_t *) (rdbuf + aoff + 1037169689Skan iep->reclen - sizeof(cn_t)); 1038169689Skan rdsize = blsize; 1039169689Skan 1040169689Skan error = ntfs_readattr(ntmp, ip, NTFS_A_INDX, "$I30", 1041169689Skan ntfs_cntob(cn), rdsize, rdbuf); 1042169689Skan if (error) 1043169689Skan goto fail; 1044169689Skan 1045169689Skan error = ntfs_procfixups(ntmp, NTFS_INDXMAGIC, 1046169689Skan rdbuf, rdsize); 1047169689Skan if (error) 1048169689Skan goto fail; 1049132718Skan 1050132718Skan aoff = (((struct attr_indexalloc *) rdbuf)->ia_hdrsize + 1051169689Skan 0x18); 1052169689Skan } else { 1053169689Skan dprintf(("ntfs_ntlookupfile: nowhere to dive :-(\n")); 1054169689Skan error = ENOENT; 1055169689Skan break; 1056169689Skan } 1057169689Skan } while (1); 1058169689Skan 1059169689Skan dprintf(("finish\n")); 1060169689Skan 1061132718Skanfail: 1062132718Skan ntfs_ntvattrrele(vap); 1063169689Skan ntfs_ntput(ip); 1064169689Skan FREE(rdbuf, M_TEMP); 1065169689Skan return (error); 1066132718Skan} 1067132718Skan 1068169689Skan/* 106918334Speter * Check if name type is permitted to show. 107018334Speter */ 107118334Speterint 1072132718Skanntfs_isnamepermitted( 107318334Speter struct ntfsmount * ntmp, 107418334Speter struct attr_indexentry * iep) 1075117395Skan{ 107618334Speter 107718334Speter if (ntmp->ntm_flag & NTFS_MFLAG_ALLNAMES) 1078117395Skan return 1; 1079117395Skan 108018334Speter switch (iep->ie_fnametype) { 108118334Speter case 2: 1082117395Skan ddprintf(("ntfs_isnamepermitted: skiped DOS name\n")); 1083117395Skan return 0; 1084117395Skan case 0: case 1: case 3: 108518334Speter return 1; 1086117395Skan default: 108718334Speter printf("ntfs_isnamepermitted: " \ 108818334Speter "WARNING! Unknown file name type: %d\n", 108918334Speter iep->ie_fnametype); 109018334Speter break; 109118334Speter } 109218334Speter return 0; 109318334Speter} 109418334Speter 1095132718Skan/* 109618334Speter * Read ntfs dir like stream of attr_indexentry, not like btree of them. 109718334Speter * This is done by scaning $BITMAP:$I30 for busy clusters and reading them. 109818334Speter * Ofcouse $INDEX_ROOT:$I30 is read before. Last read values are stored in 109990075Sobrien * fnode, so we can skip toward record number num almost immediatly. 110090075Sobrien * Anyway this is rather slow routine. The problem is that we don't know 1101132718Skan * how many records are there in $INDEX_ALLOCATION:$I30 block. 110290075Sobrien */ 1103132718Skanint 1104132718Skanntfs_ntreaddir( 1105169689Skan struct ntfsmount * ntmp, 110618334Speter struct fnode * fp, 110718334Speter u_int32_t num, 110818334Speter struct attr_indexentry ** riepp) 110990075Sobrien{ 1110117395Skan struct ntnode *ip = FTONT(fp); 111118334Speter struct ntvattr *vap = NULL; /* IndexRoot attribute */ 111218334Speter struct ntvattr *bmvap = NULL; /* BitMap attribute */ 1113132718Skan struct ntvattr *iavap = NULL; /* IndexAllocation attribute */ 111418334Speter caddr_t rdbuf; /* Buffer to read directory's blocks */ 111518334Speter u_char *bmp = NULL; /* Bitmap */ 111618334Speter u_int32_t blsize; /* Index allocation size (2048) */ 111718334Speter u_int32_t rdsize; /* Length of data to read */ 1118117395Skan u_int32_t attrnum; /* Current attribute type */ 111918334Speter u_int32_t cpbl = 1; /* Clusters per directory block */ 1120117395Skan u_int32_t blnum; 1121117395Skan struct attr_indexentry *iep; 112218334Speter int error = ENOENT; 112318334Speter u_int32_t aoff, cnum; 112418334Speter 112518334Speter dprintf(("ntfs_ntreaddir: read ino: %d, num: %d\n", ip->i_number, num)); 112618334Speter error = ntfs_ntget(ip); 112718334Speter if (error) 112818334Speter return (error); 112918334Speter 1130132718Skan error = ntfs_ntvattrget(ntmp, ip, NTFS_A_INDXROOT, "$I30", 0, &vap); 113118334Speter if (error) 1132169689Skan return (ENOTDIR); 1133169689Skan 113418334Speter if (fp->f_dirblbuf == NULL) { 1135169689Skan fp->f_dirblsz = vap->va_a_iroot->ir_size; 1136169689Skan MALLOC(fp->f_dirblbuf, caddr_t, 1137169689Skan max(vap->va_datalen,fp->f_dirblsz), M_NTFSDIR, M_WAITOK); 1138169689Skan } 1139169689Skan 1140169689Skan blsize = fp->f_dirblsz; 1141169689Skan rdbuf = fp->f_dirblbuf; 1142169689Skan 1143169689Skan dprintf(("ntfs_ntreaddir: rdbuf: 0x%p, blsize: %d\n", rdbuf, blsize)); 1144169689Skan 1145169689Skan if (vap->va_a_iroot->ir_flag & NTFS_IRFLAG_INDXALLOC) { 1146169689Skan error = ntfs_ntvattrget(ntmp, ip, NTFS_A_INDXBITMAP, "$I30", 1147169689Skan 0, &bmvap); 1148169689Skan if (error) { 114918334Speter error = ENOTDIR; 1150169689Skan goto fail; 1151169689Skan } 115290075Sobrien MALLOC(bmp, u_char *, bmvap->va_datalen, M_TEMP, M_WAITOK); 115318334Speter error = ntfs_readattr(ntmp, ip, NTFS_A_INDXBITMAP, "$I30", 0, 115418334Speter bmvap->va_datalen, bmp); 115518334Speter if (error) 115618334Speter goto fail; 115718334Speter 115850397Sobrien error = ntfs_ntvattrget(ntmp, ip, NTFS_A_INDX, "$I30", 115950397Sobrien 0, &iavap); 116018334Speter if (error) { 116118334Speter error = ENOTDIR; 1162132718Skan goto fail; 116318334Speter } 116490075Sobrien cpbl = ntfs_btocn(blsize + ntfs_cntob(1) - 1); 116518334Speter dprintf(("ntfs_ntreaddir: indexalloc: %d, cpbl: %d\n", 116618334Speter iavap->va_datalen, cpbl)); 116718334Speter } else { 116850397Sobrien dprintf(("ntfs_ntreadidir: w/o BitMap and IndexAllocation\n")); 116918334Speter iavap = bmvap = NULL; 117018334Speter bmp = NULL; 117118334Speter } 117218334Speter 117318334Speter /* Try use previous values */ 117418334Speter if ((fp->f_lastdnum < num) && (fp->f_lastdnum != 0)) { 1175169689Skan attrnum = fp->f_lastdattr; 1176169689Skan aoff = fp->f_lastdoff; 1177169689Skan blnum = fp->f_lastdblnum; 1178169689Skan cnum = fp->f_lastdnum; 1179169689Skan } else { 1180169689Skan attrnum = NTFS_A_INDXROOT; 1181169689Skan aoff = sizeof(struct attr_indexroot); 1182169689Skan blnum = 0; 1183169689Skan cnum = 0; 1184169689Skan } 1185169689Skan 1186169689Skan do { 1187169689Skan dprintf(("ntfs_ntreaddir: scan: 0x%x, %d, %d, %d, %d\n", 1188169689Skan attrnum, (u_int32_t) blnum, cnum, num, aoff)); 1189169689Skan rdsize = (attrnum == NTFS_A_INDXROOT) ? vap->va_datalen : blsize; 1190169689Skan error = ntfs_readattr(ntmp, ip, attrnum, "$I30", 1191169689Skan ntfs_cntob(blnum * cpbl), rdsize, rdbuf); 1192169689Skan if (error) 1193169689Skan goto fail; 1194169689Skan 1195169689Skan if (attrnum == NTFS_A_INDX) { 1196169689Skan error = ntfs_procfixups(ntmp, NTFS_INDXMAGIC, 1197169689Skan rdbuf, rdsize); 1198169689Skan if (error) 1199169689Skan goto fail; 1200169689Skan } 1201169689Skan if (aoff == 0) 1202169689Skan aoff = (attrnum == NTFS_A_INDX) ? 1203169689Skan (0x18 + ((struct attr_indexalloc *) rdbuf)->ia_hdrsize) : 1204169689Skan sizeof(struct attr_indexroot); 1205169689Skan 1206169689Skan iep = (struct attr_indexentry *) (rdbuf + aoff); 1207169689Skan while (!(iep->ie_flag & NTFS_IEFLAG_LAST) && (rdsize > aoff)) { 1208169689Skan if (ntfs_isnamepermitted(ntmp, iep)) { 1209169689Skan if (cnum >= num) { 1210169689Skan fp->f_lastdnum = cnum; 1211169689Skan fp->f_lastdoff = aoff; 1212169689Skan fp->f_lastdblnum = blnum; 1213169689Skan fp->f_lastdattr = attrnum; 1214169689Skan 1215169689Skan *riepp = iep; 1216169689Skan 1217169689Skan error = 0; 1218169689Skan goto fail; 1219169689Skan } 1220169689Skan cnum++; 1221169689Skan } 1222169689Skan aoff += iep->reclen; 1223169689Skan iep = (struct attr_indexentry *) (rdbuf + aoff); 1224169689Skan } 1225169689Skan 1226169689Skan if (iavap) { 1227169689Skan if (attrnum == NTFS_A_INDXROOT) 1228169689Skan blnum = 0; 1229169689Skan else 1230169689Skan blnum++; 1231169689Skan 1232169689Skan while (ntfs_cntob(blnum * cpbl) < iavap->va_datalen) { 1233169689Skan if (bmp[blnum >> 3] & (1 << (blnum & 3))) 1234169689Skan break; 1235169689Skan blnum++; 1236169689Skan } 1237169689Skan 1238169689Skan attrnum = NTFS_A_INDX; 1239169689Skan aoff = 0; 1240169689Skan if (ntfs_cntob(blnum * cpbl) >= iavap->va_datalen) 1241169689Skan break; 124218334Speter dprintf(("ntfs_ntreaddir: blnum: %d\n", (u_int32_t) blnum)); 124350397Sobrien } 124418334Speter } while (iavap); 1245169689Skan 124618334Speter *riepp = NULL; 124790075Sobrien fp->f_lastdnum = 0; 1248117395Skan 124918334Speterfail: 125018334Speter if (vap) 1251117395Skan ntfs_ntvattrrele(vap); 1252117395Skan if (bmvap) 125318334Speter ntfs_ntvattrrele(bmvap); 125418334Speter if (iavap) 1255169689Skan ntfs_ntvattrrele(iavap); 125618334Speter if (bmp) 1257132718Skan FREE(bmp, M_TEMP); 1258169689Skan ntfs_ntput(ip); 125918334Speter return (error); 126018334Speter} 126118334Speter 126218334Speter/* 126318334Speter * Convert NTFS times that are in 100 ns units and begins from 126418334Speter * 1601 Jan 1 into unix times. 126518334Speter */ 126618334Speterstruct timespec 126718334Speterntfs_nttimetounix( 126818334Speter u_int64_t nt) 1269132718Skan{ 127018334Speter struct timespec t; 127118334Speter 127218334Speter /* WindowNT times are in 100 ns and from 1601 Jan 1 */ 127318334Speter t.tv_nsec = (nt % (1000 * 1000 * 10)) * 100; 127418334Speter t.tv_sec = nt / (1000 * 1000 * 10) - 127518334Speter 369LL * 365LL * 24LL * 60LL * 60LL - 127618334Speter 89LL * 1LL * 24LL * 60LL * 60LL; 127718334Speter return (t); 127818334Speter} 127918334Speter 128018334Speter/* 128118334Speter * Get file times from NTFS_A_NAME attribute. 128218334Speter */ 128318334Speterint 128418334Speterntfs_times( 1285132718Skan struct ntfsmount * ntmp, 128618334Speter struct ntnode * ip, 128718334Speter ntfs_times_t * tm) 128818334Speter{ 128918334Speter struct ntvattr *vap; 129018334Speter int error; 129118334Speter 129218334Speter dprintf(("ntfs_times: ino: %d...\n", ip->i_number)); 129318334Speter 129418334Speter error = ntfs_ntget(ip); 129518334Speter if (error) 129618334Speter return (error); 129718334Speter 129818334Speter error = ntfs_ntvattrget(ntmp, ip, NTFS_A_NAME, NULL, 0, &vap); 129918334Speter if (error) { 130018334Speter ntfs_ntput(ip); 1301132718Skan return (error); 130218334Speter } 130390075Sobrien *tm = vap->va_a_name->n_times; 130490075Sobrien ntfs_ntvattrrele(vap); 130518334Speter ntfs_ntput(ip); 130618334Speter 130718334Speter return (0); 130818334Speter} 130918334Speter 131018334Speter/* 131118334Speter * Get file sizes from corresponding attribute. 131218334Speter * 1313169689Skan * ntnode under fnode should be locked. 131418334Speter */ 131518334Speterint 1316169689Skanntfs_filesize( 1317169689Skan struct ntfsmount * ntmp, 1318169689Skan struct fnode * fp, 1319169689Skan u_int64_t * size, 132018334Speter u_int64_t * bytes) 1321169689Skan{ 132218334Speter struct ntvattr *vap; 132318334Speter struct ntnode *ip = FTONT(fp); 132418334Speter u_int64_t sz, bn; 132518334Speter int error; 132618334Speter 132718334Speter dprintf(("ntfs_filesize: ino: %d\n", ip->i_number)); 132890075Sobrien 132990075Sobrien error = ntfs_ntvattrget(ntmp, ip, 133018334Speter fp->f_attrtype, fp->f_attrname, 0, &vap); 133118334Speter if (error) 133218334Speter return (error); 1333169689Skan 1334169689Skan bn = vap->va_allocated; 1335169689Skan sz = vap->va_datalen; 133618334Speter 133718334Speter dprintf(("ntfs_filesize: %d bytes (%d bytes allocated)\n", 133818334Speter (u_int32_t) sz, (u_int32_t) bn)); 133918334Speter 134018334Speter if (size) 134118334Speter *size = sz; 134290075Sobrien if (bytes) 134390075Sobrien *bytes = bn; 134418334Speter 134518334Speter ntfs_ntvattrrele(vap); 134690075Sobrien 134718334Speter return (0); 134818334Speter} 134918334Speter 135018334Speter/* 135118334Speter * This is one of write routine. 135218334Speter * 1353132718Skan * ntnode should be locked. 135418334Speter */ 135550397Sobrienint 135618334Speterntfs_writeattr_plain( 135718334Speter struct ntfsmount * ntmp, 135818334Speter struct ntnode * ip, 135918334Speter u_int32_t attrnum, 136018334Speter char *attrname, 136118334Speter off_t roff, 136218334Speter size_t rsize, 136318334Speter void *rdata, 136418334Speter size_t * initp) 1365169689Skan{ 136618334Speter size_t init; 136718334Speter int error = 0; 136850397Sobrien off_t off = roff, left = rsize, towrite; 136950397Sobrien caddr_t data = rdata; 137018334Speter struct ntvattr *vap; 137118334Speter *initp = 0; 137218334Speter 137350397Sobrien while (left) { 137450397Sobrien error = ntfs_ntvattrget(ntmp, ip, attrnum, attrname, 137550397Sobrien ntfs_btocn(off), &vap); 137650397Sobrien if (error) 137750397Sobrien return (error); 137850397Sobrien towrite = min(left, ntfs_cntob(vap->va_vcnend + 1) - off); 137950397Sobrien ddprintf(("ntfs_writeattr_plain: o: %d, s: %d (%d - %d)\n", 138050397Sobrien (u_int32_t) off, (u_int32_t) towrite, 138150397Sobrien (u_int32_t) vap->va_vcnstart, 138250397Sobrien (u_int32_t) vap->va_vcnend)); 138350397Sobrien error = ntfs_writentvattr_plain(ntmp, ip, vap, 138450397Sobrien off - ntfs_cntob(vap->va_vcnstart), 138550397Sobrien towrite, data, &init); 138650397Sobrien if (error) { 138718334Speter printf("ntfs_writeattr_plain: " \ 138818334Speter "ntfs_writentvattr_plain failed: o: %d, s: %d\n", 138918334Speter (u_int32_t) off, (u_int32_t) towrite); 139018334Speter printf("ntfs_writeattr_plain: attrib: %d - %d\n", 139118334Speter (u_int32_t) vap->va_vcnstart, 139218334Speter (u_int32_t) vap->va_vcnend); 139318334Speter ntfs_ntvattrrele(vap); 1394132718Skan break; 1395132718Skan } 1396132718Skan ntfs_ntvattrrele(vap); 1397132718Skan left -= towrite; 1398132718Skan off += towrite; 1399132718Skan data = data + towrite; 1400132718Skan *initp += init; 1401132718Skan } 1402132718Skan 1403132718Skan return (error); 1404132718Skan} 1405132718Skan 1406132718Skan/* 1407132718Skan * This is one of write routine. 1408132718Skan * 1409132718Skan * ntnode should be locked. 141050397Sobrien */ 141150397Sobrienint 141250397Sobrienntfs_writentvattr_plain( 141350397Sobrien struct ntfsmount * ntmp, 1414132718Skan struct ntnode * ip, 141550397Sobrien struct ntvattr * vap, 141650397Sobrien off_t roff, 141750397Sobrien size_t rsize, 141850397Sobrien void *rdata, 141950397Sobrien size_t * initp) 142050397Sobrien{ 142150397Sobrien int error = 0; 142250397Sobrien int off; 142350397Sobrien 142450397Sobrien *initp = 0; 142550397Sobrien if (vap->va_flag & NTFS_AF_INRUN) { 142650397Sobrien int cnt; 142750397Sobrien cn_t ccn, ccl, cn, left, cl; 142850397Sobrien caddr_t data = rdata; 142950397Sobrien struct buf *bp; 143050397Sobrien size_t tocopy; 143150397Sobrien 143250397Sobrien ddprintf(("ntfs_writentvattr_plain: data in run: %d chains\n", 143350397Sobrien vap->va_vruncnt)); 143450397Sobrien 143550397Sobrien off = roff; 143650397Sobrien left = rsize; 143750397Sobrien ccl = 0; 143850397Sobrien ccn = 0; 143950397Sobrien cnt = 0; 144050397Sobrien while (left && (cnt < vap->va_vruncnt)) { 144150397Sobrien ccn = vap->va_vruncn[cnt]; 144250397Sobrien ccl = vap->va_vruncl[cnt]; 144350397Sobrien 144450397Sobrien ddprintf(("ntfs_writentvattr_plain: " \ 144590075Sobrien "left %d, cn: 0x%x, cl: %d, off: %d\n", \ 144650397Sobrien (u_int32_t) left, (u_int32_t) ccn, \ 144750397Sobrien (u_int32_t) ccl, (u_int32_t) off)); 144890075Sobrien 144990075Sobrien if (ntfs_cntob(ccl) < off) { 145090075Sobrien off -= ntfs_cntob(ccl); 145190075Sobrien cnt++; 1452132718Skan continue; 145390075Sobrien } 145490075Sobrien if (ccn || ip->i_number == NTFS_BOOTINO) { /* XXX */ 145590075Sobrien ccl -= ntfs_btocn(off); 145690075Sobrien cn = ccn + ntfs_btocn(off); 145790075Sobrien off = ntfs_btocnoff(off); 145890075Sobrien 145990075Sobrien while (left && ccl) { 146090075Sobrien tocopy = min(left, 146190075Sobrien min(ntfs_cntob(ccl) - off, 146290075Sobrien MAXBSIZE - off)); 146390075Sobrien cl = ntfs_btocl(tocopy + off); 146490075Sobrien ddprintf(("ntfs_writentvattr_plain: " \ 146590075Sobrien "write: cn: 0x%x cl: %d, " \ 146690075Sobrien "off: %d len: %d, left: %d\n", 146790075Sobrien (u_int32_t) cn, 146890075Sobrien (u_int32_t) cl, 146990075Sobrien (u_int32_t) off, 147090075Sobrien (u_int32_t) tocopy, 147190075Sobrien (u_int32_t) left)); 147290075Sobrien if ((off == 0) && 147390075Sobrien (tocopy == ntfs_cntob(cl))) { 147490075Sobrien bp = getblk(ntmp->ntm_devvp, 147590075Sobrien ntfs_cntobn(cn), 147690075Sobrien ntfs_cntob(cl), 147790075Sobrien 0, 0); 147890075Sobrien clrbuf(bp); 147990075Sobrien } else { 148090075Sobrien error = bread(ntmp->ntm_devvp, 148190075Sobrien ntfs_cntobn(cn), 148290075Sobrien ntfs_cntob(cl), 148390075Sobrien NOCRED, &bp); 148490075Sobrien if (error) { 148590075Sobrien brelse(bp); 148690075Sobrien return (error); 148718334Speter } 148818334Speter } 148918334Speter memcpy(bp->b_data + off, data, tocopy); 1490132718Skan bawrite(bp); 149118334Speter data = data + tocopy; 149218334Speter *initp += tocopy; 149318334Speter off = 0; 149418334Speter left -= tocopy; 149518334Speter cn += cl; 149618334Speter ccl -= cl; 149718334Speter } 149818334Speter } 149918334Speter cnt++; 150018334Speter } 150118334Speter if (left) { 150218334Speter printf("ntfs_writentvattr_plain: POSSIBLE RUN ERROR\n"); 150318334Speter error = EINVAL; 1504132718Skan } 150518334Speter } else { 150618334Speter printf("ntfs_writevattr_plain: CAN'T WRITE RES. ATTRIBUTE\n"); 150718334Speter error = ENOTTY; 150818334Speter } 150918334Speter 151018334Speter return (error); 151118334Speter} 151218334Speter 151318334Speter/* 151418334Speter * This is one of read routines. 151518334Speter * 151618334Speter * ntnode should be locked. 151718334Speter */ 1518132718Skanint 151918334Speterntfs_readntvattr_plain( 152018334Speter struct ntfsmount * ntmp, 152118334Speter struct ntnode * ip, 152218334Speter struct ntvattr * vap, 152318334Speter off_t roff, 152418334Speter size_t rsize, 152518334Speter void *rdata, 152618334Speter size_t * initp) 152718334Speter{ 152818334Speter int error = 0; 1529117395Skan int off; 1530117395Skan 1531117395Skan *initp = 0; 1532132718Skan if (vap->va_flag & NTFS_AF_INRUN) { 1533117395Skan int cnt; 1534117395Skan cn_t ccn, ccl, cn, left, cl; 1535117395Skan caddr_t data = rdata; 1536117395Skan struct buf *bp; 1537117395Skan size_t tocopy; 1538117395Skan 1539117395Skan ddprintf(("ntfs_readntvattr_plain: data in run: %d chains\n", 1540117395Skan vap->va_vruncnt)); 1541117395Skan 1542117395Skan off = roff; 154318334Speter left = rsize; 154490075Sobrien ccl = 0; 154518334Speter ccn = 0; 1546132718Skan cnt = 0; 154718334Speter while (left && (cnt < vap->va_vruncnt)) { 154818334Speter ccn = vap->va_vruncn[cnt]; 154918334Speter ccl = vap->va_vruncl[cnt]; 155018334Speter 155118334Speter ddprintf(("ntfs_readntvattr_plain: " \ 155218334Speter "left %d, cn: 0x%x, cl: %d, off: %d\n", \ 155318334Speter (u_int32_t) left, (u_int32_t) ccn, \ 155418334Speter (u_int32_t) ccl, (u_int32_t) off)); 155518334Speter 155618334Speter if (ntfs_cntob(ccl) < off) { 155718334Speter off -= ntfs_cntob(ccl); 155818334Speter cnt++; 155918334Speter continue; 1560132718Skan } 156118334Speter if (ccn || ip->i_number == NTFS_BOOTINO) { 156218334Speter ccl -= ntfs_btocn(off); 156318334Speter cn = ccn + ntfs_btocn(off); 156418334Speter off = ntfs_btocnoff(off); 156518334Speter 156618334Speter while (left && ccl) { 156718334Speter tocopy = min(left, 156818334Speter min(ntfs_cntob(ccl) - off, 156918334Speter MAXBSIZE - off)); 157018334Speter cl = ntfs_btocl(tocopy + off); 157118334Speter ddprintf(("ntfs_readntvattr_plain: " \ 157218334Speter "read: cn: 0x%x cl: %d, " \ 157318334Speter "off: %d len: %d, left: %d\n", 157418334Speter (u_int32_t) cn, 1575132718Skan (u_int32_t) cl, 157618334Speter (u_int32_t) off, 157718334Speter (u_int32_t) tocopy, 157818334Speter (u_int32_t) left)); 157918334Speter error = bread(ntmp->ntm_devvp, 158018334Speter ntfs_cntobn(cn), 158118334Speter ntfs_cntob(cl), 158218334Speter NOCRED, &bp); 158318334Speter if (error) { 158418334Speter brelse(bp); 158518334Speter return (error); 158650397Sobrien } 158718334Speter memcpy(data, bp->b_data + off, tocopy); 158818334Speter brelse(bp); 1589132718Skan data = data + tocopy; 159018334Speter *initp += tocopy; 159118334Speter off = 0; 159218334Speter left -= tocopy; 159318334Speter cn += cl; 159418334Speter ccl -= cl; 159518334Speter } 159618334Speter } else { 159718334Speter tocopy = min(left, ntfs_cntob(ccl) - off); 159818334Speter ddprintf(("ntfs_readntvattr_plain: " 159918334Speter "sparce: ccn: 0x%x ccl: %d, off: %d, " \ 160018334Speter " len: %d, left: %d\n", 160118334Speter (u_int32_t) ccn, (u_int32_t) ccl, 160218334Speter (u_int32_t) off, (u_int32_t) tocopy, 160318334Speter (u_int32_t) left)); 160418334Speter left -= tocopy; 160518334Speter off = 0; 1606132718Skan bzero(data, tocopy); 160718334Speter data = data + tocopy; 1608169689Skan } 1609169689Skan cnt++; 1610169689Skan } 1611169689Skan if (left) { 161290075Sobrien printf("ntfs_readntvattr_plain: POSSIBLE RUN ERROR\n"); 161318334Speter error = E2BIG; 1614169689Skan } 1615169689Skan } else { 1616169689Skan ddprintf(("ntfs_readnvattr_plain: data is in mft record\n")); 1617169689Skan memcpy(rdata, vap->va_datap + roff, rsize); 1618169689Skan *initp += rsize; 1619169689Skan } 1620169689Skan 1621169689Skan return (error); 1622169689Skan} 1623169689Skan 162418334Speter/* 162518334Speter * This is one of read routines. 162618334Speter * 162718334Speter * ntnode should be locked. 162890075Sobrien */ 162990075Sobrienint 163090075Sobrienntfs_readattr_plain( 1631132718Skan struct ntfsmount * ntmp, 163290075Sobrien struct ntnode * ip, 163390075Sobrien u_int32_t attrnum, 163490075Sobrien char *attrname, 163590075Sobrien off_t roff, 163690075Sobrien size_t rsize, 163790075Sobrien void *rdata, 163890075Sobrien size_t * initp) 163990075Sobrien{ 164090075Sobrien size_t init; 164190075Sobrien int error = 0; 164290075Sobrien off_t off = roff, left = rsize, toread; 164318334Speter caddr_t data = rdata; 164418334Speter struct ntvattr *vap; 164518334Speter *initp = 0; 164618334Speter 164718334Speter while (left) { 1648132718Skan error = ntfs_ntvattrget(ntmp, ip, attrnum, attrname, 164918334Speter ntfs_btocn(off), &vap); 1650132718Skan if (error) 165118334Speter return (error); 1652132718Skan toread = min(left, ntfs_cntob(vap->va_vcnend + 1) - off); 1653132718Skan ddprintf(("ntfs_readattr_plain: o: %d, s: %d (%d - %d)\n", 1654132718Skan (u_int32_t) off, (u_int32_t) toread, 1655132718Skan (u_int32_t) vap->va_vcnstart, 1656132718Skan (u_int32_t) vap->va_vcnend)); 1657132718Skan error = ntfs_readntvattr_plain(ntmp, ip, vap, 1658132718Skan off - ntfs_cntob(vap->va_vcnstart), 1659132718Skan toread, data, &init); 1660132718Skan if (error) { 166190075Sobrien printf("ntfs_readattr_plain: " \ 1662132718Skan "ntfs_readntvattr_plain failed: o: %d, s: %d\n", 1663132718Skan (u_int32_t) off, (u_int32_t) toread); 1664132718Skan printf("ntfs_readattr_plain: attrib: %d - %d\n", 1665169689Skan (u_int32_t) vap->va_vcnstart, 1666132718Skan (u_int32_t) vap->va_vcnend); 166790075Sobrien ntfs_ntvattrrele(vap); 166818334Speter break; 1669132718Skan } 167018334Speter ntfs_ntvattrrele(vap); 167118334Speter left -= toread; 167218334Speter off += toread; 167318334Speter data = data + toread; 167418334Speter *initp += init; 1675132718Skan } 167618334Speter 167790075Sobrien return (error); 167818334Speter} 167950397Sobrien 168018334Speter/* 168118334Speter * This is one of read routines. 168218334Speter * 168318334Speter * ntnode should be locked. 168418334Speter */ 168518334Speterint 168618334Speterntfs_readattr( 168718334Speter struct ntfsmount * ntmp, 1688132718Skan struct ntnode * ip, 168918334Speter u_int32_t attrnum, 169090075Sobrien char *attrname, 169118334Speter off_t roff, 169218334Speter size_t rsize, 169318334Speter void *rdata) 169418334Speter{ 169518334Speter int error = 0; 169618334Speter struct ntvattr *vap; 169718334Speter size_t init; 169818334Speter 169918334Speter ddprintf(("ntfs_readattr: reading %d: 0x%x, from %d size %d bytes\n", 170018334Speter ip->i_number, attrnum, (u_int32_t) roff, (u_int32_t) rsize)); 170118334Speter 170218334Speter error = ntfs_ntvattrget(ntmp, ip, attrnum, attrname, 0, &vap); 170318334Speter if (error) 1704169689Skan return (error); 170518334Speter 1706169689Skan if ((roff > vap->va_datalen) || 170718334Speter (roff + rsize > vap->va_datalen)) { 170818334Speter ddprintf(("ntfs_readattr: offset too big\n")); 170918334Speter ntfs_ntvattrrele(vap); 171018334Speter return (E2BIG); 171118334Speter } 171218334Speter if (vap->va_compression && vap->va_compressalg) { 1713132718Skan u_int8_t *cup; 171418334Speter u_int8_t *uup; 171518334Speter off_t off = roff, left = rsize, tocopy; 171618334Speter caddr_t data = rdata; 1717169689Skan cn_t cn; 171818334Speter 171990075Sobrien ddprintf(("ntfs_ntreadattr: compression: %d\n", 172090075Sobrien vap->va_compressalg)); 1721169689Skan 172290075Sobrien MALLOC(cup, u_int8_t *, ntfs_cntob(NTFS_COMPUNIT_CL), 172390075Sobrien M_NTFSDECOMP, M_WAITOK); 172490075Sobrien MALLOC(uup, u_int8_t *, ntfs_cntob(NTFS_COMPUNIT_CL), 172518334Speter M_NTFSDECOMP, M_WAITOK); 172690075Sobrien 172790075Sobrien cn = (ntfs_btocn(roff)) & (~(NTFS_COMPUNIT_CL - 1)); 172818334Speter off = roff - ntfs_cntob(cn); 172918334Speter 173018334Speter while (left) { 173118334Speter error = ntfs_readattr_plain(ntmp, ip, attrnum, 173218334Speter attrname, ntfs_cntob(cn), 173318334Speter ntfs_cntob(NTFS_COMPUNIT_CL), 173418334Speter cup, &init); 173518334Speter if (error) 173618334Speter break; 173718334Speter 173818334Speter tocopy = min(left, ntfs_cntob(NTFS_COMPUNIT_CL) - off); 173918334Speter 174018334Speter if (init == ntfs_cntob(NTFS_COMPUNIT_CL)) { 174118334Speter memcpy(data, cup + off, tocopy); 174218334Speter } else if (init == 0) { 174318334Speter bzero(data, tocopy); 174418334Speter } else { 1745132718Skan error = ntfs_uncompunit(ntmp, uup, cup); 174618334Speter if (error) 174718334Speter break; 174818334Speter memcpy(data, uup + off, tocopy); 174918334Speter } 175018334Speter 175150397Sobrien left -= tocopy; 175218334Speter data = data + tocopy; 175350397Sobrien off += tocopy - ntfs_cntob(NTFS_COMPUNIT_CL); 175490075Sobrien cn += NTFS_COMPUNIT_CL; 175550397Sobrien } 175618334Speter 1757169689Skan FREE(uup, M_NTFSDECOMP); 175890075Sobrien FREE(cup, M_NTFSDECOMP); 175918334Speter } else 176090075Sobrien error = ntfs_readattr_plain(ntmp, ip, attrnum, attrname, 176118334Speter roff, rsize, rdata, &init); 1762169689Skan ntfs_ntvattrrele(vap); 176350397Sobrien return (error); 176418334Speter} 176518334Speter 176618334Speter#if UNUSED_CODE 176750397Sobrienint 176850397Sobrienntfs_parserun( 176918334Speter cn_t * cn, 177050397Sobrien cn_t * cl, 1771132718Skan u_int8_t * run, 177218334Speter u_long len, 177350397Sobrien u_long *off) 177450397Sobrien{ 177518334Speter u_int8_t sz; 177618334Speter int i; 177750397Sobrien 177818334Speter if (NULL == run) { 177950397Sobrien printf("ntfs_parsetun: run == NULL\n"); 178050397Sobrien return (EINVAL); 178150397Sobrien } 178290075Sobrien sz = run[(*off)++]; 178390075Sobrien if (0 == sz) { 178490075Sobrien printf("ntfs_parserun: trying to go out of run\n"); 178518334Speter return (E2BIG); 178650397Sobrien } 178750397Sobrien *cl = 0; 178818334Speter if ((sz & 0xF) > 8 || (*off) + (sz & 0xF) > len) { 1789169689Skan printf("ntfs_parserun: " \ 1790169689Skan "bad run: length too big: sz: 0x%02x (%ld < %ld + sz)\n", 1791169689Skan sz, len, *off); 1792169689Skan return (EINVAL); 1793169689Skan } 1794169689Skan for (i = 0; i < (sz & 0xF); i++) 1795169689Skan *cl += (u_int32_t) run[(*off)++] << (i << 3); 1796169689Skan 1797169689Skan sz >>= 4; 1798169689Skan if ((sz & 0xF) > 8 || (*off) + (sz & 0xF) > len) { 1799169689Skan printf("ntfs_parserun: " \ 1800169689Skan "bad run: length too big: sz: 0x%02x (%ld < %ld + sz)\n", 1801169689Skan sz, len, *off); 1802169689Skan return (EINVAL); 1803169689Skan } 1804169689Skan for (i = 0; i < (sz & 0xF); i++) 1805169689Skan *cn += (u_int32_t) run[(*off)++] << (i << 3); 1806169689Skan 1807169689Skan return (0); 1808169689Skan} 1809169689Skan#endif 1810169689Skan 1811169689Skan/* 1812169689Skan * Process fixup routine on given buffer. 1813169689Skan */ 1814169689Skanint 1815169689Skanntfs_procfixups( 1816169689Skan struct ntfsmount * ntmp, 1817169689Skan u_int32_t magic, 1818169689Skan caddr_t buf, 1819169689Skan size_t len) 1820169689Skan{ 1821169689Skan struct fixuphdr *fhp = (struct fixuphdr *) buf; 182218334Speter int i; 182390075Sobrien u_int16_t fixup; 182490075Sobrien u_int16_t *fxp; 182518334Speter u_int16_t *cfxp; 182690075Sobrien 1827132718Skan if (fhp->fh_magic != magic) { 182890075Sobrien printf("ntfs_procfixups: magic doesn't match: %08x != %08x\n", 182990075Sobrien fhp->fh_magic, magic); 183090075Sobrien return (EINVAL); 183190075Sobrien } 183290075Sobrien if ((fhp->fh_fnum - 1) * ntmp->ntm_bps != len) { 1833169689Skan printf("ntfs_procfixups: " \ 1834169689Skan "bad fixups number: %d for %d bytes block\n", 1835169689Skan fhp->fh_fnum, len); 183690075Sobrien return (EINVAL); 183790075Sobrien } 1838132718Skan if (fhp->fh_foff >= ntmp->ntm_spc * ntmp->ntm_mftrecsz * ntmp->ntm_bps) { 183990075Sobrien printf("ntfs_procfixups: invalid offset: %x", fhp->fh_foff); 184090075Sobrien return (EINVAL); 184190075Sobrien } 184290075Sobrien fxp = (u_int16_t *) (buf + fhp->fh_foff); 184390075Sobrien cfxp = (u_int16_t *) (buf + ntmp->ntm_bps - 2); 184490075Sobrien fixup = *fxp++; 184590075Sobrien for (i = 1; i < fhp->fh_fnum; i++, fxp++) { 184618334Speter if (*cfxp != fixup) { 1847132718Skan printf("ntfs_procfixups: fixup %d doesn't match\n", i); 184890075Sobrien return (EINVAL); 184990075Sobrien } 185090075Sobrien *cfxp = *fxp; 185190075Sobrien ((caddr_t) cfxp) += ntmp->ntm_bps; 185290075Sobrien } 1853169689Skan return (0); 1854169689Skan} 1855169689Skan 185690075Sobrien#if UNUSED_CODE 185790075Sobrienint 1858132718Skanntfs_runtocn( 185990075Sobrien cn_t * cn, 186090075Sobrien struct ntfsmount * ntmp, 186190075Sobrien u_int8_t * run, 186290075Sobrien u_long len, 186390075Sobrien cn_t vcn) 186490075Sobrien{ 186590075Sobrien cn_t ccn = 0; 1866132718Skan cn_t ccl = 0; 186790075Sobrien u_long off = 0; 186890075Sobrien int error = 0; 186990075Sobrien 187090075Sobrien#if NTFS_DEBUG 187190075Sobrien int i; 187290075Sobrien printf("ntfs_runtocn: run: 0x%p, %ld bytes, vcn:%ld\n", 187390075Sobrien run, len, (u_long) vcn); 187490075Sobrien printf("ntfs_runtocn: run: "); 187590075Sobrien for (i = 0; i < len; i++) 187690075Sobrien printf("0x%02x ", run[i]); 187790075Sobrien printf("\n"); 187890075Sobrien#endif 187990075Sobrien 188090075Sobrien if (NULL == run) { 1881169689Skan printf("ntfs_runtocn: run == NULL\n"); 188290075Sobrien return (EINVAL); 188390075Sobrien } 188490075Sobrien do { 188590075Sobrien if (run[off] == 0) { 188690075Sobrien printf("ntfs_runtocn: vcn too big\n"); 188790075Sobrien return (E2BIG); 188890075Sobrien } 188990075Sobrien vcn -= ccl; 189090075Sobrien error = ntfs_parserun(&ccn, &ccl, run, len, &off); 189190075Sobrien if (error) { 1892258748Spfg printf("ntfs_runtocn: ntfs_parserun failed\n"); 1893258748Spfg return (error); 189490075Sobrien } 189590075Sobrien } while (ccl <= vcn); 189690075Sobrien *cn = ccn + vcn; 1897258748Spfg return (0); 1898258748Spfg} 189990075Sobrien#endif 190090075Sobrien