2 * linux/fs/isofs/rock.c
4 * (C) 1992, 1993 Eric Youngdale
6 * Rock Ridge Extensions to iso9660
9 #include <linux/stat.h>
10 #include <linux/sched.h>
11 #include <linux/iso_fs.h>
12 #include <linux/string.h>
14 #include <linux/malloc.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
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
38 #define CONTINUE_DECLS \
39 int cont_extent = 0, cont_offset = 0, cont_size = 0; \
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]; \
50 CHR = ((unsigned char *) DE) + LEN; \
51 LEN = *((unsigned char *) DE) - LEN;}
53 #define MAYBE_CONTINUE(LABEL,DEV) \
54 {if (buffer) kfree(buffer); \
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; \
63 pbh = bread(DEV->i_dev, block, ISOFS_BUFFER_SIZE(DEV)); \
65 memcpy(buffer + offset1, pbh->b_data + offset, cont_size - offset1); \
67 chr = (unsigned char *) buffer; \
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
) {
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
);
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];
113 rrflag
= rr
->u
.RR
.flags
[0];
114 if (flag
&& !(rrflag
& RR_PL
)) goto out
;
115 if (!flag
&& !(rrflag
& RR_CL
)) goto out
;
125 retval
= isonum_733(rr
->u
.CL
.location
);
134 retval
= isonum_733(rr
->u
.PL
.location
);
139 CHECK_CE
; /* This tells is if there is a continuation record */
146 MAYBE_CONTINUE(repeat
, inode
);
149 if(buffer
) kfree(buffer
);
153 int get_rock_ridge_filename(struct iso_directory_record
* de
,
154 char * retname
, struct inode
* inode
)
159 int retnamlen
= 0, truncate
=0;
161 if (!inode
->i_sb
->u
.isofs_sb
.s_rock
) return 0;
164 SETUP_ROCK_RIDGE(de
, chr
, len
);
167 struct rock_ridge
* rr
;
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];
179 if((rr
->u
.RR
.flags
[0] & RR_NM
) == 0) goto out
;
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
196 if (rr
->u
.NM
.flags
& 6) {
200 if (rr
->u
.NM
.flags
& ~1) {
201 printk("Unsupported NM flag settings (%d)\n",rr
->u
.NM
.flags
);
204 if((strlen(retname
) + rr
->len
- 5) >= 254) {
208 strncat(retname
, rr
->u
.NM
.name
, rr
->len
- 5);
209 retnamlen
+= rr
->len
- 5;
213 printk("RR: RE (%x)\n", inode
->i_ino
);
215 if (buffer
) kfree(buffer
);
222 MAYBE_CONTINUE(repeat
,inode
);
223 return retnamlen
; /* If 0, this file did not have a NM field */
225 if(buffer
) kfree(buffer
);
229 int parse_rock_ridge_inode(struct iso_directory_record
* de
,
230 struct inode
* inode
){
236 if (!inode
->i_sb
->u
.isofs_sb
.s_rock
) return 0;
238 SETUP_ROCK_RIDGE(de
, chr
, len
);
242 struct inode
* reloc
;
243 struct rock_ridge
* rr
;
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];
255 if((rr
->u
.RR
.flags
[0] &
256 (RR_PX
| RR_TF
| RR_SL
| RR_CL
)) == 0) goto out
;
265 inode
->i_sb
->u
.isofs_sb
.s_rock
= 1;
266 printk(KERN_DEBUG
"ISO 9660 Extensions: ");
268 for(p
=0;p
<rr
->u
.ER
.len_id
;p
++) printk("%c",rr
->u
.ER
.data
[p
]);
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
);
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);
292 inode
->i_rdev
= MKDEV(high
, low
);
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);
311 struct SL_component
* slp
;
312 struct SL_component
* oldslp
;
314 slp
= &rr
->u
.SL
.link
;
315 inode
->i_size
= symlink_len
;
318 switch(slp
->flags
&~1){
320 inode
->i_size
+= slp
->len
;
333 printk("Symlink component flag not implemented\n");
335 slen
-= slp
->len
+ 2;
337 slp
= (struct SL_component
*) (((char *) slp
) + slp
->len
+ 2);
340 if( ((rr
->u
.SL
.flags
& 1) != 0)
341 && ((oldslp
->flags
& 1) == 0) ) inode
->i_size
+= 1;
346 * If this component record isn't continued, then append a '/'.
349 && ((oldslp
->flags
& 1) == 0) ) inode
->i_size
+= 1;
352 symlink_len
= inode
->i_size
;
355 printk("Attempt to read inode for relocated directory\n");
359 printk("RR CL (%x)\n",inode
->i_ino
);
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
);
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
;
382 MAYBE_CONTINUE(repeat
,inode
);
385 if(buffer
) kfree(buffer
);
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
;
400 struct iso_directory_record
* raw_inode
;
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
);
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
)
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
);
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];
442 if((rr
->u
.RR
.flags
[0] & RR_SL
) == 0) goto out
;
449 struct SL_component
* oldslp
;
450 struct SL_component
* slp
;
452 slp
= &rr
->u
.SL
.link
;
455 rpnt
= (char *) kmalloc (inode
->i_size
+1, GFP_KERNEL
);
460 switch(slp
->flags
&~1){
462 strncat(rpnt
,slp
->text
, slp
->len
);
475 printk("Symlink component flag not implemented (%d)\n",slen
);
477 slen
-= slp
->len
+ 2;
479 slp
= (struct SL_component
*) (((char *) slp
) + slp
->len
+ 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
,"/");
492 * If this component record isn't continued, then append a '/'.
495 && ((oldslp
->flags
& 1) == 0) ) strcat(rpnt
,"/");
500 CHECK_CE
; /* This tells is if there is a continuation record */
507 MAYBE_CONTINUE(repeat
,inode
);
513 /* error exit from macro */
522 printk("unable to read i-node block");
525 printk("symlink spans iso9660 blocks\n");