ZeXFS filesystem was completely rewritten, brings stability, great recoverable space...
[ZeXOS.git] / kernel / drivers / fs / isofs.c
blobd19f261bce6706846942f4c293703b601fa9eab3
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 } __PACKED__ isofs_dir_t;
102 typedef struct isofs_path_context {
103 struct isofs_path_context *next, *prev;
105 unsigned char name_len;
106 unsigned char sect_num;
107 unsigned sect_data;
108 unsigned short rec_num;
109 unsigned char *name;
110 } isofs_pathtbl_t;
112 isofs_pathtbl_t path_table_list;
114 /* FIXME: limit for one mounted iso fs */
115 static isofs_pathtbl_t *path_curr;
116 static isofs_pathtbl_t *path_prev;
118 unsigned isofs_sector_read (partition_t *p, unsigned sector, unsigned char *buffer)
120 /* iso9660 sector is 2kB length */
121 unsigned address = sector * 4;
123 /* lba28_drive_read () read 512 bytes from drive 4 times +512 bytes */
124 lba28_drive_read (p, address, (unsigned char *) buffer);
125 lba28_drive_read (p, address+1, (unsigned char *) buffer+512);
126 lba28_drive_read (p, address+2, (unsigned char *) buffer+1024);
127 lba28_drive_read (p, address+3, (unsigned char *) buffer+1536);
129 return 1;
132 isofs_pathtbl_t *isofs_path_find (char *name)
134 isofs_pathtbl_t *path;
135 for (path = path_table_list.next; path != &path_table_list; path = path->next) {
136 if (!strcmp (path->name, name))
137 return path;
140 return 0;
143 unsigned isofs_dir_scan (partition_t *p, char *block)
145 /*dir = (isofs_dir_t *) (block + dir->rec_len);
147 dir = (isofs_dir_t *) (block + dir->rec_len);*/
149 unsigned dir_next = 0;
150 unsigned entry = 0;
152 while (1) {
153 isofs_dir_t *isodir = (isofs_dir_t *) (block + dir_next);
155 if (!isodir->rec_len)
156 break;
158 //kprintf ("dir -> %d:%d:%d:%d:%d - %d - %d - %s\n", dir->year+1900, dir->month, dir->day, dir->hour, dir->minute, dir->rec_len, dir->id_len, dir->id);
159 /* clear name for prevent */
160 memset (dir[entry].name, 0, 10);
162 /* there are directories and files */
163 if (entry > 1) {
164 if (isodir->id_len > 9)
165 memcpy (dir[entry].name, isodir->id, 9);
166 else {
167 if (isodir->flags & ISOFS_DIR_FLAGS_DIR)
168 memcpy (dir[entry].name, isodir->id, isodir->id_len);
169 else
170 memcpy (dir[entry].name, isodir->id, isodir->id_len-2);
172 } else {
173 // "." and ".." directories are not correctly named in iso9660
175 /* "." directory */
176 if (entry == 0)
177 memcpy (dir[entry].name, ".", 1);
178 if (entry == 1)
179 memcpy (dir[entry].name, "..", 2);
182 /* assign flags */
183 if (isodir->flags & ISOFS_DIR_FLAGS_DIR)
184 dir[entry].dir = 1;
185 else
186 dir[entry].dir = 0;
188 dir_next += isodir->rec_len;
189 entry ++;
192 /* for prevent clear last+1 entry of dir[] */
193 memset (dir[entry].name, 0, 10);
195 return 1;
198 isofs_dir_t *isofs_dir_find (partition_t *p, char *block, char *name)
200 unsigned dir_next = 0;
201 unsigned entry = 0;
202 unsigned name_len = strlen (name);
204 while (1) {
205 isofs_dir_t *isodir = (isofs_dir_t *) (block + dir_next);
207 if (!isodir->rec_len)
208 break;
210 if (!strncmp (name, isodir->id, name_len))
211 return isodir;
213 dir_next += isodir->rec_len;
214 entry ++;
217 return 0;
220 unsigned isofs_path_gettable (partition_t *p)
222 char *block = (char *) kmalloc (sizeof (char) * 2048);
224 if (!block)
225 return 0;
227 unsigned path_prev = 0;
228 unsigned path_num = 0;
230 isofs_sector_read (p, 19, (unsigned char *) block);
232 while (1) {
233 isofs_path_t *path = (isofs_path_t *) (block + path_prev);
235 if (!path)
236 return 0;
238 if (!path->name_len)
239 break;
241 /* alloc and init context */
242 isofs_pathtbl_t *table = (isofs_pathtbl_t *) kmalloc (sizeof (isofs_pathtbl_t));
244 if (!table)
245 return 0;
247 table->name_len = path->name_len;
248 table->sect_num = path->sect_num;
249 table->sect_data = path->sect_data;
250 table->rec_num = path->rec_num;
252 table->name = (unsigned char *) kmalloc (sizeof (unsigned char) * path->name_len);
254 if (!table->name)
255 return 0;
257 memcpy (table->name, &path->name, path->name_len);
258 kprintf ("dd: %s\n", table->name);
259 //memcpy (table->path, path, sizeof (isofs_path_t)+path->name_len);
261 /* add into list */
262 table->next = &path_table_list;
263 table->prev = path_table_list.prev;
264 table->prev->next = table;
265 table->next->prev = table;
267 path_prev += 9 + path->name_len;
269 /* padding */
270 if (!block[path_prev+path->name_len+1])
271 path_prev ++;
273 path_num ++;
276 kfree (block);
278 return 1;
281 unsigned isofs_cd_root (partition_t *p)
283 isofs_pathtbl_t *path;
284 for (path = path_table_list.next; path != &path_table_list; path = path->next) {
285 /* we need find root dir (ussualy it is first in list) */
286 if (path->name_len == 1) {
287 char *block = (char *) kmalloc (sizeof (char) * 2048);
289 if (!block)
290 return 0;
292 path_prev = path_curr;
293 path_curr = path;
295 isofs_sector_read (p, path->sect_data, block);
297 isofs_dir_scan (p, block);
299 kfree (block);
301 return 1;
305 return 0;
308 /* go to next directory placed in current directory */
309 unsigned isofs_cd (partition_t *p, unsigned char *name)
311 isofs_pathtbl_t *path;
313 if (!strcmp (name, "..")) {
314 path = path_prev;
316 char *block = (char *) kmalloc (sizeof (char) * 2048);
318 if (!block)
319 return 0;
321 path_prev = path_curr;
322 path_curr = path;
324 isofs_sector_read (p, path->sect_data, block);
326 isofs_dir_scan (p, block);
328 kfree (block);
330 return 0;
333 for (path = path_table_list.next; path != &path_table_list; path = path->next) {
334 /* we need to find wanted dir */
335 if (!strncmp (path->name, name, path->name_len)) {
336 char *block = (char *) kmalloc (sizeof (char) * 2048);
338 if (!block)
339 return 0;
341 path_prev = path_curr;
342 path_curr = path;
344 isofs_sector_read (p, path->sect_data, block);
346 isofs_dir_scan (p, block);
348 kfree (block);
350 return 1;
354 return 0;
357 extern unsigned long file_cache_id;
358 unsigned isofs_cat (partition_t *p, unsigned char *name)
360 if (!path_curr)
361 return 0;
363 isofs_pathtbl_t *path = path_curr;
365 char *block = (char *) kmalloc (sizeof (char) * 2048);
367 if (!block)
368 return 0;
370 isofs_sector_read (p, path->sect_data, block);
372 isofs_dir_t *isodir = isofs_dir_find (p, block, name);
374 if (!isodir) {
375 kfree (block);
376 return 0;
379 if (isodir->flags & ISOFS_DIR_FLAGS_DIR ||
380 !isodir->data_sec[0] ||
381 !isodir->data_len[0]) {
382 kfree (block);
383 return 0;
386 unsigned long len = 0;
387 file_cache_id = 2048;
388 unsigned i = 0;
390 while (1) {
391 //file_cache = (unsigned char *) krealloc ((void *) file_cache, file_cache_id+len);
393 //if (!file_cache)
394 // return 0;
396 isofs_sector_read (p, isodir->data_sec[0]+i, file_cache+len);
398 if ((len+2048) > isodir->data_len[0])
399 break;
401 len += 2048;
402 i ++;
405 file_cache_id = isodir->data_len[0];
407 kfree (block);
409 return 1;
412 /* iso9660 filesystem initialization function */
413 unsigned isofs_init (partition_t *p)
415 isofs_volume_t *volume = (isofs_volume_t *) kmalloc (sizeof (isofs_volume_t));
417 if (!volume)
418 return 0;
420 isofs_sector_read (p, ISOFS_SUPERBLOCK_SECTOR, (unsigned char *) volume);
423 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]);
425 path_table_list.next = &path_table_list;
426 path_table_list.prev = &path_table_list;
428 isofs_path_gettable (p);
430 path_curr = 0;
431 path_prev = 0;
433 /*char *block = (char *) kmalloc (sizeof (char) * 2048);
435 if (!block)
436 return 0;*/
438 /*isofs_pathtbl_t *path;
439 for (path = path_table_list.next; path != &path_table_list; path = path->next) {
440 kprintf ("path - %s - %d\n", path->name, path->sect_data);
442 isofs_sector_read (p, path->sect_data, block);
444 isofs_dir_scan (p, block);
447 //timer_wait (1000);
449 kfree (volume);
451 return 1;
454 /* handler which is used by device management and pretty needed
455 for communication between zexos and this filesystem */
456 bool isofs_handler (unsigned act, char *block, unsigned n, unsigned long l)
458 switch (act) {
459 case FS_ACT_INIT:
461 return 1;
463 break;
464 case FS_ACT_READ:
466 isofs_cat (curr_part, dir[n].name);
468 return 1;
470 break;
471 case FS_ACT_WRITE:
474 return 0;
476 break;
477 case FS_ACT_CHDIR:
479 if (n == -1) {
480 isofs_cd_root (curr_part);
481 return 1;
484 /* go to another directory */
485 isofs_cd (curr_part, dir[n].name);
487 break;
488 case FS_ACT_MKDIR:
491 return 0;
493 break;
494 case FS_ACT_TOUCH:
497 return 0;
501 return 0;
503 #endif