Direct support for serial mouse in kernel - it is recognized as /dev/mousecom; added...
[ZeXOS.git] / kernel / core / vfs.c
blobcaa83c10af521cb37275a48a5fe8d10ed2666d23
1 /*
2 * ZeX/OS
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/>.
22 #include <system.h>
23 #include <string.h>
24 #include <mount.h>
25 #include <vfs.h>
26 #include <smp.h>
27 #include <fd.h>
29 vfs_t vfs_list;
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);
38 vfs_t *vfs;
39 for (vfs = vfs_list.next; vfs != &vfs_list; vfs = vfs->next) {
40 if (!strncmp (vfs->name, name, l) && !strcmp (vfs->mountpoint, mountpoint))
41 return vfs;
44 return 0;
47 vfs_t *vfs_list_findbymp (char *mountpoint)
49 char mdir[128];
50 char pwd[64];
51 strcpy (pwd, (char *) env_get ("PWD"));
52 unsigned l = strlen (pwd);
54 vfs_t *vfs;
55 for (vfs = vfs_list.next; vfs != &vfs_list; vfs = vfs->next) {
56 if (strncmp (pwd, vfs->mountpoint, l))
57 continue;
59 sprintf (mdir, "%s%s/", vfs->mountpoint, vfs->name);
61 if (!strcmp (mdir, mountpoint))
62 return vfs;
65 return 0;
68 vfs_t *vfs_list_add (char *name, unsigned attrib, char *mountpoint)
70 unsigned name_len = strlen (name);
71 unsigned mp_len = strlen (mountpoint);
73 vfs_t *vfs;
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");
77 return 0;
81 /* alloc and init context */
82 vfs = (vfs_t *) kmalloc (sizeof (vfs_t));
84 if (!vfs)
85 return 0;
87 memset (vfs, 0, sizeof (vfs_t));
89 vfs->name = (char *) kmalloc (sizeof (char) * VFS_FILENAME_LEN + 2);
91 if (!vfs->name) {
92 kfree (vfs);
93 return 0;
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;
106 vfs->content = 0;
108 /* add into list */
109 vfs->next = &vfs_list;
110 vfs->prev = vfs_list.prev;
111 vfs->prev->next = vfs;
112 vfs->next->prev = vfs;
114 return vfs;
117 bool vfs_list_del (vfs_t *vfs)
119 if (!vfs)
120 return 0;
122 vfs->next->prev = vfs->prev;
123 vfs->prev->next = vfs->next;
125 if (vfs->content) {
126 if (vfs->content->ptr)
127 kfree (vfs->content->ptr);
129 kfree (vfs->content);
132 return 1;
135 bool vfs_list_delbymp (char *mountpoint)
137 bool f = 0;
138 vfs_t *vfs;
139 for (vfs = vfs_list.next; vfs != &vfs_list; vfs = vfs->next) {
140 if (!strncmp (vfs->mountpoint, mountpoint, strlen (mountpoint))) {
141 f = 1;
142 break;
146 if (f) {
147 vfs->next->prev = vfs->prev;
148 vfs->prev->next = vfs->next;
150 if (vfs->content) {
151 if (vfs->content->ptr)
152 kfree (vfs->content->ptr);
154 kfree (vfs->content);
157 //kfree (vfs);
158 return 1;
161 return 0;
164 bool vfs_mmap (char *file, unsigned file_len, char *data, unsigned long len)
166 vfs_t *vfs;
168 char pwd[64];
169 strcpy (pwd, (char *) env_get ("PWD"));
171 char buf[65];
172 unsigned pwd_len = strlen (pwd);
174 unsigned i = file[0] == '/' ? 1 : 0;
176 if (!i) {
177 memcpy (buf, pwd, pwd_len);
178 memcpy (buf+pwd_len, file+i, file_len-i);
179 buf[pwd_len+file_len-i] = '\0';
180 } else {
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);
192 char buf2[65];
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");
200 return 0;
203 if (vfs->attrib & VFS_FILEATTR_MOUNTED) {
204 partition_t *p = (partition_t *) partition_findbyfile (file);
206 if (p) {
207 i = 0;
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);
213 i ++;
216 return 0;
217 } else {
218 printf ("ERROR -> device not respond\n");
219 return 0;
221 } else {
222 if (vfs->content) {
223 printf ("ERROR -> You can't overwrite content of this file\n");
224 return 1;
227 vfs->content = (vfs_content_t *) kmalloc (sizeof (vfs_content_t));
229 if (!vfs->content)
230 return 1;
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);
240 vfs->content = 0;
241 return 0;
244 memcpy (vfs->content->ptr, data, len);
245 vfs->content->ptr[len] = '\0';*/
247 vfs->content->ptr = data;
249 vfs->content->len = len;
252 return 1;
255 return 0;
258 extern unsigned long file_cache_id;
259 int vfs_read (char *file, unsigned file_len)
261 vfs_t *vfs;
263 char pwd[64];
264 strcpy (pwd, (char *) env_get ("PWD"));
266 char buf[65];
267 unsigned pwd_len = strlen (pwd);
269 char *block;
270 unsigned long len;
272 unsigned i = file[0] == '/' ? 1 : 0;
274 if (!i) {
275 memcpy (buf, pwd, pwd_len);
276 memcpy (buf+pwd_len, file+i, file_len-i);
277 buf[pwd_len+file_len-i] = '\0';
278 } else {
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);
290 char buf2[128];
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");
298 return -1;
301 if (vfs->attrib & VFS_FILEATTR_MOUNTED) {
302 partition_t *p = (partition_t *) partition_findbyfile (file);
304 if (p) {
305 i = 0;
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);
311 return i;
314 i ++;
316 } else {
317 printf ("ERROR -> device not respond\n");
318 return -1;
320 } else {
321 if (vfs->attrib & VFS_FILEATTR_DEVICE && !(vfs->attrib & VFS_FILEATTR_READ)) {
322 file_cache_id = 0;
323 printf ("ERROR -> This file is non-char or non-block device\n");
324 return 0;
327 if (!vfs->content) {
328 printf ("ERROR -> This file not contain a valid data\n");
329 return -1;
332 file_cache = vfs->content->ptr;
333 file_cache_id = vfs->content->len;
335 return 0;
338 file_cache_id = 0;
340 return -1;
344 file_cache_id = 0;
346 return -2;
349 bool vfs_cat (char *file, unsigned file_len)
351 unsigned long i;
352 int index;
354 index = vfs_read (file, file_len);
356 if (index == -1)
357 return 0;
359 for (i = 0; i < file_cache_id; i ++)
360 tty_putch (file_cache[i]);
362 return 1;
365 bool vfs_ls (char *file, unsigned file_len)
367 char ls[64];
369 vfs_t *vfs;
370 bool res = false;
372 if (!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);
377 res = true;
379 } else {
380 if (!strncmp(file,"/",1)) {
381 strcpy (ls,file);
382 } else {
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);
395 res = true;
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);*/
407 if (res)
408 printf ("\n");
410 return 1;
413 bool vfs_cd (char *file, unsigned file_len)
415 /* go back */
416 if (!strcmp (file, "..")) {
417 char pwd[64];
418 strcpy (pwd, (char *) env_get ("PWD"));
420 unsigned pwd_len = strlen (pwd);
422 if (!strcmp (pwd, "/"))
423 return 0;
425 /* vymaze kus retezce - az po predposledni / */
426 pwd_len --; // preskoci / na konci retezce
427 while (pwd_len) {
428 pwd_len --;
429 if (pwd[pwd_len] == '/') {
430 pwd[pwd_len+1] = '\0';
431 break;
435 vfs_t *vfs;
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);
442 if (p) {
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")));
449 break;
450 } else {
451 printf ("ERROR -> device not respond\n");
452 return 0;
457 env_set ("PWD", pwd); // set new directory
459 return 1;
462 /* nothing */
463 if (!strcmp (file, "."))
464 return 1;
466 vfs_t *vfs;
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"));
475 if (p)
476 mount (p, file, "");
480 return 1;
483 /* go to another directory */
484 char pwd[64];
485 strcpy (pwd, (char *) env_get ("PWD"));
487 char buf[65];
488 unsigned pwd_len = strlen (pwd);
490 unsigned i = file[0] == '/' ? 1 : 0;
492 if (!i) {
493 memcpy (buf, pwd, pwd_len);
494 memcpy (buf+pwd_len, file+i, file_len-i);
495 buf[pwd_len+file_len-i] = '\0';
496 } else {
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] == '/')
506 buf[buf_l-1] = '\0';
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);
512 char buf2[65];
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");
520 return 0;
523 // check permissions
524 if (vfs->attrib & VFS_FILEATTR_SYSTEM && strcmp ((char *) env_get ("USER"), "root")) {
525 printf ("ERROR -> only root can do that\n");
526 return 0;
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"));
536 if (p)
537 mount (p, file, pwd);
538 else {
539 printf ("ERROR -> device not respond\n");
540 return 0;
544 env_set ("PWD", pwd);
546 return 1;
550 return 0;
553 bool vfs_mkdir (char *file, unsigned file_len)
555 if (file_len) {
556 char pwd[64];
557 strcpy (pwd, (char *) env_get ("PWD"));
559 partition_t *p = mount_find ((char *) pwd);
561 if (p) {
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);
564 } else {
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");
570 return 1;
573 return 0;
576 bool vfs_touch (char *file, unsigned file_len)
578 if (file_len) {
579 char pwd[64];
580 strcpy (pwd, (char *) env_get ("PWD"));
582 unsigned i;
583 for (i = file_len; i; i --) {
584 if (file[i] == '/') {
585 vfs_cd (file, i);
586 break;
590 char *path = 0;
591 char *f = 0;
593 if (i) {
594 path = (char *) kmalloc (sizeof (char) * (file_len+1));
596 if (!path)
597 return 0;
599 memcpy (path, file, i+1);
600 path[i+1] = '\0';
602 f = file + i + 1;
603 } else {
604 path = (char *) pwd;
605 f = file;
608 partition_t *p = mount_find ((char *) pwd);
610 if (p) {
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));
613 } else {
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");
618 if (i) {
619 kfree (path);
620 vfs_cd (pwd, strlen (pwd));
623 DPRINT ("vfs_touch ()\n");
624 return 1;
627 return 0;
630 int vfs_rm (char *file, unsigned file_len)
632 if (file_len) {
633 char pwd[64];
634 strcpy (pwd, (char *) env_get ("PWD"));
636 unsigned i;
637 for (i = file_len; i; i --) {
638 if (file[i] == '/') {
639 vfs_cd (file, i);
640 break;
644 char *path = 0;
645 char *f = 0;
647 if (i) {
648 path = (char *) kmalloc (sizeof (char) * (file_len+1));
650 if (!path)
651 return 0;
653 memcpy (path, file, i+1);
654 path[i+1] = '\0';
656 f = file + i + 1;
657 } else {
658 path = (char *) pwd;
659 f = file;
662 vfs_t *vfs = vfs_list_find (f, (char *) path);
664 /* file not found */
665 if (!vfs)
666 return -1;
668 if (vfs->attrib & VFS_FILEATTR_SYSTEM || vfs->attrib & VFS_FILEATTR_DIR)
669 return -2;
671 if (vfs->attrib & VFS_FILEATTR_MOUNTED) {
672 partition_t *p = mount_find ((char *) pwd);
674 if (!p)
675 return 0;
677 p->fs->handler (FS_ACT_RM, file, 0, strlen (file));
678 } else {
679 /* delete vfs file with content */
680 vfs_list_del (vfs);
683 if (i) {
684 kfree (path);
685 vfs_cd (pwd, strlen (pwd));
688 DPRINT ("vfs_rm ()\n");
689 return 1;
692 return 0;
695 vfs_dirent_t *vfs_dirent ()
697 char pwd[64];
698 strcpy (pwd, (char *) env_get ("PWD"));
700 vfs_t *vfs;
701 bool res = false;
703 unsigned dirents = 0;
705 for (vfs = vfs_list.next; vfs != &vfs_list; vfs = vfs->next)
706 if (!strcmp (vfs->mountpoint, pwd))
707 dirents ++;
709 if (!dirents)
710 return 0;
712 vfs_dirent_t *dirent = (vfs_dirent_t *) kmalloc (sizeof (vfs_dirent_t) * (dirents+1));
714 if (!dirent)
715 return 0;
717 unsigned i = 0;
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));
723 if (!dirent[i].name)
724 return 0;
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)
733 dirent[i].next = 0;
734 else
735 dirent[i].next = 1;
737 i ++;
740 dirent[dirents].next = 0;
742 return dirent;
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 */
768 smp_cpu_check ();
770 return 1;