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/udf/misc.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  * misc.c
    3  *
    4  * PURPOSE
    5  *      Miscellaneous routines for the OSTA-UDF(tm) filesystem.
    6  *
    7  * COPYRIGHT
    8  *      This file is distributed under the terms of the GNU General Public
    9  *      License (GPL). Copies of the GPL can be obtained from:
   10  *              ftp://prep.ai.mit.edu/pub/gnu/GPL
   11  *      Each contributing author retains all rights to their own work.
   12  *
   13  *  (C) 1998 Dave Boynton
   14  *  (C) 1998-2004 Ben Fennema
   15  *  (C) 1999-2000 Stelias Computing Inc
   16  *
   17  * HISTORY
   18  *
   19  *  04/19/99 blf  partial support for reading/writing specific EA's
   20  */
   21 
   22 #include "udfdecl.h"
   23 
   24 #include <linux/fs.h>
   25 #include <linux/string.h>
   26 #include <linux/buffer_head.h>
   27 #include <linux/crc-itu-t.h>
   28 
   29 #include "udf_i.h"
   30 #include "udf_sb.h"
   31 
   32 struct buffer_head *udf_tgetblk(struct super_block *sb, int block)
   33 {
   34         if (UDF_QUERY_FLAG(sb, UDF_FLAG_VARCONV))
   35                 return sb_getblk(sb, udf_fixed_to_variable(block));
   36         else
   37                 return sb_getblk(sb, block);
   38 }
   39 
   40 struct buffer_head *udf_tread(struct super_block *sb, int block)
   41 {
   42         if (UDF_QUERY_FLAG(sb, UDF_FLAG_VARCONV))
   43                 return sb_bread(sb, udf_fixed_to_variable(block));
   44         else
   45                 return sb_bread(sb, block);
   46 }
   47 
   48 struct genericFormat *udf_add_extendedattr(struct inode *inode, uint32_t size,
   49                                            uint32_t type, uint8_t loc)
   50 {
   51         uint8_t *ea = NULL, *ad = NULL;
   52         int offset;
   53         uint16_t crclen;
   54         struct udf_inode_info *iinfo = UDF_I(inode);
   55 
   56         ea = iinfo->i_ext.i_data;
   57         if (iinfo->i_lenEAttr) {
   58                 ad = iinfo->i_ext.i_data + iinfo->i_lenEAttr;
   59         } else {
   60                 ad = ea;
   61                 size += sizeof(struct extendedAttrHeaderDesc);
   62         }
   63 
   64         offset = inode->i_sb->s_blocksize - udf_file_entry_alloc_offset(inode) -
   65                 iinfo->i_lenAlloc;
   66 
   67         /* TODO - Check for FreeEASpace */
   68 
   69         if (loc & 0x01 && offset >= size) {
   70                 struct extendedAttrHeaderDesc *eahd;
   71                 eahd = (struct extendedAttrHeaderDesc *)ea;
   72 
   73                 if (iinfo->i_lenAlloc)
   74                         memmove(&ad[size], ad, iinfo->i_lenAlloc);
   75 
   76                 if (iinfo->i_lenEAttr) {
   77                         /* check checksum/crc */
   78                         if (eahd->descTag.tagIdent !=
   79                                         cpu_to_le16(TAG_IDENT_EAHD) ||
   80                             le32_to_cpu(eahd->descTag.tagLocation) !=
   81                                         iinfo->i_location.logicalBlockNum)
   82                                 return NULL;
   83                 } else {
   84                         struct udf_sb_info *sbi = UDF_SB(inode->i_sb);
   85 
   86                         size -= sizeof(struct extendedAttrHeaderDesc);
   87                         iinfo->i_lenEAttr +=
   88                                 sizeof(struct extendedAttrHeaderDesc);
   89                         eahd->descTag.tagIdent = cpu_to_le16(TAG_IDENT_EAHD);
   90                         if (sbi->s_udfrev >= 0x0200)
   91                                 eahd->descTag.descVersion = cpu_to_le16(3);
   92                         else
   93                                 eahd->descTag.descVersion = cpu_to_le16(2);
   94                         eahd->descTag.tagSerialNum =
   95                                         cpu_to_le16(sbi->s_serial_number);
   96                         eahd->descTag.tagLocation = cpu_to_le32(
   97                                         iinfo->i_location.logicalBlockNum);
   98                         eahd->impAttrLocation = cpu_to_le32(0xFFFFFFFF);
   99                         eahd->appAttrLocation = cpu_to_le32(0xFFFFFFFF);
  100                 }
  101 
  102                 offset = iinfo->i_lenEAttr;
  103                 if (type < 2048) {
  104                         if (le32_to_cpu(eahd->appAttrLocation) <
  105                                         iinfo->i_lenEAttr) {
  106                                 uint32_t aal =
  107                                         le32_to_cpu(eahd->appAttrLocation);
  108                                 memmove(&ea[offset - aal + size],
  109                                         &ea[aal], offset - aal);
  110                                 offset -= aal;
  111                                 eahd->appAttrLocation =
  112                                                 cpu_to_le32(aal + size);
  113                         }
  114                         if (le32_to_cpu(eahd->impAttrLocation) <
  115                                         iinfo->i_lenEAttr) {
  116                                 uint32_t ial =
  117                                         le32_to_cpu(eahd->impAttrLocation);
  118                                 memmove(&ea[offset - ial + size],
  119                                         &ea[ial], offset - ial);
  120                                 offset -= ial;
  121                                 eahd->impAttrLocation =
  122                                                 cpu_to_le32(ial + size);
  123                         }
  124                 } else if (type < 65536) {
  125                         if (le32_to_cpu(eahd->appAttrLocation) <
  126                                         iinfo->i_lenEAttr) {
  127                                 uint32_t aal =
  128                                         le32_to_cpu(eahd->appAttrLocation);
  129                                 memmove(&ea[offset - aal + size],
  130                                         &ea[aal], offset - aal);
  131                                 offset -= aal;
  132                                 eahd->appAttrLocation =
  133                                                 cpu_to_le32(aal + size);
  134                         }
  135                 }
  136                 /* rewrite CRC + checksum of eahd */
  137                 crclen = sizeof(struct extendedAttrHeaderDesc) - sizeof(struct tag);
  138                 eahd->descTag.descCRCLength = cpu_to_le16(crclen);
  139                 eahd->descTag.descCRC = cpu_to_le16(crc_itu_t(0, (char *)eahd +
  140                                                 sizeof(struct tag), crclen));
  141                 eahd->descTag.tagChecksum = udf_tag_checksum(&eahd->descTag);
  142                 iinfo->i_lenEAttr += size;
  143                 return (struct genericFormat *)&ea[offset];
  144         }
  145         if (loc & 0x02)
  146                 ;
  147 
  148         return NULL;
  149 }
  150 
  151 struct genericFormat *udf_get_extendedattr(struct inode *inode, uint32_t type,
  152                                            uint8_t subtype)
  153 {
  154         struct genericFormat *gaf;
  155         uint8_t *ea = NULL;
  156         uint32_t offset;
  157         struct udf_inode_info *iinfo = UDF_I(inode);
  158 
  159         ea = iinfo->i_ext.i_data;
  160 
  161         if (iinfo->i_lenEAttr) {
  162                 struct extendedAttrHeaderDesc *eahd;
  163                 eahd = (struct extendedAttrHeaderDesc *)ea;
  164 
  165                 /* check checksum/crc */
  166                 if (eahd->descTag.tagIdent !=
  167                                 cpu_to_le16(TAG_IDENT_EAHD) ||
  168                     le32_to_cpu(eahd->descTag.tagLocation) !=
  169                                 iinfo->i_location.logicalBlockNum)
  170                         return NULL;
  171 
  172                 if (type < 2048)
  173                         offset = sizeof(struct extendedAttrHeaderDesc);
  174                 else if (type < 65536)
  175                         offset = le32_to_cpu(eahd->impAttrLocation);
  176                 else
  177                         offset = le32_to_cpu(eahd->appAttrLocation);
  178 
  179                 while (offset < iinfo->i_lenEAttr) {
  180                         gaf = (struct genericFormat *)&ea[offset];
  181                         if (le32_to_cpu(gaf->attrType) == type &&
  182                                         gaf->attrSubtype == subtype)
  183                                 return gaf;
  184                         else
  185                                 offset += le32_to_cpu(gaf->attrLength);
  186                 }
  187         }
  188 
  189         return NULL;
  190 }
  191 
  192 /*
  193  * udf_read_tagged
  194  *
  195  * PURPOSE
  196  *      Read the first block of a tagged descriptor.
  197  *
  198  * HISTORY
  199  *      July 1, 1997 - Andrew E. Mileski
  200  *      Written, tested, and released.
  201  */
  202 struct buffer_head *udf_read_tagged(struct super_block *sb, uint32_t block,
  203                                     uint32_t location, uint16_t *ident)
  204 {
  205         struct tag *tag_p;
  206         struct buffer_head *bh = NULL;
  207         u8 checksum;
  208 
  209         /* Read the block */
  210         if (block == 0xFFFFFFFF)
  211                 return NULL;
  212 
  213         bh = udf_tread(sb, block);
  214         if (!bh) {
  215                 udf_err(sb, "read failed, block=%u, location=%d\n",
  216                         block, location);
  217                 return NULL;
  218         }
  219 
  220         tag_p = (struct tag *)(bh->b_data);
  221 
  222         *ident = le16_to_cpu(tag_p->tagIdent);
  223 
  224         if (location != le32_to_cpu(tag_p->tagLocation)) {
  225                 udf_debug("location mismatch block %u, tag %u != %u\n",
  226                           block, le32_to_cpu(tag_p->tagLocation), location);
  227                 goto error_out;
  228         }
  229 
  230         /* Verify the tag checksum */
  231         checksum = udf_tag_checksum(tag_p);
  232         if (checksum != tag_p->tagChecksum) {
  233                 udf_err(sb, "tag checksum failed, block %u: 0x%02x != 0x%02x\n",
  234                         block, checksum, tag_p->tagChecksum);
  235                 goto error_out;
  236         }
  237 
  238         /* Verify the tag version */
  239         if (tag_p->descVersion != cpu_to_le16(0x0002U) &&
  240             tag_p->descVersion != cpu_to_le16(0x0003U)) {
  241                 udf_err(sb, "tag version 0x%04x != 0x0002 || 0x0003, block %u\n",
  242                         le16_to_cpu(tag_p->descVersion), block);
  243                 goto error_out;
  244         }
  245 
  246         /* Verify the descriptor CRC */
  247         if (le16_to_cpu(tag_p->descCRCLength) + sizeof(struct tag) > sb->s_blocksize ||
  248             le16_to_cpu(tag_p->descCRC) == crc_itu_t(0,
  249                                         bh->b_data + sizeof(struct tag),
  250                                         le16_to_cpu(tag_p->descCRCLength)))
  251                 return bh;
  252 
  253         udf_debug("Crc failure block %d: crc = %d, crclen = %d\n", block,
  254                   le16_to_cpu(tag_p->descCRC),
  255                   le16_to_cpu(tag_p->descCRCLength));
  256 error_out:
  257         brelse(bh);
  258         return NULL;
  259 }
  260 
  261 struct buffer_head *udf_read_ptagged(struct super_block *sb,
  262                                      struct kernel_lb_addr *loc,
  263                                      uint32_t offset, uint16_t *ident)
  264 {
  265         return udf_read_tagged(sb, udf_get_lb_pblock(sb, loc, offset),
  266                                loc->logicalBlockNum + offset, ident);
  267 }
  268 
  269 void udf_update_tag(char *data, int length)
  270 {
  271         struct tag *tptr = (struct tag *)data;
  272         length -= sizeof(struct tag);
  273 
  274         tptr->descCRCLength = cpu_to_le16(length);
  275         tptr->descCRC = cpu_to_le16(crc_itu_t(0, data + sizeof(struct tag), length));
  276         tptr->tagChecksum = udf_tag_checksum(tptr);
  277 }
  278 
  279 void udf_new_tag(char *data, uint16_t ident, uint16_t version, uint16_t snum,
  280                  uint32_t loc, int length)
  281 {
  282         struct tag *tptr = (struct tag *)data;
  283         tptr->tagIdent = cpu_to_le16(ident);
  284         tptr->descVersion = cpu_to_le16(version);
  285         tptr->tagSerialNum = cpu_to_le16(snum);
  286         tptr->tagLocation = cpu_to_le32(loc);
  287         udf_update_tag(data, length);
  288 }
  289 
  290 u8 udf_tag_checksum(const struct tag *t)
  291 {
  292         u8 *data = (u8 *)t;
  293         u8 checksum = 0;
  294         int i;
  295         for (i = 0; i < sizeof(struct tag); ++i)
  296                 if (i != 4) /* position of checksum */
  297                         checksum += data[i];
  298         return checksum;
  299 }

Cache object: 86cae1f19ecbfdef22bbf77cbf14d945


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