source: mainline/uspace/srv/fs/tmpfs/tmpfs_ops.c@ 4b11571

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

TMPFS work.
VFS_LOOKUP implemented.

  • Property mode set to 100644
File size: 5.8 KB
Line 
1/*
2 * Copyright (c) 2007 Jakub Jermar
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 tmpfs_ops.c
35 * @brief Implementation of VFS operations for the TMPFS file system
36 * server.
37 */
38
39#include "tmpfs.h"
40#include "../../vfs/vfs.h"
41#include <ipc/ipc.h>
42#include <async.h>
43#include <errno.h>
44#include <atomic.h>
45#include <stdlib.h>
46#include <string.h>
47#include <stdio.h>
48
49#define PLB_GET_CHAR(i) (tmpfs_reg.plb_ro[(i) % PLB_SIZE])
50
51unsigned tmpfs_next_index = 1;
52
53static void tmpfs_dentry_initialize(tmpfs_dentry_t *dentry)
54{
55 dentry->index = 0;
56 dentry->parent = NULL;
57 dentry->sibling = NULL;
58 dentry->child = NULL;
59 dentry->name = NULL;
60 dentry->type = TMPFS_NONE;
61 dentry->size = 0;
62 dentry->data = NULL;
63}
64
65/*
66 * For now, we don't distinguish between different dev_handles/instances. All
67 * requests resolve to the only instance, rooted in the following variable.
68 */
69static tmpfs_dentry_t *root;
70
71static bool tmpfs_init(void)
72{
73 root = (tmpfs_dentry_t *) malloc(sizeof(tmpfs_dentry_t));
74 if (!root) {
75 return false;
76 }
77 tmpfs_dentry_initialize(root);
78 root->index = tmpfs_next_index++;
79 root->name = "";
80 root->type = TMPFS_DIRECTORY;
81
82 /*
83 * This is only for debugging. Once we can create files and directories
84 * using VFS, we can get rid of this.
85 */
86 tmpfs_dentry_t *d;
87 d = (tmpfs_dentry_t *) malloc(sizeof(tmpfs_dentry_t));
88 if (!d) {
89 free(root);
90 root = NULL;
91 return false;
92 }
93 tmpfs_dentry_initialize(d);
94 d->index = tmpfs_next_index++;
95 root->child = d;
96 d->parent = root;
97 d->type = TMPFS_DIRECTORY;
98 d->name = "dir1";
99
100 d = (tmpfs_dentry_t *) malloc(sizeof(tmpfs_dentry_t));
101 if (!d) {
102 free(root->child);
103 free(root);
104 root = NULL;
105 return false;
106 }
107 tmpfs_dentry_initialize(d);
108 d->index = tmpfs_next_index++;
109 root->child->sibling = d;
110 d->parent = root;
111 d->type = TMPFS_DIRECTORY;
112 d->name = "dir2";
113
114 d = (tmpfs_dentry_t *) malloc(sizeof(tmpfs_dentry_t));
115 if (!d) {
116 free(root->child->sibling);
117 free(root->child);
118 free(root);
119 root = NULL;
120 return false;
121 }
122 tmpfs_dentry_initialize(d);
123 d->index = tmpfs_next_index++;
124 root->child->child = d;
125 d->parent = root->child;
126 d->type = TMPFS_FILE;
127 d->name = "file1";
128 d->data = "This is the contents of /dir1/file1.\n";
129 d->size = strlen(d->data);
130
131 d = (tmpfs_dentry_t *) malloc(sizeof(tmpfs_dentry_t));
132 if (!d) {
133 free(root->child->sibling);
134 free(root->child->child);
135 free(root->child);
136 free(root);
137 root = NULL;
138 return false;
139 }
140 tmpfs_dentry_initialize(d);
141 d->index = tmpfs_next_index++;
142 root->child->sibling->child = d;
143 d->parent = root->child->sibling;
144 d->type = TMPFS_FILE;
145 d->name = "file2";
146 d->data = "This is the contents of /dir2/file2.\n";
147 d->size = strlen(d->data);
148
149 return true;
150}
151
152/** Compare one component of path to a directory entry.
153 *
154 * @param dentry Directory entry to compare the path component with.
155 * @param start Index into PLB where the path component starts.
156 * @param last Index of the last character of the path in PLB.
157 *
158 * @return Zero on failure or delta such that (index + delta) %
159 * PLB_SIZE points to the first unprocessed character in
160 * PLB which comprises the path.
161 */
162static unsigned match_path_component(tmpfs_dentry_t *dentry, unsigned start,
163 unsigned last)
164{
165 int i, j;
166 size_t namelen;
167
168 namelen = strlen(dentry->name);
169
170 if (last < start)
171 last += PLB_SIZE;
172
173 for (i = 0, j = start; i < namelen && j <= last; i++, j++) {
174 if (dentry->name[i] != PLB_GET_CHAR(j))
175 return 0;
176 }
177
178 if (i != namelen)
179 return 0;
180 if (j < last && PLB_GET_CHAR(j) != '/')
181 return 0;
182 if (j == last)
183 return 0;
184
185 return (j - start);
186}
187
188void tmpfs_lookup(ipc_callid_t rid, ipc_call_t *request)
189{
190 unsigned next = IPC_GET_ARG1(*request);
191 unsigned last = IPC_GET_ARG2(*request);
192 int dev_handle = IPC_GET_ARG3(*request);
193
194 if (last < next)
195 last += PLB_SIZE;
196
197 if (!root && !tmpfs_init()) {
198 ipc_answer_0(rid, ENOMEM);
199 return;
200 }
201
202 tmpfs_dentry_t *dtmp = root->child;
203 tmpfs_dentry_t *dcur = root;
204
205 bool hit = true;
206
207 if (PLB_GET_CHAR(next) == '/')
208 next++; /* eat slash */
209
210 while (next <= last) {
211 unsigned delta;
212 hit = false;
213 do {
214 delta = match_path_component(dtmp, next, last);
215 if (!delta) {
216 dtmp = dtmp->sibling;
217 } else {
218 hit = true;
219 next += delta;
220 next++; /* eat slash */
221 dcur = dtmp;
222 dtmp = dtmp->child;
223 }
224 } while (delta == 0 && dtmp);
225 if (!hit) {
226 ipc_answer_3(rid, ENOENT, tmpfs_reg.fs_handle,
227 dev_handle, dcur->index);
228 return;
229 }
230 }
231
232 ipc_answer_3(rid, EOK, tmpfs_reg.fs_handle, dev_handle, dcur->index);
233}
234
235/**
236 * @}
237 */
Note: See TracBrowser for help on using the repository browser.