source: mainline/uspace/srv/fs/devfs/devfs_ops.c@ a095d20

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since a095d20 was a095d20, checked in by Martin Decky <martin@…>, 16 years ago

add simple devfs filesystem and mount it as /dev
add generic NULL device "null"

  • Property mode set to 100644
File size: 5.6 KB
Line 
1/*
2 * Copyright (c) 2009 Martin Decky
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 *
9 * - Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * - Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 * - The name of the author may not be used to endorse or promote products
15 * derived from this software without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 */
28
29/** @addtogroup fs
30 * @{
31 */
32
33/**
34 * @file devfs_ops.c
35 * @brief Implementation of VFS operations for the devfs file system server.
36 */
37
38#include <ipc/ipc.h>
39#include <bool.h>
40#include <errno.h>
41#include <malloc.h>
42#include <string.h>
43#include <libfs.h>
44#include "devfs.h"
45#include "devfs_ops.h"
46
47#define PLB_GET_CHAR(pos) (devfs_reg.plb_ro[pos % PLB_SIZE])
48
49bool devfs_init(void)
50{
51 if (devmap_get_phone(DEVMAP_CLIENT, IPC_FLAG_BLOCKING) < 0)
52 return false;
53
54 return true;
55}
56
57void devfs_mounted(ipc_callid_t rid, ipc_call_t *request)
58{
59 /* Accept the mount options */
60 ipc_callid_t callid;
61 size_t size;
62 if (!ipc_data_write_receive(&callid, &size)) {
63 ipc_answer_0(callid, EINVAL);
64 ipc_answer_0(rid, EINVAL);
65 return;
66 }
67
68 char *opts = malloc(size + 1);
69 if (!opts) {
70 ipc_answer_0(callid, ENOMEM);
71 ipc_answer_0(rid, ENOMEM);
72 return;
73 }
74
75 ipcarg_t retval = ipc_data_write_finalize(callid, opts, size);
76 if (retval != EOK) {
77 ipc_answer_0(rid, retval);
78 free(opts);
79 return;
80 }
81
82 free(opts);
83
84 ipc_answer_3(rid, EOK, 0, 0, 0);
85}
86
87void devfs_mount(ipc_callid_t rid, ipc_call_t *request)
88{
89 ipc_answer_0(rid, ENOTSUP);
90}
91
92void devfs_lookup(ipc_callid_t rid, ipc_call_t *request)
93{
94 ipcarg_t first = IPC_GET_ARG1(*request);
95 ipcarg_t last = IPC_GET_ARG2(*request);
96 dev_handle_t dev_handle = IPC_GET_ARG3(*request);
97 ipcarg_t lflag = IPC_GET_ARG4(*request);
98 fs_index_t index = IPC_GET_ARG5(*request);
99
100 /* Hierarchy is flat, no altroot is supported */
101 if (index != 0) {
102 ipc_answer_0(rid, ENOENT);
103 return;
104 }
105
106 /* This is a read-only filesystem */
107 if ((lflag & L_CREATE) || (lflag & L_LINK) || (lflag & L_UNLINK)) {
108 ipc_answer_0(rid, ENOTSUP);
109 return;
110 }
111
112 /* Eat slash */
113 if (PLB_GET_CHAR(first) == '/') {
114 first++;
115 first %= PLB_SIZE;
116 }
117
118 if (first >= last) {
119 /* Root entry */
120 if (lflag & L_DIRECTORY)
121 ipc_answer_5(rid, EOK, devfs_reg.fs_handle, dev_handle, 0, 0, 0);
122 else
123 ipc_answer_0(rid, ENOENT);
124 } else {
125 if (lflag & L_FILE) {
126 count_t len;
127 if (last >= first)
128 len = last - first + 1;
129 else
130 len = first + PLB_SIZE - last + 1;
131
132 char *name = (char *) malloc(len + 1);
133 if (name == NULL) {
134 ipc_answer_0(rid, ENOMEM);
135 return;
136 }
137
138 count_t i;
139 for (i = 0; i < len; i++)
140 name[i] = PLB_GET_CHAR(first + i);
141
142 name[len] = 0;
143
144 dev_handle_t handle;
145 if (devmap_device_get_handle(name, &handle, 0) != EOK) {
146 free(name);
147 ipc_answer_0(rid, ENOENT);
148 return;
149 }
150
151 free(name);
152
153 ipc_answer_5(rid, EOK, devfs_reg.fs_handle, dev_handle, handle, 0, 1);
154 } else
155 ipc_answer_0(rid, ENOENT);
156 }
157}
158
159void devfs_read(ipc_callid_t rid, ipc_call_t *request)
160{
161 fs_index_t index = (fs_index_t) IPC_GET_ARG2(*request);
162 off_t pos = (off_t) IPC_GET_ARG3(*request);
163
164 if (index != 0) {
165 ipc_answer_1(rid, ENOENT, 0);
166 return;
167 }
168
169 /*
170 * Receive the read request.
171 */
172 ipc_callid_t callid;
173 size_t size;
174 if (!ipc_data_read_receive(&callid, &size)) {
175 ipc_answer_0(callid, EINVAL);
176 ipc_answer_0(rid, EINVAL);
177 return;
178 }
179
180 size_t bytes = 0;
181 if (index != 0) {
182 (void) ipc_data_read_finalize(callid, NULL, bytes);
183 } else {
184 count_t count = devmap_device_get_count();
185 dev_desc_t *desc = malloc(count * sizeof(dev_desc_t));
186 if (desc == NULL) {
187 ipc_answer_0(callid, ENOENT);
188 ipc_answer_1(rid, ENOENT, 0);
189 return;
190 }
191
192 count_t max = devmap_device_get_devices(count, desc);
193
194 if (pos < max) {
195 ipc_data_read_finalize(callid, desc[pos].name, str_size(desc[pos].name) + 1);
196 } else {
197 ipc_answer_0(callid, ENOENT);
198 ipc_answer_1(rid, ENOENT, 0);
199 return;
200 }
201
202 free(desc);
203 bytes = 1;
204 }
205
206 ipc_answer_1(rid, EOK, bytes);
207}
208
209void devfs_write(ipc_callid_t rid, ipc_call_t *request)
210{
211 fs_index_t index = (fs_index_t) IPC_GET_ARG2(*request);
212 off_t pos = (off_t) IPC_GET_ARG3(*request);
213
214 /*
215 * Receive the write request.
216 */
217 ipc_callid_t callid;
218 size_t size;
219 if (!ipc_data_write_receive(&callid, &size)) {
220 ipc_answer_0(callid, EINVAL);
221 ipc_answer_0(rid, EINVAL);
222 return;
223 }
224
225 // TODO
226 ipc_answer_0(callid, ENOENT);
227 ipc_answer_2(rid, ENOENT, 0, 0);
228}
229
230void devfs_truncate(ipc_callid_t rid, ipc_call_t *request)
231{
232 ipc_answer_0(rid, ENOTSUP);
233}
234
235void devfs_destroy(ipc_callid_t rid, ipc_call_t *request)
236{
237 ipc_answer_0(rid, ENOTSUP);
238}
239
240/**
241 * @}
242 */
Note: See TracBrowser for help on using the repository browser.