diff options
Diffstat (limited to 'fs/udf/misc.c')
-rw-r--r-- | fs/udf/misc.c | 146 |
1 files changed, 80 insertions, 66 deletions
diff --git a/fs/udf/misc.c b/fs/udf/misc.c index 15297deb5051..a1d6da0caf71 100644 --- a/fs/udf/misc.c +++ b/fs/udf/misc.c | |||
@@ -51,18 +51,18 @@ struct genericFormat *udf_add_extendedattr(struct inode *inode, uint32_t size, | |||
51 | uint8_t *ea = NULL, *ad = NULL; | 51 | uint8_t *ea = NULL, *ad = NULL; |
52 | int offset; | 52 | int offset; |
53 | uint16_t crclen; | 53 | uint16_t crclen; |
54 | int i; | 54 | struct udf_inode_info *iinfo = UDF_I(inode); |
55 | 55 | ||
56 | ea = UDF_I_DATA(inode); | 56 | ea = iinfo->i_ext.i_data; |
57 | if (UDF_I_LENEATTR(inode)) { | 57 | if (iinfo->i_lenEAttr) { |
58 | ad = UDF_I_DATA(inode) + UDF_I_LENEATTR(inode); | 58 | ad = iinfo->i_ext.i_data + iinfo->i_lenEAttr; |
59 | } else { | 59 | } else { |
60 | ad = ea; | 60 | ad = ea; |
61 | size += sizeof(struct extendedAttrHeaderDesc); | 61 | size += sizeof(struct extendedAttrHeaderDesc); |
62 | } | 62 | } |
63 | 63 | ||
64 | offset = inode->i_sb->s_blocksize - udf_file_entry_alloc_offset(inode) - | 64 | offset = inode->i_sb->s_blocksize - udf_file_entry_alloc_offset(inode) - |
65 | UDF_I_LENALLOC(inode); | 65 | iinfo->i_lenAlloc; |
66 | 66 | ||
67 | /* TODO - Check for FreeEASpace */ | 67 | /* TODO - Check for FreeEASpace */ |
68 | 68 | ||
@@ -70,69 +70,80 @@ struct genericFormat *udf_add_extendedattr(struct inode *inode, uint32_t size, | |||
70 | struct extendedAttrHeaderDesc *eahd; | 70 | struct extendedAttrHeaderDesc *eahd; |
71 | eahd = (struct extendedAttrHeaderDesc *)ea; | 71 | eahd = (struct extendedAttrHeaderDesc *)ea; |
72 | 72 | ||
73 | if (UDF_I_LENALLOC(inode)) { | 73 | if (iinfo->i_lenAlloc) |
74 | memmove(&ad[size], ad, UDF_I_LENALLOC(inode)); | 74 | memmove(&ad[size], ad, iinfo->i_lenAlloc); |
75 | } | ||
76 | 75 | ||
77 | if (UDF_I_LENEATTR(inode)) { | 76 | if (iinfo->i_lenEAttr) { |
78 | /* check checksum/crc */ | 77 | /* check checksum/crc */ |
79 | if (le16_to_cpu(eahd->descTag.tagIdent) != TAG_IDENT_EAHD || | 78 | if (eahd->descTag.tagIdent != |
80 | le32_to_cpu(eahd->descTag.tagLocation) != UDF_I_LOCATION(inode).logicalBlockNum) { | 79 | cpu_to_le16(TAG_IDENT_EAHD) || |
80 | le32_to_cpu(eahd->descTag.tagLocation) != | ||
81 | iinfo->i_location.logicalBlockNum) | ||
81 | return NULL; | 82 | return NULL; |
82 | } | ||
83 | } else { | 83 | } else { |
84 | struct udf_sb_info *sbi = UDF_SB(inode->i_sb); | ||
85 | |||
84 | size -= sizeof(struct extendedAttrHeaderDesc); | 86 | size -= sizeof(struct extendedAttrHeaderDesc); |
85 | UDF_I_LENEATTR(inode) += sizeof(struct extendedAttrHeaderDesc); | 87 | iinfo->i_lenEAttr += |
88 | sizeof(struct extendedAttrHeaderDesc); | ||
86 | eahd->descTag.tagIdent = cpu_to_le16(TAG_IDENT_EAHD); | 89 | eahd->descTag.tagIdent = cpu_to_le16(TAG_IDENT_EAHD); |
87 | if (UDF_SB_UDFREV(inode->i_sb) >= 0x0200) | 90 | if (sbi->s_udfrev >= 0x0200) |
88 | eahd->descTag.descVersion = cpu_to_le16(3); | 91 | eahd->descTag.descVersion = cpu_to_le16(3); |
89 | else | 92 | else |
90 | eahd->descTag.descVersion = cpu_to_le16(2); | 93 | eahd->descTag.descVersion = cpu_to_le16(2); |
91 | eahd->descTag.tagSerialNum = cpu_to_le16(UDF_SB_SERIALNUM(inode->i_sb)); | 94 | eahd->descTag.tagSerialNum = |
92 | eahd->descTag.tagLocation = cpu_to_le32(UDF_I_LOCATION(inode).logicalBlockNum); | 95 | cpu_to_le16(sbi->s_serial_number); |
96 | eahd->descTag.tagLocation = cpu_to_le32( | ||
97 | iinfo->i_location.logicalBlockNum); | ||
93 | eahd->impAttrLocation = cpu_to_le32(0xFFFFFFFF); | 98 | eahd->impAttrLocation = cpu_to_le32(0xFFFFFFFF); |
94 | eahd->appAttrLocation = cpu_to_le32(0xFFFFFFFF); | 99 | eahd->appAttrLocation = cpu_to_le32(0xFFFFFFFF); |
95 | } | 100 | } |
96 | 101 | ||
97 | offset = UDF_I_LENEATTR(inode); | 102 | offset = iinfo->i_lenEAttr; |
98 | if (type < 2048) { | 103 | if (type < 2048) { |
99 | if (le32_to_cpu(eahd->appAttrLocation) < UDF_I_LENEATTR(inode)) { | 104 | if (le32_to_cpu(eahd->appAttrLocation) < |
100 | uint32_t aal = le32_to_cpu(eahd->appAttrLocation); | 105 | iinfo->i_lenEAttr) { |
106 | uint32_t aal = | ||
107 | le32_to_cpu(eahd->appAttrLocation); | ||
101 | memmove(&ea[offset - aal + size], | 108 | memmove(&ea[offset - aal + size], |
102 | &ea[aal], offset - aal); | 109 | &ea[aal], offset - aal); |
103 | offset -= aal; | 110 | offset -= aal; |
104 | eahd->appAttrLocation = cpu_to_le32(aal + size); | 111 | eahd->appAttrLocation = |
112 | cpu_to_le32(aal + size); | ||
105 | } | 113 | } |
106 | if (le32_to_cpu(eahd->impAttrLocation) < UDF_I_LENEATTR(inode)) { | 114 | if (le32_to_cpu(eahd->impAttrLocation) < |
107 | uint32_t ial = le32_to_cpu(eahd->impAttrLocation); | 115 | iinfo->i_lenEAttr) { |
116 | uint32_t ial = | ||
117 | le32_to_cpu(eahd->impAttrLocation); | ||
108 | memmove(&ea[offset - ial + size], | 118 | memmove(&ea[offset - ial + size], |
109 | &ea[ial], offset - ial); | 119 | &ea[ial], offset - ial); |
110 | offset -= ial; | 120 | offset -= ial; |
111 | eahd->impAttrLocation = cpu_to_le32(ial + size); | 121 | eahd->impAttrLocation = |
122 | cpu_to_le32(ial + size); | ||
112 | } | 123 | } |
113 | } else if (type < 65536) { | 124 | } else if (type < 65536) { |
114 | if (le32_to_cpu(eahd->appAttrLocation) < UDF_I_LENEATTR(inode)) { | 125 | if (le32_to_cpu(eahd->appAttrLocation) < |
115 | uint32_t aal = le32_to_cpu(eahd->appAttrLocation); | 126 | iinfo->i_lenEAttr) { |
127 | uint32_t aal = | ||
128 | le32_to_cpu(eahd->appAttrLocation); | ||
116 | memmove(&ea[offset - aal + size], | 129 | memmove(&ea[offset - aal + size], |
117 | &ea[aal], offset - aal); | 130 | &ea[aal], offset - aal); |
118 | offset -= aal; | 131 | offset -= aal; |
119 | eahd->appAttrLocation = cpu_to_le32(aal + size); | 132 | eahd->appAttrLocation = |
133 | cpu_to_le32(aal + size); | ||
120 | } | 134 | } |
121 | } | 135 | } |
122 | /* rewrite CRC + checksum of eahd */ | 136 | /* rewrite CRC + checksum of eahd */ |
123 | crclen = sizeof(struct extendedAttrHeaderDesc) - sizeof(tag); | 137 | crclen = sizeof(struct extendedAttrHeaderDesc) - sizeof(tag); |
124 | eahd->descTag.descCRCLength = cpu_to_le16(crclen); | 138 | eahd->descTag.descCRCLength = cpu_to_le16(crclen); |
125 | eahd->descTag.descCRC = cpu_to_le16(udf_crc((char *)eahd + | 139 | eahd->descTag.descCRC = cpu_to_le16(udf_crc((char *)eahd + |
126 | sizeof(tag), crclen, 0)); | 140 | sizeof(tag), crclen, 0)); |
127 | eahd->descTag.tagChecksum = 0; | 141 | eahd->descTag.tagChecksum = udf_tag_checksum(&eahd->descTag); |
128 | for (i = 0; i < 16; i++) | 142 | iinfo->i_lenEAttr += size; |
129 | if (i != 4) | ||
130 | eahd->descTag.tagChecksum += ((uint8_t *)&(eahd->descTag))[i]; | ||
131 | UDF_I_LENEATTR(inode) += size; | ||
132 | return (struct genericFormat *)&ea[offset]; | 143 | return (struct genericFormat *)&ea[offset]; |
133 | } | 144 | } |
134 | if (loc & 0x02) { | 145 | if (loc & 0x02) |
135 | } | 146 | ; |
136 | 147 | ||
137 | return NULL; | 148 | return NULL; |
138 | } | 149 | } |
@@ -143,18 +154,20 @@ struct genericFormat *udf_get_extendedattr(struct inode *inode, uint32_t type, | |||
143 | struct genericFormat *gaf; | 154 | struct genericFormat *gaf; |
144 | uint8_t *ea = NULL; | 155 | uint8_t *ea = NULL; |
145 | uint32_t offset; | 156 | uint32_t offset; |
157 | struct udf_inode_info *iinfo = UDF_I(inode); | ||
146 | 158 | ||
147 | ea = UDF_I_DATA(inode); | 159 | ea = iinfo->i_ext.i_data; |
148 | 160 | ||
149 | if (UDF_I_LENEATTR(inode)) { | 161 | if (iinfo->i_lenEAttr) { |
150 | struct extendedAttrHeaderDesc *eahd; | 162 | struct extendedAttrHeaderDesc *eahd; |
151 | eahd = (struct extendedAttrHeaderDesc *)ea; | 163 | eahd = (struct extendedAttrHeaderDesc *)ea; |
152 | 164 | ||
153 | /* check checksum/crc */ | 165 | /* check checksum/crc */ |
154 | if (le16_to_cpu(eahd->descTag.tagIdent) != TAG_IDENT_EAHD || | 166 | if (eahd->descTag.tagIdent != |
155 | le32_to_cpu(eahd->descTag.tagLocation) != UDF_I_LOCATION(inode).logicalBlockNum) { | 167 | cpu_to_le16(TAG_IDENT_EAHD) || |
168 | le32_to_cpu(eahd->descTag.tagLocation) != | ||
169 | iinfo->i_location.logicalBlockNum) | ||
156 | return NULL; | 170 | return NULL; |
157 | } | ||
158 | 171 | ||
159 | if (type < 2048) | 172 | if (type < 2048) |
160 | offset = sizeof(struct extendedAttrHeaderDesc); | 173 | offset = sizeof(struct extendedAttrHeaderDesc); |
@@ -163,9 +176,10 @@ struct genericFormat *udf_get_extendedattr(struct inode *inode, uint32_t type, | |||
163 | else | 176 | else |
164 | offset = le32_to_cpu(eahd->appAttrLocation); | 177 | offset = le32_to_cpu(eahd->appAttrLocation); |
165 | 178 | ||
166 | while (offset < UDF_I_LENEATTR(inode)) { | 179 | while (offset < iinfo->i_lenEAttr) { |
167 | gaf = (struct genericFormat *)&ea[offset]; | 180 | gaf = (struct genericFormat *)&ea[offset]; |
168 | if (le32_to_cpu(gaf->attrType) == type && gaf->attrSubtype == subtype) | 181 | if (le32_to_cpu(gaf->attrType) == type && |
182 | gaf->attrSubtype == subtype) | ||
169 | return gaf; | 183 | return gaf; |
170 | else | 184 | else |
171 | offset += le32_to_cpu(gaf->attrLength); | 185 | offset += le32_to_cpu(gaf->attrLength); |
@@ -186,21 +200,20 @@ struct genericFormat *udf_get_extendedattr(struct inode *inode, uint32_t type, | |||
186 | * Written, tested, and released. | 200 | * Written, tested, and released. |
187 | */ | 201 | */ |
188 | struct buffer_head *udf_read_tagged(struct super_block *sb, uint32_t block, | 202 | struct buffer_head *udf_read_tagged(struct super_block *sb, uint32_t block, |
189 | uint32_t location, uint16_t * ident) | 203 | uint32_t location, uint16_t *ident) |
190 | { | 204 | { |
191 | tag *tag_p; | 205 | tag *tag_p; |
192 | struct buffer_head *bh = NULL; | 206 | struct buffer_head *bh = NULL; |
193 | register uint8_t checksum; | 207 | struct udf_sb_info *sbi = UDF_SB(sb); |
194 | register int i; | ||
195 | 208 | ||
196 | /* Read the block */ | 209 | /* Read the block */ |
197 | if (block == 0xFFFFFFFF) | 210 | if (block == 0xFFFFFFFF) |
198 | return NULL; | 211 | return NULL; |
199 | 212 | ||
200 | bh = udf_tread(sb, block + UDF_SB_SESSION(sb)); | 213 | bh = udf_tread(sb, block + sbi->s_session); |
201 | if (!bh) { | 214 | if (!bh) { |
202 | udf_debug("block=%d, location=%d: read failed\n", | 215 | udf_debug("block=%d, location=%d: read failed\n", |
203 | block + UDF_SB_SESSION(sb), location); | 216 | block + sbi->s_session, location); |
204 | return NULL; | 217 | return NULL; |
205 | } | 218 | } |
206 | 219 | ||
@@ -210,24 +223,20 @@ struct buffer_head *udf_read_tagged(struct super_block *sb, uint32_t block, | |||
210 | 223 | ||
211 | if (location != le32_to_cpu(tag_p->tagLocation)) { | 224 | if (location != le32_to_cpu(tag_p->tagLocation)) { |
212 | udf_debug("location mismatch block %u, tag %u != %u\n", | 225 | udf_debug("location mismatch block %u, tag %u != %u\n", |
213 | block + UDF_SB_SESSION(sb), le32_to_cpu(tag_p->tagLocation), location); | 226 | block + sbi->s_session, |
227 | le32_to_cpu(tag_p->tagLocation), location); | ||
214 | goto error_out; | 228 | goto error_out; |
215 | } | 229 | } |
216 | 230 | ||
217 | /* Verify the tag checksum */ | 231 | /* Verify the tag checksum */ |
218 | checksum = 0U; | 232 | if (udf_tag_checksum(tag_p) != tag_p->tagChecksum) { |
219 | for (i = 0; i < 4; i++) | ||
220 | checksum += (uint8_t)(bh->b_data[i]); | ||
221 | for (i = 5; i < 16; i++) | ||
222 | checksum += (uint8_t)(bh->b_data[i]); | ||
223 | if (checksum != tag_p->tagChecksum) { | ||
224 | printk(KERN_ERR "udf: tag checksum failed block %d\n", block); | 233 | printk(KERN_ERR "udf: tag checksum failed block %d\n", block); |
225 | goto error_out; | 234 | goto error_out; |
226 | } | 235 | } |
227 | 236 | ||
228 | /* Verify the tag version */ | 237 | /* Verify the tag version */ |
229 | if (le16_to_cpu(tag_p->descVersion) != 0x0002U && | 238 | if (tag_p->descVersion != cpu_to_le16(0x0002U) && |
230 | le16_to_cpu(tag_p->descVersion) != 0x0003U) { | 239 | tag_p->descVersion != cpu_to_le16(0x0003U)) { |
231 | udf_debug("tag version 0x%04x != 0x0002 || 0x0003 block %d\n", | 240 | udf_debug("tag version 0x%04x != 0x0002 || 0x0003 block %d\n", |
232 | le16_to_cpu(tag_p->descVersion), block); | 241 | le16_to_cpu(tag_p->descVersion), block); |
233 | goto error_out; | 242 | goto error_out; |
@@ -236,11 +245,11 @@ struct buffer_head *udf_read_tagged(struct super_block *sb, uint32_t block, | |||
236 | /* Verify the descriptor CRC */ | 245 | /* Verify the descriptor CRC */ |
237 | if (le16_to_cpu(tag_p->descCRCLength) + sizeof(tag) > sb->s_blocksize || | 246 | if (le16_to_cpu(tag_p->descCRCLength) + sizeof(tag) > sb->s_blocksize || |
238 | le16_to_cpu(tag_p->descCRC) == udf_crc(bh->b_data + sizeof(tag), | 247 | le16_to_cpu(tag_p->descCRC) == udf_crc(bh->b_data + sizeof(tag), |
239 | le16_to_cpu(tag_p->descCRCLength), 0)) { | 248 | le16_to_cpu(tag_p->descCRCLength), 0)) |
240 | return bh; | 249 | return bh; |
241 | } | 250 | |
242 | udf_debug("Crc failure block %d: crc = %d, crclen = %d\n", | 251 | udf_debug("Crc failure block %d: crc = %d, crclen = %d\n", |
243 | block + UDF_SB_SESSION(sb), le16_to_cpu(tag_p->descCRC), | 252 | block + sbi->s_session, le16_to_cpu(tag_p->descCRC), |
244 | le16_to_cpu(tag_p->descCRCLength)); | 253 | le16_to_cpu(tag_p->descCRCLength)); |
245 | 254 | ||
246 | error_out: | 255 | error_out: |
@@ -249,7 +258,7 @@ error_out: | |||
249 | } | 258 | } |
250 | 259 | ||
251 | struct buffer_head *udf_read_ptagged(struct super_block *sb, kernel_lb_addr loc, | 260 | struct buffer_head *udf_read_ptagged(struct super_block *sb, kernel_lb_addr loc, |
252 | uint32_t offset, uint16_t * ident) | 261 | uint32_t offset, uint16_t *ident) |
253 | { | 262 | { |
254 | return udf_read_tagged(sb, udf_get_lb_pblock(sb, loc, offset), | 263 | return udf_read_tagged(sb, udf_get_lb_pblock(sb, loc, offset), |
255 | loc.logicalBlockNum + offset, ident); | 264 | loc.logicalBlockNum + offset, ident); |
@@ -258,17 +267,11 @@ struct buffer_head *udf_read_ptagged(struct super_block *sb, kernel_lb_addr loc, | |||
258 | void udf_update_tag(char *data, int length) | 267 | void udf_update_tag(char *data, int length) |
259 | { | 268 | { |
260 | tag *tptr = (tag *)data; | 269 | tag *tptr = (tag *)data; |
261 | int i; | ||
262 | |||
263 | length -= sizeof(tag); | 270 | length -= sizeof(tag); |
264 | 271 | ||
265 | tptr->tagChecksum = 0; | ||
266 | tptr->descCRCLength = cpu_to_le16(length); | 272 | tptr->descCRCLength = cpu_to_le16(length); |
267 | tptr->descCRC = cpu_to_le16(udf_crc(data + sizeof(tag), length, 0)); | 273 | tptr->descCRC = cpu_to_le16(udf_crc(data + sizeof(tag), length, 0)); |
268 | 274 | tptr->tagChecksum = udf_tag_checksum(tptr); | |
269 | for (i = 0; i < 16; i++) | ||
270 | if (i != 4) | ||
271 | tptr->tagChecksum += (uint8_t)(data[i]); | ||
272 | } | 275 | } |
273 | 276 | ||
274 | void udf_new_tag(char *data, uint16_t ident, uint16_t version, uint16_t snum, | 277 | void udf_new_tag(char *data, uint16_t ident, uint16_t version, uint16_t snum, |
@@ -281,3 +284,14 @@ void udf_new_tag(char *data, uint16_t ident, uint16_t version, uint16_t snum, | |||
281 | tptr->tagLocation = cpu_to_le32(loc); | 284 | tptr->tagLocation = cpu_to_le32(loc); |
282 | udf_update_tag(data, length); | 285 | udf_update_tag(data, length); |
283 | } | 286 | } |
287 | |||
288 | u8 udf_tag_checksum(const tag *t) | ||
289 | { | ||
290 | u8 *data = (u8 *)t; | ||
291 | u8 checksum = 0; | ||
292 | int i; | ||
293 | for (i = 0; i < sizeof(tag); ++i) | ||
294 | if (i != 4) /* position of checksum */ | ||
295 | checksum += data[i]; | ||
296 | return checksum; | ||
297 | } | ||