dblist.c revision ab13b5a9795a8c20f1d6da8fe1da340f545ec0e0
148486893f46d2e12e926682a3ecb908716bc66c4Chris Lattner/*
2b2109ce97881269a610fa4afbcbca350e975174dJohn Criswell * dblist.c -- directory block list functions
3b2109ce97881269a610fa4afbcbca350e975174dJohn Criswell *
4b2109ce97881269a610fa4afbcbca350e975174dJohn Criswell * Copyright 1997 by Theodore Ts'o
5b2109ce97881269a610fa4afbcbca350e975174dJohn Criswell *
6b2109ce97881269a610fa4afbcbca350e975174dJohn Criswell * %Begin-Header%
7b2109ce97881269a610fa4afbcbca350e975174dJohn Criswell * This file may be redistributed under the terms of the GNU Library
8b2109ce97881269a610fa4afbcbca350e975174dJohn Criswell * General Public License, version 2.
9589df88ba03a81b2b3dc9d084c191a3a74724ecdChris Lattner * %End-Header%
10589df88ba03a81b2b3dc9d084c191a3a74724ecdChris Lattner */
11589df88ba03a81b2b3dc9d084c191a3a74724ecdChris Lattner
12589df88ba03a81b2b3dc9d084c191a3a74724ecdChris Lattner#include <stdio.h>
13589df88ba03a81b2b3dc9d084c191a3a74724ecdChris Lattner#if HAVE_UNISTD_H
14589df88ba03a81b2b3dc9d084c191a3a74724ecdChris Lattner#include <unistd.h>
15589df88ba03a81b2b3dc9d084c191a3a74724ecdChris Lattner#endif
16589df88ba03a81b2b3dc9d084c191a3a74724ecdChris Lattner#include <string.h>
17589df88ba03a81b2b3dc9d084c191a3a74724ecdChris Lattner#include <time.h>
18589df88ba03a81b2b3dc9d084c191a3a74724ecdChris Lattner
197e70829632f82de15db187845666aaca6e04b792Chris Lattner#include "ext2_fs.h"
20589df88ba03a81b2b3dc9d084c191a3a74724ecdChris Lattner#include "ext2fsP.h"
21589df88ba03a81b2b3dc9d084c191a3a74724ecdChris Lattner
227e70829632f82de15db187845666aaca6e04b792Chris Lattnerstatic EXT2_QSORT_TYPE dir_block_cmp(const void *a, const void *b);
237e70829632f82de15db187845666aaca6e04b792Chris Lattnerstatic EXT2_QSORT_TYPE dir_block_cmp2(const void *a, const void *b);
247e70829632f82de15db187845666aaca6e04b792Chris Lattnerstatic EXT2_QSORT_TYPE (*sortfunc32)(const void *a, const void *b);
257e70829632f82de15db187845666aaca6e04b792Chris Lattner
267e70829632f82de15db187845666aaca6e04b792Chris Lattner/*
277e70829632f82de15db187845666aaca6e04b792Chris Lattner * Returns the number of directories in the filesystem as reported by
287e70829632f82de15db187845666aaca6e04b792Chris Lattner * the group descriptors.  Of course, the group descriptors could be
297e70829632f82de15db187845666aaca6e04b792Chris Lattner * wrong!
307e70829632f82de15db187845666aaca6e04b792Chris Lattner */
317e70829632f82de15db187845666aaca6e04b792Chris Lattnererrcode_t ext2fs_get_num_dirs(ext2_filsys fs, ext2_ino_t *ret_num_dirs)
327e70829632f82de15db187845666aaca6e04b792Chris Lattner{
337e70829632f82de15db187845666aaca6e04b792Chris Lattner	dgrp_t	i;
347e70829632f82de15db187845666aaca6e04b792Chris Lattner	ext2_ino_t	num_dirs, max_dirs;
357e70829632f82de15db187845666aaca6e04b792Chris Lattner
367e70829632f82de15db187845666aaca6e04b792Chris Lattner	EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS);
377e70829632f82de15db187845666aaca6e04b792Chris Lattner
387e70829632f82de15db187845666aaca6e04b792Chris Lattner	num_dirs = 0;
397e70829632f82de15db187845666aaca6e04b792Chris Lattner	max_dirs = fs->super->s_inodes_per_group;
407e70829632f82de15db187845666aaca6e04b792Chris Lattner	for (i = 0; i < fs->group_desc_count; i++) {
417e70829632f82de15db187845666aaca6e04b792Chris Lattner		if (ext2fs_bg_used_dirs_count(fs, i) > max_dirs)
427e70829632f82de15db187845666aaca6e04b792Chris Lattner			num_dirs += max_dirs / 8;
43589df88ba03a81b2b3dc9d084c191a3a74724ecdChris Lattner		else
44589df88ba03a81b2b3dc9d084c191a3a74724ecdChris Lattner			num_dirs += ext2fs_bg_used_dirs_count(fs, i);
45589df88ba03a81b2b3dc9d084c191a3a74724ecdChris Lattner	}
467e70829632f82de15db187845666aaca6e04b792Chris Lattner	if (num_dirs > fs->super->s_inodes_count)
477e70829632f82de15db187845666aaca6e04b792Chris Lattner		num_dirs = fs->super->s_inodes_count;
487e70829632f82de15db187845666aaca6e04b792Chris Lattner
497e70829632f82de15db187845666aaca6e04b792Chris Lattner	*ret_num_dirs = num_dirs;
507e70829632f82de15db187845666aaca6e04b792Chris Lattner
517e70829632f82de15db187845666aaca6e04b792Chris Lattner	return 0;
527e70829632f82de15db187845666aaca6e04b792Chris Lattner}
537e70829632f82de15db187845666aaca6e04b792Chris Lattner
547e70829632f82de15db187845666aaca6e04b792Chris Lattner/*
557e70829632f82de15db187845666aaca6e04b792Chris Lattner * helper function for making a new directory block list (for
567e70829632f82de15db187845666aaca6e04b792Chris Lattner * initialize and copy).
577e70829632f82de15db187845666aaca6e04b792Chris Lattner */
587e70829632f82de15db187845666aaca6e04b792Chris Lattnerstatic errcode_t make_dblist(ext2_filsys fs, ext2_ino_t size,
597e70829632f82de15db187845666aaca6e04b792Chris Lattner			     ext2_ino_t count,
607e70829632f82de15db187845666aaca6e04b792Chris Lattner			     struct ext2_db_entry2 *list,
617e70829632f82de15db187845666aaca6e04b792Chris Lattner			     ext2_dblist *ret_dblist)
627e70829632f82de15db187845666aaca6e04b792Chris Lattner{
637e70829632f82de15db187845666aaca6e04b792Chris Lattner	ext2_dblist	dblist;
647e70829632f82de15db187845666aaca6e04b792Chris Lattner	errcode_t	retval;
657e70829632f82de15db187845666aaca6e04b792Chris Lattner	ext2_ino_t	num_dirs;
667e70829632f82de15db187845666aaca6e04b792Chris Lattner	size_t		len;
677e70829632f82de15db187845666aaca6e04b792Chris Lattner
687e70829632f82de15db187845666aaca6e04b792Chris Lattner	EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS);
697e70829632f82de15db187845666aaca6e04b792Chris Lattner
707e70829632f82de15db187845666aaca6e04b792Chris Lattner	if ((ret_dblist == 0) && fs->dblist &&
717e70829632f82de15db187845666aaca6e04b792Chris Lattner	    (fs->dblist->magic == EXT2_ET_MAGIC_DBLIST))
72776f776838d6e2f83d899bc99452dc83779c341bChris Lattner		return 0;
73589df88ba03a81b2b3dc9d084c191a3a74724ecdChris Lattner
747e70829632f82de15db187845666aaca6e04b792Chris Lattner	retval = ext2fs_get_mem(sizeof(struct ext2_struct_dblist), &dblist);
757e70829632f82de15db187845666aaca6e04b792Chris Lattner	if (retval)
767e70829632f82de15db187845666aaca6e04b792Chris Lattner		return retval;
777e70829632f82de15db187845666aaca6e04b792Chris Lattner	memset(dblist, 0, sizeof(struct ext2_struct_dblist));
787e70829632f82de15db187845666aaca6e04b792Chris Lattner
795a6d63ae29512d654c8c697f42f32f97b9dc010bChris Lattner	dblist->magic = EXT2_ET_MAGIC_DBLIST;
807e70829632f82de15db187845666aaca6e04b792Chris Lattner	dblist->fs = fs;
817e70829632f82de15db187845666aaca6e04b792Chris Lattner	if (size)
827e70829632f82de15db187845666aaca6e04b792Chris Lattner		dblist->size = size;
837e70829632f82de15db187845666aaca6e04b792Chris Lattner	else {
847e70829632f82de15db187845666aaca6e04b792Chris Lattner		retval = ext2fs_get_num_dirs(fs, &num_dirs);
857e70829632f82de15db187845666aaca6e04b792Chris Lattner		if (retval)
867e70829632f82de15db187845666aaca6e04b792Chris Lattner			goto cleanup;
877e70829632f82de15db187845666aaca6e04b792Chris Lattner		dblist->size = (num_dirs * 2) + 12;
887e70829632f82de15db187845666aaca6e04b792Chris Lattner	}
897e70829632f82de15db187845666aaca6e04b792Chris Lattner	len = (size_t) sizeof(struct ext2_db_entry2) * dblist->size;
907e70829632f82de15db187845666aaca6e04b792Chris Lattner	dblist->count = count;
917e70829632f82de15db187845666aaca6e04b792Chris Lattner	retval = ext2fs_get_array(dblist->size, sizeof(struct ext2_db_entry2),
927e70829632f82de15db187845666aaca6e04b792Chris Lattner		&dblist->list);
937e70829632f82de15db187845666aaca6e04b792Chris Lattner	if (retval)
947e70829632f82de15db187845666aaca6e04b792Chris Lattner		goto cleanup;
957e70829632f82de15db187845666aaca6e04b792Chris Lattner
967e70829632f82de15db187845666aaca6e04b792Chris Lattner	if (list)
977e70829632f82de15db187845666aaca6e04b792Chris Lattner		memcpy(dblist->list, list, len);
987e70829632f82de15db187845666aaca6e04b792Chris Lattner	else
997e70829632f82de15db187845666aaca6e04b792Chris Lattner		memset(dblist->list, 0, len);
1007e70829632f82de15db187845666aaca6e04b792Chris Lattner	if (ret_dblist)
1017e70829632f82de15db187845666aaca6e04b792Chris Lattner		*ret_dblist = dblist;
1027e70829632f82de15db187845666aaca6e04b792Chris Lattner	else
1037e70829632f82de15db187845666aaca6e04b792Chris Lattner		fs->dblist = dblist;
1047e70829632f82de15db187845666aaca6e04b792Chris Lattner	return 0;
1057e70829632f82de15db187845666aaca6e04b792Chris Lattnercleanup:
1067e70829632f82de15db187845666aaca6e04b792Chris Lattner	if (dblist)
1077e70829632f82de15db187845666aaca6e04b792Chris Lattner		ext2fs_free_mem(&dblist);
1087e70829632f82de15db187845666aaca6e04b792Chris Lattner	return retval;
1097e70829632f82de15db187845666aaca6e04b792Chris Lattner}
110589df88ba03a81b2b3dc9d084c191a3a74724ecdChris Lattner
1117e70829632f82de15db187845666aaca6e04b792Chris Lattner/*
1127e70829632f82de15db187845666aaca6e04b792Chris Lattner * Initialize a directory block list
113589df88ba03a81b2b3dc9d084c191a3a74724ecdChris Lattner */
114589df88ba03a81b2b3dc9d084c191a3a74724ecdChris Lattnererrcode_t ext2fs_init_dblist(ext2_filsys fs, ext2_dblist *ret_dblist)
1157e70829632f82de15db187845666aaca6e04b792Chris Lattner{
1167e70829632f82de15db187845666aaca6e04b792Chris Lattner	ext2_dblist	dblist;
1177e70829632f82de15db187845666aaca6e04b792Chris Lattner	errcode_t	retval;
1187e70829632f82de15db187845666aaca6e04b792Chris Lattner
1197e70829632f82de15db187845666aaca6e04b792Chris Lattner	retval = make_dblist(fs, 0, 0, 0, &dblist);
1207e70829632f82de15db187845666aaca6e04b792Chris Lattner	if (retval)
1217e70829632f82de15db187845666aaca6e04b792Chris Lattner		return retval;
1227e70829632f82de15db187845666aaca6e04b792Chris Lattner
1237e70829632f82de15db187845666aaca6e04b792Chris Lattner	dblist->sorted = 1;
1247e70829632f82de15db187845666aaca6e04b792Chris Lattner	if (ret_dblist)
1257e70829632f82de15db187845666aaca6e04b792Chris Lattner		*ret_dblist = dblist;
1267e70829632f82de15db187845666aaca6e04b792Chris Lattner	else
1277e70829632f82de15db187845666aaca6e04b792Chris Lattner		fs->dblist = dblist;
1287e70829632f82de15db187845666aaca6e04b792Chris Lattner
1297e70829632f82de15db187845666aaca6e04b792Chris Lattner	return 0;
1307e70829632f82de15db187845666aaca6e04b792Chris Lattner}
1317e70829632f82de15db187845666aaca6e04b792Chris Lattner
1327e70829632f82de15db187845666aaca6e04b792Chris Lattner/*
1337e70829632f82de15db187845666aaca6e04b792Chris Lattner * Copy a directory block list
1347e70829632f82de15db187845666aaca6e04b792Chris Lattner */
1357e70829632f82de15db187845666aaca6e04b792Chris Lattnererrcode_t ext2fs_copy_dblist(ext2_dblist src, ext2_dblist *dest)
1367e70829632f82de15db187845666aaca6e04b792Chris Lattner{
1377e70829632f82de15db187845666aaca6e04b792Chris Lattner	ext2_dblist	dblist;
1387e70829632f82de15db187845666aaca6e04b792Chris Lattner	errcode_t	retval;
1397e70829632f82de15db187845666aaca6e04b792Chris Lattner
1407e70829632f82de15db187845666aaca6e04b792Chris Lattner	retval = make_dblist(src->fs, src->size, src->count, src->list,
1417e70829632f82de15db187845666aaca6e04b792Chris Lattner			     &dblist);
1427e70829632f82de15db187845666aaca6e04b792Chris Lattner	if (retval)
1437e70829632f82de15db187845666aaca6e04b792Chris Lattner		return retval;
1447e70829632f82de15db187845666aaca6e04b792Chris Lattner	dblist->sorted = src->sorted;
1457e70829632f82de15db187845666aaca6e04b792Chris Lattner	*dest = dblist;
1467e70829632f82de15db187845666aaca6e04b792Chris Lattner	return 0;
1477e70829632f82de15db187845666aaca6e04b792Chris Lattner}
1487e70829632f82de15db187845666aaca6e04b792Chris Lattner
1497e70829632f82de15db187845666aaca6e04b792Chris Lattner/*
1507e70829632f82de15db187845666aaca6e04b792Chris Lattner * Close a directory block list
1517e70829632f82de15db187845666aaca6e04b792Chris Lattner *
1527e70829632f82de15db187845666aaca6e04b792Chris Lattner * (moved to closefs.c)
1537e70829632f82de15db187845666aaca6e04b792Chris Lattner */
1547e70829632f82de15db187845666aaca6e04b792Chris Lattner
1557e70829632f82de15db187845666aaca6e04b792Chris Lattner
1567e70829632f82de15db187845666aaca6e04b792Chris Lattner/*
1577e70829632f82de15db187845666aaca6e04b792Chris Lattner * Add a directory block to the directory block list
1587e70829632f82de15db187845666aaca6e04b792Chris Lattner */
1597e70829632f82de15db187845666aaca6e04b792Chris Lattnererrcode_t ext2fs_add_dir_block2(ext2_dblist dblist, ext2_ino_t ino,
1607e70829632f82de15db187845666aaca6e04b792Chris Lattner				blk64_t blk, e2_blkcnt_t blockcnt)
1615a6d63ae29512d654c8c697f42f32f97b9dc010bChris Lattner{
1627e70829632f82de15db187845666aaca6e04b792Chris Lattner	struct ext2_db_entry2 	*new_entry;
1637e70829632f82de15db187845666aaca6e04b792Chris Lattner	errcode_t		retval;
1647e70829632f82de15db187845666aaca6e04b792Chris Lattner	unsigned long		old_size;
1657e70829632f82de15db187845666aaca6e04b792Chris Lattner
1667e70829632f82de15db187845666aaca6e04b792Chris Lattner	EXT2_CHECK_MAGIC(dblist, EXT2_ET_MAGIC_DBLIST);
1677e70829632f82de15db187845666aaca6e04b792Chris Lattner
1687e70829632f82de15db187845666aaca6e04b792Chris Lattner	if (dblist->count >= dblist->size) {
1695a6d63ae29512d654c8c697f42f32f97b9dc010bChris Lattner		old_size = dblist->size * sizeof(struct ext2_db_entry2);
1707e70829632f82de15db187845666aaca6e04b792Chris Lattner		dblist->size += dblist->size > 200 ? dblist->size / 2 : 100;
1715a6d63ae29512d654c8c697f42f32f97b9dc010bChris Lattner		retval = ext2fs_resize_mem(old_size, (size_t) dblist->size *
1727e70829632f82de15db187845666aaca6e04b792Chris Lattner					   sizeof(struct ext2_db_entry2),
1737e70829632f82de15db187845666aaca6e04b792Chris Lattner					   &dblist->list);
1747e70829632f82de15db187845666aaca6e04b792Chris Lattner		if (retval) {
1757e70829632f82de15db187845666aaca6e04b792Chris Lattner			dblist->size -= 100;
1767e70829632f82de15db187845666aaca6e04b792Chris Lattner			return retval;
1777e70829632f82de15db187845666aaca6e04b792Chris Lattner		}
1785a6d63ae29512d654c8c697f42f32f97b9dc010bChris Lattner	}
1795a6d63ae29512d654c8c697f42f32f97b9dc010bChris Lattner	new_entry = dblist->list + ( dblist->count++);
1807e70829632f82de15db187845666aaca6e04b792Chris Lattner	new_entry->blk = blk;
1817e70829632f82de15db187845666aaca6e04b792Chris Lattner	new_entry->ino = ino;
1827e70829632f82de15db187845666aaca6e04b792Chris Lattner	new_entry->blockcnt = blockcnt;
1837e70829632f82de15db187845666aaca6e04b792Chris Lattner
184589df88ba03a81b2b3dc9d084c191a3a74724ecdChris Lattner	dblist->sorted = 0;
185589df88ba03a81b2b3dc9d084c191a3a74724ecdChris Lattner
186589df88ba03a81b2b3dc9d084c191a3a74724ecdChris Lattner	return 0;
187589df88ba03a81b2b3dc9d084c191a3a74724ecdChris Lattner}
188589df88ba03a81b2b3dc9d084c191a3a74724ecdChris Lattner
189589df88ba03a81b2b3dc9d084c191a3a74724ecdChris Lattner/*
1907e70829632f82de15db187845666aaca6e04b792Chris Lattner * Change the directory block to the directory block list
191589df88ba03a81b2b3dc9d084c191a3a74724ecdChris Lattner */
192589df88ba03a81b2b3dc9d084c191a3a74724ecdChris Lattnererrcode_t ext2fs_set_dir_block2(ext2_dblist dblist, ext2_ino_t ino,
1935a6d63ae29512d654c8c697f42f32f97b9dc010bChris Lattner				blk64_t blk, e2_blkcnt_t blockcnt)
19488d942d8983aadecae477fee523c23312d194515Misha Brukman{
1955a6d63ae29512d654c8c697f42f32f97b9dc010bChris Lattner	dgrp_t			i;
1965a6d63ae29512d654c8c697f42f32f97b9dc010bChris Lattner
197589df88ba03a81b2b3dc9d084c191a3a74724ecdChris Lattner	EXT2_CHECK_MAGIC(dblist, EXT2_ET_MAGIC_DBLIST);
198589df88ba03a81b2b3dc9d084c191a3a74724ecdChris Lattner
199589df88ba03a81b2b3dc9d084c191a3a74724ecdChris Lattner	for (i=0; i < dblist->count; i++) {
200589df88ba03a81b2b3dc9d084c191a3a74724ecdChris Lattner		if ((dblist->list[i].ino != ino) ||
201589df88ba03a81b2b3dc9d084c191a3a74724ecdChris Lattner		    (dblist->list[i].blockcnt != blockcnt))
202589df88ba03a81b2b3dc9d084c191a3a74724ecdChris Lattner			continue;
2035a6d63ae29512d654c8c697f42f32f97b9dc010bChris Lattner		dblist->list[i].blk = blk;
2047e70829632f82de15db187845666aaca6e04b792Chris Lattner		dblist->sorted = 0;
20588d942d8983aadecae477fee523c23312d194515Misha Brukman		return 0;
2067e70829632f82de15db187845666aaca6e04b792Chris Lattner	}
207589df88ba03a81b2b3dc9d084c191a3a74724ecdChris Lattner	return EXT2_ET_DB_NOT_FOUND;
208589df88ba03a81b2b3dc9d084c191a3a74724ecdChris Lattner}
209589df88ba03a81b2b3dc9d084c191a3a74724ecdChris Lattner
210589df88ba03a81b2b3dc9d084c191a3a74724ecdChris Lattnervoid ext2fs_dblist_sort2(ext2_dblist dblist,
211589df88ba03a81b2b3dc9d084c191a3a74724ecdChris Lattner			 EXT2_QSORT_TYPE (*sortfunc)(const void *,
212589df88ba03a81b2b3dc9d084c191a3a74724ecdChris Lattner						     const void *))
213589df88ba03a81b2b3dc9d084c191a3a74724ecdChris Lattner{
214589df88ba03a81b2b3dc9d084c191a3a74724ecdChris Lattner	if (!sortfunc)
2151ff1da7ac9bff43ba24445ff30ba2fd79bd95cd7Chris Lattner		sortfunc = dir_block_cmp2;
216589df88ba03a81b2b3dc9d084c191a3a74724ecdChris Lattner	qsort(dblist->list, (size_t) dblist->count,
217589df88ba03a81b2b3dc9d084c191a3a74724ecdChris Lattner	      sizeof(struct ext2_db_entry2), sortfunc);
218589df88ba03a81b2b3dc9d084c191a3a74724ecdChris Lattner	dblist->sorted = 1;
219ea0f49e52436272c65b52fe1e83f5009aa191a21Chris Lattner}
220ea0f49e52436272c65b52fe1e83f5009aa191a21Chris Lattner
221589df88ba03a81b2b3dc9d084c191a3a74724ecdChris Lattner/*
222589df88ba03a81b2b3dc9d084c191a3a74724ecdChris Lattner * This function iterates over the directory block list
223589df88ba03a81b2b3dc9d084c191a3a74724ecdChris Lattner */
224589df88ba03a81b2b3dc9d084c191a3a74724ecdChris Lattnererrcode_t ext2fs_dblist_iterate2(ext2_dblist dblist,
225589df88ba03a81b2b3dc9d084c191a3a74724ecdChris Lattner				 int (*func)(ext2_filsys fs,
226589df88ba03a81b2b3dc9d084c191a3a74724ecdChris Lattner					     struct ext2_db_entry2 *db_info,
2271ff1da7ac9bff43ba24445ff30ba2fd79bd95cd7Chris Lattner					     void	*priv_data),
2281ff1da7ac9bff43ba24445ff30ba2fd79bd95cd7Chris Lattner				 void *priv_data)
2297e70829632f82de15db187845666aaca6e04b792Chris Lattner{
2307e70829632f82de15db187845666aaca6e04b792Chris Lattner	unsigned long long	i;
2317e70829632f82de15db187845666aaca6e04b792Chris Lattner	int		ret;
2327e70829632f82de15db187845666aaca6e04b792Chris Lattner
2337e70829632f82de15db187845666aaca6e04b792Chris Lattner	EXT2_CHECK_MAGIC(dblist, EXT2_ET_MAGIC_DBLIST);
2347e70829632f82de15db187845666aaca6e04b792Chris Lattner
2357e70829632f82de15db187845666aaca6e04b792Chris Lattner	if (!dblist->sorted)
2367e70829632f82de15db187845666aaca6e04b792Chris Lattner		ext2fs_dblist_sort2(dblist, 0);
2377e70829632f82de15db187845666aaca6e04b792Chris Lattner	for (i=0; i < dblist->count; i++) {
2387e70829632f82de15db187845666aaca6e04b792Chris Lattner		ret = (*func)(dblist->fs, &dblist->list[i], priv_data);
2397e70829632f82de15db187845666aaca6e04b792Chris Lattner		if (ret & DBLIST_ABORT)
2407e70829632f82de15db187845666aaca6e04b792Chris Lattner			return 0;
2417e70829632f82de15db187845666aaca6e04b792Chris Lattner	}
2427e70829632f82de15db187845666aaca6e04b792Chris Lattner	return 0;
2437e70829632f82de15db187845666aaca6e04b792Chris Lattner}
2447e70829632f82de15db187845666aaca6e04b792Chris Lattner
2457e70829632f82de15db187845666aaca6e04b792Chris Lattnerstatic EXT2_QSORT_TYPE dir_block_cmp2(const void *a, const void *b)
2467e70829632f82de15db187845666aaca6e04b792Chris Lattner{
2477e70829632f82de15db187845666aaca6e04b792Chris Lattner	const struct ext2_db_entry2 *db_a =
2487e70829632f82de15db187845666aaca6e04b792Chris Lattner		(const struct ext2_db_entry2 *) a;
2497e70829632f82de15db187845666aaca6e04b792Chris Lattner	const struct ext2_db_entry2 *db_b =
2507e70829632f82de15db187845666aaca6e04b792Chris Lattner		(const struct ext2_db_entry2 *) b;
2517e70829632f82de15db187845666aaca6e04b792Chris Lattner
2527e70829632f82de15db187845666aaca6e04b792Chris Lattner	if (db_a->blk != db_b->blk)
2537e70829632f82de15db187845666aaca6e04b792Chris Lattner		return (int) (db_a->blk - db_b->blk);
2547e70829632f82de15db187845666aaca6e04b792Chris Lattner
2557e70829632f82de15db187845666aaca6e04b792Chris Lattner	if (db_a->ino != db_b->ino)
2567e70829632f82de15db187845666aaca6e04b792Chris Lattner		return (int) (db_a->ino - db_b->ino);
2577e70829632f82de15db187845666aaca6e04b792Chris Lattner
2587e70829632f82de15db187845666aaca6e04b792Chris Lattner	return (db_a->blockcnt - db_b->blockcnt);
2597e70829632f82de15db187845666aaca6e04b792Chris Lattner}
2607e70829632f82de15db187845666aaca6e04b792Chris Lattner
2617e70829632f82de15db187845666aaca6e04b792Chris Lattnerblk64_t ext2fs_dblist_count2(ext2_dblist dblist)
2627e70829632f82de15db187845666aaca6e04b792Chris Lattner{
2637e70829632f82de15db187845666aaca6e04b792Chris Lattner	return dblist->count;
2647e70829632f82de15db187845666aaca6e04b792Chris Lattner}
2657e70829632f82de15db187845666aaca6e04b792Chris Lattner
2667e70829632f82de15db187845666aaca6e04b792Chris Lattnererrcode_t ext2fs_dblist_get_last2(ext2_dblist dblist,
2677e70829632f82de15db187845666aaca6e04b792Chris Lattner				  struct ext2_db_entry2 **entry)
2687e70829632f82de15db187845666aaca6e04b792Chris Lattner{
2697e70829632f82de15db187845666aaca6e04b792Chris Lattner	EXT2_CHECK_MAGIC(dblist, EXT2_ET_MAGIC_DBLIST);
2707e70829632f82de15db187845666aaca6e04b792Chris Lattner
2717e70829632f82de15db187845666aaca6e04b792Chris Lattner	if (dblist->count == 0)
2727e70829632f82de15db187845666aaca6e04b792Chris Lattner		return EXT2_ET_DBLIST_EMPTY;
2737e70829632f82de15db187845666aaca6e04b792Chris Lattner
2747e70829632f82de15db187845666aaca6e04b792Chris Lattner	if (entry)
2757e70829632f82de15db187845666aaca6e04b792Chris Lattner		*entry = dblist->list + ( dblist->count-1);
2767e70829632f82de15db187845666aaca6e04b792Chris Lattner	return 0;
2777e70829632f82de15db187845666aaca6e04b792Chris Lattner}
2787e70829632f82de15db187845666aaca6e04b792Chris Lattner
2797e70829632f82de15db187845666aaca6e04b792Chris Lattnererrcode_t ext2fs_dblist_drop_last(ext2_dblist dblist)
2807e70829632f82de15db187845666aaca6e04b792Chris Lattner{
2817e70829632f82de15db187845666aaca6e04b792Chris Lattner	EXT2_CHECK_MAGIC(dblist, EXT2_ET_MAGIC_DBLIST);
2827e70829632f82de15db187845666aaca6e04b792Chris Lattner
2837e70829632f82de15db187845666aaca6e04b792Chris Lattner	if (dblist->count == 0)
2847e70829632f82de15db187845666aaca6e04b792Chris Lattner		return EXT2_ET_DBLIST_EMPTY;
2857e70829632f82de15db187845666aaca6e04b792Chris Lattner
2867e70829632f82de15db187845666aaca6e04b792Chris Lattner	dblist->count--;
2877e70829632f82de15db187845666aaca6e04b792Chris Lattner	return 0;
2887e70829632f82de15db187845666aaca6e04b792Chris Lattner}
2897e70829632f82de15db187845666aaca6e04b792Chris Lattner
2907e70829632f82de15db187845666aaca6e04b792Chris Lattner/*
2917e70829632f82de15db187845666aaca6e04b792Chris Lattner * Legacy 32-bit versions
292589df88ba03a81b2b3dc9d084c191a3a74724ecdChris Lattner */
293589df88ba03a81b2b3dc9d084c191a3a74724ecdChris Lattner
294589df88ba03a81b2b3dc9d084c191a3a74724ecdChris Lattner/*
2957e70829632f82de15db187845666aaca6e04b792Chris Lattner * Add a directory block to the directory block list
2967e70829632f82de15db187845666aaca6e04b792Chris Lattner */
297errcode_t ext2fs_add_dir_block(ext2_dblist dblist, ext2_ino_t ino, blk_t blk,
298			       int blockcnt)
299{
300	return ext2fs_add_dir_block2(dblist, ino, blk, blockcnt);
301}
302
303/*
304 * Change the directory block to the directory block list
305 */
306errcode_t ext2fs_set_dir_block(ext2_dblist dblist, ext2_ino_t ino, blk_t blk,
307			       int blockcnt)
308{
309	return ext2fs_set_dir_block2(dblist, ino, blk, blockcnt);
310}
311
312void ext2fs_dblist_sort(ext2_dblist dblist,
313			EXT2_QSORT_TYPE (*sortfunc)(const void *,
314						    const void *))
315{
316	if (sortfunc) {
317		sortfunc32 = sortfunc;
318		sortfunc = dir_block_cmp;
319	} else
320		sortfunc = dir_block_cmp2;
321	qsort(dblist->list, (size_t) dblist->count,
322	      sizeof(struct ext2_db_entry2), sortfunc);
323	dblist->sorted = 1;
324}
325
326/*
327 * This function iterates over the directory block list
328 */
329struct iterate_passthrough {
330	int (*func)(ext2_filsys fs,
331		    struct ext2_db_entry *db_info,
332		    void	*priv_data);
333	void *priv_data;
334};
335
336static int passthrough_func(ext2_filsys fs,
337			    struct ext2_db_entry2 *db_info,
338			    void	*priv_data)
339{
340	struct iterate_passthrough *p = priv_data;
341	struct ext2_db_entry db;
342	int ret;
343
344	db.ino = db_info->ino;
345	db.blk = (blk_t) db_info->blk;
346	db.blockcnt = (int) db_info->blockcnt;
347	ret = (p->func)(fs, &db, p->priv_data);
348	db_info->ino = db.ino;
349	db_info->blk = db.blk;
350	db_info->blockcnt = db.blockcnt;
351	return ret;
352}
353
354errcode_t ext2fs_dblist_iterate(ext2_dblist dblist,
355				int (*func)(ext2_filsys fs,
356					    struct ext2_db_entry *db_info,
357					    void	*priv_data),
358				void *priv_data)
359{
360	struct iterate_passthrough pass;
361
362	EXT2_CHECK_MAGIC(dblist, EXT2_ET_MAGIC_DBLIST);
363	pass.func = func;
364	pass.priv_data = priv_data;
365
366	return ext2fs_dblist_iterate2(dblist, passthrough_func, &pass);
367}
368
369static EXT2_QSORT_TYPE dir_block_cmp(const void *a, const void *b)
370{
371	const struct ext2_db_entry2 *db_a =
372		(const struct ext2_db_entry2 *) a;
373	const struct ext2_db_entry2 *db_b =
374		(const struct ext2_db_entry2 *) b;
375
376	struct ext2_db_entry a32, b32;
377
378	a32.ino = db_a->ino;  a32.blk = db_a->blk;
379	a32.blockcnt = db_a->blockcnt;
380
381	b32.ino = db_b->ino;  b32.blk = db_b->blk;
382	b32.blockcnt = db_b->blockcnt;
383
384	return sortfunc32(&a32, &b32);
385}
386
387int ext2fs_dblist_count(ext2_dblist dblist)
388{
389	return dblist->count;
390}
391
392errcode_t ext2fs_dblist_get_last(ext2_dblist dblist,
393				 struct ext2_db_entry **entry)
394{
395	EXT2_CHECK_MAGIC(dblist, EXT2_ET_MAGIC_DBLIST);
396	static struct ext2_db_entry ret_entry;
397	struct ext2_db_entry2 *last;
398
399	if (dblist->count == 0)
400		return EXT2_ET_DBLIST_EMPTY;
401
402	if (!entry)
403		return 0;
404
405	last = dblist->list + dblist->count -1;
406
407	ret_entry.ino = last->ino;
408	ret_entry.blk = last->blk;
409	ret_entry.blockcnt = last->blockcnt;
410	*entry = &ret_entry;
411
412	return 0;
413}
414
415