📄 reiserfslib.c
字号:
/* * Copyright 2000-2004 by Hans Reiser, licensing governed by * reiserfsprogs/README */#define _GNU_SOURCE#include "includes.h"#include <linux/kdev_t.h>struct key root_dir_key = {0, 0, {{0, 0},}};struct key parent_root_dir_key = {0, 0, {{0, 0},}};struct key lost_found_dir_key = {0, 0, {{0, 0}, }};struct key badblock_key = {BADBLOCK_DIRID, BADBLOCK_OBJID, {{0, 0},}};__u16 root_dir_format = 0;__u16 lost_found_dir_format = 0;static void make_const_keys (void){ set_key_dirid (&root_dir_key, REISERFS_ROOT_PARENT_OBJECTID); set_key_objectid (&root_dir_key, REISERFS_ROOT_OBJECTID); set_key_dirid (&parent_root_dir_key, 0); set_key_objectid (&parent_root_dir_key, REISERFS_ROOT_PARENT_OBJECTID);}/* reiserfs needs at least: enough blocks for journal, 64 k at the beginning, one block for super block, bitmap block and root block. Note that first bitmap block must point to all of them */int is_block_count_correct (unsigned long journal_offset, unsigned int block_size, unsigned long block_count, unsigned long journal_size){ unsigned long blocks; /* RESERVED, MD RAID SBs, super block, bitmap, root, journal size with journal header */ blocks = journal_offset + journal_size; /* we have a limit: skipped area, super block, journal and root block all have to be addressed by one first bitmap */ if (blocks > block_size * 8) return 0; if (blocks > block_count) return 0; return 1;}/* read super block. fixme: only 4k blocks, pre-journaled format is refused. Journal and bitmap are to be opened separately. skip_check is set to 1 if checks of openned SB should be omitted.*/reiserfs_filsys_t * reiserfs_open (char * filename, int flags, int *error, void * vp, int check){ reiserfs_filsys_t * fs; struct buffer_head * bh; struct reiserfs_super_block * sb; int fd, i; /* convert root dir key and parent root dir key to little endian format */ make_const_keys (); if (error) *error = 0; fd = open (filename, flags #if defined(O_LARGEFILE) | O_LARGEFILE#endif ); if (fd == -1) { if (error) *error = errno; return 0; } fs = getmem (sizeof (*fs)); fs->fs_dev = fd; fs->fs_vp = vp; asprintf (&fs->fs_file_name, "%s", filename); /* reiserfs super block is either in 16-th or in 2-nd 4k block of the device */ for (i = 2; i < 17; i += 14) { bh = bread (fd, i, 4096); if (!bh) { reiserfs_warning (stderr, "reiserfs_open: bread failed reading block %d\n", i); } else { sb = (struct reiserfs_super_block *)bh->b_data; if (is_any_reiserfs_magic_string(sb)) goto found; /* reiserfs signature is not found at the i-th 4k block */ brelse (bh); } } reiserfs_warning(stderr, "\nreiserfs_open: the reiserfs superblock cannot be found on %s.\n", filename); freemem (fs); close (fd); fs = NULL; return fs; found: if (!is_blocksize_correct(get_sb_block_size(sb))) { reiserfs_warning(stderr, "reiserfs_open: a superblock with wrong parameters " "was found in the block (%d).\n", i); freemem (fs); close (fd); brelse(bh); return NULL; } if (check) { /* A few checks of found super block. */ struct buffer_head *tmp_bh; tmp_bh = bread (fd, get_sb_block_count(sb) - 1, get_sb_block_size(sb)); if (!tmp_bh) { reiserfs_warning (stderr, "\n%s: Your partition is not big enough to contain the \n" "filesystem of (%lu) blocks as was specified in the found super block.\n", __FUNCTION__, get_sb_block_count(sb) - 1); freemem (fs); close (fd); brelse(bh); return NULL; } brelse(tmp_bh); } fs->fs_blocksize = get_sb_block_size (sb); /* check block size on the filesystem */ if (fs->fs_blocksize != 4096) { i = bh->b_blocknr * 4096 / fs->fs_blocksize; brelse (bh); bh = bread (fd, i, fs->fs_blocksize); if (!bh) { reiserfs_warning (stderr, "reiserfs_open: bread failed reading block %d, size %d\n", i, fs->fs_blocksize); freemem (fs); return 0; } sb = (struct reiserfs_super_block *)bh->b_data; } fs->fs_hash_function = code2func (get_sb_hash_code (sb)); fs->fs_super_bh = bh; fs->fs_ondisk_sb = sb; fs->fs_flags = flags; /* O_RDONLY or O_RDWR */ fs->fs_format = get_reiserfs_format (sb); /*reiserfs_read_bitmap_blocks(fs);*/ if (flags & O_RDWR) fs->fs_dirt = 1; else fs->fs_dirt = 0; return fs;}/* creates buffer for super block and fills it up with fields which are constant for given size and version of a filesystem */reiserfs_filsys_t * reiserfs_create (char * filename, int version, unsigned long block_count, int block_size, int default_journal, int new_format){ reiserfs_filsys_t * fs; /* convert root dir key and parent root dir key to little endian format */ make_const_keys (); if (count_blocks (filename, block_size) < block_count) { reiserfs_warning (stderr, "reiserfs_create: no enough blocks on device\n"); return 0; } if (!is_block_count_correct (REISERFS_DISK_OFFSET_IN_BYTES / block_size, block_size, block_count, 0)) { reiserfs_warning (stderr, "reiserfs_create: can not create that small " "(%d blocks) filesystem\n", block_count); return 0; } fs = getmem (sizeof (*fs)); if (!fs) { reiserfs_warning (stderr, "reiserfs_create: getmem failed\n"); return 0; } fs->fs_dev = open (filename, O_RDWR #if defined(O_LARGEFILE) | O_LARGEFILE#endif ); if (fs->fs_dev == -1) { reiserfs_warning (stderr, "reiserfs_create: could not open %s: %s\n", filename, strerror(errno)); freemem (fs); return 0; } fs->fs_blocksize = block_size; asprintf (&fs->fs_file_name, "%s", filename); fs->fs_format = version; if (new_format) fs->fs_super_bh = getblk (fs->fs_dev, REISERFS_DISK_OFFSET_IN_BYTES / block_size, block_size); else fs->fs_super_bh = getblk (fs->fs_dev, REISERFS_OLD_DISK_OFFSET_IN_BYTES / block_size, block_size); if (!fs->fs_super_bh) { reiserfs_warning (stderr, "reiserfs_create: getblk failed\n"); return 0; } mark_buffer_uptodate (fs->fs_super_bh, 1); fs->fs_ondisk_sb = (struct reiserfs_super_block *)fs->fs_super_bh->b_data; memset (fs->fs_ondisk_sb, 0, block_size); /* fill super block fields which are constant for given version and block count */ set_sb_block_count (fs->fs_ondisk_sb, block_count); /* sb_free_blocks */ /* sb_root_block */ /* sb_journal_1st_block */ /* sb_journal_dev */ /* sb_orig_journal_size */ /* sb_joural_magic */ /* sb_journal magic_F */ /* sb_mount_id */ /* sb_not_used0 */ /* sb_generation_number */ set_sb_block_size (fs->fs_ondisk_sb, block_size); switch (version) { case REISERFS_FORMAT_3_5: set_sb_oid_maxsize (fs->fs_ondisk_sb, (block_size - SB_SIZE_V1) / sizeof(__u32) / 2 * 2); /* sb_oid_cursize */ /* sb_state */ memcpy (fs->fs_ondisk_sb->s_v1.s_magic, REISERFS_3_5_SUPER_MAGIC_STRING, strlen (REISERFS_3_5_SUPER_MAGIC_STRING)); break; case REISERFS_FORMAT_3_6: set_sb_oid_maxsize (fs->fs_ondisk_sb, (block_size - SB_SIZE) / sizeof(__u32) / 2 * 2); /* sb_oid_cursize */ /* sb_state */ memcpy (fs->fs_ondisk_sb->s_v1.s_magic, REISERFS_3_6_SUPER_MAGIC_STRING, strlen (REISERFS_3_6_SUPER_MAGIC_STRING)); break; } if (!default_journal) memcpy (fs->fs_ondisk_sb->s_v1.s_magic, REISERFS_JR_SUPER_MAGIC_STRING, strlen (REISERFS_JR_SUPER_MAGIC_STRING)); /* sb_fsck_state */ /* sb_hash_function_code */ /* sb_tree_height */ set_sb_bmap_nr (fs->fs_ondisk_sb, (block_count + (block_size * 8 - 1)) / (block_size * 8)); set_sb_version (fs->fs_ondisk_sb, version); /* sb_not_used1 */ mark_buffer_dirty (fs->fs_super_bh); fs->fs_dirt = 1; return fs;}int no_reiserfs_found (reiserfs_filsys_t * fs){ return (fs == NULL || fs->fs_blocksize == 0) ? 1 : 0;}int new_format (reiserfs_filsys_t * fs){ return fs->fs_super_bh->b_blocknr != 2;}int spread_bitmaps (reiserfs_filsys_t * fs){ return fs->fs_super_bh->b_blocknr != 2;}/* 0 means: do not guarantee that fs is consistent */int reiserfs_is_fs_consistent (reiserfs_filsys_t * fs){ if (get_sb_umount_state (fs->fs_ondisk_sb) == FS_CLEANLY_UMOUNTED && get_sb_fs_state (fs->fs_ondisk_sb) == FS_CONSISTENT) return 1; return 0;}/* flush bitmap, brelse super block, flush all dirty buffers, close and open again the device, read super block */static void reiserfs_only_reopen (reiserfs_filsys_t * fs, int flag){ unsigned long super_block; /* reiserfs_flush_to_ondisk_bitmap (fs->fs_bitmap2, fs);*/ super_block = fs->fs_super_bh->b_blocknr; brelse (fs->fs_super_bh); flush_buffers (fs->fs_dev); invalidate_buffers (fs->fs_dev); if (close (fs->fs_dev)) die ("reiserfs_reopen: closed failed: %s", strerror(errno)); fs->fs_dev = open (fs->fs_file_name, flag #if defined(O_LARGEFILE) | O_LARGEFILE#endif ); if (fs->fs_dev == -1) die ("reiserfs_reopen: could not reopen device: %s", strerror(errno)); fs->fs_super_bh = bread (fs->fs_dev, super_block, fs->fs_blocksize); if (!fs->fs_super_bh) die ("reiserfs_reopen: reading super block failed"); fs->fs_ondisk_sb = (struct reiserfs_super_block *)fs->fs_super_bh->b_data; fs->fs_flags = flag; /* O_RDONLY or O_RDWR */ if (flag & O_RDWR) fs->fs_dirt = 1; else fs->fs_dirt = 0;}void reiserfs_reopen (reiserfs_filsys_t * fs, int flag){ reiserfs_only_reopen (fs, flag); reiserfs_reopen_journal (fs, flag);}int is_opened_rw (reiserfs_filsys_t * fs){ if ((fs->fs_flags) & O_RDWR) return 1; return 0;}/* flush all changes made on a filesystem */void reiserfs_flush (reiserfs_filsys_t * fs){ if (fs->fs_dirt) { reiserfs_flush_journal (fs); flush_buffers (fs->fs_dev); } fs->fs_dirt = 0;}/* free all memory involved into manipulating with filesystem */void reiserfs_free (reiserfs_filsys_t * fs){ reiserfs_free_journal (fs); reiserfs_free_ondisk_bitmap (fs); /* release super block and memory used by filesystem handler */ brelse (fs->fs_super_bh); fs->fs_super_bh = 0; free_buffers (); free (fs->fs_file_name); fs->fs_file_name = 0; freemem (fs);}/* this closes everything: journal. bitmap and the fs itself */void reiserfs_close (reiserfs_filsys_t * fs){ reiserfs_close_journal (fs); reiserfs_close_ondisk_bitmap (fs); reiserfs_flush (fs); reiserfs_free (fs); fsync(fs->fs_dev);}int reiserfs_new_blocknrs (reiserfs_filsys_t * fs, unsigned long * free_blocknrs, unsigned long start, int amount_needed){ if (fs->block_allocator) return fs->block_allocator (fs, free_blocknrs, start, amount_needed); die ("block allocator is not defined\n"); return 0;}int reiserfs_free_block (reiserfs_filsys_t * fs, unsigned long block){ if (fs->block_deallocator) return fs->block_deallocator (fs, block); die ("block deallocator is not defined\n"); return 0;}static int reiserfs_search_by_key_x (reiserfs_filsys_t * fs, struct key * key, struct path * path, int key_length){ struct buffer_head * bh; unsigned long block; struct path_element * curr; int retval; block = get_sb_root_block (fs->fs_ondisk_sb); if (not_data_block(fs, block)) return IO_ERROR; path->path_length = ILLEGAL_PATH_ELEMENT_OFFSET; while (1) { curr = PATH_OFFSET_PELEMENT (path, ++ path->path_length); bh = curr->pe_buffer = bread (fs->fs_dev, block, fs->fs_blocksize); if (bh == 0) { path->path_length --; pathrelse (path); return ITEM_NOT_FOUND; } retval = reiserfs_bin_search (key, B_N_PKEY (bh, 0), B_NR_ITEMS (bh), is_leaf_node (bh) ? IH_SIZE : KEY_SIZE, &(curr->pe_position), key_length == 4 ? comp_keys : comp_keys_3); if (retval == POSITION_FOUND) { /* key found, return if this is leaf level */ if (is_leaf_node (bh)) { path->pos_in_item = 0; return ITEM_FOUND; } curr->pe_position ++; } else { /* key not found in the node */ if (is_leaf_node (bh)) return ITEM_NOT_FOUND; } block = get_dc_child_blocknr (B_N_CHILD (bh, curr->pe_position)); if (not_data_block(fs, block)) return IO_ERROR; } printf ("search_by_key: you can not get here\n"); return ITEM_NOT_FOUND;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -