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/fs/ntfs/mst.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 /*
    2  * mst.c - NTFS multi sector transfer protection handling code. Part of the
    3  *         Linux-NTFS project.
    4  *
    5  * Copyright (c) 2001-2004 Anton Altaparmakov
    6  *
    7  * This program/include file is free software; you can redistribute it and/or
    8  * modify it under the terms of the GNU General Public License as published
    9  * by the Free Software Foundation; either version 2 of the License, or
   10  * (at your option) any later version.
   11  *
   12  * This program/include file is distributed in the hope that it will be
   13  * useful, but WITHOUT ANY WARRANTY; without even the implied warranty
   14  * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   15  * GNU General Public License for more details.
   16  *
   17  * You should have received a copy of the GNU General Public License
   18  * along with this program (in the main directory of the Linux-NTFS
   19  * distribution in the file COPYING); if not, write to the Free Software
   20  * Foundation,Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
   21  */
   22 
   23 #include "ntfs.h"
   24 
   25 /**
   26  * post_read_mst_fixup - deprotect multi sector transfer protected data
   27  * @b:          pointer to the data to deprotect
   28  * @size:       size in bytes of @b
   29  *
   30  * Perform the necessary post read multi sector transfer fixup and detect the
   31  * presence of incomplete multi sector transfers. - In that case, overwrite the
   32  * magic of the ntfs record header being processed with "BAAD" (in memory only!)
   33  * and abort processing.
   34  *
   35  * Return 0 on success and -EINVAL on error ("BAAD" magic will be present).
   36  *
   37  * NOTE: We consider the absence / invalidity of an update sequence array to
   38  * mean that the structure is not protected at all and hence doesn't need to
   39  * be fixed up. Thus, we return success and not failure in this case. This is
   40  * in contrast to pre_write_mst_fixup(), see below.
   41  */
   42 int post_read_mst_fixup(NTFS_RECORD *b, const u32 size)
   43 {
   44         u16 usa_ofs, usa_count, usn;
   45         u16 *usa_pos, *data_pos;
   46 
   47         /* Setup the variables. */
   48         usa_ofs = le16_to_cpu(b->usa_ofs);
   49         /* Decrement usa_count to get number of fixups. */
   50         usa_count = le16_to_cpu(b->usa_count) - 1;
   51         /* Size and alignment checks. */
   52         if ( size & (NTFS_BLOCK_SIZE - 1)       ||
   53              usa_ofs & 1                        ||
   54              usa_ofs + (usa_count * 2) > size   ||
   55              (size >> NTFS_BLOCK_SIZE_BITS) != usa_count)
   56                 return 0;
   57         /* Position of usn in update sequence array. */
   58         usa_pos = (u16*)b + usa_ofs/sizeof(u16);
   59         /*
   60          * The update sequence number which has to be equal to each of the
   61          * u16 values before they are fixed up. Note no need to care for
   62          * endianness since we are comparing and moving data for on disk
   63          * structures which means the data is consistent. - If it is
   64          * consistenty the wrong endianness it doesn't make any difference.
   65          */
   66         usn = *usa_pos;
   67         /*
   68          * Position in protected data of first u16 that needs fixing up.
   69          */
   70         data_pos = (u16*)b + NTFS_BLOCK_SIZE/sizeof(u16) - 1;
   71         /*
   72          * Check for incomplete multi sector transfer(s).
   73          */
   74         while (usa_count--) {
   75                 if (*data_pos != usn) {
   76                         /*
   77                          * Incomplete multi sector transfer detected! )-:
   78                          * Set the magic to "BAAD" and return failure.
   79                          * Note that magic_BAAD is already converted to le32.
   80                          */
   81                         b->magic = magic_BAAD;
   82                         return -EINVAL;
   83                 }
   84                 data_pos += NTFS_BLOCK_SIZE/sizeof(u16);
   85         }
   86         /* Re-setup the variables. */
   87         usa_count = le16_to_cpu(b->usa_count) - 1;
   88         data_pos = (u16*)b + NTFS_BLOCK_SIZE/sizeof(u16) - 1;
   89         /* Fixup all sectors. */
   90         while (usa_count--) {
   91                 /*
   92                  * Increment position in usa and restore original data from
   93                  * the usa into the data buffer.
   94                  */
   95                 *data_pos = *(++usa_pos);
   96                 /* Increment position in data as well. */
   97                 data_pos += NTFS_BLOCK_SIZE/sizeof(u16);
   98         }
   99         return 0;
  100 }
  101 
  102 /**
  103  * pre_write_mst_fixup - apply multi sector transfer protection
  104  * @b:          pointer to the data to protect
  105  * @size:       size in bytes of @b
  106  *
  107  * Perform the necessary pre write multi sector transfer fixup on the data
  108  * pointer to by @b of @size.
  109  *
  110  * Return 0 if fixup applied (success) or -EINVAL if no fixup was performed
  111  * (assumed not needed). This is in contrast to post_read_mst_fixup() above.
  112  *
  113  * NOTE: We consider the absence / invalidity of an update sequence array to
  114  * mean that the structure is not subject to protection and hence doesn't need
  115  * to be fixed up. This means that you have to create a valid update sequence
  116  * array header in the ntfs record before calling this function, otherwise it
  117  * will fail (the header needs to contain the position of the update sequence
  118  * array together with the number of elements in the array). You also need to
  119  * initialise the update sequence number before calling this function
  120  * otherwise a random word will be used (whatever was in the record at that
  121  * position at that time).
  122  */
  123 int pre_write_mst_fixup(NTFS_RECORD *b, const u32 size)
  124 {
  125         le16 *usa_pos, *data_pos;
  126         u16 usa_ofs, usa_count, usn;
  127         le16 le_usn;
  128 
  129         /* Sanity check + only fixup if it makes sense. */
  130         if (!b || ntfs_is_baad_record(b->magic) ||
  131                         ntfs_is_hole_record(b->magic))
  132                 return -EINVAL;
  133         /* Setup the variables. */
  134         usa_ofs = le16_to_cpu(b->usa_ofs);
  135         /* Decrement usa_count to get number of fixups. */
  136         usa_count = le16_to_cpu(b->usa_count) - 1;
  137         /* Size and alignment checks. */
  138         if ( size & (NTFS_BLOCK_SIZE - 1)       ||
  139              usa_ofs & 1                        ||
  140              usa_ofs + (usa_count * 2) > size   ||
  141              (size >> NTFS_BLOCK_SIZE_BITS) != usa_count)
  142                 return -EINVAL;
  143         /* Position of usn in update sequence array. */
  144         usa_pos = (le16*)((u8*)b + usa_ofs);
  145         /*
  146          * Cyclically increment the update sequence number
  147          * (skipping 0 and -1, i.e. 0xffff).
  148          */
  149         usn = le16_to_cpup(usa_pos) + 1;
  150         if (usn == 0xffff || !usn)
  151                 usn = 1;
  152         le_usn = cpu_to_le16(usn);
  153         *usa_pos = le_usn;
  154         /* Position in data of first u16 that needs fixing up. */
  155         data_pos = (le16*)b + NTFS_BLOCK_SIZE/sizeof(le16) - 1;
  156         /* Fixup all sectors. */
  157         while (usa_count--) {
  158                 /*
  159                  * Increment the position in the usa and save the
  160                  * original data from the data buffer into the usa.
  161                  */
  162                 *(++usa_pos) = *data_pos;
  163                 /* Apply fixup to data. */
  164                 *data_pos = le_usn;
  165                 /* Increment position in data as well. */
  166                 data_pos += NTFS_BLOCK_SIZE/sizeof(le16);
  167         }
  168         return 0;
  169 }
  170 
  171 /**
  172  * post_write_mst_fixup - fast deprotect multi sector transfer protected data
  173  * @b:          pointer to the data to deprotect
  174  *
  175  * Perform the necessary post write multi sector transfer fixup, not checking
  176  * for any errors, because we assume we have just used pre_write_mst_fixup(),
  177  * thus the data will be fine or we would never have gotten here.
  178  */
  179 void post_write_mst_fixup(NTFS_RECORD *b)
  180 {
  181         le16 *usa_pos, *data_pos;
  182 
  183         u16 usa_ofs = le16_to_cpu(b->usa_ofs);
  184         u16 usa_count = le16_to_cpu(b->usa_count) - 1;
  185 
  186         /* Position of usn in update sequence array. */
  187         usa_pos = (le16*)b + usa_ofs/sizeof(le16);
  188 
  189         /* Position in protected data of first u16 that needs fixing up. */
  190         data_pos = (le16*)b + NTFS_BLOCK_SIZE/sizeof(le16) - 1;
  191 
  192         /* Fixup all sectors. */
  193         while (usa_count--) {
  194                 /*
  195                  * Increment position in usa and restore original data from
  196                  * the usa into the data buffer.
  197                  */
  198                 *data_pos = *(++usa_pos);
  199 
  200                 /* Increment position in data as well. */
  201                 data_pos += NTFS_BLOCK_SIZE/sizeof(le16);
  202         }
  203 }

Cache object: 67f4a21af3b097f264e871ab63175a96


[ 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.