2 * ISO 9660 filesystem backend for GRUB (GRand Unified Bootloader)
3 * including Rock Ridge Extensions support
5 * Copyright (C) 1998, 1999 Kousuke Takai <tak@kmc.kyoto-u.ac.jp>
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
23 * linux/fs/isofs/rock.[ch]
24 * mkisofs-1.11.1/diag/isoinfo.c
25 * mkisofs-1.11.1/iso9660.h
26 * (all are written by Eric Youngdale)
29 * Leonid Lisovskiy <lly@pisem.net> 2003
38 /* iso9660 super-block data in memory */
40 unsigned long vol_sector
;
44 /* iso fs inode data in memory */
45 struct iso_inode_info
{
46 unsigned long file_start
;
50 ((struct iso_sb_info *)(FSYS_BUF))
52 ((struct iso_inode_info *)(FSYS_BUF+sizeof(struct iso_sb_info)))
53 #define PRIMDESC ((struct iso_primary_descriptor *)(FSYS_BUF + 2048))
54 #define DIRREC ((struct iso_directory_record *)(FSYS_BUF + 4096))
55 #define RRCONT_BUF ((unsigned char *)(FSYS_BUF + 6144))
56 #define NAME_BUF ((unsigned char *)(FSYS_BUF + 8192))
59 static inline unsigned long
60 grub_log2 (unsigned long word
)
62 asm volatile ("bsfl %1,%0"
67 #define log2 grub_log2
70 iso9660_devread (int sector
, int byte_offset
, int byte_len
, char *buf
)
72 static int read_count
= 0, threshold
= 2;
73 unsigned short sector_size_lg2
= log2(buf_geom
.sector_size
);
76 * We have to use own devread() function since BIOS return wrong geometry
80 errnum
= ERR_OUTSIDE_PART
;
86 sector
+= (byte_offset
>> sector_size_lg2
);
87 byte_offset
&= (buf_geom
.sector_size
- 1);
88 asm volatile ("shl%L0 %1,%0"
90 : "Ic"((int8_t)(ISO_SECTOR_BITS
- sector_size_lg2
)),
93 #if !defined(STAGE1_5)
94 if (disk_read_hook
&& debug
)
95 printf ("<%d, %d, %d>", sector
, byte_offset
, byte_len
);
96 #endif /* !STAGE1_5 */
98 read_count
+= (byte_len
>> 9);
99 if ((read_count
>> 11) > threshold
) {
101 threshold
+= 2; /* one dot every 2 MB */
103 return rawread(current_drive
, part_start
+ sector
, byte_offset
, byte_len
, buf
);
112 * Because there is no defined slice type ID for ISO-9660 filesystem,
113 * this test will pass only either (1) if entire disk is used, or
114 * (2) if current partition is BSD style sub-partition whose ID is
117 if ((current_partition
!= 0xFFFFFF)
118 && !IS_PC_SLICE_TYPE_BSD_WITH_FS(current_slice
, FS_ISO9660
))
122 * Currently, only FIRST session of MultiSession disks are supported !!!
124 for (sector
= 16 ; sector
< 32 ; sector
++)
126 if (!iso9660_devread(sector
, 0, sizeof(*PRIMDESC
), (char *)PRIMDESC
))
128 /* check ISO_VD_PRIMARY and ISO_STANDARD_ID */
129 if (PRIMDESC
->type
.l
== ISO_VD_PRIMARY
130 && !memcmp(PRIMDESC
->id
, ISO_STANDARD_ID
, sizeof(PRIMDESC
->id
)))
132 ISO_SUPER
->vol_sector
= sector
;
133 INODE
->file_start
= 0;
134 fsmax
= PRIMDESC
->volume_space_size
.l
;
143 iso9660_dir (char *dirname
)
145 struct iso_directory_record
*idr
;
147 struct rock_ridge
*ce_ptr
;
148 unsigned int pathlen
;
151 unsigned char file_type
;
153 unsigned char rr_flag
;
155 idr
= &PRIMDESC
->root_directory_record
;
156 INODE
->file_start
= 0;
160 while (*dirname
== '/') /* skip leading slashes */
162 /* pathlen = strcspn(dirname, "/\n\t "); */
165 && !isspace(dirname
[pathlen
]) && dirname
[pathlen
] != '/' ;
170 extent
= idr
->extent
.l
;
174 if (!iso9660_devread(extent
, 0, ISO_SECTOR_SIZE
, (char *)DIRREC
))
176 errnum
= ERR_FSYS_CORRUPT
;
181 idr
= (struct iso_directory_record
*)DIRREC
;
182 for (; idr
->length
.l
> 0;
183 idr
= (struct iso_directory_record
*)((char *)idr
+ idr
->length
.l
) )
185 const char *name
= idr
->name
;
186 unsigned int name_len
= idr
->name_len
.l
;
188 file_type
= (idr
->flags
.l
& 2) ? ISO_DIRECTORY
: ISO_REGULAR
;
191 if ((name
[0] == 0) || /* self */
192 (name
[0] == 1)) /* parent */
195 if (name_len
> 2 && CHECK2(name
+ name_len
- 2, ';', '1'))
197 name_len
-= 2; /* truncate trailing file version */
198 if (name_len
> 1 && name
[name_len
- 1] == '.')
199 name_len
--; /* truncate trailing dot */
203 * Parse Rock-Ridge extension
205 rr_len
= (idr
->length
.l
- idr
->name_len
.l
206 - sizeof(struct iso_directory_record
)
207 + sizeof(idr
->name
));
208 rr_ptr
.ptr
= ((unsigned char *)idr
+ idr
->name_len
.l
209 + sizeof(struct iso_directory_record
)
210 - sizeof(idr
->name
));
212 rr_ptr
.i
++, rr_len
--;
214 rr_flag
= RR_FLAG_NM
| RR_FLAG_PX
/*| RR_FLAG_SL*/;
218 if (rr_ptr
.rr
->version
!= 1)
223 "Non-supported version (%d) RockRidge chunk "
224 "`%c%c'\n", rr_ptr
.rr
->version
,
225 rr_ptr
.rr
->signature
& 0xFF,
226 rr_ptr
.rr
->signature
>> 8);
231 switch (rr_ptr
.rr
->signature
)
233 case RRMAGIC('R', 'R'):
234 if ( rr_ptr
.rr
->len
>= (4+sizeof(struct RR
)))
235 rr_flag
&= rr_ptr
.rr
->u
.rr
.flags
.l
;
237 case RRMAGIC('N', 'M'):
238 name
= rr_ptr
.rr
->u
.nm
.name
;
239 name_len
= rr_ptr
.rr
->len
- (4+sizeof(struct NM
));
240 rr_flag
&= ~RR_FLAG_NM
;
242 case RRMAGIC('P', 'X'):
243 if (rr_ptr
.rr
->len
>= (4+sizeof(struct PX
)))
245 file_type
= ((rr_ptr
.rr
->u
.px
.mode
.l
& POSIX_S_IFMT
)
248 : ((rr_ptr
.rr
->u
.px
.mode
.l
& POSIX_S_IFMT
)
250 ? ISO_DIRECTORY
: ISO_OTHER
));
251 rr_flag
&= ~RR_FLAG_PX
;
254 case RRMAGIC('C', 'E'):
255 if (rr_ptr
.rr
->len
>= (4+sizeof(struct CE
)))
258 #if 0 // RockRidge symlinks are not supported yet
259 case RRMAGIC('S', 'L'):
262 unsigned char rootflag
, prevflag
;
263 char *rpnt
= NAME_BUF
+1024;
264 struct SL_component
*slp
;
266 slen
= rr_ptr
.rr
->len
- (4+1);
267 slp
= &rr_ptr
.rr
->u
.sl
.link
;
271 switch (slp
->flags
.l
)
274 memcpy(rpnt
, slp
->text
, slp
->len
);
288 printf("Symlink component flag not implemented (%d)\n",
293 slen
-= slp
->len
+ 2;
294 prevflag
= slp
->flags
.l
;
295 slp
= (struct SL_component
*) ((char *) slp
+ slp
->len
+ 2);
300 * If there is another SL record, and this component
301 * record isn't continued, then add a slash.
303 if ((!rootflag
) && (rr_ptr
.rr
->u
.sl
.flags
.l
& 1) && !(prevflag
& 1))
309 * If this component record isn't continued, then append a '/'.
311 if (!rootflag
&& !(prevflag
& 1))
315 grub_putstr(NAME_BUF
+1024);// debug print!
317 rr_flag
&= ~RR_FLAG_SL
;
326 * There is no more extension we expects...
330 rr_len
-= rr_ptr
.rr
->len
;
331 rr_ptr
.ptr
+= rr_ptr
.rr
->len
;
332 if (rr_len
< 4 && ce_ptr
!= NULL
)
334 /* preserve name before loading new extent. */
335 if( RRCONT_BUF
<= (unsigned char *)name
336 && (unsigned char *)name
< RRCONT_BUF
+ ISO_SECTOR_SIZE
)
338 memcpy(NAME_BUF
, name
, name_len
);
341 rr_ptr
.ptr
= RRCONT_BUF
+ ce_ptr
->u
.ce
.offset
.l
;
342 rr_len
= ce_ptr
->u
.ce
.size
.l
;
343 if (!iso9660_devread(ce_ptr
->u
.ce
.extent
.l
, 0, ISO_SECTOR_SIZE
, RRCONT_BUF
))
345 errnum
= 0; /* this is not fatal. */
353 if (name_len
>= pathlen
354 && !memcmp(name
, dirname
, pathlen
))
356 if (dirname
[pathlen
] == '/' || !print_possibilities
)
359 * DIRNAME is directory component of pathname,
360 * or we are to open a file.
362 if (pathlen
== name_len
)
364 if (dirname
[pathlen
] == '/')
366 if (file_type
!= ISO_DIRECTORY
)
368 errnum
= ERR_BAD_FILETYPE
;
373 if (file_type
!= ISO_REGULAR
)
375 errnum
= ERR_BAD_FILETYPE
;
378 INODE
->file_start
= idr
->extent
.l
;
380 filemax
= idr
->size
.l
;
384 else /* Completion */
387 if (print_possibilities
> 0)
388 print_possibilities
= -print_possibilities
;
389 memcpy(NAME_BUF
, name
, name_len
);
390 NAME_BUF
[name_len
] = '\0';
391 print_a_completion (NAME_BUF
);
397 size
-= ISO_SECTOR_SIZE
;
400 if (dirname
[pathlen
] == '/' || print_possibilities
>= 0)
402 errnum
= ERR_FILE_NOT_FOUND
;
409 } while (*dirname
== '/');
415 iso9660_read (char *buf
, int len
)
417 int sector
, blkoffset
, size
, ret
;
419 if (INODE
->file_start
== 0)
423 blkoffset
= filepos
& (ISO_SECTOR_SIZE
- 1);
424 sector
= filepos
>> ISO_SECTOR_BITS
;
427 size
= ISO_SECTOR_SIZE
- blkoffset
;
431 disk_read_func
= disk_read_hook
;
433 if (!iso9660_devread(INODE
->file_start
+ sector
, blkoffset
, size
, buf
))
436 disk_read_func
= NULL
;
449 #endif /* FSYS_ISO9660 */