blob: aafe356ec1b730c57edf17e6d2a8e4745d3a0152 [file] [log] [blame]
Linus Torvalds1da177e2005-04-16 15:20:36 -07001/*
2 * linux/fs/isofs/rock.c
3 *
4 * (C) 1992, 1993 Eric Youngdale
5 *
6 * Rock Ridge Extensions to iso9660
7 */
8
Linus Torvalds1da177e2005-04-16 15:20:36 -07009#include <linux/slab.h>
10#include <linux/pagemap.h>
11#include <linux/smp_lock.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070012
Al Viro94f2f712005-04-25 18:32:12 -070013#include "isofs.h"
Linus Torvalds1da177e2005-04-16 15:20:36 -070014#include "rock.h"
15
16/* These functions are designed to read the system areas of a directory record
17 * and extract relevant information. There are different functions provided
18 * depending upon what information we need at the time. One function fills
19 * out an inode structure, a second one extracts a filename, a third one
20 * returns a symbolic link name, and a fourth one returns the extent number
21 * for the file. */
22
Andrew Morton1d372112005-06-21 17:16:42 -070023#define SIG(A,B) ((A) | ((B) << 8)) /* isonum_721() */
Linus Torvalds1da177e2005-04-16 15:20:36 -070024
Andrew Morton12121712005-06-21 17:16:44 -070025/*
26 * This is a way of ensuring that we have something in the system
27 * use fields that is compatible with Rock Ridge. Return zero on success.
28 */
29
30static int check_sp(struct rock_ridge *rr, struct inode *inode)
31{
32 if (rr->u.SP.magic[0] != 0xbe)
33 return -1;
34 if (rr->u.SP.magic[1] != 0xef)
35 return -1;
36 ISOFS_SB(inode->i_sb)->s_rock_offset = rr->u.SP.skip;
37 return 0;
38}
39
Andrew Morton76ab07e2005-06-21 17:16:46 -070040static void setup_rock_ridge(struct iso_directory_record *de,
41 struct inode *inode, unsigned char **chr, int *len)
42{
43 *len = sizeof(struct iso_directory_record) + de->name_len[0];
44 if (*len & 1)
45 (*len)++;
46 *chr = (unsigned char *)de + *len;
47 *len = *((unsigned char *)de) - *len;
48 if (*len < 0)
49 *len = 0;
50
51 if (ISOFS_SB(inode->i_sb)->s_rock_offset != -1) {
52 *len -= ISOFS_SB(inode->i_sb)->s_rock_offset;
53 *chr += ISOFS_SB(inode->i_sb)->s_rock_offset;
54 if (*len < 0)
55 *len = 0;
56 }
Andrew Morton1d372112005-06-21 17:16:42 -070057}
Linus Torvalds1da177e2005-04-16 15:20:36 -070058
59#define MAYBE_CONTINUE(LABEL,DEV) \
60 {if (buffer) { kfree(buffer); buffer = NULL; } \
61 if (cont_extent){ \
62 int block, offset, offset1; \
63 struct buffer_head * pbh; \
64 buffer = kmalloc(cont_size,GFP_KERNEL); \
65 if (!buffer) goto out; \
66 block = cont_extent; \
67 offset = cont_offset; \
68 offset1 = 0; \
69 pbh = sb_bread(DEV->i_sb, block); \
70 if(pbh){ \
71 if (offset > pbh->b_size || offset + cont_size > pbh->b_size){ \
72 brelse(pbh); \
73 goto out; \
74 } \
75 memcpy(buffer + offset1, pbh->b_data + offset, cont_size - offset1); \
76 brelse(pbh); \
77 chr = (unsigned char *) buffer; \
78 len = cont_size; \
79 cont_extent = 0; \
80 cont_size = 0; \
81 cont_offset = 0; \
82 goto LABEL; \
83 } \
84 printk("Unable to read rock-ridge attributes\n"); \
85 }}
86
87/* return length of name field; 0: not found, -1: to be ignored */
Andrew Morton1d372112005-06-21 17:16:42 -070088int get_rock_ridge_filename(struct iso_directory_record *de,
89 char *retname, struct inode *inode)
Linus Torvalds1da177e2005-04-16 15:20:36 -070090{
Andrew Morton1d372112005-06-21 17:16:42 -070091 int len;
92 unsigned char *chr;
Andrew Mortona40ea8f2005-06-21 17:16:44 -070093 int cont_extent = 0;
94 int cont_offset = 0;
95 int cont_size = 0;
96 void *buffer = NULL;
Andrew Morton7fa393a2005-06-21 17:16:43 -070097 struct rock_ridge *rr;
98 int sig;
99 int retnamlen = 0;
100 int truncate = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700101
Andrew Morton1d372112005-06-21 17:16:42 -0700102 if (!ISOFS_SB(inode->i_sb)->s_rock)
103 return 0;
104 *retname = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700105
Andrew Morton76ab07e2005-06-21 17:16:46 -0700106 setup_rock_ridge(de, inode, &chr, &len);
Andrew Morton7fa393a2005-06-21 17:16:43 -0700107repeat:
Linus Torvalds1da177e2005-04-16 15:20:36 -0700108
Andrew Morton7fa393a2005-06-21 17:16:43 -0700109 while (len > 2) { /* There may be one byte for padding somewhere */
110 rr = (struct rock_ridge *)chr;
111 if (rr->len < 3)
112 goto out; /* Something got screwed up here */
113 sig = isonum_721(chr);
114 chr += rr->len;
115 len -= rr->len;
116 if (len < 0)
117 goto out; /* corrupted isofs */
Andrew Morton1d372112005-06-21 17:16:42 -0700118
Andrew Morton7fa393a2005-06-21 17:16:43 -0700119 switch (sig) {
120 case SIG('R', 'R'):
121 if ((rr->u.RR.flags[0] & RR_NM) == 0)
122 goto out;
123 break;
124 case SIG('S', 'P'):
Andrew Morton12121712005-06-21 17:16:44 -0700125 if (check_sp(rr, inode))
126 goto out;
Andrew Morton7fa393a2005-06-21 17:16:43 -0700127 break;
128 case SIG('C', 'E'):
Andrew Morton04f7aa92005-06-21 17:16:45 -0700129 cont_extent = isonum_733(rr->u.CE.extent);
130 cont_offset = isonum_733(rr->u.CE.offset);
131 cont_size = isonum_733(rr->u.CE.size);
Andrew Morton7fa393a2005-06-21 17:16:43 -0700132 break;
133 case SIG('N', 'M'):
134 if (truncate)
Andrew Morton1d372112005-06-21 17:16:42 -0700135 break;
Andrew Morton7fa393a2005-06-21 17:16:43 -0700136 if (rr->len < 5)
Andrew Morton1d372112005-06-21 17:16:42 -0700137 break;
Andrew Morton7fa393a2005-06-21 17:16:43 -0700138 /*
139 * If the flags are 2 or 4, this indicates '.' or '..'.
140 * We don't want to do anything with this, because it
141 * screws up the code that calls us. We don't really
142 * care anyways, since we can just use the non-RR
143 * name.
144 */
145 if (rr->u.NM.flags & 6)
Andrew Morton1d372112005-06-21 17:16:42 -0700146 break;
Andrew Morton1d372112005-06-21 17:16:42 -0700147
Andrew Morton7fa393a2005-06-21 17:16:43 -0700148 if (rr->u.NM.flags & ~1) {
149 printk("Unsupported NM flag settings (%d)\n",
150 rr->u.NM.flags);
Andrew Morton1d372112005-06-21 17:16:42 -0700151 break;
152 }
Andrew Morton7fa393a2005-06-21 17:16:43 -0700153 if ((strlen(retname) + rr->len - 5) >= 254) {
154 truncate = 1;
155 break;
156 }
157 strncat(retname, rr->u.NM.name, rr->len - 5);
158 retnamlen += rr->len - 5;
159 break;
160 case SIG('R', 'E'):
161 if (buffer)
162 kfree(buffer);
163 return -1;
164 default:
165 break;
Andrew Morton1d372112005-06-21 17:16:42 -0700166 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700167 }
Andrew Morton1d372112005-06-21 17:16:42 -0700168 MAYBE_CONTINUE(repeat, inode);
Andrew Morton7fa393a2005-06-21 17:16:43 -0700169 kfree(buffer);
Andrew Morton1d372112005-06-21 17:16:42 -0700170 return retnamlen; /* If 0, this file did not have a NM field */
Andrew Morton7fa393a2005-06-21 17:16:43 -0700171out:
Andrew Morton1d372112005-06-21 17:16:42 -0700172 if (buffer)
173 kfree(buffer);
174 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700175}
176
177static int
178parse_rock_ridge_inode_internal(struct iso_directory_record *de,
179 struct inode *inode, int regard_xa)
180{
Andrew Morton1d372112005-06-21 17:16:42 -0700181 int len;
182 unsigned char *chr;
183 int symlink_len = 0;
Andrew Morton7fa393a2005-06-21 17:16:43 -0700184 int cnt, sig;
185 struct inode *reloc;
186 struct rock_ridge *rr;
187 int rootflag;
Andrew Mortona40ea8f2005-06-21 17:16:44 -0700188 int cont_extent = 0;
189 int cont_offset = 0;
190 int cont_size = 0;
191 void *buffer = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700192
Andrew Morton1d372112005-06-21 17:16:42 -0700193 if (!ISOFS_SB(inode->i_sb)->s_rock)
194 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700195
Andrew Morton76ab07e2005-06-21 17:16:46 -0700196 setup_rock_ridge(de, inode, &chr, &len);
Andrew Morton1d372112005-06-21 17:16:42 -0700197 if (regard_xa) {
198 chr += 14;
199 len -= 14;
200 if (len < 0)
201 len = 0;
202 }
203
Andrew Morton7fa393a2005-06-21 17:16:43 -0700204repeat:
205 while (len > 2) { /* There may be one byte for padding somewhere */
206 rr = (struct rock_ridge *)chr;
207 if (rr->len < 3)
208 goto out; /* Something got screwed up here */
209 sig = isonum_721(chr);
210 chr += rr->len;
211 len -= rr->len;
212 if (len < 0)
213 goto out; /* corrupted isofs */
Andrew Morton1d372112005-06-21 17:16:42 -0700214
Andrew Morton7fa393a2005-06-21 17:16:43 -0700215 switch (sig) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700216#ifndef CONFIG_ZISOFS /* No flag for SF or ZF */
Andrew Morton7fa393a2005-06-21 17:16:43 -0700217 case SIG('R', 'R'):
218 if ((rr->u.RR.flags[0] &
219 (RR_PX | RR_TF | RR_SL | RR_CL)) == 0)
Andrew Morton1d372112005-06-21 17:16:42 -0700220 goto out;
Andrew Morton7fa393a2005-06-21 17:16:43 -0700221 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700222#endif
Andrew Morton7fa393a2005-06-21 17:16:43 -0700223 case SIG('S', 'P'):
Andrew Morton12121712005-06-21 17:16:44 -0700224 if (check_sp(rr, inode))
225 goto out;
Andrew Morton7fa393a2005-06-21 17:16:43 -0700226 break;
227 case SIG('C', 'E'):
Andrew Morton04f7aa92005-06-21 17:16:45 -0700228 cont_extent = isonum_733(rr->u.CE.extent);
229 cont_offset = isonum_733(rr->u.CE.offset);
230 cont_size = isonum_733(rr->u.CE.size);
Andrew Morton7fa393a2005-06-21 17:16:43 -0700231 break;
232 case SIG('E', 'R'):
233 ISOFS_SB(inode->i_sb)->s_rock = 1;
234 printk(KERN_DEBUG "ISO 9660 Extensions: ");
235 {
236 int p;
237 for (p = 0; p < rr->u.ER.len_id; p++)
238 printk("%c", rr->u.ER.data[p]);
Andrew Morton1d372112005-06-21 17:16:42 -0700239 }
Andrew Morton7fa393a2005-06-21 17:16:43 -0700240 printk("\n");
241 break;
242 case SIG('P', 'X'):
243 inode->i_mode = isonum_733(rr->u.PX.mode);
244 inode->i_nlink = isonum_733(rr->u.PX.n_links);
245 inode->i_uid = isonum_733(rr->u.PX.uid);
246 inode->i_gid = isonum_733(rr->u.PX.gid);
247 break;
248 case SIG('P', 'N'):
249 {
250 int high, low;
251 high = isonum_733(rr->u.PN.dev_high);
252 low = isonum_733(rr->u.PN.dev_low);
253 /*
254 * The Rock Ridge standard specifies that if
255 * sizeof(dev_t) <= 4, then the high field is
256 * unused, and the device number is completely
257 * stored in the low field. Some writers may
258 * ignore this subtlety,
259 * and as a result we test to see if the entire
260 * device number is
261 * stored in the low field, and use that.
262 */
263 if ((low & ~0xff) && high == 0) {
264 inode->i_rdev =
265 MKDEV(low >> 8, low & 0xff);
266 } else {
267 inode->i_rdev =
268 MKDEV(high, low);
269 }
270 }
271 break;
272 case SIG('T', 'F'):
273 /*
274 * Some RRIP writers incorrectly place ctime in the
275 * TF_CREATE field. Try to handle this correctly for
276 * either case.
277 */
278 /* Rock ridge never appears on a High Sierra disk */
279 cnt = 0;
280 if (rr->u.TF.flags & TF_CREATE) {
281 inode->i_ctime.tv_sec =
282 iso_date(rr->u.TF.times[cnt++].time,
283 0);
284 inode->i_ctime.tv_nsec = 0;
285 }
286 if (rr->u.TF.flags & TF_MODIFY) {
287 inode->i_mtime.tv_sec =
288 iso_date(rr->u.TF.times[cnt++].time,
289 0);
290 inode->i_mtime.tv_nsec = 0;
291 }
292 if (rr->u.TF.flags & TF_ACCESS) {
293 inode->i_atime.tv_sec =
294 iso_date(rr->u.TF.times[cnt++].time,
295 0);
296 inode->i_atime.tv_nsec = 0;
297 }
298 if (rr->u.TF.flags & TF_ATTRIBUTES) {
299 inode->i_ctime.tv_sec =
300 iso_date(rr->u.TF.times[cnt++].time,
301 0);
302 inode->i_ctime.tv_nsec = 0;
303 }
304 break;
305 case SIG('S', 'L'):
306 {
307 int slen;
308 struct SL_component *slp;
309 struct SL_component *oldslp;
310 slen = rr->len - 5;
311 slp = &rr->u.SL.link;
312 inode->i_size = symlink_len;
313 while (slen > 1) {
314 rootflag = 0;
315 switch (slp->flags & ~1) {
316 case 0:
317 inode->i_size +=
318 slp->len;
319 break;
320 case 2:
321 inode->i_size += 1;
322 break;
323 case 4:
324 inode->i_size += 2;
325 break;
326 case 8:
327 rootflag = 1;
328 inode->i_size += 1;
329 break;
330 default:
331 printk("Symlink component flag "
332 "not implemented\n");
333 }
334 slen -= slp->len + 2;
335 oldslp = slp;
336 slp = (struct SL_component *)
337 (((char *)slp) + slp->len + 2);
338
339 if (slen < 2) {
340 if (((rr->u.SL.
341 flags & 1) != 0)
342 &&
343 ((oldslp->
344 flags & 1) == 0))
345 inode->i_size +=
346 1;
347 break;
348 }
349
350 /*
351 * If this component record isn't
352 * continued, then append a '/'.
353 */
354 if (!rootflag
355 && (oldslp->flags & 1) == 0)
356 inode->i_size += 1;
357 }
358 }
359 symlink_len = inode->i_size;
360 break;
361 case SIG('R', 'E'):
362 printk(KERN_WARNING "Attempt to read inode for "
363 "relocated directory\n");
364 goto out;
365 case SIG('C', 'L'):
366 ISOFS_I(inode)->i_first_extent =
367 isonum_733(rr->u.CL.location);
368 reloc =
369 isofs_iget(inode->i_sb,
370 ISOFS_I(inode)->i_first_extent,
371 0);
372 if (!reloc)
373 goto out;
374 inode->i_mode = reloc->i_mode;
375 inode->i_nlink = reloc->i_nlink;
376 inode->i_uid = reloc->i_uid;
377 inode->i_gid = reloc->i_gid;
378 inode->i_rdev = reloc->i_rdev;
379 inode->i_size = reloc->i_size;
380 inode->i_blocks = reloc->i_blocks;
381 inode->i_atime = reloc->i_atime;
382 inode->i_ctime = reloc->i_ctime;
383 inode->i_mtime = reloc->i_mtime;
384 iput(reloc);
385 break;
386#ifdef CONFIG_ZISOFS
387 case SIG('Z', 'F'): {
388 int algo;
389
390 if (ISOFS_SB(inode->i_sb)->s_nocompress)
391 break;
392 algo = isonum_721(rr->u.ZF.algorithm);
393 if (algo == SIG('p', 'z')) {
394 int block_shift =
395 isonum_711(&rr->u.ZF.parms[1]);
396 if (block_shift < PAGE_CACHE_SHIFT
397 || block_shift > 17) {
398 printk(KERN_WARNING "isofs: "
399 "Can't handle ZF block "
400 "size of 2^%d\n",
401 block_shift);
402 } else {
403 /*
404 * Note: we don't change
405 * i_blocks here
406 */
407 ISOFS_I(inode)->i_file_format =
408 isofs_file_compressed;
409 /*
410 * Parameters to compression
411 * algorithm (header size,
412 * block size)
413 */
414 ISOFS_I(inode)->i_format_parm[0] =
415 isonum_711(&rr->u.ZF.parms[0]);
416 ISOFS_I(inode)->i_format_parm[1] =
417 isonum_711(&rr->u.ZF.parms[1]);
418 inode->i_size =
419 isonum_733(rr->u.ZF.
420 real_size);
421 }
422 } else {
423 printk(KERN_WARNING
424 "isofs: Unknown ZF compression "
425 "algorithm: %c%c\n",
426 rr->u.ZF.algorithm[0],
427 rr->u.ZF.algorithm[1]);
428 }
429 break;
430 }
431#endif
432 default:
433 break;
Andrew Morton1d372112005-06-21 17:16:42 -0700434 }
435 }
436 MAYBE_CONTINUE(repeat, inode);
Andrew Morton7fa393a2005-06-21 17:16:43 -0700437out:
Andrew Morton1d372112005-06-21 17:16:42 -0700438 if (buffer)
439 kfree(buffer);
440 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700441}
442
443static char *get_symlink_chunk(char *rpnt, struct rock_ridge *rr, char *plimit)
444{
445 int slen;
446 int rootflag;
447 struct SL_component *oldslp;
448 struct SL_component *slp;
449 slen = rr->len - 5;
450 slp = &rr->u.SL.link;
451 while (slen > 1) {
452 rootflag = 0;
453 switch (slp->flags & ~1) {
454 case 0:
455 if (slp->len > plimit - rpnt)
456 return NULL;
457 memcpy(rpnt, slp->text, slp->len);
Andrew Morton1d372112005-06-21 17:16:42 -0700458 rpnt += slp->len;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700459 break;
460 case 2:
461 if (rpnt >= plimit)
462 return NULL;
Andrew Morton1d372112005-06-21 17:16:42 -0700463 *rpnt++ = '.';
Linus Torvalds1da177e2005-04-16 15:20:36 -0700464 break;
465 case 4:
466 if (2 > plimit - rpnt)
467 return NULL;
Andrew Morton1d372112005-06-21 17:16:42 -0700468 *rpnt++ = '.';
469 *rpnt++ = '.';
Linus Torvalds1da177e2005-04-16 15:20:36 -0700470 break;
471 case 8:
472 if (rpnt >= plimit)
473 return NULL;
474 rootflag = 1;
Andrew Morton1d372112005-06-21 17:16:42 -0700475 *rpnt++ = '/';
Linus Torvalds1da177e2005-04-16 15:20:36 -0700476 break;
477 default:
478 printk("Symlink component flag not implemented (%d)\n",
Andrew Morton1d372112005-06-21 17:16:42 -0700479 slp->flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700480 }
481 slen -= slp->len + 2;
482 oldslp = slp;
Andrew Morton1d372112005-06-21 17:16:42 -0700483 slp = (struct SL_component *)((char *)slp + slp->len + 2);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700484
485 if (slen < 2) {
486 /*
487 * If there is another SL record, and this component
488 * record isn't continued, then add a slash.
489 */
490 if ((!rootflag) && (rr->u.SL.flags & 1) &&
491 !(oldslp->flags & 1)) {
492 if (rpnt >= plimit)
493 return NULL;
Andrew Morton1d372112005-06-21 17:16:42 -0700494 *rpnt++ = '/';
Linus Torvalds1da177e2005-04-16 15:20:36 -0700495 }
496 break;
497 }
498
499 /*
500 * If this component record isn't continued, then append a '/'.
501 */
502 if (!rootflag && !(oldslp->flags & 1)) {
503 if (rpnt >= plimit)
504 return NULL;
Andrew Morton1d372112005-06-21 17:16:42 -0700505 *rpnt++ = '/';
Linus Torvalds1da177e2005-04-16 15:20:36 -0700506 }
507 }
508 return rpnt;
509}
510
Andrew Morton1d372112005-06-21 17:16:42 -0700511int parse_rock_ridge_inode(struct iso_directory_record *de, struct inode *inode)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700512{
Andrew Morton1d372112005-06-21 17:16:42 -0700513 int result = parse_rock_ridge_inode_internal(de, inode, 0);
514 /* if rockridge flag was reset and we didn't look for attributes
515 * behind eventual XA attributes, have a look there */
516 if ((ISOFS_SB(inode->i_sb)->s_rock_offset == -1)
517 && (ISOFS_SB(inode->i_sb)->s_rock == 2)) {
518 result = parse_rock_ridge_inode_internal(de, inode, 14);
519 }
520 return result;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700521}
522
523/* readpage() for symlinks: reads symlink contents into the page and either
524 makes it uptodate and returns 0 or returns error (-EIO) */
525
526static int rock_ridge_symlink_readpage(struct file *file, struct page *page)
527{
528 struct inode *inode = page->mapping->host;
Andrew Morton1d372112005-06-21 17:16:42 -0700529 struct iso_inode_info *ei = ISOFS_I(inode);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700530 char *link = kmap(page);
531 unsigned long bufsize = ISOFS_BUFFER_SIZE(inode);
532 struct buffer_head *bh;
533 char *rpnt = link;
534 unsigned char *pnt;
Andrew Morton76ab07e2005-06-21 17:16:46 -0700535 struct iso_directory_record *raw_de;
Andrew Mortona40ea8f2005-06-21 17:16:44 -0700536 int cont_extent = 0;
537 int cont_offset = 0;
538 int cont_size = 0;
539 void *buffer = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700540 unsigned long block, offset;
541 int sig;
542 int len;
543 unsigned char *chr;
544 struct rock_ridge *rr;
545
546 if (!ISOFS_SB(inode->i_sb)->s_rock)
547 goto error;
548
549 block = ei->i_iget5_block;
550 lock_kernel();
551 bh = sb_bread(inode->i_sb, block);
552 if (!bh)
553 goto out_noread;
554
Andrew Morton1d372112005-06-21 17:16:42 -0700555 offset = ei->i_iget5_offset;
556 pnt = (unsigned char *)bh->b_data + offset;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700557
Andrew Morton76ab07e2005-06-21 17:16:46 -0700558 raw_de = (struct iso_directory_record *)pnt;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700559
560 /*
561 * If we go past the end of the buffer, there is some sort of error.
562 */
563 if (offset + *pnt > bufsize)
564 goto out_bad_span;
565
566 /* Now test for possible Rock Ridge extensions which will override
567 some of these numbers in the inode structure. */
568
Andrew Morton76ab07e2005-06-21 17:16:46 -0700569 setup_rock_ridge(raw_de, inode, &chr, &len);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700570
Andrew Morton7fa393a2005-06-21 17:16:43 -0700571repeat:
572 while (len > 2) { /* There may be one byte for padding somewhere */
Andrew Morton1d372112005-06-21 17:16:42 -0700573 rr = (struct rock_ridge *)chr;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700574 if (rr->len < 3)
575 goto out; /* Something got screwed up here */
576 sig = isonum_721(chr);
577 chr += rr->len;
578 len -= rr->len;
579 if (len < 0)
580 goto out; /* corrupted isofs */
581
582 switch (sig) {
583 case SIG('R', 'R'):
584 if ((rr->u.RR.flags[0] & RR_SL) == 0)
585 goto out;
586 break;
587 case SIG('S', 'P'):
Andrew Morton12121712005-06-21 17:16:44 -0700588 if (check_sp(rr, inode))
589 goto out;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700590 break;
591 case SIG('S', 'L'):
592 rpnt = get_symlink_chunk(rpnt, rr,
593 link + (PAGE_SIZE - 1));
594 if (rpnt == NULL)
595 goto out;
596 break;
597 case SIG('C', 'E'):
598 /* This tells is if there is a continuation record */
Andrew Morton04f7aa92005-06-21 17:16:45 -0700599 cont_extent = isonum_733(rr->u.CE.extent);
600 cont_offset = isonum_733(rr->u.CE.offset);
601 cont_size = isonum_733(rr->u.CE.size);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700602 default:
603 break;
604 }
605 }
606 MAYBE_CONTINUE(repeat, inode);
Andrew Morton7fa393a2005-06-21 17:16:43 -0700607 kfree(buffer);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700608
609 if (rpnt == link)
610 goto fail;
611 brelse(bh);
612 *rpnt = '\0';
613 unlock_kernel();
614 SetPageUptodate(page);
615 kunmap(page);
616 unlock_page(page);
617 return 0;
618
619 /* error exit from macro */
Andrew Morton7fa393a2005-06-21 17:16:43 -0700620out:
Linus Torvalds1da177e2005-04-16 15:20:36 -0700621 if (buffer)
622 kfree(buffer);
623 goto fail;
Andrew Morton7fa393a2005-06-21 17:16:43 -0700624out_noread:
Linus Torvalds1da177e2005-04-16 15:20:36 -0700625 printk("unable to read i-node block");
626 goto fail;
Andrew Morton7fa393a2005-06-21 17:16:43 -0700627out_bad_span:
Linus Torvalds1da177e2005-04-16 15:20:36 -0700628 printk("symlink spans iso9660 blocks\n");
Andrew Morton7fa393a2005-06-21 17:16:43 -0700629fail:
Linus Torvalds1da177e2005-04-16 15:20:36 -0700630 brelse(bh);
631 unlock_kernel();
Andrew Morton7fa393a2005-06-21 17:16:43 -0700632error:
Linus Torvalds1da177e2005-04-16 15:20:36 -0700633 SetPageError(page);
634 kunmap(page);
635 unlock_page(page);
636 return -EIO;
637}
638
639struct address_space_operations isofs_symlink_aops = {
Andrew Morton1d372112005-06-21 17:16:42 -0700640 .readpage = rock_ridge_symlink_readpage
Linus Torvalds1da177e2005-04-16 15:20:36 -0700641};