3 * Copyright (C) 2007 Tomas 'ZeXx86' Jedrzejek (zexx86@gmail.com)
4 * Copyright (C) 2008 Tomas 'ZeXx86' Jedrzejek (zexx86@gmail.com)
5 * Copyright (C) 2009 Tomas 'ZeXx86' Jedrzejek (zexx86@gmail.com)
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 extern mount_t mount_list
;
32 extern unsigned int fd_count
;
34 vfs_t
*vfs_list_find (char *name
, char *mountpoint
)
36 unsigned l
= strlen (name
);
39 for (vfs
= vfs_list
.next
; vfs
!= &vfs_list
; vfs
= vfs
->next
) {
40 if (!strncmp (vfs
->name
, name
, l
) && !strcmp (vfs
->mountpoint
, mountpoint
))
47 vfs_t
*vfs_list_findbymp (char *mountpoint
)
51 strcpy (pwd
, (char *) env_get ("PWD"));
52 unsigned l
= strlen (pwd
);
55 for (vfs
= vfs_list
.next
; vfs
!= &vfs_list
; vfs
= vfs
->next
) {
56 if (strncmp (pwd
, vfs
->mountpoint
, l
))
59 sprintf (mdir
, "%s%s/", vfs
->mountpoint
, vfs
->name
);
61 if (!strcmp (mdir
, mountpoint
))
68 vfs_t
*vfs_list_add (char *name
, unsigned attrib
, char *mountpoint
)
70 unsigned name_len
= strlen (name
);
71 unsigned mp_len
= strlen (mountpoint
);
74 for (vfs
= vfs_list
.next
; vfs
!= &vfs_list
; vfs
= vfs
->next
) {
75 if (!strcmp (vfs
->name
, name
) && !strcmp (vfs
->mountpoint
, mountpoint
)) {
76 DPRINT ("ERROR -> vfs_list_add () - vfs object already exist !\n");
81 /* alloc and init context */
82 vfs
= (vfs_t
*) kmalloc (sizeof (vfs_t
));
87 memset (vfs
, 0, sizeof (vfs_t
));
89 vfs
->name
= (char *) kmalloc (sizeof (char) * VFS_FILENAME_LEN
+ 2);
96 memset (vfs
->name
, 0, VFS_FILENAME_LEN
);
97 memcpy (vfs
->name
, name
, name_len
);
98 vfs
->name
[name_len
] = '\0';
100 memset (vfs
->mountpoint
, 0, VFS_MOUNTPOINT_LEN
);
101 memcpy (vfs
->mountpoint
, mountpoint
, mp_len
);
102 vfs
->mountpoint
[mp_len
] = '\0';
104 vfs
->attrib
= attrib
;
109 vfs
->next
= &vfs_list
;
110 vfs
->prev
= vfs_list
.prev
;
111 vfs
->prev
->next
= vfs
;
112 vfs
->next
->prev
= vfs
;
117 bool vfs_list_del (vfs_t
*vfs
)
122 vfs
->next
->prev
= vfs
->prev
;
123 vfs
->prev
->next
= vfs
->next
;
126 if (vfs
->content
->ptr
)
127 kfree (vfs
->content
->ptr
);
129 kfree (vfs
->content
);
135 bool vfs_list_delbymp (char *mountpoint
)
139 for (vfs
= vfs_list
.next
; vfs
!= &vfs_list
; vfs
= vfs
->next
) {
140 if (!strncmp (vfs
->mountpoint
, mountpoint
, strlen (mountpoint
))) {
147 vfs
->next
->prev
= vfs
->prev
;
148 vfs
->prev
->next
= vfs
->next
;
151 if (vfs
->content
->ptr
)
152 kfree (vfs
->content
->ptr
);
154 kfree (vfs
->content
);
164 bool vfs_mmap (char *file
, unsigned file_len
, char *data
, unsigned long len
)
169 strcpy (pwd
, (char *) env_get ("PWD"));
172 unsigned pwd_len
= strlen (pwd
);
174 unsigned i
= file
[0] == '/' ? 1 : 0;
177 memcpy (buf
, pwd
, pwd_len
);
178 memcpy (buf
+pwd_len
, file
+i
, file_len
-i
);
179 buf
[pwd_len
+file_len
-i
] = '\0';
181 memcpy (buf
, file
, file_len
);
182 buf
[file_len
] = '\0';
185 if (buf
[pwd_len
+file_len
-i
-1] == '/')
186 buf
[pwd_len
+file_len
-i
-1] = '\0';
188 for (vfs
= vfs_list
.next
; vfs
!= &vfs_list
; vfs
= vfs
->next
) {
189 unsigned mp_len
= strlen (vfs
->mountpoint
);
190 unsigned nm_len
= strlen (vfs
->name
);
193 memcpy (buf2
, vfs
->mountpoint
, mp_len
);
194 memcpy (buf2
+mp_len
, vfs
->name
, nm_len
);
195 buf2
[mp_len
+nm_len
] = '\0';
197 if (!cstrcmp (buf
, buf2
)) {
198 if (vfs
->attrib
& VFS_FILEATTR_DIR
) {
199 printf ("ERROR -> this is a directory, not an file\n");
203 if (vfs
->attrib
& VFS_FILEATTR_MOUNTED
) {
204 partition_t
*p
= (partition_t
*) partition_findbyfile (file
);
209 while (strlen (dir
[i
].name
)) {
210 if (!strncmp (file
, dir
[i
].name
, file_len
))
211 return p
->fs
->handler (FS_ACT_WRITE
, data
, i
, len
);
218 printf ("ERROR -> device not respond\n");
223 printf ("ERROR -> You can't overwrite content of this file\n");
227 vfs
->content
= (vfs_content_t
*) kmalloc (sizeof (vfs_content_t
));
232 /*vfs->content->ptr = (char *) kmalloc (sizeof (char) * (len+1));
234 if (!vfs->content->ptr) {
235 kfree (vfs->content);
240 memcpy (vfs->content->ptr, data, len);
241 vfs->content->ptr[len] = '\0';*/
243 vfs
->content
->ptr
= data
;
245 vfs
->content
->len
= len
;
254 extern unsigned long file_cache_id
;
255 int vfs_read (char *file
, unsigned file_len
)
260 strcpy (pwd
, (char *) env_get ("PWD"));
263 unsigned pwd_len
= strlen (pwd
);
268 unsigned i
= file
[0] == '/' ? 1 : 0;
271 memcpy (buf
, pwd
, pwd_len
);
272 memcpy (buf
+pwd_len
, file
+i
, file_len
-i
);
273 buf
[pwd_len
+file_len
-i
] = '\0';
275 memcpy (buf
, file
, file_len
);
276 buf
[file_len
] = '\0';
279 if (buf
[pwd_len
+file_len
-i
-1] == '/')
280 buf
[pwd_len
+file_len
-i
-1] = '\0';
282 for (vfs
= vfs_list
.next
; vfs
!= &vfs_list
; vfs
= vfs
->next
) {
283 unsigned mp_len
= strlen (vfs
->mountpoint
);
284 unsigned nm_len
= strlen (vfs
->name
);
287 memcpy (buf2
, vfs
->mountpoint
, mp_len
);
288 memcpy (buf2
+mp_len
, vfs
->name
, nm_len
);
289 buf2
[mp_len
+nm_len
] = '\0';
291 if (!cstrcmp (buf
, buf2
)) {
292 if (vfs
->attrib
& VFS_FILEATTR_DIR
) {
293 printf ("ERROR -> this is a directory, not an file\n");
297 if (vfs
->attrib
& VFS_FILEATTR_MOUNTED
) {
298 partition_t
*p
= (partition_t
*) partition_findbyfile (file
);
303 while (strlen (dir
[i
].name
)) {
304 if (!strncmp (file
, dir
[i
].name
, file_len
)) {
305 p
->fs
->handler (FS_ACT_READ
, block
, i
, len
);
313 printf ("ERROR -> device not respond\n");
317 if (vfs
->attrib
& VFS_FILEATTR_DEVICE
) {
322 printf ("ERROR -> This file not contain a valid data\n");
326 file_cache
= vfs
->content
->ptr
;
327 file_cache_id
= vfs
->content
->len
;
339 bool vfs_cat (char *file
, unsigned file_len
)
344 index
= vfs_read (file
, file_len
);
349 for (i
= 0; i
< file_cache_id
; i
++)
350 tty_putch (file_cache
[i
]);
355 bool vfs_ls (char *file
, unsigned file_len
)
363 strcpy (ls
, (char *) env_get ("PWD"));
364 for (vfs
= vfs_list
.next
; vfs
!= &vfs_list
; vfs
= vfs
->next
)
365 if (!strcmp (vfs
->mountpoint
, ls
)) {
366 printf ("%s\t", vfs
->name
);
370 if (!strncmp(file
,"/",1)) {
373 strcpy (ls
,(char *) env_get ("PWD"));
374 strcpy (ls
+strlen(ls
),file
);
377 if (strncmp(file
+file_len
-1,"/",1)) {
378 strcpy(ls
+strlen(ls
),"/");
381 for (vfs
= vfs_list
.next
; vfs
!= &vfs_list
; vfs
= vfs
->next
)
382 if (!strcmp (vfs
->mountpoint
, ls
) ||
383 !strcmp (vfs
->mountpoint
+1, ls
)) {
384 printf ("%s\t", vfs
->name
);
389 /*printf ("%s\t%u%u%u%u%u%u%u\n", vfs->name,
390 vfs->attrib & VFS_FILEATTR_READ,
391 vfs->attrib & VFS_FILEATTR_WRITE,
392 vfs->attrib & VFS_FILEATTR_HIDDEN,
393 vfs->attrib & VFS_FILEATTR_SYSTEM,
394 vfs->attrib & VFS_FILEATTR_DIR,
395 vfs->attrib & VFS_FILEATTR_BIN);*/
403 bool vfs_cd (char *file
, unsigned file_len
)
406 if (!strcmp (file
, "..")) {
408 strcpy (pwd
, (char *) env_get ("PWD"));
410 unsigned pwd_len
= strlen (pwd
);
412 if (!strcmp (pwd
, "/"))
415 /* vymaze kus retezce - az po predposledni / */
416 pwd_len
--; // preskoci / na konci retezce
419 if (pwd
[pwd_len
] == '/') {
420 pwd
[pwd_len
+1] = '\0';
426 for (vfs
= vfs_list
.next
; vfs
!= &vfs_list
; vfs
= vfs
->next
)
427 if (!strcmp (vfs
->mountpoint
, pwd
)) {
428 if (vfs
->attrib
& VFS_FILEATTR_MOUNTED
) {
429 //printf ("vfs->mountpoint: %s | pwd: %s\n", vfs->mountpoint, pwd);
430 partition_t
*p
= mount_find (pwd
);
433 mount (p
, file
, ""); // first return to last directory
435 umount (p
, (char *) env_get ("PWD")); // then umount old directory
437 while (vfs_list_delbymp ((char *) env_get ("PWD")));
441 printf ("ERROR -> device not respond\n");
447 env_set ("PWD", pwd
); // set new directory
453 if (!strcmp (file
, "."))
457 /* go to root fs dir */
458 if (!strcmp (file
, "/")) {
459 env_set ("PWD", file
);
461 for (vfs
= vfs_list
.next
; vfs
!= &vfs_list
; vfs
= vfs
->next
) {
462 if (vfs
->attrib
& VFS_FILEATTR_MOUNTED
) {
463 partition_t
*p
= mount_find ((char *) env_get ("PWD"));
473 /* go to another directory */
475 strcpy (pwd
, (char *) env_get ("PWD"));
478 unsigned pwd_len
= strlen (pwd
);
480 unsigned i
= file
[0] == '/' ? 1 : 0;
483 memcpy (buf
, pwd
, pwd_len
);
484 memcpy (buf
+pwd_len
, file
+i
, file_len
-i
);
485 buf
[pwd_len
+file_len
-i
] = '\0';
487 memcpy (buf
, file
, file_len
);
488 buf
[file_len
] = '\0';
491 if (buf
[pwd_len
+file_len
-i
-1] == '/')
492 buf
[pwd_len
+file_len
-i
-1] = '\0';
494 unsigned buf_l
= strlen (buf
);
495 if (buf
[buf_l
-1] == '/')
498 for (vfs
= vfs_list
.next
; vfs
!= &vfs_list
; vfs
= vfs
->next
) {
499 unsigned mp_len
= strlen (vfs
->mountpoint
);
500 unsigned nm_len
= strlen (vfs
->name
);
503 memcpy (buf2
, vfs
->mountpoint
, mp_len
);
504 memcpy (buf2
+mp_len
, vfs
->name
, nm_len
);
505 buf2
[mp_len
+nm_len
] = '\0';
507 if (!cstrcmp (buf
, buf2
)) {
508 if (vfs
->attrib
& VFS_FILEATTR_FILE
) {
509 printf ("ERROR -> this is a file, not an directory\n");
514 if (vfs
->attrib
& VFS_FILEATTR_SYSTEM
&& strcmp ((char *) env_get ("USER"), "root")) {
515 printf ("ERROR -> only root can do that\n");
519 memcpy (pwd
, buf2
, mp_len
+nm_len
);
520 pwd
[mp_len
+nm_len
] = '/';
521 pwd
[mp_len
+nm_len
+1] = '\0';
523 if (vfs
->attrib
& VFS_FILEATTR_MOUNTED
) {
524 partition_t
*p
= mount_find ((char *) env_get ("PWD"));
527 mount (p
, file
, pwd
);
529 printf ("ERROR -> device not respond\n");
534 env_set ("PWD", pwd
);
543 bool vfs_mkdir (char *file
, unsigned file_len
)
547 strcpy (pwd
, (char *) env_get ("PWD"));
549 partition_t
*p
= mount_find ((char *) pwd
);
552 vfs_list_add (file
, VFS_FILEATTR_DIR
| VFS_FILEATTR_READ
| VFS_FILEATTR_MOUNTED
, (char *) pwd
);
553 p
->fs
->handler (FS_ACT_MKDIR
, file
, 0, file_len
);
555 vfs_list_add (file
, VFS_FILEATTR_DIR
| VFS_FILEATTR_READ
, (char *) pwd
);
556 DPRINT ("NOTE -> this directory is created only in virtual file system\n");
559 DPRINT ("vfs_mkdir ()\n");
566 bool vfs_touch (char *file
, unsigned file_len
)
570 strcpy (pwd
, (char *) env_get ("PWD"));
573 for (i
= file_len
; i
; i
--) {
574 if (file
[i
] == '/') {
584 path
= (char *) kmalloc (sizeof (char) * (file_len
+1));
589 memcpy (path
, file
, i
+1);
598 partition_t
*p
= mount_find ((char *) pwd
);
601 vfs_list_add (f
, VFS_FILEATTR_FILE
| VFS_FILEATTR_READ
| VFS_FILEATTR_BIN
| VFS_FILEATTR_MOUNTED
, (char *) path
);
602 p
->fs
->handler (FS_ACT_TOUCH
, file
, 0, strlen (file
));
604 vfs_list_add (f
, VFS_FILEATTR_FILE
| VFS_FILEATTR_READ
| VFS_FILEATTR_BIN
, (char *) path
);
605 DPRINT ("NOTE -> this file is created only in virtual file system\n");
610 vfs_cd (pwd
, strlen (pwd
));
613 DPRINT ("vfs_touch ()\n");
620 int vfs_rm (char *file
, unsigned file_len
)
624 strcpy (pwd
, (char *) env_get ("PWD"));
627 for (i
= file_len
; i
; i
--) {
628 if (file
[i
] == '/') {
638 path
= (char *) kmalloc (sizeof (char) * (file_len
+1));
643 memcpy (path
, file
, i
+1);
652 vfs_t
*vfs
= vfs_list_find (f
, (char *) path
);
658 if (vfs
->attrib
& VFS_FILEATTR_SYSTEM
|| vfs
->attrib
& VFS_FILEATTR_DIR
)
661 if (vfs
->attrib
& VFS_FILEATTR_MOUNTED
) {
662 partition_t
*p
= mount_find ((char *) pwd
);
667 p
->fs
->handler (FS_ACT_RM
, file
, 0, strlen (file
));
669 /* delete vfs file with content */
675 vfs_cd (pwd
, strlen (pwd
));
678 DPRINT ("vfs_rm ()\n");
685 vfs_dirent_t
*vfs_dirent ()
688 strcpy (pwd
, (char *) env_get ("PWD"));
693 unsigned dirents
= 0;
695 for (vfs
= vfs_list
.next
; vfs
!= &vfs_list
; vfs
= vfs
->next
)
696 if (!strcmp (vfs
->mountpoint
, pwd
))
702 vfs_dirent_t
*dirent
= (vfs_dirent_t
*) kmalloc (sizeof (vfs_dirent_t
) * (dirents
+1));
708 for (vfs
= vfs_list
.next
; vfs
!= &vfs_list
; vfs
= vfs
->next
)
709 if (!strcmp (vfs
->mountpoint
, pwd
)) {
710 /*unsigned len = strlen (vfs->name);
711 dirent[i].name = (char *) kmalloc (sizeof (char) * (len + 1));
716 memcpy (dirent[i].name, vfs->name, len);
717 dirent[i].name[len] = '\0';*/
718 dirent
[i
].name
= vfs
->name
;
720 dirent
[i
].attrib
= vfs
->attrib
;
722 if ((i
+1) == dirents
)
730 dirent
[dirents
].next
= 0;
735 unsigned int init_vfs ()
737 mount_list
.next
= &mount_list
;
738 mount_list
.prev
= &mount_list
;
740 vfs_list
.next
= &vfs_list
;
741 vfs_list
.prev
= &vfs_list
;
743 vfs_list_add ("bin", VFS_FILEATTR_DIR
| VFS_FILEATTR_SYSTEM
| VFS_FILEATTR_READ
, "/");
744 vfs_list_add ("cd", VFS_FILEATTR_FILE
| VFS_FILEATTR_SYSTEM
| VFS_FILEATTR_READ
| VFS_FILEATTR_BIN
, "/bin/");
745 vfs_list_add ("ls", VFS_FILEATTR_FILE
| VFS_FILEATTR_SYSTEM
| VFS_FILEATTR_READ
| VFS_FILEATTR_BIN
, "/bin/");
746 vfs_list_add ("exec", VFS_FILEATTR_FILE
| VFS_FILEATTR_SYSTEM
| VFS_FILEATTR_READ
| VFS_FILEATTR_BIN
, "/bin/");
747 vfs_list_add ("dev", VFS_FILEATTR_DIR
| VFS_FILEATTR_SYSTEM
| VFS_FILEATTR_READ
, "/");
748 vfs_list_add ("etc", VFS_FILEATTR_DIR
| VFS_FILEATTR_SYSTEM
| VFS_FILEATTR_READ
, "/");
749 vfs_list_add ("mnt", VFS_FILEATTR_DIR
| VFS_FILEATTR_SYSTEM
| VFS_FILEATTR_READ
, "/");
750 vfs_list_add ("floppy", VFS_FILEATTR_DIR
| VFS_FILEATTR_SYSTEM
| VFS_FILEATTR_READ
, "/mnt/");
751 vfs_list_add ("cdrom", VFS_FILEATTR_DIR
| VFS_FILEATTR_SYSTEM
| VFS_FILEATTR_READ
, "/mnt/");
752 vfs_list_add ("hdd", VFS_FILEATTR_DIR
| VFS_FILEATTR_SYSTEM
| VFS_FILEATTR_READ
, "/mnt/");
753 vfs_list_add ("usr", VFS_FILEATTR_DIR
| VFS_FILEATTR_SYSTEM
| VFS_FILEATTR_READ
, "/");
754 vfs_list_add ("root", VFS_FILEATTR_DIR
| VFS_FILEATTR_SYSTEM
| VFS_FILEATTR_READ
, "/usr/");
755 vfs_list_add ("proc", VFS_FILEATTR_DIR
| VFS_FILEATTR_SYSTEM
| VFS_FILEATTR_READ
, "/");
757 /* let's build /proc/cpuinfo */