121c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o/* 221c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o * dblist.c -- directory block list functions 3efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o * 421c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o * Copyright 1997 by Theodore Ts'o 5efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o * 621c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o * %Begin-Header% 7543547a52a20cb7e69d74921b2f691078fd55d83Theodore Ts'o * This file may be redistributed under the terms of the GNU Library 8543547a52a20cb7e69d74921b2f691078fd55d83Theodore Ts'o * General Public License, version 2. 921c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o * %End-Header% 1021c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o */ 1121c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o 1221c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o#include <stdio.h> 134cbe8af4b0d0c72fb28bb500c1bd8a46b00fdde3Theodore Ts'o#if HAVE_UNISTD_H 1421c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o#include <unistd.h> 154cbe8af4b0d0c72fb28bb500c1bd8a46b00fdde3Theodore Ts'o#endif 1621c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o#include <string.h> 1721c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o#include <time.h> 1821c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o 19b5abe6fac9c9e7caf4710501d1657d30e4857ef6Theodore Ts'o#include "ext2_fs.h" 2021c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o#include "ext2fsP.h" 2121c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o 224c77fe50d97a773e32a4756c79dade3adbb6a601Theodore Ts'ostatic EXT2_QSORT_TYPE dir_block_cmp(const void *a, const void *b); 23e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrallstatic EXT2_QSORT_TYPE dir_block_cmp2(const void *a, const void *b); 24e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrallstatic EXT2_QSORT_TYPE (*sortfunc32)(const void *a, const void *b); 2521c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o 2621c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o/* 2721c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o * Returns the number of directories in the filesystem as reported by 2821c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o * the group descriptors. Of course, the group descriptors could be 2921c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o * wrong! 3021c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o */ 3131dbecd482405e0d3a67eb58e1a1c8cb9f2ad83eTheodore Ts'oerrcode_t ext2fs_get_num_dirs(ext2_filsys fs, ext2_ino_t *ret_num_dirs) 3221c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o{ 332eb374c9401079aa56aa12f0047ca3866e69b754Theodore Ts'o dgrp_t i; 3431dbecd482405e0d3a67eb58e1a1c8cb9f2ad83eTheodore Ts'o ext2_ino_t num_dirs, max_dirs; 3521c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o 3621c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS); 37efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o 3821c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o num_dirs = 0; 3979b05dbed2003cd678ba6b210695420486ce920dTheodore Ts'o max_dirs = fs->super->s_inodes_per_group; 405be8dc2143c7b3b21a9b8fb56797dd855ee87560Theodore Ts'o for (i = 0; i < fs->group_desc_count; i++) { 41e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall if (ext2fs_bg_used_dirs_count(fs, i) > max_dirs) 4279b05dbed2003cd678ba6b210695420486ce920dTheodore Ts'o num_dirs += max_dirs / 8; 435be8dc2143c7b3b21a9b8fb56797dd855ee87560Theodore Ts'o else 44e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall num_dirs += ext2fs_bg_used_dirs_count(fs, i); 455be8dc2143c7b3b21a9b8fb56797dd855ee87560Theodore Ts'o } 465be8dc2143c7b3b21a9b8fb56797dd855ee87560Theodore Ts'o if (num_dirs > fs->super->s_inodes_count) 475be8dc2143c7b3b21a9b8fb56797dd855ee87560Theodore Ts'o num_dirs = fs->super->s_inodes_count; 4821c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o 4921c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o *ret_num_dirs = num_dirs; 5021c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o 5121c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o return 0; 5221c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o} 5321c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o 5421c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o/* 55a29f4d30f24d68f1f1c75548e020689ede532c05Theodore Ts'o * helper function for making a new directory block list (for 56a29f4d30f24d68f1f1c75548e020689ede532c05Theodore Ts'o * initialize and copy). 5721c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o */ 58e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrallstatic errcode_t make_dblist(ext2_filsys fs, ext2_ino_t size, 59e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall ext2_ino_t count, 60e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall struct ext2_db_entry2 *list, 61a29f4d30f24d68f1f1c75548e020689ede532c05Theodore Ts'o ext2_dblist *ret_dblist) 6221c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o{ 63e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall ext2_dblist dblist = NULL; 6421c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o errcode_t retval; 65e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall ext2_ino_t num_dirs; 66a29f4d30f24d68f1f1c75548e020689ede532c05Theodore Ts'o size_t len; 6721c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o 6821c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS); 6921c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o 7021c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o if ((ret_dblist == 0) && fs->dblist && 7121c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o (fs->dblist->magic == EXT2_ET_MAGIC_DBLIST)) 7221c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o return 0; 7321c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o 74c4e3d3f374b409500e3dd05c0b0eca6ac98a6b4eTheodore Ts'o retval = ext2fs_get_mem(sizeof(struct ext2_struct_dblist), &dblist); 757b4e4534f9361b21d3fafdd88a58f133decee38cTheodore Ts'o if (retval) 76e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall goto cleanup; 7721c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o memset(dblist, 0, sizeof(struct ext2_struct_dblist)); 7821c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o 7921c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o dblist->magic = EXT2_ET_MAGIC_DBLIST; 8021c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o dblist->fs = fs; 81a29f4d30f24d68f1f1c75548e020689ede532c05Theodore Ts'o if (size) 82a29f4d30f24d68f1f1c75548e020689ede532c05Theodore Ts'o dblist->size = size; 83a29f4d30f24d68f1f1c75548e020689ede532c05Theodore Ts'o else { 84e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall retval = ext2fs_get_num_dirs(fs, &num_dirs); 85a29f4d30f24d68f1f1c75548e020689ede532c05Theodore Ts'o if (retval) 86a29f4d30f24d68f1f1c75548e020689ede532c05Theodore Ts'o goto cleanup; 87e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall dblist->size = (num_dirs * 2) + 12; 88a29f4d30f24d68f1f1c75548e020689ede532c05Theodore Ts'o } 89e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall len = (size_t) sizeof(struct ext2_db_entry2) * dblist->size; 90a29f4d30f24d68f1f1c75548e020689ede532c05Theodore Ts'o dblist->count = count; 91e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall retval = ext2fs_get_array(dblist->size, sizeof(struct ext2_db_entry2), 92ee01079a17bfecd17292ccd60058056fb3a8ba6cTheodore Ts'o &dblist->list); 937b4e4534f9361b21d3fafdd88a58f133decee38cTheodore Ts'o if (retval) 9421c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o goto cleanup; 95efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o 96a29f4d30f24d68f1f1c75548e020689ede532c05Theodore Ts'o if (list) 97a29f4d30f24d68f1f1c75548e020689ede532c05Theodore Ts'o memcpy(dblist->list, list, len); 9821c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o else 99a29f4d30f24d68f1f1c75548e020689ede532c05Theodore Ts'o memset(dblist->list, 0, len); 1002eb374c9401079aa56aa12f0047ca3866e69b754Theodore Ts'o if (ret_dblist) 1012eb374c9401079aa56aa12f0047ca3866e69b754Theodore Ts'o *ret_dblist = dblist; 1022eb374c9401079aa56aa12f0047ca3866e69b754Theodore Ts'o else 1032eb374c9401079aa56aa12f0047ca3866e69b754Theodore Ts'o fs->dblist = dblist; 10421c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o return 0; 10521c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'ocleanup: 10621c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o if (dblist) 107c4e3d3f374b409500e3dd05c0b0eca6ac98a6b4eTheodore Ts'o ext2fs_free_mem(&dblist); 10821c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o return retval; 10921c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o} 11021c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o 11121c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o/* 112a29f4d30f24d68f1f1c75548e020689ede532c05Theodore Ts'o * Initialize a directory block list 113a29f4d30f24d68f1f1c75548e020689ede532c05Theodore Ts'o */ 114a29f4d30f24d68f1f1c75548e020689ede532c05Theodore Ts'oerrcode_t ext2fs_init_dblist(ext2_filsys fs, ext2_dblist *ret_dblist) 115a29f4d30f24d68f1f1c75548e020689ede532c05Theodore Ts'o{ 116a29f4d30f24d68f1f1c75548e020689ede532c05Theodore Ts'o ext2_dblist dblist; 117a29f4d30f24d68f1f1c75548e020689ede532c05Theodore Ts'o errcode_t retval; 118a29f4d30f24d68f1f1c75548e020689ede532c05Theodore Ts'o 119a29f4d30f24d68f1f1c75548e020689ede532c05Theodore Ts'o retval = make_dblist(fs, 0, 0, 0, &dblist); 120a29f4d30f24d68f1f1c75548e020689ede532c05Theodore Ts'o if (retval) 121a29f4d30f24d68f1f1c75548e020689ede532c05Theodore Ts'o return retval; 122a29f4d30f24d68f1f1c75548e020689ede532c05Theodore Ts'o 123a29f4d30f24d68f1f1c75548e020689ede532c05Theodore Ts'o dblist->sorted = 1; 124a29f4d30f24d68f1f1c75548e020689ede532c05Theodore Ts'o if (ret_dblist) 125a29f4d30f24d68f1f1c75548e020689ede532c05Theodore Ts'o *ret_dblist = dblist; 126a29f4d30f24d68f1f1c75548e020689ede532c05Theodore Ts'o else 127a29f4d30f24d68f1f1c75548e020689ede532c05Theodore Ts'o fs->dblist = dblist; 128a29f4d30f24d68f1f1c75548e020689ede532c05Theodore Ts'o 129a29f4d30f24d68f1f1c75548e020689ede532c05Theodore Ts'o return 0; 130a29f4d30f24d68f1f1c75548e020689ede532c05Theodore Ts'o} 131a29f4d30f24d68f1f1c75548e020689ede532c05Theodore Ts'o 132a29f4d30f24d68f1f1c75548e020689ede532c05Theodore Ts'o/* 133a29f4d30f24d68f1f1c75548e020689ede532c05Theodore Ts'o * Copy a directory block list 134a29f4d30f24d68f1f1c75548e020689ede532c05Theodore Ts'o */ 135a29f4d30f24d68f1f1c75548e020689ede532c05Theodore Ts'oerrcode_t ext2fs_copy_dblist(ext2_dblist src, ext2_dblist *dest) 136a29f4d30f24d68f1f1c75548e020689ede532c05Theodore Ts'o{ 137a29f4d30f24d68f1f1c75548e020689ede532c05Theodore Ts'o ext2_dblist dblist; 138a29f4d30f24d68f1f1c75548e020689ede532c05Theodore Ts'o errcode_t retval; 139a29f4d30f24d68f1f1c75548e020689ede532c05Theodore Ts'o 140a29f4d30f24d68f1f1c75548e020689ede532c05Theodore Ts'o retval = make_dblist(src->fs, src->size, src->count, src->list, 141a29f4d30f24d68f1f1c75548e020689ede532c05Theodore Ts'o &dblist); 142a29f4d30f24d68f1f1c75548e020689ede532c05Theodore Ts'o if (retval) 143a29f4d30f24d68f1f1c75548e020689ede532c05Theodore Ts'o return retval; 144a29f4d30f24d68f1f1c75548e020689ede532c05Theodore Ts'o dblist->sorted = src->sorted; 145a29f4d30f24d68f1f1c75548e020689ede532c05Theodore Ts'o *dest = dblist; 146a29f4d30f24d68f1f1c75548e020689ede532c05Theodore Ts'o return 0; 147a29f4d30f24d68f1f1c75548e020689ede532c05Theodore Ts'o} 148a29f4d30f24d68f1f1c75548e020689ede532c05Theodore Ts'o 149a29f4d30f24d68f1f1c75548e020689ede532c05Theodore Ts'o/* 15021c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o * Close a directory block list 15121c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o * 15221c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o * (moved to closefs.c) 15321c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o */ 15421c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o 15521c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o 15621c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o/* 15721c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o * Add a directory block to the directory block list 15821c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o */ 159e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrallerrcode_t ext2fs_add_dir_block2(ext2_dblist dblist, ext2_ino_t ino, 160e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall blk64_t blk, e2_blkcnt_t blockcnt) 16121c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o{ 162e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall struct ext2_db_entry2 *new_entry; 1637b4e4534f9361b21d3fafdd88a58f133decee38cTheodore Ts'o errcode_t retval; 16476f875daa1c9c2cdc72f0c6f0f7be4bbc7f0fc07Theodore Ts'o unsigned long old_size; 165efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o 16621c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o EXT2_CHECK_MAGIC(dblist, EXT2_ET_MAGIC_DBLIST); 16721c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o 16821c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o if (dblist->count >= dblist->size) { 169e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall old_size = dblist->size * sizeof(struct ext2_db_entry2); 1709f9e5c3aea024c92c50e8bb834a3ea33d9e1f55dAndreas Dilger dblist->size += dblist->size > 200 ? dblist->size / 2 : 100; 17176f875daa1c9c2cdc72f0c6f0f7be4bbc7f0fc07Theodore Ts'o retval = ext2fs_resize_mem(old_size, (size_t) dblist->size * 172e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall sizeof(struct ext2_db_entry2), 173c4e3d3f374b409500e3dd05c0b0eca6ac98a6b4eTheodore Ts'o &dblist->list); 1747b4e4534f9361b21d3fafdd88a58f133decee38cTheodore Ts'o if (retval) { 175e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall dblist->size = old_size / sizeof(struct ext2_db_entry2); 1767b4e4534f9361b21d3fafdd88a58f133decee38cTheodore Ts'o return retval; 17721c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o } 17821c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o } 179e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall new_entry = dblist->list + ( dblist->count++); 180b5abe6fac9c9e7caf4710501d1657d30e4857ef6Theodore Ts'o new_entry->blk = blk; 181b5abe6fac9c9e7caf4710501d1657d30e4857ef6Theodore Ts'o new_entry->ino = ino; 182b5abe6fac9c9e7caf4710501d1657d30e4857ef6Theodore Ts'o new_entry->blockcnt = blockcnt; 18321c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o 18421c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o dblist->sorted = 0; 18521c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o 18621c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o return 0; 18721c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o} 18821c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o 18921c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o/* 190521e36857227b21e7ab47b0a97f788d2af9f9717Theodore Ts'o * Change the directory block to the directory block list 191521e36857227b21e7ab47b0a97f788d2af9f9717Theodore Ts'o */ 192e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrallerrcode_t ext2fs_set_dir_block2(ext2_dblist dblist, ext2_ino_t ino, 193e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall blk64_t blk, e2_blkcnt_t blockcnt) 194521e36857227b21e7ab47b0a97f788d2af9f9717Theodore Ts'o{ 1952eb374c9401079aa56aa12f0047ca3866e69b754Theodore Ts'o dgrp_t i; 196efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o 197521e36857227b21e7ab47b0a97f788d2af9f9717Theodore Ts'o EXT2_CHECK_MAGIC(dblist, EXT2_ET_MAGIC_DBLIST); 198521e36857227b21e7ab47b0a97f788d2af9f9717Theodore Ts'o 199521e36857227b21e7ab47b0a97f788d2af9f9717Theodore Ts'o for (i=0; i < dblist->count; i++) { 200521e36857227b21e7ab47b0a97f788d2af9f9717Theodore Ts'o if ((dblist->list[i].ino != ino) || 201521e36857227b21e7ab47b0a97f788d2af9f9717Theodore Ts'o (dblist->list[i].blockcnt != blockcnt)) 202521e36857227b21e7ab47b0a97f788d2af9f9717Theodore Ts'o continue; 203521e36857227b21e7ab47b0a97f788d2af9f9717Theodore Ts'o dblist->list[i].blk = blk; 204521e36857227b21e7ab47b0a97f788d2af9f9717Theodore Ts'o dblist->sorted = 0; 205521e36857227b21e7ab47b0a97f788d2af9f9717Theodore Ts'o return 0; 206521e36857227b21e7ab47b0a97f788d2af9f9717Theodore Ts'o } 2071f0b6c1f895d189fea6999d0c07a7fee936a4baaTheodore Ts'o return EXT2_ET_DB_NOT_FOUND; 208521e36857227b21e7ab47b0a97f788d2af9f9717Theodore Ts'o} 209521e36857227b21e7ab47b0a97f788d2af9f9717Theodore Ts'o 210e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrallvoid ext2fs_dblist_sort2(ext2_dblist dblist, 211e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall EXT2_QSORT_TYPE (*sortfunc)(const void *, 212e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall const void *)) 213ea1959f01523ffc105747d660ccc5b7f02805928Theodore Ts'o{ 214ea1959f01523ffc105747d660ccc5b7f02805928Theodore Ts'o if (!sortfunc) 215e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall sortfunc = dir_block_cmp2; 216ea1959f01523ffc105747d660ccc5b7f02805928Theodore Ts'o qsort(dblist->list, (size_t) dblist->count, 217e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall sizeof(struct ext2_db_entry2), sortfunc); 218ea1959f01523ffc105747d660ccc5b7f02805928Theodore Ts'o dblist->sorted = 1; 219ea1959f01523ffc105747d660ccc5b7f02805928Theodore Ts'o} 220ea1959f01523ffc105747d660ccc5b7f02805928Theodore Ts'o 221521e36857227b21e7ab47b0a97f788d2af9f9717Theodore Ts'o/* 22221c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o * This function iterates over the directory block list 22321c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o */ 224e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrallerrcode_t ext2fs_dblist_iterate2(ext2_dblist dblist, 225e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall int (*func)(ext2_filsys fs, 226e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall struct ext2_db_entry2 *db_info, 227e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall void *priv_data), 228e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall void *priv_data) 22921c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o{ 230e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall unsigned long long i; 23131dbecd482405e0d3a67eb58e1a1c8cb9f2ad83eTheodore Ts'o int ret; 232efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o 23321c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o EXT2_CHECK_MAGIC(dblist, EXT2_ET_MAGIC_DBLIST); 23421c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o 235ea1959f01523ffc105747d660ccc5b7f02805928Theodore Ts'o if (!dblist->sorted) 236e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall ext2fs_dblist_sort2(dblist, 0); 23721c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o for (i=0; i < dblist->count; i++) { 238e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall ret = (*func)(dblist->fs, &dblist->list[i], priv_data); 23921c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o if (ret & DBLIST_ABORT) 24021c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o return 0; 24121c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o } 24221c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o return 0; 24321c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o} 24421c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o 245e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrallstatic EXT2_QSORT_TYPE dir_block_cmp2(const void *a, const void *b) 24621c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o{ 247e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall const struct ext2_db_entry2 *db_a = 248e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall (const struct ext2_db_entry2 *) a; 249e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall const struct ext2_db_entry2 *db_b = 250e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall (const struct ext2_db_entry2 *) b; 25121c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o 25221c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o if (db_a->blk != db_b->blk) 2533cb6c5021d722e17b7105d1bc090880671f6fc6dTheodore Ts'o return (int) (db_a->blk - db_b->blk); 254efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o 25521c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o if (db_a->ino != db_b->ino) 2563cb6c5021d722e17b7105d1bc090880671f6fc6dTheodore Ts'o return (int) (db_a->ino - db_b->ino); 25721c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o 258e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall return (db_a->blockcnt - db_b->blockcnt); 25921c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o} 26021c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o 261e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrallblk64_t ext2fs_dblist_count2(ext2_dblist dblist) 262549860c5c7a5a2974c103a55d881fbd5701aff13Theodore Ts'o{ 263e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall return dblist->count; 264549860c5c7a5a2974c103a55d881fbd5701aff13Theodore Ts'o} 26552b1dd5e496c199e9cbcc238f26fd2264a07a2cfTheodore Ts'o 266e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrallerrcode_t ext2fs_dblist_get_last2(ext2_dblist dblist, 267e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall struct ext2_db_entry2 **entry) 26852b1dd5e496c199e9cbcc238f26fd2264a07a2cfTheodore Ts'o{ 26952b1dd5e496c199e9cbcc238f26fd2264a07a2cfTheodore Ts'o EXT2_CHECK_MAGIC(dblist, EXT2_ET_MAGIC_DBLIST); 27052b1dd5e496c199e9cbcc238f26fd2264a07a2cfTheodore Ts'o 27152b1dd5e496c199e9cbcc238f26fd2264a07a2cfTheodore Ts'o if (dblist->count == 0) 27252b1dd5e496c199e9cbcc238f26fd2264a07a2cfTheodore Ts'o return EXT2_ET_DBLIST_EMPTY; 27352b1dd5e496c199e9cbcc238f26fd2264a07a2cfTheodore Ts'o 27452b1dd5e496c199e9cbcc238f26fd2264a07a2cfTheodore Ts'o if (entry) 275e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall *entry = dblist->list + ( dblist->count-1); 27652b1dd5e496c199e9cbcc238f26fd2264a07a2cfTheodore Ts'o return 0; 27752b1dd5e496c199e9cbcc238f26fd2264a07a2cfTheodore Ts'o} 27852b1dd5e496c199e9cbcc238f26fd2264a07a2cfTheodore Ts'o 27952b1dd5e496c199e9cbcc238f26fd2264a07a2cfTheodore Ts'oerrcode_t ext2fs_dblist_drop_last(ext2_dblist dblist) 280efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o{ 28152b1dd5e496c199e9cbcc238f26fd2264a07a2cfTheodore Ts'o EXT2_CHECK_MAGIC(dblist, EXT2_ET_MAGIC_DBLIST); 28252b1dd5e496c199e9cbcc238f26fd2264a07a2cfTheodore Ts'o 28352b1dd5e496c199e9cbcc238f26fd2264a07a2cfTheodore Ts'o if (dblist->count == 0) 28452b1dd5e496c199e9cbcc238f26fd2264a07a2cfTheodore Ts'o return EXT2_ET_DBLIST_EMPTY; 28552b1dd5e496c199e9cbcc238f26fd2264a07a2cfTheodore Ts'o 28652b1dd5e496c199e9cbcc238f26fd2264a07a2cfTheodore Ts'o dblist->count--; 28752b1dd5e496c199e9cbcc238f26fd2264a07a2cfTheodore Ts'o return 0; 28852b1dd5e496c199e9cbcc238f26fd2264a07a2cfTheodore Ts'o} 289e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 290e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall/* 291e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall * Legacy 32-bit versions 292e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall */ 293e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 294e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall/* 295e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall * Add a directory block to the directory block list 296e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall */ 297e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrallerrcode_t ext2fs_add_dir_block(ext2_dblist dblist, ext2_ino_t ino, blk_t blk, 298e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall int blockcnt) 299e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall{ 300e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall return ext2fs_add_dir_block2(dblist, ino, blk, blockcnt); 301e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall} 302e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 303e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall/* 304e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall * Change the directory block to the directory block list 305e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall */ 306e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrallerrcode_t ext2fs_set_dir_block(ext2_dblist dblist, ext2_ino_t ino, blk_t blk, 307e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall int blockcnt) 308e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall{ 309e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall return ext2fs_set_dir_block2(dblist, ino, blk, blockcnt); 310e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall} 311e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 312e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrallvoid ext2fs_dblist_sort(ext2_dblist dblist, 313e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall EXT2_QSORT_TYPE (*sortfunc)(const void *, 314e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall const void *)) 315e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall{ 316e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall if (sortfunc) { 317e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall sortfunc32 = sortfunc; 318e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall sortfunc = dir_block_cmp; 319e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall } else 320e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall sortfunc = dir_block_cmp2; 321e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall qsort(dblist->list, (size_t) dblist->count, 322e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall sizeof(struct ext2_db_entry2), sortfunc); 323e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall dblist->sorted = 1; 324e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall} 325e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 326e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall/* 327e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall * This function iterates over the directory block list 328e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall */ 329e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrallstruct iterate_passthrough { 330e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall int (*func)(ext2_filsys fs, 331e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall struct ext2_db_entry *db_info, 332e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall void *priv_data); 333e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall void *priv_data; 334e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall}; 335e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 336e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrallstatic int passthrough_func(ext2_filsys fs, 337e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall struct ext2_db_entry2 *db_info, 338e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall void *priv_data) 339e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall{ 340e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall struct iterate_passthrough *p = priv_data; 341e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall struct ext2_db_entry db; 342e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall int ret; 343e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 344e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall db.ino = db_info->ino; 345e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall db.blk = (blk_t) db_info->blk; 346e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall db.blockcnt = (int) db_info->blockcnt; 347e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall ret = (p->func)(fs, &db, p->priv_data); 348e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall db_info->ino = db.ino; 349e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall db_info->blk = db.blk; 350e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall db_info->blockcnt = db.blockcnt; 351e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall return ret; 352e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall} 353e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 354e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrallerrcode_t ext2fs_dblist_iterate(ext2_dblist dblist, 355e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall int (*func)(ext2_filsys fs, 356e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall struct ext2_db_entry *db_info, 357e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall void *priv_data), 358e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall void *priv_data) 359e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall{ 360e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall struct iterate_passthrough pass; 361e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 362e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall EXT2_CHECK_MAGIC(dblist, EXT2_ET_MAGIC_DBLIST); 363e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall pass.func = func; 364e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall pass.priv_data = priv_data; 365e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 366e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall return ext2fs_dblist_iterate2(dblist, passthrough_func, &pass); 367e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall} 368e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 369e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrallstatic EXT2_QSORT_TYPE dir_block_cmp(const void *a, const void *b) 370e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall{ 371e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall const struct ext2_db_entry2 *db_a = 372e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall (const struct ext2_db_entry2 *) a; 373e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall const struct ext2_db_entry2 *db_b = 374e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall (const struct ext2_db_entry2 *) b; 375e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 376e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall struct ext2_db_entry a32, b32; 377e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 378e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall a32.ino = db_a->ino; a32.blk = db_a->blk; 379e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall a32.blockcnt = db_a->blockcnt; 380e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 381e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall b32.ino = db_b->ino; b32.blk = db_b->blk; 382e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall b32.blockcnt = db_b->blockcnt; 383e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 384e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall return sortfunc32(&a32, &b32); 385e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall} 386e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 387e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrallint ext2fs_dblist_count(ext2_dblist dblist) 388e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall{ 389e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall return dblist->count; 390e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall} 391e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 392e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrallerrcode_t ext2fs_dblist_get_last(ext2_dblist dblist, 393e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall struct ext2_db_entry **entry) 394e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall{ 395e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall static struct ext2_db_entry ret_entry; 396e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall struct ext2_db_entry2 *last; 397e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 398e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall EXT2_CHECK_MAGIC(dblist, EXT2_ET_MAGIC_DBLIST); 399e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 400e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall if (dblist->count == 0) 401e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall return EXT2_ET_DBLIST_EMPTY; 402e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 403e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall if (!entry) 404e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall return 0; 405e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 406e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall last = dblist->list + dblist->count -1; 407e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 408e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall ret_entry.ino = last->ino; 409e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall ret_entry.blk = last->blk; 410e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall ret_entry.blockcnt = last->blockcnt; 411e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall *entry = &ret_entry; 412e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 413e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall return 0; 414e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall} 415e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 416