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