3 * Copyright (C) 2008 Tomas 'ZeXx86' Jedrzejek (zexx86@gmail.com)
4 * Copyright (C) 2009 Tomas 'ZeXx86' Jedrzejek (zexx86@gmail.com)
6 * This program is free software: you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation, either version 3 of the License, or
9 * (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program. If not, see <http://www.gnu.org/licenses/>.
30 #include <partition.h>
32 #define ISOFS_SUPERBLOCK_SECTOR 16 // NOTE: sector is 2kB length
34 #define ISOFS_DIR_FLAGS_HIDDEN 0x1
35 #define ISOFS_DIR_FLAGS_DIR 0x2
37 #define __PACKED__ __attribute__ ((__packed__))
43 unsigned char sys_id
[32];
44 unsigned char vol_id
[32];
45 unsigned char zeros
[8];
46 unsigned long sectors
[2];
47 unsigned char zeros2
[32];
48 unsigned short set_size
[2];
49 unsigned short seq_num
[2];
50 unsigned short sector_size
[2];
51 unsigned long path_tbl
[2];
52 unsigned first_sec_fle_ptbl
;
53 unsigned first_sec_sle_ptbl
;
54 unsigned first_sec_fbe_ptbl
;
55 unsigned first_sec_sbe_ptbl
;
56 unsigned char root_dir_rec
[34]; // 158
57 unsigned char set_id
[128];
58 unsigned char pub_id
[128];
59 unsigned char datap_id
[128]; // 542
60 unsigned char app_id
[128];
61 unsigned char copy_id
[37];
62 unsigned char abst_id
[37];
63 unsigned char bibl_id
[37];
64 unsigned char date_volcr
[17];
65 unsigned char date_mod
[17];
66 unsigned char date_expir
[17];
67 unsigned char date_eff
[17];
70 unsigned char reserved
[512];
71 unsigned char zeros3
[653];
72 } __PACKED__ isofs_volume_t
; // 1395
75 unsigned char name_len
;
76 unsigned char sect_num
;
78 unsigned short rec_num
;
80 } __PACKED__ isofs_path_t
;
83 unsigned char rec_len
;
84 unsigned char sec_num
;
85 unsigned long data_sec
[2];
86 unsigned long data_len
[2];
93 unsigned char time_offset
;
95 unsigned char unit_size
;
96 unsigned char gap_size
;
97 unsigned short vol_seq_num
[2];
100 unsigned char id2
[50];
101 } __PACKED__ isofs_dir_t
;
103 typedef struct isofs_path_context
{
104 struct isofs_path_context
*next
, *prev
;
106 unsigned char name_len
;
107 unsigned char sect_num
;
109 unsigned short rec_num
;
113 isofs_pathtbl_t path_table_list
;
115 /* FIXME: limit for one mounted iso fs */
116 static isofs_pathtbl_t
*path_curr
;
117 static isofs_pathtbl_t
*path_prev
;
120 static unsigned char tolower (char c
)
122 return ((c
>= 'A' && c
<= 'Z') ? c
+ 32: c
);
125 static void toupper (char *str
)
129 for (i
= 0; str
[i
]; i
++ ) {
130 if (str
[i
] >= 'a' && str
[i
] <= 'z')
135 unsigned isofs_sector_read (partition_t
*p
, unsigned sector
, unsigned char *buffer
)
137 /* iso9660 sector is 2kB length */
138 unsigned address
= sector
* 4;
140 /* lba28_drive_read () read 512 bytes from drive 4 times +512 bytes */
141 lba28_drive_read (p
, address
, (unsigned char *) buffer
);
142 lba28_drive_read (p
, address
+1, (unsigned char *) buffer
+512);
143 lba28_drive_read (p
, address
+2, (unsigned char *) buffer
+1024);
144 lba28_drive_read (p
, address
+3, (unsigned char *) buffer
+1536);
149 isofs_pathtbl_t
*isofs_path_find (char *name
)
151 isofs_pathtbl_t
*path
;
152 for (path
= path_table_list
.next
; path
!= &path_table_list
; path
= path
->next
) {
153 if (!strcmp (path
->name
, name
))
160 unsigned isofs_dir_scan (partition_t
*p
, char *block
)
162 /*dir = (isofs_dir_t *) (block + dir->rec_len);
164 dir = (isofs_dir_t *) (block + dir->rec_len);*/
166 unsigned dir_next
= 0;
170 isofs_dir_t
*isodir
= (isofs_dir_t
*) (block
+ dir_next
);
172 if (!isodir
->rec_len
)
175 //kprintf ("dir -> %d:%d:%d:%d:%d - %d - %d - %s\n", isodir->year+1900, isodir->month, isodir->day, isodir->hour, isodir->minute, isodir->rec_len, isodir->id_len, isodir->id);
176 /* clear name for prevent */
177 memset (dir
[entry
].name
, 0, 11);
179 /* there are directories and files */
181 unsigned p
= isodir
->id
[isodir
->id_len
] ? 0 : 1;
182 unsigned l
= isodir
->id_len
;
184 if (isodir
->id_len
> 10)
186 if (!(isodir
->flags
& ISOFS_DIR_FLAGS_DIR
))
188 if (isodir
->id
[l
-1] == '.')
191 memcpy (dir
[entry
].name
, isodir
->id
+isodir
->id_len
+10+p
, l
);
193 // "." and ".." directories are not correctly named in iso9660
197 memcpy (dir
[entry
].name
, ".", 1);
199 memcpy (dir
[entry
].name
, "..", 2);
203 if (isodir
->flags
& ISOFS_DIR_FLAGS_DIR
)
208 /*if (!isodir->id[isodir->id_len])
209 kprintf (": isodir->rec_len: %d | '%s' | 0x%x\n", isodir->rec_len, isodir->id+isodir->id_len+11, isodir->id[isodir->id_len]);
211 kprintf (":1 isodir->rec_len: %d | '%s' | 0x%x\n", isodir->rec_len, isodir->id+isodir->id_len+10, isodir->id[isodir->id_len]);*/
213 dir_next
+= isodir
->rec_len
;
217 /* for prevent clear last+1 entry of dir[] */
218 memset (dir
[entry
].name
, 0, 10);
223 isofs_dir_t
*isofs_dir_find (partition_t
*p
, char *block
, char *name
)
225 unsigned dir_next
= 0;
227 unsigned name_len
= strlen (name
);
230 isofs_dir_t
*isodir
= (isofs_dir_t
*) (block
+ dir_next
);
232 if (!isodir
->rec_len
)
235 if (!strncmp (name
, isodir
->id
, name_len
))
238 dir_next
+= isodir
->rec_len
;
245 unsigned isofs_path_gettable (partition_t
*p
)
247 char *block
= (char *) kmalloc (sizeof (char) * 2048);
252 unsigned path_prev
= 0;
253 unsigned path_num
= 0;
255 isofs_sector_read (p
, 20, (unsigned char *) block
);
258 isofs_path_t
*path
= (isofs_path_t
*) ((void *) block
+ path_prev
);
266 /* alloc and init context */
267 isofs_pathtbl_t
*table
= (isofs_pathtbl_t
*) kmalloc (sizeof (isofs_pathtbl_t
));
272 table
->name_len
= path
->name_len
;
273 table
->sect_num
= path
->sect_num
;
274 table
->sect_data
= path
->sect_data
;
275 table
->rec_num
= path
->rec_num
;
277 table
->name
= (unsigned char *) kmalloc (sizeof (unsigned char) * path
->name_len
);
282 memcpy (table
->name
, &path
->name
, path
->name_len
);
283 table
->name
[path
->name_len
] = '\0';
284 //kprintf ("dd: %s : %d\n", table->name, table->sect_data);
285 //memcpy (table->path, path, sizeof (isofs_path_t)+path->name_len);
288 table
->next
= &path_table_list
;
289 table
->prev
= path_table_list
.prev
;
290 table
->prev
->next
= table
;
291 table
->next
->prev
= table
;
293 path_prev
+= 8 + path
->name_len
;
296 if (block
[path_prev
+path
->name_len
])
307 unsigned isofs_cd_root (partition_t
*p
)
309 isofs_pathtbl_t
*path
;
310 for (path
= path_table_list
.next
; path
!= &path_table_list
; path
= path
->next
) {
311 /* we need find root dir (ussualy it is first in list) */
312 if (path
->name_len
== 1) {
313 char *block
= (char *) kmalloc (sizeof (char) * 2048);
318 path_prev
= path_curr
;
321 isofs_sector_read (p
, path
->sect_data
, block
);
323 isofs_dir_scan (p
, block
);
334 /* go to next directory placed in current directory */
335 unsigned isofs_cd (partition_t
*p
, unsigned char *name
)
337 isofs_pathtbl_t
*path
;
339 if (!strcmp (name
, "..")) {
342 char *block
= (char *) kmalloc (sizeof (char) * 2048);
347 path_prev
= path_curr
;
350 isofs_sector_read (p
, path
->sect_data
, block
);
352 isofs_dir_scan (p
, block
);
361 for (path
= path_table_list
.next
; path
!= &path_table_list
; path
= path
->next
) {
362 /* we need to find wanted dir */
363 if (!strncmp (path
->name
, name
, path
->name_len
)) {
364 char *block
= (char *) kmalloc (sizeof (char) * 2048);
369 path_prev
= path_curr
;
372 isofs_sector_read (p
, path
->sect_data
, block
);
374 isofs_dir_scan (p
, block
);
385 extern unsigned long file_cache_id
;
386 unsigned isofs_cat (partition_t
*p
, unsigned char *name
)
393 isofs_pathtbl_t
*path
= path_curr
;
395 char *block
= (char *) kmalloc (sizeof (char) * 2048);
400 isofs_sector_read (p
, path
->sect_data
, block
);
402 memcpy (n
, name
, 11);
406 isofs_dir_t
*isodir
= isofs_dir_find (p
, block
, n
);
413 if (isodir
->flags
& ISOFS_DIR_FLAGS_DIR
||
414 !isodir
->data_sec
[0] ||
415 !isodir
->data_len
[0]) {
420 /* NOTE: this is prevent before memory corruption (Max file length is ~47KB) */
421 /* if (isodir->data_len[0] > 47000) {
427 unsigned long len
= 0;
428 file_cache_id
= 2048;
432 //file_cache = (unsigned char *) krealloc ((void *) file_cache, file_cache_id+len);
437 isofs_sector_read (p
, isodir
->data_sec
[0]+i
, file_cache
+len
);
439 if ((len
+2048) > isodir
->data_len
[0])
446 file_cache_id
= isodir
->data_len
[0];
453 /* iso9660 filesystem initialization function */
454 unsigned isofs_init (partition_t
*p
)
456 isofs_volume_t
*volume
= (isofs_volume_t
*) kmalloc (sizeof (isofs_volume_t
));
461 isofs_sector_read (p
, ISOFS_SUPERBLOCK_SECTOR
, (unsigned char *) volume
);
464 //kprintf ("isofs -> %d, %d:%d:%s:%s:%d:%s:%s:%s:%d\n", sizeof (isofs_volume_t), volume->one, volume->zero, volume->sys_id, volume->vol_id, volume->sector_size[0], volume->pub_id, volume->root_dir_rec, volume->zeros, volume->seq_num[0]);
466 path_table_list
.next
= &path_table_list
;
467 path_table_list
.prev
= &path_table_list
;
469 isofs_path_gettable (p
);
474 /*char *block = (char *) kmalloc (sizeof (char) * 2048);
479 /*isofs_pathtbl_t *path;
480 for (path = path_table_list.next; path != &path_table_list; path = path->next) {
481 kprintf ("path - %s - %d\n", path->name, path->sect_data);
483 isofs_sector_read (p, path->sect_data, block);
485 isofs_dir_scan (p, block);
495 /* handler which is used by device management and pretty needed
496 for communication between zexos and this filesystem */
497 bool isofs_handler (unsigned act
, char *block
, unsigned n
, unsigned long l
)
502 return (bool) isofs_init ((partition_t
*) block
);
507 return (bool) isofs_cat (curr_part
, dir
[n
].name
);
518 return (bool) isofs_cd_root (curr_part
);
521 /* go to another directory */
522 return (bool) isofs_cd (curr_part
, dir
[n
].name
);