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