Fixed ZDE build - missing header file
[ZeXOS.git] / kernel / drivers / fs / isofs.c
blob2f39da8c64d6df7d0d10007370e263c7d705c25b
1 /*
2 * ZeX/OS
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/>.
22 #include <config.h>
23 #include <build.h>
25 #ifdef ARCH_i386
27 #include <system.h>
28 #include <string.h>
29 #include <dev.h>
30 #include <fs.h>
31 #include <partition.h>
32 #include <cache.h>
33 #include <vfs.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__))
42 typedef struct {
43 unsigned char one;
44 unsigned char dst[6];
45 unsigned char zero;
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];
71 unsigned char one2;
72 unsigned char zero2;
73 unsigned char reserved[512];
74 unsigned char zeros3[653];
75 } __PACKED__ isofs_volume_t; // 1395
77 typedef struct {
78 unsigned char name_len;
79 unsigned char sect_num;
80 unsigned sect_data;
81 unsigned short rec_num;
82 unsigned char name;
83 } __PACKED__ isofs_path_t;
85 typedef struct {
86 unsigned char rec_len;
87 unsigned char sec_num;
88 unsigned long data_sec[2];
89 unsigned long data_len[2];
90 unsigned char year;
91 unsigned char month;
92 unsigned char day;
93 unsigned char hour;
94 unsigned char minute;
95 unsigned char second;
96 unsigned char time_offset;
97 unsigned char flags;
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;
111 unsigned sect_data;
112 unsigned short rec_num;
113 unsigned char *name;
114 } isofs_pathtbl_t;
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)
130 unsigned i;
132 for (i = 0; str[i]; i ++ ) {
133 if (str[i] >= 'a' && str[i] <= 'z')
134 str[i] -= 32;
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);
149 return 1;
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))
157 return path;
160 return 0;
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;
170 unsigned entry = 0;
172 for (;;) {
173 isofs_dir_t *isodir = (isofs_dir_t *) (block + dir_next);
175 if (!isodir->rec_len)
176 break;
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 */
183 if (entry > 1) {
184 unsigned p = isodir->id[isodir->id_len] ? 0 : 1;
185 unsigned l = isodir->id_len;
187 if (isodir->id_len > 10)
188 l = 10;
189 if (!(isodir->flags & ISOFS_DIR_FLAGS_DIR))
190 l -= 2;
191 if (isodir->id[l-1] == '.')
192 l --;
194 memcpy (dir[entry].name, isodir->id+isodir->id_len+10+p, l);
195 } else {
196 // "." and ".." directories are not correctly named in iso9660
198 /* "." directory */
199 if (entry == 0)
200 memcpy (dir[entry].name, ".", 1);
201 if (entry == 1)
202 memcpy (dir[entry].name, "..", 2);
205 /* assign flags */
206 if (isodir->flags & ISOFS_DIR_FLAGS_DIR)
207 dir[entry].dir = 1;
208 else
209 dir[entry].dir = 0;
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]);
213 else
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;
217 entry ++;
220 /* for prevent clear last+1 entry of dir[] */
221 memset (dir[entry].name, 0, 10);
223 return 1;
226 isofs_dir_t *isofs_dir_find (partition_t *p, char *block, char *name)
228 unsigned dir_next = 0;
229 unsigned entry = 0;
230 unsigned name_len = strlen (name);
232 for (;;) {
233 isofs_dir_t *isodir = (isofs_dir_t *) (block + dir_next);
235 if (!isodir->rec_len)
236 break;
238 if (!strncmp (name, isodir->id, name_len))
239 return isodir;
241 dir_next += isodir->rec_len;
242 entry ++;
245 return 0;
248 unsigned isofs_path_gettable (partition_t *p)
250 char block[2049];
252 unsigned path_prev = 0;
253 unsigned path_num = 0;
255 isofs_sector_read (p, 20, (unsigned char *) block);
257 for (;;) {
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+1));
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 return 1;
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);
313 if (!block)
314 return 0;
316 path_prev = path_curr;
317 path_curr = path;
319 isofs_sector_read (p, path->sect_data, block);
321 isofs_dir_scan (p, block);
323 kfree (block);
325 return 1;
329 return 0;
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, "..")) {
338 path = path_prev;
340 char *block = (char *) kmalloc (sizeof (char) * 2049);
342 if (!block)
343 return 0;
345 path_prev = path_curr;
346 path_curr = path;
348 isofs_sector_read (p, path->sect_data, block);
350 isofs_dir_scan (p, block);
352 kfree (block);
354 return 1;
357 toupper (name);
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);
364 if (!block)
365 return 0;
367 path_prev = path_curr;
368 path_curr = path;
370 isofs_sector_read (p, path->sect_data, block);
372 isofs_dir_scan (p, block);
374 kfree (block);
376 return 1;
380 return 0;
383 unsigned isofs_cat (partition_t *p, unsigned char *name, vfs_content_t *content)
385 char n[12];
387 if (!path_curr)
388 return 0;
390 isofs_pathtbl_t *path = path_curr;
392 char block[2049];
394 isofs_sector_read (p, path->sect_data, block);
396 memcpy (n, name, 11);
398 toupper (n);
400 isofs_dir_t *isodir = isofs_dir_find (p, block, n);
402 if (!isodir)
403 return 0;
405 if (isodir->flags & ISOFS_DIR_FLAGS_DIR ||
406 !isodir->data_sec[0] ||
407 !isodir->data_len[0]) {
408 return 0;
411 /* NOTE: this is prevent before memory corruption (Max file length is ~47KB) */
412 /* if (isodir->data_len[0] > 47000) {
413 kfree (block);
414 file_cache_id = 0;
415 return 0;
418 cache_t *cache = cache_create (0, isodir->data_len[0], 1);
420 if (!cache)
421 return 0;
423 unsigned long len = 0;
425 unsigned i = 0;
427 char data[2049];
429 //if (!data)
430 // return 0;
432 for (;;) {
433 isofs_sector_read (p, isodir->data_sec[0]+i, data);
435 if ((isodir->data_len[0] - len) > 2048)
436 cache_add (data, 2048);
437 else
438 cache_add (data, isodir->data_len[0] - len);
440 if ((len+2048) > isodir->data_len[0])
441 break;
443 len += 2048;
444 i ++;
447 content->ptr = (char *) &cache->data;
448 content->len = cache->limit;
450 return 1;
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);
467 path_curr = 0;
468 path_prev = 0;
470 char *block = (char *) kmalloc (sizeof (char) * 2048);
472 if (!block)
473 return 0;
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);
484 //timer_wait (1000);
486 return 1;
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)
493 switch (act) {
494 case FS_ACT_INIT:
496 return (bool) isofs_init ((partition_t *) block);
498 break;
499 case FS_ACT_READ:
501 return (bool) isofs_cat (curr_part, dir[n].name, (vfs_content_t *) block);
503 break;
504 case FS_ACT_WRITE:
506 return 0;
508 break;
509 case FS_ACT_CHDIR:
511 if (n == -1)
512 return (bool) isofs_cd_root (curr_part);
514 /* go to another directory */
515 return (bool) isofs_cd (curr_part, dir[n].name);
517 break;
518 case FS_ACT_MKDIR:
520 return 0;
522 break;
523 case FS_ACT_TOUCH:
525 return 0;
527 break;
528 case FS_ACT_EXIT:
530 /* TODO */
532 return 0;
534 break;
537 return 0;
539 #endif