From 22c02b9b2fd91e8ded9b77fdfc4f75dd6bfd3db0 Mon Sep 17 00:00:00 2001 From: Mario Danic Date: Fri, 1 Jun 2007 07:02:15 +0000 Subject: [PATCH] Commited second part of major changes --- libisofs/file.c | 188 ++++++++++++++++++++++++++++++++++++++++++++++++ libisofs/file.h | 55 ++++++++++++++ 2 files changed, 243 insertions(+) create mode 100644 libisofs/file.c create mode 100644 libisofs/file.h diff --git a/libisofs/file.c b/libisofs/file.c new file mode 100644 index 0000000..5303516 --- /dev/null +++ b/libisofs/file.c @@ -0,0 +1,188 @@ +#include +#include +#include +#include +#include +#include + +#include "file.h" +#include "tree.h" + +//TODO: refactor both hash and this hash table into a single one!! + +struct iso_file * +iso_file_new(struct iso_tree_node_file *f) +{ + struct iso_file *file = calloc(1, sizeof(struct iso_file)); + file->path = f->path; /*TODO strdup? it needs to be free on clear then */ + file->size = f->node.attrib.st_size; + file->nlink = 1; + file->real_dev = f->node.attrib.st_dev; + file->real_ino = f->node.attrib.st_ino; + file->sort_weight = f->sort_weight; + return file; +} + +static unsigned int +iso_file_table_hash(const char *path) +{ + unsigned int hash_num=0; + const char *c; + + c=path; + while(*c) + hash_num = (hash_num << 15) + (hash_num << 3) + (hash_num >> 3) + *c++; + + return hash_num % FILE_HASH_NODES; +} + +static inline unsigned int +iso_file_table_hash_inode(dev_t dev, ino_t ino) +{ + return (dev ^ ino) % FILE_HASH_NODES; +} + +struct iso_file_table* +iso_file_table_new(int cache_inodes) +{ + struct iso_file_table *table = calloc(1, sizeof(struct iso_file_table)); + table->cache_inodes = cache_inodes; + return table; +} + +static struct iso_file_hash_node * +iso_file_table_node_new(struct iso_file *file) +{ + struct iso_file_hash_node *node; + node = calloc(1, sizeof(struct iso_file_hash_node) ); + node->file = file; + return node; +} + +static void +iso_file_table_node_free(struct iso_file_hash_node *node) +{ + free(node->file); + free(node); +} + +void +iso_file_table_clear(struct iso_file_table *ft) +{ + int i; + + for (i=0; i < FILE_HASH_NODES; i++) { + struct iso_file_hash_node *node; + + node=ft->table[i]; + if (!node) + continue; + + ft->table[i] = NULL; + + do { + struct iso_file_hash_node *next; + + next = node->next; + iso_file_table_node_free(node); + node = next; + } while (node); + } +} + +/** + * return 0 if equal, != 0 if not + */ +static int +iso_table_compare_files(struct iso_file_table *ft, + struct iso_file *f1, struct iso_file *f2) +{ + if (ft->cache_inodes) { + return (f1->real_dev != f2->real_dev) || (f1->real_ino != f2->real_ino); + } else { + return strcmp(f1->path, f2->path); + } +} + +int +iso_file_table_add_file(struct iso_file_table *ft, struct iso_file *f) +{ + struct iso_file_hash_node *node; + unsigned int hash_num; + + /* find the hash number */ + if (ft->cache_inodes) + hash_num = iso_file_table_hash_inode(f->real_dev, f->real_ino); + else + hash_num = iso_file_table_hash(f->path); + + /* insert it */ + node = ft->table[hash_num]; + + /* unfortunately, we can't safely consider that a file + * won't be twice in the hash table so make sure it + * doesn't already exists */ + if (!node) { + ft->table[hash_num]=iso_file_table_node_new(f); + ft->count++; + return 1; + } + + /* if it's already in, we don't do anything */ + if (!iso_table_compare_files(ft, f, node->file)) + return 0; + + while (node->next) { + node = node->next; + + /* if it's already in, we don't do anything */ + if (!iso_table_compare_files(ft, f, node->file)) + return 0; + } + + node->next = iso_file_table_node_new(f); + ft->count++; + return 1; +} + +struct iso_file * +iso_file_table_lookup(struct iso_file_table *ft, struct iso_tree_node_file *f) +{ + struct iso_file_hash_node *node; + unsigned int hash_num; + int equal; + + /* find the hash number */ + if ( ft->cache_inodes ) + hash_num = iso_file_table_hash_inode(f->node.attrib.st_dev, + f->node.attrib.st_ino); + else + hash_num = iso_file_table_hash(f->path); + + node = ft->table[hash_num]; + + if (!node) + return NULL; + + equal = ft->cache_inodes ? + ((f->node.attrib.st_dev == node->file->real_dev) + && (f->node.attrib.st_ino == node->file->real_ino)) + : !strcmp(f->path, node->file->path); + if (equal) + return node->file; + + while (node->next) { + node = node->next; + + equal = ft->cache_inodes ? + ((f->node.attrib.st_dev == node->file->real_dev) + && (f->node.attrib.st_ino == node->file->real_ino)) + : !strcmp(f->path, node->file->path); + if (equal) + return node->file; + } + + return NULL; +} + + diff --git a/libisofs/file.h b/libisofs/file.h new file mode 100644 index 0000000..9c2745b --- /dev/null +++ b/libisofs/file.h @@ -0,0 +1,55 @@ +/* -*- indent-tabs-mode: t; tab-width: 8; c-basic-offset: 8; -*- */ +/* vim: set noet ts=8 sts=8 sw=8 : */ + +/** + * \file file.h + * + * Declare the structs to keep track of the files to be written into image. + * + */ + +#ifndef FILE_H_ +#define FILE_H_ + +#define FILE_HASH_NODES 2048 + +struct iso_file { + char *path; + off_t size; /**< size of this file */ + ino_t ino; /**< This will be the inode number on CD of the file (RR) */ + nlink_t nlink; /**< Number of hard links of the file on CD (RR) */ + size_t block; /**< Block where this file is to be written on image */ + dev_t real_dev; + ino_t real_ino; /**< for lookup by inode caching */ + int sort_weight; +}; + +struct iso_file_hash_node { + struct iso_file_hash_node *next; + struct iso_file *file; +}; + +struct iso_file_table { + struct iso_file_hash_node *table[FILE_HASH_NODES]; + size_t count; + int cache_inodes; /**< 1 to index by inode number */ +}; + +struct iso_tree_node_file; + +struct iso_file *iso_file_new(struct iso_tree_node_file*); + +struct iso_file_table *iso_file_table_new(int cache_inodes); + +/** + * Clear a hash table. All iso_file structs stored will also be freed, + * but not the path of each iso_file + */ +void iso_file_table_clear(struct iso_file_table *ft); + +int iso_file_table_add_file(struct iso_file_table *ft, struct iso_file *f); + +struct iso_file *iso_file_table_lookup(struct iso_file_table *ft, + struct iso_tree_node_file *f); + +#endif /*FILE_H_*/