7 #include "iso9660_fs.h"
9 static struct inode *new_iso_inode(void)
11 struct inode *inode = malloc(sizeof(*inode));
14 malloc_error("inode structure in new_iso_inode");
17 memset(inode, 0, sizeof(*inode));
19 inode->data = malloc(sizeof(uint32_t));
21 malloc_error("inode->data in new_iso_inode");
30 static void iso_close_file(struct file *file)
34 free_inode(file->inode);
38 static inline struct iso_sb_info * ISO_SB(struct fs_info *fs)
44 * Mangle a filename pointed to by src into a buffer pointed
45 * to by dst; ends on encountering any whitespace.
48 * This verifies that a filename is < FilENAME_MAX characters,
49 * doesn't contain whitespace, zero-pads the output buffer,
50 * and removes trailing dots and redumndant slashes, so "repe
51 * cmpsb" can do a compare, and the path-searching routine gets
52 * a bit of an easier job.
55 static void iso_mangle_name(char *dst, const char *src)
58 int i = FILENAME_MAX - 1;
60 while (not_whitespace(*src)) {
62 if ( *(src+1) == '/' ) {
77 if ( (*(dst-1) != '.') && (*(dst-1) != '/') )
89 static int iso_convert_name(char *dst, char *src, int len)
94 for (; i < len; i++) {
99 /* remove ';1' in the end */
100 if (c == ';' && i == len - 2 && src[i + 1] == '1')
102 /* convert others ';' to '.' */
108 /* Then remove the terminal dots */
109 while (*(dst - 1) == '.') {
121 * Unlike strcmp, it does return 1 on match, or reutrn 0 if not match.
123 static int iso_compare_name(char *de_name, int len, char *file_name)
125 char iso_file_name[256];
126 char *p = iso_file_name;
130 i = iso_convert_name(iso_file_name, de_name, len);
132 if (i != (int)strlen(file_name))
139 /* convert to lower case */
149 static inline int cdrom_read_blocks(struct disk *disk, void *buf,
150 int block, int blocks)
152 return disk->rdwr_sectors(disk, buf, block, blocks, 0);
156 * Get multiple clusters from a file, given the file pointer.
158 static uint32_t iso_getfssec(struct file *file, char *buf,
159 int blocks, bool *have_more)
161 struct fs_info *fs = file->fs;
162 struct disk *disk = fs->fs_dev->disk;
163 uint32_t bytes_read = blocks << fs->block_shift;
164 uint32_t bytes_left = file->inode->size - file->offset;
165 uint32_t blocks_left = (bytes_left + BLOCK_SIZE(file->fs) - 1)
166 >> file->fs->block_shift;
167 block_t block = *file->inode->data + (file->offset >> fs->block_shift);
169 if (blocks > blocks_left)
170 blocks = blocks_left;
171 cdrom_read_blocks(disk, buf, block, blocks);
173 if (bytes_read >= bytes_left) {
174 bytes_read = bytes_left;
180 file->offset += bytes_read;
185 * Find a entry in the specified dir with name _dname_.
187 static struct iso_dir_entry *iso_find_entry(char *dname, struct inode *inode)
189 block_t dir_block = *inode->data;
190 int i = 0, offset = 0;
192 int de_name_len, de_len;
193 struct iso_dir_entry *de;
194 struct iso_dir_entry tmpde;
195 struct cache_struct *cs = NULL;
199 if (++i > inode->blocks)
201 cs = get_cache_block(this_fs->fs_dev, dir_block++);
202 de = (struct iso_dir_entry *)cs->data;
205 de = (struct iso_dir_entry *)(cs->data + offset);
208 if (de_len == 0) { /* move on to the next block */
214 /* Make sure we have a full directory entry */
215 if (offset >= BLOCK_SIZE(this_fs)) {
216 int slop = de_len + BLOCK_SIZE(this_fs) - offset;
218 memcpy(&tmpde, de, slop);
219 offset &= BLOCK_SIZE(this_fs) - 1;
221 if (++i > inode->blocks)
223 cs = get_cache_block(this_fs->fs_dev, dir_block++);
224 memcpy((void *)&tmpde + slop, cs->data, offset);
230 printf("Corrupted directory entry in sector %u\n",
231 (uint32_t)(dir_block - 1));
235 de_name_len = de->name_len;
237 /* Handling the special case ".' and '..' here */
238 if((de_name_len == 1) && (*de_name == 0)) {
240 } else if ((de_name_len == 1) && (*de_name == 1)) {
244 if (iso_compare_name(de_name, de_name_len, dname))
249 static inline int get_inode_mode(uint8_t flags)
257 static struct inode *iso_get_inode(struct iso_dir_entry *de)
259 struct inode *inode = new_iso_inode();
263 inode->mode = get_inode_mode(de->flags);
264 inode->size = *(uint32_t *)de->size;
265 *inode->data = *(uint32_t *)de->extent;
266 inode->blocks = (inode->size + BLOCK_SIZE(this_fs) - 1)
267 >> this_fs->block_shift;
273 static struct inode *iso_iget_root(void)
275 struct inode *inode = new_iso_inode();
276 struct iso_dir_entry *root = &ISO_SB(this_fs)->root;
282 inode->size = *(uint32_t *)root->size;
283 *inode->data = *(uint32_t *)root->extent;
284 inode->blocks = (inode->size + BLOCK_SIZE(this_fs) - 1)
285 >> this_fs->block_shift;
290 static struct inode *iso_iget(char *dname, struct inode *parent)
292 struct iso_dir_entry *de;
294 de = iso_find_entry(dname, parent);
298 return iso_get_inode(de);
301 /* Load the config file, return 1 if failed, or 0 */
302 static int iso_load_config(void)
304 const char *config_file[] = {
305 "/boot/isolinux/isolinux.cfg",
306 "/isolinux/isolinux.cfg"
313 memset(®s, 0, sizeof regs);
314 strcpy(ConfigName, config_file[i]);
315 regs.edi.w[0] = OFFS_WRT(ConfigName, 0);
316 call16(core_open, ®s, ®s);
317 if (!(regs.eflags.l & EFLAGS_ZF))
321 printf("No config file found\n");
325 strcpy(ConfigName, "isolinux.cfg");
326 strcpy(CurrentDirName, config_file[i]);
327 p = strrchr(CurrentDirName, '/');
334 static int iso_fs_init(struct fs_info *fs)
336 struct iso_sb_info *sbi;
340 sbi = malloc(sizeof(*sbi));
342 malloc_error("iso_sb_info structure");
347 cdrom_read_blocks(fs->fs_dev->disk, trackbuf, 16, 1);
348 memcpy(&sbi->root, trackbuf + ROOT_DIR_OFFSET, sizeof(sbi->root));
350 fs->block_shift = 11;
351 return fs->block_shift;
355 const struct fs_ops iso_fs_ops = {
357 .fs_flags = FS_USEMEM | FS_THISIND,
358 .fs_init = iso_fs_init,
360 .getfssec = iso_getfssec,
361 .close_file = iso_close_file,
362 .mangle_name = iso_mangle_name,
363 .unmangle_name = generic_unmangle_name,
364 .load_config = iso_load_config,
365 .iget_root = iso_iget_root,
366 .iget_current = NULL,