source: mainline/uspace/lib/libfs/libfs.c@ 7b6d98b

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since 7b6d98b was 7b6d98b, checked in by Jakub Jermar <jakub@…>, 17 years ago

No need to keep the parent pointer in the TMPFS node. Moreover, other file
systems won't have it either. Finally, if TMPFS is to support hardlinks, there
can be multiple parents.

  • Property mode set to 100644
File size: 7.7 KB
RevLine 
[74303b6]1/*
[2c448fb]2 * Copyright (c) 2008 Jakub Jermar
[74303b6]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 libfs
30 * @{
31 */
32/**
33 * @file
34 * Glue code which is commonod to all FS implementations.
35 */
36
37#include "libfs.h"
[efd4a72]38#include "../../srv/vfs/vfs.h"
39#include <errno.h>
40#include <async.h>
41#include <ipc/ipc.h>
42#include <as.h>
[2c448fb]43#include <assert.h>
44#include <dirent.h>
[efd4a72]45
46/** Register file system server.
47 *
48 * This function abstracts away the tedious registration protocol from
49 * file system implementations and lets them to reuse this registration glue
50 * code.
51 *
52 * @param vfs_phone Open phone for communication with VFS.
53 * @param reg File system registration structure. It will be
54 * initialized by this function.
55 * @param info VFS info structure supplied by the file system
56 * implementation.
57 * @param conn Connection fibril for handling all calls originating in
58 * VFS.
59 *
60 * @return EOK on success or a non-zero error code on errror.
61 */
62int fs_register(int vfs_phone, fs_reg_t *reg, vfs_info_t *info,
63 async_client_conn_t conn)
64{
65 /*
66 * Tell VFS that we are here and want to get registered.
67 * We use the async framework because VFS will answer the request
68 * out-of-order, when it knows that the operation succeeded or failed.
69 */
70 ipc_call_t answer;
71 aid_t req = async_send_0(vfs_phone, VFS_REGISTER, &answer);
72
73 /*
74 * Send our VFS info structure to VFS.
75 */
[215e375]76 int rc = ipc_data_write_start(vfs_phone, info, sizeof(*info));
[efd4a72]77 if (rc != EOK) {
78 async_wait_for(req, NULL);
79 return rc;
80 }
81
82 /*
83 * Ask VFS for callback connection.
84 */
85 ipc_connect_to_me(vfs_phone, 0, 0, 0, &reg->vfs_phonehash);
86
87 /*
88 * Allocate piece of address space for PLB.
89 */
90 reg->plb_ro = as_get_mappable_page(PLB_SIZE);
91 if (!reg->plb_ro) {
92 async_wait_for(req, NULL);
93 return ENOMEM;
94 }
95
96 /*
97 * Request sharing the Path Lookup Buffer with VFS.
98 */
[215e375]99 rc = ipc_share_in_start_0_0(vfs_phone, reg->plb_ro, PLB_SIZE);
[efd4a72]100 if (rc) {
101 async_wait_for(req, NULL);
102 return rc;
103 }
104
105 /*
106 * Pick up the answer for the request to the VFS_REQUEST call.
107 */
108 async_wait_for(req, NULL);
109 reg->fs_handle = (int) IPC_GET_ARG1(answer);
110
111 /*
112 * Create a connection fibril to handle the callback connection.
113 */
114 async_new_connection(reg->vfs_phonehash, 0, NULL, conn);
115
116 /*
117 * Tell the async framework that other connections are to be handled by
118 * the same connection fibril as well.
119 */
120 async_set_client_connection(conn);
121
122 return IPC_GET_RETVAL(answer);
123}
[74303b6]124
[1e50f81]125/** Lookup VFS triplet by name in the file system name space.
[9bb85f3]126 *
127 * The path passed in the PLB must be in the canonical file system path format
128 * as returned by the canonify() function.
[1e50f81]129 *
130 * @param ops libfs operations structure with function pointers to
131 * file system implementation
132 * @param fs_handle File system handle of the file system where to perform
133 * the lookup.
134 * @param rid Request ID of the VFS_LOOKUP request.
135 * @param request VFS_LOOKUP request data itself.
136 */
[2c448fb]137void libfs_lookup(libfs_ops_t *ops, int fs_handle, ipc_callid_t rid,
138 ipc_call_t *request)
139{
140 unsigned next = IPC_GET_ARG1(*request);
141 unsigned last = IPC_GET_ARG2(*request);
142 int dev_handle = IPC_GET_ARG3(*request);
143 int lflag = IPC_GET_ARG4(*request);
144
145 if (last < next)
146 last += PLB_SIZE;
147
[7b6d98b]148 void *par = NULL;
[2c448fb]149 void *cur = ops->root_get();
150 void *tmp = ops->child_get(cur);
151
152 if (ops->plb_get_char(next) == '/')
153 next++; /* eat slash */
154
155 char component[NAME_MAX + 1];
156 int len = 0;
157 while (tmp && next <= last) {
158
159 /* collect the component */
160 if (ops->plb_get_char(next) != '/') {
161 if (len + 1 == NAME_MAX) {
162 /* comopnent length overflow */
163 ipc_answer_0(rid, ENAMETOOLONG);
164 return;
165 }
166 component[len++] = ops->plb_get_char(next);
167 next++; /* process next character */
168 if (next <= last)
169 continue;
170 }
171
172 assert(len);
173 component[len] = '\0';
174 next++; /* eat slash */
175 len = 0;
176
177 /* match the component */
178 while (tmp && !ops->match(tmp, component))
179 tmp = ops->sibling_get(tmp);
180
181 /* handle miss: match amongst siblings */
182 if (!tmp) {
183 if ((next > last) && (lflag & L_CREATE)) {
184 /* no components left and L_CREATE specified */
185 if (!ops->is_directory(cur)) {
186 ipc_answer_0(rid, ENOTDIR);
187 return;
188 }
189 void *nodep = ops->create(lflag);
190 if (nodep) {
191 if (!ops->link(cur, nodep, component)) {
192 ops->destroy(nodep);
193 ipc_answer_0(rid, ENOSPC);
194 } else {
195 ipc_answer_5(rid, EOK,
196 fs_handle, dev_handle,
197 ops->index_get(nodep), 0,
198 ops->lnkcnt_get(nodep));
199 }
200 } else {
201 ipc_answer_0(rid, ENOSPC);
202 }
203 return;
204 }
205 ipc_answer_0(rid, ENOENT);
206 return;
207 }
208
209 /* descend one level */
[7b6d98b]210 par = cur;
[2c448fb]211 cur = tmp;
212 tmp = ops->child_get(tmp);
213 }
214
215 /* handle miss: excessive components */
216 if (!tmp && next <= last) {
217 if (lflag & L_CREATE) {
218 if (!ops->is_directory(cur)) {
219 ipc_answer_0(rid, ENOTDIR);
220 return;
221 }
222
223 /* collect next component */
224 while (next <= last) {
225 if (ops->plb_get_char(next) == '/') {
226 /* more than one component */
227 ipc_answer_0(rid, ENOENT);
228 return;
229 }
230 if (len + 1 == NAME_MAX) {
231 /* component length overflow */
232 ipc_answer_0(rid, ENAMETOOLONG);
233 return;
234 }
235 component[len++] = ops->plb_get_char(next);
236 next++; /* process next character */
237 }
238 assert(len);
239 component[len] = '\0';
240 len = 0;
241
242 void *nodep = ops->create(lflag);
243 if (nodep) {
244 if (!ops->link(cur, nodep, component)) {
245 ops->destroy(nodep);
246 ipc_answer_0(rid, ENOSPC);
247 } else {
248 ipc_answer_5(rid, EOK,
249 fs_handle, dev_handle,
250 ops->index_get(nodep), 0,
251 ops->lnkcnt_get(nodep));
252 }
253 } else {
254 ipc_answer_0(rid, ENOSPC);
255 }
256 return;
257 }
258 ipc_answer_0(rid, ENOENT);
259 return;
260 }
261
262 /* handle hit */
263 if (lflag & L_DESTROY) {
264 unsigned old_lnkcnt = ops->lnkcnt_get(cur);
[7b6d98b]265 int res = ops->unlink(par, cur);
[2c448fb]266 ipc_answer_5(rid, (ipcarg_t)res, fs_handle, dev_handle,
267 ops->index_get(cur), ops->size_get(cur), old_lnkcnt);
268 return;
269 }
270 if ((lflag & (L_CREATE | L_EXCLUSIVE)) == (L_CREATE | L_EXCLUSIVE)) {
271 ipc_answer_0(rid, EEXIST);
272 return;
273 }
274 if ((lflag & L_FILE) && (ops->is_directory(cur))) {
275 ipc_answer_0(rid, EISDIR);
276 return;
277 }
278 if ((lflag & L_DIRECTORY) && (ops->is_file(cur))) {
279 ipc_answer_0(rid, ENOTDIR);
280 return;
281 }
282
283 ipc_answer_5(rid, EOK, fs_handle, dev_handle, ops->index_get(cur),
284 ops->size_get(cur), ops->lnkcnt_get(cur));
285}
286
[74303b6]287/** @}
288 */
Note: See TracBrowser for help on using the repository browser.