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/>.
32 extern mount_t mount_list
;
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 !");
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 int 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
);
216 DPRINT ("vfs_mmap () - file '%s' not found in mounted filesystem", file
);
219 printf ("ERROR -> device not respond\n");
225 printf ("ERROR -> You can't overwrite content of this file\n");
230 vfs
->content
= (vfs_content_t
*) kmalloc (sizeof (vfs_content_t
));
237 /* NOTE: when file in VFS is device, we match it as READable */
238 if (!(vfs
->attrib
& VFS_FILEATTR_READ
))
239 vfs
->attrib
|= VFS_FILEATTR_READ
;
241 vfs
->content
->ptr
= data
;
243 vfs
->content
->len
= len
;
252 DPRINT ("vfs_mmap () - file '%s' not found", file
);
257 extern unsigned long file_cache_id
;
258 int vfs_read (char *file
, unsigned file_len
)
263 strcpy (pwd
, (char *) env_get ("PWD"));
266 unsigned pwd_len
= strlen (pwd
);
271 unsigned i
= file
[0] == '/' ? 1 : 0;
274 memcpy (buf
, pwd
, pwd_len
);
275 memcpy (buf
+pwd_len
, file
+i
, file_len
-i
);
276 buf
[pwd_len
+file_len
-i
] = '\0';
278 memcpy (buf
, file
, file_len
);
279 buf
[file_len
] = '\0';
282 if (buf
[pwd_len
+file_len
-i
-1] == '/')
283 buf
[pwd_len
+file_len
-i
-1] = '\0';
285 for (vfs
= vfs_list
.next
; vfs
!= &vfs_list
; vfs
= vfs
->next
) {
286 unsigned mp_len
= strlen (vfs
->mountpoint
);
287 unsigned nm_len
= strlen (vfs
->name
);
290 memcpy (buf2
, vfs
->mountpoint
, mp_len
);
291 memcpy (buf2
+mp_len
, vfs
->name
, nm_len
);
292 buf2
[mp_len
+nm_len
] = '\0';
294 if (!cstrcmp (buf
, buf2
)) {
295 if (vfs
->attrib
& VFS_FILEATTR_DIR
) {
296 printf ("ERROR -> This is a directory, not an file\n");
300 if (vfs
->attrib
& VFS_FILEATTR_MOUNTED
) {
301 partition_t
*p
= (partition_t
*) partition_findbyfile (file
);
306 while (strlen (dir
[i
].name
)) {
307 if (!strncmp (file
, dir
[i
].name
, file_len
)) {
308 file_cache
= (unsigned char *) FILE_CACHE
; // file_cache store address
310 if (!p
->fs
->handler (FS_ACT_READ
, block
, i
, len
)) {
312 printf ("ERROR -> Device read action\n");
322 printf ("ERROR -> device not respond\n");
326 if (vfs
->attrib
& VFS_FILEATTR_DEVICE
&& !(vfs
->attrib
& VFS_FILEATTR_READ
)) {
328 printf ("ERROR -> This file is non-char or non-block device\n");
333 printf ("ERROR -> This file not contain a valid data\n");
338 if (!vfs
->content
->ptr
) {
339 printf ("ERROR -> This file not contain a valid data\n");
343 file_cache
= vfs
->content
->ptr
;
344 file_cache_id
= vfs
->content
->len
;
360 int vfs_cat (char *file
, unsigned file_len
)
365 index
= vfs_read (file
, file_len
);
370 for (i
= 0; i
< file_cache_id
; i
++)
371 tty_putch (file_cache
[i
]);
376 int vfs_cp (char *what
, unsigned what_len
, char *where
, unsigned where_len
)
381 index
= vfs_read (what
, what_len
);
386 if (!vfs_touch (where
, where_len
))
389 if (!vfs_mmap (where
, where_len
, file_cache
, file_cache_id
))
395 int vfs_ls (char *file
, unsigned file_len
)
403 strcpy (ls
, (char *) env_get ("PWD"));
404 for (vfs
= vfs_list
.next
; vfs
!= &vfs_list
; vfs
= vfs
->next
)
405 if (!strcmp (vfs
->mountpoint
, ls
)) {
406 printf ("%s\t", vfs
->name
);
410 if (!strncmp(file
,"/",1)) {
413 strcpy (ls
,(char *) env_get ("PWD"));
414 strcpy (ls
+strlen(ls
),file
);
417 if (strncmp(file
+file_len
-1,"/",1)) {
418 strcpy(ls
+strlen(ls
),"/");
421 for (vfs
= vfs_list
.next
; vfs
!= &vfs_list
; vfs
= vfs
->next
)
422 if (!strcmp (vfs
->mountpoint
, ls
) ||
423 !strcmp (vfs
->mountpoint
+1, ls
)) {
424 printf ("%s\t", vfs
->name
);
429 /*printf ("%s\t%u%u%u%u%u%u%u\n", vfs->name,
430 vfs->attrib & VFS_FILEATTR_READ,
431 vfs->attrib & VFS_FILEATTR_WRITE,
432 vfs->attrib & VFS_FILEATTR_HIDDEN,
433 vfs->attrib & VFS_FILEATTR_SYSTEM,
434 vfs->attrib & VFS_FILEATTR_DIR,
435 vfs->attrib & VFS_FILEATTR_BIN);*/
443 int vfs_cd (char *file
, unsigned file_len
)
446 if (!strcmp (file
, "..")) {
448 strcpy (pwd
, (char *) env_get ("PWD"));
450 unsigned pwd_len
= strlen (pwd
);
452 if (!strcmp (pwd
, "/"))
455 /* vymaze kus retezce - az po predposledni / */
456 pwd_len
--; // preskoci / na konci retezce
459 if (pwd
[pwd_len
] == '/') {
460 pwd
[pwd_len
+1] = '\0';
466 for (vfs
= vfs_list
.next
; vfs
!= &vfs_list
; vfs
= vfs
->next
)
467 if (!strcmp (vfs
->mountpoint
, pwd
)) {
468 if (vfs
->attrib
& VFS_FILEATTR_MOUNTED
) {
469 //printf ("vfs->mountpoint: %s | pwd: %s\n", vfs->mountpoint, pwd);
470 partition_t
*p
= mount_find (pwd
);
473 mount (p
, file
, ""); // first return to last directory
475 umount (p
, (char *) env_get ("PWD")); // then umount old directory
477 while (vfs_list_delbymp ((char *) env_get ("PWD")));
481 printf ("ERROR -> device not respond\n");
487 env_set ("PWD", pwd
); // set new directory
493 if (!strcmp (file
, "."))
497 /* go to root fs dir */
498 if (!strcmp (file
, "/")) {
499 env_set ("PWD", file
);
501 for (vfs
= vfs_list
.next
; vfs
!= &vfs_list
; vfs
= vfs
->next
) {
502 if (vfs
->attrib
& VFS_FILEATTR_MOUNTED
) {
503 partition_t
*p
= mount_find ((char *) env_get ("PWD"));
513 /* go to another directory */
515 strcpy (pwd
, (char *) env_get ("PWD"));
518 unsigned pwd_len
= strlen (pwd
);
520 unsigned i
= file
[0] == '/' ? 1 : 0;
523 memcpy (buf
, pwd
, pwd_len
);
524 memcpy (buf
+pwd_len
, file
+i
, file_len
-i
);
525 buf
[pwd_len
+file_len
-i
] = '\0';
527 memcpy (buf
, file
, file_len
);
528 buf
[file_len
] = '\0';
531 if (buf
[pwd_len
+file_len
-i
-1] == '/')
532 buf
[pwd_len
+file_len
-i
-1] = '\0';
534 unsigned buf_l
= strlen (buf
);
535 if (buf
[buf_l
-1] == '/')
538 for (vfs
= vfs_list
.next
; vfs
!= &vfs_list
; vfs
= vfs
->next
) {
539 unsigned mp_len
= strlen (vfs
->mountpoint
);
540 unsigned nm_len
= strlen (vfs
->name
);
543 memcpy (buf2
, vfs
->mountpoint
, mp_len
);
544 memcpy (buf2
+mp_len
, vfs
->name
, nm_len
);
545 buf2
[mp_len
+nm_len
] = '\0';
547 if (!cstrcmp (buf
, buf2
)) {
548 if (vfs
->attrib
& VFS_FILEATTR_FILE
) {
549 printf ("ERROR -> this is a file, not an directory\n");
554 if (vfs
->attrib
& VFS_FILEATTR_SYSTEM
&& strcmp ((char *) env_get ("USER"), "root")) {
555 printf ("ERROR -> only root can do that\n");
559 memcpy (pwd
, buf2
, mp_len
+nm_len
);
560 pwd
[mp_len
+nm_len
] = '/';
561 pwd
[mp_len
+nm_len
+1] = '\0';
563 if (vfs
->attrib
& VFS_FILEATTR_MOUNTED
) {
564 partition_t
*p
= mount_find ((char *) env_get ("PWD"));
567 mount (p
, file
, pwd
);
569 printf ("ERROR -> device not respond\n");
574 env_set ("PWD", pwd
);
583 int vfs_mkdir (char *file
, unsigned file_len
)
587 strcpy (pwd
, (char *) env_get ("PWD"));
590 for (i
= file_len
; i
; i
--) {
591 if (file
[i
] == '/') {
601 path
= (char *) kmalloc (sizeof (char) * (file_len
+1));
606 memcpy (path
, file
, i
+1);
615 partition_t
*p
= mount_find ((char *) env_get ("PWD"));
618 vfs_list_add (f
, VFS_FILEATTR_DIR
| VFS_FILEATTR_READ
| VFS_FILEATTR_BIN
| VFS_FILEATTR_MOUNTED
, (char *) path
);
619 p
->fs
->handler (FS_ACT_MKDIR
, file
, 0, strlen (file
));
621 vfs_list_add (f
, VFS_FILEATTR_DIR
| VFS_FILEATTR_READ
| VFS_FILEATTR_BIN
, (char *) path
);
622 DPRINT ("NOTE -> this directory is created only in virtual file system");
627 vfs_cd (pwd
, strlen (pwd
));
630 DPRINT ("vfs_mkdir ()");
637 int vfs_touch (char *file
, unsigned file_len
)
641 strcpy (pwd
, (char *) env_get ("PWD"));
644 for (i
= file_len
; i
; i
--) {
645 if (file
[i
] == '/') {
655 path
= (char *) kmalloc (sizeof (char) * (file_len
+1));
660 memcpy (path
, file
, i
+1);
669 partition_t
*p
= mount_find ((char *) env_get ("PWD"));
672 vfs_list_add (f
, VFS_FILEATTR_FILE
| VFS_FILEATTR_READ
| VFS_FILEATTR_BIN
| VFS_FILEATTR_MOUNTED
, (char *) path
);
673 p
->fs
->handler (FS_ACT_TOUCH
, file
, 0, strlen (file
));
675 vfs_list_add (f
, VFS_FILEATTR_FILE
| VFS_FILEATTR_READ
| VFS_FILEATTR_BIN
, (char *) path
);
676 DPRINT ("NOTE -> this file is created only in virtual file system");
681 vfs_cd (pwd
, strlen (pwd
));
684 DPRINT ("vfs_touch ()");
691 int vfs_rm (char *file
, unsigned file_len
)
695 strcpy (pwd
, (char *) env_get ("PWD"));
698 for (i
= file_len
; i
; i
--) {
699 if (file
[i
] == '/') {
709 path
= (char *) kmalloc (sizeof (char) * (file_len
+1));
714 memcpy (path
, file
, i
+1);
723 vfs_t
*vfs
= vfs_list_find (f
, (char *) path
);
729 if (vfs
->attrib
& VFS_FILEATTR_SYSTEM
|| vfs
->attrib
& VFS_FILEATTR_DIR
)
732 if (vfs
->attrib
& VFS_FILEATTR_MOUNTED
) {
733 partition_t
*p
= mount_find ((char *) pwd
);
738 p
->fs
->handler (FS_ACT_RM
, file
, 0, strlen (file
));
740 /* delete vfs file with content */
746 vfs_cd (pwd
, strlen (pwd
));
749 DPRINT ("vfs_rm ()");
756 vfs_dirent_t
*vfs_dirent ()
759 strcpy (pwd
, (char *) env_get ("PWD"));
764 unsigned dirents
= 0;
766 for (vfs
= vfs_list
.next
; vfs
!= &vfs_list
; vfs
= vfs
->next
)
767 if (!strcmp (vfs
->mountpoint
, pwd
))
773 vfs_dirent_t
*dirent
= (vfs_dirent_t
*) kmalloc (sizeof (vfs_dirent_t
) * (dirents
+1));
779 for (vfs
= vfs_list
.next
; vfs
!= &vfs_list
; vfs
= vfs
->next
)
780 if (!strcmp (vfs
->mountpoint
, pwd
)) {
781 /*unsigned len = strlen (vfs->name);
782 dirent[i].name = (char *) kmalloc (sizeof (char) * (len + 1));
787 memcpy (dirent[i].name, vfs->name, len);
788 dirent[i].name[len] = '\0';*/
789 dirent
[i
].name
= vfs
->name
;
791 dirent
[i
].attrib
= vfs
->attrib
;
793 if ((i
+1) == dirents
)
801 dirent
[dirents
].next
= 0;
806 unsigned int init_vfs ()
808 mount_list
.next
= &mount_list
;
809 mount_list
.prev
= &mount_list
;
811 vfs_list
.next
= &vfs_list
;
812 vfs_list
.prev
= &vfs_list
;
814 if (!(kernel_attr
& KERNEL_NOLIVE
)) {
815 vfs_list_add ("bin", VFS_FILEATTR_DIR
| VFS_FILEATTR_SYSTEM
| VFS_FILEATTR_READ
, "/");
816 vfs_list_add ("cd", VFS_FILEATTR_FILE
| VFS_FILEATTR_SYSTEM
| VFS_FILEATTR_READ
| VFS_FILEATTR_BIN
, "/bin/");
817 vfs_list_add ("ls", VFS_FILEATTR_FILE
| VFS_FILEATTR_SYSTEM
| VFS_FILEATTR_READ
| VFS_FILEATTR_BIN
, "/bin/");
818 vfs_list_add ("exec", VFS_FILEATTR_FILE
| VFS_FILEATTR_SYSTEM
| VFS_FILEATTR_READ
| VFS_FILEATTR_BIN
, "/bin/");
819 vfs_list_add ("dev", VFS_FILEATTR_DIR
| VFS_FILEATTR_SYSTEM
| VFS_FILEATTR_READ
, "/");
820 vfs_list_add ("etc", VFS_FILEATTR_DIR
| VFS_FILEATTR_SYSTEM
| VFS_FILEATTR_READ
, "/");
821 vfs_list_add ("mnt", VFS_FILEATTR_DIR
| VFS_FILEATTR_SYSTEM
| VFS_FILEATTR_READ
, "/");
822 vfs_list_add ("floppy", VFS_FILEATTR_DIR
| VFS_FILEATTR_SYSTEM
| VFS_FILEATTR_READ
, "/mnt/");
823 vfs_list_add ("cdrom", VFS_FILEATTR_DIR
| VFS_FILEATTR_SYSTEM
| VFS_FILEATTR_READ
, "/mnt/");
824 vfs_list_add ("hdd", VFS_FILEATTR_DIR
| VFS_FILEATTR_SYSTEM
| VFS_FILEATTR_READ
, "/mnt/");
825 vfs_list_add ("usr", VFS_FILEATTR_DIR
| VFS_FILEATTR_SYSTEM
| VFS_FILEATTR_READ
, "/");
826 vfs_list_add ("root", VFS_FILEATTR_DIR
| VFS_FILEATTR_SYSTEM
| VFS_FILEATTR_READ
, "/usr/");
827 vfs_list_add ("proc", VFS_FILEATTR_DIR
| VFS_FILEATTR_SYSTEM
| VFS_FILEATTR_READ
, "/");
830 /* let's build /proc/cpuinfo */