Branch data Line data Source code
1 : : // SPDX-License-Identifier: GPL-2.0
2 : : /*
3 : : * linux/fs/isofs/rock.c
4 : : *
5 : : * (C) 1992, 1993 Eric Youngdale
6 : : *
7 : : * Rock Ridge Extensions to iso9660
8 : : */
9 : :
10 : : #include <linux/slab.h>
11 : : #include <linux/pagemap.h>
12 : :
13 : : #include "isofs.h"
14 : : #include "rock.h"
15 : :
16 : : /*
17 : : * These functions are designed to read the system areas of a directory record
18 : : * and extract relevant information. There are different functions provided
19 : : * depending upon what information we need at the time. One function fills
20 : : * out an inode structure, a second one extracts a filename, a third one
21 : : * returns a symbolic link name, and a fourth one returns the extent number
22 : : * for the file.
23 : : */
24 : :
25 : : #define SIG(A,B) ((A) | ((B) << 8)) /* isonum_721() */
26 : :
27 : : struct rock_state {
28 : : void *buffer;
29 : : unsigned char *chr;
30 : : int len;
31 : : int cont_size;
32 : : int cont_extent;
33 : : int cont_offset;
34 : : int cont_loops;
35 : : struct inode *inode;
36 : : };
37 : :
38 : : /*
39 : : * This is a way of ensuring that we have something in the system
40 : : * use fields that is compatible with Rock Ridge. Return zero on success.
41 : : */
42 : :
43 : 0 : static int check_sp(struct rock_ridge *rr, struct inode *inode)
44 : : {
45 : 0 : if (rr->u.SP.magic[0] != 0xbe)
46 : : return -1;
47 [ # # # # : 0 : if (rr->u.SP.magic[1] != 0xef)
# # ]
48 : : return -1;
49 : 0 : ISOFS_SB(inode->i_sb)->s_rock_offset = rr->u.SP.skip;
50 : 0 : return 0;
51 : : }
52 : :
53 : : static void setup_rock_ridge(struct iso_directory_record *de,
54 : : struct inode *inode, struct rock_state *rs)
55 : : {
56 : : rs->len = sizeof(struct iso_directory_record) + de->name_len[0];
57 : : if (rs->len & 1)
58 : : (rs->len)++;
59 : : rs->chr = (unsigned char *)de + rs->len;
60 : : rs->len = *((unsigned char *)de) - rs->len;
61 : : if (rs->len < 0)
62 : : rs->len = 0;
63 : :
64 : : if (ISOFS_SB(inode->i_sb)->s_rock_offset != -1) {
65 : : rs->len -= ISOFS_SB(inode->i_sb)->s_rock_offset;
66 : : rs->chr += ISOFS_SB(inode->i_sb)->s_rock_offset;
67 : : if (rs->len < 0)
68 : : rs->len = 0;
69 : : }
70 : : }
71 : :
72 : 0 : static void init_rock_state(struct rock_state *rs, struct inode *inode)
73 : : {
74 : 0 : memset(rs, 0, sizeof(*rs));
75 : 0 : rs->inode = inode;
76 : : }
77 : :
78 : : /* Maximum number of Rock Ridge continuation entries */
79 : : #define RR_MAX_CE_ENTRIES 32
80 : :
81 : : /*
82 : : * Returns 0 if the caller should continue scanning, 1 if the scan must end
83 : : * and -ve on error.
84 : : */
85 : 0 : static int rock_continue(struct rock_state *rs)
86 : : {
87 : 0 : int ret = 1;
88 : 0 : int blocksize = 1 << rs->inode->i_blkbits;
89 : 0 : const int min_de_size = offsetof(struct rock_ridge, u);
90 : :
91 : 0 : kfree(rs->buffer);
92 : 0 : rs->buffer = NULL;
93 : :
94 [ # # ]: 0 : if ((unsigned)rs->cont_offset > blocksize - min_de_size ||
95 [ # # ]: 0 : (unsigned)rs->cont_size > blocksize ||
96 [ # # ]: 0 : (unsigned)(rs->cont_offset + rs->cont_size) > blocksize) {
97 : 0 : printk(KERN_NOTICE "rock: corrupted directory entry. "
98 : : "extent=%d, offset=%d, size=%d\n",
99 : : rs->cont_extent, rs->cont_offset, rs->cont_size);
100 : 0 : ret = -EIO;
101 : 0 : goto out;
102 : : }
103 : :
104 [ # # ]: 0 : if (rs->cont_extent) {
105 : 0 : struct buffer_head *bh;
106 : :
107 [ # # ]: 0 : rs->buffer = kmalloc(rs->cont_size, GFP_KERNEL);
108 [ # # ]: 0 : if (!rs->buffer) {
109 : 0 : ret = -ENOMEM;
110 : 0 : goto out;
111 : : }
112 : 0 : ret = -EIO;
113 [ # # ]: 0 : if (++rs->cont_loops >= RR_MAX_CE_ENTRIES)
114 : 0 : goto out;
115 : 0 : bh = sb_bread(rs->inode->i_sb, rs->cont_extent);
116 [ # # ]: 0 : if (bh) {
117 : 0 : memcpy(rs->buffer, bh->b_data + rs->cont_offset,
118 : 0 : rs->cont_size);
119 : 0 : put_bh(bh);
120 : 0 : rs->chr = rs->buffer;
121 : 0 : rs->len = rs->cont_size;
122 : 0 : rs->cont_extent = 0;
123 : 0 : rs->cont_size = 0;
124 : 0 : rs->cont_offset = 0;
125 : 0 : return 0;
126 : : }
127 : 0 : printk("Unable to read rock-ridge attributes\n");
128 : : }
129 : 0 : out:
130 : 0 : kfree(rs->buffer);
131 : 0 : rs->buffer = NULL;
132 : 0 : return ret;
133 : : }
134 : :
135 : : /*
136 : : * We think there's a record of type `sig' at rs->chr. Parse the signature
137 : : * and make sure that there's really room for a record of that type.
138 : : */
139 : : static int rock_check_overflow(struct rock_state *rs, int sig)
140 : : {
141 : : int len;
142 : :
143 : : switch (sig) {
144 : : case SIG('S', 'P'):
145 : : len = sizeof(struct SU_SP_s);
146 : : break;
147 : : case SIG('C', 'E'):
148 : : len = sizeof(struct SU_CE_s);
149 : : break;
150 : : case SIG('E', 'R'):
151 : : len = sizeof(struct SU_ER_s);
152 : : break;
153 : : case SIG('R', 'R'):
154 : : len = sizeof(struct RR_RR_s);
155 : : break;
156 : : case SIG('P', 'X'):
157 : : len = sizeof(struct RR_PX_s);
158 : : break;
159 : : case SIG('P', 'N'):
160 : : len = sizeof(struct RR_PN_s);
161 : : break;
162 : : case SIG('S', 'L'):
163 : : len = sizeof(struct RR_SL_s);
164 : : break;
165 : : case SIG('N', 'M'):
166 : : len = sizeof(struct RR_NM_s);
167 : : break;
168 : : case SIG('C', 'L'):
169 : : len = sizeof(struct RR_CL_s);
170 : : break;
171 : : case SIG('P', 'L'):
172 : : len = sizeof(struct RR_PL_s);
173 : : break;
174 : : case SIG('T', 'F'):
175 : : len = sizeof(struct RR_TF_s);
176 : : break;
177 : : case SIG('Z', 'F'):
178 : : len = sizeof(struct RR_ZF_s);
179 : : break;
180 : : default:
181 : : len = 0;
182 : : break;
183 : : }
184 : : len += offsetof(struct rock_ridge, u);
185 : : if (len > rs->len) {
186 : : printk(KERN_NOTICE "rock: directory entry would overflow "
187 : : "storage\n");
188 : : printk(KERN_NOTICE "rock: sig=0x%02x, size=%d, remaining=%d\n",
189 : : sig, len, rs->len);
190 : : return -EIO;
191 : : }
192 : : return 0;
193 : : }
194 : :
195 : : /*
196 : : * return length of name field; 0: not found, -1: to be ignored
197 : : */
198 : 0 : int get_rock_ridge_filename(struct iso_directory_record *de,
199 : : char *retname, struct inode *inode)
200 : : {
201 : 0 : struct rock_state rs;
202 : 0 : struct rock_ridge *rr;
203 : 0 : int sig;
204 : 0 : int retnamlen = 0;
205 : 0 : int truncate = 0;
206 : 0 : int ret = 0;
207 : 0 : char *p;
208 : 0 : int len;
209 : :
210 [ # # ]: 0 : if (!ISOFS_SB(inode->i_sb)->s_rock)
211 : : return 0;
212 : 0 : *retname = 0;
213 : :
214 : 0 : init_rock_state(&rs, inode);
215 : 0 : setup_rock_ridge(de, inode, &rs);
216 : : repeat:
217 : :
218 [ # # ]: 0 : while (rs.len > 2) { /* There may be one byte for padding somewhere */
219 : 0 : rr = (struct rock_ridge *)rs.chr;
220 : : /*
221 : : * Ignore rock ridge info if rr->len is out of range, but
222 : : * don't return -EIO because that would make the file
223 : : * invisible.
224 : : */
225 [ # # ]: 0 : if (rr->len < 3)
226 : 0 : goto out; /* Something got screwed up here */
227 : 0 : sig = isonum_721(rs.chr);
228 [ # # ]: 0 : if (rock_check_overflow(&rs, sig))
229 : 0 : goto eio;
230 : 0 : rs.chr += rr->len;
231 : 0 : rs.len -= rr->len;
232 : : /*
233 : : * As above, just ignore the rock ridge info if rr->len
234 : : * is bogus.
235 : : */
236 [ # # ]: 0 : if (rs.len < 0)
237 : 0 : goto out; /* Something got screwed up here */
238 : :
239 [ # # # # : 0 : switch (sig) {
# # ]
240 : 0 : case SIG('R', 'R'):
241 [ # # ]: 0 : if ((rr->u.RR.flags[0] & RR_NM) == 0)
242 : 0 : goto out;
243 : : break;
244 : 0 : case SIG('S', 'P'):
245 [ # # ]: 0 : if (check_sp(rr, inode))
246 : 0 : goto out;
247 : : break;
248 : 0 : case SIG('C', 'E'):
249 : 0 : rs.cont_extent = isonum_733(rr->u.CE.extent);
250 : 0 : rs.cont_offset = isonum_733(rr->u.CE.offset);
251 : 0 : rs.cont_size = isonum_733(rr->u.CE.size);
252 : 0 : break;
253 : 0 : case SIG('N', 'M'):
254 [ # # ]: 0 : if (truncate)
255 : : break;
256 [ # # ]: 0 : if (rr->len < 5)
257 : : break;
258 : : /*
259 : : * If the flags are 2 or 4, this indicates '.' or '..'.
260 : : * We don't want to do anything with this, because it
261 : : * screws up the code that calls us. We don't really
262 : : * care anyways, since we can just use the non-RR
263 : : * name.
264 : : */
265 [ # # ]: 0 : if (rr->u.NM.flags & 6)
266 : : break;
267 : :
268 [ # # ]: 0 : if (rr->u.NM.flags & ~1) {
269 : 0 : printk("Unsupported NM flag settings (%d)\n",
270 : : rr->u.NM.flags);
271 : 0 : break;
272 : : }
273 : 0 : len = rr->len - 5;
274 [ # # ]: 0 : if (retnamlen + len >= 254) {
275 : : truncate = 1;
276 : : break;
277 : : }
278 : 0 : p = memchr(rr->u.NM.name, '\0', len);
279 [ # # ]: 0 : if (unlikely(p))
280 : 0 : len = p - rr->u.NM.name;
281 : 0 : memcpy(retname + retnamlen, rr->u.NM.name, len);
282 : 0 : retnamlen += len;
283 : 0 : retname[retnamlen] = '\0';
284 : 0 : break;
285 : 0 : case SIG('R', 'E'):
286 : 0 : kfree(rs.buffer);
287 : 0 : return -1;
288 : : default:
289 : : break;
290 : : }
291 : 0 : }
292 : 0 : ret = rock_continue(&rs);
293 [ # # ]: 0 : if (ret == 0)
294 : 0 : goto repeat;
295 [ # # ]: 0 : if (ret == 1)
296 : : return retnamlen; /* If 0, this file did not have a NM field */
297 : 0 : out:
298 : 0 : kfree(rs.buffer);
299 : 0 : return ret;
300 : : eio:
301 : 0 : ret = -EIO;
302 : 0 : goto out;
303 : : }
304 : :
305 : : #define RR_REGARD_XA 1
306 : : #define RR_RELOC_DE 2
307 : :
308 : : static int
309 : 0 : parse_rock_ridge_inode_internal(struct iso_directory_record *de,
310 : : struct inode *inode, int flags)
311 : : {
312 : 0 : int symlink_len = 0;
313 : 0 : int cnt, sig;
314 : 0 : unsigned int reloc_block;
315 : 0 : struct inode *reloc;
316 : 0 : struct rock_ridge *rr;
317 : 0 : int rootflag;
318 : 0 : struct rock_state rs;
319 : 0 : int ret = 0;
320 : :
321 [ # # ]: 0 : if (!ISOFS_SB(inode->i_sb)->s_rock)
322 : : return 0;
323 : :
324 : 0 : init_rock_state(&rs, inode);
325 : 0 : setup_rock_ridge(de, inode, &rs);
326 [ # # ]: 0 : if (flags & RR_REGARD_XA) {
327 : 0 : rs.chr += 14;
328 : 0 : rs.len -= 14;
329 [ # # ]: 0 : if (rs.len < 0)
330 : 0 : rs.len = 0;
331 : : }
332 : :
333 : 0 : repeat:
334 [ # # ]: 0 : while (rs.len > 2) { /* There may be one byte for padding somewhere */
335 : 0 : rr = (struct rock_ridge *)rs.chr;
336 : : /*
337 : : * Ignore rock ridge info if rr->len is out of range, but
338 : : * don't return -EIO because that would make the file
339 : : * invisible.
340 : : */
341 [ # # ]: 0 : if (rr->len < 3)
342 : 0 : goto out; /* Something got screwed up here */
343 : 0 : sig = isonum_721(rs.chr);
344 [ # # ]: 0 : if (rock_check_overflow(&rs, sig))
345 : 0 : goto eio;
346 : 0 : rs.chr += rr->len;
347 : 0 : rs.len -= rr->len;
348 : : /*
349 : : * As above, just ignore the rock ridge info if rr->len
350 : : * is bogus.
351 : : */
352 [ # # ]: 0 : if (rs.len < 0)
353 : 0 : goto out; /* Something got screwed up here */
354 : :
355 [ # # # # : 0 : switch (sig) {
# # # # #
# # ]
356 : : #ifndef CONFIG_ZISOFS /* No flag for SF or ZF */
357 : : case SIG('R', 'R'):
358 : : if ((rr->u.RR.flags[0] &
359 : : (RR_PX | RR_TF | RR_SL | RR_CL)) == 0)
360 : : goto out;
361 : : break;
362 : : #endif
363 : 0 : case SIG('S', 'P'):
364 [ # # ]: 0 : if (check_sp(rr, inode))
365 : 0 : goto out;
366 : : break;
367 : 0 : case SIG('C', 'E'):
368 : 0 : rs.cont_extent = isonum_733(rr->u.CE.extent);
369 : 0 : rs.cont_offset = isonum_733(rr->u.CE.offset);
370 : 0 : rs.cont_size = isonum_733(rr->u.CE.size);
371 : 0 : break;
372 : 0 : case SIG('E', 'R'):
373 : : /* Invalid length of ER tag id? */
374 [ # # ]: 0 : if (rr->u.ER.len_id + offsetof(struct rock_ridge, u.ER.data) > rr->len)
375 : 0 : goto out;
376 : 0 : ISOFS_SB(inode->i_sb)->s_rock = 1;
377 : 0 : printk(KERN_DEBUG "ISO 9660 Extensions: ");
378 : : {
379 : 0 : int p;
380 [ # # ]: 0 : for (p = 0; p < rr->u.ER.len_id; p++)
381 : 0 : printk(KERN_CONT "%c", rr->u.ER.data[p]);
382 : : }
383 : 0 : printk(KERN_CONT "\n");
384 : 0 : break;
385 : 0 : case SIG('P', 'X'):
386 : 0 : inode->i_mode = isonum_733(rr->u.PX.mode);
387 : 0 : set_nlink(inode, isonum_733(rr->u.PX.n_links));
388 : 0 : i_uid_write(inode, isonum_733(rr->u.PX.uid));
389 : 0 : i_gid_write(inode, isonum_733(rr->u.PX.gid));
390 : : break;
391 : 0 : case SIG('P', 'N'):
392 : : {
393 : 0 : int high, low;
394 [ # # ]: 0 : high = isonum_733(rr->u.PN.dev_high);
395 : 0 : low = isonum_733(rr->u.PN.dev_low);
396 : : /*
397 : : * The Rock Ridge standard specifies that if
398 : : * sizeof(dev_t) <= 4, then the high field is
399 : : * unused, and the device number is completely
400 : : * stored in the low field. Some writers may
401 : : * ignore this subtlety,
402 : : * and as a result we test to see if the entire
403 : : * device number is
404 : : * stored in the low field, and use that.
405 : : */
406 [ # # # # ]: 0 : if ((low & ~0xff) && high == 0) {
407 : 0 : inode->i_rdev =
408 : 0 : MKDEV(low >> 8, low & 0xff);
409 : : } else {
410 : 0 : inode->i_rdev =
411 : 0 : MKDEV(high, low);
412 : : }
413 : : }
414 : : break;
415 : 0 : case SIG('T', 'F'):
416 : : /*
417 : : * Some RRIP writers incorrectly place ctime in the
418 : : * TF_CREATE field. Try to handle this correctly for
419 : : * either case.
420 : : */
421 : : /* Rock ridge never appears on a High Sierra disk */
422 : 0 : cnt = 0;
423 [ # # ]: 0 : if (rr->u.TF.flags & TF_CREATE) {
424 : 0 : inode->i_ctime.tv_sec =
425 : 0 : iso_date(rr->u.TF.times[cnt++].time,
426 : : 0);
427 : 0 : inode->i_ctime.tv_nsec = 0;
428 : : }
429 [ # # ]: 0 : if (rr->u.TF.flags & TF_MODIFY) {
430 : 0 : inode->i_mtime.tv_sec =
431 : 0 : iso_date(rr->u.TF.times[cnt++].time,
432 : : 0);
433 : 0 : inode->i_mtime.tv_nsec = 0;
434 : : }
435 [ # # ]: 0 : if (rr->u.TF.flags & TF_ACCESS) {
436 : 0 : inode->i_atime.tv_sec =
437 : 0 : iso_date(rr->u.TF.times[cnt++].time,
438 : : 0);
439 : 0 : inode->i_atime.tv_nsec = 0;
440 : : }
441 [ # # ]: 0 : if (rr->u.TF.flags & TF_ATTRIBUTES) {
442 : 0 : inode->i_ctime.tv_sec =
443 : 0 : iso_date(rr->u.TF.times[cnt++].time,
444 : : 0);
445 : 0 : inode->i_ctime.tv_nsec = 0;
446 : : }
447 : : break;
448 : 0 : case SIG('S', 'L'):
449 : : {
450 : 0 : int slen;
451 : 0 : struct SL_component *slp;
452 : 0 : struct SL_component *oldslp;
453 : 0 : slen = rr->len - 5;
454 : 0 : slp = &rr->u.SL.link;
455 : 0 : inode->i_size = symlink_len;
456 [ # # ]: 0 : while (slen > 1) {
457 : 0 : rootflag = 0;
458 [ # # # # : 0 : switch (slp->flags & ~1) {
# ]
459 : 0 : case 0:
460 : 0 : inode->i_size +=
461 : 0 : slp->len;
462 : 0 : break;
463 : 0 : case 2:
464 : 0 : inode->i_size += 1;
465 : 0 : break;
466 : 0 : case 4:
467 : 0 : inode->i_size += 2;
468 : 0 : break;
469 : 0 : case 8:
470 : 0 : rootflag = 1;
471 : 0 : inode->i_size += 1;
472 : 0 : break;
473 : 0 : default:
474 : 0 : printk("Symlink component flag "
475 : : "not implemented\n");
476 : : }
477 : 0 : slen -= slp->len + 2;
478 : 0 : oldslp = slp;
479 : 0 : slp = (struct SL_component *)
480 : 0 : (((char *)slp) + slp->len + 2);
481 : :
482 [ # # ]: 0 : if (slen < 2) {
483 [ # # ]: 0 : if (((rr->u.SL.
484 : : flags & 1) != 0)
485 : 0 : &&
486 [ # # ]: 0 : ((oldslp->
487 : : flags & 1) == 0))
488 : 0 : inode->i_size +=
489 : : 1;
490 : : break;
491 : : }
492 : :
493 : : /*
494 : : * If this component record isn't
495 : : * continued, then append a '/'.
496 : : */
497 [ # # ]: 0 : if (!rootflag
498 [ # # ]: 0 : && (oldslp->flags & 1) == 0)
499 : 0 : inode->i_size += 1;
500 : : }
501 : : }
502 : 0 : symlink_len = inode->i_size;
503 : 0 : break;
504 : 0 : case SIG('R', 'E'):
505 : 0 : printk(KERN_WARNING "Attempt to read inode for "
506 : : "relocated directory\n");
507 : 0 : goto out;
508 : 0 : case SIG('C', 'L'):
509 [ # # ]: 0 : if (flags & RR_RELOC_DE) {
510 : 0 : printk(KERN_ERR
511 : : "ISOFS: Recursive directory relocation "
512 : : "is not supported\n");
513 : 0 : goto eio;
514 : : }
515 [ # # ]: 0 : reloc_block = isonum_733(rr->u.CL.location);
516 [ # # ]: 0 : if (reloc_block == ISOFS_I(inode)->i_iget5_block &&
517 [ # # ]: 0 : ISOFS_I(inode)->i_iget5_offset == 0) {
518 : 0 : printk(KERN_ERR
519 : : "ISOFS: Directory relocation points to "
520 : : "itself\n");
521 : 0 : goto eio;
522 : : }
523 : 0 : ISOFS_I(inode)->i_first_extent = reloc_block;
524 : 0 : reloc = isofs_iget_reloc(inode->i_sb, reloc_block, 0);
525 [ # # ]: 0 : if (IS_ERR(reloc)) {
526 : 0 : ret = PTR_ERR(reloc);
527 : 0 : goto out;
528 : : }
529 : 0 : inode->i_mode = reloc->i_mode;
530 : 0 : set_nlink(inode, reloc->i_nlink);
531 : 0 : inode->i_uid = reloc->i_uid;
532 : 0 : inode->i_gid = reloc->i_gid;
533 : 0 : inode->i_rdev = reloc->i_rdev;
534 : 0 : inode->i_size = reloc->i_size;
535 : 0 : inode->i_blocks = reloc->i_blocks;
536 : 0 : inode->i_atime = reloc->i_atime;
537 : 0 : inode->i_ctime = reloc->i_ctime;
538 : 0 : inode->i_mtime = reloc->i_mtime;
539 : 0 : iput(reloc);
540 : 0 : break;
541 : : #ifdef CONFIG_ZISOFS
542 : 0 : case SIG('Z', 'F'): {
543 : 0 : int algo;
544 : :
545 [ # # ]: 0 : if (ISOFS_SB(inode->i_sb)->s_nocompress)
546 : : break;
547 [ # # ]: 0 : algo = isonum_721(rr->u.ZF.algorithm);
548 [ # # ]: 0 : if (algo == SIG('p', 'z')) {
549 : 0 : int block_shift =
550 [ # # ]: 0 : isonum_711(&rr->u.ZF.parms[1]);
551 [ # # ]: 0 : if (block_shift > 17) {
552 : 0 : printk(KERN_WARNING "isofs: "
553 : : "Can't handle ZF block "
554 : : "size of 2^%d\n",
555 : : block_shift);
556 : : } else {
557 : : /*
558 : : * Note: we don't change
559 : : * i_blocks here
560 : : */
561 : 0 : ISOFS_I(inode)->i_file_format =
562 : : isofs_file_compressed;
563 : : /*
564 : : * Parameters to compression
565 : : * algorithm (header size,
566 : : * block size)
567 : : */
568 : 0 : ISOFS_I(inode)->i_format_parm[0] =
569 : 0 : isonum_711(&rr->u.ZF.parms[0]);
570 : 0 : ISOFS_I(inode)->i_format_parm[1] =
571 : 0 : isonum_711(&rr->u.ZF.parms[1]);
572 : 0 : inode->i_size =
573 : 0 : isonum_733(rr->u.ZF.
574 : : real_size);
575 : : }
576 : : } else {
577 : 0 : printk(KERN_WARNING
578 : : "isofs: Unknown ZF compression "
579 : : "algorithm: %c%c\n",
580 : 0 : rr->u.ZF.algorithm[0],
581 : 0 : rr->u.ZF.algorithm[1]);
582 : : }
583 : : break;
584 : : }
585 : : #endif
586 : : default:
587 : : break;
588 : : }
589 : 0 : }
590 : 0 : ret = rock_continue(&rs);
591 [ # # ]: 0 : if (ret == 0)
592 : 0 : goto repeat;
593 [ # # ]: 0 : if (ret == 1)
594 : 0 : ret = 0;
595 : 0 : out:
596 : 0 : kfree(rs.buffer);
597 : 0 : return ret;
598 : 0 : eio:
599 : 0 : ret = -EIO;
600 : 0 : goto out;
601 : : }
602 : :
603 : 0 : static char *get_symlink_chunk(char *rpnt, struct rock_ridge *rr, char *plimit)
604 : : {
605 : 0 : int slen;
606 : 0 : int rootflag;
607 : 0 : struct SL_component *oldslp;
608 : 0 : struct SL_component *slp;
609 : 0 : slen = rr->len - 5;
610 : 0 : slp = &rr->u.SL.link;
611 [ # # ]: 0 : while (slen > 1) {
612 : 0 : rootflag = 0;
613 [ # # # # : 0 : switch (slp->flags & ~1) {
# ]
614 : 0 : case 0:
615 [ # # ]: 0 : if (slp->len > plimit - rpnt)
616 : : return NULL;
617 : 0 : memcpy(rpnt, slp->text, slp->len);
618 : 0 : rpnt += slp->len;
619 : 0 : break;
620 : 0 : case 2:
621 [ # # ]: 0 : if (rpnt >= plimit)
622 : : return NULL;
623 : 0 : *rpnt++ = '.';
624 : 0 : break;
625 : 0 : case 4:
626 [ # # ]: 0 : if (2 > plimit - rpnt)
627 : : return NULL;
628 : 0 : *rpnt++ = '.';
629 : 0 : *rpnt++ = '.';
630 : 0 : break;
631 : 0 : case 8:
632 [ # # ]: 0 : if (rpnt >= plimit)
633 : : return NULL;
634 : 0 : rootflag = 1;
635 : 0 : *rpnt++ = '/';
636 : 0 : break;
637 : 0 : default:
638 : 0 : printk("Symlink component flag not implemented (%d)\n",
639 : : slp->flags);
640 : : }
641 : 0 : slen -= slp->len + 2;
642 : 0 : oldslp = slp;
643 : 0 : slp = (struct SL_component *)((char *)slp + slp->len + 2);
644 : :
645 [ # # ]: 0 : if (slen < 2) {
646 : : /*
647 : : * If there is another SL record, and this component
648 : : * record isn't continued, then add a slash.
649 : : */
650 [ # # # # ]: 0 : if ((!rootflag) && (rr->u.SL.flags & 1) &&
651 [ # # ]: 0 : !(oldslp->flags & 1)) {
652 [ # # ]: 0 : if (rpnt >= plimit)
653 : : return NULL;
654 : 0 : *rpnt++ = '/';
655 : : }
656 : : break;
657 : : }
658 : :
659 : : /*
660 : : * If this component record isn't continued, then append a '/'.
661 : : */
662 [ # # # # ]: 0 : if (!rootflag && !(oldslp->flags & 1)) {
663 [ # # ]: 0 : if (rpnt >= plimit)
664 : : return NULL;
665 : 0 : *rpnt++ = '/';
666 : : }
667 : : }
668 : : return rpnt;
669 : : }
670 : :
671 : 0 : int parse_rock_ridge_inode(struct iso_directory_record *de, struct inode *inode,
672 : : int relocated)
673 : : {
674 [ # # ]: 0 : int flags = relocated ? RR_RELOC_DE : 0;
675 : 0 : int result = parse_rock_ridge_inode_internal(de, inode, flags);
676 : :
677 : : /*
678 : : * if rockridge flag was reset and we didn't look for attributes
679 : : * behind eventual XA attributes, have a look there
680 : : */
681 [ # # ]: 0 : if ((ISOFS_SB(inode->i_sb)->s_rock_offset == -1)
682 [ # # ]: 0 : && (ISOFS_SB(inode->i_sb)->s_rock == 2)) {
683 : 0 : result = parse_rock_ridge_inode_internal(de, inode,
684 : : flags | RR_REGARD_XA);
685 : : }
686 : 0 : return result;
687 : : }
688 : :
689 : : /*
690 : : * readpage() for symlinks: reads symlink contents into the page and either
691 : : * makes it uptodate and returns 0 or returns error (-EIO)
692 : : */
693 : 0 : static int rock_ridge_symlink_readpage(struct file *file, struct page *page)
694 : : {
695 : 0 : struct inode *inode = page->mapping->host;
696 [ # # ]: 0 : struct iso_inode_info *ei = ISOFS_I(inode);
697 [ # # ]: 0 : struct isofs_sb_info *sbi = ISOFS_SB(inode->i_sb);
698 [ # # ]: 0 : char *link = page_address(page);
699 : 0 : unsigned long bufsize = ISOFS_BUFFER_SIZE(inode);
700 : 0 : struct buffer_head *bh;
701 : 0 : char *rpnt = link;
702 : 0 : unsigned char *pnt;
703 : 0 : struct iso_directory_record *raw_de;
704 : 0 : unsigned long block, offset;
705 : 0 : int sig;
706 : 0 : struct rock_ridge *rr;
707 : 0 : struct rock_state rs;
708 : 0 : int ret;
709 : :
710 [ # # ]: 0 : if (!sbi->s_rock)
711 : 0 : goto error;
712 : :
713 : 0 : init_rock_state(&rs, inode);
714 : 0 : block = ei->i_iget5_block;
715 : 0 : bh = sb_bread(inode->i_sb, block);
716 [ # # ]: 0 : if (!bh)
717 : 0 : goto out_noread;
718 : :
719 : 0 : offset = ei->i_iget5_offset;
720 : 0 : pnt = (unsigned char *)bh->b_data + offset;
721 : :
722 : 0 : raw_de = (struct iso_directory_record *)pnt;
723 : :
724 : : /*
725 : : * If we go past the end of the buffer, there is some sort of error.
726 : : */
727 [ # # ]: 0 : if (offset + *pnt > bufsize)
728 : 0 : goto out_bad_span;
729 : :
730 : : /*
731 : : * Now test for possible Rock Ridge extensions which will override
732 : : * some of these numbers in the inode structure.
733 : : */
734 : :
735 : 0 : setup_rock_ridge(raw_de, inode, &rs);
736 : :
737 : : repeat:
738 [ # # ]: 0 : while (rs.len > 2) { /* There may be one byte for padding somewhere */
739 : 0 : rr = (struct rock_ridge *)rs.chr;
740 [ # # ]: 0 : if (rr->len < 3)
741 : 0 : goto out; /* Something got screwed up here */
742 : 0 : sig = isonum_721(rs.chr);
743 [ # # ]: 0 : if (rock_check_overflow(&rs, sig))
744 : 0 : goto out;
745 : 0 : rs.chr += rr->len;
746 : 0 : rs.len -= rr->len;
747 [ # # ]: 0 : if (rs.len < 0)
748 : 0 : goto out; /* corrupted isofs */
749 : :
750 [ # # # # : 0 : switch (sig) {
# ]
751 : 0 : case SIG('R', 'R'):
752 [ # # ]: 0 : if ((rr->u.RR.flags[0] & RR_SL) == 0)
753 : 0 : goto out;
754 : : break;
755 : 0 : case SIG('S', 'P'):
756 [ # # ]: 0 : if (check_sp(rr, inode))
757 : 0 : goto out;
758 : : break;
759 : 0 : case SIG('S', 'L'):
760 : 0 : rpnt = get_symlink_chunk(rpnt, rr,
761 : : link + (PAGE_SIZE - 1));
762 [ # # ]: 0 : if (rpnt == NULL)
763 : 0 : goto out;
764 : : break;
765 : 0 : case SIG('C', 'E'):
766 : : /* This tells is if there is a continuation record */
767 : 0 : rs.cont_extent = isonum_733(rr->u.CE.extent);
768 : 0 : rs.cont_offset = isonum_733(rr->u.CE.offset);
769 : 0 : rs.cont_size = isonum_733(rr->u.CE.size);
770 : : default:
771 : : break;
772 : : }
773 : : }
774 : 0 : ret = rock_continue(&rs);
775 [ # # ]: 0 : if (ret == 0)
776 : 0 : goto repeat;
777 [ # # ]: 0 : if (ret < 0)
778 : 0 : goto fail;
779 : :
780 [ # # ]: 0 : if (rpnt == link)
781 : 0 : goto fail;
782 : 0 : brelse(bh);
783 : 0 : *rpnt = '\0';
784 : 0 : SetPageUptodate(page);
785 : 0 : unlock_page(page);
786 : 0 : return 0;
787 : :
788 : : /* error exit from macro */
789 : 0 : out:
790 : 0 : kfree(rs.buffer);
791 : 0 : goto fail;
792 : : out_noread:
793 : 0 : printk("unable to read i-node block");
794 : 0 : goto fail;
795 : : out_bad_span:
796 : 0 : printk("symlink spans iso9660 blocks\n");
797 : 0 : fail:
798 [ # # ]: 0 : brelse(bh);
799 : 0 : error:
800 [ # # ]: 0 : SetPageError(page);
801 : 0 : unlock_page(page);
802 : 0 : return -EIO;
803 : : }
804 : :
805 : : const struct address_space_operations isofs_symlink_aops = {
806 : : .readpage = rock_ridge_symlink_readpage
807 : : };
|