App inst fixed on invalid image file; App zinstall for ZDE works - we've got GUI...
[ZeXOS.git] / kernel / drivers / fs / ext2.c
blob73bab19f87ae8fac260766bb79388104bd214280
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 <arch/io.h>
29 #include <string.h>
30 #include <dev.h>
31 #include <fs.h>
32 #include <partition.h>
33 #include <cache.h>
34 #include <vfs.h>
36 #define EXT2_MAGIC 0xEF53 // magic number for ext2 filesystem
38 #define EXT2_SUPERBLOCK_SECTOR 1 // sector, where is placed superblock
40 #define EXT2_GOOD_OLD_REV 0 // original format
41 #define EXT2_DYNAMIC_REV 1 // V2 format with dynamic inode sizes
43 #define EXT2_BAD_INO 0x01 // bad blocks inode
44 #define EXT2_ROOT_INO 0x02 // root directory inode
45 #define EXT2_ACL_IDX_INO 0x03 // ACL index inode (deprecated?)
46 #define EXT2_ACL_DATA_INO 0x04 // ACL data inode (deprecated?)
47 #define EXT2_BOOT_LOADER_INO 0x05 // boot loader inode
48 #define EXT2_UNDEL_DIR_INO 0x06 // undelete directory inode
50 #define EXT2_S_IFMT 0xF000 // format mask
51 #define EXT2_S_IFSOCK 0xC000 // socket
52 #define EXT2_S_IFLNK 0xA000 // symbolic link
53 #define EXT2_S_IFREG 0x8000 // regular file
54 #define EXT2_S_IFBLK 0x6000 // block device
55 #define EXT2_S_IFDIR 0x4000 // directory
56 #define EXT2_S_IFCHR 0x2000 // character device
57 #define EXT2_S_IFIFO 0x1000 // fifo
59 #define EXT2_S_ISUID 0x0800 // SUID
60 #define EXT2_S_ISGID 0x0400 // SGID
61 #define EXT2_S_ISVTX 0x0200 // sticky bit
62 #define EXT2_S_IRWXU 0x01C0 // user access rights mask
63 #define EXT2_S_IRUSR 0x0100 // read
64 #define EXT2_S_IWUSR 0x0080 // write
65 #define EXT2_S_IXUSR 0x0040 // execute
66 #define EXT2_S_IRWXG 0x0038 // group access rights mask
67 #define EXT2_S_IRGRP 0x0020 // read
68 #define EXT2_S_IWGRP 0x0010 // write
69 #define EXT2_S_IXGRP 0x0008 // execute
70 #define EXT2_S_IRWXO 0x0007 // others access rights mask
71 #define EXT2_S_IROTH 0x0004 // read
72 #define EXT2_S_IWOTH 0x0002 // write
73 #define EXT2_S_IXOTH 0x0001 // execute
75 #define EXT2_FT_UNKNOWN 0
76 #define EXT2_FT_REG_FILE 1
77 #define EXT2_FT_DIR 2
78 #define EXT2_FT_CHRDEV 3
79 #define EXT2_FT_BLKDEV 4
80 #define EXT2_FT_FIFO 5
81 #define EXT2_FT_SOCK 6
82 #define EXT2_FT_SYMLINK 7
83 #define EXT2_FT_MAX 8
85 typedef struct {
86 unsigned inodecount;
87 unsigned blockcount;
88 unsigned r_blockcount;
89 unsigned free_blockcount;
90 unsigned free_inodecount;
91 unsigned first_data_block;
92 unsigned log_block_size;
93 unsigned log_frag_size;
94 unsigned blocks_per_group;
95 unsigned frags_per_group;
96 unsigned inodes_per_group;
97 unsigned mtime;
98 unsigned wtime;
99 unsigned short mnt_count;
100 unsigned short max_mnt_count;
101 unsigned short magic;
102 unsigned short state;
103 unsigned short errors;
104 unsigned short minor_rev_level;
105 unsigned lastcheck;
106 unsigned checkinterval;
107 unsigned creator_os;
108 unsigned rev_level;
109 unsigned short def_resuid;
110 unsigned short def_resgid;
111 // -- EXT2_DYNAMIC_REV Specific --
112 unsigned first_ino;
113 unsigned short inode_size;
114 unsigned short block_group_nr;
115 unsigned feature_compat;
116 unsigned feature_incompat;
117 unsigned feature_ro_compat;
118 unsigned char uuid[16];
119 unsigned char volume_name[16];
120 unsigned char last_mounted[64];
121 unsigned algo_bitmap;
122 // -- Performance Hints --
123 unsigned char prealloc_blocks;
124 unsigned char prealloc_dir_blocks;
125 unsigned short alignment;
126 // -- Journaling Support --
127 unsigned char journal_uuid[16];
128 unsigned journal_inum;
129 unsigned journal_dev;
130 unsigned last_orphan;
131 // -- Unused --
132 unsigned char padding[788];
133 } ext2_superblock_t;
135 typedef struct {
136 unsigned block_bitmap;
137 unsigned inode_bitmap;
138 unsigned inode_table;
139 unsigned short free_blocks_count;
140 unsigned short free_inodes_count;
141 unsigned short used_dirs_count;
142 unsigned short pad;
143 unsigned char reserved[12];
144 } ext2_group_t;
146 typedef struct {
147 unsigned short mode;
148 unsigned short uid;
149 unsigned size;
150 unsigned atime;
151 unsigned ctime;
152 unsigned mtime;
153 unsigned dtime;
154 unsigned short gid;
155 unsigned short links_count;
156 unsigned blocks;
157 unsigned flags;
158 unsigned osd1;
159 unsigned block[15];
160 unsigned generation;
161 unsigned file_acl;
162 unsigned dir_acl;
163 unsigned faddr;
164 unsigned char osd2[12];
165 } ext2_inode_t;
167 typedef struct {
168 unsigned inode;
169 unsigned short rec_len;
170 unsigned char name_len;
171 unsigned char file_type;
172 unsigned char name[255];
173 } ext2_dir_t;
175 static unsigned block_size = 0;
176 static unsigned block_free = 0;
177 static unsigned inode_curr = 0;
179 ext2_superblock_t *superblock;
181 unsigned ext2_sector_read (partition_t *p, unsigned sector, unsigned char *buffer)
183 /* ext2 sector is 1kB length */
184 unsigned address = sector * 2;
186 /* lba28_drive_read () read 512 bytes from drive 2 times +512 bytes */
187 lba28_drive_read (p, address+p->sector_start, (unsigned char *) buffer);
188 lba28_drive_read (p, address+p->sector_start+1, (unsigned char *) buffer+512);
190 return 1;
193 unsigned ext2_sector_write (partition_t *p, unsigned sector, unsigned char *buffer)
195 /* ext2 sector is 1kB length */
196 unsigned address = sector * 2;
198 /* lba28_drive_write () write 512 bytes to drive 2 times +512 bytes */
199 lba28_drive_write (p, address+p->sector_start, (unsigned char *) buffer);
200 lba28_drive_write (p, address+p->sector_start+1, (unsigned char *) buffer+512);
202 return 1;
205 extern unsigned long file_cache_id;
206 /* read data block of file by inode */
207 unsigned ext2_block_read (partition_t *p, ext2_inode_t *inode, vfs_content_t *content)
209 unsigned address = inode->block[0] * 2 + p->sector_start;
210 unsigned long len = 0;
211 unsigned i = 0;
213 DPRINT (DBG_DRIVER | DBG_FS, "blocks: %d %d %d %d %d %d %d %d %d %d", inode->block[0], inode->block[1], inode->block[2], inode->block[3], inode->block[4], inode->block[5], inode->block[6], inode->block[12], inode->block[13], inode->block[14]);
214 //timer_wait (1000);
215 char *block = (char *) kmalloc (1024);
217 unsigned block_new[15];
218 /* indirect block */
219 if (inode->block[12]) {
220 ext2_sector_read (p, inode->block[12], block);
222 memcpy (&block_new, block, sizeof (unsigned) * 15);
225 cache_t *cache = cache_create (0, inode->size, 1);
227 if (!cache)
228 return 0;
230 for (;;) {
231 /* first 12 address are direct and next are from indirect block */
232 if (i < 12)
233 address = inode->block[i];
234 else
235 address = block_new[i-12];
237 if (!address)
238 break;
240 /* read 1024 bytes block and put data to file_cache */
241 ext2_sector_read (p, address, (unsigned char *) block);
243 /*unsigned x = 0;
244 while (x < 1024) {
245 putch (block[x]);
246 x ++;
249 if ((inode->size - len) > 1024)
250 cache_add (block, 1024);
251 else
252 cache_add (block, inode->size - len);
254 if ((len+1024) > inode->size)
255 break;
257 len += 1024;
258 i ++;
261 kfree (block);
263 content->ptr = (char *) &cache->data;
264 content->len = cache->limit;
266 return 1;
269 /* write data block of file by inode */
270 unsigned ext2_block_write (partition_t *p, ext2_inode_t *inode)
272 /* when it is new file, lets assign free data block */
273 if (!inode->block[0])
274 inode->block[0] = 10000;
276 /* REWRITE */
277 unsigned address = inode->block[0] * 2 + p->sector_start;
278 unsigned long len = 0;
279 unsigned i = 0;
281 cache_t *cache = cache_read ();
283 if (!cache) {
284 printf ("ext2 -> nothing to write\n");
285 return 0;
288 for (;;) {
289 /* write 512 bytes block from file_cache */
290 lba28_drive_write (p, address+i, &cache->data+len);
292 if ((len+512) > cache->limit)
293 break;
295 len += 512;
296 i ++;
299 inode->size = cache->limit;
301 return 1;
304 /* return inode structure by inode id number */
305 ext2_inode_t *ext2_inode_read (partition_t *p, char *block, unsigned id)
307 /* group descriptors */
308 char buf[1024];
309 ext2_group_t *group = (ext2_group_t *) &buf;//kmalloc (1024);
311 if (!group)
312 return 0;
314 ext2_sector_read (p, 2, (unsigned char *) group);
316 /* locate inode group and structure */
317 unsigned group_num = (id - 1) / superblock->inodes_per_group;
318 unsigned id_new = (id - 1) % superblock->inodes_per_group;
320 ext2_sector_read (p, group[group_num].inode_table, (unsigned char *) block);
322 ext2_inode_t *inode = (ext2_inode_t *) block;
324 DPRINT (DBG_DRIVER | DBG_FS, "inode -> %d / %d - 0x%x - %d - %d - %d", superblock->inodes_per_group, id_new, inode[id_new].mode, inode[id_new].ctime, inode[id_new].size, inode[id_new].block[0]);
326 //kfree (group);
328 return &inode[id_new];
331 /* write inode structure by inode id number */
332 unsigned ext2_inode_write (partition_t *p, ext2_inode_t *inode, unsigned id)
334 /* group descriptors */
335 ext2_group_t *group = (ext2_group_t *) kmalloc (1024);
337 if (!group)
338 return 0;
340 ext2_sector_read (p, 2, (unsigned char *) group);
342 /* locate inode group and structure */
343 unsigned group_num = (id - 1) / superblock->inodes_per_group;
344 unsigned id_new = (id - 1) % superblock->inodes_per_group;
346 ext2_inode_t *block = (ext2_inode_t *) kmalloc (1024);
348 if (!block) {
349 kfree (group);
350 return 0;
353 ext2_sector_read (p, group[group_num].inode_table, (unsigned char *) block);
355 memcpy (&block[id_new], inode, sizeof (ext2_inode_t));
357 ext2_sector_write (p, group[group_num].inode_table, (unsigned char *) block);
359 //DPRINT (DBG_DRIVER | DBG_FS, "inode -> %d / %d - 0x%x - %d - %d - %d", superblock->inodes_per_group, id_new, inode[id_new].mode, inode[id_new].ctime, inode[id_new].size, inode[id_new].block[0]);
361 kfree (block);
362 kfree (group);
364 return 1;
367 /* scan current directory and assign to dir[] structure */
368 unsigned ext2_dir_scan (partition_t *p, ext2_inode_t *inode)
370 char buf[1024];
371 ext2_dir_t *ext2dir = (ext2_dir_t *) &buf;//kmalloc (1024);
373 if (!ext2dir)
374 return 0;
376 /* read direct block */
377 ext2_sector_read (p, inode->block[0], (unsigned char *) ext2dir);
379 unsigned dir_next = 0;
380 unsigned entry = 0;
382 for (;;) {
383 ext2_dir_t *dir_new = (ext2_dir_t *) ((void *) ext2dir + dir_next);
385 DPRINT (DBG_DRIVER | DBG_FS, "dir -> 0x%x : %d - %d - %d - %s - %d", dir_new, dir_new->inode, dir_new->rec_len, dir_new->name_len, dir_new->name, dir_new->file_type);
387 if (!dir_new->rec_len || !dir_new->inode || dir_next >= 1024)
388 break;
390 /* we won't unknown file type */
391 if (dir_new->file_type == EXT2_FT_UNKNOWN) {
392 dir_next += dir_new->rec_len;
393 continue;
396 /* yeah :( .. limit to 10 characters for dir[] entry */
397 if (dir_new->name_len < 10) {
398 memcpy (dir[entry].name, dir_new->name, dir_new->name_len);
399 dir[entry].name[dir_new->name_len] = '\0';
400 } else {
401 memcpy (dir[entry].name, dir_new->name, 9);
402 dir[entry].name[9] = '\0';
405 /* check for directory type or file */
406 if (dir_new->file_type == EXT2_FT_DIR)
407 dir[entry].dir = 1;
408 else
409 dir[entry].dir = 0;
411 /* increase dir_next with current record length for find next ext2_dir_t * structure */
412 dir_next += dir_new->rec_len;
413 /* increase dir[] entry */
414 entry ++;
417 //kfree (ext2dir);
419 /* clear last+1 entry of dir[] for prevent */
420 memset (dir[entry].name, 0, 10);
422 return 1;
425 unsigned ext2_create_entity (partition_t *p, char *name, unsigned char type)
427 if (!name)
428 return 0;
430 char *block = (char *) kmalloc (1024);
432 if (!block)
433 return 0;
435 DPRINT (DBG_DRIVER | DBG_FS, "ext2_create_entity -> %d : %s", inode_curr, name);
437 /* read inode structure by current inode id number */
438 ext2_inode_t *inode = ext2_inode_read (p, block, inode_curr);
440 if (!inode) {
441 kfree (block);
442 return 0;
445 ext2_dir_t *ext2dir = (ext2_dir_t *) kmalloc (1024);
447 if (!ext2dir) {
448 kfree (block);
449 return 0;
452 /* read direct block */
453 ext2_sector_read (p, inode->block[0], (unsigned char *) ext2dir);
455 unsigned dir_next = 0;
457 for (;;) {
458 ext2_dir_t *dir_new = (ext2_dir_t *) ((char *) ext2dir + dir_next);
460 if (dir_new->rec_len && dir_new->inode) {
461 dir_next += dir_new->rec_len;
462 printf ("dir_next: %d | %d | %d\n", dir_next, dir_new->rec_len, dir_new->inode);
464 if (dir_next >= 1024) {
465 if (dir_new->rec_len < 264) {
466 printf ("ERROR -> out of dirent\n");
467 break;
470 dir_next -= dir_new->rec_len;
471 dir_new->rec_len = (dir_new->name_len+9) <= 12 ? 12 : 20;
472 dir_next += dir_new->rec_len;
473 printf ("dir_new->rec_len: %d dir_next: %d\n", dir_new->rec_len, dir_next);
475 int inode = dir_new->inode + 1;
477 if (type == EXT2_FT_DIR)
478 inode += 2000;
480 dir_new = (ext2_dir_t *) ((char *) ext2dir + dir_next);
482 dir_new->inode = inode;
483 } else
484 continue;
487 /* set the file type */
488 dir_new->file_type = type;
490 unsigned name_len = strlen (name);
492 if (name_len > 9)
493 name_len = 9;
495 /* yeah :( .. limit to 10 characters for dir[] entry */
496 memcpy (dir_new->name, name, name_len);
497 dir_new->name_len = name_len;
498 dir_new->rec_len = 1024 - dir_next;
500 ext2_inode_t *inode_new = (ext2_inode_t *) kmalloc (sizeof (ext2_inode_t));
502 if (!inode_new)
503 return 0;
505 tm *t = rtc_getcurrtime ();
507 inode_new->mode = 0;
508 inode_new->uid = 0;
509 inode_new->size = 0;
510 inode_new->atime = t->__tm_gmtoff;
511 inode_new->ctime = t->__tm_gmtoff;
512 inode_new->mtime = t->__tm_gmtoff;
513 inode_new->dtime = 0;
514 inode_new->gid = 0;
515 inode_new->links_count = 0;
516 inode_new->blocks = 0;
517 inode_new->flags = 0;
518 inode_new->osd1 = 0;
520 if (dir_new->file_type != EXT2_FT_DIR)
521 inode_new->block[0] = block_free;
522 else
523 inode_new->block[0] = 0;
525 if (!ext2_inode_write (p, inode_new, dir_new->inode)) {
526 kfree (ext2dir);
527 kfree (block);
529 return 0;
532 /* write direct block */
533 ext2_sector_write (p, inode->block[0], (unsigned char *) ext2dir);
535 block_free += 32;
537 DPRINT (DBG_DRIVER | DBG_FS, "dir -> dir_new->inode: %d | %d | %d", dir_new->inode, dir_new->rec_len, sizeof (ext2_inode_t));
539 kfree (inode_new);
543 //if (!inode_new)
544 // goto flush;
546 //DPRINT (DBG_DRIVER | DBG_FS, "dir -> %d - %d %d %d %d %d\n", inode_new->size, inode_new->block[0], inode_new->block[1], inode_new->block[2], inode_new->block[13], inode_new->block[14]);
548 /* write chunk of data */
549 //ext2_block_write (p, inode_new);
551 break;
554 kfree (ext2dir);
555 kfree (block);
557 return 1;
560 unsigned ext2_cd_root (partition_t *p)
562 /* group descriptors */
563 char buf[1024];
564 ext2_group_t *group = (ext2_group_t *) &buf; //kmalloc (1024);
566 if (!group)
567 return 0;
569 /* read group decriptor */
570 ext2_sector_read (p, 2, (unsigned char *) group);
572 DPRINT (DBG_DRIVER | DBG_FS, "group -> %d - %d - %d", group[0].block_bitmap, group[0].inode_bitmap, group[0].inode_table);
574 /* inode tables */
575 ext2_inode_t *inode = (ext2_inode_t *) kmalloc (1024);
577 if (!inode)
578 return 0;
580 /* read root inode */
581 ext2_sector_read (p, group[0].inode_table, (unsigned char *) inode);
583 DPRINT (DBG_DRIVER | DBG_FS, "inode -> 0x%x - %d - %d - %d", inode[1].mode, inode[1].ctime, inode[1].size, inode[1].block[0]);
585 /* read dir entries from root inode */
586 ext2_dir_scan (p, &inode[EXT2_ROOT_INO-1]);
588 inode_curr = EXT2_ROOT_INO;
590 kfree (inode);
591 // kfree (group);
593 return 1;
596 unsigned ext2_cd (partition_t *p, char *name)
598 char buf[1024];
599 char *block = (char *) &buf;// kmalloc (1024);
601 if (!block)
602 return 0;
604 /* read inode structure by current inode id number */
605 ext2_inode_t *inode = ext2_inode_read (p, block, inode_curr);
607 if (!inode) {
608 kfree (block);
609 return 0;
612 ext2_dir_t *ext2dir = (ext2_dir_t *) kmalloc (1024);
614 if (!ext2dir) {
615 kfree (block);
616 return 0;
619 /* read direct block by inode */
620 ext2_sector_read (p, inode->block[0], (unsigned char *) ext2dir);
622 unsigned dir_next = 0;
623 unsigned entry = 0;
624 unsigned name_len = strlen (name);
626 /* loop for find name of directory, where we want go */
627 for (;;) {
628 ext2_dir_t *dir_new = (ext2_dir_t *) ((void *) ext2dir + dir_next);
630 if (!dir_new->rec_len || !dir_new->inode || dir_next >= 1024)
631 break;
633 DPRINT (DBG_DRIVER | DBG_FS, "dir -> 0x%x : %d - %d - %d - %s", dir_new, dir_new->inode, dir_new->rec_len, dir_new->name_len, dir_new->name);
635 /* is it really directory ? */
636 if (dir_new->file_type == EXT2_FT_DIR)
637 if (!strncmp (name, dir_new->name, name_len)) {
638 /* we've found inode of directory, what we need. Let's get this inode structure */
639 ext2_inode_t *inode_new = ext2_inode_read (p, block, dir_new->inode);
641 DPRINT (DBG_DRIVER | DBG_FS, "dir -> dir_new->inode: %d", dir_new->inode);
643 if (!inode_new)
644 goto flush;
646 inode_curr = dir_new->inode;
648 DPRINT (DBG_DRIVER | DBG_FS, "dir -> %d %d %d %d %d", inode_new->block[0], inode_new->block[1], inode_new->block[2], inode_new->block[13], inode_new->block[14]);
650 /* assign new content to dir[] structure */
651 ext2_dir_scan (p, inode_new);
653 goto flush;
656 dir_next += dir_new->rec_len;
657 entry ++;
660 flush:
661 kfree (ext2dir);
662 // kfree (block);
664 return 1;
667 unsigned ext2_cat (partition_t *p, char *name, vfs_content_t *content)
669 char *block = (char *) kmalloc (1024);
671 if (!block)
672 return 0;
674 DPRINT (DBG_DRIVER | DBG_FS, "cat -> %d", inode_curr);
676 /* read inode structure by current inode id number */
677 ext2_inode_t *inode = ext2_inode_read (p, block, inode_curr);
679 if (!inode) {
680 kfree (block);
681 return 0;
684 ext2_dir_t *ext2dir = (ext2_dir_t *) kmalloc (1024);
686 if (!ext2dir) {
687 kfree (block);
688 return 0;
691 /* read direct block */
692 ext2_sector_read (p, inode->block[0], (unsigned char *) ext2dir);
694 unsigned dir_next = 0;
695 unsigned name_len = strlen (name);
697 for (;;) {
698 ext2_dir_t *dir_new = (ext2_dir_t *) ((void *) ext2dir + dir_next);
700 if (!dir_new->rec_len || !dir_new->inode || dir_next >= 1024)
701 break;
703 /* check for file type - regular file */
704 if (dir_new->file_type == EXT2_FT_REG_FILE)
705 if (!strncmp (name, dir_new->name, name_len)) {
706 ext2_inode_t *inode_new = ext2_inode_read (p, block, dir_new->inode);
708 DPRINT (DBG_DRIVER | DBG_FS, "dir -> dir_new->inode: %d", dir_new->inode);
710 if (!inode_new)
711 goto flush;
713 DPRINT (DBG_DRIVER | DBG_FS, "dir -> %d - %d %d %d %d %d", inode_new->size, inode_new->block[0], inode_new->block[1], inode_new->block[2], inode_new->block[13], inode_new->block[14]);
715 /* when file is not clear and direct block is available,
716 read file content*/
717 if (inode_new->size && inode_new->block[0])
718 ext2_block_read (p, inode_new, content);
720 goto flush;
723 dir_next += dir_new->rec_len;
726 flush:
727 kfree (ext2dir);
728 kfree (block);
730 return 1;
733 unsigned ext2_write_file (partition_t *p, char *name)
735 char *block = (char *) kmalloc (1024);
737 if (!block)
738 return 0;
740 DPRINT (DBG_DRIVER | DBG_FS, "write_file -> %d", inode_curr);
742 /* read inode structure by current inode id number */
743 ext2_inode_t *inode = ext2_inode_read (p, block, inode_curr);
745 if (!inode) {
746 kfree (block);
747 return 0;
750 ext2_dir_t *ext2dir = (ext2_dir_t *) kmalloc (1024);
752 if (!ext2dir) {
753 kfree (block);
754 return 0;
757 /* read direct block */
758 ext2_sector_read (p, inode->block[0], (unsigned char *) ext2dir);
760 unsigned dir_next = 0;
761 unsigned name_len = strlen (name);
763 for (;;) {
764 ext2_dir_t *dir_new = (ext2_dir_t *) ((void *) ext2dir + dir_next);
766 if (!dir_new->rec_len || !dir_new->inode || dir_next >= 1024)
767 break;
769 /* check for file type - regular file */
770 if (dir_new->file_type == EXT2_FT_REG_FILE)
771 if (!strncmp (name, dir_new->name, name_len)) {
772 ext2_inode_t *inode_new = ext2_inode_read (p, block, dir_new->inode);
774 DPRINT (DBG_DRIVER | DBG_FS, "dir -> dir_new->inode: %d", dir_new->inode);
776 if (!inode_new)
777 goto flush;
779 DPRINT (DBG_DRIVER | DBG_FS, "dir -> %d - %d %d %d %d %d", inode_new->size, inode_new->block[0], inode_new->block[1], inode_new->block[2], inode_new->block[13], inode_new->block[14]);
781 /* write chunk of data */
782 ext2_block_write (p, inode_new);
784 goto flush;
787 dir_next += dir_new->rec_len;
790 flush:
791 kfree (ext2dir);
792 kfree (block);
794 return 1;
797 unsigned mkext2 (partition_t *p)
799 if (!p)
800 return 0;
802 if (!superblock)
803 superblock = (ext2_superblock_t *) kmalloc (sizeof (ext2_superblock_t));
805 if (!superblock)
806 return 0;
808 superblock->inodecount = 2;
809 //superblock->uuid = ;
810 superblock->magic = EXT2_MAGIC;
811 superblock->inode_size = 128;
812 superblock->log_block_size = 0;
813 superblock->first_ino = 2;
814 superblock->rev_level = 0;
815 superblock->inodes_per_group = 1832;
817 /* write superblock from drive on first sector */
818 ext2_sector_write (p, EXT2_SUPERBLOCK_SECTOR, (unsigned char *) superblock);
820 DPRINT (DBG_DRIVER | DBG_FS, "superblock -> %d, %d - %s - %x - %d", sizeof (ext2_superblock_t), superblock->inodecount, superblock->uuid, superblock->magic, superblock->inode_size);
822 /* check ext2 magic number */
823 if (superblock->magic != EXT2_MAGIC) {
824 kfree (superblock);
825 return 0;
828 /* read block size (default is 1024) */
829 block_size = 1024 << superblock->log_block_size;
831 DPRINT (DBG_DRIVER | DBG_FS, "superblock -> %d - %d - %d - %d", block_size, superblock->first_ino, superblock->rev_level, superblock->inodes_per_group);
834 /* group descriptors */
835 ext2_group_t *group = (ext2_group_t *) kmalloc (1024);
837 if (!group)
838 return 0;
840 /* read group decriptor */
841 ext2_sector_write (p, 2, (unsigned char *) group);
843 DPRINT (DBG_DRIVER | DBG_FS, "group -> %d - %d - %d", group[0].block_bitmap, group[0].inode_bitmap, group[0].inode_table);
845 /* inode tables */
846 ext2_inode_t *inode = (ext2_inode_t *) kmalloc (1024);
848 if (!inode)
849 return 0;
851 /* read root inode */
852 ext2_sector_read (p, group[0].inode_table, (unsigned char *) inode);
854 DPRINT (DBG_DRIVER | DBG_FS, "inode -> 0x%x - %d - %d - %d", inode[1].mode, inode[1].ctime, inode[1].size, inode[1].block[0]);
856 /* read dir entries from root inode */
857 ext2_dir_scan (p, &inode[EXT2_ROOT_INO-1]);
859 inode_curr = EXT2_ROOT_INO;
861 kfree (inode);
862 kfree (group);
864 return 1;
867 unsigned ext2_init (partition_t *p)
869 if (!p)
870 return 0;
872 superblock = (ext2_superblock_t *) kmalloc (sizeof (ext2_superblock_t));
874 if (!superblock)
875 return 0;
877 /* read superblock from drive on first sector */
878 ext2_sector_read (p, EXT2_SUPERBLOCK_SECTOR, (unsigned char *) superblock);
880 DPRINT (DBG_DRIVER | DBG_FS, "superblock -> %d, %d - %s - %x - %d", sizeof (ext2_superblock_t), superblock->inodecount, superblock->uuid, superblock->magic, superblock->inode_size);
882 /* check ext2 magic number */
883 if (superblock->magic != EXT2_MAGIC) {
884 kfree (superblock);
885 return 0;
888 /* read block size (default is 1024) */
889 block_size = 1024 << superblock->log_block_size;
891 block_free = 128;
893 DPRINT (DBG_DRIVER | DBG_FS, "superblock -> %d - %d - %d - %d", block_size, superblock->first_ino, superblock->rev_level, superblock->inodes_per_group);
895 return 1;
898 bool ext2_handler (unsigned act, char *block, unsigned n, unsigned long l)
900 switch (act) {
901 case FS_ACT_INIT:
903 return (bool) ext2_init ((partition_t *) block);
905 break;
906 case FS_ACT_READ:
908 return (bool) ext2_cat (curr_part, dir[n].name, (vfs_content_t *) block);
910 break;
911 case FS_ACT_WRITE:
913 ext2_write_file (curr_part, dir[n].name);
915 return 1;
917 break;
918 case FS_ACT_CHDIR:
920 /* root directory - mount action*/
921 if (n == -1)
922 return (bool) ext2_cd_root (curr_part);
924 /* walk to another directory */
925 return (bool) ext2_cd (curr_part, block);
927 break;
928 case FS_ACT_MKDIR:
930 return ext2_create_entity (curr_part, block, EXT2_FT_DIR);
932 break;
933 case FS_ACT_TOUCH:
935 return ext2_create_entity (curr_part, block, EXT2_FT_REG_FILE);
939 return 0;
941 #endif