Subversion Repositories HelenOS

Rev

Rev 2828 | Rev 2844 | Go to most recent revision | Blame | Compare with Previous | Last modification | View Log | Download | RSS feed

  1. /*
  2.  * Copyright (c) 2008 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    fat_ops.c
  35.  * @brief   Implementation of VFS operations for the FAT file system server.
  36.  */
  37.  
  38. #include "fat.h"
  39. #include "../../vfs/vfs.h"
  40. #include <libfs.h>
  41. #include <ipc/ipc.h>
  42. #include <async.h>
  43. #include <errno.h>
  44. #include <string.h>
  45. #include <byteorder.h>
  46. #include <libadt/hash_table.h>
  47. #include <libadt/list.h>
  48. #include <assert.h>
  49.  
  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.  
  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.  
  66. static 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.  
  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)
  100. {
  101.     return NULL;    /* TODO */
  102. }
  103.  
  104. static block_t *fat_block_get(dev_handle_t dev_handle, fs_index_t index,
  105.     off_t offset) {
  106.     return NULL;    /* TODO */
  107. }
  108.  
  109. static void block_put(block_t *block)
  110. {
  111.     /* TODO */
  112. }
  113.  
  114. static void fat_node_initialize(fat_node_t *node)
  115. {
  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.  
  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.  
  187. #define BS_BLOCK    0
  188.  
  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];
  193.     unsigned i, j;
  194.     unsigned bps;       /* bytes per sector */
  195.     unsigned dps;       /* dentries per sector */
  196.     unsigned blocks;
  197.     fat_dentry_t *d;
  198.     block_t *bb;
  199.     block_t *b;
  200.  
  201.     bb = block_get(parentp->dev_handle, BS_BLOCK);
  202.     if (!bb)
  203.         return NULL;
  204.     bps = uint16_t_le2host(((fat_bs_t *)bb->data)->bps);
  205.     block_put(bb);
  206.     dps = bps / sizeof(fat_dentry_t);
  207.     blocks = parentp->size / bps + (parentp->size % bps != 0);
  208.     for (i = 0; i < blocks; i++) {
  209.         unsigned dentries;
  210.        
  211.         b = fat_block_get(parentp->dev_handle, parentp->index, i);
  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.             }
  240.        
  241.             dentry_name_canonify(d, name);
  242.             if (strcmp(name, component) == 0) {
  243.                 /* hit */
  244.                 void *node = fat_node_get(parentp->dev_handle,
  245.                     (fs_index_t)uint16_t_le2host(d->firstc),
  246.                     parentp->index);
  247.                 block_put(b);
  248.                 return node;
  249.             }
  250.         }
  251.         block_put(b);
  252.     }
  253.  
  254.     return NULL;
  255. }
  256.  
  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.  
  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,
  293.     .index_get = fat_index_get,
  294.     .size_get = fat_size_get,
  295.     .lnkcnt_get = fat_lnkcnt_get,
  296.     .has_children = NULL,
  297.     .root_get = NULL,
  298.     .plb_get_char = NULL,
  299.     .is_directory = fat_is_directory,
  300.     .is_file = fat_is_file
  301. };
  302.  
  303. void fat_lookup(ipc_callid_t rid, ipc_call_t *request)
  304. {
  305.     libfs_lookup(&fat_libfs_ops, fat_reg.fs_handle, rid, request);
  306. }
  307.  
  308. /**
  309.  * @}
  310.  */
  311.