source: mainline/uspace/lib/libfs/libfs.c@ 253227a

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

fix typo

  • Property mode set to 100644
File size: 8.8 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 */
[f2ec8c8]137void libfs_lookup(libfs_ops_t *ops, fs_handle_t fs_handle, ipc_callid_t rid,
[2c448fb]138 ipc_call_t *request)
139{
140 unsigned next = IPC_GET_ARG1(*request);
141 unsigned last = IPC_GET_ARG2(*request);
[f2ec8c8]142 dev_handle_t dev_handle = IPC_GET_ARG3(*request);
[2c448fb]143 int lflag = IPC_GET_ARG4(*request);
[f2ec8c8]144 fs_index_t index = IPC_GET_ARG5(*request); /* when L_LINK specified */
[c9f6e49f]145 char component[NAME_MAX + 1];
146 int len;
[2c448fb]147
148 if (last < next)
149 last += PLB_SIZE;
150
[7b6d98b]151 void *par = NULL;
[74ea3c6]152 void *cur = ops->root_get(dev_handle);
[06901c6b]153 void *tmp = NULL;
[2c448fb]154
155 if (ops->plb_get_char(next) == '/')
156 next++; /* eat slash */
157
[92f9baca]158 while (next <= last && ops->has_children(cur)) {
[2c448fb]159 /* collect the component */
[c9f6e49f]160 len = 0;
[fa832eb]161 while ((next <= last) && (ops->plb_get_char(next) != '/')) {
[2c448fb]162 if (len + 1 == NAME_MAX) {
[abb2865]163 /* component length overflow */
[2c448fb]164 ipc_answer_0(rid, ENAMETOOLONG);
[06901c6b]165 goto out;
[2c448fb]166 }
167 component[len++] = ops->plb_get_char(next);
168 next++; /* process next character */
169 }
170
171 assert(len);
172 component[len] = '\0';
173 next++; /* eat slash */
174
175 /* match the component */
[736c164]176 tmp = ops->match(cur, component);
[2c448fb]177
178 /* handle miss: match amongst siblings */
179 if (!tmp) {
[a8e9ab8d]180 if (next <= last) {
181 /* there are unprocessed components */
182 ipc_answer_0(rid, ENOENT);
[06901c6b]183 goto out;
[a8e9ab8d]184 }
185 /* miss in the last component */
186 if (lflag & (L_CREATE | L_LINK)) {
187 /* request to create a new link */
[2c448fb]188 if (!ops->is_directory(cur)) {
189 ipc_answer_0(rid, ENOTDIR);
[06901c6b]190 goto out;
[a8e9ab8d]191 }
192 void *nodep;
193 if (lflag & L_CREATE)
194 nodep = ops->create(lflag);
195 else
[94b0b63]196 nodep = ops->node_get(dev_handle,
[34f62f8]197 index);
[2c448fb]198 if (nodep) {
199 if (!ops->link(cur, nodep, component)) {
[92f9baca]200 if (lflag & L_CREATE) {
201 (void)ops->destroy(
202 nodep);
203 }
[2c448fb]204 ipc_answer_0(rid, ENOSPC);
205 } else {
206 ipc_answer_5(rid, EOK,
207 fs_handle, dev_handle,
[a8e9ab8d]208 ops->index_get(nodep),
209 ops->size_get(nodep),
[2c448fb]210 ops->lnkcnt_get(nodep));
[06901c6b]211 ops->node_put(nodep);
[2c448fb]212 }
213 } else {
214 ipc_answer_0(rid, ENOSPC);
215 }
[06901c6b]216 goto out;
[a8e9ab8d]217 } else if (lflag & L_PARENT) {
218 /* return parent */
219 ipc_answer_5(rid, EOK, fs_handle, dev_handle,
220 ops->index_get(cur), ops->size_get(cur),
221 ops->lnkcnt_get(cur));
222 }
[2c448fb]223 ipc_answer_0(rid, ENOENT);
[06901c6b]224 goto out;
[2c448fb]225 }
226
[06901c6b]227 if (par)
228 ops->node_put(par);
229
[2c448fb]230 /* descend one level */
[7b6d98b]231 par = cur;
[2c448fb]232 cur = tmp;
[06901c6b]233 tmp = NULL;
[2c448fb]234 }
235
236 /* handle miss: excessive components */
[92f9baca]237 if (next <= last && !ops->has_children(cur)) {
[a8e9ab8d]238 if (lflag & (L_CREATE | L_LINK)) {
[2c448fb]239 if (!ops->is_directory(cur)) {
240 ipc_answer_0(rid, ENOTDIR);
[06901c6b]241 goto out;
[2c448fb]242 }
243
244 /* collect next component */
[c9f6e49f]245 len = 0;
[2c448fb]246 while (next <= last) {
247 if (ops->plb_get_char(next) == '/') {
248 /* more than one component */
249 ipc_answer_0(rid, ENOENT);
[06901c6b]250 goto out;
[2c448fb]251 }
252 if (len + 1 == NAME_MAX) {
253 /* component length overflow */
254 ipc_answer_0(rid, ENAMETOOLONG);
[06901c6b]255 goto out;
[2c448fb]256 }
257 component[len++] = ops->plb_get_char(next);
258 next++; /* process next character */
259 }
260 assert(len);
261 component[len] = '\0';
262
[a8e9ab8d]263 void *nodep;
264 if (lflag & L_CREATE)
265 nodep = ops->create(lflag);
266 else
[34f62f8]267 nodep = ops->node_get(dev_handle, index);
[2c448fb]268 if (nodep) {
269 if (!ops->link(cur, nodep, component)) {
[a8e9ab8d]270 if (lflag & L_CREATE)
[80e8482]271 (void)ops->destroy(nodep);
[2c448fb]272 ipc_answer_0(rid, ENOSPC);
273 } else {
274 ipc_answer_5(rid, EOK,
275 fs_handle, dev_handle,
[a8e9ab8d]276 ops->index_get(nodep),
277 ops->size_get(nodep),
[2c448fb]278 ops->lnkcnt_get(nodep));
[06901c6b]279 ops->node_put(nodep);
[2c448fb]280 }
281 } else {
282 ipc_answer_0(rid, ENOSPC);
283 }
[06901c6b]284 goto out;
[2c448fb]285 }
286 ipc_answer_0(rid, ENOENT);
[06901c6b]287 goto out;
[2c448fb]288 }
289
290 /* handle hit */
[a8e9ab8d]291 if (lflag & L_PARENT) {
[06901c6b]292 ops->node_put(cur);
[a8e9ab8d]293 cur = par;
[06901c6b]294 par = NULL;
[a8e9ab8d]295 if (!cur) {
296 ipc_answer_0(rid, ENOENT);
[06901c6b]297 goto out;
[a8e9ab8d]298 }
299 }
300 if (lflag & L_UNLINK) {
[2c448fb]301 unsigned old_lnkcnt = ops->lnkcnt_get(cur);
[7b6d98b]302 int res = ops->unlink(par, cur);
[2c448fb]303 ipc_answer_5(rid, (ipcarg_t)res, fs_handle, dev_handle,
304 ops->index_get(cur), ops->size_get(cur), old_lnkcnt);
[06901c6b]305 goto out;
[2c448fb]306 }
[a8e9ab8d]307 if (((lflag & (L_CREATE | L_EXCLUSIVE)) == (L_CREATE | L_EXCLUSIVE)) ||
308 (lflag & L_LINK)) {
[2c448fb]309 ipc_answer_0(rid, EEXIST);
[06901c6b]310 goto out;
[2c448fb]311 }
312 if ((lflag & L_FILE) && (ops->is_directory(cur))) {
313 ipc_answer_0(rid, EISDIR);
[06901c6b]314 goto out;
[2c448fb]315 }
316 if ((lflag & L_DIRECTORY) && (ops->is_file(cur))) {
317 ipc_answer_0(rid, ENOTDIR);
[06901c6b]318 goto out;
[2c448fb]319 }
320
321 ipc_answer_5(rid, EOK, fs_handle, dev_handle, ops->index_get(cur),
322 ops->size_get(cur), ops->lnkcnt_get(cur));
[06901c6b]323
324out:
325 if (par)
326 ops->node_put(par);
327 if (cur)
328 ops->node_put(cur);
329 if (tmp)
330 ops->node_put(tmp);
[2c448fb]331}
332
[74303b6]333/** @}
334 */
Note: See TracBrowser for help on using the repository browser.