File mode stored in i_mode
[akaros.git] / kern / src / devfs.c
1 /* Copyright (c) 2010 The Regents of the University of California
2  * Barret Rhoden <brho@cs.berkeley.edu>
3  * See LICENSE for details.
4  *
5  * Devfs: filesystem interfaces to devices.  For now, we just create the
6  * needed/discovered devices in KFS in its /dev/ folder, and only do this for
7  * stdin and stdout. */
8
9 #include <devfs.h>
10 #include <kfs.h>
11 #include <error.h>
12 #include <syscall.h>
13 #include <process.h>
14 #include <smp.h>
15 #include <umem.h>
16
17 /* These structs are declared again and initialized farther down */
18 struct file_operations dev_f_op_stdin;
19 struct file_operations dev_f_op_stdout;
20
21 struct file *dev_stdin, *dev_stdout, *dev_stderr;
22
23 /* Helper to build stdin, stdout, and stderr */
24 static struct file *get_stdinout(char *name, int mode,
25                                  struct file_operations *fop)
26 {
27         struct file *f_char_dev = do_file_open(name, O_CREAT, mode);
28         assert(f_char_dev);
29         /* Overwrite the f_op with our own f_ops */
30         f_char_dev->f_dentry->d_inode->i_fop = fop;
31         f_char_dev->f_op = fop;
32         SET_FTYPE(f_char_dev->f_dentry->d_inode->i_mode, __S_IFCHR);
33         return f_char_dev;
34 }
35
36 void devfs_init(void)
37 {
38         int mode;
39         /* Make sure there is a dev directory */
40         struct dentry *dentry = lookup_dentry("/dev/", 0);      
41         if (!dentry) {
42                 assert(!do_mkdir("/dev/", S_IRWXU | S_IRWXG | S_IRWXO));
43         } else {
44                 kref_put(&dentry->d_kref);
45         }
46         /* Notice we don't kref_put().  We're storing the refs globally */
47         dev_stdin = get_stdinout("/dev/stdin", S_IRUSR | S_IRGRP | S_IROTH,
48                                  &dev_f_op_stdin);
49         dev_stdout = get_stdinout("/dev/stdout", S_IWUSR | S_IWGRP | S_IWOTH,
50                                   &dev_f_op_stdout);
51         /* Note stderr uses the same f_op as stdout */
52         dev_stderr = get_stdinout("/dev/stderr", S_IWUSR | S_IWGRP | S_IWOTH,
53                                   &dev_f_op_stdout);
54 }
55
56 /* We provide a separate set of f_ops and pm_ops for devices (char for now), and
57  * this is the only thing that differs from the regular KFS.  We need to do some
58  * ghetto-overriding of these ops after we create them. */
59
60 off_t dev_c_llseek(struct file *file, off_t offset, int whence)
61 {
62         set_errno(EINVAL);
63         return -1;
64 }
65
66 ssize_t dev_stdin_read(struct file *file, char *buf, size_t count,
67                        off_t *offset)
68 {
69         printk("[kernel] Tried to read %d bytes from stdin\n", count);
70         return -1;
71 }
72
73 ssize_t dev_stdout_write(struct file *file, const char *buf, size_t count,
74                          off_t *offset)
75 {
76         char *t_buf;
77         struct proc *p = current;
78         if (p)
79                 t_buf = user_strdup_errno(p, buf, count);
80         else
81                 t_buf = (char*)buf;
82         if (!t_buf)
83                 return -1;
84         printk("%s", t_buf);
85         return count;
86 }
87
88 /* we don't allow mmapping of any device file */
89 int dev_mmap(struct file *file, struct vm_region *vmr)
90 {
91         set_errno(EINVAL);
92         return -1;
93 }
94
95 /* Character device file ops */
96 struct file_operations dev_f_op_stdin = {
97         dev_c_llseek,
98         dev_stdin_read,
99         0,      /* write - can't write to stdin */
100         kfs_readdir,    /* this will fail gracefully */
101         dev_mmap,
102         kfs_open,
103         kfs_flush,
104         kfs_release,
105         0,      /* fsync - makes no sense */
106         kfs_poll,
107         0,      /* readv */
108         0,      /* writev */
109         kfs_sendpage,
110         kfs_check_flags,
111 };
112
113 struct file_operations dev_f_op_stdout = {
114         dev_c_llseek,
115         0,      /* read - can't read stdout */
116         dev_stdout_write,
117         kfs_readdir,    /* this will fail gracefully */
118         dev_mmap,
119         kfs_open,
120         kfs_flush,
121         kfs_release,
122         0,      /* fsync - makes no sense */
123         kfs_poll,
124         0,      /* readv */
125         0,      /* writev */
126         kfs_sendpage,
127         kfs_check_flags,
128 };