/*
* dblist.c -- directory block list functions
- *
+ *
* Copyright 1997 by Theodore Ts'o
- *
+ *
* %Begin-Header%
* This file may be redistributed under the terms of the GNU Public
* License.
* %End-Header%
- *
+ *
*/
#include <stdio.h>
#include <string.h>
#include <time.h>
-#if EXT2_FLAT_INCLUDES
#include "ext2_fs.h"
-#else
-#include <linux/ext2_fs.h>
-#endif
-
#include "ext2fsP.h"
-static int dir_block_cmp(const void *a, const void *b);
+static EXT2_QSORT_TYPE dir_block_cmp(const void *a, const void *b);
/*
* Returns the number of directories in the filesystem as reported by
* the group descriptors. Of course, the group descriptors could be
* wrong!
*/
-errcode_t ext2fs_get_num_dirs(ext2_filsys fs, ino_t *ret_num_dirs)
+errcode_t ext2fs_get_num_dirs(ext2_filsys fs, ext2_ino_t *ret_num_dirs)
{
- int i;
- ino_t num_dirs, max_dirs;
+ dgrp_t i;
+ ext2_ino_t num_dirs, max_dirs;
EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS);
-
+
num_dirs = 0;
max_dirs = fs->super->s_inodes_per_group;
for (i = 0; i < fs->group_desc_count; i++) {
* helper function for making a new directory block list (for
* initialize and copy).
*/
-static errcode_t make_dblist(ext2_filsys fs, ino_t size, ino_t count,
+static errcode_t make_dblist(ext2_filsys fs, ext2_ino_t size, ext2_ino_t count,
struct ext2_db_entry *list,
ext2_dblist *ret_dblist)
{
(fs->dblist->magic == EXT2_ET_MAGIC_DBLIST))
return 0;
- retval = ext2fs_get_mem(sizeof(struct ext2_struct_dblist),
- (void **) &dblist);
+ retval = ext2fs_get_mem(sizeof(struct ext2_struct_dblist), &dblist);
if (retval)
return retval;
memset(dblist, 0, sizeof(struct ext2_struct_dblist));
}
len = (size_t) sizeof(struct ext2_db_entry) * dblist->size;
dblist->count = count;
- retval = ext2fs_get_mem(len, (void **) &dblist->list);
+ retval = ext2fs_get_array(dblist->size, sizeof(struct ext2_db_entry),
+ &dblist->list);
if (retval)
goto cleanup;
-
+
if (list)
memcpy(dblist->list, list, len);
else
memset(dblist->list, 0, len);
- *ret_dblist = dblist;
+ if (ret_dblist)
+ *ret_dblist = dblist;
+ else
+ fs->dblist = dblist;
return 0;
cleanup:
if (dblist)
- ext2fs_free_mem((void **) &dblist);
+ ext2fs_free_mem(&dblist);
return retval;
}
/*
* Add a directory block to the directory block list
*/
-errcode_t ext2fs_add_dir_block(ext2_dblist dblist, ino_t ino, blk_t blk,
+errcode_t ext2fs_add_dir_block(ext2_dblist dblist, ext2_ino_t ino, blk_t blk,
int blockcnt)
{
struct ext2_db_entry *new_entry;
errcode_t retval;
-
+ unsigned long old_size;
+
EXT2_CHECK_MAGIC(dblist, EXT2_ET_MAGIC_DBLIST);
if (dblist->count >= dblist->size) {
- dblist->size += 100;
- retval = ext2fs_resize_mem((size_t) dblist->size *
+ old_size = dblist->size * sizeof(struct ext2_db_entry);
+ dblist->size += dblist->size > 200 ? dblist->size / 2 : 100;
+ retval = ext2fs_resize_mem(old_size, (size_t) dblist->size *
sizeof(struct ext2_db_entry),
- (void **) &dblist->list);
+ &dblist->list);
if (retval) {
dblist->size -= 100;
return retval;
/*
* Change the directory block to the directory block list
*/
-errcode_t ext2fs_set_dir_block(ext2_dblist dblist, ino_t ino, blk_t blk,
+errcode_t ext2fs_set_dir_block(ext2_dblist dblist, ext2_ino_t ino, blk_t blk,
int blockcnt)
{
- int i;
-
+ dgrp_t i;
+
EXT2_CHECK_MAGIC(dblist, EXT2_ET_MAGIC_DBLIST);
for (i=0; i < dblist->count; i++) {
return EXT2_ET_DB_NOT_FOUND;
}
+void ext2fs_dblist_sort(ext2_dblist dblist,
+ EXT2_QSORT_TYPE (*sortfunc)(const void *,
+ const void *))
+{
+ if (!sortfunc)
+ sortfunc = dir_block_cmp;
+ qsort(dblist->list, (size_t) dblist->count,
+ sizeof(struct ext2_db_entry), sortfunc);
+ dblist->sorted = 1;
+}
+
/*
* This function iterates over the directory block list
*/
void *priv_data),
void *priv_data)
{
- ino_t i;
- int ret;
-
+ ext2_ino_t i;
+ int ret;
+
EXT2_CHECK_MAGIC(dblist, EXT2_ET_MAGIC_DBLIST);
- if (!dblist->sorted) {
- qsort(dblist->list, (size_t) dblist->count,
- sizeof(struct ext2_db_entry), dir_block_cmp);
- dblist->sorted = 1;
- }
+ if (!dblist->sorted)
+ ext2fs_dblist_sort(dblist, 0);
for (i=0; i < dblist->count; i++) {
ret = (*func)(dblist->fs, &dblist->list[(int)i], priv_data);
if (ret & DBLIST_ABORT)
return 0;
}
-
-static int dir_block_cmp(const void *a, const void *b)
+static EXT2_QSORT_TYPE dir_block_cmp(const void *a, const void *b)
{
const struct ext2_db_entry *db_a =
(const struct ext2_db_entry *) a;
if (db_a->blk != db_b->blk)
return (int) (db_a->blk - db_b->blk);
-
+
if (db_a->ino != db_b->ino)
return (int) (db_a->ino - db_b->ino);
{
return (int) dblist->count;
}
+
+errcode_t ext2fs_dblist_get_last(ext2_dblist dblist,
+ struct ext2_db_entry **entry)
+{
+ EXT2_CHECK_MAGIC(dblist, EXT2_ET_MAGIC_DBLIST);
+
+ if (dblist->count == 0)
+ return EXT2_ET_DBLIST_EMPTY;
+
+ if (entry)
+ *entry = dblist->list + ( (int) dblist->count-1);
+ return 0;
+}
+
+errcode_t ext2fs_dblist_drop_last(ext2_dblist dblist)
+{
+ EXT2_CHECK_MAGIC(dblist, EXT2_ET_MAGIC_DBLIST);
+
+ if (dblist->count == 0)
+ return EXT2_ET_DBLIST_EMPTY;
+
+ dblist->count--;
+ return 0;
+}