static errcode_t get_inode_count(ext2_icount_t icount, ext2_ino_t ino, __u32 *count) { struct ext2_icount_el *el; TDB_DATA key, data; if (icount->tdb) { key.dptr = (unsigned char *) &ino; key.dsize = sizeof(ext2_ino_t); data = tdb_fetch(icount->tdb, key); if (data.dptr == NULL) { *count = 0; return tdb_error(icount->tdb) + EXT2_ET_TDB_SUCCESS; } *count = *((__u32 *) data.dptr); free(data.dptr); return 0; } el = get_icount_el(icount, ino, 0); if (!el) { *count = 0; return ENOENT; } *count = el->count; return 0; }
static errcode_t set_inode_count(ext2_icount_t icount, ext2_ino_t ino, __u32 count) { struct ext2_icount_el *el; TDB_DATA key, data; if (icount->tdb) { key.dptr = (unsigned char *) &ino; key.dsize = sizeof(ext2_ino_t); data.dptr = (unsigned char *) &count; data.dsize = sizeof(__u32); if (count) { if (tdb_store(icount->tdb, key, data, TDB_REPLACE)) return tdb_error(icount->tdb) + EXT2_ET_TDB_SUCCESS; } else { if (tdb_delete(icount->tdb, key)) return tdb_error(icount->tdb) + EXT2_ET_TDB_SUCCESS; } return 0; } el = get_icount_el(icount, ino, 1); if (!el) return EXT2_ET_NO_MEMORY; el->count = count; return 0; }
errcode_t ext2fs_icount_fetch(ext2_icount_t icount, ext2_ino_t ino, __u16 *ret) { struct ext2_icount_el *el; EXT2_CHECK_MAGIC(icount, EXT2_ET_MAGIC_ICOUNT); if (!ino || (ino > icount->num_inodes)) return EXT2_ET_INVALID_ARGUMENT; if (ext2fs_test_inode_bitmap(icount->single, ino)) { *ret = 1; return 0; } if (icount->multiple && !ext2fs_test_inode_bitmap(icount->multiple, ino)) { *ret = 0; return 0; } el = get_icount_el(icount, ino, 0); if (!el) { *ret = 0; return 0; } *ret = el->count; return 0; }
errcode_t ext2fs_icount_store(ext2_icount_t icount, ext2_ino_t ino, __u16 count) { struct ext2_icount_el *el; if (!ino || (ino > icount->num_inodes)) return EXT2_ET_INVALID_ARGUMENT; EXT2_CHECK_MAGIC(icount, EXT2_ET_MAGIC_ICOUNT); if (count == 1) { ext2fs_mark_inode_bitmap(icount->single, ino); if (icount->multiple) ext2fs_unmark_inode_bitmap(icount->multiple, ino); return 0; } if (count == 0) { ext2fs_unmark_inode_bitmap(icount->single, ino); if (icount->multiple) { /* * If the icount->multiple bitmap is enabled, * we can just clear both bitmaps and we're done */ ext2fs_unmark_inode_bitmap(icount->multiple, ino); } else { el = get_icount_el(icount, ino, 0); if (el) el->count = 0; } return 0; } /* * Get the icount element */ el = get_icount_el(icount, ino, 1); if (!el) return EXT2_ET_NO_MEMORY; el->count = count; ext2fs_unmark_inode_bitmap(icount->single, ino); if (icount->multiple) ext2fs_mark_inode_bitmap(icount->multiple, ino); return 0; }
errcode_t ext2fs_icount_decrement(ext2_icount_t icount, ext2_ino_t ino, __u16 *ret) { struct ext2_icount_el *el; if (!ino || (ino > icount->num_inodes)) return EXT2_ET_INVALID_ARGUMENT; EXT2_CHECK_MAGIC(icount, EXT2_ET_MAGIC_ICOUNT); if (ext2fs_test_inode_bitmap(icount->single, ino)) { ext2fs_unmark_inode_bitmap(icount->single, ino); if (icount->multiple) ext2fs_unmark_inode_bitmap(icount->multiple, ino); else { el = get_icount_el(icount, ino, 0); if (el) el->count = 0; } if (ret) *ret = 0; return 0; } if (icount->multiple && !ext2fs_test_inode_bitmap(icount->multiple, ino)) return EXT2_ET_INVALID_ARGUMENT; el = get_icount_el(icount, ino, 0); if (!el || el->count == 0) return EXT2_ET_INVALID_ARGUMENT; el->count--; if (el->count == 1) ext2fs_mark_inode_bitmap(icount->single, ino); if ((el->count == 0) && icount->multiple) ext2fs_unmark_inode_bitmap(icount->multiple, ino); if (ret) *ret = el->count; return 0; }
errcode_t ext2fs_icount_increment(ext2_icount_t icount, ext2_ino_t ino, __u16 *ret) { struct ext2_icount_el *el; EXT2_CHECK_MAGIC(icount, EXT2_ET_MAGIC_ICOUNT); if (!ino || (ino > icount->num_inodes)) return EXT2_ET_INVALID_ARGUMENT; if (ext2fs_test_inode_bitmap(icount->single, ino)) { /* * If the existing count is 1, then we know there is * no entry in the list. */ el = get_icount_el(icount, ino, 1); if (!el) return EXT2_ET_NO_MEMORY; ext2fs_unmark_inode_bitmap(icount->single, ino); el->count = 2; } else if (icount->multiple) { /* * The count is either zero or greater than 1; if the * inode is set in icount->multiple, then there should * be an entry in the list, so find it using * get_icount_el(). */ if (ext2fs_test_inode_bitmap(icount->multiple, ino)) { el = get_icount_el(icount, ino, 1); if (!el) return EXT2_ET_NO_MEMORY; el->count++; } else { /* * The count was zero; mark the single bitmap * and return. */ zero_count: ext2fs_mark_inode_bitmap(icount->single, ino); if (ret) *ret = 1; return 0; } } else { /* * The count is either zero or greater than 1; try to * find an entry in the list to determine which. */ el = get_icount_el(icount, ino, 0); if (!el) { /* No entry means the count was zero */ goto zero_count; } el = get_icount_el(icount, ino, 1); if (!el) return EXT2_ET_NO_MEMORY; el->count++; } if (icount->multiple) ext2fs_mark_inode_bitmap(icount->multiple, ino); if (ret) *ret = el->count; return 0; }