source: mainline/uspace/srv/fs/fat/fat_ops.c@ e1e3b26

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

Commit progress on the FAT file system server implementation.

  • Property mode set to 100644
File size: 6.8 KB
RevLine 
[be815bc]1/*
[a2aa1dec]2 * Copyright (c) 2008 Jakub Jermar
[be815bc]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 fat_ops.c
35 * @brief Implementation of VFS operations for the FAT file system server.
36 */
37
38#include "fat.h"
[6364d3c]39#include "../../vfs/vfs.h"
[a2aa1dec]40#include <libfs.h>
[be815bc]41#include <ipc/ipc.h>
42#include <async.h>
43#include <errno.h>
[a2aa1dec]44#include <string.h>
[776f2e6]45#include <byteorder.h>
[e1e3b26]46#include <libadt/hash_table.h>
47#include <libadt/list.h>
48#include <assert.h>
49
50/** Hash table of FAT in-core nodes. */
51hash_table_t fin_hash;
52
53/** List of free FAT in-core nodes. */
54link_t ffn_head;
[6364d3c]55
56#define FAT_NAME_LEN 8
57#define FAT_EXT_LEN 3
58
59#define FAT_PAD ' '
60
61#define FAT_DENTRY_UNUSED 0x00
62#define FAT_DENTRY_E5_ESC 0x05
63#define FAT_DENTRY_DOT 0x2e
64#define FAT_DENTRY_ERASED 0xe5
65
[a2aa1dec]66static void dentry_name_canonify(fat_dentry_t *d, char *buf)
67{
68 int i;
69
70 for (i = 0; i < FAT_NAME_LEN; i++) {
71 if (d->name[i] == FAT_PAD) {
72 buf++;
73 break;
74 }
75 if (d->name[i] == FAT_DENTRY_E5_ESC)
76 *buf++ = 0xe5;
77 else
78 *buf++ = d->name[i];
79 }
80 if (d->ext[0] != FAT_PAD)
81 *buf++ = '.';
82 for (i = 0; i < FAT_EXT_LEN; i++) {
83 if (d->ext[i] == FAT_PAD) {
84 *buf = '\0';
85 return;
86 }
87 if (d->ext[i] == FAT_DENTRY_E5_ESC)
88 *buf++ = 0xe5;
89 else
90 *buf++ = d->ext[i];
91 }
92}
93
[79dbc3e]94/* TODO and also move somewhere else */
95typedef struct {
96 void *data;
97} block_t;
98
99static block_t *block_get(dev_handle_t dev_handle, off_t offset)
[a2aa1dec]100{
101 return NULL; /* TODO */
102}
103
[e1e3b26]104static block_t *fat_block_get(dev_handle_t dev_handle, fs_index_t index,
105 off_t offset) {
[79dbc3e]106 return NULL; /* TODO */
107}
108
109static void block_put(block_t *block)
[6364d3c]110{
[a2aa1dec]111 /* TODO */
112}
113
[e1e3b26]114static void fat_node_initialize(fat_node_t *node)
[a2aa1dec]115{
[e1e3b26]116 node->type = 0;
117 node->index = 0;
118 node->pindex = 0;
119 node->dev_handle = 0;
120 link_initialize(&node->fin_link);
121 link_initialize(&node->ffn_link);
122 node->size = 0;
123 node->lnkcnt = 0;
124 node->refcnt = 0;
125 node->dirty = false;
126}
127
128static void fat_sync_node(fat_node_t *node)
129{
130 /* TODO */
131}
132
133static void *
134fat_node_get(dev_handle_t dev_handle, fs_index_t index, fs_index_t pindex)
135{
136 link_t *lnk;
137 fat_node_t *node = NULL;
138 block_t *bb;
139 block_t *b;
140 fat_dentry_t *d;
141 unsigned bps; /* bytes per sector */
142 unsigned dps; /* dentries per sector */
143
144 unsigned long key[] = {
145 dev_handle,
146 index
147 };
148
149 lnk = hash_table_find(&fin_hash, key);
150 if (lnk) {
151 /*
152 * The in-core node was found in the hash table.
153 */
154 node = hash_table_get_instance(lnk, fat_node_t, fin_link);
155 if (!node->refcnt++)
156 list_remove(&node->ffn_link);
157 return (void *) node;
158 }
159
160 if (!list_empty(&ffn_head)) {
161 /*
162 * We are going to reuse a node from the free list.
163 */
164 lnk = ffn_head.next;
165 list_remove(lnk);
166 node = list_get_instance(lnk, fat_node_t, ffn_link);
167 assert(!node->refcnt);
168 if (node->dirty)
169 fat_sync_node(node);
170 } else {
171 /*
172 * We need to allocate a new node.
173 */
174 node = malloc(sizeof(fat_node_t));
175 if (!node)
176 return NULL;
177 }
178 fat_node_initialize(node);
179
180 if (!pindex) {
181
182 } else {
183 }
184
[a2aa1dec]185}
186
[79dbc3e]187#define BS_BLOCK 0
188
[a2aa1dec]189static void *fat_match(void *prnt, const char *component)
190{
191 fat_node_t *parentp = (fat_node_t *)prnt;
192 char name[FAT_NAME_LEN + 1 + FAT_EXT_LEN + 1];
[79dbc3e]193 unsigned i, j;
[5446bee0]194 unsigned bps; /* bytes per sector */
[79dbc3e]195 unsigned dps; /* dentries per sector */
196 unsigned blocks;
[a2aa1dec]197 fat_dentry_t *d;
[79dbc3e]198 block_t *bb;
199 block_t *b;
200
201 bb = block_get(parentp->dev_handle, BS_BLOCK);
202 if (!bb)
203 return NULL;
[5446bee0]204 bps = uint16_t_le2host(((fat_bs_t *)bb->data)->bps);
[79dbc3e]205 block_put(bb);
[5446bee0]206 dps = bps / sizeof(fat_dentry_t);
207 blocks = parentp->size / bps + (parentp->size % bps != 0);
[79dbc3e]208 for (i = 0; i < blocks; i++) {
209 unsigned dentries;
210
[e1e3b26]211 b = fat_block_get(parentp->dev_handle, parentp->index, i);
[79dbc3e]212 if (!b)
213 return NULL;
214
215 dentries = (i == blocks - 1) ?
216 parentp->size % sizeof(fat_dentry_t) :
217 dps;
218 for (j = 0; j < dentries; j++) {
219 d = ((fat_dentry_t *)b->data) + j;
220 if (d->attr & FAT_ATTR_VOLLABEL) {
221 /* volume label entry */
222 continue;
223 }
224 if (d->name[0] == FAT_DENTRY_ERASED) {
225 /* not-currently-used entry */
226 continue;
227 }
228 if (d->name[0] == FAT_DENTRY_UNUSED) {
229 /* never used entry */
230 block_put(b);
231 return NULL;
232 }
233 if (d->name[0] == FAT_DENTRY_DOT) {
234 /*
235 * Most likely '.' or '..'.
236 * It cannot occur in a regular file name.
237 */
238 continue;
239 }
[a2aa1dec]240
[79dbc3e]241 dentry_name_canonify(d, name);
242 if (strcmp(name, component) == 0) {
243 /* hit */
244 void *node = fat_node_get(parentp->dev_handle,
[e1e3b26]245 (fs_index_t)uint16_t_le2host(d->firstc),
246 parentp->index);
[79dbc3e]247 block_put(b);
248 return node;
249 }
[9119d25]250 }
[79dbc3e]251 block_put(b);
[9119d25]252 }
[a2aa1dec]253
254 return NULL;
[6364d3c]255}
256
[e1e3b26]257static fs_index_t fat_index_get(void *node)
258{
259 fat_node_t *fnodep = (fat_node_t *)node;
260 if (!fnodep)
261 return 0;
262 return fnodep->index;
263}
264
265static size_t fat_size_get(void *node)
266{
267 return ((fat_node_t *)node)->size;
268}
269
270static unsigned fat_lnkcnt_get(void *node)
271{
272 return ((fat_node_t *)node)->lnkcnt;
273}
274
275static bool fat_is_directory(void *node)
276{
277 return ((fat_node_t *)node)->type == FAT_DIRECTORY;
278}
279
280static bool fat_is_file(void *node)
281{
282 return ((fat_node_t *)node)->type == FAT_FILE;
283}
284
[a2aa1dec]285/** libfs operations */
286libfs_ops_t fat_libfs_ops = {
287 .match = fat_match,
288 .node_get = fat_node_get,
289 .create = NULL,
290 .destroy = NULL,
291 .link = NULL,
292 .unlink = NULL,
[e1e3b26]293 .index_get = fat_index_get,
294 .size_get = fat_size_get,
295 .lnkcnt_get = fat_lnkcnt_get,
[a2aa1dec]296 .has_children = NULL,
297 .root_get = NULL,
298 .plb_get_char = NULL,
[e1e3b26]299 .is_directory = fat_is_directory,
300 .is_file = fat_is_file
[a2aa1dec]301};
302
[be815bc]303void fat_lookup(ipc_callid_t rid, ipc_call_t *request)
304{
[a2aa1dec]305 libfs_lookup(&fat_libfs_ops, fat_reg.fs_handle, rid, request);
[be815bc]306}
307
308/**
309 * @}
310 */
Note: See TracBrowser for help on using the repository browser.