3 * Copyright (C) 2007 Tomas 'ZeXx86' Jedrzejek (zexx86@zexos.org)
4 * Copyright (C) 2008 Tomas 'ZeXx86' Jedrzejek (zexx86@zexos.org)
5 * Copyright (C) 2009 Tomas 'ZeXx86' Jedrzejek (zexx86@zexos.org)
6 * Copyright (C) 2010 Tomas 'ZeXx86' Jedrzejek (zexx86@zexos.org)
8 * This program is free software: you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation, either version 3 of the License, or
11 * (at your option) any later version.
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
18 * You should have received a copy of the GNU General Public License
19 * along with this program. If not, see <http://www.gnu.org/licenses/>.
35 extern mount_t mount_list
;
37 vfs_t
*vfs_list_find (char *name
, char *mountpoint
)
39 unsigned l
= strlen (name
);
42 for (vfs
= vfs_list
.next
; vfs
!= &vfs_list
; vfs
= vfs
->next
) {
43 if (!strncmp (vfs
->name
, name
, l
) && !strcmp (vfs
->mountpoint
, mountpoint
))
50 vfs_t
*vfs_list_findbymp (char *mountpoint
)
54 strcpy (pwd
, (char *) env_get ("PWD"));
55 unsigned l
= strlen (pwd
);
58 for (vfs
= vfs_list
.next
; vfs
!= &vfs_list
; vfs
= vfs
->next
) {
59 if (strncmp (pwd
, vfs
->mountpoint
, l
))
62 sprintf (mdir
, "%s%s/", vfs
->mountpoint
, vfs
->name
);
64 if (!strcmp (mdir
, mountpoint
))
71 vfs_t
*vfs_find (char *file
, unsigned file_len
)
77 strcpy (pwd
, (char *) env_get ("PWD"));
80 unsigned pwd_len
= strlen (pwd
);
82 unsigned i
= file
[0] == '/' ? 1 : 0;
85 memcpy (buf
, pwd
, pwd_len
);
86 memcpy (buf
+pwd_len
, file
+i
, file_len
-i
);
87 buf
[pwd_len
+file_len
-i
] = '\0';
89 memcpy (buf
, file
, file_len
);
93 if (buf
[pwd_len
+file_len
-i
-1] == '/')
94 buf
[pwd_len
+file_len
-i
-1] = '\0';
97 for (vfs
= vfs_list
.next
; vfs
!= &vfs_list
; vfs
= vfs
->next
) {
98 unsigned mp_len
= strlen (vfs
->mountpoint
);
99 unsigned nm_len
= strlen (vfs
->name
);
102 memcpy (buf2
, vfs
->mountpoint
, mp_len
);
103 memcpy (buf2
+mp_len
, vfs
->name
, nm_len
);
104 buf2
[mp_len
+nm_len
] = '\0';
106 if (!cstrcmp (buf
, buf2
))
113 vfs_t
*vfs_list_add (char *name
, unsigned attrib
, char *mountpoint
)
115 unsigned name_len
= strlen (name
);
116 unsigned mp_len
= strlen (mountpoint
);
119 for (vfs
= vfs_list
.next
; vfs
!= &vfs_list
; vfs
= vfs
->next
) {
120 if (!strcmp (vfs
->name
, name
) && !strcmp (vfs
->mountpoint
, mountpoint
)) {
121 DPRINT (DBG_VFS
, "ERROR -> vfs_list_add () - vfs object already exist !");
126 /* alloc and init context */
127 vfs
= (vfs_t
*) kmalloc (sizeof (vfs_t
));
132 memset (vfs
, 0, sizeof (vfs_t
));
134 vfs
->name
= (char *) kmalloc (sizeof (char) * VFS_FILENAME_LEN
+ 2);
141 memset (vfs
->name
, 0, VFS_FILENAME_LEN
);
142 memcpy (vfs
->name
, name
, name_len
);
143 vfs
->name
[name_len
] = '\0';
145 memset (vfs
->mountpoint
, 0, VFS_MOUNTPOINT_LEN
);
146 memcpy (vfs
->mountpoint
, mountpoint
, mp_len
);
147 vfs
->mountpoint
[mp_len
] = '\0';
149 vfs
->attrib
= attrib
;
154 vfs
->next
= &vfs_list
;
155 vfs
->prev
= vfs_list
.prev
;
156 vfs
->prev
->next
= vfs
;
157 vfs
->next
->prev
= vfs
;
162 bool vfs_list_del (vfs_t
*vfs
)
167 vfs
->next
->prev
= vfs
->prev
;
168 vfs
->prev
->next
= vfs
->next
;
171 if (vfs
->content
->ptr
)
172 cache_closebyptr (vfs
->content
->ptr
);
174 kfree (vfs
->content
);
180 bool vfs_list_delbymp (char *mountpoint
)
184 for (vfs
= vfs_list
.next
; vfs
!= &vfs_list
; vfs
= vfs
->next
) {
185 if (!strncmp (vfs
->mountpoint
, mountpoint
, strlen (mountpoint
))) {
192 vfs
->next
->prev
= vfs
->prev
;
193 vfs
->prev
->next
= vfs
->next
;
196 if (vfs
->content
->ptr
)
197 kfree (vfs
->content
->ptr
);
199 kfree (vfs
->content
);
209 int vfs_mmap (char *file
, unsigned file_len
, vfs_content_t
*content
)
211 vfs_t
*vfs
= vfs_find (file
, file_len
);
216 DPRINT (DBG_VFS
, "vfs_mmap () - file '%s' not found", file
);
220 if (vfs
->attrib
& VFS_FILEATTR_DIR
) {
221 printf ("ERROR -> this is a directory, not an file\n");
225 if (vfs
->attrib
& VFS_FILEATTR_MOUNTED
) {
226 partition_t
*p
= (partition_t
*) mount_find ((char *) vfs
->mountpoint
);
230 unsigned l
= strlen (vfs
->name
);
232 while (strlen (dir
[i
].name
)) {
233 if (!strncmp (vfs
->name
, dir
[i
].name
, l
))
234 return p
->fs
->handler (FS_ACT_WRITE
, (char *) content
, i
, 0);
239 DPRINT (DBG_VFS
, "vfs_mmap () - file '%s' not found in mounted filesystem", file
);
242 printf ("ERROR -> device not respond\n");
248 printf ("ERROR -> You can't overwrite content of this file\n");
253 vfs
->content
= (vfs_content_t
*) kmalloc (sizeof (vfs_content_t
));
260 /* NOTE: when file in VFS is device, we match it as READable */
261 if (!(vfs
->attrib
& VFS_FILEATTR_READ
))
262 vfs
->attrib
|= VFS_FILEATTR_READ
;
264 /*cache_t *cache = cache_create (data, len, 1);
271 vfs
->content
->ptr
= content
->ptr
;
272 vfs
->content
->len
= content
->len
;
278 int vfs_read (char *file
, unsigned file_len
, vfs_content_t
*content
)
280 vfs_t
*vfs
= vfs_find (file
, file_len
);
285 if (vfs
->attrib
& VFS_FILEATTR_DIR
) {
286 printf ("ERROR -> This is a directory, not an file\n");
290 if (vfs
->attrib
& VFS_FILEATTR_MOUNTED
) {
291 partition_t
*p
= (partition_t
*) mount_find ((char *) vfs
->mountpoint
);
295 unsigned l
= strlen (vfs
->name
);
297 while (strlen (dir
[i
].name
)) {
298 if (!strncmp (vfs
->name
, dir
[i
].name
, l
)) {
299 if (!p
->fs
->handler (FS_ACT_READ
, (char *) content
, i
, 0)) {
300 printf ("ERROR -> Device read action\n");
310 printf ("ERROR -> device not respond\n");
314 if (vfs
->attrib
& VFS_FILEATTR_DEVICE
&& !(vfs
->attrib
& VFS_FILEATTR_READ
)) {
315 printf ("ERROR -> This file is non-char or non-block device\n");
320 printf ("ERROR -> This file not contain a valid data\n");
324 if (!vfs
->content
->ptr
) {
325 printf ("ERROR -> This file not contain a valid data\n");
329 content
->ptr
= vfs
->content
->ptr
;
330 content
->len
= vfs
->content
->len
;
338 int vfs_cat (char *file
, unsigned file_len
)
341 vfs_content_t content
;
345 int index
= vfs_read (file
, file_len
, &content
);
350 paging_disable (); /* HACK: we can occasionally access user address space (behind kernel-space which is unmapped for us) */
353 for (i
= 0; i
< content
.len
; i
++)
354 tty_putch (content
.ptr
[i
]);
361 int vfs_cp (char *what
, unsigned what_len
, char *where
, unsigned where_len
)
363 vfs_content_t content
;
365 int index
= vfs_read (what
, what_len
, &content
);
370 if (!vfs_touch (where
, where_len
))
373 if (!vfs_mmap (where
, where_len
, &content
))
379 int vfs_ls (char *file
, unsigned file_len
)
387 strcpy (ls
, (char *) env_get ("PWD"));
388 for (vfs
= vfs_list
.next
; vfs
!= &vfs_list
; vfs
= vfs
->next
)
389 if (!strcmp (vfs
->mountpoint
, ls
)) {
390 printf ("%s\t", vfs
->name
);
394 if (!strncmp(file
,"/",1))
397 strcpy (ls
,(char *) env_get ("PWD"));
398 strcpy (ls
+strlen(ls
),file
);
401 if (strncmp(file
+file_len
-1,"/",1)) {
402 strcpy(ls
+strlen(ls
),"/");
405 for (vfs
= vfs_list
.next
; vfs
!= &vfs_list
; vfs
= vfs
->next
)
406 if (!strcmp (vfs
->mountpoint
, ls
) ||
407 !strcmp (vfs
->mountpoint
+1, ls
)) {
408 printf ("%s\t", vfs
->name
);
419 int vfs_cd (char *file
, unsigned file_len
)
422 if (!strcmp (file
, "..")) {
424 strcpy (pwd
, (char *) env_get ("PWD"));
426 unsigned pwd_len
= strlen (pwd
);
428 if (!strcmp (pwd
, "/"))
431 /* vymaze kus retezce - az po predposledni / */
432 pwd_len
--; // preskoci / na konci retezce
435 if (pwd
[pwd_len
] == '/') {
436 pwd
[pwd_len
+1] = '\0';
442 for (vfs
= vfs_list
.next
; vfs
!= &vfs_list
; vfs
= vfs
->next
)
443 if (!strcmp (vfs
->mountpoint
, pwd
)) {
444 if (vfs
->attrib
& VFS_FILEATTR_MOUNTED
) {
445 //printf ("vfs->mountpoint: %s | pwd: %s\n", vfs->mountpoint, pwd);
446 partition_t
*p
= mount_find (pwd
);
449 mount (p
, file
, ""); // first return to last directory
451 umount (p
, (char *) env_get ("PWD")); // then umount old directory
453 while (vfs_list_delbymp ((char *) env_get ("PWD")));
457 printf ("ERROR -> device not respond\n");
463 env_set ("PWD", pwd
); // set new directory
469 if (!strcmp (file
, "."))
473 /* go to root fs dir */
474 if (!strcmp (file
, "/")) {
475 env_set ("PWD", file
);
477 for (vfs
= vfs_list
.next
; vfs
!= &vfs_list
; vfs
= vfs
->next
) {
478 if (vfs
->attrib
& VFS_FILEATTR_MOUNTED
) {
479 partition_t
*p
= mount_find ((char *) env_get ("PWD"));
489 /* go to another directory */
491 strcpy (pwd
, (char *) env_get ("PWD"));
494 unsigned pwd_len
= strlen (pwd
);
496 unsigned i
= file
[0] == '/' ? 1 : 0;
499 memcpy (buf
, pwd
, pwd_len
);
500 memcpy (buf
+pwd_len
, file
+i
, file_len
-i
);
501 buf
[pwd_len
+file_len
-i
] = '\0';
503 memcpy (buf
, file
, file_len
);
504 buf
[file_len
] = '\0';
507 if (buf
[pwd_len
+file_len
-i
-1] == '/')
508 buf
[pwd_len
+file_len
-i
-1] = '\0';
510 unsigned buf_l
= strlen (buf
);
511 if (buf
[buf_l
-1] == '/')
514 for (vfs
= vfs_list
.next
; vfs
!= &vfs_list
; vfs
= vfs
->next
) {
515 unsigned mp_len
= strlen (vfs
->mountpoint
);
516 unsigned nm_len
= strlen (vfs
->name
);
519 memcpy (buf2
, vfs
->mountpoint
, mp_len
);
520 memcpy (buf2
+mp_len
, vfs
->name
, nm_len
);
521 buf2
[mp_len
+nm_len
] = '\0';
523 if (!cstrcmp (buf
, buf2
)) {
524 if (vfs
->attrib
& VFS_FILEATTR_FILE
) {
525 printf ("ERROR -> this is a file, not an directory\n");
530 if (vfs
->attrib
& VFS_FILEATTR_SYSTEM
&& strcmp ((char *) env_get ("USER"), "root")) {
531 printf ("ERROR -> only root can do that\n");
535 memcpy (pwd
, buf2
, mp_len
+nm_len
);
536 pwd
[mp_len
+nm_len
] = '/';
537 pwd
[mp_len
+nm_len
+1] = '\0';
539 if (vfs
->attrib
& VFS_FILEATTR_MOUNTED
) {
540 partition_t
*p
= mount_find ((char *) env_get ("PWD"));
543 mount (p
, file
, pwd
);
545 printf ("ERROR -> device not respond\n");
550 env_set ("PWD", pwd
);
559 int vfs_mkdir (char *file
, unsigned file_len
)
565 strcpy (pwd
, (char *) env_get ("PWD"));
568 for (i
= file_len
; i
; i
--) {
569 if (file
[i
] == '/') {
579 path
= (char *) kmalloc (sizeof (char) * (file_len
+1));
584 memcpy (path
, file
, i
+1);
593 partition_t
*p
= mount_find ((char *) env_get ("PWD"));
596 vfs_list_add (f
, VFS_FILEATTR_DIR
| VFS_FILEATTR_READ
| VFS_FILEATTR_BIN
| VFS_FILEATTR_MOUNTED
, (char *) path
);
597 p
->fs
->handler (FS_ACT_MKDIR
, file
, 0, strlen (file
));
599 vfs_list_add (f
, VFS_FILEATTR_DIR
| VFS_FILEATTR_READ
| VFS_FILEATTR_BIN
, (char *) path
);
600 DPRINT (DBG_VFS
, "NOTE -> this directory is created only in virtual file system");
605 vfs_cd (pwd
, strlen (pwd
));
608 DPRINT (DBG_VFS
, "vfs_mkdir (%s)", file
);
613 int vfs_touch (char *file
, unsigned file_len
)
619 strcpy (pwd
, (char *) env_get ("PWD"));
622 for (i
= file_len
; i
; i
--) {
623 if (file
[i
] == '/') {
633 path
= (char *) kmalloc (sizeof (char) * (file_len
+1));
638 memcpy (path
, file
, i
+1);
647 partition_t
*p
= mount_find ((char *) env_get ("PWD"));
650 printf ("f: %s\n", f
);
651 vfs_list_add (f
, VFS_FILEATTR_FILE
| VFS_FILEATTR_READ
| VFS_FILEATTR_BIN
| VFS_FILEATTR_MOUNTED
, (char *) path
);
652 p
->fs
->handler (FS_ACT_TOUCH
, f
, 0, strlen (f
));
654 vfs_list_add (f
, VFS_FILEATTR_FILE
| VFS_FILEATTR_READ
| VFS_FILEATTR_BIN
, (char *) path
);
655 DPRINT (DBG_VFS
, "NOTE -> this file is created only in virtual file system");
660 vfs_cd (pwd
, strlen (pwd
));
663 DPRINT (DBG_VFS
, "vfs_touch (%s)", file
);
668 int vfs_rm (char *file
, unsigned file_len
)
674 strcpy (pwd
, (char *) env_get ("PWD"));
677 for (i
= file_len
; i
; i
--) {
678 if (file
[i
] == '/') {
688 path
= (char *) kmalloc (sizeof (char) * (file_len
+1));
693 memcpy (path
, file
, i
+1);
702 vfs_t
*vfs
= vfs_list_find (f
, (char *) path
);
708 if (vfs
->attrib
& VFS_FILEATTR_SYSTEM
|| vfs
->attrib
& VFS_FILEATTR_DIR
)
711 if (vfs
->attrib
& VFS_FILEATTR_MOUNTED
) {
712 partition_t
*p
= mount_find ((char *) pwd
);
717 p
->fs
->handler (FS_ACT_RM
, file
, 0, strlen (file
));
719 /* delete vfs file with content */
725 vfs_cd (pwd
, strlen (pwd
));
728 DPRINT (DBG_VFS
, "vfs_rm (%s)", file
);
733 vfs_dirent_t
*vfs_dirent ()
736 strcpy (pwd
, (char *) env_get ("PWD"));
741 unsigned dirents
= 0;
743 for (vfs
= vfs_list
.next
; vfs
!= &vfs_list
; vfs
= vfs
->next
)
744 if (!strcmp (vfs
->mountpoint
, pwd
))
750 vfs_dirent_t
*dirent
= (vfs_dirent_t
*) kmalloc (sizeof (vfs_dirent_t
) * (dirents
+1));
756 for (vfs
= vfs_list
.next
; vfs
!= &vfs_list
; vfs
= vfs
->next
)
757 if (!strcmp (vfs
->mountpoint
, pwd
)) {
758 dirent
[i
].name
= vfs
->name
;
760 dirent
[i
].attrib
= vfs
->attrib
;
762 if ((i
+1) == dirents
)
770 dirent
[dirents
].next
= 0;
775 unsigned int init_vfs ()
777 mount_list
.next
= &mount_list
;
778 mount_list
.prev
= &mount_list
;
780 vfs_list
.next
= &vfs_list
;
781 vfs_list
.prev
= &vfs_list
;
783 if (!(kernel_attr
& KERNEL_NOLIVE
)) {
784 vfs_list_add ("bin", VFS_FILEATTR_DIR
| VFS_FILEATTR_SYSTEM
| VFS_FILEATTR_READ
, "/");
785 vfs_list_add ("cd", VFS_FILEATTR_FILE
| VFS_FILEATTR_SYSTEM
| VFS_FILEATTR_READ
| VFS_FILEATTR_BIN
, "/bin/");
786 vfs_list_add ("ls", VFS_FILEATTR_FILE
| VFS_FILEATTR_SYSTEM
| VFS_FILEATTR_READ
| VFS_FILEATTR_BIN
, "/bin/");
787 vfs_list_add ("exec", VFS_FILEATTR_FILE
| VFS_FILEATTR_SYSTEM
| VFS_FILEATTR_READ
| VFS_FILEATTR_BIN
, "/bin/");
788 vfs_list_add ("dev", VFS_FILEATTR_DIR
| VFS_FILEATTR_SYSTEM
| VFS_FILEATTR_READ
, "/");
789 vfs_list_add ("etc", VFS_FILEATTR_DIR
| VFS_FILEATTR_SYSTEM
| VFS_FILEATTR_READ
, "/");
790 vfs_list_add ("mnt", VFS_FILEATTR_DIR
| VFS_FILEATTR_SYSTEM
| VFS_FILEATTR_READ
, "/");
791 vfs_list_add ("floppy", VFS_FILEATTR_DIR
| VFS_FILEATTR_SYSTEM
| VFS_FILEATTR_READ
, "/mnt/");
792 vfs_list_add ("cdrom", VFS_FILEATTR_DIR
| VFS_FILEATTR_SYSTEM
| VFS_FILEATTR_READ
, "/mnt/");
793 vfs_list_add ("hdd", VFS_FILEATTR_DIR
| VFS_FILEATTR_SYSTEM
| VFS_FILEATTR_READ
, "/mnt/");
794 vfs_list_add ("usr", VFS_FILEATTR_DIR
| VFS_FILEATTR_SYSTEM
| VFS_FILEATTR_READ
, "/");
795 vfs_list_add ("root", VFS_FILEATTR_DIR
| VFS_FILEATTR_SYSTEM
| VFS_FILEATTR_READ
, "/usr/");
796 vfs_list_add ("proc", VFS_FILEATTR_DIR
| VFS_FILEATTR_SYSTEM
| VFS_FILEATTR_READ
, "/");
799 /* let's build /proc/cpuinfo */