Made file data buffer larger (2*PAGE_SIZE); stdlibc: fixed getcwd()
[meinos.git] / apps / lib / libmeinos / devfs.c
blobd861f27608374434f71ab5ed9ad2aff8da2e88ce
1 /*
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 Lesser 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 Lesser General Public License for more details.
15 You should have received a copy of the GNU Lesser General Public License
16 along with this program. If not, see <http://www.gnu.org/licenses/>.
19 #include <sys/types.h>
20 #include <stdlib.h>
21 #include <string.h>
22 #include <rpc.h>
23 #include <stdio.h>
24 #include <sys/shm.h>
25 #include <llist.h>
26 #include <errno.h>
28 #include <devfs.h>
30 static llist_t devlist;
32 /**
33 * Gets list index by DevID
34 * @param devid DevID
35 * @return List index
37 static int getlidx_id(int devid) {
38 devfs_dev_t *dev;
39 int i;
40 for (i=0;(dev = llist_get(devlist,i));i++) {
41 if (dev->id==devid) return i;
43 return -1;
46 /**
47 * Reads from device
48 * @param devid DevID
49 * @param data Buffer
50 * @return How many bytes read (-Errorcode)
52 static int devfs_read(int devid,size_t size,off_t offset) {
53 devfs_dev_t *dev = llist_get(devlist,getlidx_id(devid));
54 if (dev->func_read!=NULL) return dev->func_read(dev,dev->shmbuf,size,offset);
55 else return -ENOSYS;
58 /**
59 * Writes to device
60 * @param devid DevID
61 * @param data Buffer
62 * @return How many bytes written (-Errorcode)
64 static int devfs_write(int devid,size_t size,off_t offset) {
65 devfs_dev_t *dev = llist_get(devlist,getlidx_id(devid));
66 if (dev->func_write!=NULL) return dev->func_write(dev,dev->shmbuf,size,offset);
67 else return -ENOSYS;
71 #define devfs_func_create(func,synopsis,bufsize) _devfs_func_create(__STRING(func),func,synopsis,bufsize,pid)
72 static int _devfs_func_create(char *name,void *func,char *synopsis,size_t bufsize,pid_t pid) {
73 char *rpc;
74 asprintf(&rpc,"%s_%x",name,pid);
75 int ret = rpc_func_create(rpc,func,synopsis,bufsize);
76 free(rpc);
77 return ret;
80 /**
81 * Initializes DevFS
83 void devfs_init() {
84 pid_t pid = getpid();
85 devlist = llist_create();
86 devfs_func_create(devfs_read,"iii",sizeof(int)*3);
87 devfs_func_create(devfs_write,"iii",sizeof(int)*3);
90 /**
91 * Creates an device
92 * @param _name Name of the device
93 * @return Device
95 devfs_dev_t *devfs_createdev(const char *name) {
96 int shmid = shmget(IPC_PRIVATE,DEVFS_BUFSIZE,0);
97 if (shmid!=-1) {
98 int id = rpc_call("devfs_createdev",0,name,shmid);
99 if (id>=0) {
100 devfs_dev_t *new = malloc(0*sizeof(devfs_dev_t));
101 new->name = strdup(name);
102 new->id = id;
103 new->shmid = shmid;
104 new->shmbuf = shmat(shmid,NULL,0);
105 new->func_read = NULL;
106 new->func_write = NULL;
107 llist_push(devlist,new);
108 return new;
110 else shmctl(shmid,IPC_RMID,NULL);
112 return NULL;
116 * Removes an device
117 * @param dev Device to remove
119 int devfs_removedev(devfs_dev_t *dev) {
120 int res = rpc_call("devfs_removedev",0,dev->id);
121 if (res>=0) {
122 llist_remove(devlist,getlidx_id(dev->id));
123 shmdt(dev->shmbuf);
124 shmctl(dev->shmid,IPC_RMID,NULL);
125 free(dev->name);
126 free(dev);
128 return res;