2 meinOS - A unix-like x86 microkernel operating system
3 Copyright (C) 2008 Janosch Gräf <janosch.graef@gmx.net>
5 This program is free software: you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation, either version 3 of the License, or
8 (at your option) any later version.
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with this program. If not, see <http://www.gnu.org/licenses/>.
19 #include <sys/types.h>
31 enum { DT_CHAR
,DT_BLOCK
} type
;
36 static llist_t devlist
;
39 #define getnew_devid() (nextdevid++)
42 * Gets ListID by DevID
46 static int getlid_devid(int devid
) {
47 struct devlist_item
*dev
;
49 for (i
=0;(dev
= llist_get(devlist
,i
));i
++) {
50 if (dev
->id
==devid
) return i
;
57 * @param name Device name
60 static struct devlist_item
*getdev_name(char *name
) {
61 struct devlist_item
*dev
;
64 for (i
=0;(dev
= llist_get(devlist
,i
));i
++) {
65 if (strcmp(dev
->name
,name
)==0) return dev
;
72 * @param path Path to file
76 static int devfs_open(const char *path
,struct fuse_file_info
*fi
) {
77 struct devlist_item
*dev
= getdev_name((char*)path
+1);
78 if (dev
!=NULL
) return 0;
84 * @param path Path to file
88 static int devfs_close(const char *path
,struct fuse_file_info
*fi
) {
94 * @param path Path to file
95 * @param buf Buffer to store read data in
96 * @param count How many bytes to read
97 * @param offset Offset to start at
99 * @return How many bytes read (-Errorcode)
101 static int devfs_read(const char *path
,char *buf
,size_t count
,off_t offset
,struct fuse_file_info
*fi
) {
102 struct devlist_item
*dev
= getdev_name((char*)path
+1);
104 if (count
>dev
->bufsz
) count
= dev
->bufsz
;
105 //dbgmsg("devfs:\tdevfs_read(%s,0x%x,0x%x,0x%x)\n",path,buf,count,offset);
106 int ret
= rpc_call("devfs_read",RPC_FLAG_SENDTO
,dev
->owner
,dev
->id
,count
,offset
);
107 //dbgmsg("devfs:\tret = 0x%x\n",ret);
108 memcpy(buf
,dev
->shmbuf
,ret
);
116 * @param path Path to file
117 * @param buf Buffer to get data from
118 * @param count How many bytes to write
119 * @param offset Offset to start at
120 * @param fi File info
121 * @return How many bytes written (-Errorcode)
123 static int devfs_write(const char *path
,const char *buf
,size_t count
,off_t offset
,struct fuse_file_info
*fi
) {
124 struct devlist_item
*dev
= getdev_name((char*)path
+1);
126 if (count
>dev
->bufsz
) count
= dev
->bufsz
;
127 memcpy(dev
->shmbuf
,buf
,count
);
128 return rpc_call("devfs_write",RPC_FLAG_SENDTO
,dev
->owner
,dev
->id
,count
,offset
);
135 * @param path Path to dir
136 * @param buf Buffer for dir entries
137 * @param filler Filler function
138 * @param off Dir offset
139 * @param fi File info
140 * @return 0=success (-Errorcode)
142 static int devfs_readdir(const char *path
,void *buf
,fuse_fill_dir_t filler
,off_t off
,struct fuse_file_info
*fi
) {
143 if (strcmp(path
,"/")==0) {
145 struct devlist_item
*dev
;
146 filler(buf
,".",NULL
,0);
147 filler(buf
,"..",NULL
,0);
148 for (i
=0;(dev
= llist_get(devlist
,i
));i
++) filler(buf
,dev
->name
,NULL
,0);
155 * Gets informations about files
156 * @param path Path to file
157 * @param stbuf Buffer to store informations in
158 * @return 0=success (-Errorcode)
160 static int devfs_getattr(const char *path
,struct stat
*stbuf
) {
161 struct devlist_item
*dev
;
162 memset(stbuf
,0,sizeof(struct stat
));
163 if (strcmp(path
,"/") == 0) {
164 stbuf
->st_mode
= S_IFDIR
|0755;
167 else if ((dev
= getdev_name((char*)path
+1))!=NULL
) {
168 stbuf
->st_mode
= (dev
->type
==DT_BLOCK
?S_IFBLK
:S_IFCHR
)|0744;
177 * Creates a new device
178 * @param name Device name
181 static int devfs_createdev(char *name
,int shmid
) {
182 int devid
= getnew_devid();
183 if (devid
>=0 && getdev_name(name
)==NULL
) {
184 struct devlist_item
*new = malloc(sizeof(struct devlist_item
));
185 struct shmid_ds shmid_ds
;
186 shmctl(shmid
,IPC_STAT
,&shmid_ds
);
188 new->name
= strdup(name
);
189 new->owner
= rpc_curpid
;
190 new->shmbuf
= shmat(shmid
,NULL
,0);
191 new->bufsz
= shmid_ds
.shm_segsz
;
192 llist_push(devlist
,new);
196 fprintf(stderr
,"devfs: Could not create device: %s\n",name
);
204 * @return 0=success; -1=failure
206 static int devfs_removedev(int id
) {
207 struct devlist_item
*dev
= llist_get(devlist
,getlid_devid(id
));
208 if (dev
!=NULL
&& dev
->owner
==rpc_curpid
) {
209 llist_remove(devlist
,getlid_devid(id
));
220 * @param argc Number of arguments
221 * @param argv Values of arguments
222 * @return Return value
224 int main(int argc
,char *argv
[]) {
225 devlist
= llist_create();
228 rpc_func(devfs_createdev
,"$ii",NAME_MAX
+sizeof(int));
229 rpc_func(devfs_removedev
,"i",sizeof(int));
231 struct fuse_operations devfs_oper
= {
233 .release
= devfs_close
,
235 .write
= devfs_write
,
236 .readdir
= devfs_readdir
,
237 .getattr
= devfs_getattr
242 char *fake_argv
[2] = { "devfs","/dev" };
243 fuse_main(fake_argc
,fake_argv
,&devfs_oper
,NULL
);