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>
15 #include <linux/pagemap.h>
16 #include <linux/smp_lock.h>
20 /* These functions are designed to read the system areas of a directory record
21 * and extract relevant information. There are different functions provided
22 * depending upon what information we need at the time. One function fills
23 * out an inode structure, a second one extracts a filename, a third one
24 * returns a symbolic link name, and a fourth one returns the extent number
27 #define SIG(A,B) ((A << 8) | B)
30 /* This is a way of ensuring that we have something in the system
31 use fields that is compatible with Rock Ridge */
32 #define CHECK_SP(FAIL) \
33 if(rr->u.SP.magic[0] != 0xbe) FAIL; \
34 if(rr->u.SP.magic[1] != 0xef) FAIL;
36 /* We define a series of macros because each function must do exactly the
37 same thing in certain places. We use the macros to ensure that everything
40 #define CONTINUE_DECLS \
41 int cont_extent = 0, cont_offset = 0, cont_size = 0; \
45 {cont_extent = isonum_733(rr->u.CE.extent); \
46 cont_offset = isonum_733(rr->u.CE.offset); \
47 cont_size = isonum_733(rr->u.CE.size);}
49 #define SETUP_ROCK_RIDGE(DE,CHR,LEN) \
50 {LEN= sizeof(struct iso_directory_record) + DE->name_len[0]; \
52 CHR = ((unsigned char *) DE) + LEN; \
53 LEN = *((unsigned char *) DE) - LEN;}
55 #define MAYBE_CONTINUE(LABEL,DEV) \
56 {if (buffer) kfree(buffer); \
58 int block, offset, offset1; \
59 struct buffer_head * pbh; \
60 buffer = kmalloc(cont_size,GFP_KERNEL); \
61 if (!buffer) goto out; \
62 block = cont_extent; \
63 offset = cont_offset; \
65 pbh = bread(DEV->i_dev, block, ISOFS_BUFFER_SIZE(DEV)); \
67 memcpy(buffer + offset1, pbh->b_data + offset, cont_size - offset1); \
69 chr = (unsigned char *) buffer; \
76 printk("Unable to read rock-ridge attributes\n"); \
79 /* This is the inner layer of the get filename routine, and is called
80 for each system area and continuation record related to the file */
82 int find_rock_ridge_relocation(struct iso_directory_record
* de
,
83 struct inode
* inode
) {
91 /* If this is a '..' then we are looking for the parent, otherwise we
92 are looking for the child */
94 if (de
->name
[0]==1 && de
->name_len
[0]==1) flag
= 1;
95 /* Return value if we do not find appropriate record. */
96 retval
= isonum_733 (de
->extent
);
98 if (!inode
->i_sb
->u
.isofs_sb
.s_rock
) return retval
;
100 SETUP_ROCK_RIDGE(de
, chr
, len
);
104 struct rock_ridge
* rr
;
106 while (len
> 1){ /* There may be one byte for padding somewhere */
107 rr
= (struct rock_ridge
*) chr
;
108 if (rr
->len
== 0) goto out
; /* Something got screwed up here */
109 sig
= (chr
[0] << 8) + chr
[1];
115 rrflag
= rr
->u
.RR
.flags
[0];
116 if (flag
&& !(rrflag
& RR_PL
)) goto out
;
117 if (!flag
&& !(rrflag
& RR_CL
)) goto out
;
124 retval
= isonum_733(rr
->u
.CL
.location
);
130 retval
= isonum_733(rr
->u
.PL
.location
);
135 CHECK_CE
; /* This tells is if there is a continuation record */
142 MAYBE_CONTINUE(repeat
, inode
);
145 if(buffer
) kfree(buffer
);
149 /* return length of name field; 0: not found, -1: to be ignored */
150 int get_rock_ridge_filename(struct iso_directory_record
* de
,
151 char * retname
, struct inode
* inode
)
156 int retnamlen
= 0, truncate
=0;
158 if (!inode
->i_sb
->u
.isofs_sb
.s_rock
) return 0;
161 SETUP_ROCK_RIDGE(de
, chr
, len
);
164 struct rock_ridge
* rr
;
167 while (len
> 1){ /* There may be one byte for padding somewhere */
168 rr
= (struct rock_ridge
*) chr
;
169 if (rr
->len
== 0) goto out
; /* Something got screwed up here */
170 sig
= (chr
[0] << 8) + chr
[1];
176 if((rr
->u
.RR
.flags
[0] & RR_NM
) == 0) goto out
;
187 * If the flags are 2 or 4, this indicates '.' or '..'.
188 * We don't want to do anything with this, because it
189 * screws up the code that calls us. We don't really
190 * care anyways, since we can just use the non-RR
193 if (rr
->u
.NM
.flags
& 6) {
197 if (rr
->u
.NM
.flags
& ~1) {
198 printk("Unsupported NM flag settings (%d)\n",rr
->u
.NM
.flags
);
201 if((strlen(retname
) + rr
->len
- 5) >= 254) {
205 strncat(retname
, rr
->u
.NM
.name
, rr
->len
- 5);
206 retnamlen
+= rr
->len
- 5;
209 if (buffer
) kfree(buffer
);
216 MAYBE_CONTINUE(repeat
,inode
);
217 return retnamlen
; /* If 0, this file did not have a NM field */
219 if(buffer
) kfree(buffer
);
223 int parse_rock_ridge_inode(struct iso_directory_record
* de
,
224 struct inode
* inode
){
230 if (!inode
->i_sb
->u
.isofs_sb
.s_rock
) return 0;
232 SETUP_ROCK_RIDGE(de
, chr
, len
);
236 struct inode
* reloc
;
237 struct rock_ridge
* rr
;
240 while (len
> 1){ /* There may be one byte for padding somewhere */
241 rr
= (struct rock_ridge
*) chr
;
242 if (rr
->len
== 0) goto out
; /* Something got screwed up here */
243 sig
= (chr
[0] << 8) + chr
[1];
249 if((rr
->u
.RR
.flags
[0] &
250 (RR_PX
| RR_TF
| RR_SL
| RR_CL
)) == 0) goto out
;
259 inode
->i_sb
->u
.isofs_sb
.s_rock
= 1;
260 printk(KERN_DEBUG
"ISO 9660 Extensions: ");
262 for(p
=0;p
<rr
->u
.ER
.len_id
;p
++) printk("%c",rr
->u
.ER
.data
[p
]);
267 inode
->i_mode
= isonum_733(rr
->u
.PX
.mode
);
268 inode
->i_nlink
= isonum_733(rr
->u
.PX
.n_links
);
269 inode
->i_uid
= isonum_733(rr
->u
.PX
.uid
);
270 inode
->i_gid
= isonum_733(rr
->u
.PX
.gid
);
274 high
= isonum_733(rr
->u
.PN
.dev_high
);
275 low
= isonum_733(rr
->u
.PN
.dev_low
);
277 * The Rock Ridge standard specifies that if sizeof(dev_t) <= 4,
278 * then the high field is unused, and the device number is completely
279 * stored in the low field. Some writers may ignore this subtlety,
280 * and as a result we test to see if the entire device number is
281 * stored in the low field, and use that.
283 if((low
& ~0xff) && high
== 0) {
284 inode
->i_rdev
= MKDEV(low
>> 8, low
& 0xff);
286 inode
->i_rdev
= MKDEV(high
, low
);
291 /* Some RRIP writers incorrectly place ctime in the TF_CREATE field.
292 Try to handle this correctly for either case. */
293 cnt
= 0; /* Rock ridge never appears on a High Sierra disk */
294 if(rr
->u
.TF
.flags
& TF_CREATE
)
295 inode
->i_ctime
= iso_date(rr
->u
.TF
.times
[cnt
++].time
, 0);
296 if(rr
->u
.TF
.flags
& TF_MODIFY
)
297 inode
->i_mtime
= iso_date(rr
->u
.TF
.times
[cnt
++].time
, 0);
298 if(rr
->u
.TF
.flags
& TF_ACCESS
)
299 inode
->i_atime
= iso_date(rr
->u
.TF
.times
[cnt
++].time
, 0);
300 if(rr
->u
.TF
.flags
& TF_ATTRIBUTES
)
301 inode
->i_ctime
= iso_date(rr
->u
.TF
.times
[cnt
++].time
, 0);
305 struct SL_component
* slp
;
306 struct SL_component
* oldslp
;
308 slp
= &rr
->u
.SL
.link
;
309 inode
->i_size
= symlink_len
;
312 switch(slp
->flags
&~1){
314 inode
->i_size
+= slp
->len
;
327 printk("Symlink component flag not implemented\n");
329 slen
-= slp
->len
+ 2;
331 slp
= (struct SL_component
*) (((char *) slp
) + slp
->len
+ 2);
334 if( ((rr
->u
.SL
.flags
& 1) != 0)
335 && ((oldslp
->flags
& 1) == 0) ) inode
->i_size
+= 1;
340 * If this component record isn't continued, then append a '/'.
342 if (!rootflag
&& (oldslp
->flags
& 1) == 0)
346 symlink_len
= inode
->i_size
;
349 printk(KERN_WARNING
"Attempt to read inode for relocated directory\n");
352 inode
->u
.isofs_i
.i_first_extent
= isonum_733(rr
->u
.CL
.location
);
353 reloc
= iget(inode
->i_sb
,
354 (inode
->u
.isofs_i
.i_first_extent
<<
355 inode
-> i_sb
-> u
.isofs_sb
.s_log_zone_size
));
358 inode
->i_mode
= reloc
->i_mode
;
359 inode
->i_nlink
= reloc
->i_nlink
;
360 inode
->i_uid
= reloc
->i_uid
;
361 inode
->i_gid
= reloc
->i_gid
;
362 inode
->i_rdev
= reloc
->i_rdev
;
363 inode
->i_size
= reloc
->i_size
;
364 inode
->i_atime
= reloc
->i_atime
;
365 inode
->i_ctime
= reloc
->i_ctime
;
366 inode
->i_mtime
= reloc
->i_mtime
;
374 MAYBE_CONTINUE(repeat
,inode
);
377 if(buffer
) kfree(buffer
);
381 static char *get_symlink_chunk(char *rpnt
, struct rock_ridge
*rr
)
385 struct SL_component
*oldslp
;
386 struct SL_component
*slp
;
388 slp
= &rr
->u
.SL
.link
;
391 switch (slp
->flags
& ~1) {
393 memcpy(rpnt
, slp
->text
, slp
->len
);
407 printk("Symlink component flag not implemented (%d)\n",
410 slen
-= slp
->len
+ 2;
412 slp
= (struct SL_component
*) ((char *) slp
+ slp
->len
+ 2);
416 * If there is another SL record, and this component
417 * record isn't continued, then add a slash.
419 if ((rr
->u
.SL
.flags
& 1) && !(oldslp
->flags
& 1))
425 * If this component record isn't continued, then append a '/'.
427 if (!rootflag
&& !(oldslp
->flags
& 1))
435 /* readpage() for symlinks: reads symlink contents into the page and either
436 makes it uptodate and returns 0 or returns error (-EIO) */
438 static int rock_ridge_symlink_readpage(struct file
*file
, struct page
*page
)
440 struct inode
*inode
= page
->mapping
->host
;
441 char *link
= kmap(page
);
442 unsigned long bufsize
= ISOFS_BUFFER_SIZE(inode
);
443 unsigned char bufbits
= ISOFS_BUFFER_BITS(inode
);
444 struct buffer_head
*bh
;
447 struct iso_directory_record
*raw_inode
;
453 struct rock_ridge
*rr
;
455 if (!inode
->i_sb
->u
.isofs_sb
.s_rock
)
456 panic ("Cannot have symlink with high sierra variant of iso filesystem\n");
458 block
= inode
->i_ino
>> bufbits
;
460 bh
= bread(inode
->i_dev
, block
, bufsize
);
464 pnt
= (unsigned char *) bh
->b_data
+ (inode
->i_ino
& (bufsize
- 1));
466 raw_inode
= (struct iso_directory_record
*) pnt
;
469 * If we go past the end of the buffer, there is some sort of error.
471 if ((inode
->i_ino
& (bufsize
- 1)) + *pnt
> bufsize
)
474 /* Now test for possible Rock Ridge extensions which will override
475 some of these numbers in the inode structure. */
477 SETUP_ROCK_RIDGE(raw_inode
, chr
, len
);
480 while (len
> 1) { /* There may be one byte for padding somewhere */
481 rr
= (struct rock_ridge
*) chr
;
483 goto out
; /* Something got screwed up here */
484 sig
= (chr
[0] << 8) + chr
[1];
490 if ((rr
->u
.RR
.flags
[0] & RR_SL
) == 0)
497 rpnt
= get_symlink_chunk(rpnt
, rr
);
500 /* This tells is if there is a continuation record */
506 MAYBE_CONTINUE(repeat
, inode
);
513 SetPageUptodate(page
);
518 /* error exit from macro */
524 printk("unable to read i-node block");
527 printk("symlink spans iso9660 blocks\n");
537 struct address_space_operations isofs_symlink_aops
= {
538 readpage
: rock_ridge_symlink_readpage