1/* 2 * misc.c 3 * 4 * PURPOSE 5 * Miscellaneous routines for the OSTA-UDF(tm) filesystem. 6 * 7 * CONTACTS 8 * E-mail regarding any portion of the Linux UDF file system should be 9 * directed to the development team mailing list (run by majordomo): 10 * linux_udf@hpesjro.fc.hp.com 11 * 12 * COPYRIGHT 13 * This file is distributed under the terms of the GNU General Public 14 * License (GPL). Copies of the GPL can be obtained from: 15 * ftp://prep.ai.mit.edu/pub/gnu/GPL 16 * Each contributing author retains all rights to their own work. 17 * 18 * (C) 1998 Dave Boynton 19 * (C) 1998-2001 Ben Fennema 20 * (C) 1999-2000 Stelias Computing Inc 21 * 22 * HISTORY 23 * 24 * 04/19/99 blf partial support for reading/writing specific EA's 25 */ 26 27#include "udfdecl.h" 28 29#include <linux/fs.h> 30#include <linux/string.h> 31#include <linux/udf_fs.h> 32 33#include "udf_i.h" 34#include "udf_sb.h" 35 36uint32_t 37udf64_low32(uint64_t indat) 38{ 39 return indat & 0x00000000FFFFFFFFULL; 40} 41 42uint32_t 43udf64_high32(uint64_t indat) 44{ 45 return indat >> 32; 46} 47 48extern struct buffer_head * 49udf_tgetblk(struct super_block *sb, int block) 50{ 51 if (UDF_QUERY_FLAG(sb, UDF_FLAG_VARCONV)) 52 return sb_getblk(sb, udf_fixed_to_variable(block)); 53 else 54 return sb_getblk(sb, block); 55} 56 57extern struct buffer_head * 58udf_tread(struct super_block *sb, int block) 59{ 60 if (UDF_QUERY_FLAG(sb, UDF_FLAG_VARCONV)) 61 return sb_bread(sb, udf_fixed_to_variable(block)); 62 else 63 return sb_bread(sb, block); 64} 65 66extern struct genericFormat * 67udf_add_extendedattr(struct inode * inode, uint32_t size, uint32_t type, 68 uint8_t loc, struct buffer_head **bh) 69{ 70 uint8_t *ea = NULL, *ad = NULL; 71 long_ad eaicb; 72 int offset; 73 74 *bh = udf_tread(inode->i_sb, inode->i_ino); 75 76 if (UDF_I_EXTENDED_FE(inode) == 0) 77 { 78 struct fileEntry *fe; 79 80 fe = (struct fileEntry *)(*bh)->b_data; 81 eaicb = lela_to_cpu(fe->extendedAttrICB); 82 offset = sizeof(struct fileEntry); 83 } 84 else 85 { 86 struct extendedFileEntry *efe; 87 88 efe = (struct extendedFileEntry *)(*bh)->b_data; 89 eaicb = lela_to_cpu(efe->extendedAttrICB); 90 offset = sizeof(struct extendedFileEntry); 91 } 92 93 ea = &(*bh)->b_data[offset]; 94 if (UDF_I_LENEATTR(inode)) 95 offset += UDF_I_LENEATTR(inode); 96 else 97 size += sizeof(struct extendedAttrHeaderDesc); 98 99 ad = &(*bh)->b_data[offset]; 100 if (UDF_I_LENALLOC(inode)) 101 offset += UDF_I_LENALLOC(inode); 102 103 offset = inode->i_sb->s_blocksize - offset; 104 105 /* TODO - Check for FreeEASpace */ 106 107 if (loc & 0x01 && offset >= size) 108 { 109 struct extendedAttrHeaderDesc *eahd; 110 eahd = (struct extendedAttrHeaderDesc *)ea; 111 112 if (UDF_I_LENALLOC(inode)) 113 { 114 memmove(&ad[size], ad, UDF_I_LENALLOC(inode)); 115 } 116 117 if (UDF_I_LENEATTR(inode)) 118 { 119 /* check checksum/crc */ 120 if (le16_to_cpu(eahd->descTag.tagIdent) != TAG_IDENT_EAHD || 121 le32_to_cpu(eahd->descTag.tagLocation) != UDF_I_LOCATION(inode).logicalBlockNum) 122 { 123 udf_release_data(*bh); 124 return NULL; 125 } 126 } 127 else 128 { 129 size -= sizeof(struct extendedAttrHeaderDesc); 130 UDF_I_LENEATTR(inode) += sizeof(struct extendedAttrHeaderDesc); 131 eahd->descTag.tagIdent = cpu_to_le16(TAG_IDENT_EAHD); 132 eahd->descTag.descVersion = cpu_to_le16(2); 133 eahd->descTag.tagSerialNum = cpu_to_le16(1); 134 eahd->descTag.tagLocation = cpu_to_le32(UDF_I_LOCATION(inode).logicalBlockNum); 135 eahd->impAttrLocation = cpu_to_le32(0xFFFFFFFF); 136 eahd->appAttrLocation = cpu_to_le32(0xFFFFFFFF); 137 } 138 139 offset = UDF_I_LENEATTR(inode); 140 if (type < 2048) 141 { 142 if (le32_to_cpu(eahd->appAttrLocation) < UDF_I_LENEATTR(inode)) 143 { 144 uint32_t aal = le32_to_cpu(eahd->appAttrLocation); 145 memmove(&ea[offset - aal + size], 146 &ea[aal], offset - aal); 147 offset -= aal; 148 eahd->appAttrLocation = cpu_to_le32(aal + size); 149 } 150 if (le32_to_cpu(eahd->impAttrLocation) < UDF_I_LENEATTR(inode)) 151 { 152 uint32_t ial = le32_to_cpu(eahd->impAttrLocation); 153 memmove(&ea[offset - ial + size], 154 &ea[ial], offset - ial); 155 offset -= ial; 156 eahd->impAttrLocation = cpu_to_le32(ial + size); 157 } 158 } 159 else if (type < 65536) 160 { 161 if (le32_to_cpu(eahd->appAttrLocation) < UDF_I_LENEATTR(inode)) 162 { 163 uint32_t aal = le32_to_cpu(eahd->appAttrLocation); 164 memmove(&ea[offset - aal + size], 165 &ea[aal], offset - aal); 166 offset -= aal; 167 eahd->appAttrLocation = cpu_to_le32(aal + size); 168 } 169 } 170 /* rewrite CRC + checksum of eahd */ 171 UDF_I_LENEATTR(inode) += size; 172 return (struct genericFormat *)&ea[offset]; 173 } 174 if (loc & 0x02) 175 { 176 } 177 udf_release_data(*bh); 178 return NULL; 179} 180 181extern struct genericFormat * 182udf_get_extendedattr(struct inode * inode, uint32_t type, uint8_t subtype, 183 struct buffer_head **bh) 184{ 185 struct genericFormat *gaf; 186 uint8_t *ea = NULL; 187 long_ad eaicb; 188 uint32_t offset; 189 190 *bh = udf_tread(inode->i_sb, inode->i_ino); 191 192 if (UDF_I_EXTENDED_FE(inode) == 0) 193 { 194 struct fileEntry *fe; 195 196 fe = (struct fileEntry *)(*bh)->b_data; 197 eaicb = lela_to_cpu(fe->extendedAttrICB); 198 if (UDF_I_LENEATTR(inode)) 199 ea = fe->extendedAttr; 200 } 201 else 202 { 203 struct extendedFileEntry *efe; 204 205 efe = (struct extendedFileEntry *)(*bh)->b_data; 206 eaicb = lela_to_cpu(efe->extendedAttrICB); 207 if (UDF_I_LENEATTR(inode)) 208 ea = efe->extendedAttr; 209 } 210 211 if (UDF_I_LENEATTR(inode)) 212 { 213 struct extendedAttrHeaderDesc *eahd; 214 eahd = (struct extendedAttrHeaderDesc *)ea; 215 216 /* check checksum/crc */ 217 if (le16_to_cpu(eahd->descTag.tagIdent) != TAG_IDENT_EAHD || 218 le32_to_cpu(eahd->descTag.tagLocation) != UDF_I_LOCATION(inode).logicalBlockNum) 219 { 220 udf_release_data(*bh); 221 return NULL; 222 } 223 224 if (type < 2048) 225 offset = sizeof(struct extendedAttrHeaderDesc); 226 else if (type < 65536) 227 offset = le32_to_cpu(eahd->impAttrLocation); 228 else 229 offset = le32_to_cpu(eahd->appAttrLocation); 230 231 while (offset < UDF_I_LENEATTR(inode)) 232 { 233 gaf = (struct genericFormat *)&ea[offset]; 234 if (le32_to_cpu(gaf->attrType) == type && gaf->attrSubtype == subtype) 235 return gaf; 236 else 237 offset += le32_to_cpu(gaf->attrLength); 238 } 239 } 240 241 udf_release_data(*bh); 242 if (eaicb.extLength) 243 { 244 /* TODO */ 245 } 246 return NULL; 247} 248 249/* 250 * udf_read_tagged 251 * 252 * PURPOSE 253 * Read the first block of a tagged descriptor. 254 * 255 * HISTORY 256 * July 1, 1997 - Andrew E. Mileski 257 * Written, tested, and released. 258 */ 259extern struct buffer_head * 260udf_read_tagged(struct super_block *sb, uint32_t block, uint32_t location, uint16_t *ident) 261{ 262 tag *tag_p; 263 struct buffer_head *bh = NULL; 264 register uint8_t checksum; 265 register int i; 266 267 /* Read the block */ 268 if (block == 0xFFFFFFFF) 269 return NULL; 270 271 bh = udf_tread(sb, block); 272 if (!bh) 273 { 274 udf_debug("block=%d, location=%d: read failed\n", block, location); 275 return NULL; 276 } 277 278 tag_p = (tag *)(bh->b_data); 279 280 *ident = le16_to_cpu(tag_p->tagIdent); 281 282 if ( location != le32_to_cpu(tag_p->tagLocation) ) 283 { 284 udf_debug("location mismatch block %u, tag %u != %u\n", 285 block, le32_to_cpu(tag_p->tagLocation), location); 286 goto error_out; 287 } 288 289 /* Verify the tag checksum */ 290 checksum = 0U; 291 for (i = 0; i < 4; i++) 292 checksum += (uint8_t)(bh->b_data[i]); 293 for (i = 5; i < 16; i++) 294 checksum += (uint8_t)(bh->b_data[i]); 295 if (checksum != tag_p->tagChecksum) { 296 printk(KERN_ERR "udf: tag checksum failed block %d\n", block); 297 goto error_out; 298 } 299 300 /* Verify the tag version */ 301 if (le16_to_cpu(tag_p->descVersion) != 0x0002U && 302 le16_to_cpu(tag_p->descVersion) != 0x0003U) 303 { 304 udf_debug("tag version 0x%04x != 0x0002 || 0x0003 block %d\n", 305 le16_to_cpu(tag_p->descVersion), block); 306 goto error_out; 307 } 308 309 /* Verify the descriptor CRC */ 310 if (le16_to_cpu(tag_p->descCRCLength) + sizeof(tag) > sb->s_blocksize || 311 le16_to_cpu(tag_p->descCRC) == udf_crc(bh->b_data + sizeof(tag), 312 le16_to_cpu(tag_p->descCRCLength), 0)) 313 { 314 return bh; 315 } 316 udf_debug("Crc failure block %d: crc = %d, crclen = %d\n", 317 block, le16_to_cpu(tag_p->descCRC), le16_to_cpu(tag_p->descCRCLength)); 318 319error_out: 320 brelse(bh); 321 return NULL; 322} 323 324extern struct buffer_head * 325udf_read_ptagged(struct super_block *sb, lb_addr loc, uint32_t offset, uint16_t *ident) 326{ 327 return udf_read_tagged(sb, udf_get_lb_pblock(sb, loc, offset), 328 loc.logicalBlockNum + offset, ident); 329} 330 331void udf_release_data(struct buffer_head *bh) 332{ 333 if (bh) 334 brelse(bh); 335} 336 337void udf_update_tag(char *data, int length) 338{ 339 tag *tptr = (tag *)data; 340 int i; 341 342 length -= sizeof(tag); 343 344 tptr->tagChecksum = 0; 345 tptr->descCRCLength = le16_to_cpu(length); 346 tptr->descCRC = le16_to_cpu(udf_crc(data + sizeof(tag), length, 0)); 347 348 for (i=0; i<16; i++) 349 if (i != 4) 350 tptr->tagChecksum += (uint8_t)(data[i]); 351} 352 353void udf_new_tag(char *data, uint16_t ident, uint16_t version, uint16_t snum, 354 uint32_t loc, int length) 355{ 356 tag *tptr = (tag *)data; 357 tptr->tagIdent = le16_to_cpu(ident); 358 tptr->descVersion = le16_to_cpu(version); 359 tptr->tagSerialNum = le16_to_cpu(snum); 360 tptr->tagLocation = le32_to_cpu(loc); 361 udf_update_tag(data, length); 362} 363