The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/ntfs/ntfs_subr.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    1 /*      $NetBSD: ntfs_subr.c,v 1.2 1999/05/06 15:43:19 christos Exp $   */
    2 
    3 /*-
    4  * Copyright (c) 1998, 1999 Semen Ustimenko (semenu@FreeBSD.org)
    5  * All rights reserved.
    6  *
    7  * Redistribution and use in source and binary forms, with or without
    8  * modification, are permitted provided that the following conditions
    9  * are met:
   10  * 1. Redistributions of source code must retain the above copyright
   11  *    notice, this list of conditions and the following disclaimer.
   12  * 2. Redistributions in binary form must reproduce the above copyright
   13  *    notice, this list of conditions and the following disclaimer in the
   14  *    documentation and/or other materials provided with the distribution.
   15  *
   16  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
   17  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   18  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   19  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
   20  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   21  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   22  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   23  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   24  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   25  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   26  * SUCH DAMAGE.
   27  *
   28  * $FreeBSD$
   29  */
   30 
   31 #include <sys/param.h>
   32 #include <sys/types.h>
   33 #include <sys/systm.h>
   34 #include <sys/namei.h>
   35 #include <sys/proc.h>
   36 #include <sys/kernel.h>
   37 #include <sys/vnode.h>
   38 #include <sys/mount.h>
   39 #include <sys/buf.h>
   40 #include <sys/file.h>
   41 #include <sys/malloc.h>
   42 #if defined(__FreeBSD__)
   43 #include <machine/clock.h>
   44 #endif
   45 
   46 #include <miscfs/specfs/specdev.h>
   47 
   48 /* #define NTFS_DEBUG 1 */
   49 #include <ntfs/ntfs.h>
   50 #include <ntfs/ntfsmount.h>
   51 #include <ntfs/ntfs_inode.h>
   52 #include <ntfs/ntfs_vfsops.h>
   53 #include <ntfs/ntfs_extern.h>
   54 #include <ntfs/ntfs_subr.h>
   55 #include <ntfs/ntfs_compr.h>
   56 #include <ntfs/ntfs_ihash.h>
   57 
   58 #if defined(__FreeBSD__)
   59 MALLOC_DEFINE(M_NTFSNTVATTR, "NTFS vattr", "NTFS file attribute information");
   60 MALLOC_DEFINE(M_NTFSRDATA, "NTFS res data", "NTFS resident data");
   61 MALLOC_DEFINE(M_NTFSRUN, "NTFS vrun", "NTFS vrun storage");
   62 MALLOC_DEFINE(M_NTFSDECOMP, "NTFS decomp", "NTFS decompression temporary");
   63 #endif
   64 
   65 /*
   66  * 
   67  */
   68 int
   69 ntfs_ntvattrrele(
   70                  struct ntvattr * vap)
   71 {
   72         dprintf(("ntfs_ntvattrrele: ino: %d, type: 0x%x\n",
   73                  vap->va_ip->i_number, vap->va_type));
   74 
   75         ntfs_ntrele(vap->va_ip);
   76 
   77         return (0);
   78 }
   79 
   80 /*
   81  * Search attribute specifed in ntnode (load ntnode if nessecary).
   82  * If not found but ATTR_A_ATTRLIST present, read it in and search throught.
   83  * VOP_VGET node needed, and lookup througth it's ntnode (load if nessesary).
   84  *
   85  * ntnode should be locked
   86  */
   87 int
   88 ntfs_ntvattrget(
   89                 struct ntfsmount * ntmp,
   90                 struct ntnode * ip,
   91                 u_int32_t type,
   92                 char *name,
   93                 cn_t vcn,
   94                 struct ntvattr ** vapp)
   95 {
   96         int             error;
   97         struct ntvattr *vap;
   98         struct ntvattr *lvap = NULL;
   99         struct attr_attrlist *aalp;
  100         struct attr_attrlist *nextaalp;
  101         caddr_t         alpool;
  102         int             len, namelen;
  103 
  104         *vapp = NULL;
  105 
  106         if (name) {
  107                 dprintf(("ntfs_ntvattrget: " \
  108                          "ino: %d, type: 0x%x, name: %s, vcn: %d\n", \
  109                          ip->i_number, type, name, (u_int32_t) vcn));
  110                 namelen = strlen(name);
  111         } else {
  112                 dprintf(("ntfs_ntvattrget: " \
  113                          "ino: %d, type: 0x%x, vcn: %d\n", \
  114                          ip->i_number, type, (u_int32_t) vcn));
  115                 name = "";
  116                 namelen = 0;
  117         }
  118 
  119         if((ip->i_flag & IN_LOADED) == 0) {
  120                 dprintf(("ntfs_ntvattrget: node not loaded, ino: %d\n",
  121                        ip->i_number));
  122                 error = ntfs_loadntnode(ntmp,ip);
  123                 if(error) {
  124                         printf("ntfs_ntvattrget: FAILED TO LOAD INO: %d\n",
  125                                ip->i_number);
  126                         return (error);
  127                 }
  128         }
  129 
  130         for (vap = ip->i_valist.lh_first; vap; vap = vap->va_list.le_next) {
  131                 ddprintf(("type: 0x%x, vcn: %d - %d\n", \
  132                           vap->va_type, (u_int32_t) vap->va_vcnstart, \
  133                           (u_int32_t) vap->va_vcnend));
  134                 if ((vap->va_type == type) &&
  135                     (vap->va_vcnstart <= vcn) && (vap->va_vcnend >= vcn) &&
  136                     (vap->va_namelen == namelen) &&
  137                     (!strncmp(name, vap->va_name, namelen))) {
  138                         *vapp = vap;
  139                         ntfs_ntref(vap->va_ip);
  140                         return (0);
  141                 }
  142                 if (vap->va_type == NTFS_A_ATTRLIST)
  143                         lvap = vap;
  144         }
  145 
  146         if (!lvap) {
  147                 dprintf(("ntfs_ntvattrget: UNEXISTED ATTRIBUTE: " \
  148                        "ino: %d, type: 0x%x, name: %s, vcn: %d\n", \
  149                        ip->i_number, type, name, (u_int32_t) vcn));
  150                 return (ENOENT);
  151         }
  152         /* Scan $ATTRIBUTE_LIST for requested attribute */
  153         len = lvap->va_datalen;
  154         MALLOC(alpool, caddr_t, len, M_TEMP, M_WAITOK);
  155         error = ntfs_readntvattr_plain(ntmp, ip, lvap, 0, len, alpool, &len);
  156         if (error)
  157                 goto out;
  158 
  159         aalp = (struct attr_attrlist *) alpool;
  160         nextaalp = NULL;
  161 
  162         while (len > 0) {
  163                 dprintf(("ntfs_ntvattrget: " \
  164                          "attrlist: ino: %d, attr: 0x%x, vcn: %d\n", \
  165                          aalp->al_inumber, aalp->al_type, \
  166                          (u_int32_t) aalp->al_vcnstart));
  167 
  168                 if (len > aalp->reclen) {
  169                         nextaalp = NTFS_NEXTREC(aalp, struct attr_attrlist *);
  170                 } else {
  171                         nextaalp = NULL;
  172                 }
  173                 len -= aalp->reclen;
  174 
  175 #define AALPCMP(aalp,type,name,namelen) (                               \
  176   (aalp->al_type == type) && (aalp->al_namelen == namelen) &&           \
  177   !uastrcmp(aalp->al_name,aalp->al_namelen,name,namelen) )
  178 
  179                 if (AALPCMP(aalp, type, name, namelen) &&
  180                     (!nextaalp || (nextaalp->al_vcnstart > vcn) ||
  181                      !AALPCMP(nextaalp, type, name, namelen))) {
  182                         struct vnode   *newvp;
  183                         struct ntnode  *newip;
  184 
  185                         dprintf(("ntfs_ntvattrget: attrbute in ino: %d\n",
  186                                  aalp->al_inumber));
  187 
  188 /*
  189                         error = VFS_VGET(ntmp->ntm_mountp, aalp->al_inumber,
  190                                          &newvp);
  191 */
  192                         error = ntfs_vgetex(ntmp->ntm_mountp, aalp->al_inumber,
  193                                         NTFS_A_DATA, NULL, LK_EXCLUSIVE,
  194                                         VG_EXT, curproc, &newvp);
  195                         if (error) {
  196                                 printf("ntfs_ntvattrget: CAN'T VGET INO: %d\n",
  197                                        aalp->al_inumber);
  198                                 goto out;
  199                         }
  200                         newip = VTONT(newvp);
  201                         /* XXX have to lock ntnode */
  202                         if(~newip->i_flag & IN_LOADED) {
  203                                 dprintf(("ntfs_ntvattrget: node not loaded," \
  204                                          " ino: %d\n", newip->i_number));
  205                                 error = ntfs_loadntnode(ntmp,ip);
  206                                 if(error) {
  207                                         printf("ntfs_ntvattrget: CAN'T LOAD " \
  208                                                "INO: %d\n", newip->i_number);
  209                                         vput(newvp);
  210                                         goto out;
  211                                 }
  212                         }
  213                         for (vap = newip->i_valist.lh_first; vap; vap = vap->va_list.le_next) {
  214                                 if ((vap->va_type == type) &&
  215                                     (vap->va_vcnstart <= vcn) &&
  216                                     (vap->va_vcnend >= vcn) &&
  217                                     (vap->va_namelen == namelen) &&
  218                                   (!strncmp(name, vap->va_name, namelen))) {
  219                                         *vapp = vap;
  220                                         ntfs_ntref(vap->va_ip);
  221                                         vput(newvp);
  222                                         error = 0;
  223                                         goto out;
  224                                 }
  225                                 if (vap->va_type == NTFS_A_ATTRLIST)
  226                                         lvap = vap;
  227                         }
  228                         printf("ntfs_ntvattrget: ATTRLIST ERROR.\n");
  229                         vput(newvp);
  230                         break;
  231                 }
  232 #undef AALPCMP
  233                 aalp = nextaalp;
  234         }
  235         error = ENOENT;
  236 
  237         dprintf(("ntfs_ntvattrget: UNEXISTED ATTRIBUTE: " \
  238                "ino: %d, type: 0x%x, name: %s, vcn: %d\n", \
  239                ip->i_number, type, name, (u_int32_t) vcn));
  240 out:
  241         FREE(alpool, M_TEMP);
  242         return (error);
  243 }
  244 
  245 /*
  246  * Read ntnode from disk, make ntvattr list.
  247  *
  248  * ntnode should be locked
  249  */
  250 int
  251 ntfs_loadntnode(
  252               struct ntfsmount * ntmp,
  253               struct ntnode * ip)
  254 {
  255         struct filerec  *mfrp;
  256         daddr_t         bn;
  257         int             error,off;
  258         struct attr    *ap;
  259         struct ntvattr *nvap;
  260 
  261         dprintf(("ntfs_loadnode: loading ino: %d\n",ip->i_number));
  262 
  263         MALLOC(mfrp, struct filerec *, ntfs_bntob(ntmp->ntm_bpmftrec),
  264                M_TEMP, M_WAITOK);
  265 
  266         if (ip->i_number < NTFS_SYSNODESNUM) {
  267                 struct buf     *bp;
  268 
  269                 dprintf(("ntfs_loadnode: read system node\n"));
  270 
  271                 bn = ntfs_cntobn(ntmp->ntm_mftcn) +
  272                         ntmp->ntm_bpmftrec * ip->i_number;
  273 
  274                 error = bread(ntmp->ntm_devvp,
  275                               bn, ntfs_bntob(ntmp->ntm_bpmftrec),
  276                               NOCRED, &bp);
  277                 if (error) {
  278                         printf("ntfs_loadnode: BREAD FAILED\n");
  279                         brelse(bp);
  280                         goto out;
  281                 }
  282                 memcpy(mfrp, bp->b_data, ntfs_bntob(ntmp->ntm_bpmftrec));
  283                 bqrelse(bp);
  284         } else {
  285                 struct vnode   *vp;
  286 
  287                 vp = ntmp->ntm_sysvn[NTFS_MFTINO];
  288                 error = ntfs_readattr(ntmp, VTONT(vp), NTFS_A_DATA, NULL,
  289                                ip->i_number * ntfs_bntob(ntmp->ntm_bpmftrec),
  290                                ntfs_bntob(ntmp->ntm_bpmftrec), mfrp);
  291                 if (error) {
  292                         printf("ntfs_loadnode: ntfs_readattr failed\n");
  293                         goto out;
  294                 }
  295         }
  296 
  297         /* Check if magic and fixups are correct */
  298         error = ntfs_procfixups(ntmp, NTFS_FILEMAGIC, (caddr_t)mfrp,
  299                                 ntfs_bntob(ntmp->ntm_bpmftrec));
  300         if (error) {
  301                 printf("ntfs_loadnode: BAD MFT RECORD %d\n",
  302                        (u_int32_t) ip->i_number);
  303                 goto out;
  304         }
  305 
  306         dprintf(("ntfs_loadnode: load attrs for ino: %d\n",ip->i_number));
  307         off = mfrp->fr_attroff;
  308         ap = (struct attr *) ((caddr_t)mfrp + off);
  309 
  310         LIST_INIT(&ip->i_valist);
  311         
  312         while (ap->a_hdr.a_type != -1) {
  313                 error = ntfs_attrtontvattr(ntmp, &nvap, ap);
  314                 if (error)
  315                         break;
  316                 nvap->va_ip = ip;
  317 
  318                 LIST_INSERT_HEAD(&ip->i_valist, nvap, va_list);
  319 
  320                 off += ap->a_hdr.reclen;
  321                 ap = (struct attr *) ((caddr_t)mfrp + off);
  322         }
  323         if (error) {
  324                 printf("ntfs_loadnode: failed to load attr ino: %d\n",
  325                        ip->i_number);
  326                 goto out;
  327         }
  328 
  329         ip->i_mainrec = mfrp->fr_mainrec;
  330         ip->i_nlink = mfrp->fr_nlink;
  331         ip->i_frflag = mfrp->fr_flags;
  332 
  333         ip->i_flag |= IN_LOADED;
  334 
  335 out:
  336         FREE(mfrp, M_TEMP);
  337         return (error);
  338 }
  339                 
  340 /*
  341  * Routine locks ntnode and increase usecount, just opposite of
  342  * ntfs_ntput.
  343  */
  344 int
  345 ntfs_ntget(
  346            struct ntnode *ip)
  347 {
  348         dprintf(("ntfs_ntget: get ntnode %d: %p, usecount: %d\n",
  349                 ip->i_number, ip, ip->i_usecount));
  350 
  351         ip->i_usecount++;
  352 
  353 restart:
  354         if (ip->i_lock) {
  355                 while (ip->i_lock) {
  356                         ip->i_lock = -1;
  357                         tsleep(&ip->i_lock, PVM, "ntnode", 0);
  358                 }
  359                 goto restart;
  360         }
  361         ip->i_lock = 1;
  362 
  363         return 0;
  364 }
  365 
  366 /*
  367  * Routine search ntnode in hash, if found: lock, inc usecount and return.
  368  * If not in hash allocate structure for ntnode, prefill it, lock,
  369  * inc count and return.
  370  *
  371  * ntnode returned locked
  372  */
  373 static int ntfs_ntnode_hash_lock;
  374 int
  375 ntfs_ntlookup(
  376            struct ntfsmount * ntmp,
  377            ino_t ino,
  378            struct ntnode ** ipp)
  379 {
  380         struct ntnode  *ip;
  381 
  382         dprintf(("ntfs_ntlookup: for ntnode %d\n", ino));
  383         *ipp = NULL;
  384 
  385 restart:
  386         ip = ntfs_nthashlookup(ntmp->ntm_dev, ino); /* XXX */
  387         if (ip) {
  388                 ntfs_ntget(ip);
  389                 *ipp = ip;
  390                 dprintf(("ntfs_ntlookup: ntnode %d: %p, usecount: %d\n",
  391                         ino, ip, ip->i_usecount));
  392 
  393                 return (0);
  394         }
  395 
  396         if (ntfs_ntnode_hash_lock) {
  397                 while(ntfs_ntnode_hash_lock) {
  398                         ntfs_ntnode_hash_lock = -1;
  399                         tsleep(&ntfs_ntnode_hash_lock, PVM, "ntfsntgt", 0);
  400                 }
  401                 goto restart;
  402         }
  403         ntfs_ntnode_hash_lock = 1;
  404 
  405         MALLOC(ip, struct ntnode *, sizeof(struct ntnode),
  406                M_NTFSNTNODE, M_WAITOK);
  407         ddprintf(("ntfs_ntlookup: allocating ntnode: %d: %p\n", ino, ip));
  408         bzero((caddr_t) ip, sizeof(struct ntnode));
  409 
  410         /* Generic initialization */
  411         ip->i_number = ino;
  412         ip->i_mp = ntmp;
  413         ip->i_dev = ntmp->ntm_dev;
  414         ip->i_uid = ntmp->ntm_uid;
  415         ip->i_gid = ntmp->ntm_gid;
  416         ip->i_mode = ntmp->ntm_mode;
  417         ip->i_usecount++;
  418 
  419         ip->i_lock = 1;
  420 
  421         LIST_INIT(&ip->i_fnlist);
  422 
  423         ntfs_nthashins(ip);
  424 
  425         if (ntfs_ntnode_hash_lock < 0)
  426                 wakeup(&ntfs_ntnode_hash_lock);
  427         ntfs_ntnode_hash_lock = 0;
  428 
  429         *ipp = ip;
  430 
  431         dprintf(("ntfs_ntlookup: ntnode %d: %p, usecount: %d\n",
  432                 ino, ip, ip->i_usecount));
  433 
  434         return (0);
  435 }
  436 
  437 /*
  438  * Decrement usecount of ntnode and unlock it, if usecount reach zero,
  439  * deallocate ntnode.
  440  *
  441  * ntnode should be locked on entry, and unlocked on return.
  442  */
  443 void
  444 ntfs_ntput(
  445            struct ntnode *ip)
  446 {
  447         struct ntvattr *vap;
  448 
  449         if (!ip->i_lock) printf("ntfs_ntput: NOT LOCKED");
  450 
  451         dprintf(("ntfs_ntput: rele ntnode %d: %p, usecount: %d\n",
  452                 ip->i_number, ip, ip->i_usecount));
  453 
  454         ip->i_usecount--;
  455 
  456         if (ip->i_usecount < 0) {
  457                 panic("ntfs_ntput: ino: %d usecount: %d \n",
  458                       ip->i_number,ip->i_usecount);
  459         } else if (ip->i_usecount == 0) {
  460                 dprintf(("ntfs_ntput: deallocating ntnode: %d\n",
  461                         ip->i_number));
  462 
  463                 if (ip->i_fnlist.lh_first)
  464                         panic("ntfs_ntput: ntnode has fnodes\n");
  465 
  466                 ntfs_nthashrem(ip);
  467 
  468                 while (ip->i_valist.lh_first != NULL) {
  469                         vap = ip->i_valist.lh_first;
  470                         LIST_REMOVE(vap,va_list);
  471                         ntfs_freentvattr(vap);
  472                 }
  473                 FREE(ip, M_NTFSNTNODE);
  474         } else {
  475                 if (ip->i_lock < 0)
  476                         wakeup(&ip->i_lock);
  477                 ip->i_lock = 0;
  478         }
  479 }
  480 
  481 /*
  482  * Decrement usecount of ntnode.
  483  */
  484 void
  485 ntfs_ntrele(
  486             struct ntnode * ip)
  487 {
  488         dprintf(("ntfs_ntrele: rele ntnode %d: %p, usecount: %d\n",
  489                 ip->i_number, ip, ip->i_usecount));
  490 
  491         ip->i_usecount--;
  492 
  493         if (ip->i_usecount < 0)
  494                 panic("ntfs_ntrele: ino: %d usecount: %d \n",
  495                       ip->i_number,ip->i_usecount);
  496 }
  497 
  498 /*
  499  * Deallocate all memory allocated for ntvattr by call to
  500  * ntfs_attrtontvattr and some other functions.
  501  */
  502 void
  503 ntfs_freentvattr(
  504                  struct ntvattr * vap)
  505 {
  506         if (vap->va_flag & NTFS_AF_INRUN) {
  507                 if (vap->va_vruncn)
  508                         FREE(vap->va_vruncn, M_NTFSRUN);
  509                 if (vap->va_vruncl)
  510                         FREE(vap->va_vruncl, M_NTFSRUN);
  511         } else {
  512                 if (vap->va_datap)
  513                         FREE(vap->va_datap, M_NTFSRDATA);
  514         }
  515         FREE(vap, M_NTFSNTVATTR);
  516 }
  517 
  518 /*
  519  * Convert disk image of attribute into ntvattr structure,
  520  * runs are expanded also.
  521  */
  522 int
  523 ntfs_attrtontvattr(
  524                    struct ntfsmount * ntmp,
  525                    struct ntvattr ** rvapp,
  526                    struct attr * rap)
  527 {
  528         int             error, i;
  529         struct ntvattr *vap;
  530 
  531         error = 0;
  532         *rvapp = NULL;
  533 
  534         MALLOC(vap, struct ntvattr *, sizeof(struct ntvattr),
  535                 M_NTFSNTVATTR, M_WAITOK);
  536         bzero(vap, sizeof(struct ntvattr));
  537         vap->va_ip = NULL;
  538         vap->va_flag = rap->a_hdr.a_flag;
  539         vap->va_type = rap->a_hdr.a_type;
  540         vap->va_compression = rap->a_hdr.a_compression;
  541         vap->va_index = rap->a_hdr.a_index;
  542 
  543         ddprintf(("type: 0x%x, index: %d", vap->va_type, vap->va_index));
  544 
  545         vap->va_namelen = rap->a_hdr.a_namelen;
  546         if (rap->a_hdr.a_namelen) {
  547                 wchar *unp = (wchar *) ((caddr_t) rap + rap->a_hdr.a_nameoff);
  548                 ddprintf((", name:["));
  549                 for (i = 0; i < vap->va_namelen; i++) {
  550                         vap->va_name[i] = unp[i];
  551                         ddprintf(("%c", vap->va_name[i]));
  552                 }
  553                 ddprintf(("]"));
  554         }
  555         if (vap->va_flag & NTFS_AF_INRUN) {
  556                 ddprintf((", nonres."));
  557                 vap->va_datalen = rap->a_nr.a_datalen;
  558                 vap->va_allocated = rap->a_nr.a_allocated;
  559                 vap->va_vcnstart = rap->a_nr.a_vcnstart;
  560                 vap->va_vcnend = rap->a_nr.a_vcnend;
  561                 vap->va_compressalg = rap->a_nr.a_compressalg;
  562                 error = ntfs_runtovrun(&(vap->va_vruncn), &(vap->va_vruncl),
  563                                        &(vap->va_vruncnt),
  564                                        (caddr_t) rap + rap->a_nr.a_dataoff);
  565         } else {
  566                 vap->va_compressalg = 0;
  567                 ddprintf((", res."));
  568                 vap->va_datalen = rap->a_r.a_datalen;
  569                 vap->va_allocated = rap->a_r.a_datalen;
  570                 vap->va_vcnstart = 0;
  571                 vap->va_vcnend = ntfs_btocn(vap->va_allocated);
  572                 MALLOC(vap->va_datap, caddr_t, vap->va_datalen,
  573                        M_NTFSRDATA, M_WAITOK);
  574                 memcpy(vap->va_datap, (caddr_t) rap + rap->a_r.a_dataoff,
  575                        rap->a_r.a_datalen);
  576         }
  577         ddprintf((", len: %d", vap->va_datalen));
  578 
  579         if (error)
  580                 FREE(vap, M_NTFSNTVATTR);
  581         else
  582                 *rvapp = vap;
  583 
  584         ddprintf(("\n"));
  585 
  586         return (error);
  587 }
  588 
  589 /*
  590  * Expand run into more utilizable and more memory eating format.
  591  */
  592 int
  593 ntfs_runtovrun(
  594                cn_t ** rcnp,
  595                cn_t ** rclp,
  596                u_long * rcntp,
  597                u_int8_t * run)
  598 {
  599         u_int32_t       off;
  600         u_int32_t       sz, i;
  601         cn_t           *cn;
  602         cn_t           *cl;
  603         u_long          cnt;
  604         cn_t            prev;
  605         cn_t            tmp;
  606 
  607         off = 0;
  608         cnt = 0;
  609         i = 0;
  610         while (run[off]) {
  611                 off += (run[off] & 0xF) + ((run[off] >> 4) & 0xF) + 1;
  612                 cnt++;
  613         }
  614         MALLOC(cn, cn_t *, cnt * sizeof(cn_t), M_NTFSRUN, M_WAITOK);
  615         MALLOC(cl, cn_t *, cnt * sizeof(cn_t), M_NTFSRUN, M_WAITOK);
  616 
  617         off = 0;
  618         cnt = 0;
  619         prev = 0;
  620         while (run[off]) {
  621 
  622                 sz = run[off++];
  623                 cl[cnt] = 0;
  624 
  625                 for (i = 0; i < (sz & 0xF); i++)
  626                         cl[cnt] += (u_int32_t) run[off++] << (i << 3);
  627 
  628                 sz >>= 4;
  629                 if (run[off + sz - 1] & 0x80) {
  630                         tmp = ((u_int64_t) - 1) << (sz << 3);
  631                         for (i = 0; i < sz; i++)
  632                                 tmp |= (u_int64_t) run[off++] << (i << 3);
  633                 } else {
  634                         tmp = 0;
  635                         for (i = 0; i < sz; i++)
  636                                 tmp |= (u_int64_t) run[off++] << (i << 3);
  637                 }
  638                 if (tmp)
  639                         prev = cn[cnt] = prev + tmp;
  640                 else
  641                         cn[cnt] = tmp;
  642 
  643                 cnt++;
  644         }
  645         *rcnp = cn;
  646         *rclp = cl;
  647         *rcntp = cnt;
  648         return (0);
  649 }
  650 
  651 /*
  652  * Convert wchar to uppercase wchar, should be macros?
  653  */
  654 wchar
  655 ntfs_toupper(
  656              struct ntfsmount * ntmp,
  657              wchar wc)
  658 {
  659         return (ntmp->ntm_upcase[wc & 0xFF]);
  660 }
  661 
  662 /*
  663  * Compare to unicode strings case insensible.
  664  */
  665 int
  666 ntfs_uustricmp(
  667                struct ntfsmount * ntmp,
  668                wchar * str1,
  669                int str1len,
  670                wchar * str2,
  671                int str2len)
  672 {
  673         int             i;
  674         int             res;
  675 
  676         for (i = 0; i < str1len && i < str2len; i++) {
  677                 res = (int) ntfs_toupper(ntmp, str1[i]) -
  678                         (int) ntfs_toupper(ntmp, str2[i]);
  679                 if (res)
  680                         return res;
  681         }
  682         return (str1len - str2len);
  683 }
  684 
  685 /*
  686  * Compare unicode and ascii string case insens.
  687  */
  688 int
  689 ntfs_uastricmp(
  690                struct ntfsmount * ntmp,
  691                const wchar *str1,
  692                int str1len,
  693                const char *str2,
  694                int str2len)
  695 {
  696         int             i;
  697         int             res;
  698 
  699         for (i = 0; i < str1len && i < str2len; i++) {
  700                 res = (int) ntfs_toupper(ntmp, str1[i]) -
  701                         (int) ntfs_toupper(ntmp, (wchar) str2[i]);
  702                 if (res)
  703                         return res;
  704         }
  705         return (str1len - str2len);
  706 }
  707 
  708 /*
  709  * Compare unicode and ascii string case sens.
  710  */
  711 int
  712 ntfs_uastrcmp(
  713               struct ntfsmount *ntmp,
  714               const wchar *str1,
  715               int str1len,
  716               const char *str2,
  717               int str2len)
  718 {
  719         int             i;
  720         int             res;
  721 
  722         for (i = 0; (i < str1len) && (i < str2len); i++) {
  723                 res = ((int) str1[i]) - ((int) str2[i]);
  724                 if (res)
  725                         return res;
  726         }
  727         return (str1len - str2len);
  728 }
  729 
  730 /* 
  731  * Search fnode in ntnode, if not found allocate and preinitialize.
  732  *
  733  * ntnode should be locked on entry.
  734  */
  735 int
  736 ntfs_fget(
  737         struct ntfsmount *ntmp,
  738         struct ntnode *ip,
  739         int attrtype,
  740         char *attrname,
  741         struct fnode **fpp)
  742 {
  743         struct fnode *fp;
  744 
  745         dprintf(("ntfs_fget: ino: %d, attrtype: 0x%x, attrname: %s\n",
  746                 ip->i_number,attrtype, attrname?attrname:""));
  747         *fpp = NULL;
  748         for (fp = ip->i_fnlist.lh_first; fp != NULL; fp = fp->f_fnlist.le_next){
  749                 dprintf(("ntfs_fget: fnode: attrtype: %d, attrname: %s\n",
  750                         fp->f_attrtype, fp->f_attrname?fp->f_attrname:""));
  751 
  752                 if ((attrtype == fp->f_attrtype) && 
  753                     ((!attrname && !fp->f_attrname) ||
  754                      (attrname && fp->f_attrname &&
  755                       !strcmp(attrname,fp->f_attrname)))){
  756                         dprintf(("ntfs_fget: found existed: %p\n",fp));
  757                         *fpp = fp;
  758                 }
  759         }
  760 
  761         if (*fpp)
  762                 return (0);
  763 
  764         MALLOC(fp, struct fnode *, sizeof(struct fnode), M_NTFSFNODE, M_WAITOK);
  765         bzero(fp, sizeof(struct fnode));
  766         dprintf(("ntfs_fget: allocating fnode: %p\n",fp));
  767 
  768         fp->f_devvp = ntmp->ntm_devvp;
  769         fp->f_dev = ntmp->ntm_dev;
  770         fp->f_mp = ntmp;
  771 
  772         fp->f_ip = ip;
  773         fp->f_attrname = attrname;
  774         if (fp->f_attrname) fp->f_flag |= FN_AATTRNAME;
  775         fp->f_attrtype = attrtype;
  776 
  777         ntfs_ntref(ip);
  778 
  779         LIST_INSERT_HEAD(&ip->i_fnlist, fp, f_fnlist);
  780 
  781         *fpp = fp;
  782 
  783         return (0);
  784 }
  785 
  786 /*
  787  * Deallocate fnode, remove it from ntnode's fnode list.
  788  *
  789  * ntnode should be locked.
  790  */
  791 void
  792 ntfs_frele(
  793         struct fnode *fp)
  794 {
  795         struct ntnode *ip = FTONT(fp);
  796 
  797         dprintf(("ntfs_frele: fnode: %p for %d: %p\n", fp, ip->i_number, ip));
  798 
  799         dprintf(("ntfs_frele: deallocating fnode\n"));
  800         LIST_REMOVE(fp,f_fnlist);
  801         if (fp->f_flag & FN_AATTRNAME)
  802                 FREE(fp->f_attrname, M_TEMP);
  803         if (fp->f_dirblbuf)
  804                 FREE(fp->f_dirblbuf, M_NTFSDIR);
  805         FREE(fp, M_NTFSFNODE);
  806         ntfs_ntrele(ip);
  807 }
  808 
  809 /*
  810  * Lookup attribute name in format: [[:$ATTR_TYPE]:$ATTR_NAME], 
  811  * $ATTR_TYPE is searched in attrdefs read from $AttrDefs.
  812  * If $ATTR_TYPE nott specifed, ATTR_A_DATA assumed.
  813  */
  814 int
  815 ntfs_ntlookupattr(
  816                 struct ntfsmount * ntmp,
  817                 const char * name,
  818                 int namelen,
  819                 int *attrtype,
  820                 char **attrname)
  821 {
  822         const char *sys;
  823         size_t syslen, i;
  824         struct ntvattrdef *adp;
  825 
  826         if (namelen == 0)
  827                 return (0);
  828 
  829         if (name[0] == '$') {
  830                 sys = name;
  831                 for (syslen = 0; syslen < namelen; syslen++) {
  832                         if(sys[syslen] == ':') {
  833                                 name++;
  834                                 namelen--;
  835                                 break;
  836                         }
  837                 }
  838                 name += syslen;
  839                 namelen -= syslen;
  840 
  841                 adp = ntmp->ntm_ad;
  842                 for (i = 0; i < ntmp->ntm_adnum; i++){
  843                         if((syslen == adp->ad_namelen) && 
  844                            (!strncmp(sys,adp->ad_name,syslen))) {
  845                                 *attrtype = adp->ad_type;
  846                                 if(namelen) {
  847                                         MALLOC((*attrname), char *, namelen,
  848                                                 M_TEMP, M_WAITOK);
  849                                         memcpy((*attrname), name, namelen);
  850                                         (*attrname)[namelen] = '\0';
  851                                 }
  852                                 return (0);
  853                         }
  854                         adp++;
  855                 }
  856                 return (ENOENT);
  857         }
  858 
  859         if(namelen) {
  860                 MALLOC((*attrname), char *, namelen, M_TEMP, M_WAITOK);
  861                 memcpy((*attrname), name, namelen);
  862                 (*attrname)[namelen] = '\0';
  863                 *attrtype = NTFS_A_DATA;
  864         }
  865 
  866         return (0);
  867 }
  868 
  869 /*
  870  * Lookup specifed node for filename, matching cnp,
  871  * return fnode filled.
  872  */
  873 int
  874 ntfs_ntlookupfile(
  875               struct ntfsmount * ntmp,
  876               struct vnode * vp,
  877               struct componentname * cnp,
  878               struct vnode ** vpp)
  879 {
  880         struct fnode   *fp = VTOF(vp);
  881         struct ntnode  *ip = FTONT(fp);
  882         struct ntvattr *vap;    /* Root attribute */
  883         cn_t            cn;     /* VCN in current attribute */
  884         caddr_t         rdbuf;  /* Buffer to read directory's blocks  */
  885         u_int32_t       blsize;
  886         u_int32_t       rdsize; /* Length of data to read from current block */
  887         struct attr_indexentry *iep;
  888         int             error, res, anamelen, fnamelen;
  889         const char     *fname,*aname;
  890         u_int32_t       aoff;
  891 
  892         error = ntfs_ntget(ip);
  893         if (error)
  894                 return (error);
  895 
  896         error = ntfs_ntvattrget(ntmp, ip, NTFS_A_INDXROOT, "$I30", 0, &vap);
  897         if (error || (vap->va_flag & NTFS_AF_INRUN))
  898                 return (ENOTDIR);
  899 
  900         blsize = vap->va_a_iroot->ir_size;
  901         rdsize = vap->va_datalen;
  902 
  903         /*
  904          * Divide file name into: foofilefoofilefoofile[:attrspec]
  905          * Store like this:       fname:fnamelen       [aname:anamelen]
  906          */
  907         fname = cnp->cn_nameptr;
  908         aname = NULL;
  909         anamelen = 0;
  910         for (fnamelen = 0; fnamelen < cnp->cn_namelen; fnamelen++)
  911                 if(fname[fnamelen] == ':') {
  912                         aname = fname + fnamelen + 1;
  913                         anamelen = cnp->cn_namelen - fnamelen - 1;
  914                         dprintf(("ntfs_ntlookupfile: %s (%d), attr: %s (%d)\n",
  915                                 fname, fnamelen, aname, anamelen));
  916                         break;
  917                 }
  918 
  919         dprintf(("ntfs_ntlookupfile: blksz: %d, rdsz: %d\n", blsize, rdsize));
  920 
  921         MALLOC(rdbuf, caddr_t, blsize, M_TEMP, M_WAITOK);
  922 
  923         error = ntfs_readattr(ntmp, ip, NTFS_A_INDXROOT, "$I30",
  924                                0, rdsize, rdbuf);
  925         if (error)
  926                 goto fail;
  927 
  928         aoff = sizeof(struct attr_indexroot);
  929 
  930         do {
  931                 iep = (struct attr_indexentry *) (rdbuf + aoff);
  932 
  933                 while (!(iep->ie_flag & NTFS_IEFLAG_LAST) && (rdsize > aoff)) {
  934                         ddprintf(("scan: %d, %d\n",
  935                                   (u_int32_t) iep->ie_number,
  936                                   (u_int32_t) iep->ie_fnametype));
  937                         res = ntfs_uastricmp(ntmp, iep->ie_fname,
  938                                              iep->ie_fnamelen, fname,
  939                                              fnamelen);
  940                         if (res == 0) {
  941                                 /* Matched something (case ins.) */
  942                                 if (iep->ie_fnametype == 0 ||
  943                                     !(ntmp->ntm_flag & NTFS_MFLAG_CASEINS))
  944                                         res = ntfs_uastrcmp(ntmp,
  945                                                             iep->ie_fname,
  946                                                             iep->ie_fnamelen,
  947                                                             fname,
  948                                                             fnamelen);
  949                                 if (res == 0) {
  950                                         int attrtype = NTFS_A_DATA;
  951                                         char *attrname = NULL;
  952                                         struct fnode   *nfp;
  953                                         struct vnode   *nvp;
  954 
  955                                         if (aname) {
  956                                                 error = ntfs_ntlookupattr(ntmp,
  957                                                         aname, anamelen,
  958                                                         &attrtype, &attrname);
  959                                                 if (error)
  960                                                         goto fail;
  961                                         }
  962 
  963                                         /* Check if we've found ourself */
  964                                         if ((iep->ie_number == ip->i_number) &&
  965                                             (attrtype == fp->f_attrtype) &&
  966                                             ((!attrname && !fp->f_attrname) ||
  967                                              (attrname && fp->f_attrname &&
  968                                               !strcmp(attrname, fp->f_attrname)))) {
  969                                                 VREF(vp);
  970                                                 *vpp = vp;
  971                                                 goto fail;
  972                                         }
  973 
  974                                         /* vget node, but don't load it */
  975                                         error = ntfs_vgetex(ntmp->ntm_mountp,
  976                                                            iep->ie_number,
  977                                                            attrtype,
  978                                                            attrname,
  979                                                            LK_EXCLUSIVE,
  980                                                            VG_DONTLOADIN | 
  981                                                             VG_DONTVALIDFN,
  982                                                            curproc,
  983                                                            &nvp);
  984                                         if(error)
  985                                                 goto fail;
  986 
  987                                         nfp = VTOF(nvp);
  988 
  989                                         if (nfp->f_flag & FN_VALID) {
  990                                                 *vpp = nvp;
  991                                                 goto fail;
  992                                         }
  993 
  994                                         nfp->f_fflag = iep->ie_fflag;
  995                                         nfp->f_pnumber = iep->ie_fpnumber;
  996                                         nfp->f_times = iep->ie_ftimes;
  997 
  998                                         if((nfp->f_fflag & NTFS_FFLAG_DIR) &&
  999                                            (nfp->f_attrtype == NTFS_A_DATA) &&
 1000                                            (nfp->f_attrname == NULL))
 1001                                                 nfp->f_type = VDIR;     
 1002                                         else
 1003                                                 nfp->f_type = VREG;     
 1004 
 1005                                         nvp->v_type = nfp->f_type;
 1006 
 1007                                         if ((nfp->f_attrtype == NTFS_A_DATA) &&
 1008                                             (nfp->f_attrname == NULL)) {
 1009                                                 /* Opening default attribute */
 1010                                                 nfp->f_size = iep->ie_fsize;
 1011                                                 nfp->f_allocated = iep->ie_fallocated;
 1012                                                 nfp->f_flag |= FN_PRELOADED;
 1013                                         } else {
 1014                                                 error = ntfs_filesize(ntmp, nfp,
 1015                                                             &nfp->f_size,
 1016                                                             &nfp->f_allocated);
 1017                                                 if (error) {
 1018                                                         vput(nvp);
 1019                                                         goto fail;
 1020                                                 }
 1021                                         }
 1022 
 1023                                         nfp->f_flag &= ~FN_VALID;
 1024                                         *vpp = nvp;
 1025                                         goto fail;
 1026                                 }
 1027                         } else if (res > 0)
 1028                                 break;
 1029 
 1030                         aoff += iep->reclen;
 1031                         iep = (struct attr_indexentry *) (rdbuf + aoff);
 1032                 }
 1033 
 1034                 /* Dive if possible */
 1035                 if (iep->ie_flag & NTFS_IEFLAG_SUBNODE) {
 1036                         dprintf(("ntfs_ntlookupfile: diving\n"));
 1037 
 1038                         cn = *(cn_t *) (rdbuf + aoff +
 1039                                         iep->reclen - sizeof(cn_t));
 1040                         rdsize = blsize;
 1041 
 1042                         error = ntfs_readattr(ntmp, ip, NTFS_A_INDX, "$I30",
 1043                                              ntfs_cntob(cn), rdsize, rdbuf);
 1044                         if (error)
 1045                                 goto fail;
 1046 
 1047                         error = ntfs_procfixups(ntmp, NTFS_INDXMAGIC,
 1048                                                 rdbuf, rdsize);
 1049                         if (error)
 1050                                 goto fail;
 1051 
 1052                         aoff = (((struct attr_indexalloc *) rdbuf)->ia_hdrsize +
 1053                                 0x18);
 1054                 } else {
 1055                         dprintf(("ntfs_ntlookupfile: nowhere to dive :-(\n"));
 1056                         error = ENOENT;
 1057                         break;
 1058                 }
 1059         } while (1);
 1060 
 1061         dprintf(("finish\n"));
 1062 
 1063 fail:
 1064         ntfs_ntvattrrele(vap);
 1065         ntfs_ntput(ip);
 1066         FREE(rdbuf, M_TEMP);
 1067         return (error);
 1068 }
 1069 
 1070 /*
 1071  * Check if name type is permitted to show.
 1072  */
 1073 int
 1074 ntfs_isnamepermitted(
 1075                      struct ntfsmount * ntmp,
 1076                      struct attr_indexentry * iep)
 1077 {
 1078 
 1079         if (ntmp->ntm_flag & NTFS_MFLAG_ALLNAMES)
 1080                 return 1;
 1081 
 1082         switch (iep->ie_fnametype) {
 1083         case 2:
 1084                 ddprintf(("ntfs_isnamepermitted: skiped DOS name\n"));
 1085                 return 0;
 1086         case 0: case 1: case 3:
 1087                 return 1;
 1088         default:
 1089                 printf("ntfs_isnamepermitted: " \
 1090                        "WARNING! Unknown file name type: %d\n",
 1091                        iep->ie_fnametype);
 1092                 break;
 1093         }
 1094         return 0;
 1095 }
 1096 
 1097 /*
 1098  * Read ntfs dir like stream of attr_indexentry, not like btree of them.
 1099  * This is done by scaning $BITMAP:$I30 for busy clusters and reading them.
 1100  * Ofcouse $INDEX_ROOT:$I30 is read before. Last read values are stored in
 1101  * fnode, so we can skip toward record number num almost immediatly.
 1102  * Anyway this is rather slow routine. The problem is that we don't know
 1103  * how many records are there in $INDEX_ALLOCATION:$I30 block.
 1104  */
 1105 int
 1106 ntfs_ntreaddir(
 1107                struct ntfsmount * ntmp,
 1108                struct fnode * fp,
 1109                u_int32_t num,
 1110                struct attr_indexentry ** riepp)
 1111 {
 1112         struct ntnode  *ip = FTONT(fp);
 1113         struct ntvattr *vap = NULL;     /* IndexRoot attribute */
 1114         struct ntvattr *bmvap = NULL;   /* BitMap attribute */
 1115         struct ntvattr *iavap = NULL;   /* IndexAllocation attribute */
 1116         caddr_t         rdbuf;          /* Buffer to read directory's blocks  */
 1117         u_char         *bmp = NULL;     /* Bitmap */
 1118         u_int32_t       blsize;         /* Index allocation size (2048) */
 1119         u_int32_t       rdsize;         /* Length of data to read */
 1120         u_int32_t       attrnum;        /* Current attribute type */
 1121         u_int32_t       cpbl = 1;       /* Clusters per directory block */
 1122         u_int32_t       blnum;
 1123         struct attr_indexentry *iep;
 1124         int             error = ENOENT;
 1125         u_int32_t       aoff, cnum;
 1126 
 1127         dprintf(("ntfs_ntreaddir: read ino: %d, num: %d\n", ip->i_number, num));
 1128         error = ntfs_ntget(ip);
 1129         if (error)
 1130                 return (error);
 1131 
 1132         error = ntfs_ntvattrget(ntmp, ip, NTFS_A_INDXROOT, "$I30", 0, &vap);
 1133         if (error)
 1134                 return (ENOTDIR);
 1135 
 1136         if (fp->f_dirblbuf == NULL) {
 1137                 fp->f_dirblsz = vap->va_a_iroot->ir_size;
 1138                 MALLOC(fp->f_dirblbuf, caddr_t,
 1139                        max(vap->va_datalen,fp->f_dirblsz), M_NTFSDIR, M_WAITOK);
 1140         }
 1141 
 1142         blsize = fp->f_dirblsz;
 1143         rdbuf = fp->f_dirblbuf;
 1144 
 1145         dprintf(("ntfs_ntreaddir: rdbuf: 0x%p, blsize: %d\n", rdbuf, blsize));
 1146 
 1147         if (vap->va_a_iroot->ir_flag & NTFS_IRFLAG_INDXALLOC) {
 1148                 error = ntfs_ntvattrget(ntmp, ip, NTFS_A_INDXBITMAP, "$I30",
 1149                                         0, &bmvap);
 1150                 if (error) {
 1151                         error = ENOTDIR;
 1152                         goto fail;
 1153                 }
 1154                 MALLOC(bmp, u_char *, bmvap->va_datalen, M_TEMP, M_WAITOK);
 1155                 error = ntfs_readattr(ntmp, ip, NTFS_A_INDXBITMAP, "$I30", 0,
 1156                                        bmvap->va_datalen, bmp);
 1157                 if (error)
 1158                         goto fail;
 1159 
 1160                 error = ntfs_ntvattrget(ntmp, ip, NTFS_A_INDX, "$I30",
 1161                                         0, &iavap);
 1162                 if (error) {
 1163                         error = ENOTDIR;
 1164                         goto fail;
 1165                 }
 1166                 cpbl = ntfs_btocn(blsize + ntfs_cntob(1) - 1);
 1167                 dprintf(("ntfs_ntreaddir: indexalloc: %d, cpbl: %d\n",
 1168                          iavap->va_datalen, cpbl));
 1169         } else {
 1170                 dprintf(("ntfs_ntreadidir: w/o BitMap and IndexAllocation\n"));
 1171                 iavap = bmvap = NULL;
 1172                 bmp = NULL;
 1173         }
 1174 
 1175         /* Try use previous values */
 1176         if ((fp->f_lastdnum < num) && (fp->f_lastdnum != 0)) {
 1177                 attrnum = fp->f_lastdattr;
 1178                 aoff = fp->f_lastdoff;
 1179                 blnum = fp->f_lastdblnum;
 1180                 cnum = fp->f_lastdnum;
 1181         } else {
 1182                 attrnum = NTFS_A_INDXROOT;
 1183                 aoff = sizeof(struct attr_indexroot);
 1184                 blnum = 0;
 1185                 cnum = 0;
 1186         }
 1187 
 1188         do {
 1189                 dprintf(("ntfs_ntreaddir: scan: 0x%x, %d, %d, %d, %d\n",
 1190                          attrnum, (u_int32_t) blnum, cnum, num, aoff));
 1191                 rdsize = (attrnum == NTFS_A_INDXROOT) ? vap->va_datalen : blsize;
 1192                 error = ntfs_readattr(ntmp, ip, attrnum, "$I30",
 1193                                    ntfs_cntob(blnum * cpbl), rdsize, rdbuf);
 1194                 if (error)
 1195                         goto fail;
 1196 
 1197                 if (attrnum == NTFS_A_INDX) {
 1198                         error = ntfs_procfixups(ntmp, NTFS_INDXMAGIC,
 1199                                                 rdbuf, rdsize);
 1200                         if (error)
 1201                                 goto fail;
 1202                 }
 1203                 if (aoff == 0)
 1204                         aoff = (attrnum == NTFS_A_INDX) ?
 1205                                 (0x18 + ((struct attr_indexalloc *) rdbuf)->ia_hdrsize) :
 1206                                 sizeof(struct attr_indexroot);
 1207 
 1208                 iep = (struct attr_indexentry *) (rdbuf + aoff);
 1209                 while (!(iep->ie_flag & NTFS_IEFLAG_LAST) && (rdsize > aoff)) {
 1210                         if (ntfs_isnamepermitted(ntmp, iep)) {
 1211                                 if (cnum >= num) {
 1212                                         fp->f_lastdnum = cnum;
 1213                                         fp->f_lastdoff = aoff;
 1214                                         fp->f_lastdblnum = blnum;
 1215                                         fp->f_lastdattr = attrnum;
 1216 
 1217                                         *riepp = iep;
 1218 
 1219                                         error = 0;
 1220                                         goto fail;
 1221                                 }
 1222                                 cnum++;
 1223                         }
 1224                         aoff += iep->reclen;
 1225                         iep = (struct attr_indexentry *) (rdbuf + aoff);
 1226                 }
 1227 
 1228                 if (iavap) {
 1229                         if (attrnum == NTFS_A_INDXROOT)
 1230                                 blnum = 0;
 1231                         else
 1232                                 blnum++;
 1233 
 1234                         while (ntfs_cntob(blnum * cpbl) < iavap->va_datalen) {
 1235                                 if (bmp[blnum >> 3] & (1 << (blnum & 3)))
 1236                                         break;
 1237                                 blnum++;
 1238                         }
 1239 
 1240                         attrnum = NTFS_A_INDX;
 1241                         aoff = 0;
 1242                         if (ntfs_cntob(blnum * cpbl) >= iavap->va_datalen)
 1243                                 break;
 1244                         dprintf(("ntfs_ntreaddir: blnum: %d\n", (u_int32_t) blnum));
 1245                 }
 1246         } while (iavap);
 1247 
 1248         *riepp = NULL;
 1249         fp->f_lastdnum = 0;
 1250 
 1251 fail:
 1252         if (vap)
 1253                 ntfs_ntvattrrele(vap);
 1254         if (bmvap)
 1255                 ntfs_ntvattrrele(bmvap);
 1256         if (iavap)
 1257                 ntfs_ntvattrrele(iavap);
 1258         if (bmp)
 1259                 FREE(bmp, M_TEMP);
 1260         ntfs_ntput(ip);
 1261         return (error);
 1262 }
 1263 
 1264 /*
 1265  * Convert NTFS times that are in 100 ns units and begins from
 1266  * 1601 Jan 1 into unix times.
 1267  */
 1268 struct timespec
 1269 ntfs_nttimetounix(
 1270                   u_int64_t nt)
 1271 {
 1272         struct timespec t;
 1273 
 1274         /* WindowNT times are in 100 ns and from 1601 Jan 1 */
 1275         t.tv_nsec = (nt % (1000 * 1000 * 10)) * 100;
 1276         t.tv_sec = nt / (1000 * 1000 * 10) -
 1277                 369LL * 365LL * 24LL * 60LL * 60LL -
 1278                 89LL * 1LL * 24LL * 60LL * 60LL;
 1279         return (t);
 1280 }
 1281 
 1282 /*
 1283  * Get file times from NTFS_A_NAME attribute.
 1284  */
 1285 int
 1286 ntfs_times(
 1287            struct ntfsmount * ntmp,
 1288            struct ntnode * ip,
 1289            ntfs_times_t * tm)
 1290 {
 1291         struct ntvattr *vap;
 1292         int             error;
 1293 
 1294         dprintf(("ntfs_times: ino: %d...\n", ip->i_number));
 1295 
 1296         error = ntfs_ntget(ip);
 1297         if (error)
 1298                 return (error);
 1299 
 1300         error = ntfs_ntvattrget(ntmp, ip, NTFS_A_NAME, NULL, 0, &vap);
 1301         if (error) {
 1302                 ntfs_ntput(ip);
 1303                 return (error);
 1304         }
 1305         *tm = vap->va_a_name->n_times;
 1306         ntfs_ntvattrrele(vap);
 1307         ntfs_ntput(ip);
 1308 
 1309         return (0);
 1310 }
 1311 
 1312 /*
 1313  * Get file sizes from corresponding attribute. 
 1314  * 
 1315  * ntnode under fnode should be locked.
 1316  */
 1317 int
 1318 ntfs_filesize(
 1319               struct ntfsmount * ntmp,
 1320               struct fnode * fp,
 1321               u_int64_t * size,
 1322               u_int64_t * bytes)
 1323 {
 1324         struct ntvattr *vap;
 1325         struct ntnode *ip = FTONT(fp);
 1326         u_int64_t       sz, bn;
 1327         int             error;
 1328 
 1329         dprintf(("ntfs_filesize: ino: %d\n", ip->i_number));
 1330 
 1331         error = ntfs_ntvattrget(ntmp, ip,
 1332                 fp->f_attrtype, fp->f_attrname, 0, &vap);
 1333         if (error)
 1334                 return (error);
 1335 
 1336         bn = vap->va_allocated;
 1337         sz = vap->va_datalen;
 1338 
 1339         dprintf(("ntfs_filesize: %d bytes (%d bytes allocated)\n",
 1340                 (u_int32_t) sz, (u_int32_t) bn));
 1341 
 1342         if (size)
 1343                 *size = sz;
 1344         if (bytes)
 1345                 *bytes = bn;
 1346 
 1347         ntfs_ntvattrrele(vap);
 1348 
 1349         return (0);
 1350 }
 1351 
 1352 /*
 1353  * This is one of write routine.
 1354  *
 1355  * ntnode should be locked.
 1356  */
 1357 int
 1358 ntfs_writeattr_plain(
 1359                      struct ntfsmount * ntmp,
 1360                      struct ntnode * ip,
 1361                      u_int32_t attrnum, 
 1362                      char *attrname,
 1363                      off_t roff,
 1364                      size_t rsize,
 1365                      void *rdata,
 1366                      size_t * initp)
 1367 {
 1368         size_t          init;
 1369         int             error = 0;
 1370         off_t           off = roff, left = rsize, towrite;
 1371         caddr_t         data = rdata;
 1372         struct ntvattr *vap;
 1373         *initp = 0;
 1374 
 1375         while (left) {
 1376                 error = ntfs_ntvattrget(ntmp, ip, attrnum, attrname,
 1377                                         ntfs_btocn(off), &vap);
 1378                 if (error)
 1379                         return (error);
 1380                 towrite = min(left, ntfs_cntob(vap->va_vcnend + 1) - off);
 1381                 ddprintf(("ntfs_writeattr_plain: o: %d, s: %d (%d - %d)\n",
 1382                          (u_int32_t) off, (u_int32_t) towrite,
 1383                          (u_int32_t) vap->va_vcnstart,
 1384                          (u_int32_t) vap->va_vcnend));
 1385                 error = ntfs_writentvattr_plain(ntmp, ip, vap,
 1386                                          off - ntfs_cntob(vap->va_vcnstart),
 1387                                          towrite, data, &init);
 1388                 if (error) {
 1389                         printf("ntfs_writeattr_plain: " \
 1390                                "ntfs_writentvattr_plain failed: o: %d, s: %d\n",
 1391                                (u_int32_t) off, (u_int32_t) towrite);
 1392                         printf("ntfs_writeattr_plain: attrib: %d - %d\n",
 1393                                (u_int32_t) vap->va_vcnstart, 
 1394                                (u_int32_t) vap->va_vcnend);
 1395                         ntfs_ntvattrrele(vap);
 1396                         break;
 1397                 }
 1398                 ntfs_ntvattrrele(vap);
 1399                 left -= towrite;
 1400                 off += towrite;
 1401                 data = data + towrite;
 1402                 *initp += init;
 1403         }
 1404 
 1405         return (error);
 1406 }
 1407 
 1408 /*
 1409  * This is one of write routine.
 1410  *
 1411  * ntnode should be locked.
 1412  */
 1413 int
 1414 ntfs_writentvattr_plain(
 1415                         struct ntfsmount * ntmp,
 1416                         struct ntnode * ip,
 1417                         struct ntvattr * vap,
 1418                         off_t roff,
 1419                         size_t rsize,
 1420                         void *rdata,
 1421                         size_t * initp)
 1422 {
 1423         int             error = 0;
 1424         int             off;
 1425 
 1426         *initp = 0;
 1427         if (vap->va_flag & NTFS_AF_INRUN) {
 1428                 int             cnt;
 1429                 cn_t            ccn, ccl, cn, left, cl;
 1430                 caddr_t         data = rdata;
 1431                 struct buf     *bp;
 1432                 size_t          tocopy;
 1433 
 1434                 ddprintf(("ntfs_writentvattr_plain: data in run: %d chains\n",
 1435                          vap->va_vruncnt));
 1436 
 1437                 off = roff;
 1438                 left = rsize;
 1439                 ccl = 0;
 1440                 ccn = 0;
 1441                 cnt = 0;
 1442                 while (left && (cnt < vap->va_vruncnt)) {
 1443                         ccn = vap->va_vruncn[cnt];
 1444                         ccl = vap->va_vruncl[cnt];
 1445 
 1446                         ddprintf(("ntfs_writentvattr_plain: " \
 1447                                  "left %d, cn: 0x%x, cl: %d, off: %d\n", \
 1448                                  (u_int32_t) left, (u_int32_t) ccn, \
 1449                                  (u_int32_t) ccl, (u_int32_t) off));
 1450 
 1451                         if (ntfs_cntob(ccl) < off) {
 1452                                 off -= ntfs_cntob(ccl);
 1453                                 cnt++;
 1454                                 continue;
 1455                         }
 1456                         if (ccn || ip->i_number == NTFS_BOOTINO) { /* XXX */
 1457                                 ccl -= ntfs_btocn(off);
 1458                                 cn = ccn + ntfs_btocn(off);
 1459                                 off = ntfs_btocnoff(off);
 1460 
 1461                                 while (left && ccl) {
 1462                                         tocopy = min(left,
 1463                                                   min(ntfs_cntob(ccl) - off,
 1464                                                       MAXBSIZE - off));
 1465                                         cl = ntfs_btocl(tocopy + off);
 1466                                         ddprintf(("ntfs_writentvattr_plain: " \
 1467                                                 "write: cn: 0x%x cl: %d, " \
 1468                                                 "off: %d len: %d, left: %d\n",
 1469                                                 (u_int32_t) cn, 
 1470                                                 (u_int32_t) cl, 
 1471                                                 (u_int32_t) off, 
 1472                                                 (u_int32_t) tocopy, 
 1473                                                 (u_int32_t) left));
 1474                                         if ((off == 0) && 
 1475                                             (tocopy == ntfs_cntob(cl))) {
 1476                                                 bp = getblk(ntmp->ntm_devvp,
 1477                                                             ntfs_cntobn(cn),
 1478                                                             ntfs_cntob(cl),
 1479                                                             0, 0);
 1480                                                 clrbuf(bp);
 1481                                         } else {
 1482                                                 error = bread(ntmp->ntm_devvp,
 1483                                                               ntfs_cntobn(cn),
 1484                                                               ntfs_cntob(cl),
 1485                                                               NOCRED, &bp);
 1486                                                 if (error) {
 1487                                                         brelse(bp);
 1488                                                         return (error);
 1489                                                 }
 1490                                         }
 1491                                         memcpy(bp->b_data + off, data, tocopy);
 1492                                         bawrite(bp);
 1493                                         data = data + tocopy;
 1494                                         *initp += tocopy;
 1495                                         off = 0;
 1496                                         left -= tocopy;
 1497                                         cn += cl;
 1498                                         ccl -= cl;
 1499                                 }
 1500                         }
 1501                         cnt++;
 1502                 }
 1503                 if (left) {
 1504                         printf("ntfs_writentvattr_plain: POSSIBLE RUN ERROR\n");
 1505                         error = EINVAL;
 1506                 }
 1507         } else {
 1508                 printf("ntfs_writevattr_plain: CAN'T WRITE RES. ATTRIBUTE\n");
 1509                 error = ENOTTY;
 1510         }
 1511 
 1512         return (error);
 1513 }
 1514 
 1515 /*
 1516  * This is one of read routines.
 1517  *
 1518  * ntnode should be locked.
 1519  */
 1520 int
 1521 ntfs_readntvattr_plain(
 1522                         struct ntfsmount * ntmp,
 1523                         struct ntnode * ip,
 1524                         struct ntvattr * vap,
 1525                         off_t roff,
 1526                         size_t rsize,
 1527                         void *rdata,
 1528                         size_t * initp)
 1529 {
 1530         int             error = 0;
 1531         int             off;
 1532 
 1533         *initp = 0;
 1534         if (vap->va_flag & NTFS_AF_INRUN) {
 1535                 int             cnt;
 1536                 cn_t            ccn, ccl, cn, left, cl;
 1537                 caddr_t         data = rdata;
 1538                 struct buf     *bp;
 1539                 size_t          tocopy;
 1540 
 1541                 ddprintf(("ntfs_readntvattr_plain: data in run: %d chains\n",
 1542                          vap->va_vruncnt));
 1543 
 1544                 off = roff;
 1545                 left = rsize;
 1546                 ccl = 0;
 1547                 ccn = 0;
 1548                 cnt = 0;
 1549                 while (left && (cnt < vap->va_vruncnt)) {
 1550                         ccn = vap->va_vruncn[cnt];
 1551                         ccl = vap->va_vruncl[cnt];
 1552 
 1553                         ddprintf(("ntfs_readntvattr_plain: " \
 1554                                  "left %d, cn: 0x%x, cl: %d, off: %d\n", \
 1555                                  (u_int32_t) left, (u_int32_t) ccn, \
 1556                                  (u_int32_t) ccl, (u_int32_t) off));
 1557 
 1558                         if (ntfs_cntob(ccl) < off) {
 1559                                 off -= ntfs_cntob(ccl);
 1560                                 cnt++;
 1561                                 continue;
 1562                         }
 1563                         if (ccn || ip->i_number == NTFS_BOOTINO) {
 1564                                 ccl -= ntfs_btocn(off);
 1565                                 cn = ccn + ntfs_btocn(off);
 1566                                 off = ntfs_btocnoff(off);
 1567 
 1568                                 while (left && ccl) {
 1569                                         tocopy = min(left,
 1570                                                   min(ntfs_cntob(ccl) - off,
 1571                                                       MAXBSIZE - off));
 1572                                         cl = ntfs_btocl(tocopy + off);
 1573                                         ddprintf(("ntfs_readntvattr_plain: " \
 1574                                                 "read: cn: 0x%x cl: %d, " \
 1575                                                 "off: %d len: %d, left: %d\n",
 1576                                                 (u_int32_t) cn, 
 1577                                                 (u_int32_t) cl, 
 1578                                                 (u_int32_t) off, 
 1579                                                 (u_int32_t) tocopy, 
 1580                                                 (u_int32_t) left));
 1581                                         error = bread(ntmp->ntm_devvp,
 1582                                                       ntfs_cntobn(cn),
 1583                                                       ntfs_cntob(cl),
 1584                                                       NOCRED, &bp);
 1585                                         if (error) {
 1586                                                 brelse(bp);
 1587                                                 return (error);
 1588                                         }
 1589                                         memcpy(data, bp->b_data + off, tocopy);
 1590                                         brelse(bp);
 1591                                         data = data + tocopy;
 1592                                         *initp += tocopy;
 1593                                         off = 0;
 1594                                         left -= tocopy;
 1595                                         cn += cl;
 1596                                         ccl -= cl;
 1597                                 }
 1598                         } else {
 1599                                 tocopy = min(left, ntfs_cntob(ccl) - off);
 1600                                 ddprintf(("ntfs_readntvattr_plain: "
 1601                                         "sparce: ccn: 0x%x ccl: %d, off: %d, " \
 1602                                         " len: %d, left: %d\n", 
 1603                                         (u_int32_t) ccn, (u_int32_t) ccl, 
 1604                                         (u_int32_t) off, (u_int32_t) tocopy, 
 1605                                         (u_int32_t) left));
 1606                                 left -= tocopy;
 1607                                 off = 0;
 1608                                 bzero(data, tocopy);
 1609                                 data = data + tocopy;
 1610                         }
 1611                         cnt++;
 1612                 }
 1613                 if (left) {
 1614                         printf("ntfs_readntvattr_plain: POSSIBLE RUN ERROR\n");
 1615                         error = E2BIG;
 1616                 }
 1617         } else {
 1618                 ddprintf(("ntfs_readnvattr_plain: data is in mft record\n"));
 1619                 memcpy(rdata, vap->va_datap + roff, rsize);
 1620                 *initp += rsize;
 1621         }
 1622 
 1623         return (error);
 1624 }
 1625 
 1626 /*
 1627  * This is one of read routines.
 1628  *
 1629  * ntnode should be locked.
 1630  */
 1631 int
 1632 ntfs_readattr_plain(
 1633                      struct ntfsmount * ntmp,
 1634                      struct ntnode * ip,
 1635                      u_int32_t attrnum, 
 1636                      char *attrname,
 1637                      off_t roff,
 1638                      size_t rsize,
 1639                      void *rdata,
 1640                      size_t * initp)
 1641 {
 1642         size_t          init;
 1643         int             error = 0;
 1644         off_t           off = roff, left = rsize, toread;
 1645         caddr_t         data = rdata;
 1646         struct ntvattr *vap;
 1647         *initp = 0;
 1648 
 1649         while (left) {
 1650                 error = ntfs_ntvattrget(ntmp, ip, attrnum, attrname,
 1651                                         ntfs_btocn(off), &vap);
 1652                 if (error)
 1653                         return (error);
 1654                 toread = min(left, ntfs_cntob(vap->va_vcnend + 1) - off);
 1655                 ddprintf(("ntfs_readattr_plain: o: %d, s: %d (%d - %d)\n",
 1656                          (u_int32_t) off, (u_int32_t) toread,
 1657                          (u_int32_t) vap->va_vcnstart,
 1658                          (u_int32_t) vap->va_vcnend));
 1659                 error = ntfs_readntvattr_plain(ntmp, ip, vap,
 1660                                          off - ntfs_cntob(vap->va_vcnstart),
 1661                                          toread, data, &init);
 1662                 if (error) {
 1663                         printf("ntfs_readattr_plain: " \
 1664                                "ntfs_readntvattr_plain failed: o: %d, s: %d\n",
 1665                                (u_int32_t) off, (u_int32_t) toread);
 1666                         printf("ntfs_readattr_plain: attrib: %d - %d\n",
 1667                                (u_int32_t) vap->va_vcnstart, 
 1668                                (u_int32_t) vap->va_vcnend);
 1669                         ntfs_ntvattrrele(vap);
 1670                         break;
 1671                 }
 1672                 ntfs_ntvattrrele(vap);
 1673                 left -= toread;
 1674                 off += toread;
 1675                 data = data + toread;
 1676                 *initp += init;
 1677         }
 1678 
 1679         return (error);
 1680 }
 1681 
 1682 /*
 1683  * This is one of read routines.
 1684  *
 1685  * ntnode should be locked.
 1686  */
 1687 int
 1688 ntfs_readattr(
 1689                struct ntfsmount * ntmp,
 1690                struct ntnode * ip,
 1691                u_int32_t attrnum,
 1692                char *attrname,
 1693                off_t roff,
 1694                size_t rsize,
 1695                void *rdata)
 1696 {
 1697         int             error = 0;
 1698         struct ntvattr *vap;
 1699         size_t          init;
 1700 
 1701         ddprintf(("ntfs_readattr: reading %d: 0x%x, from %d size %d bytes\n",
 1702                ip->i_number, attrnum, (u_int32_t) roff, (u_int32_t) rsize));
 1703 
 1704         error = ntfs_ntvattrget(ntmp, ip, attrnum, attrname, 0, &vap);
 1705         if (error)
 1706                 return (error);
 1707 
 1708         if ((roff > vap->va_datalen) ||
 1709             (roff + rsize > vap->va_datalen)) {
 1710                 ddprintf(("ntfs_readattr: offset too big\n"));
 1711                 ntfs_ntvattrrele(vap);
 1712                 return (E2BIG);
 1713         }
 1714         if (vap->va_compression && vap->va_compressalg) {
 1715                 u_int8_t       *cup;
 1716                 u_int8_t       *uup;
 1717                 off_t           off = roff, left = rsize, tocopy;
 1718                 caddr_t         data = rdata;
 1719                 cn_t            cn;
 1720 
 1721                 ddprintf(("ntfs_ntreadattr: compression: %d\n",
 1722                          vap->va_compressalg));
 1723 
 1724                 MALLOC(cup, u_int8_t *, ntfs_cntob(NTFS_COMPUNIT_CL),
 1725                        M_NTFSDECOMP, M_WAITOK);
 1726                 MALLOC(uup, u_int8_t *, ntfs_cntob(NTFS_COMPUNIT_CL),
 1727                        M_NTFSDECOMP, M_WAITOK);
 1728 
 1729                 cn = (ntfs_btocn(roff)) & (~(NTFS_COMPUNIT_CL - 1));
 1730                 off = roff - ntfs_cntob(cn);
 1731 
 1732                 while (left) {
 1733                         error = ntfs_readattr_plain(ntmp, ip, attrnum,
 1734                                                   attrname, ntfs_cntob(cn),
 1735                                                   ntfs_cntob(NTFS_COMPUNIT_CL),
 1736                                                   cup, &init);
 1737                         if (error)
 1738                                 break;
 1739 
 1740                         tocopy = min(left, ntfs_cntob(NTFS_COMPUNIT_CL) - off);
 1741 
 1742                         if (init == ntfs_cntob(NTFS_COMPUNIT_CL)) {
 1743                                 memcpy(data, cup + off, tocopy);
 1744                         } else if (init == 0) {
 1745                                 bzero(data, tocopy);
 1746                         } else {
 1747                                 error = ntfs_uncompunit(ntmp, uup, cup);
 1748                                 if (error)
 1749                                         break;
 1750                                 memcpy(data, uup + off, tocopy);
 1751                         }
 1752 
 1753                         left -= tocopy;
 1754                         data = data + tocopy;
 1755                         off += tocopy - ntfs_cntob(NTFS_COMPUNIT_CL);
 1756                         cn += NTFS_COMPUNIT_CL;
 1757                 }
 1758 
 1759                 FREE(uup, M_NTFSDECOMP);
 1760                 FREE(cup, M_NTFSDECOMP);
 1761         } else
 1762                 error = ntfs_readattr_plain(ntmp, ip, attrnum, attrname,
 1763                                              roff, rsize, rdata, &init);
 1764         ntfs_ntvattrrele(vap);
 1765         return (error);
 1766 }
 1767 
 1768 #if UNUSED_CODE
 1769 int
 1770 ntfs_parserun(
 1771               cn_t * cn,
 1772               cn_t * cl,
 1773               u_int8_t * run,
 1774               u_long len,
 1775               u_long *off)
 1776 {
 1777         u_int8_t        sz;
 1778         int             i;
 1779 
 1780         if (NULL == run) {
 1781                 printf("ntfs_parsetun: run == NULL\n");
 1782                 return (EINVAL);
 1783         }
 1784         sz = run[(*off)++];
 1785         if (0 == sz) {
 1786                 printf("ntfs_parserun: trying to go out of run\n");
 1787                 return (E2BIG);
 1788         }
 1789         *cl = 0;
 1790         if ((sz & 0xF) > 8 || (*off) + (sz & 0xF) > len) {
 1791                 printf("ntfs_parserun: " \
 1792                        "bad run: length too big: sz: 0x%02x (%ld < %ld + sz)\n",
 1793                        sz, len, *off);
 1794                 return (EINVAL);
 1795         }
 1796         for (i = 0; i < (sz & 0xF); i++)
 1797                 *cl += (u_int32_t) run[(*off)++] << (i << 3);
 1798 
 1799         sz >>= 4;
 1800         if ((sz & 0xF) > 8 || (*off) + (sz & 0xF) > len) {
 1801                 printf("ntfs_parserun: " \
 1802                        "bad run: length too big: sz: 0x%02x (%ld < %ld + sz)\n",
 1803                        sz, len, *off);
 1804                 return (EINVAL);
 1805         }
 1806         for (i = 0; i < (sz & 0xF); i++)
 1807                 *cn += (u_int32_t) run[(*off)++] << (i << 3);
 1808 
 1809         return (0);
 1810 }
 1811 #endif
 1812 
 1813 /*
 1814  * Process fixup routine on given buffer.
 1815  */
 1816 int
 1817 ntfs_procfixups(
 1818                 struct ntfsmount * ntmp,
 1819                 u_int32_t magic,
 1820                 caddr_t buf,
 1821                 size_t len)
 1822 {
 1823         struct fixuphdr *fhp = (struct fixuphdr *) buf;
 1824         int             i;
 1825         u_int16_t       fixup;
 1826         u_int16_t      *fxp;
 1827         u_int16_t      *cfxp;
 1828 
 1829         if (fhp->fh_magic != magic) {
 1830                 printf("ntfs_procfixups: magic doesn't match: %08x != %08x\n",
 1831                        fhp->fh_magic, magic);
 1832                 return (EINVAL);
 1833         }
 1834         if ((fhp->fh_fnum - 1) * ntmp->ntm_bps != len) {
 1835                 printf("ntfs_procfixups: " \
 1836                        "bad fixups number: %d for %d bytes block\n", 
 1837                        fhp->fh_fnum, len);
 1838                 return (EINVAL);
 1839         }
 1840         if (fhp->fh_foff >= ntmp->ntm_spc * ntmp->ntm_mftrecsz * ntmp->ntm_bps) {
 1841                 printf("ntfs_procfixups: invalid offset: %x", fhp->fh_foff);
 1842                 return (EINVAL);
 1843         }
 1844         fxp = (u_int16_t *) (buf + fhp->fh_foff);
 1845         cfxp = (u_int16_t *) (buf + ntmp->ntm_bps - 2);
 1846         fixup = *fxp++;
 1847         for (i = 1; i < fhp->fh_fnum; i++, fxp++) {
 1848                 if (*cfxp != fixup) {
 1849                         printf("ntfs_procfixups: fixup %d doesn't match\n", i);
 1850                         return (EINVAL);
 1851                 }
 1852                 *cfxp = *fxp;
 1853                 ((caddr_t) cfxp) += ntmp->ntm_bps;
 1854         }
 1855         return (0);
 1856 }
 1857 
 1858 #if UNUSED_CODE
 1859 int
 1860 ntfs_runtocn(
 1861              cn_t * cn, 
 1862              struct ntfsmount * ntmp,
 1863              u_int8_t * run,
 1864              u_long len,
 1865              cn_t vcn)
 1866 {
 1867         cn_t            ccn = 0;
 1868         cn_t            ccl = 0;
 1869         u_long          off = 0;
 1870         int             error = 0;
 1871 
 1872 #if NTFS_DEBUG
 1873         int             i;
 1874         printf("ntfs_runtocn: run: 0x%p, %ld bytes, vcn:%ld\n",
 1875                 run, len, (u_long) vcn);
 1876         printf("ntfs_runtocn: run: ");
 1877         for (i = 0; i < len; i++)
 1878                 printf("0x%02x ", run[i]);
 1879         printf("\n");
 1880 #endif
 1881 
 1882         if (NULL == run) {
 1883                 printf("ntfs_runtocn: run == NULL\n");
 1884                 return (EINVAL);
 1885         }
 1886         do {
 1887                 if (run[off] == 0) {
 1888                         printf("ntfs_runtocn: vcn too big\n");
 1889                         return (E2BIG);
 1890                 }
 1891                 vcn -= ccl;
 1892                 error = ntfs_parserun(&ccn, &ccl, run, len, &off);
 1893                 if (error) {
 1894                         printf("ntfs_runtocn: ntfs_parserun failed\n");
 1895                         return (error);
 1896                 }
 1897         } while (ccl <= vcn);
 1898         *cn = ccn + vcn;
 1899         return (0);
 1900 }
 1901 #endif

Cache object: 30ebdde6eedc77b46a8e0486fe284330


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.