Subversion Repositories HelenOS

Rev

Rev 2828 | Rev 2843 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
2627 jermar 1
/*
2793 jermar 2
 * Copyright (c) 2008 Jakub Jermar
2627 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    fat_ops.c
35
 * @brief   Implementation of VFS operations for the FAT file system server.
36
 */
37
 
38
#include "fat.h"
2638 jermar 39
#include "../../vfs/vfs.h"
2793 jermar 40
#include <libfs.h>
2627 jermar 41
#include <ipc/ipc.h>
42
#include <async.h>
43
#include <errno.h>
2793 jermar 44
#include <string.h>
2798 jermar 45
#include <byteorder.h>
2831 jermar 46
#include <libadt/hash_table.h>
47
#include <libadt/list.h>
48
#include <assert.h>
2627 jermar 49
 
2831 jermar 50
/** Hash table of FAT in-core nodes. */
51
hash_table_t fin_hash;
52
 
53
/** List of free FAT in-core nodes. */
54
link_t ffn_head;
55
 
2638 jermar 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
 
2793 jermar 66
static void dentry_name_canonify(fat_dentry_t *d, char *buf)
2638 jermar 67
{
2793 jermar 68
    int i;
2639 jermar 69
 
2793 jermar 70
    for (i = 0; i < FAT_NAME_LEN; i++) {
71
        if (d->name[i] == FAT_PAD) {
72
            buf++;
73
            break;
2639 jermar 74
        }
2793 jermar 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
 
2822 jermar 94
/* TODO and also move somewhere else */
95
typedef struct {
96
    void *data;
97
} block_t;
98
 
99
static block_t *block_get(dev_handle_t dev_handle, off_t offset)
2793 jermar 100
{
101
    return NULL;    /* TODO */
102
}
103
 
2831 jermar 104
static block_t *fat_block_get(dev_handle_t dev_handle, fs_index_t index,
105
    off_t offset) {
2822 jermar 106
    return NULL;    /* TODO */
107
}
108
 
109
static void block_put(block_t *block)
2793 jermar 110
{
111
    /* TODO */
112
}
113
 
2831 jermar 114
static void fat_node_initialize(fat_node_t *node)
2793 jermar 115
{
2831 jermar 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;
2793 jermar 126
}
127
 
2831 jermar 128
static void fat_sync_node(fat_node_t *node)
129
{
130
    /* TODO */
131
}
132
 
133
static void *
134
fat_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
 
185
}
186
 
2822 jermar 187
#define BS_BLOCK    0
188
 
2793 jermar 189
static 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];
2822 jermar 193
    unsigned i, j;
2828 jermar 194
    unsigned bps;       /* bytes per sector */
2822 jermar 195
    unsigned dps;       /* dentries per sector */
196
    unsigned blocks;
2793 jermar 197
    fat_dentry_t *d;
2822 jermar 198
    block_t *bb;
199
    block_t *b;
2793 jermar 200
 
2822 jermar 201
    bb = block_get(parentp->dev_handle, BS_BLOCK);
202
    if (!bb)
203
        return NULL;
2828 jermar 204
    bps = uint16_t_le2host(((fat_bs_t *)bb->data)->bps);
2822 jermar 205
    block_put(bb);
2828 jermar 206
    dps = bps / sizeof(fat_dentry_t);
207
    blocks = parentp->size / bps + (parentp->size % bps != 0);
2822 jermar 208
    for (i = 0; i < blocks; i++) {
209
        unsigned dentries;
2793 jermar 210
 
2831 jermar 211
        b = fat_block_get(parentp->dev_handle, parentp->index, i);
2822 jermar 212
        if (!b)
213
            return NULL;
2793 jermar 214
 
2822 jermar 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
            }
240
 
241
            dentry_name_canonify(d, name);
242
            if (strcmp(name, component) == 0) {
243
                /* hit */
244
                void *node = fat_node_get(parentp->dev_handle,
2831 jermar 245
                    (fs_index_t)uint16_t_le2host(d->firstc),
246
                    parentp->index);
2822 jermar 247
                block_put(b);
248
                return node;
249
            }
2793 jermar 250
        }
2822 jermar 251
        block_put(b);
2639 jermar 252
    }
2793 jermar 253
 
254
    return NULL;
2638 jermar 255
}
256
 
2831 jermar 257
static 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
 
265
static size_t fat_size_get(void *node)
266
{
267
    return ((fat_node_t *)node)->size;
268
}
269
 
270
static unsigned fat_lnkcnt_get(void *node)
271
{
272
    return ((fat_node_t *)node)->lnkcnt;
273
}
274
 
275
static bool fat_is_directory(void *node)
276
{
277
    return ((fat_node_t *)node)->type == FAT_DIRECTORY;
278
}
279
 
280
static bool fat_is_file(void *node)
281
{
282
    return ((fat_node_t *)node)->type == FAT_FILE;
283
}
284
 
2793 jermar 285
/** libfs operations */
286
libfs_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,
2831 jermar 293
    .index_get = fat_index_get,
294
    .size_get = fat_size_get,
295
    .lnkcnt_get = fat_lnkcnt_get,
2793 jermar 296
    .has_children = NULL,
297
    .root_get = NULL,
298
    .plb_get_char = NULL,
2831 jermar 299
    .is_directory = fat_is_directory,
300
    .is_file = fat_is_file
2793 jermar 301
};
302
 
2627 jermar 303
void fat_lookup(ipc_callid_t rid, ipc_call_t *request)
304
{
2793 jermar 305
    libfs_lookup(&fat_libfs_ops, fat_reg.fs_handle, rid, request);
2627 jermar 306
}
307
 
308
/**
309
 * @}
310
 */