3 * Copyright (C) 2008 Tomas 'ZeXx86' Jedrzejek (zexx86@zexos.org)
4 * Copyright (C) 2009 Tomas 'ZeXx86' Jedrzejek (zexx86@zexos.org)
5 * Copyright (C) 2010 Tomas 'ZeXx86' Jedrzejek (zexx86@zexos.org)
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 3 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, see <http://www.gnu.org/licenses/>.
31 #include <partition.h>
35 #define ISOFS_SUPERBLOCK_SECTOR 16 // NOTE: sector is 2kB length
37 #define ISOFS_DIR_FLAGS_HIDDEN 0x1
38 #define ISOFS_DIR_FLAGS_DIR 0x2
40 #define __PACKED__ __attribute__ ((__packed__))
46 unsigned char sys_id
[32];
47 unsigned char vol_id
[32];
48 unsigned char zeros
[8];
49 unsigned long sectors
[2];
50 unsigned char zeros2
[32];
51 unsigned short set_size
[2];
52 unsigned short seq_num
[2];
53 unsigned short sector_size
[2];
54 unsigned long path_tbl
[2];
55 unsigned first_sec_fle_ptbl
;
56 unsigned first_sec_sle_ptbl
;
57 unsigned first_sec_fbe_ptbl
;
58 unsigned first_sec_sbe_ptbl
;
59 unsigned char root_dir_rec
[34]; // 158
60 unsigned char set_id
[128];
61 unsigned char pub_id
[128];
62 unsigned char datap_id
[128]; // 542
63 unsigned char app_id
[128];
64 unsigned char copy_id
[37];
65 unsigned char abst_id
[37];
66 unsigned char bibl_id
[37];
67 unsigned char date_volcr
[17];
68 unsigned char date_mod
[17];
69 unsigned char date_expir
[17];
70 unsigned char date_eff
[17];
73 unsigned char reserved
[512];
74 unsigned char zeros3
[653];
75 } __PACKED__ isofs_volume_t
; // 1395
78 unsigned char name_len
;
79 unsigned char sect_num
;
81 unsigned short rec_num
;
83 } __PACKED__ isofs_path_t
;
86 unsigned char rec_len
;
87 unsigned char sec_num
;
88 unsigned long data_sec
[2];
89 unsigned long data_len
[2];
96 unsigned char time_offset
;
98 unsigned char unit_size
;
99 unsigned char gap_size
;
100 unsigned short vol_seq_num
[2];
101 unsigned char id_len
;
102 unsigned char id
[32];
103 unsigned char id2
[50];
104 } __PACKED__ isofs_dir_t
;
106 typedef struct isofs_path_context
{
107 struct isofs_path_context
*next
, *prev
;
109 unsigned char name_len
;
110 unsigned char sect_num
;
112 unsigned short rec_num
;
116 isofs_pathtbl_t path_table_list
;
118 /* FIXME: limit for one mounted iso fs */
119 static isofs_pathtbl_t
*path_curr
;
120 static isofs_pathtbl_t
*path_prev
;
123 static unsigned char tolower (char c
)
125 return ((c
>= 'A' && c
<= 'Z') ? c
+ 32: c
);
128 static void toupper (char *str
)
132 for (i
= 0; str
[i
]; i
++ ) {
133 if (str
[i
] >= 'a' && str
[i
] <= 'z')
138 unsigned isofs_sector_read (partition_t
*p
, unsigned sector
, unsigned char *buffer
)
140 /* iso9660 sector is 2kB length */
141 unsigned address
= sector
* 4;
143 /* lba28_drive_read () read 512 bytes from drive 4 times +512 bytes */
144 lba28_drive_read (p
, address
, (unsigned char *) buffer
);
145 lba28_drive_read (p
, address
+1, (unsigned char *) buffer
+512);
146 lba28_drive_read (p
, address
+2, (unsigned char *) buffer
+1024);
147 lba28_drive_read (p
, address
+3, (unsigned char *) buffer
+1536);
152 isofs_pathtbl_t
*isofs_path_find (char *name
)
154 isofs_pathtbl_t
*path
;
155 for (path
= path_table_list
.next
; path
!= &path_table_list
; path
= path
->next
) {
156 if (!strcmp (path
->name
, name
))
163 unsigned isofs_dir_scan (partition_t
*p
, char *block
)
165 /*dir = (isofs_dir_t *) (block + dir->rec_len);
167 dir = (isofs_dir_t *) (block + dir->rec_len);*/
169 unsigned dir_next
= 0;
173 isofs_dir_t
*isodir
= (isofs_dir_t
*) (block
+ dir_next
);
175 if (!isodir
->rec_len
)
178 //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);
179 /* clear name for prevent */
180 memset (dir
[entry
].name
, 0, 11);
182 /* there are directories and files */
184 unsigned p
= isodir
->id
[isodir
->id_len
] ? 0 : 1;
185 unsigned l
= isodir
->id_len
;
187 if (isodir
->id_len
> 10)
189 if (!(isodir
->flags
& ISOFS_DIR_FLAGS_DIR
))
191 if (isodir
->id
[l
-1] == '.')
194 memcpy (dir
[entry
].name
, isodir
->id
+isodir
->id_len
+10+p
, l
);
196 // "." and ".." directories are not correctly named in iso9660
200 memcpy (dir
[entry
].name
, ".", 1);
202 memcpy (dir
[entry
].name
, "..", 2);
206 if (isodir
->flags
& ISOFS_DIR_FLAGS_DIR
)
211 /*if (!isodir->id[isodir->id_len])
212 kprintf (": isodir->rec_len: %d | '%s' | 0x%x\n", isodir->rec_len, isodir->id+isodir->id_len+11, isodir->id[isodir->id_len]);
214 kprintf (":1 isodir->rec_len: %d | '%s' | 0x%x\n", isodir->rec_len, isodir->id+isodir->id_len+10, isodir->id[isodir->id_len]);*/
216 dir_next
+= isodir
->rec_len
;
220 /* for prevent clear last+1 entry of dir[] */
221 memset (dir
[entry
].name
, 0, 10);
226 isofs_dir_t
*isofs_dir_find (partition_t
*p
, char *block
, char *name
)
228 unsigned dir_next
= 0;
230 unsigned name_len
= strlen (name
);
233 isofs_dir_t
*isodir
= (isofs_dir_t
*) (block
+ dir_next
);
235 if (!isodir
->rec_len
)
238 if (!strncmp (name
, isodir
->id
, name_len
))
241 dir_next
+= isodir
->rec_len
;
248 unsigned isofs_path_gettable (partition_t
*p
)
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
+1));
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
])
305 unsigned isofs_cd_root (partition_t
*p
)
307 isofs_pathtbl_t
*path
;
308 for (path
= path_table_list
.next
; path
!= &path_table_list
; path
= path
->next
) {
309 /* we need find root dir (ussualy it is first in list) */
310 if (path
->name_len
== 1) {
311 char *block
= (char *) kmalloc (sizeof (char) * 2049);
316 path_prev
= path_curr
;
319 isofs_sector_read (p
, path
->sect_data
, block
);
321 isofs_dir_scan (p
, block
);
332 /* go to next directory placed in current directory */
333 unsigned isofs_cd (partition_t
*p
, unsigned char *name
)
335 isofs_pathtbl_t
*path
;
337 if (!strcmp (name
, "..")) {
340 char *block
= (char *) kmalloc (sizeof (char) * 2049);
345 path_prev
= path_curr
;
348 isofs_sector_read (p
, path
->sect_data
, block
);
350 isofs_dir_scan (p
, block
);
359 for (path
= path_table_list
.next
; path
!= &path_table_list
; path
= path
->next
) {
360 /* we need to find wanted dir */
361 if (!strncmp (path
->name
, name
, path
->name_len
)) {
362 char *block
= (char *) kmalloc (sizeof (char) * 2049);
367 path_prev
= path_curr
;
370 isofs_sector_read (p
, path
->sect_data
, block
);
372 isofs_dir_scan (p
, block
);
383 unsigned isofs_cat (partition_t
*p
, unsigned char *name
, vfs_content_t
*content
)
390 isofs_pathtbl_t
*path
= path_curr
;
394 isofs_sector_read (p
, path
->sect_data
, block
);
396 memcpy (n
, name
, 11);
400 isofs_dir_t
*isodir
= isofs_dir_find (p
, block
, n
);
405 if (isodir
->flags
& ISOFS_DIR_FLAGS_DIR
||
406 !isodir
->data_sec
[0] ||
407 !isodir
->data_len
[0]) {
411 /* NOTE: this is prevent before memory corruption (Max file length is ~47KB) */
412 /* if (isodir->data_len[0] > 47000) {
418 cache_t
*cache
= cache_create (0, isodir
->data_len
[0], 1);
423 unsigned long len
= 0;
433 isofs_sector_read (p
, isodir
->data_sec
[0]+i
, data
);
435 if ((isodir
->data_len
[0] - len
) > 2048)
436 cache_add (data
, 2048);
438 cache_add (data
, isodir
->data_len
[0] - len
);
440 if ((len
+2048) > isodir
->data_len
[0])
447 content
->ptr
= (char *) &cache
->data
;
448 content
->len
= cache
->limit
;
453 /* iso9660 filesystem initialization function */
454 unsigned isofs_init (partition_t
*p
)
456 //isofs_volume_t volume;
458 //isofs_sector_read (p, ISOFS_SUPERBLOCK_SECTOR, (unsigned char *) &volume);
460 //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]);
462 path_table_list
.next
= &path_table_list
;
463 path_table_list
.prev
= &path_table_list
;
465 isofs_path_gettable (p
);
470 char *block
= (char *) kmalloc (sizeof (char) * 2048);
475 /*isofs_pathtbl_t *path;
476 for (path = path_table_list.next; path != &path_table_list; path = path->next) {
477 kprintf ("path - %s - %d\n", path->name, path->sect_data);
479 isofs_sector_read (p, path->sect_data, block);
481 isofs_dir_scan (p, block);
489 /* handler which is used by device management and pretty needed
490 for communication between zexos and this filesystem */
491 bool isofs_handler (unsigned act
, char *block
, unsigned n
, unsigned long l
)
496 return (bool) isofs_init ((partition_t
*) block
);
501 return (bool) isofs_cat (curr_part
, dir
[n
].name
, (vfs_content_t
*) block
);
512 return (bool) isofs_cd_root (curr_part
);
514 /* go to another directory */
515 return (bool) isofs_cd (curr_part
, dir
[n
].name
);