Newer
Older
ubixos / src / sys / ubixfs / dirCache.c
#include <assert.h>
#include <ubixfs/dirCache.h>
#include <lib/kmalloc.h>
#include <lib/kprintf.h>
#include <lib/string.h>


struct cacheNode *
dirCacheFind(struct cacheNode * head, char * name) {
  struct cacheNode * tmp = head;
  unsigned int i;
  char dirName[256];
  char * nextDir = NULL;

  if (name == NULL || head == NULL) return NULL;
  if (*name == '\0') return NULL;

  /* 
   * walk down the tree recursively until we find the node we're looking
   * for
   */
  i = 0;
  while (name[i] != '\0' && name[i] != '/' && i < sizeof(dirName)) {
    dirName[i] = name[i];
    i++;
  } /* while */
  assert(i < sizeof(dirName));
  if (i == sizeof(dirName)) return NULL;

  if (i == 0) dirName[i++] = '/';

  dirName[i] = '\0';
  
  nextDir = &name[i];
  if (*nextDir == '/') nextDir++;

  /* 
   * nextDir points to the next dir
   * name points to a null terminated directory name
   * if nextDir isn't null, then make sure that this dir is present
   */

  if (*nextDir != '\0') {
    while (tmp != NULL) {
      if (strcmp(tmp->name, dirName) == 0) 
        return dirCacheFind(tmp->subDirsHead, nextDir);
      tmp = tmp->next;
    } /* while */
    /* if we're here, then one level of the dir isn't cached */
    return NULL;
  } /* if */ 

  /*
   * if nextDir was null, then we're at the bottom level. Look for the
   * dir listing here 
   */
  while (tmp != NULL) {
    assert(tmp->name);
/* don't forget to check to see if it's a directory */
    if (strcmp(tmp->name, name) == 0) {
      /* 
       * we found the node. Move it to the front of the list 
       * (if it isn't already)
       */
      if (tmp != tmp->parent->subDirsHead) {
        assert(tmp->parent);

        /* if we're the tail, point the tail to our prev */
        if (tmp == tmp->parent->subDirsTail) {
          tmp->parent->subDirsTail = tmp->prev;
        } /* if */

        if (tmp->next != NULL) tmp->next->prev = tmp->prev;
        if (tmp->prev != NULL) tmp->prev->next = tmp->next;
        tmp->next = tmp->parent->subDirsHead;
        tmp->prev = NULL;
        tmp->parent->subDirsHead = tmp;
      } /* if */
      return tmp;
    } /* if */
    tmp = tmp->next;
  } /* while */

  return NULL;  /* couldn't find it */
} /* findNode */

struct cacheNode * 
dirCacheNew(const char * name) {
  struct cacheNode * tmp = kmalloc(sizeof(struct cacheNode));
  assert(tmp);
  tmp->parent = tmp;
  tmp->prev = tmp->next = tmp->subDirsHead = tmp->subDirsTail = NULL;
  tmp->dirList = NULL;
  tmp->dirListEntryCount = tmp->dirty = tmp->dirBlock = 0;
  tmp->name = (char *)kmalloc(strlen(name));
  strcpy(tmp->name, name);
  return tmp;
} /* newNode */

void
dirCacheDelete(struct cacheNode ** head) {
  struct cacheNode * tmp = NULL;
  struct cacheNode * del = NULL;

  if (head == NULL) return;
  if (*head == NULL) return;

  tmp = *head;
  while (tmp != NULL) {
    /* if there are any child nodes, delete them first */

    /* 
     * the following commented out ``if'' statement is redundant, since it 
     * will be caught with the above checks
     */
    /* if (tmp->subDirsHead != NULL) */
    dirCacheDelete(&tmp->subDirsHead);

    kfree(tmp->dirList);
    kfree(tmp->name);
    del = tmp;
    tmp = tmp->next;
    kfree(del);
  } /* while */
  *head = NULL;
  return;
} /* deleteNode */
#if 0
void
addNode(struct cacheNode ** node, struct cacheNode * newNode) {
  if (node == NULL) return;
  newNode->next = *node;
  if (*node != NULL) (*node)->prev = newNode;
  newNode->prev = NULL;
  *node = newNode;
  return;
} /* addNode */
#endif

void
dirCacheAdd(struct cacheNode *node, struct cacheNode * newNode) {
  struct cacheNode * tmp;

  assert(node);
  newNode->parent = node;
  newNode->next = node->subDirsHead;
  newNode->prev = NULL;
  if (node->subDirsHead == NULL) 
    node->subDirsTail = newNode;
  else
    node->subDirsHead->prev = newNode;

  node->subDirsHead = newNode;
  tmp = node->subDirsHead;
  return;
} /* dirCacheAdd */