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 /* NOTE: when file in VFS is device, we match it as READable */
233 if (!(vfs
->attrib
& VFS_FILEATTR_READ
))
234 vfs
->attrib
|= VFS_FILEATTR_READ
;
236 /*vfs->content->ptr = (char *) kmalloc (sizeof (char) * (len+1));
238 if (!vfs->content->ptr) {
239 kfree (vfs->content);
244 memcpy (vfs->content->ptr, data, len);
245 vfs->content->ptr[len] = '\0';*/
247 vfs
->content
->ptr
= data
;
249 vfs
->content
->len
= len
;
258 extern unsigned long file_cache_id
;
259 int vfs_read (char *file
, unsigned file_len
)
264 strcpy (pwd
, (char *) env_get ("PWD"));
267 unsigned pwd_len
= strlen (pwd
);
272 unsigned i
= file
[0] == '/' ? 1 : 0;
275 memcpy (buf
, pwd
, pwd_len
);
276 memcpy (buf
+pwd_len
, file
+i
, file_len
-i
);
277 buf
[pwd_len
+file_len
-i
] = '\0';
279 memcpy (buf
, file
, file_len
);
280 buf
[file_len
] = '\0';
283 if (buf
[pwd_len
+file_len
-i
-1] == '/')
284 buf
[pwd_len
+file_len
-i
-1] = '\0';
286 for (vfs
= vfs_list
.next
; vfs
!= &vfs_list
; vfs
= vfs
->next
) {
287 unsigned mp_len
= strlen (vfs
->mountpoint
);
288 unsigned nm_len
= strlen (vfs
->name
);
291 memcpy (buf2
, vfs
->mountpoint
, mp_len
);
292 memcpy (buf2
+mp_len
, vfs
->name
, nm_len
);
293 buf2
[mp_len
+nm_len
] = '\0';
295 if (!cstrcmp (buf
, buf2
)) {
296 if (vfs
->attrib
& VFS_FILEATTR_DIR
) {
297 printf ("ERROR -> this is a directory, not an file\n");
301 if (vfs
->attrib
& VFS_FILEATTR_MOUNTED
) {
302 partition_t
*p
= (partition_t
*) partition_findbyfile (file
);
307 while (strlen (dir
[i
].name
)) {
308 if (!strncmp (file
, dir
[i
].name
, file_len
)) {
309 p
->fs
->handler (FS_ACT_READ
, block
, i
, len
);
317 printf ("ERROR -> device not respond\n");
321 if (vfs
->attrib
& VFS_FILEATTR_DEVICE
&& !(vfs
->attrib
& VFS_FILEATTR_READ
)) {
323 printf ("ERROR -> This file is non-char or non-block device\n");
328 printf ("ERROR -> This file not contain a valid data\n");
332 file_cache
= vfs
->content
->ptr
;
333 file_cache_id
= vfs
->content
->len
;
349 bool vfs_cat (char *file
, unsigned file_len
)
354 index
= vfs_read (file
, file_len
);
359 for (i
= 0; i
< file_cache_id
; i
++)
360 tty_putch (file_cache
[i
]);
365 bool vfs_ls (char *file
, unsigned file_len
)
373 strcpy (ls
, (char *) env_get ("PWD"));
374 for (vfs
= vfs_list
.next
; vfs
!= &vfs_list
; vfs
= vfs
->next
)
375 if (!strcmp (vfs
->mountpoint
, ls
)) {
376 printf ("%s\t", vfs
->name
);
380 if (!strncmp(file
,"/",1)) {
383 strcpy (ls
,(char *) env_get ("PWD"));
384 strcpy (ls
+strlen(ls
),file
);
387 if (strncmp(file
+file_len
-1,"/",1)) {
388 strcpy(ls
+strlen(ls
),"/");
391 for (vfs
= vfs_list
.next
; vfs
!= &vfs_list
; vfs
= vfs
->next
)
392 if (!strcmp (vfs
->mountpoint
, ls
) ||
393 !strcmp (vfs
->mountpoint
+1, ls
)) {
394 printf ("%s\t", vfs
->name
);
399 /*printf ("%s\t%u%u%u%u%u%u%u\n", vfs->name,
400 vfs->attrib & VFS_FILEATTR_READ,
401 vfs->attrib & VFS_FILEATTR_WRITE,
402 vfs->attrib & VFS_FILEATTR_HIDDEN,
403 vfs->attrib & VFS_FILEATTR_SYSTEM,
404 vfs->attrib & VFS_FILEATTR_DIR,
405 vfs->attrib & VFS_FILEATTR_BIN);*/
413 bool vfs_cd (char *file
, unsigned file_len
)
416 if (!strcmp (file
, "..")) {
418 strcpy (pwd
, (char *) env_get ("PWD"));
420 unsigned pwd_len
= strlen (pwd
);
422 if (!strcmp (pwd
, "/"))
425 /* vymaze kus retezce - az po predposledni / */
426 pwd_len
--; // preskoci / na konci retezce
429 if (pwd
[pwd_len
] == '/') {
430 pwd
[pwd_len
+1] = '\0';
436 for (vfs
= vfs_list
.next
; vfs
!= &vfs_list
; vfs
= vfs
->next
)
437 if (!strcmp (vfs
->mountpoint
, pwd
)) {
438 if (vfs
->attrib
& VFS_FILEATTR_MOUNTED
) {
439 //printf ("vfs->mountpoint: %s | pwd: %s\n", vfs->mountpoint, pwd);
440 partition_t
*p
= mount_find (pwd
);
443 mount (p
, file
, ""); // first return to last directory
445 umount (p
, (char *) env_get ("PWD")); // then umount old directory
447 while (vfs_list_delbymp ((char *) env_get ("PWD")));
451 printf ("ERROR -> device not respond\n");
457 env_set ("PWD", pwd
); // set new directory
463 if (!strcmp (file
, "."))
467 /* go to root fs dir */
468 if (!strcmp (file
, "/")) {
469 env_set ("PWD", file
);
471 for (vfs
= vfs_list
.next
; vfs
!= &vfs_list
; vfs
= vfs
->next
) {
472 if (vfs
->attrib
& VFS_FILEATTR_MOUNTED
) {
473 partition_t
*p
= mount_find ((char *) env_get ("PWD"));
483 /* go to another directory */
485 strcpy (pwd
, (char *) env_get ("PWD"));
488 unsigned pwd_len
= strlen (pwd
);
490 unsigned i
= file
[0] == '/' ? 1 : 0;
493 memcpy (buf
, pwd
, pwd_len
);
494 memcpy (buf
+pwd_len
, file
+i
, file_len
-i
);
495 buf
[pwd_len
+file_len
-i
] = '\0';
497 memcpy (buf
, file
, file_len
);
498 buf
[file_len
] = '\0';
501 if (buf
[pwd_len
+file_len
-i
-1] == '/')
502 buf
[pwd_len
+file_len
-i
-1] = '\0';
504 unsigned buf_l
= strlen (buf
);
505 if (buf
[buf_l
-1] == '/')
508 for (vfs
= vfs_list
.next
; vfs
!= &vfs_list
; vfs
= vfs
->next
) {
509 unsigned mp_len
= strlen (vfs
->mountpoint
);
510 unsigned nm_len
= strlen (vfs
->name
);
513 memcpy (buf2
, vfs
->mountpoint
, mp_len
);
514 memcpy (buf2
+mp_len
, vfs
->name
, nm_len
);
515 buf2
[mp_len
+nm_len
] = '\0';
517 if (!cstrcmp (buf
, buf2
)) {
518 if (vfs
->attrib
& VFS_FILEATTR_FILE
) {
519 printf ("ERROR -> this is a file, not an directory\n");
524 if (vfs
->attrib
& VFS_FILEATTR_SYSTEM
&& strcmp ((char *) env_get ("USER"), "root")) {
525 printf ("ERROR -> only root can do that\n");
529 memcpy (pwd
, buf2
, mp_len
+nm_len
);
530 pwd
[mp_len
+nm_len
] = '/';
531 pwd
[mp_len
+nm_len
+1] = '\0';
533 if (vfs
->attrib
& VFS_FILEATTR_MOUNTED
) {
534 partition_t
*p
= mount_find ((char *) env_get ("PWD"));
537 mount (p
, file
, pwd
);
539 printf ("ERROR -> device not respond\n");
544 env_set ("PWD", pwd
);
553 bool vfs_mkdir (char *file
, unsigned file_len
)
557 strcpy (pwd
, (char *) env_get ("PWD"));
559 partition_t
*p
= mount_find ((char *) pwd
);
562 vfs_list_add (file
, VFS_FILEATTR_DIR
| VFS_FILEATTR_READ
| VFS_FILEATTR_MOUNTED
, (char *) pwd
);
563 p
->fs
->handler (FS_ACT_MKDIR
, file
, 0, file_len
);
565 vfs_list_add (file
, VFS_FILEATTR_DIR
| VFS_FILEATTR_READ
, (char *) pwd
);
566 DPRINT ("NOTE -> this directory is created only in virtual file system\n");
569 DPRINT ("vfs_mkdir ()\n");
576 bool vfs_touch (char *file
, unsigned file_len
)
580 strcpy (pwd
, (char *) env_get ("PWD"));
583 for (i
= file_len
; i
; i
--) {
584 if (file
[i
] == '/') {
594 path
= (char *) kmalloc (sizeof (char) * (file_len
+1));
599 memcpy (path
, file
, i
+1);
608 partition_t
*p
= mount_find ((char *) pwd
);
611 vfs_list_add (f
, VFS_FILEATTR_FILE
| VFS_FILEATTR_READ
| VFS_FILEATTR_BIN
| VFS_FILEATTR_MOUNTED
, (char *) path
);
612 p
->fs
->handler (FS_ACT_TOUCH
, file
, 0, strlen (file
));
614 vfs_list_add (f
, VFS_FILEATTR_FILE
| VFS_FILEATTR_READ
| VFS_FILEATTR_BIN
, (char *) path
);
615 DPRINT ("NOTE -> this file is created only in virtual file system\n");
620 vfs_cd (pwd
, strlen (pwd
));
623 DPRINT ("vfs_touch ()\n");
630 int vfs_rm (char *file
, unsigned file_len
)
634 strcpy (pwd
, (char *) env_get ("PWD"));
637 for (i
= file_len
; i
; i
--) {
638 if (file
[i
] == '/') {
648 path
= (char *) kmalloc (sizeof (char) * (file_len
+1));
653 memcpy (path
, file
, i
+1);
662 vfs_t
*vfs
= vfs_list_find (f
, (char *) path
);
668 if (vfs
->attrib
& VFS_FILEATTR_SYSTEM
|| vfs
->attrib
& VFS_FILEATTR_DIR
)
671 if (vfs
->attrib
& VFS_FILEATTR_MOUNTED
) {
672 partition_t
*p
= mount_find ((char *) pwd
);
677 p
->fs
->handler (FS_ACT_RM
, file
, 0, strlen (file
));
679 /* delete vfs file with content */
685 vfs_cd (pwd
, strlen (pwd
));
688 DPRINT ("vfs_rm ()\n");
695 vfs_dirent_t
*vfs_dirent ()
698 strcpy (pwd
, (char *) env_get ("PWD"));
703 unsigned dirents
= 0;
705 for (vfs
= vfs_list
.next
; vfs
!= &vfs_list
; vfs
= vfs
->next
)
706 if (!strcmp (vfs
->mountpoint
, pwd
))
712 vfs_dirent_t
*dirent
= (vfs_dirent_t
*) kmalloc (sizeof (vfs_dirent_t
) * (dirents
+1));
718 for (vfs
= vfs_list
.next
; vfs
!= &vfs_list
; vfs
= vfs
->next
)
719 if (!strcmp (vfs
->mountpoint
, pwd
)) {
720 /*unsigned len = strlen (vfs->name);
721 dirent[i].name = (char *) kmalloc (sizeof (char) * (len + 1));
726 memcpy (dirent[i].name, vfs->name, len);
727 dirent[i].name[len] = '\0';*/
728 dirent
[i
].name
= vfs
->name
;
730 dirent
[i
].attrib
= vfs
->attrib
;
732 if ((i
+1) == dirents
)
740 dirent
[dirents
].next
= 0;
745 unsigned int init_vfs ()
747 mount_list
.next
= &mount_list
;
748 mount_list
.prev
= &mount_list
;
750 vfs_list
.next
= &vfs_list
;
751 vfs_list
.prev
= &vfs_list
;
753 vfs_list_add ("bin", VFS_FILEATTR_DIR
| VFS_FILEATTR_SYSTEM
| VFS_FILEATTR_READ
, "/");
754 vfs_list_add ("cd", VFS_FILEATTR_FILE
| VFS_FILEATTR_SYSTEM
| VFS_FILEATTR_READ
| VFS_FILEATTR_BIN
, "/bin/");
755 vfs_list_add ("ls", VFS_FILEATTR_FILE
| VFS_FILEATTR_SYSTEM
| VFS_FILEATTR_READ
| VFS_FILEATTR_BIN
, "/bin/");
756 vfs_list_add ("exec", VFS_FILEATTR_FILE
| VFS_FILEATTR_SYSTEM
| VFS_FILEATTR_READ
| VFS_FILEATTR_BIN
, "/bin/");
757 vfs_list_add ("dev", VFS_FILEATTR_DIR
| VFS_FILEATTR_SYSTEM
| VFS_FILEATTR_READ
, "/");
758 vfs_list_add ("etc", VFS_FILEATTR_DIR
| VFS_FILEATTR_SYSTEM
| VFS_FILEATTR_READ
, "/");
759 vfs_list_add ("mnt", VFS_FILEATTR_DIR
| VFS_FILEATTR_SYSTEM
| VFS_FILEATTR_READ
, "/");
760 vfs_list_add ("floppy", VFS_FILEATTR_DIR
| VFS_FILEATTR_SYSTEM
| VFS_FILEATTR_READ
, "/mnt/");
761 vfs_list_add ("cdrom", VFS_FILEATTR_DIR
| VFS_FILEATTR_SYSTEM
| VFS_FILEATTR_READ
, "/mnt/");
762 vfs_list_add ("hdd", VFS_FILEATTR_DIR
| VFS_FILEATTR_SYSTEM
| VFS_FILEATTR_READ
, "/mnt/");
763 vfs_list_add ("usr", VFS_FILEATTR_DIR
| VFS_FILEATTR_SYSTEM
| VFS_FILEATTR_READ
, "/");
764 vfs_list_add ("root", VFS_FILEATTR_DIR
| VFS_FILEATTR_SYSTEM
| VFS_FILEATTR_READ
, "/usr/");
765 vfs_list_add ("proc", VFS_FILEATTR_DIR
| VFS_FILEATTR_SYSTEM
| VFS_FILEATTR_READ
, "/");
767 /* let's build /proc/cpuinfo */