0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022 #include "udfdecl.h"
0023
0024 #include <linux/fs.h>
0025 #include <linux/string.h>
0026 #include <linux/crc-itu-t.h>
0027
0028 #include "udf_i.h"
0029 #include "udf_sb.h"
0030
0031 struct buffer_head *udf_tgetblk(struct super_block *sb, udf_pblk_t block)
0032 {
0033 if (UDF_QUERY_FLAG(sb, UDF_FLAG_VARCONV))
0034 return sb_getblk(sb, udf_fixed_to_variable(block));
0035 else
0036 return sb_getblk(sb, block);
0037 }
0038
0039 struct buffer_head *udf_tread(struct super_block *sb, udf_pblk_t block)
0040 {
0041 if (UDF_QUERY_FLAG(sb, UDF_FLAG_VARCONV))
0042 return sb_bread(sb, udf_fixed_to_variable(block));
0043 else
0044 return sb_bread(sb, block);
0045 }
0046
0047 struct genericFormat *udf_add_extendedattr(struct inode *inode, uint32_t size,
0048 uint32_t type, uint8_t loc)
0049 {
0050 uint8_t *ea = NULL, *ad = NULL;
0051 int offset;
0052 uint16_t crclen;
0053 struct udf_inode_info *iinfo = UDF_I(inode);
0054
0055 ea = iinfo->i_data;
0056 if (iinfo->i_lenEAttr) {
0057 ad = iinfo->i_data + iinfo->i_lenEAttr;
0058 } else {
0059 ad = ea;
0060 size += sizeof(struct extendedAttrHeaderDesc);
0061 }
0062
0063 offset = inode->i_sb->s_blocksize - udf_file_entry_alloc_offset(inode) -
0064 iinfo->i_lenAlloc;
0065
0066
0067
0068 if (loc & 0x01 && offset >= size) {
0069 struct extendedAttrHeaderDesc *eahd;
0070 eahd = (struct extendedAttrHeaderDesc *)ea;
0071
0072 if (iinfo->i_lenAlloc)
0073 memmove(&ad[size], ad, iinfo->i_lenAlloc);
0074
0075 if (iinfo->i_lenEAttr) {
0076
0077 if (eahd->descTag.tagIdent !=
0078 cpu_to_le16(TAG_IDENT_EAHD) ||
0079 le32_to_cpu(eahd->descTag.tagLocation) !=
0080 iinfo->i_location.logicalBlockNum)
0081 return NULL;
0082 } else {
0083 struct udf_sb_info *sbi = UDF_SB(inode->i_sb);
0084
0085 size -= sizeof(struct extendedAttrHeaderDesc);
0086 iinfo->i_lenEAttr +=
0087 sizeof(struct extendedAttrHeaderDesc);
0088 eahd->descTag.tagIdent = cpu_to_le16(TAG_IDENT_EAHD);
0089 if (sbi->s_udfrev >= 0x0200)
0090 eahd->descTag.descVersion = cpu_to_le16(3);
0091 else
0092 eahd->descTag.descVersion = cpu_to_le16(2);
0093 eahd->descTag.tagSerialNum =
0094 cpu_to_le16(sbi->s_serial_number);
0095 eahd->descTag.tagLocation = cpu_to_le32(
0096 iinfo->i_location.logicalBlockNum);
0097 eahd->impAttrLocation = cpu_to_le32(0xFFFFFFFF);
0098 eahd->appAttrLocation = cpu_to_le32(0xFFFFFFFF);
0099 }
0100
0101 offset = iinfo->i_lenEAttr;
0102 if (type < 2048) {
0103 if (le32_to_cpu(eahd->appAttrLocation) <
0104 iinfo->i_lenEAttr) {
0105 uint32_t aal =
0106 le32_to_cpu(eahd->appAttrLocation);
0107 memmove(&ea[offset - aal + size],
0108 &ea[aal], offset - aal);
0109 offset -= aal;
0110 eahd->appAttrLocation =
0111 cpu_to_le32(aal + size);
0112 }
0113 if (le32_to_cpu(eahd->impAttrLocation) <
0114 iinfo->i_lenEAttr) {
0115 uint32_t ial =
0116 le32_to_cpu(eahd->impAttrLocation);
0117 memmove(&ea[offset - ial + size],
0118 &ea[ial], offset - ial);
0119 offset -= ial;
0120 eahd->impAttrLocation =
0121 cpu_to_le32(ial + size);
0122 }
0123 } else if (type < 65536) {
0124 if (le32_to_cpu(eahd->appAttrLocation) <
0125 iinfo->i_lenEAttr) {
0126 uint32_t aal =
0127 le32_to_cpu(eahd->appAttrLocation);
0128 memmove(&ea[offset - aal + size],
0129 &ea[aal], offset - aal);
0130 offset -= aal;
0131 eahd->appAttrLocation =
0132 cpu_to_le32(aal + size);
0133 }
0134 }
0135
0136 crclen = sizeof(struct extendedAttrHeaderDesc) - sizeof(struct tag);
0137 eahd->descTag.descCRCLength = cpu_to_le16(crclen);
0138 eahd->descTag.descCRC = cpu_to_le16(crc_itu_t(0, (char *)eahd +
0139 sizeof(struct tag), crclen));
0140 eahd->descTag.tagChecksum = udf_tag_checksum(&eahd->descTag);
0141 iinfo->i_lenEAttr += size;
0142 return (struct genericFormat *)&ea[offset];
0143 }
0144
0145 return NULL;
0146 }
0147
0148 struct genericFormat *udf_get_extendedattr(struct inode *inode, uint32_t type,
0149 uint8_t subtype)
0150 {
0151 struct genericFormat *gaf;
0152 uint8_t *ea = NULL;
0153 uint32_t offset;
0154 struct udf_inode_info *iinfo = UDF_I(inode);
0155
0156 ea = iinfo->i_data;
0157
0158 if (iinfo->i_lenEAttr) {
0159 struct extendedAttrHeaderDesc *eahd;
0160 eahd = (struct extendedAttrHeaderDesc *)ea;
0161
0162
0163 if (eahd->descTag.tagIdent !=
0164 cpu_to_le16(TAG_IDENT_EAHD) ||
0165 le32_to_cpu(eahd->descTag.tagLocation) !=
0166 iinfo->i_location.logicalBlockNum)
0167 return NULL;
0168
0169 if (type < 2048)
0170 offset = sizeof(struct extendedAttrHeaderDesc);
0171 else if (type < 65536)
0172 offset = le32_to_cpu(eahd->impAttrLocation);
0173 else
0174 offset = le32_to_cpu(eahd->appAttrLocation);
0175
0176 while (offset + sizeof(*gaf) < iinfo->i_lenEAttr) {
0177 uint32_t attrLength;
0178
0179 gaf = (struct genericFormat *)&ea[offset];
0180 attrLength = le32_to_cpu(gaf->attrLength);
0181
0182
0183 if ((attrLength < sizeof(*gaf)) ||
0184 (attrLength > (iinfo->i_lenEAttr - offset)))
0185 break;
0186
0187 if (le32_to_cpu(gaf->attrType) == type &&
0188 gaf->attrSubtype == subtype)
0189 return gaf;
0190 else
0191 offset += attrLength;
0192 }
0193 }
0194
0195 return NULL;
0196 }
0197
0198
0199
0200
0201
0202
0203
0204
0205
0206
0207
0208 struct buffer_head *udf_read_tagged(struct super_block *sb, uint32_t block,
0209 uint32_t location, uint16_t *ident)
0210 {
0211 struct tag *tag_p;
0212 struct buffer_head *bh = NULL;
0213 u8 checksum;
0214
0215
0216 if (block == 0xFFFFFFFF)
0217 return NULL;
0218
0219 bh = udf_tread(sb, block);
0220 if (!bh) {
0221 udf_err(sb, "read failed, block=%u, location=%u\n",
0222 block, location);
0223 return NULL;
0224 }
0225
0226 tag_p = (struct tag *)(bh->b_data);
0227
0228 *ident = le16_to_cpu(tag_p->tagIdent);
0229
0230 if (location != le32_to_cpu(tag_p->tagLocation)) {
0231 udf_debug("location mismatch block %u, tag %u != %u\n",
0232 block, le32_to_cpu(tag_p->tagLocation), location);
0233 goto error_out;
0234 }
0235
0236
0237 checksum = udf_tag_checksum(tag_p);
0238 if (checksum != tag_p->tagChecksum) {
0239 udf_err(sb, "tag checksum failed, block %u: 0x%02x != 0x%02x\n",
0240 block, checksum, tag_p->tagChecksum);
0241 goto error_out;
0242 }
0243
0244
0245 if (tag_p->descVersion != cpu_to_le16(0x0002U) &&
0246 tag_p->descVersion != cpu_to_le16(0x0003U)) {
0247 udf_err(sb, "tag version 0x%04x != 0x0002 || 0x0003, block %u\n",
0248 le16_to_cpu(tag_p->descVersion), block);
0249 goto error_out;
0250 }
0251
0252
0253 if (le16_to_cpu(tag_p->descCRCLength) + sizeof(struct tag) > sb->s_blocksize ||
0254 le16_to_cpu(tag_p->descCRC) == crc_itu_t(0,
0255 bh->b_data + sizeof(struct tag),
0256 le16_to_cpu(tag_p->descCRCLength)))
0257 return bh;
0258
0259 udf_debug("Crc failure block %u: crc = %u, crclen = %u\n", block,
0260 le16_to_cpu(tag_p->descCRC),
0261 le16_to_cpu(tag_p->descCRCLength));
0262 error_out:
0263 brelse(bh);
0264 return NULL;
0265 }
0266
0267 struct buffer_head *udf_read_ptagged(struct super_block *sb,
0268 struct kernel_lb_addr *loc,
0269 uint32_t offset, uint16_t *ident)
0270 {
0271 return udf_read_tagged(sb, udf_get_lb_pblock(sb, loc, offset),
0272 loc->logicalBlockNum + offset, ident);
0273 }
0274
0275 void udf_update_tag(char *data, int length)
0276 {
0277 struct tag *tptr = (struct tag *)data;
0278 length -= sizeof(struct tag);
0279
0280 tptr->descCRCLength = cpu_to_le16(length);
0281 tptr->descCRC = cpu_to_le16(crc_itu_t(0, data + sizeof(struct tag), length));
0282 tptr->tagChecksum = udf_tag_checksum(tptr);
0283 }
0284
0285 void udf_new_tag(char *data, uint16_t ident, uint16_t version, uint16_t snum,
0286 uint32_t loc, int length)
0287 {
0288 struct tag *tptr = (struct tag *)data;
0289 tptr->tagIdent = cpu_to_le16(ident);
0290 tptr->descVersion = cpu_to_le16(version);
0291 tptr->tagSerialNum = cpu_to_le16(snum);
0292 tptr->tagLocation = cpu_to_le32(loc);
0293 udf_update_tag(data, length);
0294 }
0295
0296 u8 udf_tag_checksum(const struct tag *t)
0297 {
0298 u8 *data = (u8 *)t;
0299 u8 checksum = 0;
0300 int i;
0301 for (i = 0; i < sizeof(struct tag); ++i)
0302 if (i != 4)
0303 checksum += data[i];
0304 return checksum;
0305 }