All user-space apps ware moved to 8MB virtual address address (link.ld changes);...
[ZeXOS.git] / kernel / drivers / fs / isofs.c
blob46de7359dfcda492c0f3f518d69a789a3f55dadc
1 /*
2 * ZeX/OS
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/>.
21 #include <config.h>
22 #include <build.h>
24 #ifdef ARCH_i386
26 #include <system.h>
27 #include <string.h>
28 #include <dev.h>
29 #include <fs.h>
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__))
39 typedef struct {
40 unsigned char one;
41 unsigned char dst[6];
42 unsigned char zero;
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];
68 unsigned char one2;
69 unsigned char zero2;
70 unsigned char reserved[512];
71 unsigned char zeros3[653];
72 } __PACKED__ isofs_volume_t; // 1395
74 typedef struct {
75 unsigned char name_len;
76 unsigned char sect_num;
77 unsigned sect_data;
78 unsigned short rec_num;
79 unsigned char name;
80 } __PACKED__ isofs_path_t;
82 typedef struct {
83 unsigned char rec_len;
84 unsigned char sec_num;
85 unsigned long data_sec[2];
86 unsigned long data_len[2];
87 unsigned char year;
88 unsigned char month;
89 unsigned char day;
90 unsigned char hour;
91 unsigned char minute;
92 unsigned char second;
93 unsigned char time_offset;
94 unsigned char flags;
95 unsigned char unit_size;
96 unsigned char gap_size;
97 unsigned short vol_seq_num[2];
98 unsigned char id_len;
99 unsigned char id[32];
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;
108 unsigned sect_data;
109 unsigned short rec_num;
110 unsigned char *name;
111 } isofs_pathtbl_t;
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)
127 unsigned i;
129 for (i = 0; str[i]; i ++ ) {
130 if (str[i] >= 'a' && str[i] <= 'z')
131 str[i] -= 32;
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);
146 return 1;
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))
154 return path;
157 return 0;
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;
167 unsigned entry = 0;
169 while (1) {
170 isofs_dir_t *isodir = (isofs_dir_t *) (block + dir_next);
172 if (!isodir->rec_len)
173 break;
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 */
180 if (entry > 1) {
181 unsigned p = isodir->id[isodir->id_len] ? 0 : 1;
182 unsigned l = isodir->id_len;
184 if (isodir->id_len > 10)
185 l = 10;
186 if (!(isodir->flags & ISOFS_DIR_FLAGS_DIR))
187 l -= 2;
188 if (isodir->id[l-1] == '.')
189 l --;
191 memcpy (dir[entry].name, isodir->id+isodir->id_len+10+p, l);
192 } else {
193 // "." and ".." directories are not correctly named in iso9660
195 /* "." directory */
196 if (entry == 0)
197 memcpy (dir[entry].name, ".", 1);
198 if (entry == 1)
199 memcpy (dir[entry].name, "..", 2);
202 /* assign flags */
203 if (isodir->flags & ISOFS_DIR_FLAGS_DIR)
204 dir[entry].dir = 1;
205 else
206 dir[entry].dir = 0;
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]);
210 else
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;
214 entry ++;
217 /* for prevent clear last+1 entry of dir[] */
218 memset (dir[entry].name, 0, 10);
220 return 1;
223 isofs_dir_t *isofs_dir_find (partition_t *p, char *block, char *name)
225 unsigned dir_next = 0;
226 unsigned entry = 0;
227 unsigned name_len = strlen (name);
229 while (1) {
230 isofs_dir_t *isodir = (isofs_dir_t *) (block + dir_next);
232 if (!isodir->rec_len)
233 break;
235 if (!strncmp (name, isodir->id, name_len))
236 return isodir;
238 dir_next += isodir->rec_len;
239 entry ++;
242 return 0;
245 unsigned isofs_path_gettable (partition_t *p)
247 char *block = (char *) kmalloc (sizeof (char) * 2048);
249 if (!block)
250 return 0;
252 unsigned path_prev = 0;
253 unsigned path_num = 0;
255 isofs_sector_read (p, 20, (unsigned char *) block);
257 while (1) {
258 isofs_path_t *path = (isofs_path_t *) ((void *) block + path_prev);
260 if (!path)
261 return 0;
263 if (!path->name_len)
264 break;
266 /* alloc and init context */
267 isofs_pathtbl_t *table = (isofs_pathtbl_t *) kmalloc (sizeof (isofs_pathtbl_t));
269 if (!table)
270 return 0;
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);
279 if (!table->name)
280 return 0;
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);
287 /* add into list */
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;
295 /* padding */
296 if (block[path_prev+path->name_len])
297 path_prev ++;
299 path_num ++;
302 kfree (block);
304 return 1;
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);
315 if (!block)
316 return 0;
318 path_prev = path_curr;
319 path_curr = path;
321 isofs_sector_read (p, path->sect_data, block);
323 isofs_dir_scan (p, block);
325 kfree (block);
327 return 1;
331 return 0;
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, "..")) {
340 path = path_prev;
342 char *block = (char *) kmalloc (sizeof (char) * 2048);
344 if (!block)
345 return 0;
347 path_prev = path_curr;
348 path_curr = path;
350 isofs_sector_read (p, path->sect_data, block);
352 isofs_dir_scan (p, block);
354 kfree (block);
356 return 1;
359 toupper (name);
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);
366 if (!block)
367 return 0;
369 path_prev = path_curr;
370 path_curr = path;
372 isofs_sector_read (p, path->sect_data, block);
374 isofs_dir_scan (p, block);
376 kfree (block);
378 return 1;
382 return 0;
385 extern unsigned long file_cache_id;
386 unsigned isofs_cat (partition_t *p, unsigned char *name)
388 char n[12];
390 if (!path_curr)
391 return 0;
393 isofs_pathtbl_t *path = path_curr;
395 char *block = (char *) kmalloc (sizeof (char) * 2048);
397 if (!block)
398 return 0;
400 isofs_sector_read (p, path->sect_data, block);
402 memcpy (n, name, 11);
404 toupper (n);
406 isofs_dir_t *isodir = isofs_dir_find (p, block, n);
408 if (!isodir) {
409 kfree (block);
410 return 0;
413 if (isodir->flags & ISOFS_DIR_FLAGS_DIR ||
414 !isodir->data_sec[0] ||
415 !isodir->data_len[0]) {
416 kfree (block);
417 return 0;
420 /* NOTE: this is prevent before memory corruption (Max file length is ~47KB) */
421 /* if (isodir->data_len[0] > 47000) {
422 kfree (block);
423 file_cache_id = 0;
424 return 0;
427 unsigned long len = 0;
428 file_cache_id = 2048;
429 unsigned i = 0;
431 while (1) {
432 //file_cache = (unsigned char *) krealloc ((void *) file_cache, file_cache_id+len);
434 //if (!file_cache)
435 // return 0;
437 isofs_sector_read (p, isodir->data_sec[0]+i, file_cache+len);
439 if ((len+2048) > isodir->data_len[0])
440 break;
442 len += 2048;
443 i ++;
446 file_cache_id = isodir->data_len[0];
448 kfree (block);
450 return 1;
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));
458 if (!volume)
459 return 0;
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);
471 path_curr = 0;
472 path_prev = 0;
474 /*char *block = (char *) kmalloc (sizeof (char) * 2048);
476 if (!block)
477 return 0;*/
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);
488 //timer_wait (1000);
490 kfree (volume);
492 return 1;
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)
499 switch (act) {
500 case FS_ACT_INIT:
502 return (bool) isofs_init ((partition_t *) block);
504 break;
505 case FS_ACT_READ:
507 return (bool) isofs_cat (curr_part, dir[n].name);
509 break;
510 case FS_ACT_WRITE:
512 return 0;
514 break;
515 case FS_ACT_CHDIR:
517 if (n == -1) {
518 return (bool) isofs_cd_root (curr_part);
521 /* go to another directory */
522 return (bool) isofs_cd (curr_part, dir[n].name);
524 break;
525 case FS_ACT_MKDIR:
527 return 0;
529 break;
530 case FS_ACT_TOUCH:
532 return 0;
534 break;
535 case FS_ACT_EXIT:
537 /* TODO */
539 return 0;
541 break;
544 return 0;
546 #endif