aboutsummaryrefslogtreecommitdiffstats
path: root/fs/isofs/rock.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/isofs/rock.c')
-rw-r--r--fs/isofs/rock.c237
1 files changed, 130 insertions, 107 deletions
diff --git a/fs/isofs/rock.c b/fs/isofs/rock.c
index aafe356ec1b7..efefbcce4ce9 100644
--- a/fs/isofs/rock.c
+++ b/fs/isofs/rock.c
@@ -22,6 +22,16 @@
22 22
23#define SIG(A,B) ((A) | ((B) << 8)) /* isonum_721() */ 23#define SIG(A,B) ((A) | ((B) << 8)) /* isonum_721() */
24 24
25struct rock_state {
26 void *buffer;
27 unsigned char *chr;
28 int len;
29 int cont_size;
30 int cont_extent;
31 int cont_offset;
32 struct inode *inode;
33};
34
25/* 35/*
26 * This is a way of ensuring that we have something in the system 36 * 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. 37 * use fields that is compatible with Rock Ridge. Return zero on success.
@@ -38,82 +48,96 @@ static int check_sp(struct rock_ridge *rr, struct inode *inode)
38} 48}
39 49
40static void setup_rock_ridge(struct iso_directory_record *de, 50static void setup_rock_ridge(struct iso_directory_record *de,
41 struct inode *inode, unsigned char **chr, int *len) 51 struct inode *inode, struct rock_state *rs)
42{ 52{
43 *len = sizeof(struct iso_directory_record) + de->name_len[0]; 53 rs->len = sizeof(struct iso_directory_record) + de->name_len[0];
44 if (*len & 1) 54 if (rs->len & 1)
45 (*len)++; 55 (rs->len)++;
46 *chr = (unsigned char *)de + *len; 56 rs->chr = (unsigned char *)de + rs->len;
47 *len = *((unsigned char *)de) - *len; 57 rs->len = *((unsigned char *)de) - rs->len;
48 if (*len < 0) 58 if (rs->len < 0)
49 *len = 0; 59 rs->len = 0;
50 60
51 if (ISOFS_SB(inode->i_sb)->s_rock_offset != -1) { 61 if (ISOFS_SB(inode->i_sb)->s_rock_offset != -1) {
52 *len -= ISOFS_SB(inode->i_sb)->s_rock_offset; 62 rs->len -= ISOFS_SB(inode->i_sb)->s_rock_offset;
53 *chr += ISOFS_SB(inode->i_sb)->s_rock_offset; 63 rs->chr += ISOFS_SB(inode->i_sb)->s_rock_offset;
54 if (*len < 0) 64 if (rs->len < 0)
55 *len = 0; 65 rs->len = 0;
56 } 66 }
57} 67}
58 68
59#define MAYBE_CONTINUE(LABEL,DEV) \ 69static void init_rock_state(struct rock_state *rs, struct inode *inode)
60 {if (buffer) { kfree(buffer); buffer = NULL; } \ 70{
61 if (cont_extent){ \ 71 memset(rs, 0, sizeof(*rs));
62 int block, offset, offset1; \ 72 rs->inode = inode;
63 struct buffer_head * pbh; \ 73}
64 buffer = kmalloc(cont_size,GFP_KERNEL); \ 74
65 if (!buffer) goto out; \ 75/*
66 block = cont_extent; \ 76 * Returns 0 if the caller should continue scanning, 1 if the scan must end
67 offset = cont_offset; \ 77 * and -ve on error.
68 offset1 = 0; \ 78 */
69 pbh = sb_bread(DEV->i_sb, block); \ 79static int rock_continue(struct rock_state *rs)
70 if(pbh){ \ 80{
71 if (offset > pbh->b_size || offset + cont_size > pbh->b_size){ \ 81 int ret = 1;
72 brelse(pbh); \ 82
73 goto out; \ 83 kfree(rs->buffer);
74 } \ 84 rs->buffer = NULL;
75 memcpy(buffer + offset1, pbh->b_data + offset, cont_size - offset1); \ 85 if (rs->cont_extent) {
76 brelse(pbh); \ 86 struct buffer_head *bh;
77 chr = (unsigned char *) buffer; \ 87
78 len = cont_size; \ 88 rs->buffer = kmalloc(rs->cont_size, GFP_KERNEL);
79 cont_extent = 0; \ 89 if (!rs->buffer) {
80 cont_size = 0; \ 90 ret = -ENOMEM;
81 cont_offset = 0; \ 91 goto out;
82 goto LABEL; \ 92 }
83 } \ 93 ret = -EIO;
84 printk("Unable to read rock-ridge attributes\n"); \ 94 bh = sb_bread(rs->inode->i_sb, rs->cont_extent);
85 }} 95 if (bh) {
96 memcpy(rs->buffer, bh->b_data + rs->cont_offset,
97 rs->cont_size);
98 put_bh(bh);
99 rs->chr = rs->buffer;
100 rs->len = rs->cont_size;
101 rs->cont_extent = 0;
102 rs->cont_size = 0;
103 rs->cont_offset = 0;
104 return 0;
105 }
106 printk("Unable to read rock-ridge attributes\n");
107 }
108out:
109 kfree(rs->buffer);
110 rs->buffer = NULL;
111 return ret;
112}
86 113
87/* return length of name field; 0: not found, -1: to be ignored */ 114/* return length of name field; 0: not found, -1: to be ignored */
88int get_rock_ridge_filename(struct iso_directory_record *de, 115int get_rock_ridge_filename(struct iso_directory_record *de,
89 char *retname, struct inode *inode) 116 char *retname, struct inode *inode)
90{ 117{
91 int len; 118 struct rock_state rs;
92 unsigned char *chr;
93 int cont_extent = 0;
94 int cont_offset = 0;
95 int cont_size = 0;
96 void *buffer = NULL;
97 struct rock_ridge *rr; 119 struct rock_ridge *rr;
98 int sig; 120 int sig;
99 int retnamlen = 0; 121 int retnamlen = 0;
100 int truncate = 0; 122 int truncate = 0;
123 int ret = 0;
101 124
102 if (!ISOFS_SB(inode->i_sb)->s_rock) 125 if (!ISOFS_SB(inode->i_sb)->s_rock)
103 return 0; 126 return 0;
104 *retname = 0; 127 *retname = 0;
105 128
106 setup_rock_ridge(de, inode, &chr, &len); 129 init_rock_state(&rs, inode);
130 setup_rock_ridge(de, inode, &rs);
107repeat: 131repeat:
108 132
109 while (len > 2) { /* There may be one byte for padding somewhere */ 133 while (rs.len > 2) { /* There may be one byte for padding somewhere */
110 rr = (struct rock_ridge *)chr; 134 rr = (struct rock_ridge *)rs.chr;
111 if (rr->len < 3) 135 if (rr->len < 3)
112 goto out; /* Something got screwed up here */ 136 goto out; /* Something got screwed up here */
113 sig = isonum_721(chr); 137 sig = isonum_721(rs.chr);
114 chr += rr->len; 138 rs.chr += rr->len;
115 len -= rr->len; 139 rs.len -= rr->len;
116 if (len < 0) 140 if (rs.len < 0)
117 goto out; /* corrupted isofs */ 141 goto out; /* corrupted isofs */
118 142
119 switch (sig) { 143 switch (sig) {
@@ -126,9 +150,9 @@ repeat:
126 goto out; 150 goto out;
127 break; 151 break;
128 case SIG('C', 'E'): 152 case SIG('C', 'E'):
129 cont_extent = isonum_733(rr->u.CE.extent); 153 rs.cont_extent = isonum_733(rr->u.CE.extent);
130 cont_offset = isonum_733(rr->u.CE.offset); 154 rs.cont_offset = isonum_733(rr->u.CE.offset);
131 cont_size = isonum_733(rr->u.CE.size); 155 rs.cont_size = isonum_733(rr->u.CE.size);
132 break; 156 break;
133 case SIG('N', 'M'): 157 case SIG('N', 'M'):
134 if (truncate) 158 if (truncate)
@@ -158,58 +182,55 @@ repeat:
158 retnamlen += rr->len - 5; 182 retnamlen += rr->len - 5;
159 break; 183 break;
160 case SIG('R', 'E'): 184 case SIG('R', 'E'):
161 if (buffer) 185 kfree(rs.buffer);
162 kfree(buffer);
163 return -1; 186 return -1;
164 default: 187 default:
165 break; 188 break;
166 } 189 }
167 } 190 }
168 MAYBE_CONTINUE(repeat, inode); 191 ret = rock_continue(&rs);
169 kfree(buffer); 192 if (ret == 0)
170 return retnamlen; /* If 0, this file did not have a NM field */ 193 goto repeat;
194 if (ret == 1)
195 return retnamlen; /* If 0, this file did not have a NM field */
171out: 196out:
172 if (buffer) 197 kfree(rs.buffer);
173 kfree(buffer); 198 return ret;
174 return 0;
175} 199}
176 200
177static int 201static int
178parse_rock_ridge_inode_internal(struct iso_directory_record *de, 202parse_rock_ridge_inode_internal(struct iso_directory_record *de,
179 struct inode *inode, int regard_xa) 203 struct inode *inode, int regard_xa)
180{ 204{
181 int len;
182 unsigned char *chr;
183 int symlink_len = 0; 205 int symlink_len = 0;
184 int cnt, sig; 206 int cnt, sig;
185 struct inode *reloc; 207 struct inode *reloc;
186 struct rock_ridge *rr; 208 struct rock_ridge *rr;
187 int rootflag; 209 int rootflag;
188 int cont_extent = 0; 210 struct rock_state rs;
189 int cont_offset = 0; 211 int ret = 0;
190 int cont_size = 0;
191 void *buffer = NULL;
192 212
193 if (!ISOFS_SB(inode->i_sb)->s_rock) 213 if (!ISOFS_SB(inode->i_sb)->s_rock)
194 return 0; 214 return 0;
195 215
196 setup_rock_ridge(de, inode, &chr, &len); 216 init_rock_state(&rs, inode);
217 setup_rock_ridge(de, inode, &rs);
197 if (regard_xa) { 218 if (regard_xa) {
198 chr += 14; 219 rs.chr += 14;
199 len -= 14; 220 rs.len -= 14;
200 if (len < 0) 221 if (rs.len < 0)
201 len = 0; 222 rs.len = 0;
202 } 223 }
203 224
204repeat: 225repeat:
205 while (len > 2) { /* There may be one byte for padding somewhere */ 226 while (rs.len > 2) { /* There may be one byte for padding somewhere */
206 rr = (struct rock_ridge *)chr; 227 rr = (struct rock_ridge *)rs.chr;
207 if (rr->len < 3) 228 if (rr->len < 3)
208 goto out; /* Something got screwed up here */ 229 goto out; /* Something got screwed up here */
209 sig = isonum_721(chr); 230 sig = isonum_721(rs.chr);
210 chr += rr->len; 231 rs.chr += rr->len;
211 len -= rr->len; 232 rs.len -= rr->len;
212 if (len < 0) 233 if (rs.len < 0)
213 goto out; /* corrupted isofs */ 234 goto out; /* corrupted isofs */
214 235
215 switch (sig) { 236 switch (sig) {
@@ -225,9 +246,9 @@ repeat:
225 goto out; 246 goto out;
226 break; 247 break;
227 case SIG('C', 'E'): 248 case SIG('C', 'E'):
228 cont_extent = isonum_733(rr->u.CE.extent); 249 rs.cont_extent = isonum_733(rr->u.CE.extent);
229 cont_offset = isonum_733(rr->u.CE.offset); 250 rs.cont_offset = isonum_733(rr->u.CE.offset);
230 cont_size = isonum_733(rr->u.CE.size); 251 rs.cont_size = isonum_733(rr->u.CE.size);
231 break; 252 break;
232 case SIG('E', 'R'): 253 case SIG('E', 'R'):
233 ISOFS_SB(inode->i_sb)->s_rock = 1; 254 ISOFS_SB(inode->i_sb)->s_rock = 1;
@@ -433,11 +454,14 @@ repeat:
433 break; 454 break;
434 } 455 }
435 } 456 }
436 MAYBE_CONTINUE(repeat, inode); 457 ret = rock_continue(&rs);
458 if (ret == 0)
459 goto repeat;
460 if (ret == 1)
461 ret = 0;
437out: 462out:
438 if (buffer) 463 kfree(rs.buffer);
439 kfree(buffer); 464 return ret;
440 return 0;
441} 465}
442 466
443static char *get_symlink_chunk(char *rpnt, struct rock_ridge *rr, char *plimit) 467static char *get_symlink_chunk(char *rpnt, struct rock_ridge *rr, char *plimit)
@@ -533,19 +557,16 @@ static int rock_ridge_symlink_readpage(struct file *file, struct page *page)
533 char *rpnt = link; 557 char *rpnt = link;
534 unsigned char *pnt; 558 unsigned char *pnt;
535 struct iso_directory_record *raw_de; 559 struct iso_directory_record *raw_de;
536 int cont_extent = 0;
537 int cont_offset = 0;
538 int cont_size = 0;
539 void *buffer = NULL;
540 unsigned long block, offset; 560 unsigned long block, offset;
541 int sig; 561 int sig;
542 int len;
543 unsigned char *chr;
544 struct rock_ridge *rr; 562 struct rock_ridge *rr;
563 struct rock_state rs;
564 int ret;
545 565
546 if (!ISOFS_SB(inode->i_sb)->s_rock) 566 if (!ISOFS_SB(inode->i_sb)->s_rock)
547 goto error; 567 goto error;
548 568
569 init_rock_state(&rs, inode);
549 block = ei->i_iget5_block; 570 block = ei->i_iget5_block;
550 lock_kernel(); 571 lock_kernel();
551 bh = sb_bread(inode->i_sb, block); 572 bh = sb_bread(inode->i_sb, block);
@@ -566,17 +587,17 @@ static int rock_ridge_symlink_readpage(struct file *file, struct page *page)
566 /* Now test for possible Rock Ridge extensions which will override 587 /* Now test for possible Rock Ridge extensions which will override
567 some of these numbers in the inode structure. */ 588 some of these numbers in the inode structure. */
568 589
569 setup_rock_ridge(raw_de, inode, &chr, &len); 590 setup_rock_ridge(raw_de, inode, &rs);
570 591
571repeat: 592repeat:
572 while (len > 2) { /* There may be one byte for padding somewhere */ 593 while (rs.len > 2) { /* There may be one byte for padding somewhere */
573 rr = (struct rock_ridge *)chr; 594 rr = (struct rock_ridge *)rs.chr;
574 if (rr->len < 3) 595 if (rr->len < 3)
575 goto out; /* Something got screwed up here */ 596 goto out; /* Something got screwed up here */
576 sig = isonum_721(chr); 597 sig = isonum_721(rs.chr);
577 chr += rr->len; 598 rs.chr += rr->len;
578 len -= rr->len; 599 rs.len -= rr->len;
579 if (len < 0) 600 if (rs.len < 0)
580 goto out; /* corrupted isofs */ 601 goto out; /* corrupted isofs */
581 602
582 switch (sig) { 603 switch (sig) {
@@ -596,15 +617,18 @@ repeat:
596 break; 617 break;
597 case SIG('C', 'E'): 618 case SIG('C', 'E'):
598 /* This tells is if there is a continuation record */ 619 /* This tells is if there is a continuation record */
599 cont_extent = isonum_733(rr->u.CE.extent); 620 rs.cont_extent = isonum_733(rr->u.CE.extent);
600 cont_offset = isonum_733(rr->u.CE.offset); 621 rs.cont_offset = isonum_733(rr->u.CE.offset);
601 cont_size = isonum_733(rr->u.CE.size); 622 rs.cont_size = isonum_733(rr->u.CE.size);
602 default: 623 default:
603 break; 624 break;
604 } 625 }
605 } 626 }
606 MAYBE_CONTINUE(repeat, inode); 627 ret = rock_continue(&rs);
607 kfree(buffer); 628 if (ret == 0)
629 goto repeat;
630 if (ret < 0)
631 goto fail;
608 632
609 if (rpnt == link) 633 if (rpnt == link)
610 goto fail; 634 goto fail;
@@ -618,8 +642,7 @@ repeat:
618 642
619 /* error exit from macro */ 643 /* error exit from macro */
620out: 644out:
621 if (buffer) 645 kfree(rs.buffer);
622 kfree(buffer);
623 goto fail; 646 goto fail;
624out_noread: 647out_noread:
625 printk("unable to read i-node block"); 648 printk("unable to read i-node block");