Import 2.2.3pre2
[davej-history.git] / fs / isofs / rock.c
blob8b5c8befd5b9b608da3c0c9fe875643c27b6a969
1 /*
2 * linux/fs/isofs/rock.c
4 * (C) 1992, 1993 Eric Youngdale
6 * Rock Ridge Extensions to iso9660
7 */
9 #include <linux/stat.h>
10 #include <linux/sched.h>
11 #include <linux/iso_fs.h>
12 #include <linux/string.h>
13 #include <linux/mm.h>
14 #include <linux/malloc.h>
16 #include "rock.h"
18 /* These functions are designed to read the system areas of a directory record
19 * and extract relevant information. There are different functions provided
20 * depending upon what information we need at the time. One function fills
21 * out an inode structure, a second one extracts a filename, a third one
22 * returns a symbolic link name, and a fourth one returns the extent number
23 * for the file. */
25 #define SIG(A,B) ((A << 8) | B)
28 /* This is a way of ensuring that we have something in the system
29 use fields that is compatible with Rock Ridge */
30 #define CHECK_SP(FAIL) \
31 if(rr->u.SP.magic[0] != 0xbe) FAIL; \
32 if(rr->u.SP.magic[1] != 0xef) FAIL;
34 /* We define a series of macros because each function must do exactly the
35 same thing in certain places. We use the macros to ensure that everything
36 is done correctly */
38 #define CONTINUE_DECLS \
39 int cont_extent = 0, cont_offset = 0, cont_size = 0; \
40 void * buffer = 0
42 #define CHECK_CE \
43 {cont_extent = isonum_733(rr->u.CE.extent); \
44 cont_offset = isonum_733(rr->u.CE.offset); \
45 cont_size = isonum_733(rr->u.CE.size);}
47 #define SETUP_ROCK_RIDGE(DE,CHR,LEN) \
48 {LEN= sizeof(struct iso_directory_record) + DE->name_len[0]; \
49 if(LEN & 1) LEN++; \
50 CHR = ((unsigned char *) DE) + LEN; \
51 LEN = *((unsigned char *) DE) - LEN;}
53 #define MAYBE_CONTINUE(LABEL,DEV) \
54 {if (buffer) kfree(buffer); \
55 if (cont_extent){ \
56 int block, offset, offset1; \
57 struct buffer_head * pbh; \
58 buffer = kmalloc(cont_size,GFP_KERNEL); \
59 if (!buffer) goto out; \
60 block = cont_extent; \
61 offset = cont_offset; \
62 offset1 = 0; \
63 pbh = bread(DEV->i_dev, block, ISOFS_BUFFER_SIZE(DEV)); \
64 if(pbh){ \
65 memcpy(buffer + offset1, pbh->b_data + offset, cont_size - offset1); \
66 brelse(pbh); \
67 chr = (unsigned char *) buffer; \
68 len = cont_size; \
69 cont_extent = 0; \
70 cont_size = 0; \
71 cont_offset = 0; \
72 goto LABEL; \
73 }; \
74 printk("Unable to read rock-ridge attributes\n"); \
77 /* This is the inner layer of the get filename routine, and is called
78 for each system area and continuation record related to the file */
80 int find_rock_ridge_relocation(struct iso_directory_record * de,
81 struct inode * inode) {
82 int flag;
83 int len;
84 int retval;
85 unsigned char * chr;
86 CONTINUE_DECLS;
87 flag = 0;
89 /* If this is a '..' then we are looking for the parent, otherwise we
90 are looking for the child */
92 if (de->name[0]==1 && de->name_len[0]==1) flag = 1;
93 /* Return value if we do not find appropriate record. */
94 retval = isonum_733 (de->extent);
96 if (!inode->i_sb->u.isofs_sb.s_rock) return retval;
98 SETUP_ROCK_RIDGE(de, chr, len);
99 repeat:
101 int rrflag, sig;
102 struct rock_ridge * rr;
104 while (len > 1){ /* There may be one byte for padding somewhere */
105 rr = (struct rock_ridge *) chr;
106 if (rr->len == 0) goto out; /* Something got screwed up here */
107 sig = (chr[0] << 8) + chr[1];
108 chr += rr->len;
109 len -= rr->len;
111 switch(sig){
112 case SIG('R','R'):
113 rrflag = rr->u.RR.flags[0];
114 if (flag && !(rrflag & RR_PL)) goto out;
115 if (!flag && !(rrflag & RR_CL)) goto out;
116 break;
117 case SIG('S','P'):
118 CHECK_SP(goto out);
119 break;
120 case SIG('C','L'):
121 #ifdef DEBUG
122 printk("RR: CL\n");
123 #endif
124 if (flag == 0) {
125 retval = isonum_733(rr->u.CL.location);
126 goto out;
128 break;
129 case SIG('P','L'):
130 #ifdef DEBUG
131 printk("RR: PL\n");
132 #endif
133 if (flag != 0) {
134 retval = isonum_733(rr->u.PL.location);
135 goto out;
137 break;
138 case SIG('C','E'):
139 CHECK_CE; /* This tells is if there is a continuation record */
140 break;
141 default:
142 break;
146 MAYBE_CONTINUE(repeat, inode);
147 return retval;
148 out:
149 if(buffer) kfree(buffer);
150 return retval;
153 int get_rock_ridge_filename(struct iso_directory_record * de,
154 char * retname, struct inode * inode)
156 int len;
157 unsigned char * chr;
158 CONTINUE_DECLS;
159 int retnamlen = 0, truncate=0;
161 if (!inode->i_sb->u.isofs_sb.s_rock) return 0;
162 *retname = 0;
164 SETUP_ROCK_RIDGE(de, chr, len);
165 repeat:
167 struct rock_ridge * rr;
168 int sig;
170 while (len > 1){ /* There may be one byte for padding somewhere */
171 rr = (struct rock_ridge *) chr;
172 if (rr->len == 0) goto out; /* Something got screwed up here */
173 sig = (chr[0] << 8) + chr[1];
174 chr += rr->len;
175 len -= rr->len;
177 switch(sig){
178 case SIG('R','R'):
179 if((rr->u.RR.flags[0] & RR_NM) == 0) goto out;
180 break;
181 case SIG('S','P'):
182 CHECK_SP(goto out);
183 break;
184 case SIG('C','E'):
185 CHECK_CE;
186 break;
187 case SIG('N','M'):
188 if (truncate) break;
190 * If the flags are 2 or 4, this indicates '.' or '..'.
191 * We don't want to do anything with this, because it
192 * screws up the code that calls us. We don't really
193 * care anyways, since we can just use the non-RR
194 * name.
196 if (rr->u.NM.flags & 6) {
197 break;
200 if (rr->u.NM.flags & ~1) {
201 printk("Unsupported NM flag settings (%d)\n",rr->u.NM.flags);
202 break;
204 if((strlen(retname) + rr->len - 5) >= 254) {
205 truncate = 1;
206 break;
208 strncat(retname, rr->u.NM.name, rr->len - 5);
209 retnamlen += rr->len - 5;
210 break;
211 case SIG('R','E'):
212 #ifdef DEBUG
213 printk("RR: RE (%x)\n", inode->i_ino);
214 #endif
215 if (buffer) kfree(buffer);
216 return -1;
217 default:
218 break;
222 MAYBE_CONTINUE(repeat,inode);
223 return retnamlen; /* If 0, this file did not have a NM field */
224 out:
225 if(buffer) kfree(buffer);
226 return 0;
229 int parse_rock_ridge_inode(struct iso_directory_record * de,
230 struct inode * inode){
231 int len;
232 unsigned char * chr;
233 int symlink_len = 0;
234 CONTINUE_DECLS;
236 if (!inode->i_sb->u.isofs_sb.s_rock) return 0;
238 SETUP_ROCK_RIDGE(de, chr, len);
239 repeat:
241 int cnt, sig;
242 struct inode * reloc;
243 struct rock_ridge * rr;
244 int rootflag;
246 while (len > 1){ /* There may be one byte for padding somewhere */
247 rr = (struct rock_ridge *) chr;
248 if (rr->len == 0) goto out; /* Something got screwed up here */
249 sig = (chr[0] << 8) + chr[1];
250 chr += rr->len;
251 len -= rr->len;
253 switch(sig){
254 case SIG('R','R'):
255 if((rr->u.RR.flags[0] &
256 (RR_PX | RR_TF | RR_SL | RR_CL)) == 0) goto out;
257 break;
258 case SIG('S','P'):
259 CHECK_SP(goto out);
260 break;
261 case SIG('C','E'):
262 CHECK_CE;
263 break;
264 case SIG('E','R'):
265 inode->i_sb->u.isofs_sb.s_rock = 1;
266 printk(KERN_DEBUG"ISO 9660 Extensions: ");
267 { int p;
268 for(p=0;p<rr->u.ER.len_id;p++) printk("%c",rr->u.ER.data[p]);
270 printk("\n");
271 break;
272 case SIG('P','X'):
273 inode->i_mode = isonum_733(rr->u.PX.mode);
274 inode->i_nlink = isonum_733(rr->u.PX.n_links);
275 inode->i_uid = isonum_733(rr->u.PX.uid);
276 inode->i_gid = isonum_733(rr->u.PX.gid);
277 break;
278 case SIG('P','N'):
279 { int high, low;
280 high = isonum_733(rr->u.PN.dev_high);
281 low = isonum_733(rr->u.PN.dev_low);
283 * The Rock Ridge standard specifies that if sizeof(dev_t) <= 4,
284 * then the high field is unused, and the device number is completely
285 * stored in the low field. Some writers may ignore this subtlety,
286 * and as a result we test to see if the entire device number is
287 * stored in the low field, and use that.
289 if((low & ~0xff) && high == 0) {
290 inode->i_rdev = MKDEV(low >> 8, low & 0xff);
291 } else {
292 inode->i_rdev = MKDEV(high, low);
295 break;
296 case SIG('T','F'):
297 /* Some RRIP writers incorrectly place ctime in the TF_CREATE field.
298 Try to handle this correctly for either case. */
299 cnt = 0; /* Rock ridge never appears on a High Sierra disk */
300 if(rr->u.TF.flags & TF_CREATE)
301 inode->i_ctime = iso_date(rr->u.TF.times[cnt++].time, 0);
302 if(rr->u.TF.flags & TF_MODIFY)
303 inode->i_mtime = iso_date(rr->u.TF.times[cnt++].time, 0);
304 if(rr->u.TF.flags & TF_ACCESS)
305 inode->i_atime = iso_date(rr->u.TF.times[cnt++].time, 0);
306 if(rr->u.TF.flags & TF_ATTRIBUTES)
307 inode->i_ctime = iso_date(rr->u.TF.times[cnt++].time, 0);
308 break;
309 case SIG('S','L'):
310 {int slen;
311 struct SL_component * slp;
312 struct SL_component * oldslp;
313 slen = rr->len - 5;
314 slp = &rr->u.SL.link;
315 inode->i_size = symlink_len;
316 while (slen > 1){
317 rootflag = 0;
318 switch(slp->flags &~1){
319 case 0:
320 inode->i_size += slp->len;
321 break;
322 case 2:
323 inode->i_size += 1;
324 break;
325 case 4:
326 inode->i_size += 2;
327 break;
328 case 8:
329 rootflag = 1;
330 inode->i_size += 1;
331 break;
332 default:
333 printk("Symlink component flag not implemented\n");
335 slen -= slp->len + 2;
336 oldslp = slp;
337 slp = (struct SL_component *) (((char *) slp) + slp->len + 2);
339 if(slen < 2) {
340 if( ((rr->u.SL.flags & 1) != 0)
341 && ((oldslp->flags & 1) == 0) ) inode->i_size += 1;
342 break;
346 * If this component record isn't continued, then append a '/'.
348 if( (!rootflag)
349 && ((oldslp->flags & 1) == 0) ) inode->i_size += 1;
352 symlink_len = inode->i_size;
353 break;
354 case SIG('R','E'):
355 printk("Attempt to read inode for relocated directory\n");
356 goto out;
357 case SIG('C','L'):
358 #ifdef DEBUG
359 printk("RR CL (%x)\n",inode->i_ino);
360 #endif
361 inode->u.isofs_i.i_first_extent = isonum_733(rr->u.CL.location) <<
362 inode -> i_sb -> u.isofs_sb.s_log_zone_size;
363 reloc = iget(inode->i_sb, inode->u.isofs_i.i_first_extent);
364 if (!reloc)
365 goto out;
366 inode->i_mode = reloc->i_mode;
367 inode->i_nlink = reloc->i_nlink;
368 inode->i_uid = reloc->i_uid;
369 inode->i_gid = reloc->i_gid;
370 inode->i_rdev = reloc->i_rdev;
371 inode->i_size = reloc->i_size;
372 inode->i_atime = reloc->i_atime;
373 inode->i_ctime = reloc->i_ctime;
374 inode->i_mtime = reloc->i_mtime;
375 iput(reloc);
376 break;
377 default:
378 break;
382 MAYBE_CONTINUE(repeat,inode);
383 return 0;
384 out:
385 if(buffer) kfree(buffer);
386 return 0;
390 /* Returns the name of the file that this inode is symlinked to. This is
391 in malloc'd memory, so it needs to be freed, once we are through with it */
393 char * get_rock_ridge_symlink(struct inode * inode)
395 unsigned long bufsize = ISOFS_BUFFER_SIZE(inode);
396 unsigned char bufbits = ISOFS_BUFFER_BITS(inode);
397 struct buffer_head * bh;
398 char * rpnt = NULL;
399 unsigned char * pnt;
400 struct iso_directory_record * raw_inode;
401 CONTINUE_DECLS;
402 int block;
403 int sig;
404 int rootflag;
405 int len;
406 unsigned char * chr;
407 struct rock_ridge * rr;
409 if (!inode->i_sb->u.isofs_sb.s_rock)
410 panic("Cannot have symlink with high sierra variant of iso filesystem\n");
412 block = inode->i_ino >> bufbits;
413 bh = bread(inode->i_dev, block, bufsize);
414 if (!bh)
415 goto out_noread;
417 pnt = ((unsigned char *) bh->b_data) + (inode->i_ino & (bufsize - 1));
419 raw_inode = ((struct iso_directory_record *) pnt);
422 * If we go past the end of the buffer, there is some sort of error.
424 if ((inode->i_ino & (bufsize - 1)) + *pnt > bufsize)
425 goto out_bad_span;
427 /* Now test for possible Rock Ridge extensions which will override some of
428 these numbers in the inode structure. */
430 SETUP_ROCK_RIDGE(raw_inode, chr, len);
432 repeat:
433 while (len > 1){ /* There may be one byte for padding somewhere */
434 rr = (struct rock_ridge *) chr;
435 if (rr->len == 0) goto out; /* Something got screwed up here */
436 sig = (chr[0] << 8) + chr[1];
437 chr += rr->len;
438 len -= rr->len;
440 switch(sig){
441 case SIG('R','R'):
442 if((rr->u.RR.flags[0] & RR_SL) == 0) goto out;
443 break;
444 case SIG('S','P'):
445 CHECK_SP(goto out);
446 break;
447 case SIG('S','L'):
448 {int slen;
449 struct SL_component * oldslp;
450 struct SL_component * slp;
451 slen = rr->len - 5;
452 slp = &rr->u.SL.link;
453 while (slen > 1){
454 if (!rpnt){
455 rpnt = (char *) kmalloc (inode->i_size +1, GFP_KERNEL);
456 if (!rpnt) goto out;
457 *rpnt = 0;
459 rootflag = 0;
460 switch(slp->flags &~1){
461 case 0:
462 strncat(rpnt,slp->text, slp->len);
463 break;
464 case 2:
465 strcat(rpnt,".");
466 break;
467 case 4:
468 strcat(rpnt,"..");
469 break;
470 case 8:
471 rootflag = 1;
472 strcat(rpnt,"/");
473 break;
474 default:
475 printk("Symlink component flag not implemented (%d)\n",slen);
477 slen -= slp->len + 2;
478 oldslp = slp;
479 slp = (struct SL_component *) (((char *) slp) + slp->len + 2);
481 if(slen < 2) {
483 * If there is another SL record, and this component record
484 * isn't continued, then add a slash.
486 if( ((rr->u.SL.flags & 1) != 0)
487 && ((oldslp->flags & 1) == 0) ) strcat(rpnt,"/");
488 break;
492 * If this component record isn't continued, then append a '/'.
494 if( (!rootflag)
495 && ((oldslp->flags & 1) == 0) ) strcat(rpnt,"/");
498 break;
499 case SIG('C','E'):
500 CHECK_CE; /* This tells is if there is a continuation record */
501 break;
502 default:
503 break;
507 MAYBE_CONTINUE(repeat,inode);
509 out_freebh:
510 brelse(bh);
511 return rpnt;
513 /* error exit from macro */
514 out:
515 if(buffer)
516 kfree(buffer);
517 if(rpnt)
518 kfree(rpnt);
519 rpnt = NULL;
520 goto out_freebh;
521 out_noread:
522 printk("unable to read i-node block");
523 goto out_freebh;
524 out_bad_span:
525 printk("symlink spans iso9660 blocks\n");
526 goto out_freebh;