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