put small subset of e2fsprogs back in the tree:
lsattr, chattr, fsck. Old e2fsprogs tree is in e2fsprogs/old_e2fsprogs/*.
This commit is contained in:
parent
64c5402584
commit
c4f623ef2a
67
e2fsprogs/Config.in
Normal file
67
e2fsprogs/Config.in
Normal file
@ -0,0 +1,67 @@
|
||||
#
|
||||
# For a description of the syntax of this configuration file,
|
||||
# see scripts/kbuild/config-language.txt.
|
||||
#
|
||||
|
||||
menu "Linux Ext2 FS Progs"
|
||||
|
||||
config CHATTR
|
||||
bool "chattr"
|
||||
default n
|
||||
help
|
||||
chattr changes the file attributes on a second extended file system.
|
||||
|
||||
### config E2FSCK
|
||||
### bool "e2fsck"
|
||||
### default n
|
||||
### help
|
||||
### e2fsck is used to check Linux second extended file systems (ext2fs).
|
||||
### e2fsck also supports ext2 filesystems countaining a journal (ext3).
|
||||
### The normal compat symlinks 'fsck.ext2' and 'fsck.ext3' are also
|
||||
### provided.
|
||||
|
||||
config FSCK
|
||||
bool "fsck"
|
||||
default n
|
||||
help
|
||||
fsck is used to check and optionally repair one or more filesystems.
|
||||
In actuality, fsck is simply a front-end for the various file system
|
||||
checkers (fsck.fstype) available under Linux.
|
||||
|
||||
config LSATTR
|
||||
bool "lsattr"
|
||||
default n
|
||||
help
|
||||
lsattr lists the file attributes on a second extended file system.
|
||||
|
||||
### config MKE2FS
|
||||
### bool "mke2fs"
|
||||
### default n
|
||||
### help
|
||||
### mke2fs is used to create an ext2/ext3 filesystem. The normal compat
|
||||
### symlinks 'mkfs.ext2' and 'mkfs.ext3' are also provided.
|
||||
|
||||
### config TUNE2FS
|
||||
### bool "tune2fs"
|
||||
### default n
|
||||
### help
|
||||
### tune2fs allows the system administrator to adjust various tunable
|
||||
### filesystem parameters on Linux ext2/ext3 filesystems.
|
||||
|
||||
### config E2LABEL
|
||||
### bool "e2label"
|
||||
### default n
|
||||
### depends on TUNE2FS
|
||||
### help
|
||||
### e2label will display or change the filesystem label on the ext2
|
||||
### filesystem located on device.
|
||||
|
||||
### config FINDFS
|
||||
### bool "findfs"
|
||||
### default n
|
||||
### depends on TUNE2FS
|
||||
### help
|
||||
### findfs will search the disks in the system looking for a filesystem
|
||||
### which has a label matching label or a UUID equal to uuid.
|
||||
|
||||
endmenu
|
12
e2fsprogs/Kbuild
Normal file
12
e2fsprogs/Kbuild
Normal file
@ -0,0 +1,12 @@
|
||||
# Makefile for busybox
|
||||
#
|
||||
# Copyright (C) 1999-2005 by Erik Andersen <andersen@codepoet.org>
|
||||
#
|
||||
# Licensed under the GPL v2, see the file LICENSE in this tarball.
|
||||
|
||||
lib-y:=
|
||||
|
||||
lib-$(CONFIG_CHATTR) += chattr.o e2fs_lib.o
|
||||
lib-$(CONFIG_LSATTR) += lsattr.o e2fs_lib.o
|
||||
|
||||
lib-$(CONFIG_FSCK) += fsck.o
|
12
e2fsprogs/README
Normal file
12
e2fsprogs/README
Normal file
@ -0,0 +1,12 @@
|
||||
Authors and contributors of original e2fsprogs:
|
||||
|
||||
Remy Card <card@masi.ibp.fr>
|
||||
Theodore Ts'o <tytso@mit.edu>
|
||||
Stephen C. Tweedie <sct@redhat.com>
|
||||
Andreas Gruenbacher, <a.gruenbacher@computer.org>
|
||||
Kaz Kylheku <kaz@ashi.footprints.net>
|
||||
F.W. ten Wolde <franky@duteca.et.tudelft.nl>
|
||||
Jeremy Fitzhardinge <jeremy@zip.com.au>
|
||||
M.J.E. Mol <marcel@duteca.et.tudelft.nl>
|
||||
Miquel van Smoorenburg <miquels@drinkel.ow.org>
|
||||
Uwe Ohse <uwe@tirka.gun.de>
|
199
e2fsprogs/chattr.c
Normal file
199
e2fsprogs/chattr.c
Normal file
@ -0,0 +1,199 @@
|
||||
/* vi: set sw=4 ts=4: */
|
||||
/*
|
||||
* chattr.c - Change file attributes on an ext2 file system
|
||||
*
|
||||
* Copyright (C) 1993, 1994 Remy Card <card@masi.ibp.fr>
|
||||
* Laboratoire MASI, Institut Blaise Pascal
|
||||
* Universite Pierre et Marie Curie (Paris VI)
|
||||
*
|
||||
* This file can be redistributed under the terms of the GNU General
|
||||
* Public License
|
||||
*/
|
||||
|
||||
/*
|
||||
* History:
|
||||
* 93/10/30 - Creation
|
||||
* 93/11/13 - Replace stat() calls by lstat() to avoid loops
|
||||
* 94/02/27 - Integrated in Ted's distribution
|
||||
* 98/12/29 - Ignore symlinks when working recursively (G M Sipe)
|
||||
* 98/12/29 - Display version info only when -V specified (G M Sipe)
|
||||
*/
|
||||
|
||||
#include "busybox.h"
|
||||
#include "e2fs_lib.h"
|
||||
|
||||
#define OPT_ADD 1
|
||||
#define OPT_REM 2
|
||||
#define OPT_SET 4
|
||||
#define OPT_SET_VER 8
|
||||
static int flags;
|
||||
static int recursive;
|
||||
|
||||
static unsigned long version;
|
||||
|
||||
static unsigned long af;
|
||||
static unsigned long rf;
|
||||
static unsigned long sf;
|
||||
|
||||
struct flags_char {
|
||||
unsigned long flag;
|
||||
char optchar;
|
||||
};
|
||||
|
||||
static const struct flags_char flags_array[] = {
|
||||
{ EXT2_NOATIME_FL, 'A' },
|
||||
{ EXT2_SYNC_FL, 'S' },
|
||||
{ EXT2_DIRSYNC_FL, 'D' },
|
||||
{ EXT2_APPEND_FL, 'a' },
|
||||
{ EXT2_COMPR_FL, 'c' },
|
||||
{ EXT2_NODUMP_FL, 'd' },
|
||||
{ EXT2_IMMUTABLE_FL, 'i' },
|
||||
{ EXT3_JOURNAL_DATA_FL, 'j' },
|
||||
{ EXT2_SECRM_FL, 's' },
|
||||
{ EXT2_UNRM_FL, 'u' },
|
||||
{ EXT2_NOTAIL_FL, 't' },
|
||||
{ EXT2_TOPDIR_FL, 'T' },
|
||||
{ 0, 0 }
|
||||
};
|
||||
|
||||
static unsigned long get_flag(char c)
|
||||
{
|
||||
const struct flags_char *fp;
|
||||
for (fp = flags_array; fp->flag; fp++)
|
||||
if (fp->optchar == c)
|
||||
return fp->flag;
|
||||
bb_show_usage();
|
||||
/*return 0;*/
|
||||
}
|
||||
|
||||
static int decode_arg(char *arg)
|
||||
{
|
||||
unsigned long *fl;
|
||||
char opt = *arg++;
|
||||
|
||||
if (opt == '-') {
|
||||
flags |= OPT_REM;
|
||||
fl = &rf;
|
||||
} else if (opt == '+') {
|
||||
flags |= OPT_ADD;
|
||||
fl = ⁡
|
||||
} else if (opt == '=') {
|
||||
flags |= OPT_SET;
|
||||
fl = &sf;
|
||||
} else
|
||||
return 0;
|
||||
|
||||
while (*arg)
|
||||
*fl |= get_flag(*arg++);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int chattr_dir_proc(const char *, struct dirent *, void *);
|
||||
|
||||
static void change_attributes(const char * name)
|
||||
{
|
||||
unsigned long fsflags;
|
||||
struct stat st;
|
||||
|
||||
if (lstat(name, &st) == -1) {
|
||||
bb_error_msg("stat %s failed", name);
|
||||
return;
|
||||
}
|
||||
if (S_ISLNK(st.st_mode) && recursive)
|
||||
return;
|
||||
|
||||
/* Don't try to open device files, fifos etc. We probably
|
||||
* ought to display an error if the file was explicitly given
|
||||
* on the command line (whether or not recursive was
|
||||
* requested). */
|
||||
if (!S_ISREG(st.st_mode) && !S_ISLNK(st.st_mode) && !S_ISDIR(st.st_mode))
|
||||
return;
|
||||
|
||||
if (flags & OPT_SET_VER)
|
||||
if (fsetversion(name, version) == -1)
|
||||
bb_error_msg("setting version on %s", name);
|
||||
|
||||
if (flags & OPT_SET) {
|
||||
fsflags = sf;
|
||||
} else {
|
||||
if (fgetflags(name, &fsflags) == -1) {
|
||||
bb_error_msg("reading flags on %s", name);
|
||||
goto skip_setflags;
|
||||
}
|
||||
if (flags & OPT_REM)
|
||||
fsflags &= ~rf;
|
||||
if (flags & OPT_ADD)
|
||||
fsflags |= af;
|
||||
if (!S_ISDIR(st.st_mode))
|
||||
fsflags &= ~EXT2_DIRSYNC_FL;
|
||||
}
|
||||
if (fsetflags(name, fsflags) == -1)
|
||||
bb_error_msg("setting flags on %s", name);
|
||||
|
||||
skip_setflags:
|
||||
if (S_ISDIR(st.st_mode) && recursive)
|
||||
iterate_on_dir(name, chattr_dir_proc, NULL);
|
||||
}
|
||||
|
||||
static int chattr_dir_proc(const char *dir_name, struct dirent *de,
|
||||
void *private ATTRIBUTE_UNUSED)
|
||||
{
|
||||
/*if (strcmp(de->d_name, ".") || strcmp(de->d_name, "..")) {*/
|
||||
if (de->d_name[0] == '.'
|
||||
&& (!de->d_name[1] || LONE_CHAR(de->d_name+1, '.'))
|
||||
) {
|
||||
char *path = concat_subpath_file(dir_name, de->d_name);
|
||||
if (path) {
|
||||
change_attributes(path);
|
||||
free(path);
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int chattr_main(int argc, char **argv)
|
||||
{
|
||||
int i;
|
||||
char *arg;
|
||||
|
||||
/* parse the args */
|
||||
for (i = 1; i < argc; ++i) {
|
||||
arg = argv[i];
|
||||
|
||||
/* take care of -R and -v <version> */
|
||||
if (arg[0] == '-') {
|
||||
if (arg[1] == 'R' && arg[2] == '\0') {
|
||||
recursive = 1;
|
||||
continue;
|
||||
}
|
||||
if (arg[1] == 'v' && arg[2] == '\0') {
|
||||
++i;
|
||||
if (i >= argc)
|
||||
bb_show_usage();
|
||||
version = xatoul(argv[i]);
|
||||
flags |= OPT_SET_VER;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
if (!decode_arg(arg))
|
||||
break;
|
||||
}
|
||||
|
||||
/* run sanity checks on all the arguments given us */
|
||||
if (i >= argc)
|
||||
bb_show_usage();
|
||||
if ((flags & OPT_SET) && (flags & (OPT_ADD|OPT_REM)))
|
||||
bb_error_msg_and_die("= is incompatible with - and +");
|
||||
if (rf & af)
|
||||
bb_error_msg_and_die("Can't set and unset a flag");
|
||||
if (!flags)
|
||||
bb_error_msg_and_die("Must use '-v', =, - or +");
|
||||
|
||||
/* now run chattr on all the files passed to us */
|
||||
while (i < argc)
|
||||
change_attributes(argv[i++]);
|
||||
|
||||
return EXIT_SUCCESS;
|
||||
}
|
561
e2fsprogs/e2fs_defs.h
Normal file
561
e2fsprogs/e2fs_defs.h
Normal file
@ -0,0 +1,561 @@
|
||||
/* vi: set sw=4 ts=4: */
|
||||
/*
|
||||
* linux/include/linux/ext2_fs.h
|
||||
*
|
||||
* Copyright (C) 1992, 1993, 1994, 1995
|
||||
* Remy Card (card@masi.ibp.fr)
|
||||
* Laboratoire MASI - Institut Blaise Pascal
|
||||
* Universite Pierre et Marie Curie (Paris VI)
|
||||
*
|
||||
* Copyright (C) 1991, 1992 Linus Torvalds
|
||||
*/
|
||||
|
||||
#ifndef _LINUX_EXT2_FS_H
|
||||
#define _LINUX_EXT2_FS_H
|
||||
|
||||
/*
|
||||
* Special inode numbers
|
||||
*/
|
||||
#define EXT2_BAD_INO 1 /* Bad blocks inode */
|
||||
#define EXT2_ROOT_INO 2 /* Root inode */
|
||||
#define EXT2_ACL_IDX_INO 3 /* ACL inode */
|
||||
#define EXT2_ACL_DATA_INO 4 /* ACL inode */
|
||||
#define EXT2_BOOT_LOADER_INO 5 /* Boot loader inode */
|
||||
#define EXT2_UNDEL_DIR_INO 6 /* Undelete directory inode */
|
||||
#define EXT2_RESIZE_INO 7 /* Reserved group descriptors inode */
|
||||
#define EXT2_JOURNAL_INO 8 /* Journal inode */
|
||||
|
||||
/* First non-reserved inode for old ext2 filesystems */
|
||||
#define EXT2_GOOD_OLD_FIRST_INO 11
|
||||
|
||||
/*
|
||||
* The second extended file system magic number
|
||||
*/
|
||||
#define EXT2_SUPER_MAGIC 0xEF53
|
||||
|
||||
/* Assume that user mode programs are passing in an ext2fs superblock, not
|
||||
* a kernel struct super_block. This will allow us to call the feature-test
|
||||
* macros from user land. */
|
||||
#define EXT2_SB(sb) (sb)
|
||||
|
||||
/*
|
||||
* Maximal count of links to a file
|
||||
*/
|
||||
#define EXT2_LINK_MAX 32000
|
||||
|
||||
/*
|
||||
* Macro-instructions used to manage several block sizes
|
||||
*/
|
||||
#define EXT2_MIN_BLOCK_LOG_SIZE 10 /* 1024 */
|
||||
#define EXT2_MAX_BLOCK_LOG_SIZE 16 /* 65536 */
|
||||
#define EXT2_MIN_BLOCK_SIZE (1 << EXT2_MIN_BLOCK_LOG_SIZE)
|
||||
#define EXT2_MAX_BLOCK_SIZE (1 << EXT2_MAX_BLOCK_LOG_SIZE)
|
||||
#define EXT2_BLOCK_SIZE(s) (EXT2_MIN_BLOCK_SIZE << (s)->s_log_block_size)
|
||||
#define EXT2_BLOCK_SIZE_BITS(s) ((s)->s_log_block_size + 10)
|
||||
#define EXT2_INODE_SIZE(s) (((s)->s_rev_level == EXT2_GOOD_OLD_REV) ? \
|
||||
EXT2_GOOD_OLD_INODE_SIZE : (s)->s_inode_size)
|
||||
#define EXT2_FIRST_INO(s) (((s)->s_rev_level == EXT2_GOOD_OLD_REV) ? \
|
||||
EXT2_GOOD_OLD_FIRST_INO : (s)->s_first_ino)
|
||||
#define EXT2_ADDR_PER_BLOCK(s) (EXT2_BLOCK_SIZE(s) / sizeof(uint32_t))
|
||||
|
||||
/*
|
||||
* Macro-instructions used to manage fragments
|
||||
*/
|
||||
#define EXT2_MIN_FRAG_SIZE EXT2_MIN_BLOCK_SIZE
|
||||
#define EXT2_MAX_FRAG_SIZE EXT2_MAX_BLOCK_SIZE
|
||||
#define EXT2_MIN_FRAG_LOG_SIZE EXT2_MIN_BLOCK_LOG_SIZE
|
||||
#define EXT2_FRAG_SIZE(s) (EXT2_MIN_FRAG_SIZE << (s)->s_log_frag_size)
|
||||
#define EXT2_FRAGS_PER_BLOCK(s) (EXT2_BLOCK_SIZE(s) / EXT2_FRAG_SIZE(s))
|
||||
|
||||
/*
|
||||
* ACL structures
|
||||
*/
|
||||
struct ext2_acl_header { /* Header of Access Control Lists */
|
||||
uint32_t aclh_size;
|
||||
uint32_t aclh_file_count;
|
||||
uint32_t aclh_acle_count;
|
||||
uint32_t aclh_first_acle;
|
||||
};
|
||||
|
||||
struct ext2_acl_entry { /* Access Control List Entry */
|
||||
uint32_t acle_size;
|
||||
uint16_t acle_perms; /* Access permissions */
|
||||
uint16_t acle_type; /* Type of entry */
|
||||
uint16_t acle_tag; /* User or group identity */
|
||||
uint16_t acle_pad1;
|
||||
uint32_t acle_next; /* Pointer on next entry for the */
|
||||
/* same inode or on next free entry */
|
||||
};
|
||||
|
||||
/*
|
||||
* Structure of a blocks group descriptor
|
||||
*/
|
||||
struct ext2_group_desc {
|
||||
uint32_t bg_block_bitmap; /* Blocks bitmap block */
|
||||
uint32_t bg_inode_bitmap; /* Inodes bitmap block */
|
||||
uint32_t bg_inode_table; /* Inodes table block */
|
||||
uint16_t bg_free_blocks_count; /* Free blocks count */
|
||||
uint16_t bg_free_inodes_count; /* Free inodes count */
|
||||
uint16_t bg_used_dirs_count; /* Directories count */
|
||||
uint16_t bg_pad;
|
||||
uint32_t bg_reserved[3];
|
||||
};
|
||||
|
||||
/*
|
||||
* Data structures used by the directory indexing feature
|
||||
*
|
||||
* Note: all of the multibyte integer fields are little endian.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Note: dx_root_info is laid out so that if it should somehow get
|
||||
* overlaid by a dirent the two low bits of the hash version will be
|
||||
* zero. Therefore, the hash version mod 4 should never be 0.
|
||||
* Sincerely, the paranoia department.
|
||||
*/
|
||||
struct ext2_dx_root_info {
|
||||
uint32_t reserved_zero;
|
||||
uint8_t hash_version; /* 0 now, 1 at release */
|
||||
uint8_t info_length; /* 8 */
|
||||
uint8_t indirect_levels;
|
||||
uint8_t unused_flags;
|
||||
};
|
||||
|
||||
#define EXT2_HASH_LEGACY 0
|
||||
#define EXT2_HASH_HALF_MD4 1
|
||||
#define EXT2_HASH_TEA 2
|
||||
|
||||
#define EXT2_HASH_FLAG_INCOMPAT 0x1
|
||||
|
||||
struct ext2_dx_entry {
|
||||
uint32_t hash;
|
||||
uint32_t block;
|
||||
};
|
||||
|
||||
struct ext2_dx_countlimit {
|
||||
uint16_t limit;
|
||||
uint16_t count;
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
* Macro-instructions used to manage group descriptors
|
||||
*/
|
||||
#define EXT2_BLOCKS_PER_GROUP(s) (EXT2_SB(s)->s_blocks_per_group)
|
||||
#define EXT2_INODES_PER_GROUP(s) (EXT2_SB(s)->s_inodes_per_group)
|
||||
#define EXT2_INODES_PER_BLOCK(s) (EXT2_BLOCK_SIZE(s)/EXT2_INODE_SIZE(s))
|
||||
/* limits imposed by 16-bit value gd_free_{blocks,inode}_count */
|
||||
#define EXT2_MAX_BLOCKS_PER_GROUP(s) ((1 << 16) - 8)
|
||||
#define EXT2_MAX_INODES_PER_GROUP(s) ((1 << 16) - EXT2_INODES_PER_BLOCK(s))
|
||||
#define EXT2_DESC_PER_BLOCK(s) (EXT2_BLOCK_SIZE(s) / sizeof (struct ext2_group_desc))
|
||||
|
||||
/*
|
||||
* Constants relative to the data blocks
|
||||
*/
|
||||
#define EXT2_NDIR_BLOCKS 12
|
||||
#define EXT2_IND_BLOCK EXT2_NDIR_BLOCKS
|
||||
#define EXT2_DIND_BLOCK (EXT2_IND_BLOCK + 1)
|
||||
#define EXT2_TIND_BLOCK (EXT2_DIND_BLOCK + 1)
|
||||
#define EXT2_N_BLOCKS (EXT2_TIND_BLOCK + 1)
|
||||
|
||||
/*
|
||||
* Inode flags
|
||||
*/
|
||||
#define EXT2_SECRM_FL 0x00000001 /* Secure deletion */
|
||||
#define EXT2_UNRM_FL 0x00000002 /* Undelete */
|
||||
#define EXT2_COMPR_FL 0x00000004 /* Compress file */
|
||||
#define EXT2_SYNC_FL 0x00000008 /* Synchronous updates */
|
||||
#define EXT2_IMMUTABLE_FL 0x00000010 /* Immutable file */
|
||||
#define EXT2_APPEND_FL 0x00000020 /* writes to file may only append */
|
||||
#define EXT2_NODUMP_FL 0x00000040 /* do not dump file */
|
||||
#define EXT2_NOATIME_FL 0x00000080 /* do not update atime */
|
||||
/* Reserved for compression usage... */
|
||||
#define EXT2_DIRTY_FL 0x00000100
|
||||
#define EXT2_COMPRBLK_FL 0x00000200 /* One or more compressed clusters */
|
||||
#define EXT2_NOCOMPR_FL 0x00000400 /* Access raw compressed data */
|
||||
#define EXT2_ECOMPR_FL 0x00000800 /* Compression error */
|
||||
/* End compression flags --- maybe not all used */
|
||||
#define EXT2_BTREE_FL 0x00001000 /* btree format dir */
|
||||
#define EXT2_INDEX_FL 0x00001000 /* hash-indexed directory */
|
||||
#define EXT2_IMAGIC_FL 0x00002000
|
||||
#define EXT3_JOURNAL_DATA_FL 0x00004000 /* file data should be journaled */
|
||||
#define EXT2_NOTAIL_FL 0x00008000 /* file tail should not be merged */
|
||||
#define EXT2_DIRSYNC_FL 0x00010000 /* Synchronous directory modifications */
|
||||
#define EXT2_TOPDIR_FL 0x00020000 /* Top of directory hierarchies*/
|
||||
#define EXT3_EXTENTS_FL 0x00080000 /* Inode uses extents */
|
||||
#define EXT2_RESERVED_FL 0x80000000 /* reserved for ext2 lib */
|
||||
|
||||
#define EXT2_FL_USER_VISIBLE 0x0003DFFF /* User visible flags */
|
||||
#define EXT2_FL_USER_MODIFIABLE 0x000080FF /* User modifiable flags */
|
||||
|
||||
/*
|
||||
* ioctl commands
|
||||
*/
|
||||
#define EXT2_IOC_GETFLAGS _IOR('f', 1, long)
|
||||
#define EXT2_IOC_SETFLAGS _IOW('f', 2, long)
|
||||
#define EXT2_IOC_GETVERSION _IOR('v', 1, long)
|
||||
#define EXT2_IOC_SETVERSION _IOW('v', 2, long)
|
||||
|
||||
/*
|
||||
* Structure of an inode on the disk
|
||||
*/
|
||||
struct ext2_inode {
|
||||
uint16_t i_mode; /* File mode */
|
||||
uint16_t i_uid; /* Low 16 bits of Owner Uid */
|
||||
uint32_t i_size; /* Size in bytes */
|
||||
uint32_t i_atime; /* Access time */
|
||||
uint32_t i_ctime; /* Creation time */
|
||||
uint32_t i_mtime; /* Modification time */
|
||||
uint32_t i_dtime; /* Deletion Time */
|
||||
uint16_t i_gid; /* Low 16 bits of Group Id */
|
||||
uint16_t i_links_count; /* Links count */
|
||||
uint32_t i_blocks; /* Blocks count */
|
||||
uint32_t i_flags; /* File flags */
|
||||
union {
|
||||
struct {
|
||||
uint32_t l_i_reserved1;
|
||||
} linux1;
|
||||
struct {
|
||||
uint32_t h_i_translator;
|
||||
} hurd1;
|
||||
struct {
|
||||
uint32_t m_i_reserved1;
|
||||
} masix1;
|
||||
} osd1; /* OS dependent 1 */
|
||||
uint32_t i_block[EXT2_N_BLOCKS];/* Pointers to blocks */
|
||||
uint32_t i_generation; /* File version (for NFS) */
|
||||
uint32_t i_file_acl; /* File ACL */
|
||||
uint32_t i_dir_acl; /* Directory ACL */
|
||||
uint32_t i_faddr; /* Fragment address */
|
||||
union {
|
||||
struct {
|
||||
uint8_t l_i_frag; /* Fragment number */
|
||||
uint8_t l_i_fsize; /* Fragment size */
|
||||
uint16_t i_pad1;
|
||||
uint16_t l_i_uid_high; /* these 2 fields */
|
||||
uint16_t l_i_gid_high; /* were reserved2[0] */
|
||||
uint32_t l_i_reserved2;
|
||||
} linux2;
|
||||
struct {
|
||||
uint8_t h_i_frag; /* Fragment number */
|
||||
uint8_t h_i_fsize; /* Fragment size */
|
||||
uint16_t h_i_mode_high;
|
||||
uint16_t h_i_uid_high;
|
||||
uint16_t h_i_gid_high;
|
||||
uint32_t h_i_author;
|
||||
} hurd2;
|
||||
struct {
|
||||
uint8_t m_i_frag; /* Fragment number */
|
||||
uint8_t m_i_fsize; /* Fragment size */
|
||||
uint16_t m_pad1;
|
||||
uint32_t m_i_reserved2[2];
|
||||
} masix2;
|
||||
} osd2; /* OS dependent 2 */
|
||||
};
|
||||
|
||||
/*
|
||||
* Permanent part of an large inode on the disk
|
||||
*/
|
||||
struct ext2_inode_large {
|
||||
uint16_t i_mode; /* File mode */
|
||||
uint16_t i_uid; /* Low 16 bits of Owner Uid */
|
||||
uint32_t i_size; /* Size in bytes */
|
||||
uint32_t i_atime; /* Access time */
|
||||
uint32_t i_ctime; /* Creation time */
|
||||
uint32_t i_mtime; /* Modification time */
|
||||
uint32_t i_dtime; /* Deletion Time */
|
||||
uint16_t i_gid; /* Low 16 bits of Group Id */
|
||||
uint16_t i_links_count; /* Links count */
|
||||
uint32_t i_blocks; /* Blocks count */
|
||||
uint32_t i_flags; /* File flags */
|
||||
union {
|
||||
struct {
|
||||
uint32_t l_i_reserved1;
|
||||
} linux1;
|
||||
struct {
|
||||
uint32_t h_i_translator;
|
||||
} hurd1;
|
||||
struct {
|
||||
uint32_t m_i_reserved1;
|
||||
} masix1;
|
||||
} osd1; /* OS dependent 1 */
|
||||
uint32_t i_block[EXT2_N_BLOCKS];/* Pointers to blocks */
|
||||
uint32_t i_generation; /* File version (for NFS) */
|
||||
uint32_t i_file_acl; /* File ACL */
|
||||
uint32_t i_dir_acl; /* Directory ACL */
|
||||
uint32_t i_faddr; /* Fragment address */
|
||||
union {
|
||||
struct {
|
||||
uint8_t l_i_frag; /* Fragment number */
|
||||
uint8_t l_i_fsize; /* Fragment size */
|
||||
uint16_t i_pad1;
|
||||
uint16_t l_i_uid_high; /* these 2 fields */
|
||||
uint16_t l_i_gid_high; /* were reserved2[0] */
|
||||
uint32_t l_i_reserved2;
|
||||
} linux2;
|
||||
struct {
|
||||
uint8_t h_i_frag; /* Fragment number */
|
||||
uint8_t h_i_fsize; /* Fragment size */
|
||||
uint16_t h_i_mode_high;
|
||||
uint16_t h_i_uid_high;
|
||||
uint16_t h_i_gid_high;
|
||||
uint32_t h_i_author;
|
||||
} hurd2;
|
||||
struct {
|
||||
uint8_t m_i_frag; /* Fragment number */
|
||||
uint8_t m_i_fsize; /* Fragment size */
|
||||
uint16_t m_pad1;
|
||||
uint32_t m_i_reserved2[2];
|
||||
} masix2;
|
||||
} osd2; /* OS dependent 2 */
|
||||
uint16_t i_extra_isize;
|
||||
uint16_t i_pad1;
|
||||
};
|
||||
|
||||
#define i_size_high i_dir_acl
|
||||
|
||||
/*
|
||||
* File system states
|
||||
*/
|
||||
#define EXT2_VALID_FS 0x0001 /* Unmounted cleanly */
|
||||
#define EXT2_ERROR_FS 0x0002 /* Errors detected */
|
||||
|
||||
/*
|
||||
* Mount flags
|
||||
*/
|
||||
#define EXT2_MOUNT_CHECK 0x0001 /* Do mount-time checks */
|
||||
#define EXT2_MOUNT_GRPID 0x0004 /* Create files with directory's group */
|
||||
#define EXT2_MOUNT_DEBUG 0x0008 /* Some debugging messages */
|
||||
#define EXT2_MOUNT_ERRORS_CONT 0x0010 /* Continue on errors */
|
||||
#define EXT2_MOUNT_ERRORS_RO 0x0020 /* Remount fs ro on errors */
|
||||
#define EXT2_MOUNT_ERRORS_PANIC 0x0040 /* Panic on errors */
|
||||
#define EXT2_MOUNT_MINIX_DF 0x0080 /* Mimics the Minix statfs */
|
||||
#define EXT2_MOUNT_NO_UID32 0x0200 /* Disable 32-bit UIDs */
|
||||
|
||||
#define clear_opt(o, opt) o &= ~EXT2_MOUNT_##opt
|
||||
#define set_opt(o, opt) o |= EXT2_MOUNT_##opt
|
||||
#define test_opt(sb, opt) (EXT2_SB(sb)->s_mount_opt & \
|
||||
EXT2_MOUNT_##opt)
|
||||
/*
|
||||
* Maximal mount counts between two filesystem checks
|
||||
*/
|
||||
#define EXT2_DFL_MAX_MNT_COUNT 20 /* Allow 20 mounts */
|
||||
#define EXT2_DFL_CHECKINTERVAL 0 /* Don't use interval check */
|
||||
|
||||
/*
|
||||
* Behaviour when detecting errors
|
||||
*/
|
||||
#define EXT2_ERRORS_CONTINUE 1 /* Continue execution */
|
||||
#define EXT2_ERRORS_RO 2 /* Remount fs read-only */
|
||||
#define EXT2_ERRORS_PANIC 3 /* Panic */
|
||||
#define EXT2_ERRORS_DEFAULT EXT2_ERRORS_CONTINUE
|
||||
|
||||
/*
|
||||
* Structure of the super block
|
||||
*/
|
||||
struct ext2_super_block {
|
||||
uint32_t s_inodes_count; /* Inodes count */
|
||||
uint32_t s_blocks_count; /* Blocks count */
|
||||
uint32_t s_r_blocks_count; /* Reserved blocks count */
|
||||
uint32_t s_free_blocks_count; /* Free blocks count */
|
||||
uint32_t s_free_inodes_count; /* Free inodes count */
|
||||
uint32_t s_first_data_block; /* First Data Block */
|
||||
uint32_t s_log_block_size; /* Block size */
|
||||
int32_t s_log_frag_size; /* Fragment size */
|
||||
uint32_t s_blocks_per_group; /* # Blocks per group */
|
||||
uint32_t s_frags_per_group; /* # Fragments per group */
|
||||
uint32_t s_inodes_per_group; /* # Inodes per group */
|
||||
uint32_t s_mtime; /* Mount time */
|
||||
uint32_t s_wtime; /* Write time */
|
||||
uint16_t s_mnt_count; /* Mount count */
|
||||
int16_t s_max_mnt_count; /* Maximal mount count */
|
||||
uint16_t s_magic; /* Magic signature */
|
||||
uint16_t s_state; /* File system state */
|
||||
uint16_t s_errors; /* Behaviour when detecting errors */
|
||||
uint16_t s_minor_rev_level; /* minor revision level */
|
||||
uint32_t s_lastcheck; /* time of last check */
|
||||
uint32_t s_checkinterval; /* max. time between checks */
|
||||
uint32_t s_creator_os; /* OS */
|
||||
uint32_t s_rev_level; /* Revision level */
|
||||
uint16_t s_def_resuid; /* Default uid for reserved blocks */
|
||||
uint16_t s_def_resgid; /* Default gid for reserved blocks */
|
||||
/*
|
||||
* These fields are for EXT2_DYNAMIC_REV superblocks only.
|
||||
*
|
||||
* Note: the difference between the compatible feature set and
|
||||
* the incompatible feature set is that if there is a bit set
|
||||
* in the incompatible feature set that the kernel doesn't
|
||||
* know about, it should refuse to mount the filesystem.
|
||||
*
|
||||
* e2fsck's requirements are more strict; if it doesn't know
|
||||
* about a feature in either the compatible or incompatible
|
||||
* feature set, it must abort and not try to meddle with
|
||||
* things it doesn't understand...
|
||||
*/
|
||||
uint32_t s_first_ino; /* First non-reserved inode */
|
||||
uint16_t s_inode_size; /* size of inode structure */
|
||||
uint16_t s_block_group_nr; /* block group # of this superblock */
|
||||
uint32_t s_feature_compat; /* compatible feature set */
|
||||
uint32_t s_feature_incompat; /* incompatible feature set */
|
||||
uint32_t s_feature_ro_compat; /* readonly-compatible feature set */
|
||||
uint8_t s_uuid[16]; /* 128-bit uuid for volume */
|
||||
char s_volume_name[16]; /* volume name */
|
||||
char s_last_mounted[64]; /* directory where last mounted */
|
||||
uint32_t s_algorithm_usage_bitmap; /* For compression */
|
||||
/*
|
||||
* Performance hints. Directory preallocation should only
|
||||
* happen if the EXT2_FEATURE_COMPAT_DIR_PREALLOC flag is on.
|
||||
*/
|
||||
uint8_t s_prealloc_blocks; /* Nr of blocks to try to preallocate*/
|
||||
uint8_t s_prealloc_dir_blocks; /* Nr to preallocate for dirs */
|
||||
uint16_t s_reserved_gdt_blocks; /* Per group table for online growth */
|
||||
/*
|
||||
* Journaling support valid if EXT2_FEATURE_COMPAT_HAS_JOURNAL set.
|
||||
*/
|
||||
uint8_t s_journal_uuid[16]; /* uuid of journal superblock */
|
||||
uint32_t s_journal_inum; /* inode number of journal file */
|
||||
uint32_t s_journal_dev; /* device number of journal file */
|
||||
uint32_t s_last_orphan; /* start of list of inodes to delete */
|
||||
uint32_t s_hash_seed[4]; /* HTREE hash seed */
|
||||
uint8_t s_def_hash_version; /* Default hash version to use */
|
||||
uint8_t s_jnl_backup_type; /* Default type of journal backup */
|
||||
uint16_t s_reserved_word_pad;
|
||||
uint32_t s_default_mount_opts;
|
||||
uint32_t s_first_meta_bg; /* First metablock group */
|
||||
uint32_t s_mkfs_time; /* When the filesystem was created */
|
||||
uint32_t s_jnl_blocks[17]; /* Backup of the journal inode */
|
||||
uint32_t s_reserved[172]; /* Padding to the end of the block */
|
||||
};
|
||||
|
||||
/*
|
||||
* Codes for operating systems
|
||||
*/
|
||||
#define EXT2_OS_LINUX 0
|
||||
#define EXT2_OS_HURD 1
|
||||
#define EXT2_OS_MASIX 2
|
||||
#define EXT2_OS_FREEBSD 3
|
||||
#define EXT2_OS_LITES 4
|
||||
|
||||
/*
|
||||
* Revision levels
|
||||
*/
|
||||
#define EXT2_GOOD_OLD_REV 0 /* The good old (original) format */
|
||||
#define EXT2_DYNAMIC_REV 1 /* V2 format w/ dynamic inode sizes */
|
||||
|
||||
#define EXT2_CURRENT_REV EXT2_GOOD_OLD_REV
|
||||
#define EXT2_MAX_SUPP_REV EXT2_DYNAMIC_REV
|
||||
|
||||
#define EXT2_GOOD_OLD_INODE_SIZE 128
|
||||
|
||||
/*
|
||||
* Journal inode backup types
|
||||
*/
|
||||
#define EXT3_JNL_BACKUP_BLOCKS 1
|
||||
|
||||
/*
|
||||
* Feature set definitions
|
||||
*/
|
||||
|
||||
#define EXT2_HAS_COMPAT_FEATURE(sb,mask) \
|
||||
( EXT2_SB(sb)->s_feature_compat & (mask) )
|
||||
#define EXT2_HAS_RO_COMPAT_FEATURE(sb,mask) \
|
||||
( EXT2_SB(sb)->s_feature_ro_compat & (mask) )
|
||||
#define EXT2_HAS_INCOMPAT_FEATURE(sb,mask) \
|
||||
( EXT2_SB(sb)->s_feature_incompat & (mask) )
|
||||
|
||||
#define EXT2_FEATURE_COMPAT_DIR_PREALLOC 0x0001
|
||||
#define EXT2_FEATURE_COMPAT_IMAGIC_INODES 0x0002
|
||||
#define EXT3_FEATURE_COMPAT_HAS_JOURNAL 0x0004
|
||||
#define EXT2_FEATURE_COMPAT_EXT_ATTR 0x0008
|
||||
#define EXT2_FEATURE_COMPAT_RESIZE_INODE 0x0010
|
||||
#define EXT2_FEATURE_COMPAT_DIR_INDEX 0x0020
|
||||
|
||||
#define EXT2_FEATURE_RO_COMPAT_SPARSE_SUPER 0x0001
|
||||
#define EXT2_FEATURE_RO_COMPAT_LARGE_FILE 0x0002
|
||||
/* #define EXT2_FEATURE_RO_COMPAT_BTREE_DIR 0x0004 not used */
|
||||
|
||||
#define EXT2_FEATURE_INCOMPAT_COMPRESSION 0x0001
|
||||
#define EXT2_FEATURE_INCOMPAT_FILETYPE 0x0002
|
||||
#define EXT3_FEATURE_INCOMPAT_RECOVER 0x0004 /* Needs recovery */
|
||||
#define EXT3_FEATURE_INCOMPAT_JOURNAL_DEV 0x0008 /* Journal device */
|
||||
#define EXT2_FEATURE_INCOMPAT_META_BG 0x0010
|
||||
#define EXT3_FEATURE_INCOMPAT_EXTENTS 0x0040
|
||||
|
||||
|
||||
#define EXT2_FEATURE_COMPAT_SUPP 0
|
||||
#define EXT2_FEATURE_INCOMPAT_SUPP (EXT2_FEATURE_INCOMPAT_FILETYPE)
|
||||
#define EXT2_FEATURE_RO_COMPAT_SUPP (EXT2_FEATURE_RO_COMPAT_SPARSE_SUPER| \
|
||||
EXT2_FEATURE_RO_COMPAT_LARGE_FILE| \
|
||||
EXT2_FEATURE_RO_COMPAT_BTREE_DIR)
|
||||
|
||||
/*
|
||||
* Default values for user and/or group using reserved blocks
|
||||
*/
|
||||
#define EXT2_DEF_RESUID 0
|
||||
#define EXT2_DEF_RESGID 0
|
||||
|
||||
/*
|
||||
* Default mount options
|
||||
*/
|
||||
#define EXT2_DEFM_DEBUG 0x0001
|
||||
#define EXT2_DEFM_BSDGROUPS 0x0002
|
||||
#define EXT2_DEFM_XATTR_USER 0x0004
|
||||
#define EXT2_DEFM_ACL 0x0008
|
||||
#define EXT2_DEFM_UID16 0x0010
|
||||
#define EXT3_DEFM_JMODE 0x0060
|
||||
#define EXT3_DEFM_JMODE_DATA 0x0020
|
||||
#define EXT3_DEFM_JMODE_ORDERED 0x0040
|
||||
#define EXT3_DEFM_JMODE_WBACK 0x0060
|
||||
|
||||
/*
|
||||
* Structure of a directory entry
|
||||
*/
|
||||
#define EXT2_NAME_LEN 255
|
||||
|
||||
struct ext2_dir_entry {
|
||||
uint32_t inode; /* Inode number */
|
||||
uint16_t rec_len; /* Directory entry length */
|
||||
uint16_t name_len; /* Name length */
|
||||
char name[EXT2_NAME_LEN]; /* File name */
|
||||
};
|
||||
|
||||
/*
|
||||
* The new version of the directory entry. Since EXT2 structures are
|
||||
* stored in intel byte order, and the name_len field could never be
|
||||
* bigger than 255 chars, it's safe to reclaim the extra byte for the
|
||||
* file_type field.
|
||||
*/
|
||||
struct ext2_dir_entry_2 {
|
||||
uint32_t inode; /* Inode number */
|
||||
uint16_t rec_len; /* Directory entry length */
|
||||
uint8_t name_len; /* Name length */
|
||||
uint8_t file_type;
|
||||
char name[EXT2_NAME_LEN]; /* File name */
|
||||
};
|
||||
|
||||
/*
|
||||
* Ext2 directory file types. Only the low 3 bits are used. The
|
||||
* other bits are reserved for now.
|
||||
*/
|
||||
#define EXT2_FT_UNKNOWN 0
|
||||
#define EXT2_FT_REG_FILE 1
|
||||
#define EXT2_FT_DIR 2
|
||||
#define EXT2_FT_CHRDEV 3
|
||||
#define EXT2_FT_BLKDEV 4
|
||||
#define EXT2_FT_FIFO 5
|
||||
#define EXT2_FT_SOCK 6
|
||||
#define EXT2_FT_SYMLINK 7
|
||||
|
||||
#define EXT2_FT_MAX 8
|
||||
|
||||
/*
|
||||
* EXT2_DIR_PAD defines the directory entries boundaries
|
||||
*
|
||||
* NOTE: It must be a multiple of 4
|
||||
*/
|
||||
#define EXT2_DIR_PAD 4
|
||||
#define EXT2_DIR_ROUND (EXT2_DIR_PAD - 1)
|
||||
#define EXT2_DIR_REC_LEN(name_len) (((name_len) + 8 + EXT2_DIR_ROUND) & \
|
||||
~EXT2_DIR_ROUND)
|
||||
|
||||
#endif /* _LINUX_EXT2_FS_H */
|
197
e2fsprogs/e2fs_lib.c
Normal file
197
e2fsprogs/e2fs_lib.c
Normal file
@ -0,0 +1,197 @@
|
||||
/* vi: set sw=4 ts=4: */
|
||||
/*
|
||||
* See README for additional information
|
||||
*
|
||||
* This file can be redistributed under the terms of the GNU Library General
|
||||
* Public License
|
||||
*/
|
||||
|
||||
#include "libbb.h"
|
||||
#include "e2fs_lib.h"
|
||||
|
||||
#define HAVE_EXT2_IOCTLS 1
|
||||
|
||||
#if INT_MAX == LONG_MAX
|
||||
#define IF_LONG_IS_SAME(x) x
|
||||
#define IF_LONG_IS_WIDER(x)
|
||||
#else
|
||||
#define IF_LONG_IS_SAME(x)
|
||||
#define IF_LONG_IS_WIDER(x) x
|
||||
#endif
|
||||
|
||||
static void close_silently(int fd)
|
||||
{
|
||||
int e = errno;
|
||||
close(fd);
|
||||
errno = e;
|
||||
}
|
||||
|
||||
|
||||
/* Iterate a function on each entry of a directory */
|
||||
int iterate_on_dir(const char *dir_name,
|
||||
int (*func)(const char *, struct dirent *, void *),
|
||||
void * private)
|
||||
{
|
||||
DIR *dir;
|
||||
struct dirent *de, *dep;
|
||||
int max_len, len;
|
||||
|
||||
max_len = PATH_MAX + sizeof(struct dirent);
|
||||
de = xmalloc(max_len+1);
|
||||
memset(de, 0, max_len+1);
|
||||
|
||||
dir = opendir(dir_name);
|
||||
if (dir == NULL) {
|
||||
free(de);
|
||||
return -1;
|
||||
}
|
||||
while ((dep = readdir(dir))) {
|
||||
len = sizeof(struct dirent);
|
||||
if (len < dep->d_reclen)
|
||||
len = dep->d_reclen;
|
||||
if (len > max_len)
|
||||
len = max_len;
|
||||
memcpy(de, dep, len);
|
||||
func(dir_name, de, private);
|
||||
}
|
||||
closedir(dir);
|
||||
free(de);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/* Get/set a file version on an ext2 file system */
|
||||
int fgetsetversion(const char *name, unsigned long *get_version, unsigned long set_version)
|
||||
{
|
||||
#if HAVE_EXT2_IOCTLS
|
||||
int fd, r;
|
||||
IF_LONG_IS_WIDER(int ver;)
|
||||
|
||||
fd = open(name, O_NONBLOCK);
|
||||
if (fd == -1)
|
||||
return -1;
|
||||
if (!get_version) {
|
||||
IF_LONG_IS_WIDER(
|
||||
ver = (int) set_version;
|
||||
r = ioctl(fd, EXT2_IOC_SETVERSION, &ver);
|
||||
)
|
||||
IF_LONG_IS_SAME(
|
||||
r = ioctl(fd, EXT2_IOC_SETVERSION, (void*)&set_version);
|
||||
)
|
||||
} else {
|
||||
IF_LONG_IS_WIDER(
|
||||
r = ioctl(fd, EXT2_IOC_GETVERSION, &ver);
|
||||
*get_version = ver;
|
||||
)
|
||||
IF_LONG_IS_SAME(
|
||||
r = ioctl(fd, EXT2_IOC_GETVERSION, (void*)get_version);
|
||||
)
|
||||
}
|
||||
close_silently(fd);
|
||||
return r;
|
||||
#else /* ! HAVE_EXT2_IOCTLS */
|
||||
errno = EOPNOTSUPP;
|
||||
return -1;
|
||||
#endif /* ! HAVE_EXT2_IOCTLS */
|
||||
}
|
||||
|
||||
|
||||
/* Get/set a file flags on an ext2 file system */
|
||||
int fgetsetflags(const char *name, unsigned long *get_flags, unsigned long set_flags)
|
||||
{
|
||||
#if HAVE_EXT2_IOCTLS
|
||||
struct stat buf;
|
||||
int fd, r;
|
||||
IF_LONG_IS_WIDER(int f;)
|
||||
|
||||
if (stat(name, &buf) == 0 /* stat is ok */
|
||||
&& !S_ISREG(buf.st_mode) && !S_ISDIR(buf.st_mode)
|
||||
) {
|
||||
goto notsupp;
|
||||
}
|
||||
fd = open(name, O_NONBLOCK); /* neither read nor write asked for */
|
||||
if (fd == -1)
|
||||
return -1;
|
||||
|
||||
if (!get_flags) {
|
||||
IF_LONG_IS_WIDER(
|
||||
f = (int) set_flags;
|
||||
r = ioctl(fd, EXT2_IOC_SETFLAGS, &f);
|
||||
)
|
||||
IF_LONG_IS_SAME(
|
||||
r = ioctl(fd, EXT2_IOC_SETFLAGS, (void*)&set_flags);
|
||||
)
|
||||
} else {
|
||||
IF_LONG_IS_WIDER(
|
||||
r = ioctl(fd, EXT2_IOC_GETFLAGS, &f);
|
||||
*get_flags = f;
|
||||
)
|
||||
IF_LONG_IS_SAME(
|
||||
r = ioctl(fd, EXT2_IOC_GETFLAGS, (void*)get_flags);
|
||||
)
|
||||
}
|
||||
|
||||
close_silently(fd);
|
||||
return r;
|
||||
notsupp:
|
||||
#endif /* HAVE_EXT2_IOCTLS */
|
||||
errno = EOPNOTSUPP;
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
/* Print file attributes on an ext2 file system */
|
||||
struct flags_name {
|
||||
unsigned long flag;
|
||||
const char *short_name;
|
||||
const char *long_name;
|
||||
};
|
||||
|
||||
static const struct flags_name flags_array[] = {
|
||||
{ EXT2_SECRM_FL, "s", "Secure_Deletion" },
|
||||
{ EXT2_UNRM_FL, "u" , "Undelete" },
|
||||
{ EXT2_SYNC_FL, "S", "Synchronous_Updates" },
|
||||
{ EXT2_DIRSYNC_FL, "D", "Synchronous_Directory_Updates" },
|
||||
{ EXT2_IMMUTABLE_FL, "i", "Immutable" },
|
||||
{ EXT2_APPEND_FL, "a", "Append_Only" },
|
||||
{ EXT2_NODUMP_FL, "d", "No_Dump" },
|
||||
{ EXT2_NOATIME_FL, "A", "No_Atime" },
|
||||
{ EXT2_COMPR_FL, "c", "Compression_Requested" },
|
||||
#ifdef ENABLE_COMPRESSION
|
||||
{ EXT2_COMPRBLK_FL, "B", "Compressed_File" },
|
||||
{ EXT2_DIRTY_FL, "Z", "Compressed_Dirty_File" },
|
||||
{ EXT2_NOCOMPR_FL, "X", "Compression_Raw_Access" },
|
||||
{ EXT2_ECOMPR_FL, "E", "Compression_Error" },
|
||||
#endif
|
||||
{ EXT3_JOURNAL_DATA_FL, "j", "Journaled_Data" },
|
||||
{ EXT2_INDEX_FL, "I", "Indexed_direcctory" },
|
||||
{ EXT2_NOTAIL_FL, "t", "No_Tailmerging" },
|
||||
{ EXT2_TOPDIR_FL, "T", "Top_of_Directory_Hierarchies" },
|
||||
{ 0, NULL, NULL }
|
||||
};
|
||||
|
||||
void print_flags(FILE *f, unsigned long flags, unsigned options)
|
||||
{
|
||||
const struct flags_name *fp;
|
||||
|
||||
if (options & PFOPT_LONG) {
|
||||
int first = 1;
|
||||
for (fp = flags_array; fp->flag != 0; fp++) {
|
||||
if (flags & fp->flag) {
|
||||
if (!first)
|
||||
fputs(", ", f);
|
||||
fputs(fp->long_name, f);
|
||||
first = 0;
|
||||
}
|
||||
}
|
||||
if (first)
|
||||
fputs("---", f);
|
||||
} else {
|
||||
for (fp = flags_array; fp->flag != 0; fp++) {
|
||||
const char *p = "-";
|
||||
if (flags & fp->flag)
|
||||
p = fp->short_name;
|
||||
fputs(p, f);
|
||||
}
|
||||
}
|
||||
}
|
30
e2fsprogs/e2fs_lib.h
Normal file
30
e2fsprogs/e2fs_lib.h
Normal file
@ -0,0 +1,30 @@
|
||||
/* vi: set sw=4 ts=4: */
|
||||
/*
|
||||
* See README for additional information
|
||||
*
|
||||
* This file can be redistributed under the terms of the GNU Library General
|
||||
* Public License
|
||||
*/
|
||||
|
||||
/* Constants and structures */
|
||||
#include "e2fs_defs.h"
|
||||
|
||||
/* Iterate a function on each entry of a directory */
|
||||
int iterate_on_dir(const char *dir_name,
|
||||
int (*func)(const char *, struct dirent *, void *),
|
||||
void *private);
|
||||
|
||||
/* Get/set a file version on an ext2 file system */
|
||||
int fgetsetversion(const char *name, unsigned long *get_version, unsigned long set_version);
|
||||
#define fgetversion(name, version) fgetsetversion(name, version, 0)
|
||||
#define fsetversion(name, version) fgetsetversion(name, NULL, version)
|
||||
|
||||
/* Get/set a file flags on an ext2 file system */
|
||||
int fgetsetflags(const char *name, unsigned long *get_flags, unsigned long set_flags);
|
||||
#define fgetflags(name, flags) fgetsetflags(name, flags, 0)
|
||||
#define fsetflags(name, flags) fgetsetflags(name, NULL, flags)
|
||||
|
||||
/* Must be 1 for compatibility with `int long_format'. */
|
||||
#define PFOPT_LONG 1
|
||||
/* Print file attributes on an ext2 file system */
|
||||
void print_flags(FILE *f, unsigned long flags, unsigned options);
|
1319
e2fsprogs/fsck.c
Normal file
1319
e2fsprogs/fsck.c
Normal file
File diff suppressed because it is too large
Load Diff
114
e2fsprogs/lsattr.c
Normal file
114
e2fsprogs/lsattr.c
Normal file
@ -0,0 +1,114 @@
|
||||
/* vi: set sw=4 ts=4: */
|
||||
/*
|
||||
* lsattr.c - List file attributes on an ext2 file system
|
||||
*
|
||||
* Copyright (C) 1993, 1994 Remy Card <card@masi.ibp.fr>
|
||||
* Laboratoire MASI, Institut Blaise Pascal
|
||||
* Universite Pierre et Marie Curie (Paris VI)
|
||||
*
|
||||
* This file can be redistributed under the terms of the GNU General
|
||||
* Public License
|
||||
*/
|
||||
|
||||
/*
|
||||
* History:
|
||||
* 93/10/30 - Creation
|
||||
* 93/11/13 - Replace stat() calls by lstat() to avoid loops
|
||||
* 94/02/27 - Integrated in Ted's distribution
|
||||
* 98/12/29 - Display version info only when -V specified (G M Sipe)
|
||||
*/
|
||||
|
||||
#include "busybox.h"
|
||||
#include "e2fs_lib.h"
|
||||
|
||||
enum {
|
||||
OPT_RECUR = 0x1,
|
||||
OPT_ALL = 0x2,
|
||||
OPT_DIRS_OPT = 0x4,
|
||||
OPT_PF_LONG = 0x8,
|
||||
OPT_GENERATION = 0x10,
|
||||
};
|
||||
|
||||
static void list_attributes(const char *name)
|
||||
{
|
||||
unsigned long fsflags;
|
||||
unsigned long generation;
|
||||
|
||||
if (fgetflags(name, &fsflags) == -1)
|
||||
goto read_err;
|
||||
|
||||
if (option_mask32 & OPT_GENERATION) {
|
||||
if (fgetversion(name, &generation) == -1)
|
||||
goto read_err;
|
||||
printf("%5lu ", generation);
|
||||
}
|
||||
|
||||
if (option_mask32 & OPT_PF_LONG) {
|
||||
printf("%-28s ", name);
|
||||
print_flags(stdout, fsflags, PFOPT_LONG);
|
||||
puts("");
|
||||
} else {
|
||||
print_flags(stdout, fsflags, 0);
|
||||
printf(" %s\n", name);
|
||||
}
|
||||
|
||||
return;
|
||||
read_err:
|
||||
bb_perror_msg("reading %s", name);
|
||||
}
|
||||
|
||||
static int lsattr_dir_proc(const char *dir_name, struct dirent *de,
|
||||
void *private)
|
||||
{
|
||||
struct stat st;
|
||||
char *path;
|
||||
|
||||
path = concat_path_file(dir_name, de->d_name);
|
||||
|
||||
if (lstat(path, &st) == -1)
|
||||
bb_perror_msg("stat %s", path);
|
||||
|
||||
else if (de->d_name[0] != '.' || (option_mask32 & OPT_ALL)) {
|
||||
list_attributes(path);
|
||||
if (S_ISDIR(st.st_mode) && (option_mask32 & OPT_RECUR)
|
||||
&& (de->d_name[0] != '.'
|
||||
|| (de->d_name[1] != '\0' && NOT_LONE_CHAR(de->d_name+1, '.')))
|
||||
) {
|
||||
printf("\n%s:\n", path);
|
||||
iterate_on_dir(path, lsattr_dir_proc, NULL);
|
||||
puts("");
|
||||
}
|
||||
}
|
||||
|
||||
free(path);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void lsattr_args(const char *name)
|
||||
{
|
||||
struct stat st;
|
||||
|
||||
if (lstat(name, &st) == -1) {
|
||||
bb_perror_msg("stat %s", name);
|
||||
} else if (S_ISDIR(st.st_mode) && !(option_mask32 & OPT_DIRS_OPT)) {
|
||||
iterate_on_dir(name, lsattr_dir_proc, NULL);
|
||||
} else {
|
||||
list_attributes(name);
|
||||
}
|
||||
}
|
||||
|
||||
int lsattr_main(int argc, char **argv)
|
||||
{
|
||||
getopt32(argc, argv, "Radlv");
|
||||
argv += optind;
|
||||
|
||||
if (!*argv)
|
||||
lsattr_args(".");
|
||||
else {
|
||||
while (*argv)
|
||||
lsattr_args(*argv++);
|
||||
}
|
||||
|
||||
return EXIT_SUCCESS;
|
||||
}
|
67
e2fsprogs/old_e2fsprogs/Config.in
Normal file
67
e2fsprogs/old_e2fsprogs/Config.in
Normal file
@ -0,0 +1,67 @@
|
||||
#
|
||||
# For a description of the syntax of this configuration file,
|
||||
# see scripts/kbuild/config-language.txt.
|
||||
#
|
||||
|
||||
menu "Linux Ext2 FS Progs"
|
||||
|
||||
config CHATTR
|
||||
bool "chattr"
|
||||
default n
|
||||
help
|
||||
chattr changes the file attributes on a second extended file system.
|
||||
|
||||
config E2FSCK
|
||||
bool "e2fsck"
|
||||
default n
|
||||
help
|
||||
e2fsck is used to check Linux second extended file systems (ext2fs).
|
||||
e2fsck also supports ext2 filesystems countaining a journal (ext3).
|
||||
The normal compat symlinks 'fsck.ext2' and 'fsck.ext3' are also
|
||||
provided.
|
||||
|
||||
config FSCK
|
||||
bool "fsck"
|
||||
default n
|
||||
help
|
||||
fsck is used to check and optionally repair one or more filesystems.
|
||||
In actuality, fsck is simply a front-end for the various file system
|
||||
checkers (fsck.fstype) available under Linux.
|
||||
|
||||
config LSATTR
|
||||
bool "lsattr"
|
||||
default n
|
||||
help
|
||||
lsattr lists the file attributes on a second extended file system.
|
||||
|
||||
config MKE2FS
|
||||
bool "mke2fs"
|
||||
default n
|
||||
help
|
||||
mke2fs is used to create an ext2/ext3 filesystem. The normal compat
|
||||
symlinks 'mkfs.ext2' and 'mkfs.ext3' are also provided.
|
||||
|
||||
config TUNE2FS
|
||||
bool "tune2fs"
|
||||
default n
|
||||
help
|
||||
tune2fs allows the system administrator to adjust various tunable
|
||||
filesystem parameters on Linux ext2/ext3 filesystems.
|
||||
|
||||
config E2LABEL
|
||||
bool "e2label"
|
||||
default n
|
||||
depends on TUNE2FS
|
||||
help
|
||||
e2label will display or change the filesystem label on the ext2
|
||||
filesystem located on device.
|
||||
|
||||
config FINDFS
|
||||
bool "findfs"
|
||||
default n
|
||||
depends on TUNE2FS
|
||||
help
|
||||
findfs will search the disks in the system looking for a filesystem
|
||||
which has a label matching label or a UUID equal to uuid.
|
||||
|
||||
endmenu
|
16
e2fsprogs/old_e2fsprogs/Kbuild
Normal file
16
e2fsprogs/old_e2fsprogs/Kbuild
Normal file
@ -0,0 +1,16 @@
|
||||
# Makefile for busybox
|
||||
#
|
||||
# Copyright (C) 1999-2005 by Erik Andersen <andersen@codepoet.org>
|
||||
#
|
||||
# Licensed under the GPL v2, see the file LICENSE in this tarball.
|
||||
|
||||
lib-y:=
|
||||
|
||||
lib-$(CONFIG_CHATTR) += chattr.o
|
||||
lib-$(CONFIG_E2FSCK) += e2fsck.o util.o
|
||||
lib-$(CONFIG_FSCK) += fsck.o util.o
|
||||
lib-$(CONFIG_LSATTR) += lsattr.o
|
||||
lib-$(CONFIG_MKE2FS) += mke2fs.o util.o
|
||||
lib-$(CONFIG_TUNE2FS) += tune2fs.o util.o
|
||||
|
||||
CFLAGS += -include $(srctree)/e2fsprogs/e2fsbb.h
|
3
e2fsprogs/old_e2fsprogs/README
Normal file
3
e2fsprogs/old_e2fsprogs/README
Normal file
@ -0,0 +1,3 @@
|
||||
This is a pretty straight rip from the e2fsprogs pkg.
|
||||
|
||||
See README's in subdirs for specific info.
|
23
e2fsprogs/old_e2fsprogs/blkid/Kbuild
Normal file
23
e2fsprogs/old_e2fsprogs/blkid/Kbuild
Normal file
@ -0,0 +1,23 @@
|
||||
# Makefile for busybox
|
||||
#
|
||||
# Copyright (C) 1999-2005 by Erik Andersen <andersen@codepoet.org>
|
||||
#
|
||||
# Licensed under the GPL v2, see the file LICENSE in this tarball.
|
||||
|
||||
NEEDED-$(CONFIG_E2FSCK) = y
|
||||
NEEDED-$(CONFIG_FSCK) = y
|
||||
NEEDED-$(CONFIG_MKE2FS) = y
|
||||
NEEDED-$(CONFIG_TUNE2FS) = y
|
||||
|
||||
lib-y:=
|
||||
lib-$(NEEDED-y) += cache.o dev.o devname.o devno.o blkid_getsize.o \
|
||||
probe.o read.o resolve.o save.o tag.o list.o
|
||||
|
||||
CFLAGS_dev.o := -include $(srctree)/include/busybox.h
|
||||
CFLAGS_devname.o := -include $(srctree)/include/busybox.h
|
||||
CFLAGS_devno.o := -include $(srctree)/include/busybox.h
|
||||
CFLAGS_blkid_getsize.o := -include $(srctree)/include/busybox.h
|
||||
CFLAGS_probe.o := -include $(srctree)/include/busybox.h
|
||||
CFLAGS_save.o := -include $(srctree)/include/busybox.h
|
||||
CFLAGS_tag.o := -include $(srctree)/include/busybox.h
|
||||
CFLAGS_list.o := -include $(srctree)/include/busybox.h
|
105
e2fsprogs/old_e2fsprogs/blkid/blkid.h
Normal file
105
e2fsprogs/old_e2fsprogs/blkid/blkid.h
Normal file
@ -0,0 +1,105 @@
|
||||
/* vi: set sw=4 ts=4: */
|
||||
/*
|
||||
* blkid.h - Interface for libblkid, a library to identify block devices
|
||||
*
|
||||
* Copyright (C) 2001 Andreas Dilger
|
||||
* Copyright (C) 2003 Theodore Ts'o
|
||||
*
|
||||
* %Begin-Header%
|
||||
* This file may be redistributed under the terms of the
|
||||
* GNU Lesser General Public License.
|
||||
* %End-Header%
|
||||
*/
|
||||
|
||||
#ifndef _BLKID_BLKID_H
|
||||
#define _BLKID_BLKID_H
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <linux/types.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#define BLKID_VERSION "1.0.0"
|
||||
#define BLKID_DATE "12-Feb-2003"
|
||||
|
||||
typedef struct blkid_struct_dev *blkid_dev;
|
||||
typedef struct blkid_struct_cache *blkid_cache;
|
||||
typedef __s64 blkid_loff_t;
|
||||
|
||||
typedef struct blkid_struct_tag_iterate *blkid_tag_iterate;
|
||||
typedef struct blkid_struct_dev_iterate *blkid_dev_iterate;
|
||||
|
||||
/*
|
||||
* Flags for blkid_get_dev
|
||||
*
|
||||
* BLKID_DEV_CREATE Create an empty device structure if not found
|
||||
* in the cache.
|
||||
* BLKID_DEV_VERIFY Make sure the device structure corresponds
|
||||
* with reality.
|
||||
* BLKID_DEV_FIND Just look up a device entry, and return NULL
|
||||
* if it is not found.
|
||||
* BLKID_DEV_NORMAL Get a valid device structure, either from the
|
||||
* cache or by probing the device.
|
||||
*/
|
||||
#define BLKID_DEV_FIND 0x0000
|
||||
#define BLKID_DEV_CREATE 0x0001
|
||||
#define BLKID_DEV_VERIFY 0x0002
|
||||
#define BLKID_DEV_NORMAL (BLKID_DEV_CREATE | BLKID_DEV_VERIFY)
|
||||
|
||||
/* cache.c */
|
||||
extern void blkid_put_cache(blkid_cache cache);
|
||||
extern int blkid_get_cache(blkid_cache *cache, const char *filename);
|
||||
|
||||
/* dev.c */
|
||||
extern const char *blkid_dev_devname(blkid_dev dev);
|
||||
|
||||
extern blkid_dev_iterate blkid_dev_iterate_begin(blkid_cache cache);
|
||||
extern int blkid_dev_set_search(blkid_dev_iterate iter,
|
||||
char *search_type, char *search_value);
|
||||
extern int blkid_dev_next(blkid_dev_iterate iterate, blkid_dev *dev);
|
||||
extern void blkid_dev_iterate_end(blkid_dev_iterate iterate);
|
||||
|
||||
/* devno.c */
|
||||
extern char *blkid_devno_to_devname(dev_t devno);
|
||||
|
||||
/* devname.c */
|
||||
extern int blkid_probe_all(blkid_cache cache);
|
||||
extern int blkid_probe_all_new(blkid_cache cache);
|
||||
extern blkid_dev blkid_get_dev(blkid_cache cache, const char *devname,
|
||||
int flags);
|
||||
|
||||
/* getsize.c */
|
||||
extern blkid_loff_t blkid_get_dev_size(int fd);
|
||||
|
||||
/* probe.c */
|
||||
int blkid_known_fstype(const char *fstype);
|
||||
extern blkid_dev blkid_verify(blkid_cache cache, blkid_dev dev);
|
||||
|
||||
/* read.c */
|
||||
|
||||
/* resolve.c */
|
||||
extern char *blkid_get_tag_value(blkid_cache cache, const char *tagname,
|
||||
const char *devname);
|
||||
extern char *blkid_get_devname(blkid_cache cache, const char *token,
|
||||
const char *value);
|
||||
|
||||
/* tag.c */
|
||||
extern blkid_tag_iterate blkid_tag_iterate_begin(blkid_dev dev);
|
||||
extern int blkid_tag_next(blkid_tag_iterate iterate,
|
||||
const char **type, const char **value);
|
||||
extern void blkid_tag_iterate_end(blkid_tag_iterate iterate);
|
||||
extern int blkid_dev_has_tag(blkid_dev dev, const char *type,
|
||||
const char *value);
|
||||
extern blkid_dev blkid_find_dev_with_tag(blkid_cache cache,
|
||||
const char *type,
|
||||
const char *value);
|
||||
extern int blkid_parse_tag_string(const char *token, char **ret_type,
|
||||
char **ret_val);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* _BLKID_BLKID_H */
|
187
e2fsprogs/old_e2fsprogs/blkid/blkidP.h
Normal file
187
e2fsprogs/old_e2fsprogs/blkid/blkidP.h
Normal file
@ -0,0 +1,187 @@
|
||||
/* vi: set sw=4 ts=4: */
|
||||
/*
|
||||
* blkidP.h - Internal interfaces for libblkid
|
||||
*
|
||||
* Copyright (C) 2001 Andreas Dilger
|
||||
* Copyright (C) 2003 Theodore Ts'o
|
||||
*
|
||||
* %Begin-Header%
|
||||
* This file may be redistributed under the terms of the
|
||||
* GNU Lesser General Public License.
|
||||
* %End-Header%
|
||||
*/
|
||||
|
||||
#ifndef _BLKID_BLKIDP_H
|
||||
#define _BLKID_BLKIDP_H
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include "blkid.h"
|
||||
#include "list.h"
|
||||
|
||||
#ifdef __GNUC__
|
||||
#define __BLKID_ATTR(x) __attribute__(x)
|
||||
#else
|
||||
#define __BLKID_ATTR(x)
|
||||
#endif
|
||||
|
||||
|
||||
/*
|
||||
* This describes the attributes of a specific device.
|
||||
* We can traverse all of the tags by bid_tags (linking to the tag bit_names).
|
||||
* The bid_label and bid_uuid fields are shortcuts to the LABEL and UUID tag
|
||||
* values, if they exist.
|
||||
*/
|
||||
struct blkid_struct_dev
|
||||
{
|
||||
struct list_head bid_devs; /* All devices in the cache */
|
||||
struct list_head bid_tags; /* All tags for this device */
|
||||
blkid_cache bid_cache; /* Dev belongs to this cache */
|
||||
char *bid_name; /* Device inode pathname */
|
||||
char *bid_type; /* Preferred device TYPE */
|
||||
int bid_pri; /* Device priority */
|
||||
dev_t bid_devno; /* Device major/minor number */
|
||||
time_t bid_time; /* Last update time of device */
|
||||
unsigned int bid_flags; /* Device status bitflags */
|
||||
char *bid_label; /* Shortcut to device LABEL */
|
||||
char *bid_uuid; /* Shortcut to binary UUID */
|
||||
};
|
||||
|
||||
#define BLKID_BID_FL_VERIFIED 0x0001 /* Device data validated from disk */
|
||||
#define BLKID_BID_FL_INVALID 0x0004 /* Device is invalid */
|
||||
|
||||
/*
|
||||
* Each tag defines a NAME=value pair for a particular device. The tags
|
||||
* are linked via bit_names for a single device, so that traversing the
|
||||
* names list will get you a list of all tags associated with a device.
|
||||
* They are also linked via bit_values for all devices, so one can easily
|
||||
* search all tags with a given NAME for a specific value.
|
||||
*/
|
||||
struct blkid_struct_tag
|
||||
{
|
||||
struct list_head bit_tags; /* All tags for this device */
|
||||
struct list_head bit_names; /* All tags with given NAME */
|
||||
char *bit_name; /* NAME of tag (shared) */
|
||||
char *bit_val; /* value of tag */
|
||||
blkid_dev bit_dev; /* pointer to device */
|
||||
};
|
||||
typedef struct blkid_struct_tag *blkid_tag;
|
||||
|
||||
/*
|
||||
* Minimum number of seconds between device probes, even when reading
|
||||
* from the cache. This is to avoid re-probing all devices which were
|
||||
* just probed by another program that does not share the cache.
|
||||
*/
|
||||
#define BLKID_PROBE_MIN 2
|
||||
|
||||
/*
|
||||
* Time in seconds an entry remains verified in the in-memory cache
|
||||
* before being reverified (in case of long-running processes that
|
||||
* keep a cache in memory and continue to use it for a long time).
|
||||
*/
|
||||
#define BLKID_PROBE_INTERVAL 200
|
||||
|
||||
/* This describes an entire blkid cache file and probed devices.
|
||||
* We can traverse all of the found devices via bic_list.
|
||||
* We can traverse all of the tag types by bic_tags, which hold empty tags
|
||||
* for each tag type. Those tags can be used as list_heads for iterating
|
||||
* through all devices with a specific tag type (e.g. LABEL).
|
||||
*/
|
||||
struct blkid_struct_cache
|
||||
{
|
||||
struct list_head bic_devs; /* List head of all devices */
|
||||
struct list_head bic_tags; /* List head of all tag types */
|
||||
time_t bic_time; /* Last probe time */
|
||||
time_t bic_ftime; /* Mod time of the cachefile */
|
||||
unsigned int bic_flags; /* Status flags of the cache */
|
||||
char *bic_filename; /* filename of cache */
|
||||
};
|
||||
|
||||
#define BLKID_BIC_FL_PROBED 0x0002 /* We probed /proc/partition devices */
|
||||
#define BLKID_BIC_FL_CHANGED 0x0004 /* Cache has changed from disk */
|
||||
|
||||
extern char *blkid_strdup(const char *s);
|
||||
extern char *blkid_strndup(const char *s, const int length);
|
||||
|
||||
#define BLKID_CACHE_FILE "/etc/blkid.tab"
|
||||
extern const char *blkid_devdirs[];
|
||||
|
||||
#define BLKID_ERR_IO 5
|
||||
#define BLKID_ERR_PROC 9
|
||||
#define BLKID_ERR_MEM 12
|
||||
#define BLKID_ERR_CACHE 14
|
||||
#define BLKID_ERR_DEV 19
|
||||
#define BLKID_ERR_PARAM 22
|
||||
#define BLKID_ERR_BIG 27
|
||||
|
||||
/*
|
||||
* Priority settings for different types of devices
|
||||
*/
|
||||
#define BLKID_PRI_EVMS 30
|
||||
#define BLKID_PRI_LVM 20
|
||||
#define BLKID_PRI_MD 10
|
||||
|
||||
#if defined(TEST_PROGRAM) && !defined(CONFIG_BLKID_DEBUG)
|
||||
#define CONFIG_BLKID_DEBUG
|
||||
#endif
|
||||
|
||||
#define DEBUG_CACHE 0x0001
|
||||
#define DEBUG_DUMP 0x0002
|
||||
#define DEBUG_DEV 0x0004
|
||||
#define DEBUG_DEVNAME 0x0008
|
||||
#define DEBUG_DEVNO 0x0010
|
||||
#define DEBUG_PROBE 0x0020
|
||||
#define DEBUG_READ 0x0040
|
||||
#define DEBUG_RESOLVE 0x0080
|
||||
#define DEBUG_SAVE 0x0100
|
||||
#define DEBUG_TAG 0x0200
|
||||
#define DEBUG_INIT 0x8000
|
||||
#define DEBUG_ALL 0xFFFF
|
||||
|
||||
#ifdef CONFIG_BLKID_DEBUG
|
||||
#include <stdio.h>
|
||||
extern int blkid_debug_mask;
|
||||
#define DBG(m,x) if ((m) & blkid_debug_mask) x;
|
||||
#else
|
||||
#define DBG(m,x)
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_BLKID_DEBUG
|
||||
extern void blkid_debug_dump_dev(blkid_dev dev);
|
||||
extern void blkid_debug_dump_tag(blkid_tag tag);
|
||||
#endif
|
||||
|
||||
/* lseek.c */
|
||||
/* extern blkid_loff_t blkid_llseek(int fd, blkid_loff_t offset, int whence); */
|
||||
#ifdef CONFIG_LFS
|
||||
# define blkid_llseek lseek64
|
||||
#else
|
||||
# define blkid_llseek lseek
|
||||
#endif
|
||||
|
||||
/* read.c */
|
||||
extern void blkid_read_cache(blkid_cache cache);
|
||||
|
||||
/* save.c */
|
||||
extern int blkid_flush_cache(blkid_cache cache);
|
||||
|
||||
/*
|
||||
* Functions to create and find a specific tag type: tag.c
|
||||
*/
|
||||
extern void blkid_free_tag(blkid_tag tag);
|
||||
extern blkid_tag blkid_find_tag_dev(blkid_dev dev, const char *type);
|
||||
extern int blkid_set_tag(blkid_dev dev, const char *name,
|
||||
const char *value, const int vlength);
|
||||
|
||||
/*
|
||||
* Functions to create and find a specific tag type: dev.c
|
||||
*/
|
||||
extern blkid_dev blkid_new_dev(void);
|
||||
extern void blkid_free_dev(blkid_dev dev);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* _BLKID_BLKIDP_H */
|
179
e2fsprogs/old_e2fsprogs/blkid/blkid_getsize.c
Normal file
179
e2fsprogs/old_e2fsprogs/blkid/blkid_getsize.c
Normal file
@ -0,0 +1,179 @@
|
||||
/* vi: set sw=4 ts=4: */
|
||||
/*
|
||||
* getsize.c --- get the size of a partition.
|
||||
*
|
||||
* Copyright (C) 1995, 1995 Theodore Ts'o.
|
||||
*
|
||||
* %Begin-Header%
|
||||
* This file may be redistributed under the terms of the
|
||||
* GNU Lesser General Public License.
|
||||
* %End-Header%
|
||||
*/
|
||||
|
||||
/* include this before sys/queues.h! */
|
||||
#include "blkidP.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <unistd.h>
|
||||
#ifdef HAVE_ERRNO_H
|
||||
#include <errno.h>
|
||||
#endif
|
||||
#include <fcntl.h>
|
||||
#ifdef HAVE_SYS_IOCTL_H
|
||||
#include <sys/ioctl.h>
|
||||
#endif
|
||||
#ifdef HAVE_LINUX_FD_H
|
||||
#include <linux/fd.h>
|
||||
#endif
|
||||
#ifdef HAVE_SYS_DISKLABEL_H
|
||||
#include <sys/disklabel.h>
|
||||
#include <sys/stat.h>
|
||||
#endif
|
||||
#ifdef HAVE_SYS_DISK_H
|
||||
#ifdef HAVE_SYS_QUEUE_H
|
||||
#include <sys/queue.h> /* for LIST_HEAD */
|
||||
#endif
|
||||
#include <sys/disk.h>
|
||||
#endif
|
||||
#ifdef __linux__
|
||||
#include <sys/utsname.h>
|
||||
#endif
|
||||
|
||||
#if defined(__linux__) && defined(_IO) && !defined(BLKGETSIZE)
|
||||
#define BLKGETSIZE _IO(0x12,96) /* return device size */
|
||||
#endif
|
||||
|
||||
#if defined(__linux__) && defined(_IOR) && !defined(BLKGETSIZE64)
|
||||
#define BLKGETSIZE64 _IOR(0x12,114,size_t) /* return device size in bytes (u64 *arg) */
|
||||
#endif
|
||||
|
||||
#ifdef APPLE_DARWIN
|
||||
#define BLKGETSIZE DKIOCGETBLOCKCOUNT32
|
||||
#endif /* APPLE_DARWIN */
|
||||
|
||||
static int valid_offset(int fd, blkid_loff_t offset)
|
||||
{
|
||||
char ch;
|
||||
|
||||
if (blkid_llseek(fd, offset, 0) < 0)
|
||||
return 0;
|
||||
if (read(fd, &ch, 1) < 1)
|
||||
return 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* Returns the number of blocks in a partition
|
||||
*/
|
||||
blkid_loff_t blkid_get_dev_size(int fd)
|
||||
{
|
||||
int valid_blkgetsize64 = 1;
|
||||
#ifdef __linux__
|
||||
struct utsname ut;
|
||||
#endif
|
||||
unsigned long long size64;
|
||||
unsigned long size;
|
||||
blkid_loff_t high, low;
|
||||
#ifdef FDGETPRM
|
||||
struct floppy_struct this_floppy;
|
||||
#endif
|
||||
#ifdef HAVE_SYS_DISKLABEL_H
|
||||
int part = -1;
|
||||
struct disklabel lab;
|
||||
struct partition *pp;
|
||||
char ch;
|
||||
struct stat st;
|
||||
#endif /* HAVE_SYS_DISKLABEL_H */
|
||||
|
||||
#ifdef DKIOCGETBLOCKCOUNT /* For Apple Darwin */
|
||||
if (ioctl(fd, DKIOCGETBLOCKCOUNT, &size64) >= 0) {
|
||||
if ((sizeof(blkid_loff_t) < sizeof(unsigned long long))
|
||||
&& (size64 << 9 > 0xFFFFFFFF))
|
||||
return 0; /* EFBIG */
|
||||
return (blkid_loff_t) size64 << 9;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef BLKGETSIZE64
|
||||
#ifdef __linux__
|
||||
if ((uname(&ut) == 0) &&
|
||||
((ut.release[0] == '2') && (ut.release[1] == '.') &&
|
||||
(ut.release[2] < '6') && (ut.release[3] == '.')))
|
||||
valid_blkgetsize64 = 0;
|
||||
#endif
|
||||
if (valid_blkgetsize64 &&
|
||||
ioctl(fd, BLKGETSIZE64, &size64) >= 0) {
|
||||
if ((sizeof(blkid_loff_t) < sizeof(unsigned long long))
|
||||
&& ((size64) > 0xFFFFFFFF))
|
||||
return 0; /* EFBIG */
|
||||
return size64;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef BLKGETSIZE
|
||||
if (ioctl(fd, BLKGETSIZE, &size) >= 0)
|
||||
return (blkid_loff_t)size << 9;
|
||||
#endif
|
||||
|
||||
#ifdef FDGETPRM
|
||||
if (ioctl(fd, FDGETPRM, &this_floppy) >= 0)
|
||||
return (blkid_loff_t)this_floppy.size << 9;
|
||||
#endif
|
||||
#ifdef HAVE_SYS_DISKLABEL_H
|
||||
#if 0
|
||||
/*
|
||||
* This should work in theory but I haven't tested it. Anyone
|
||||
* on a BSD system want to test this for me? In the meantime,
|
||||
* binary search mechanism should work just fine.
|
||||
*/
|
||||
if ((fstat(fd, &st) >= 0) && S_ISBLK(st.st_mode))
|
||||
part = st.st_rdev & 7;
|
||||
if (part >= 0 && (ioctl(fd, DIOCGDINFO, (char *)&lab) >= 0)) {
|
||||
pp = &lab.d_partitions[part];
|
||||
if (pp->p_size)
|
||||
return pp->p_size << 9;
|
||||
}
|
||||
#endif
|
||||
#endif /* HAVE_SYS_DISKLABEL_H */
|
||||
|
||||
/*
|
||||
* OK, we couldn't figure it out by using a specialized ioctl,
|
||||
* which is generally the best way. So do binary search to
|
||||
* find the size of the partition.
|
||||
*/
|
||||
low = 0;
|
||||
for (high = 1024; valid_offset(fd, high); high *= 2)
|
||||
low = high;
|
||||
while (low < high - 1)
|
||||
{
|
||||
const blkid_loff_t mid = (low + high) / 2;
|
||||
|
||||
if (valid_offset(fd, mid))
|
||||
low = mid;
|
||||
else
|
||||
high = mid;
|
||||
}
|
||||
return low + 1;
|
||||
}
|
||||
|
||||
#ifdef TEST_PROGRAM
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
blkid_loff_t bytes;
|
||||
int fd;
|
||||
|
||||
if (argc < 2) {
|
||||
fprintf(stderr, "Usage: %s device\n"
|
||||
"Determine the size of a device\n", argv[0]);
|
||||
return 1;
|
||||
}
|
||||
|
||||
if ((fd = open(argv[1], O_RDONLY)) < 0)
|
||||
perror(argv[0]);
|
||||
|
||||
bytes = blkid_get_dev_size(fd);
|
||||
printf("Device %s has %lld 1k blocks.\n", argv[1], bytes >> 10);
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif
|
126
e2fsprogs/old_e2fsprogs/blkid/cache.c
Normal file
126
e2fsprogs/old_e2fsprogs/blkid/cache.c
Normal file
@ -0,0 +1,126 @@
|
||||
/* vi: set sw=4 ts=4: */
|
||||
/*
|
||||
* cache.c - allocation/initialization/free routines for cache
|
||||
*
|
||||
* Copyright (C) 2001 Andreas Dilger
|
||||
* Copyright (C) 2003 Theodore Ts'o
|
||||
*
|
||||
* %Begin-Header%
|
||||
* This file may be redistributed under the terms of the
|
||||
* GNU Lesser General Public License.
|
||||
* %End-Header%
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include "blkidP.h"
|
||||
|
||||
int blkid_debug_mask = 0;
|
||||
|
||||
int blkid_get_cache(blkid_cache *ret_cache, const char *filename)
|
||||
{
|
||||
blkid_cache cache;
|
||||
|
||||
#ifdef CONFIG_BLKID_DEBUG
|
||||
if (!(blkid_debug_mask & DEBUG_INIT)) {
|
||||
char *dstr = getenv("BLKID_DEBUG");
|
||||
|
||||
if (dstr)
|
||||
blkid_debug_mask = strtoul(dstr, 0, 0);
|
||||
blkid_debug_mask |= DEBUG_INIT;
|
||||
}
|
||||
#endif
|
||||
|
||||
DBG(DEBUG_CACHE, printf("creating blkid cache (using %s)\n",
|
||||
filename ? filename : "default cache"));
|
||||
|
||||
if (!(cache = (blkid_cache) calloc(1, sizeof(struct blkid_struct_cache))))
|
||||
return -BLKID_ERR_MEM;
|
||||
|
||||
INIT_LIST_HEAD(&cache->bic_devs);
|
||||
INIT_LIST_HEAD(&cache->bic_tags);
|
||||
|
||||
if (filename && !strlen(filename))
|
||||
filename = 0;
|
||||
if (!filename && (getuid() == geteuid()))
|
||||
filename = getenv("BLKID_FILE");
|
||||
if (!filename)
|
||||
filename = BLKID_CACHE_FILE;
|
||||
cache->bic_filename = blkid_strdup(filename);
|
||||
|
||||
blkid_read_cache(cache);
|
||||
|
||||
*ret_cache = cache;
|
||||
return 0;
|
||||
}
|
||||
|
||||
void blkid_put_cache(blkid_cache cache)
|
||||
{
|
||||
if (!cache)
|
||||
return;
|
||||
|
||||
(void) blkid_flush_cache(cache);
|
||||
|
||||
DBG(DEBUG_CACHE, printf("freeing cache struct\n"));
|
||||
|
||||
/* DBG(DEBUG_CACHE, blkid_debug_dump_cache(cache)); */
|
||||
|
||||
while (!list_empty(&cache->bic_devs)) {
|
||||
blkid_dev dev = list_entry(cache->bic_devs.next,
|
||||
struct blkid_struct_dev,
|
||||
bid_devs);
|
||||
blkid_free_dev(dev);
|
||||
}
|
||||
|
||||
while (!list_empty(&cache->bic_tags)) {
|
||||
blkid_tag tag = list_entry(cache->bic_tags.next,
|
||||
struct blkid_struct_tag,
|
||||
bit_tags);
|
||||
|
||||
while (!list_empty(&tag->bit_names)) {
|
||||
blkid_tag bad = list_entry(tag->bit_names.next,
|
||||
struct blkid_struct_tag,
|
||||
bit_names);
|
||||
|
||||
DBG(DEBUG_CACHE, printf("warning: unfreed tag %s=%s\n",
|
||||
bad->bit_name, bad->bit_val));
|
||||
blkid_free_tag(bad);
|
||||
}
|
||||
blkid_free_tag(tag);
|
||||
}
|
||||
free(cache->bic_filename);
|
||||
|
||||
free(cache);
|
||||
}
|
||||
|
||||
#ifdef TEST_PROGRAM
|
||||
int main(int argc, char** argv)
|
||||
{
|
||||
blkid_cache cache = NULL;
|
||||
int ret;
|
||||
|
||||
blkid_debug_mask = DEBUG_ALL;
|
||||
if ((argc > 2)) {
|
||||
fprintf(stderr, "Usage: %s [filename]\n", argv[0]);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if ((ret = blkid_get_cache(&cache, argv[1])) < 0) {
|
||||
fprintf(stderr, "error %d parsing cache file %s\n", ret,
|
||||
argv[1] ? argv[1] : BLKID_CACHE_FILE);
|
||||
exit(1);
|
||||
}
|
||||
if ((ret = blkid_get_cache(&cache, bb_dev_null)) != 0) {
|
||||
fprintf(stderr, "%s: error creating cache (%d)\n",
|
||||
argv[0], ret);
|
||||
exit(1);
|
||||
}
|
||||
if ((ret = blkid_probe_all(cache) < 0))
|
||||
fprintf(stderr, "error probing devices\n");
|
||||
|
||||
blkid_put_cache(cache);
|
||||
|
||||
return ret;
|
||||
}
|
||||
#endif
|
214
e2fsprogs/old_e2fsprogs/blkid/dev.c
Normal file
214
e2fsprogs/old_e2fsprogs/blkid/dev.c
Normal file
@ -0,0 +1,214 @@
|
||||
/* vi: set sw=4 ts=4: */
|
||||
/*
|
||||
* dev.c - allocation/initialization/free routines for dev
|
||||
*
|
||||
* Copyright (C) 2001 Andreas Dilger
|
||||
* Copyright (C) 2003 Theodore Ts'o
|
||||
*
|
||||
* %Begin-Header%
|
||||
* This file may be redistributed under the terms of the
|
||||
* GNU Lesser General Public License.
|
||||
* %End-Header%
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "blkidP.h"
|
||||
|
||||
blkid_dev blkid_new_dev(void)
|
||||
{
|
||||
blkid_dev dev;
|
||||
|
||||
if (!(dev = (blkid_dev) calloc(1, sizeof(struct blkid_struct_dev))))
|
||||
return NULL;
|
||||
|
||||
INIT_LIST_HEAD(&dev->bid_devs);
|
||||
INIT_LIST_HEAD(&dev->bid_tags);
|
||||
|
||||
return dev;
|
||||
}
|
||||
|
||||
void blkid_free_dev(blkid_dev dev)
|
||||
{
|
||||
if (!dev)
|
||||
return;
|
||||
|
||||
DBG(DEBUG_DEV,
|
||||
printf(" freeing dev %s (%s)\n", dev->bid_name, dev->bid_type));
|
||||
DBG(DEBUG_DEV, blkid_debug_dump_dev(dev));
|
||||
|
||||
list_del(&dev->bid_devs);
|
||||
while (!list_empty(&dev->bid_tags)) {
|
||||
blkid_tag tag = list_entry(dev->bid_tags.next,
|
||||
struct blkid_struct_tag,
|
||||
bit_tags);
|
||||
blkid_free_tag(tag);
|
||||
}
|
||||
if (dev->bid_name)
|
||||
free(dev->bid_name);
|
||||
free(dev);
|
||||
}
|
||||
|
||||
/*
|
||||
* Given a blkid device, return its name
|
||||
*/
|
||||
const char *blkid_dev_devname(blkid_dev dev)
|
||||
{
|
||||
return dev->bid_name;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_BLKID_DEBUG
|
||||
void blkid_debug_dump_dev(blkid_dev dev)
|
||||
{
|
||||
struct list_head *p;
|
||||
|
||||
if (!dev) {
|
||||
printf(" dev: NULL\n");
|
||||
return;
|
||||
}
|
||||
|
||||
printf(" dev: name = %s\n", dev->bid_name);
|
||||
printf(" dev: DEVNO=\"0x%0llx\"\n", dev->bid_devno);
|
||||
printf(" dev: TIME=\"%lu\"\n", dev->bid_time);
|
||||
printf(" dev: PRI=\"%d\"\n", dev->bid_pri);
|
||||
printf(" dev: flags = 0x%08X\n", dev->bid_flags);
|
||||
|
||||
list_for_each(p, &dev->bid_tags) {
|
||||
blkid_tag tag = list_entry(p, struct blkid_struct_tag, bit_tags);
|
||||
if (tag)
|
||||
printf(" tag: %s=\"%s\"\n", tag->bit_name,
|
||||
tag->bit_val);
|
||||
else
|
||||
printf(" tag: NULL\n");
|
||||
}
|
||||
puts("");
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* dev iteration routines for the public libblkid interface.
|
||||
*
|
||||
* These routines do not expose the list.h implementation, which are a
|
||||
* contamination of the namespace, and which force us to reveal far, far
|
||||
* too much of our internal implemenation. I'm not convinced I want
|
||||
* to keep list.h in the long term, anyway. It's fine for kernel
|
||||
* programming, but performance is not the #1 priority for this
|
||||
* library, and I really don't like the tradeoff of type-safety for
|
||||
* performance for this application. [tytso:20030125.2007EST]
|
||||
*/
|
||||
|
||||
/*
|
||||
* This series of functions iterate over all devices in a blkid cache
|
||||
*/
|
||||
#define DEV_ITERATE_MAGIC 0x01a5284c
|
||||
|
||||
struct blkid_struct_dev_iterate {
|
||||
int magic;
|
||||
blkid_cache cache;
|
||||
struct list_head *p;
|
||||
};
|
||||
|
||||
blkid_dev_iterate blkid_dev_iterate_begin(blkid_cache cache)
|
||||
{
|
||||
blkid_dev_iterate iter;
|
||||
|
||||
iter = xmalloc(sizeof(struct blkid_struct_dev_iterate));
|
||||
iter->magic = DEV_ITERATE_MAGIC;
|
||||
iter->cache = cache;
|
||||
iter->p = cache->bic_devs.next;
|
||||
return iter;
|
||||
}
|
||||
|
||||
/*
|
||||
* Return 0 on success, -1 on error
|
||||
*/
|
||||
extern int blkid_dev_next(blkid_dev_iterate iter,
|
||||
blkid_dev *dev)
|
||||
{
|
||||
*dev = 0;
|
||||
if (!iter || iter->magic != DEV_ITERATE_MAGIC ||
|
||||
iter->p == &iter->cache->bic_devs)
|
||||
return -1;
|
||||
*dev = list_entry(iter->p, struct blkid_struct_dev, bid_devs);
|
||||
iter->p = iter->p->next;
|
||||
return 0;
|
||||
}
|
||||
|
||||
void blkid_dev_iterate_end(blkid_dev_iterate iter)
|
||||
{
|
||||
if (!iter || iter->magic != DEV_ITERATE_MAGIC)
|
||||
return;
|
||||
iter->magic = 0;
|
||||
free(iter);
|
||||
}
|
||||
|
||||
#ifdef TEST_PROGRAM
|
||||
#ifdef HAVE_GETOPT_H
|
||||
#include <getopt.h>
|
||||
#else
|
||||
extern char *optarg;
|
||||
extern int optind;
|
||||
#endif
|
||||
|
||||
void usage(char *prog)
|
||||
{
|
||||
fprintf(stderr, "Usage: %s [-f blkid_file] [-m debug_mask]\n", prog);
|
||||
fprintf(stderr, "\tList all devices and exit\n", prog);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
blkid_dev_iterate iter;
|
||||
blkid_cache cache = NULL;
|
||||
blkid_dev dev;
|
||||
int c, ret;
|
||||
char *tmp;
|
||||
char *file = NULL;
|
||||
char *search_type = NULL;
|
||||
char *search_value = NULL;
|
||||
|
||||
while ((c = getopt (argc, argv, "m:f:")) != EOF)
|
||||
switch (c) {
|
||||
case 'f':
|
||||
file = optarg;
|
||||
break;
|
||||
case 'm':
|
||||
blkid_debug_mask = strtoul (optarg, &tmp, 0);
|
||||
if (*tmp) {
|
||||
fprintf(stderr, "Invalid debug mask: %d\n",
|
||||
optarg);
|
||||
exit(1);
|
||||
}
|
||||
break;
|
||||
case '?':
|
||||
usage(argv[0]);
|
||||
}
|
||||
if (argc >= optind+2) {
|
||||
search_type = argv[optind];
|
||||
search_value = argv[optind+1];
|
||||
optind += 2;
|
||||
}
|
||||
if (argc != optind)
|
||||
usage(argv[0]);
|
||||
|
||||
if ((ret = blkid_get_cache(&cache, file)) != 0) {
|
||||
fprintf(stderr, "%s: error creating cache (%d)\n",
|
||||
argv[0], ret);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
iter = blkid_dev_iterate_begin(cache);
|
||||
if (search_type)
|
||||
blkid_dev_set_search(iter, search_type, search_value);
|
||||
while (blkid_dev_next(iter, &dev) == 0) {
|
||||
printf("Device: %s\n", blkid_dev_devname(dev));
|
||||
}
|
||||
blkid_dev_iterate_end(iter);
|
||||
|
||||
|
||||
blkid_put_cache(cache);
|
||||
return 0;
|
||||
}
|
||||
#endif
|
368
e2fsprogs/old_e2fsprogs/blkid/devname.c
Normal file
368
e2fsprogs/old_e2fsprogs/blkid/devname.c
Normal file
@ -0,0 +1,368 @@
|
||||
/* vi: set sw=4 ts=4: */
|
||||
/*
|
||||
* devname.c - get a dev by its device inode name
|
||||
*
|
||||
* Copyright (C) Andries Brouwer
|
||||
* Copyright (C) 1999, 2000, 2001, 2002, 2003 Theodore Ts'o
|
||||
* Copyright (C) 2001 Andreas Dilger
|
||||
*
|
||||
* %Begin-Header%
|
||||
* This file may be redistributed under the terms of the
|
||||
* GNU Lesser General Public License.
|
||||
* %End-Header%
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#ifdef HAVE_UNISTD_H
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <ctype.h>
|
||||
#ifdef HAVE_SYS_TYPES_H
|
||||
#include <sys/types.h>
|
||||
#endif
|
||||
#include <sys/stat.h>
|
||||
#ifdef HAVE_ERRNO_H
|
||||
#include <errno.h>
|
||||
#endif
|
||||
#ifdef HAVE_SYS_MKDEV_H
|
||||
#include <sys/mkdev.h>
|
||||
#endif
|
||||
#include <time.h>
|
||||
|
||||
#include "blkidP.h"
|
||||
|
||||
/*
|
||||
* Find a dev struct in the cache by device name, if available.
|
||||
*
|
||||
* If there is no entry with the specified device name, and the create
|
||||
* flag is set, then create an empty device entry.
|
||||
*/
|
||||
blkid_dev blkid_get_dev(blkid_cache cache, const char *devname, int flags)
|
||||
{
|
||||
blkid_dev dev = NULL, tmp;
|
||||
struct list_head *p;
|
||||
|
||||
if (!cache || !devname)
|
||||
return NULL;
|
||||
|
||||
list_for_each(p, &cache->bic_devs) {
|
||||
tmp = list_entry(p, struct blkid_struct_dev, bid_devs);
|
||||
if (strcmp(tmp->bid_name, devname))
|
||||
continue;
|
||||
|
||||
DBG(DEBUG_DEVNAME,
|
||||
printf("found devname %s in cache\n", tmp->bid_name));
|
||||
dev = tmp;
|
||||
break;
|
||||
}
|
||||
|
||||
if (!dev && (flags & BLKID_DEV_CREATE)) {
|
||||
dev = blkid_new_dev();
|
||||
if (!dev)
|
||||
return NULL;
|
||||
dev->bid_name = blkid_strdup(devname);
|
||||
dev->bid_cache = cache;
|
||||
list_add_tail(&dev->bid_devs, &cache->bic_devs);
|
||||
cache->bic_flags |= BLKID_BIC_FL_CHANGED;
|
||||
}
|
||||
|
||||
if (flags & BLKID_DEV_VERIFY)
|
||||
dev = blkid_verify(cache, dev);
|
||||
return dev;
|
||||
}
|
||||
|
||||
/*
|
||||
* Probe a single block device to add to the device cache.
|
||||
*/
|
||||
static void probe_one(blkid_cache cache, const char *ptname,
|
||||
dev_t devno, int pri)
|
||||
{
|
||||
blkid_dev dev = NULL;
|
||||
struct list_head *p;
|
||||
const char **dir;
|
||||
char *devname = NULL;
|
||||
|
||||
/* See if we already have this device number in the cache. */
|
||||
list_for_each(p, &cache->bic_devs) {
|
||||
blkid_dev tmp = list_entry(p, struct blkid_struct_dev,
|
||||
bid_devs);
|
||||
if (tmp->bid_devno == devno) {
|
||||
dev = blkid_verify(cache, tmp);
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (dev && dev->bid_devno == devno)
|
||||
goto set_pri;
|
||||
|
||||
/*
|
||||
* Take a quick look at /dev/ptname for the device number. We check
|
||||
* all of the likely device directories. If we don't find it, or if
|
||||
* the stat information doesn't check out, use blkid_devno_to_devname()
|
||||
* to find it via an exhaustive search for the device major/minor.
|
||||
*/
|
||||
for (dir = blkid_devdirs; *dir; dir++) {
|
||||
struct stat st;
|
||||
char device[256];
|
||||
|
||||
sprintf(device, "%s/%s", *dir, ptname);
|
||||
if ((dev = blkid_get_dev(cache, device, BLKID_DEV_FIND)) &&
|
||||
dev->bid_devno == devno)
|
||||
goto set_pri;
|
||||
|
||||
if (stat(device, &st) == 0 && S_ISBLK(st.st_mode) &&
|
||||
st.st_rdev == devno) {
|
||||
devname = blkid_strdup(device);
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!devname) {
|
||||
devname = blkid_devno_to_devname(devno);
|
||||
if (!devname)
|
||||
return;
|
||||
}
|
||||
dev = blkid_get_dev(cache, devname, BLKID_DEV_NORMAL);
|
||||
free(devname);
|
||||
|
||||
set_pri:
|
||||
if (!pri && !strncmp(ptname, "md", 2))
|
||||
pri = BLKID_PRI_MD;
|
||||
if (dev)
|
||||
dev->bid_pri = pri;
|
||||
return;
|
||||
}
|
||||
|
||||
#define PROC_PARTITIONS "/proc/partitions"
|
||||
#define VG_DIR "/proc/lvm/VGs"
|
||||
|
||||
/*
|
||||
* This function initializes the UUID cache with devices from the LVM
|
||||
* proc hierarchy. We currently depend on the names of the LVM
|
||||
* hierarchy giving us the device structure in /dev. (XXX is this a
|
||||
* safe thing to do?)
|
||||
*/
|
||||
#ifdef VG_DIR
|
||||
#include <dirent.h>
|
||||
static dev_t lvm_get_devno(const char *lvm_device)
|
||||
{
|
||||
FILE *lvf;
|
||||
char buf[1024];
|
||||
int ma, mi;
|
||||
dev_t ret = 0;
|
||||
|
||||
DBG(DEBUG_DEVNAME, printf("opening %s\n", lvm_device));
|
||||
if ((lvf = fopen(lvm_device, "r")) == NULL) {
|
||||
DBG(DEBUG_DEVNAME, printf("%s: (%d) %s\n", lvm_device, errno,
|
||||
strerror(errno)));
|
||||
return 0;
|
||||
}
|
||||
|
||||
while (fgets(buf, sizeof(buf), lvf)) {
|
||||
if (sscanf(buf, "device: %d:%d", &ma, &mi) == 2) {
|
||||
ret = makedev(ma, mi);
|
||||
break;
|
||||
}
|
||||
}
|
||||
fclose(lvf);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void lvm_probe_all(blkid_cache cache)
|
||||
{
|
||||
DIR *vg_list;
|
||||
struct dirent *vg_iter;
|
||||
int vg_len = strlen(VG_DIR);
|
||||
dev_t dev;
|
||||
|
||||
if ((vg_list = opendir(VG_DIR)) == NULL)
|
||||
return;
|
||||
|
||||
DBG(DEBUG_DEVNAME, printf("probing LVM devices under %s\n", VG_DIR));
|
||||
|
||||
while ((vg_iter = readdir(vg_list)) != NULL) {
|
||||
DIR *lv_list;
|
||||
char *vdirname;
|
||||
char *vg_name;
|
||||
struct dirent *lv_iter;
|
||||
|
||||
vg_name = vg_iter->d_name;
|
||||
if (LONE_CHAR(vg_name, '.') || !strcmp(vg_name, ".."))
|
||||
continue;
|
||||
vdirname = xmalloc(vg_len + strlen(vg_name) + 8);
|
||||
sprintf(vdirname, "%s/%s/LVs", VG_DIR, vg_name);
|
||||
|
||||
lv_list = opendir(vdirname);
|
||||
free(vdirname);
|
||||
if (lv_list == NULL)
|
||||
continue;
|
||||
|
||||
while ((lv_iter = readdir(lv_list)) != NULL) {
|
||||
char *lv_name, *lvm_device;
|
||||
|
||||
lv_name = lv_iter->d_name;
|
||||
if (LONE_CHAR(lv_name, '.') || !strcmp(lv_name, ".."))
|
||||
continue;
|
||||
|
||||
lvm_device = xmalloc(vg_len + strlen(vg_name) +
|
||||
strlen(lv_name) + 8);
|
||||
sprintf(lvm_device, "%s/%s/LVs/%s", VG_DIR, vg_name,
|
||||
lv_name);
|
||||
dev = lvm_get_devno(lvm_device);
|
||||
sprintf(lvm_device, "%s/%s", vg_name, lv_name);
|
||||
DBG(DEBUG_DEVNAME, printf("LVM dev %s: devno 0x%04X\n",
|
||||
lvm_device,
|
||||
(unsigned int) dev));
|
||||
probe_one(cache, lvm_device, dev, BLKID_PRI_LVM);
|
||||
free(lvm_device);
|
||||
}
|
||||
closedir(lv_list);
|
||||
}
|
||||
closedir(vg_list);
|
||||
}
|
||||
#endif
|
||||
|
||||
#define PROC_EVMS_VOLUMES "/proc/evms/volumes"
|
||||
|
||||
static int
|
||||
evms_probe_all(blkid_cache cache)
|
||||
{
|
||||
char line[100];
|
||||
int ma, mi, sz, num = 0;
|
||||
FILE *procpt;
|
||||
char device[110];
|
||||
|
||||
procpt = fopen(PROC_EVMS_VOLUMES, "r");
|
||||
if (!procpt)
|
||||
return 0;
|
||||
while (fgets(line, sizeof(line), procpt)) {
|
||||
if (sscanf (line, " %d %d %d %*s %*s %[^\n ]",
|
||||
&ma, &mi, &sz, device) != 4)
|
||||
continue;
|
||||
|
||||
DBG(DEBUG_DEVNAME, printf("Checking partition %s (%d, %d)\n",
|
||||
device, ma, mi));
|
||||
|
||||
probe_one(cache, device, makedev(ma, mi), BLKID_PRI_EVMS);
|
||||
num++;
|
||||
}
|
||||
fclose(procpt);
|
||||
return num;
|
||||
}
|
||||
|
||||
/*
|
||||
* Read the device data for all available block devices in the system.
|
||||
*/
|
||||
int blkid_probe_all(blkid_cache cache)
|
||||
{
|
||||
FILE *proc;
|
||||
char line[1024];
|
||||
char ptname0[128], ptname1[128], *ptname = 0;
|
||||
char *ptnames[2];
|
||||
dev_t devs[2];
|
||||
int ma, mi;
|
||||
unsigned long long sz;
|
||||
int lens[2] = { 0, 0 };
|
||||
int which = 0, last = 0;
|
||||
|
||||
ptnames[0] = ptname0;
|
||||
ptnames[1] = ptname1;
|
||||
|
||||
if (!cache)
|
||||
return -BLKID_ERR_PARAM;
|
||||
|
||||
if (cache->bic_flags & BLKID_BIC_FL_PROBED &&
|
||||
time(0) - cache->bic_time < BLKID_PROBE_INTERVAL)
|
||||
return 0;
|
||||
|
||||
blkid_read_cache(cache);
|
||||
evms_probe_all(cache);
|
||||
#ifdef VG_DIR
|
||||
lvm_probe_all(cache);
|
||||
#endif
|
||||
|
||||
proc = fopen(PROC_PARTITIONS, "r");
|
||||
if (!proc)
|
||||
return -BLKID_ERR_PROC;
|
||||
|
||||
while (fgets(line, sizeof(line), proc)) {
|
||||
last = which;
|
||||
which ^= 1;
|
||||
ptname = ptnames[which];
|
||||
|
||||
if (sscanf(line, " %d %d %llu %128[^\n ]",
|
||||
&ma, &mi, &sz, ptname) != 4)
|
||||
continue;
|
||||
devs[which] = makedev(ma, mi);
|
||||
|
||||
DBG(DEBUG_DEVNAME, printf("read partition name %s\n", ptname));
|
||||
|
||||
/* Skip whole disk devs unless they have no partitions
|
||||
* If we don't have a partition on this dev, also
|
||||
* check previous dev to see if it didn't have a partn.
|
||||
* heuristic: partition name ends in a digit.
|
||||
*
|
||||
* Skip extended partitions.
|
||||
* heuristic: size is 1
|
||||
*
|
||||
* FIXME: skip /dev/{ida,cciss,rd} whole-disk devs
|
||||
*/
|
||||
|
||||
lens[which] = strlen(ptname);
|
||||
if (isdigit(ptname[lens[which] - 1])) {
|
||||
DBG(DEBUG_DEVNAME,
|
||||
printf("partition dev %s, devno 0x%04X\n",
|
||||
ptname, (unsigned int) devs[which]));
|
||||
|
||||
if (sz > 1)
|
||||
probe_one(cache, ptname, devs[which], 0);
|
||||
lens[which] = 0;
|
||||
lens[last] = 0;
|
||||
} else if (lens[last] && strncmp(ptnames[last], ptname,
|
||||
lens[last])) {
|
||||
DBG(DEBUG_DEVNAME,
|
||||
printf("whole dev %s, devno 0x%04X\n",
|
||||
ptnames[last], (unsigned int) devs[last]));
|
||||
probe_one(cache, ptnames[last], devs[last], 0);
|
||||
lens[last] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/* Handle the last device if it wasn't partitioned */
|
||||
if (lens[which])
|
||||
probe_one(cache, ptname, devs[which], 0);
|
||||
|
||||
fclose(proc);
|
||||
|
||||
cache->bic_time = time(0);
|
||||
cache->bic_flags |= BLKID_BIC_FL_PROBED;
|
||||
blkid_flush_cache(cache);
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifdef TEST_PROGRAM
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
blkid_cache cache = NULL;
|
||||
int ret;
|
||||
|
||||
blkid_debug_mask = DEBUG_ALL;
|
||||
if (argc != 1) {
|
||||
fprintf(stderr, "Usage: %s\n"
|
||||
"Probe all devices and exit\n", argv[0]);
|
||||
exit(1);
|
||||
}
|
||||
if ((ret = blkid_get_cache(&cache, bb_dev_null)) != 0) {
|
||||
fprintf(stderr, "%s: error creating cache (%d)\n",
|
||||
argv[0], ret);
|
||||
exit(1);
|
||||
}
|
||||
if (blkid_probe_all(cache) < 0)
|
||||
printf("%s: error probing devices\n", argv[0]);
|
||||
|
||||
blkid_put_cache(cache);
|
||||
return 0;
|
||||
}
|
||||
#endif
|
223
e2fsprogs/old_e2fsprogs/blkid/devno.c
Normal file
223
e2fsprogs/old_e2fsprogs/blkid/devno.c
Normal file
@ -0,0 +1,223 @@
|
||||
/* vi: set sw=4 ts=4: */
|
||||
/*
|
||||
* devno.c - find a particular device by its device number (major/minor)
|
||||
*
|
||||
* Copyright (C) 2000, 2001, 2003 Theodore Ts'o
|
||||
* Copyright (C) 2001 Andreas Dilger
|
||||
*
|
||||
* %Begin-Header%
|
||||
* This file may be redistributed under the terms of the
|
||||
* GNU Lesser General Public License.
|
||||
* %End-Header%
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#ifdef HAVE_UNISTD_H
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#ifdef HAVE_SYS_TYPES_H
|
||||
#include <sys/types.h>
|
||||
#endif
|
||||
#include <sys/stat.h>
|
||||
#include <dirent.h>
|
||||
#ifdef HAVE_ERRNO_H
|
||||
#include <errno.h>
|
||||
#endif
|
||||
#ifdef HAVE_SYS_MKDEV_H
|
||||
#include <sys/mkdev.h>
|
||||
#endif
|
||||
|
||||
#include "blkidP.h"
|
||||
|
||||
struct dir_list {
|
||||
char *name;
|
||||
struct dir_list *next;
|
||||
};
|
||||
|
||||
char *blkid_strndup(const char *s, int length)
|
||||
{
|
||||
char *ret;
|
||||
|
||||
if (!s)
|
||||
return NULL;
|
||||
|
||||
if (!length)
|
||||
length = strlen(s);
|
||||
|
||||
ret = xmalloc(length + 1);
|
||||
strncpy(ret, s, length);
|
||||
ret[length] = '\0';
|
||||
return ret;
|
||||
}
|
||||
|
||||
char *blkid_strdup(const char *s)
|
||||
{
|
||||
return blkid_strndup(s, 0);
|
||||
}
|
||||
|
||||
/*
|
||||
* This function adds an entry to the directory list
|
||||
*/
|
||||
static void add_to_dirlist(const char *name, struct dir_list **list)
|
||||
{
|
||||
struct dir_list *dp;
|
||||
|
||||
dp = xmalloc(sizeof(struct dir_list));
|
||||
dp->name = blkid_strdup(name);
|
||||
dp->next = *list;
|
||||
*list = dp;
|
||||
}
|
||||
|
||||
/*
|
||||
* This function frees a directory list
|
||||
*/
|
||||
static void free_dirlist(struct dir_list **list)
|
||||
{
|
||||
struct dir_list *dp, *next;
|
||||
|
||||
for (dp = *list; dp; dp = next) {
|
||||
next = dp->next;
|
||||
free(dp->name);
|
||||
free(dp);
|
||||
}
|
||||
*list = NULL;
|
||||
}
|
||||
|
||||
static void scan_dir(char *dir_name, dev_t devno, struct dir_list **list,
|
||||
char **devname)
|
||||
{
|
||||
DIR *dir;
|
||||
struct dirent *dp;
|
||||
char path[1024];
|
||||
int dirlen;
|
||||
struct stat st;
|
||||
|
||||
if ((dir = opendir(dir_name)) == NULL)
|
||||
return;
|
||||
dirlen = strlen(dir_name) + 2;
|
||||
while ((dp = readdir(dir)) != 0) {
|
||||
if (dirlen + strlen(dp->d_name) >= sizeof(path))
|
||||
continue;
|
||||
|
||||
if (dp->d_name[0] == '.' &&
|
||||
((dp->d_name[1] == 0) ||
|
||||
((dp->d_name[1] == '.') && (dp->d_name[2] == 0))))
|
||||
continue;
|
||||
|
||||
sprintf(path, "%s/%s", dir_name, dp->d_name);
|
||||
if (stat(path, &st) < 0)
|
||||
continue;
|
||||
|
||||
if (S_ISDIR(st.st_mode))
|
||||
add_to_dirlist(path, list);
|
||||
else if (S_ISBLK(st.st_mode) && st.st_rdev == devno) {
|
||||
*devname = blkid_strdup(path);
|
||||
DBG(DEBUG_DEVNO,
|
||||
printf("found 0x%llx at %s (%p)\n", devno,
|
||||
path, *devname));
|
||||
break;
|
||||
}
|
||||
}
|
||||
closedir(dir);
|
||||
return;
|
||||
}
|
||||
|
||||
/* Directories where we will try to search for device numbers */
|
||||
const char *blkid_devdirs[] = { "/devices", "/devfs", "/dev", NULL };
|
||||
|
||||
/*
|
||||
* This function finds the pathname to a block device with a given
|
||||
* device number. It returns a pointer to allocated memory to the
|
||||
* pathname on success, and NULL on failure.
|
||||
*/
|
||||
char *blkid_devno_to_devname(dev_t devno)
|
||||
{
|
||||
struct dir_list *list = NULL, *new_list = NULL;
|
||||
char *devname = NULL;
|
||||
const char **dir;
|
||||
|
||||
/*
|
||||
* Add the starting directories to search in reverse order of
|
||||
* importance, since we are using a stack...
|
||||
*/
|
||||
for (dir = blkid_devdirs; *dir; dir++)
|
||||
add_to_dirlist(*dir, &list);
|
||||
|
||||
while (list) {
|
||||
struct dir_list *current = list;
|
||||
|
||||
list = list->next;
|
||||
DBG(DEBUG_DEVNO, printf("directory %s\n", current->name));
|
||||
scan_dir(current->name, devno, &new_list, &devname);
|
||||
free(current->name);
|
||||
free(current);
|
||||
if (devname)
|
||||
break;
|
||||
/*
|
||||
* If we're done checking at this level, descend to
|
||||
* the next level of subdirectories. (breadth-first)
|
||||
*/
|
||||
if (list == NULL) {
|
||||
list = new_list;
|
||||
new_list = NULL;
|
||||
}
|
||||
}
|
||||
free_dirlist(&list);
|
||||
free_dirlist(&new_list);
|
||||
|
||||
if (!devname) {
|
||||
DBG(DEBUG_DEVNO,
|
||||
printf("blkid: cannot find devno 0x%04lx\n",
|
||||
(unsigned long) devno));
|
||||
} else {
|
||||
DBG(DEBUG_DEVNO,
|
||||
printf("found devno 0x%04llx as %s\n", devno, devname));
|
||||
}
|
||||
|
||||
|
||||
return devname;
|
||||
}
|
||||
|
||||
#ifdef TEST_PROGRAM
|
||||
int main(int argc, char** argv)
|
||||
{
|
||||
char *devname, *tmp;
|
||||
int major, minor;
|
||||
dev_t devno;
|
||||
const char *errmsg = "Cannot parse %s: %s\n";
|
||||
|
||||
blkid_debug_mask = DEBUG_ALL;
|
||||
if ((argc != 2) && (argc != 3)) {
|
||||
fprintf(stderr, "Usage:\t%s device_number\n\t%s major minor\n"
|
||||
"Resolve a device number to a device name\n",
|
||||
argv[0], argv[0]);
|
||||
exit(1);
|
||||
}
|
||||
if (argc == 2) {
|
||||
devno = strtoul(argv[1], &tmp, 0);
|
||||
if (*tmp) {
|
||||
fprintf(stderr, errmsg, "device number", argv[1]);
|
||||
exit(1);
|
||||
}
|
||||
} else {
|
||||
major = strtoul(argv[1], &tmp, 0);
|
||||
if (*tmp) {
|
||||
fprintf(stderr, errmsg, "major number", argv[1]);
|
||||
exit(1);
|
||||
}
|
||||
minor = strtoul(argv[2], &tmp, 0);
|
||||
if (*tmp) {
|
||||
fprintf(stderr, errmsg, "minor number", argv[2]);
|
||||
exit(1);
|
||||
}
|
||||
devno = makedev(major, minor);
|
||||
}
|
||||
printf("Looking for device 0x%04Lx\n", devno);
|
||||
devname = blkid_devno_to_devname(devno);
|
||||
free(devname);
|
||||
return 0;
|
||||
}
|
||||
#endif
|
110
e2fsprogs/old_e2fsprogs/blkid/list.c
Normal file
110
e2fsprogs/old_e2fsprogs/blkid/list.c
Normal file
@ -0,0 +1,110 @@
|
||||
/* vi: set sw=4 ts=4: */
|
||||
|
||||
#include "list.h"
|
||||
|
||||
/*
|
||||
* Insert a new entry between two known consecutive entries.
|
||||
*
|
||||
* This is only for internal list manipulation where we know
|
||||
* the prev/next entries already!
|
||||
*/
|
||||
void __list_add(struct list_head * add,
|
||||
struct list_head * prev,
|
||||
struct list_head * next)
|
||||
{
|
||||
next->prev = add;
|
||||
add->next = next;
|
||||
add->prev = prev;
|
||||
prev->next = add;
|
||||
}
|
||||
|
||||
/*
|
||||
* list_add - add a new entry
|
||||
* @add: new entry to be added
|
||||
* @head: list head to add it after
|
||||
*
|
||||
* Insert a new entry after the specified head.
|
||||
* This is good for implementing stacks.
|
||||
*/
|
||||
void list_add(struct list_head *add, struct list_head *head)
|
||||
{
|
||||
__list_add(add, head, head->next);
|
||||
}
|
||||
|
||||
/*
|
||||
* list_add_tail - add a new entry
|
||||
* @add: new entry to be added
|
||||
* @head: list head to add it before
|
||||
*
|
||||
* Insert a new entry before the specified head.
|
||||
* This is useful for implementing queues.
|
||||
*/
|
||||
void list_add_tail(struct list_head *add, struct list_head *head)
|
||||
{
|
||||
__list_add(add, head->prev, head);
|
||||
}
|
||||
|
||||
/*
|
||||
* Delete a list entry by making the prev/next entries
|
||||
* point to each other.
|
||||
*
|
||||
* This is only for internal list manipulation where we know
|
||||
* the prev/next entries already!
|
||||
*/
|
||||
void __list_del(struct list_head * prev, struct list_head * next)
|
||||
{
|
||||
next->prev = prev;
|
||||
prev->next = next;
|
||||
}
|
||||
|
||||
/*
|
||||
* list_del - deletes entry from list.
|
||||
* @entry: the element to delete from the list.
|
||||
*
|
||||
* list_empty() on @entry does not return true after this, @entry is
|
||||
* in an undefined state.
|
||||
*/
|
||||
void list_del(struct list_head *entry)
|
||||
{
|
||||
__list_del(entry->prev, entry->next);
|
||||
}
|
||||
|
||||
/*
|
||||
* list_del_init - deletes entry from list and reinitialize it.
|
||||
* @entry: the element to delete from the list.
|
||||
*/
|
||||
void list_del_init(struct list_head *entry)
|
||||
{
|
||||
__list_del(entry->prev, entry->next);
|
||||
INIT_LIST_HEAD(entry);
|
||||
}
|
||||
|
||||
/*
|
||||
* list_empty - tests whether a list is empty
|
||||
* @head: the list to test.
|
||||
*/
|
||||
int list_empty(struct list_head *head)
|
||||
{
|
||||
return head->next == head;
|
||||
}
|
||||
|
||||
/*
|
||||
* list_splice - join two lists
|
||||
* @list: the new list to add.
|
||||
* @head: the place to add it in the first list.
|
||||
*/
|
||||
void list_splice(struct list_head *list, struct list_head *head)
|
||||
{
|
||||
struct list_head *first = list->next;
|
||||
|
||||
if (first != list) {
|
||||
struct list_head *last = list->prev;
|
||||
struct list_head *at = head->next;
|
||||
|
||||
first->prev = head;
|
||||
head->next = first;
|
||||
|
||||
last->next = at;
|
||||
at->prev = last;
|
||||
}
|
||||
}
|
73
e2fsprogs/old_e2fsprogs/blkid/list.h
Normal file
73
e2fsprogs/old_e2fsprogs/blkid/list.h
Normal file
@ -0,0 +1,73 @@
|
||||
/* vi: set sw=4 ts=4: */
|
||||
#if !defined(_BLKID_LIST_H) && !defined(LIST_HEAD)
|
||||
#define _BLKID_LIST_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Simple doubly linked list implementation.
|
||||
*
|
||||
* Some of the internal functions ("__xxx") are useful when
|
||||
* manipulating whole lists rather than single entries, as
|
||||
* sometimes we already know the next/prev entries and we can
|
||||
* generate better code by using them directly rather than
|
||||
* using the generic single-entry routines.
|
||||
*/
|
||||
|
||||
struct list_head {
|
||||
struct list_head *next, *prev;
|
||||
};
|
||||
|
||||
#define LIST_HEAD_INIT(name) { &(name), &(name) }
|
||||
|
||||
#define LIST_HEAD(name) \
|
||||
struct list_head name = LIST_HEAD_INIT(name)
|
||||
|
||||
#define INIT_LIST_HEAD(ptr) do { \
|
||||
(ptr)->next = (ptr); (ptr)->prev = (ptr); \
|
||||
} while (0)
|
||||
|
||||
void __list_add(struct list_head * add, struct list_head * prev, struct list_head * next);
|
||||
void list_add(struct list_head *add, struct list_head *head);
|
||||
void list_add_tail(struct list_head *add, struct list_head *head);
|
||||
void __list_del(struct list_head * prev, struct list_head * next);
|
||||
void list_del(struct list_head *entry);
|
||||
void list_del_init(struct list_head *entry);
|
||||
int list_empty(struct list_head *head);
|
||||
void list_splice(struct list_head *list, struct list_head *head);
|
||||
|
||||
/**
|
||||
* list_entry - get the struct for this entry
|
||||
* @ptr: the &struct list_head pointer.
|
||||
* @type: the type of the struct this is embedded in.
|
||||
* @member: the name of the list_struct within the struct.
|
||||
*/
|
||||
#define list_entry(ptr, type, member) \
|
||||
((type *)((char *)(ptr)-(unsigned long)(&((type *)0)->member)))
|
||||
|
||||
/**
|
||||
* list_for_each - iterate over elements in a list
|
||||
* @pos: the &struct list_head to use as a loop counter.
|
||||
* @head: the head for your list.
|
||||
*/
|
||||
#define list_for_each(pos, head) \
|
||||
for (pos = (head)->next; pos != (head); pos = pos->next)
|
||||
|
||||
/**
|
||||
* list_for_each_safe - iterate over elements in a list, but don't dereference
|
||||
* pos after the body is done (in case it is freed)
|
||||
* @pos: the &struct list_head to use as a loop counter.
|
||||
* @pnext: the &struct list_head to use as a pointer to the next item.
|
||||
* @head: the head for your list (not included in iteration).
|
||||
*/
|
||||
#define list_for_each_safe(pos, pnext, head) \
|
||||
for (pos = (head)->next, pnext = pos->next; pos != (head); \
|
||||
pos = pnext, pnext = pos->next)
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* _BLKID_LIST_H */
|
721
e2fsprogs/old_e2fsprogs/blkid/probe.c
Normal file
721
e2fsprogs/old_e2fsprogs/blkid/probe.c
Normal file
@ -0,0 +1,721 @@
|
||||
/* vi: set sw=4 ts=4: */
|
||||
/*
|
||||
* probe.c - identify a block device by its contents, and return a dev
|
||||
* struct with the details
|
||||
*
|
||||
* Copyright (C) 1999 by Andries Brouwer
|
||||
* Copyright (C) 1999, 2000, 2003 by Theodore Ts'o
|
||||
* Copyright (C) 2001 by Andreas Dilger
|
||||
*
|
||||
* %Begin-Header%
|
||||
* This file may be redistributed under the terms of the
|
||||
* GNU Lesser General Public License.
|
||||
* %End-Header%
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
#include <sys/types.h>
|
||||
#ifdef HAVE_SYS_STAT_H
|
||||
#include <sys/stat.h>
|
||||
#endif
|
||||
#ifdef HAVE_SYS_MKDEV_H
|
||||
#include <sys/mkdev.h>
|
||||
#endif
|
||||
#ifdef HAVE_ERRNO_H
|
||||
#include <errno.h>
|
||||
#endif
|
||||
#include "blkidP.h"
|
||||
#include "../uuid/uuid.h"
|
||||
#include "probe.h"
|
||||
|
||||
/*
|
||||
* This is a special case code to check for an MDRAID device. We do
|
||||
* this special since it requires checking for a superblock at the end
|
||||
* of the device.
|
||||
*/
|
||||
static int check_mdraid(int fd, unsigned char *ret_uuid)
|
||||
{
|
||||
struct mdp_superblock_s *md;
|
||||
blkid_loff_t offset;
|
||||
char buf[4096];
|
||||
|
||||
if (fd < 0)
|
||||
return -BLKID_ERR_PARAM;
|
||||
|
||||
offset = (blkid_get_dev_size(fd) & ~((blkid_loff_t)65535)) - 65536;
|
||||
|
||||
if (blkid_llseek(fd, offset, 0) < 0 ||
|
||||
read(fd, buf, 4096) != 4096)
|
||||
return -BLKID_ERR_IO;
|
||||
|
||||
/* Check for magic number */
|
||||
if (memcmp("\251+N\374", buf, 4))
|
||||
return -BLKID_ERR_PARAM;
|
||||
|
||||
if (!ret_uuid)
|
||||
return 0;
|
||||
*ret_uuid = 0;
|
||||
|
||||
/* The MD UUID is not contiguous in the superblock, make it so */
|
||||
md = (struct mdp_superblock_s *)buf;
|
||||
if (md->set_uuid0 || md->set_uuid1 || md->set_uuid2 || md->set_uuid3) {
|
||||
memcpy(ret_uuid, &md->set_uuid0, 4);
|
||||
memcpy(ret_uuid, &md->set_uuid1, 12);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void set_uuid(blkid_dev dev, uuid_t uuid)
|
||||
{
|
||||
char str[37];
|
||||
|
||||
if (!uuid_is_null(uuid)) {
|
||||
uuid_unparse(uuid, str);
|
||||
blkid_set_tag(dev, "UUID", str, sizeof(str));
|
||||
}
|
||||
}
|
||||
|
||||
static void get_ext2_info(blkid_dev dev, unsigned char *buf)
|
||||
{
|
||||
struct ext2_super_block *es = (struct ext2_super_block *) buf;
|
||||
const char *label = 0;
|
||||
|
||||
DBG(DEBUG_PROBE, printf("ext2_sb.compat = %08X:%08X:%08X\n",
|
||||
blkid_le32(es->s_feature_compat),
|
||||
blkid_le32(es->s_feature_incompat),
|
||||
blkid_le32(es->s_feature_ro_compat)));
|
||||
|
||||
if (strlen(es->s_volume_name))
|
||||
label = es->s_volume_name;
|
||||
blkid_set_tag(dev, "LABEL", label, sizeof(es->s_volume_name));
|
||||
|
||||
set_uuid(dev, es->s_uuid);
|
||||
}
|
||||
|
||||
static int probe_ext3(int fd __BLKID_ATTR((unused)),
|
||||
blkid_cache cache __BLKID_ATTR((unused)),
|
||||
blkid_dev dev,
|
||||
const struct blkid_magic *id __BLKID_ATTR((unused)),
|
||||
unsigned char *buf)
|
||||
{
|
||||
struct ext2_super_block *es;
|
||||
|
||||
es = (struct ext2_super_block *)buf;
|
||||
|
||||
/* Distinguish between jbd and ext2/3 fs */
|
||||
if (blkid_le32(es->s_feature_incompat) &
|
||||
EXT3_FEATURE_INCOMPAT_JOURNAL_DEV)
|
||||
return -BLKID_ERR_PARAM;
|
||||
|
||||
/* Distinguish between ext3 and ext2 */
|
||||
if (!(blkid_le32(es->s_feature_compat) &
|
||||
EXT3_FEATURE_COMPAT_HAS_JOURNAL))
|
||||
return -BLKID_ERR_PARAM;
|
||||
|
||||
get_ext2_info(dev, buf);
|
||||
|
||||
blkid_set_tag(dev, "SEC_TYPE", "ext2", sizeof("ext2"));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int probe_ext2(int fd __BLKID_ATTR((unused)),
|
||||
blkid_cache cache __BLKID_ATTR((unused)),
|
||||
blkid_dev dev,
|
||||
const struct blkid_magic *id __BLKID_ATTR((unused)),
|
||||
unsigned char *buf)
|
||||
{
|
||||
struct ext2_super_block *es;
|
||||
|
||||
es = (struct ext2_super_block *)buf;
|
||||
|
||||
/* Distinguish between jbd and ext2/3 fs */
|
||||
if (blkid_le32(es->s_feature_incompat) &
|
||||
EXT3_FEATURE_INCOMPAT_JOURNAL_DEV)
|
||||
return -BLKID_ERR_PARAM;
|
||||
|
||||
get_ext2_info(dev, buf);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int probe_jbd(int fd __BLKID_ATTR((unused)),
|
||||
blkid_cache cache __BLKID_ATTR((unused)),
|
||||
blkid_dev dev,
|
||||
const struct blkid_magic *id __BLKID_ATTR((unused)),
|
||||
unsigned char *buf)
|
||||
{
|
||||
struct ext2_super_block *es = (struct ext2_super_block *) buf;
|
||||
|
||||
if (!(blkid_le32(es->s_feature_incompat) &
|
||||
EXT3_FEATURE_INCOMPAT_JOURNAL_DEV))
|
||||
return -BLKID_ERR_PARAM;
|
||||
|
||||
get_ext2_info(dev, buf);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int probe_vfat(int fd __BLKID_ATTR((unused)),
|
||||
blkid_cache cache __BLKID_ATTR((unused)),
|
||||
blkid_dev dev,
|
||||
const struct blkid_magic *id __BLKID_ATTR((unused)),
|
||||
unsigned char *buf)
|
||||
{
|
||||
struct vfat_super_block *vs;
|
||||
char serno[10];
|
||||
const char *label = 0;
|
||||
int label_len = 0;
|
||||
|
||||
vs = (struct vfat_super_block *)buf;
|
||||
|
||||
if (strncmp(vs->vs_label, "NO NAME", 7)) {
|
||||
char *end = vs->vs_label + sizeof(vs->vs_label) - 1;
|
||||
|
||||
while (*end == ' ' && end >= vs->vs_label)
|
||||
--end;
|
||||
if (end >= vs->vs_label) {
|
||||
label = vs->vs_label;
|
||||
label_len = end - vs->vs_label + 1;
|
||||
}
|
||||
}
|
||||
|
||||
/* We can't just print them as %04X, because they are unaligned */
|
||||
sprintf(serno, "%02X%02X-%02X%02X", vs->vs_serno[3], vs->vs_serno[2],
|
||||
vs->vs_serno[1], vs->vs_serno[0]);
|
||||
blkid_set_tag(dev, "LABEL", label, label_len);
|
||||
blkid_set_tag(dev, "UUID", serno, sizeof(serno));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int probe_msdos(int fd __BLKID_ATTR((unused)),
|
||||
blkid_cache cache __BLKID_ATTR((unused)),
|
||||
blkid_dev dev,
|
||||
const struct blkid_magic *id __BLKID_ATTR((unused)),
|
||||
unsigned char *buf)
|
||||
{
|
||||
struct msdos_super_block *ms = (struct msdos_super_block *) buf;
|
||||
char serno[10];
|
||||
const char *label = 0;
|
||||
int label_len = 0;
|
||||
|
||||
if (strncmp(ms->ms_label, "NO NAME", 7)) {
|
||||
char *end = ms->ms_label + sizeof(ms->ms_label) - 1;
|
||||
|
||||
while (*end == ' ' && end >= ms->ms_label)
|
||||
--end;
|
||||
if (end >= ms->ms_label) {
|
||||
label = ms->ms_label;
|
||||
label_len = end - ms->ms_label + 1;
|
||||
}
|
||||
}
|
||||
|
||||
/* We can't just print them as %04X, because they are unaligned */
|
||||
sprintf(serno, "%02X%02X-%02X%02X", ms->ms_serno[3], ms->ms_serno[2],
|
||||
ms->ms_serno[1], ms->ms_serno[0]);
|
||||
blkid_set_tag(dev, "UUID", serno, 0);
|
||||
blkid_set_tag(dev, "LABEL", label, label_len);
|
||||
blkid_set_tag(dev, "SEC_TYPE", "msdos", sizeof("msdos"));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int probe_xfs(int fd __BLKID_ATTR((unused)),
|
||||
blkid_cache cache __BLKID_ATTR((unused)),
|
||||
blkid_dev dev,
|
||||
const struct blkid_magic *id __BLKID_ATTR((unused)),
|
||||
unsigned char *buf)
|
||||
{
|
||||
struct xfs_super_block *xs;
|
||||
const char *label = 0;
|
||||
|
||||
xs = (struct xfs_super_block *)buf;
|
||||
|
||||
if (strlen(xs->xs_fname))
|
||||
label = xs->xs_fname;
|
||||
blkid_set_tag(dev, "LABEL", label, sizeof(xs->xs_fname));
|
||||
set_uuid(dev, xs->xs_uuid);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int probe_reiserfs(int fd __BLKID_ATTR((unused)),
|
||||
blkid_cache cache __BLKID_ATTR((unused)),
|
||||
blkid_dev dev,
|
||||
const struct blkid_magic *id, unsigned char *buf)
|
||||
{
|
||||
struct reiserfs_super_block *rs = (struct reiserfs_super_block *) buf;
|
||||
unsigned int blocksize;
|
||||
const char *label = 0;
|
||||
|
||||
blocksize = blkid_le16(rs->rs_blocksize);
|
||||
|
||||
/* If the superblock is inside the journal, we have the wrong one */
|
||||
if (id->bim_kboff/(blocksize>>10) > blkid_le32(rs->rs_journal_block))
|
||||
return -BLKID_ERR_BIG;
|
||||
|
||||
/* LABEL/UUID are only valid for later versions of Reiserfs v3.6. */
|
||||
if (!strcmp(id->bim_magic, "ReIsEr2Fs") ||
|
||||
!strcmp(id->bim_magic, "ReIsEr3Fs")) {
|
||||
if (strlen(rs->rs_label))
|
||||
label = rs->rs_label;
|
||||
set_uuid(dev, rs->rs_uuid);
|
||||
}
|
||||
blkid_set_tag(dev, "LABEL", label, sizeof(rs->rs_label));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int probe_jfs(int fd __BLKID_ATTR((unused)),
|
||||
blkid_cache cache __BLKID_ATTR((unused)),
|
||||
blkid_dev dev,
|
||||
const struct blkid_magic *id __BLKID_ATTR((unused)),
|
||||
unsigned char *buf)
|
||||
{
|
||||
struct jfs_super_block *js;
|
||||
const char *label = 0;
|
||||
|
||||
js = (struct jfs_super_block *)buf;
|
||||
|
||||
if (strlen((char *) js->js_label))
|
||||
label = (char *) js->js_label;
|
||||
blkid_set_tag(dev, "LABEL", label, sizeof(js->js_label));
|
||||
set_uuid(dev, js->js_uuid);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int probe_romfs(int fd __BLKID_ATTR((unused)),
|
||||
blkid_cache cache __BLKID_ATTR((unused)),
|
||||
blkid_dev dev,
|
||||
const struct blkid_magic *id __BLKID_ATTR((unused)),
|
||||
unsigned char *buf)
|
||||
{
|
||||
struct romfs_super_block *ros;
|
||||
const char *label = 0;
|
||||
|
||||
ros = (struct romfs_super_block *)buf;
|
||||
|
||||
if (strlen((char *) ros->ros_volume))
|
||||
label = (char *) ros->ros_volume;
|
||||
blkid_set_tag(dev, "LABEL", label, 0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int probe_cramfs(int fd __BLKID_ATTR((unused)),
|
||||
blkid_cache cache __BLKID_ATTR((unused)),
|
||||
blkid_dev dev,
|
||||
const struct blkid_magic *id __BLKID_ATTR((unused)),
|
||||
unsigned char *buf)
|
||||
{
|
||||
struct cramfs_super_block *csb;
|
||||
const char *label = 0;
|
||||
|
||||
csb = (struct cramfs_super_block *)buf;
|
||||
|
||||
if (strlen((char *) csb->name))
|
||||
label = (char *) csb->name;
|
||||
blkid_set_tag(dev, "LABEL", label, 0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int probe_swap0(int fd __BLKID_ATTR((unused)),
|
||||
blkid_cache cache __BLKID_ATTR((unused)),
|
||||
blkid_dev dev,
|
||||
const struct blkid_magic *id __BLKID_ATTR((unused)),
|
||||
unsigned char *buf __BLKID_ATTR((unused)))
|
||||
{
|
||||
blkid_set_tag(dev, "UUID", 0, 0);
|
||||
blkid_set_tag(dev, "LABEL", 0, 0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int probe_swap1(int fd,
|
||||
blkid_cache cache __BLKID_ATTR((unused)),
|
||||
blkid_dev dev,
|
||||
const struct blkid_magic *id __BLKID_ATTR((unused)),
|
||||
unsigned char *buf __BLKID_ATTR((unused)))
|
||||
{
|
||||
struct swap_id_block *sws;
|
||||
|
||||
probe_swap0(fd, cache, dev, id, buf);
|
||||
/*
|
||||
* Version 1 swap headers are always located at offset of 1024
|
||||
* bytes, although the swap signature itself is located at the
|
||||
* end of the page (which may vary depending on hardware
|
||||
* pagesize).
|
||||
*/
|
||||
if (lseek(fd, 1024, SEEK_SET) < 0) return 1;
|
||||
sws = xmalloc(1024);
|
||||
if (read(fd, sws, 1024) != 1024) {
|
||||
free(sws);
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* arbitrary sanity check.. is there any garbage down there? */
|
||||
if (sws->sws_pad[32] == 0 && sws->sws_pad[33] == 0) {
|
||||
if (sws->sws_volume[0])
|
||||
blkid_set_tag(dev, "LABEL", (const char*)sws->sws_volume,
|
||||
sizeof(sws->sws_volume));
|
||||
if (sws->sws_uuid[0])
|
||||
set_uuid(dev, sws->sws_uuid);
|
||||
}
|
||||
free(sws);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const char
|
||||
* const udf_magic[] = { "BEA01", "BOOT2", "CD001", "CDW02", "NSR02",
|
||||
"NSR03", "TEA01", 0 };
|
||||
|
||||
static int probe_udf(int fd, blkid_cache cache __BLKID_ATTR((unused)),
|
||||
blkid_dev dev __BLKID_ATTR((unused)),
|
||||
const struct blkid_magic *id __BLKID_ATTR((unused)),
|
||||
unsigned char *buf __BLKID_ATTR((unused)))
|
||||
{
|
||||
int j, bs;
|
||||
struct iso_volume_descriptor isosb;
|
||||
const char * const * m;
|
||||
|
||||
/* determine the block size by scanning in 2K increments
|
||||
(block sizes larger than 2K will be null padded) */
|
||||
for (bs = 1; bs < 16; bs++) {
|
||||
lseek(fd, bs*2048+32768, SEEK_SET);
|
||||
if (read(fd, (char *)&isosb, sizeof(isosb)) != sizeof(isosb))
|
||||
return 1;
|
||||
if (isosb.id[0])
|
||||
break;
|
||||
}
|
||||
|
||||
/* Scan up to another 64 blocks looking for additional VSD's */
|
||||
for (j = 1; j < 64; j++) {
|
||||
if (j > 1) {
|
||||
lseek(fd, j*bs*2048+32768, SEEK_SET);
|
||||
if (read(fd, (char *)&isosb, sizeof(isosb))
|
||||
!= sizeof(isosb))
|
||||
return 1;
|
||||
}
|
||||
/* If we find NSR0x then call it udf:
|
||||
NSR01 for UDF 1.00
|
||||
NSR02 for UDF 1.50
|
||||
NSR03 for UDF 2.00 */
|
||||
if (!strncmp(isosb.id, "NSR0", 4))
|
||||
return 0;
|
||||
for (m = udf_magic; *m; m++)
|
||||
if (!strncmp(*m, isosb.id, 5))
|
||||
break;
|
||||
if (*m == 0)
|
||||
return 1;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int probe_ocfs(int fd __BLKID_ATTR((unused)),
|
||||
blkid_cache cache __BLKID_ATTR((unused)),
|
||||
blkid_dev dev,
|
||||
const struct blkid_magic *id __BLKID_ATTR((unused)),
|
||||
unsigned char *buf)
|
||||
{
|
||||
struct ocfs_volume_header ovh;
|
||||
struct ocfs_volume_label ovl;
|
||||
__u32 major;
|
||||
|
||||
memcpy(&ovh, buf, sizeof(ovh));
|
||||
memcpy(&ovl, buf+512, sizeof(ovl));
|
||||
|
||||
major = ocfsmajor(ovh);
|
||||
if (major == 1)
|
||||
blkid_set_tag(dev,"SEC_TYPE","ocfs1",sizeof("ocfs1"));
|
||||
else if (major >= 9)
|
||||
blkid_set_tag(dev,"SEC_TYPE","ntocfs",sizeof("ntocfs"));
|
||||
|
||||
blkid_set_tag(dev, "LABEL", (const char*)ovl.label, ocfslabellen(ovl));
|
||||
blkid_set_tag(dev, "MOUNT", (const char*)ovh.mount, ocfsmountlen(ovh));
|
||||
set_uuid(dev, ovl.vol_id);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int probe_ocfs2(int fd __BLKID_ATTR((unused)),
|
||||
blkid_cache cache __BLKID_ATTR((unused)),
|
||||
blkid_dev dev,
|
||||
const struct blkid_magic *id __BLKID_ATTR((unused)),
|
||||
unsigned char *buf)
|
||||
{
|
||||
struct ocfs2_super_block *osb;
|
||||
|
||||
osb = (struct ocfs2_super_block *)buf;
|
||||
|
||||
blkid_set_tag(dev, "LABEL", (const char*)osb->s_label, sizeof(osb->s_label));
|
||||
set_uuid(dev, osb->s_uuid);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int probe_oracleasm(int fd __BLKID_ATTR((unused)),
|
||||
blkid_cache cache __BLKID_ATTR((unused)),
|
||||
blkid_dev dev,
|
||||
const struct blkid_magic *id __BLKID_ATTR((unused)),
|
||||
unsigned char *buf)
|
||||
{
|
||||
struct oracle_asm_disk_label *dl;
|
||||
|
||||
dl = (struct oracle_asm_disk_label *)buf;
|
||||
|
||||
blkid_set_tag(dev, "LABEL", dl->dl_id, sizeof(dl->dl_id));
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* BLKID_BLK_OFFS is at least as large as the highest bim_kboff defined
|
||||
* in the type_array table below + bim_kbalign.
|
||||
*
|
||||
* When probing for a lot of magics, we handle everything in 1kB buffers so
|
||||
* that we don't have to worry about reading each combination of block sizes.
|
||||
*/
|
||||
#define BLKID_BLK_OFFS 64 /* currently reiserfs */
|
||||
|
||||
/*
|
||||
* Various filesystem magics that we can check for. Note that kboff and
|
||||
* sboff are in kilobytes and bytes respectively. All magics are in
|
||||
* byte strings so we don't worry about endian issues.
|
||||
*/
|
||||
static const struct blkid_magic type_array[] = {
|
||||
/* type kboff sboff len magic probe */
|
||||
{ "oracleasm", 0, 32, 8, "ORCLDISK", probe_oracleasm },
|
||||
{ "ntfs", 0, 3, 8, "NTFS ", 0 },
|
||||
{ "jbd", 1, 0x38, 2, "\123\357", probe_jbd },
|
||||
{ "ext3", 1, 0x38, 2, "\123\357", probe_ext3 },
|
||||
{ "ext2", 1, 0x38, 2, "\123\357", probe_ext2 },
|
||||
{ "reiserfs", 8, 0x34, 8, "ReIsErFs", probe_reiserfs },
|
||||
{ "reiserfs", 64, 0x34, 9, "ReIsEr2Fs", probe_reiserfs },
|
||||
{ "reiserfs", 64, 0x34, 9, "ReIsEr3Fs", probe_reiserfs },
|
||||
{ "reiserfs", 64, 0x34, 8, "ReIsErFs", probe_reiserfs },
|
||||
{ "reiserfs", 8, 20, 8, "ReIsErFs", probe_reiserfs },
|
||||
{ "vfat", 0, 0x52, 5, "MSWIN", probe_vfat },
|
||||
{ "vfat", 0, 0x52, 8, "FAT32 ", probe_vfat },
|
||||
{ "vfat", 0, 0x36, 5, "MSDOS", probe_msdos },
|
||||
{ "vfat", 0, 0x36, 8, "FAT16 ", probe_msdos },
|
||||
{ "vfat", 0, 0x36, 8, "FAT12 ", probe_msdos },
|
||||
{ "minix", 1, 0x10, 2, "\177\023", 0 },
|
||||
{ "minix", 1, 0x10, 2, "\217\023", 0 },
|
||||
{ "minix", 1, 0x10, 2, "\150\044", 0 },
|
||||
{ "minix", 1, 0x10, 2, "\170\044", 0 },
|
||||
{ "vxfs", 1, 0, 4, "\365\374\001\245", 0 },
|
||||
{ "xfs", 0, 0, 4, "XFSB", probe_xfs },
|
||||
{ "romfs", 0, 0, 8, "-rom1fs-", probe_romfs },
|
||||
{ "bfs", 0, 0, 4, "\316\372\173\033", 0 },
|
||||
{ "cramfs", 0, 0, 4, "E=\315\050", probe_cramfs },
|
||||
{ "qnx4", 0, 4, 6, "QNX4FS", 0 },
|
||||
{ "udf", 32, 1, 5, "BEA01", probe_udf },
|
||||
{ "udf", 32, 1, 5, "BOOT2", probe_udf },
|
||||
{ "udf", 32, 1, 5, "CD001", probe_udf },
|
||||
{ "udf", 32, 1, 5, "CDW02", probe_udf },
|
||||
{ "udf", 32, 1, 5, "NSR02", probe_udf },
|
||||
{ "udf", 32, 1, 5, "NSR03", probe_udf },
|
||||
{ "udf", 32, 1, 5, "TEA01", probe_udf },
|
||||
{ "iso9660", 32, 1, 5, "CD001", 0 },
|
||||
{ "iso9660", 32, 9, 5, "CDROM", 0 },
|
||||
{ "jfs", 32, 0, 4, "JFS1", probe_jfs },
|
||||
{ "hfs", 1, 0, 2, "BD", 0 },
|
||||
{ "ufs", 8, 0x55c, 4, "T\031\001\000", 0 },
|
||||
{ "hpfs", 8, 0, 4, "I\350\225\371", 0 },
|
||||
{ "sysv", 0, 0x3f8, 4, "\020~\030\375", 0 },
|
||||
{ "swap", 0, 0xff6, 10, "SWAP-SPACE", probe_swap0 },
|
||||
{ "swap", 0, 0xff6, 10, "SWAPSPACE2", probe_swap1 },
|
||||
{ "swap", 0, 0x1ff6, 10, "SWAP-SPACE", probe_swap0 },
|
||||
{ "swap", 0, 0x1ff6, 10, "SWAPSPACE2", probe_swap1 },
|
||||
{ "swap", 0, 0x3ff6, 10, "SWAP-SPACE", probe_swap0 },
|
||||
{ "swap", 0, 0x3ff6, 10, "SWAPSPACE2", probe_swap1 },
|
||||
{ "swap", 0, 0x7ff6, 10, "SWAP-SPACE", probe_swap0 },
|
||||
{ "swap", 0, 0x7ff6, 10, "SWAPSPACE2", probe_swap1 },
|
||||
{ "swap", 0, 0xfff6, 10, "SWAP-SPACE", probe_swap0 },
|
||||
{ "swap", 0, 0xfff6, 10, "SWAPSPACE2", probe_swap1 },
|
||||
{ "ocfs", 0, 8, 9, "OracleCFS", probe_ocfs },
|
||||
{ "ocfs2", 1, 0, 6, "OCFSV2", probe_ocfs2 },
|
||||
{ "ocfs2", 2, 0, 6, "OCFSV2", probe_ocfs2 },
|
||||
{ "ocfs2", 4, 0, 6, "OCFSV2", probe_ocfs2 },
|
||||
{ "ocfs2", 8, 0, 6, "OCFSV2", probe_ocfs2 },
|
||||
{ NULL, 0, 0, 0, NULL, NULL }
|
||||
};
|
||||
|
||||
/*
|
||||
* Verify that the data in dev is consistent with what is on the actual
|
||||
* block device (using the devname field only). Normally this will be
|
||||
* called when finding items in the cache, but for long running processes
|
||||
* is also desirable to revalidate an item before use.
|
||||
*
|
||||
* If we are unable to revalidate the data, we return the old data and
|
||||
* do not set the BLKID_BID_FL_VERIFIED flag on it.
|
||||
*/
|
||||
blkid_dev blkid_verify(blkid_cache cache, blkid_dev dev)
|
||||
{
|
||||
const struct blkid_magic *id;
|
||||
unsigned char *bufs[BLKID_BLK_OFFS + 1], *buf;
|
||||
const char *type;
|
||||
struct stat st;
|
||||
time_t diff, now;
|
||||
int fd, idx;
|
||||
|
||||
if (!dev)
|
||||
return NULL;
|
||||
|
||||
now = time(0);
|
||||
diff = now - dev->bid_time;
|
||||
|
||||
if ((now < dev->bid_time) ||
|
||||
(diff < BLKID_PROBE_MIN) ||
|
||||
(dev->bid_flags & BLKID_BID_FL_VERIFIED &&
|
||||
diff < BLKID_PROBE_INTERVAL))
|
||||
return dev;
|
||||
|
||||
DBG(DEBUG_PROBE,
|
||||
printf("need to revalidate %s (time since last check %lu)\n",
|
||||
dev->bid_name, diff));
|
||||
|
||||
if (((fd = open(dev->bid_name, O_RDONLY)) < 0) ||
|
||||
(fstat(fd, &st) < 0)) {
|
||||
if (errno == ENXIO || errno == ENODEV || errno == ENOENT) {
|
||||
blkid_free_dev(dev);
|
||||
return NULL;
|
||||
}
|
||||
/* We don't have read permission, just return cache data. */
|
||||
DBG(DEBUG_PROBE,
|
||||
printf("returning unverified data for %s\n",
|
||||
dev->bid_name));
|
||||
return dev;
|
||||
}
|
||||
|
||||
memset(bufs, 0, sizeof(bufs));
|
||||
|
||||
/*
|
||||
* Iterate over the type array. If we already know the type,
|
||||
* then try that first. If it doesn't work, then blow away
|
||||
* the type information, and try again.
|
||||
*
|
||||
*/
|
||||
try_again:
|
||||
type = 0;
|
||||
if (!dev->bid_type || !strcmp(dev->bid_type, "mdraid")) {
|
||||
uuid_t uuid;
|
||||
|
||||
if (check_mdraid(fd, uuid) == 0) {
|
||||
set_uuid(dev, uuid);
|
||||
type = "mdraid";
|
||||
goto found_type;
|
||||
}
|
||||
}
|
||||
for (id = type_array; id->bim_type; id++) {
|
||||
if (dev->bid_type &&
|
||||
strcmp(id->bim_type, dev->bid_type))
|
||||
continue;
|
||||
|
||||
idx = id->bim_kboff + (id->bim_sboff >> 10);
|
||||
if (idx > BLKID_BLK_OFFS || idx < 0)
|
||||
continue;
|
||||
buf = bufs[idx];
|
||||
if (!buf) {
|
||||
if (lseek(fd, idx << 10, SEEK_SET) < 0)
|
||||
continue;
|
||||
|
||||
buf = xmalloc(1024);
|
||||
|
||||
if (read(fd, buf, 1024) != 1024) {
|
||||
free(buf);
|
||||
continue;
|
||||
}
|
||||
bufs[idx] = buf;
|
||||
}
|
||||
|
||||
if (memcmp(id->bim_magic, buf + (id->bim_sboff&0x3ff),
|
||||
id->bim_len))
|
||||
continue;
|
||||
|
||||
if ((id->bim_probe == NULL) ||
|
||||
(id->bim_probe(fd, cache, dev, id, buf) == 0)) {
|
||||
type = id->bim_type;
|
||||
goto found_type;
|
||||
}
|
||||
}
|
||||
|
||||
if (!id->bim_type && dev->bid_type) {
|
||||
/*
|
||||
* Zap the device filesystem type and try again
|
||||
*/
|
||||
blkid_set_tag(dev, "TYPE", 0, 0);
|
||||
blkid_set_tag(dev, "SEC_TYPE", 0, 0);
|
||||
blkid_set_tag(dev, "LABEL", 0, 0);
|
||||
blkid_set_tag(dev, "UUID", 0, 0);
|
||||
goto try_again;
|
||||
}
|
||||
|
||||
if (!dev->bid_type) {
|
||||
blkid_free_dev(dev);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
found_type:
|
||||
if (dev && type) {
|
||||
dev->bid_devno = st.st_rdev;
|
||||
dev->bid_time = time(0);
|
||||
dev->bid_flags |= BLKID_BID_FL_VERIFIED;
|
||||
cache->bic_flags |= BLKID_BIC_FL_CHANGED;
|
||||
|
||||
blkid_set_tag(dev, "TYPE", type, 0);
|
||||
|
||||
DBG(DEBUG_PROBE, printf("%s: devno 0x%04llx, type %s\n",
|
||||
dev->bid_name, st.st_rdev, type));
|
||||
}
|
||||
|
||||
close(fd);
|
||||
|
||||
return dev;
|
||||
}
|
||||
|
||||
int blkid_known_fstype(const char *fstype)
|
||||
{
|
||||
const struct blkid_magic *id;
|
||||
|
||||
for (id = type_array; id->bim_type; id++) {
|
||||
if (strcmp(fstype, id->bim_type) == 0)
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifdef TEST_PROGRAM
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
blkid_dev dev;
|
||||
blkid_cache cache;
|
||||
int ret;
|
||||
|
||||
blkid_debug_mask = DEBUG_ALL;
|
||||
if (argc != 2) {
|
||||
fprintf(stderr, "Usage: %s device\n"
|
||||
"Probe a single device to determine type\n", argv[0]);
|
||||
exit(1);
|
||||
}
|
||||
if ((ret = blkid_get_cache(&cache, bb_dev_null)) != 0) {
|
||||
fprintf(stderr, "%s: error creating cache (%d)\n",
|
||||
argv[0], ret);
|
||||
exit(1);
|
||||
}
|
||||
dev = blkid_get_dev(cache, argv[1], BLKID_DEV_NORMAL);
|
||||
if (!dev) {
|
||||
printf("%s: %s has an unsupported type\n", argv[0], argv[1]);
|
||||
return 1;
|
||||
}
|
||||
printf("%s is type %s\n", argv[1], dev->bid_type ?
|
||||
dev->bid_type : "(null)");
|
||||
if (dev->bid_label)
|
||||
printf("\tlabel is '%s'\n", dev->bid_label);
|
||||
if (dev->bid_uuid)
|
||||
printf("\tuuid is %s\n", dev->bid_uuid);
|
||||
|
||||
blkid_free_dev(dev);
|
||||
return 0;
|
||||
}
|
||||
#endif
|
375
e2fsprogs/old_e2fsprogs/blkid/probe.h
Normal file
375
e2fsprogs/old_e2fsprogs/blkid/probe.h
Normal file
@ -0,0 +1,375 @@
|
||||
/* vi: set sw=4 ts=4: */
|
||||
/*
|
||||
* probe.h - constants and on-disk structures for extracting device data
|
||||
*
|
||||
* Copyright (C) 1999 by Andries Brouwer
|
||||
* Copyright (C) 1999, 2000, 2003 by Theodore Ts'o
|
||||
* Copyright (C) 2001 by Andreas Dilger
|
||||
*
|
||||
* %Begin-Header%
|
||||
* This file may be redistributed under the terms of the
|
||||
* GNU Lesser General Public License.
|
||||
* %End-Header%
|
||||
*/
|
||||
|
||||
#ifndef _BLKID_PROBE_H
|
||||
#define _BLKID_PROBE_H
|
||||
|
||||
#include <linux/types.h>
|
||||
|
||||
struct blkid_magic;
|
||||
|
||||
typedef int (*blkid_probe_t)(int fd, blkid_cache cache, blkid_dev dev,
|
||||
const struct blkid_magic *id, unsigned char *buf);
|
||||
|
||||
struct blkid_magic {
|
||||
const char *bim_type; /* type name for this magic */
|
||||
long bim_kboff; /* kilobyte offset of superblock */
|
||||
unsigned bim_sboff; /* byte offset within superblock */
|
||||
unsigned bim_len; /* length of magic */
|
||||
const char *bim_magic; /* magic string */
|
||||
blkid_probe_t bim_probe; /* probe function */
|
||||
};
|
||||
|
||||
/*
|
||||
* Structures for each of the content types we want to extract information
|
||||
* from. We do not necessarily need the magic field here, because we have
|
||||
* already identified the content type before we get this far. It may still
|
||||
* be useful if there are probe functions which handle multiple content types.
|
||||
*/
|
||||
struct ext2_super_block {
|
||||
__u32 s_inodes_count;
|
||||
__u32 s_blocks_count;
|
||||
__u32 s_r_blocks_count;
|
||||
__u32 s_free_blocks_count;
|
||||
__u32 s_free_inodes_count;
|
||||
__u32 s_first_data_block;
|
||||
__u32 s_log_block_size;
|
||||
__u32 s_dummy3[7];
|
||||
unsigned char s_magic[2];
|
||||
__u16 s_state;
|
||||
__u32 s_dummy5[8];
|
||||
__u32 s_feature_compat;
|
||||
__u32 s_feature_incompat;
|
||||
__u32 s_feature_ro_compat;
|
||||
unsigned char s_uuid[16];
|
||||
char s_volume_name[16];
|
||||
};
|
||||
#define EXT3_FEATURE_COMPAT_HAS_JOURNAL 0x00000004
|
||||
#define EXT3_FEATURE_INCOMPAT_RECOVER 0x00000004
|
||||
#define EXT3_FEATURE_INCOMPAT_JOURNAL_DEV 0x00000008
|
||||
|
||||
struct xfs_super_block {
|
||||
unsigned char xs_magic[4];
|
||||
__u32 xs_blocksize;
|
||||
__u64 xs_dblocks;
|
||||
__u64 xs_rblocks;
|
||||
__u32 xs_dummy1[2];
|
||||
unsigned char xs_uuid[16];
|
||||
__u32 xs_dummy2[15];
|
||||
char xs_fname[12];
|
||||
__u32 xs_dummy3[2];
|
||||
__u64 xs_icount;
|
||||
__u64 xs_ifree;
|
||||
__u64 xs_fdblocks;
|
||||
};
|
||||
|
||||
struct reiserfs_super_block {
|
||||
__u32 rs_blocks_count;
|
||||
__u32 rs_free_blocks;
|
||||
__u32 rs_root_block;
|
||||
__u32 rs_journal_block;
|
||||
__u32 rs_journal_dev;
|
||||
__u32 rs_orig_journal_size;
|
||||
__u32 rs_dummy2[5];
|
||||
__u16 rs_blocksize;
|
||||
__u16 rs_dummy3[3];
|
||||
unsigned char rs_magic[12];
|
||||
__u32 rs_dummy4[5];
|
||||
unsigned char rs_uuid[16];
|
||||
char rs_label[16];
|
||||
};
|
||||
|
||||
struct jfs_super_block {
|
||||
unsigned char js_magic[4];
|
||||
__u32 js_version;
|
||||
__u64 js_size;
|
||||
__u32 js_bsize;
|
||||
__u32 js_dummy1;
|
||||
__u32 js_pbsize;
|
||||
__u32 js_dummy2[27];
|
||||
unsigned char js_uuid[16];
|
||||
unsigned char js_label[16];
|
||||
unsigned char js_loguuid[16];
|
||||
};
|
||||
|
||||
struct romfs_super_block {
|
||||
unsigned char ros_magic[8];
|
||||
__u32 ros_dummy1[2];
|
||||
unsigned char ros_volume[16];
|
||||
};
|
||||
|
||||
struct cramfs_super_block {
|
||||
__u8 magic[4];
|
||||
__u32 size;
|
||||
__u32 flags;
|
||||
__u32 future;
|
||||
__u8 signature[16];
|
||||
struct cramfs_info {
|
||||
__u32 crc;
|
||||
__u32 edition;
|
||||
__u32 blocks;
|
||||
__u32 files;
|
||||
} info;
|
||||
__u8 name[16];
|
||||
};
|
||||
|
||||
struct swap_id_block {
|
||||
/* unsigned char sws_boot[1024]; */
|
||||
__u32 sws_version;
|
||||
__u32 sws_lastpage;
|
||||
__u32 sws_nrbad;
|
||||
unsigned char sws_uuid[16];
|
||||
char sws_volume[16];
|
||||
unsigned char sws_pad[117];
|
||||
__u32 sws_badpg;
|
||||
};
|
||||
|
||||
/* Yucky misaligned values */
|
||||
struct vfat_super_block {
|
||||
/* 00*/ unsigned char vs_ignored[3];
|
||||
/* 03*/ unsigned char vs_sysid[8];
|
||||
/* 0b*/ unsigned char vs_sector_size[2];
|
||||
/* 0d*/ __u8 vs_cluster_size;
|
||||
/* 0e*/ __u16 vs_reserved;
|
||||
/* 10*/ __u8 vs_fats;
|
||||
/* 11*/ unsigned char vs_dir_entries[2];
|
||||
/* 13*/ unsigned char vs_sectors[2];
|
||||
/* 15*/ unsigned char vs_media;
|
||||
/* 16*/ __u16 vs_fat_length;
|
||||
/* 18*/ __u16 vs_secs_track;
|
||||
/* 1a*/ __u16 vs_heads;
|
||||
/* 1c*/ __u32 vs_hidden;
|
||||
/* 20*/ __u32 vs_total_sect;
|
||||
/* 24*/ __u32 vs_fat32_length;
|
||||
/* 28*/ __u16 vs_flags;
|
||||
/* 2a*/ __u8 vs_version[2];
|
||||
/* 2c*/ __u32 vs_root_cluster;
|
||||
/* 30*/ __u16 vs_insfo_sector;
|
||||
/* 32*/ __u16 vs_backup_boot;
|
||||
/* 34*/ __u16 vs_reserved2[6];
|
||||
/* 40*/ unsigned char vs_unknown[3];
|
||||
/* 43*/ unsigned char vs_serno[4];
|
||||
/* 47*/ char vs_label[11];
|
||||
/* 52*/ unsigned char vs_magic[8];
|
||||
/* 5a*/ unsigned char vs_dummy2[164];
|
||||
/*1fe*/ unsigned char vs_pmagic[2];
|
||||
};
|
||||
|
||||
/* Yucky misaligned values */
|
||||
struct msdos_super_block {
|
||||
/* 00*/ unsigned char ms_ignored[3];
|
||||
/* 03*/ unsigned char ms_sysid[8];
|
||||
/* 0b*/ unsigned char ms_sector_size[2];
|
||||
/* 0d*/ __u8 ms_cluster_size;
|
||||
/* 0e*/ __u16 ms_reserved;
|
||||
/* 10*/ __u8 ms_fats;
|
||||
/* 11*/ unsigned char ms_dir_entries[2];
|
||||
/* 13*/ unsigned char ms_sectors[2];
|
||||
/* 15*/ unsigned char ms_media;
|
||||
/* 16*/ __u16 ms_fat_length;
|
||||
/* 18*/ __u16 ms_secs_track;
|
||||
/* 1a*/ __u16 ms_heads;
|
||||
/* 1c*/ __u32 ms_hidden;
|
||||
/* 20*/ __u32 ms_total_sect;
|
||||
/* 24*/ unsigned char ms_unknown[3];
|
||||
/* 27*/ unsigned char ms_serno[4];
|
||||
/* 2b*/ char ms_label[11];
|
||||
/* 36*/ unsigned char ms_magic[8];
|
||||
/* 3d*/ unsigned char ms_dummy2[192];
|
||||
/*1fe*/ unsigned char ms_pmagic[2];
|
||||
};
|
||||
|
||||
struct minix_super_block {
|
||||
__u16 ms_ninodes;
|
||||
__u16 ms_nzones;
|
||||
__u16 ms_imap_blocks;
|
||||
__u16 ms_zmap_blocks;
|
||||
__u16 ms_firstdatazone;
|
||||
__u16 ms_log_zone_size;
|
||||
__u32 ms_max_size;
|
||||
unsigned char ms_magic[2];
|
||||
__u16 ms_state;
|
||||
__u32 ms_zones;
|
||||
};
|
||||
|
||||
struct mdp_superblock_s {
|
||||
__u32 md_magic;
|
||||
__u32 major_version;
|
||||
__u32 minor_version;
|
||||
__u32 patch_version;
|
||||
__u32 gvalid_words;
|
||||
__u32 set_uuid0;
|
||||
__u32 ctime;
|
||||
__u32 level;
|
||||
__u32 size;
|
||||
__u32 nr_disks;
|
||||
__u32 raid_disks;
|
||||
__u32 md_minor;
|
||||
__u32 not_persistent;
|
||||
__u32 set_uuid1;
|
||||
__u32 set_uuid2;
|
||||
__u32 set_uuid3;
|
||||
};
|
||||
|
||||
struct hfs_super_block {
|
||||
char h_magic[2];
|
||||
char h_dummy[18];
|
||||
__u32 h_blksize;
|
||||
};
|
||||
|
||||
struct ocfs_volume_header {
|
||||
unsigned char minor_version[4];
|
||||
unsigned char major_version[4];
|
||||
unsigned char signature[128];
|
||||
char mount[128];
|
||||
unsigned char mount_len[2];
|
||||
};
|
||||
|
||||
struct ocfs_volume_label {
|
||||
unsigned char disk_lock[48];
|
||||
char label[64];
|
||||
unsigned char label_len[2];
|
||||
unsigned char vol_id[16];
|
||||
unsigned char vol_id_len[2];
|
||||
};
|
||||
|
||||
#define ocfsmajor(o) ((__u32)o.major_version[0] \
|
||||
+ (((__u32) o.major_version[1]) << 8) \
|
||||
+ (((__u32) o.major_version[2]) << 16) \
|
||||
+ (((__u32) o.major_version[3]) << 24))
|
||||
#define ocfslabellen(o) ((__u32)o.label_len[0] + (((__u32) o.label_len[1]) << 8))
|
||||
#define ocfsmountlen(o) ((__u32)o.mount_len[0] + (((__u32) o.mount_len[1])<<8))
|
||||
|
||||
#define OCFS_MAGIC "OracleCFS"
|
||||
|
||||
struct ocfs2_super_block {
|
||||
unsigned char signature[8];
|
||||
unsigned char s_dummy1[184];
|
||||
unsigned char s_dummy2[80];
|
||||
char s_label[64];
|
||||
unsigned char s_uuid[16];
|
||||
};
|
||||
|
||||
#define OCFS2_MIN_BLOCKSIZE 512
|
||||
#define OCFS2_MAX_BLOCKSIZE 4096
|
||||
|
||||
#define OCFS2_SUPER_BLOCK_BLKNO 2
|
||||
|
||||
#define OCFS2_SUPER_BLOCK_SIGNATURE "OCFSV2"
|
||||
|
||||
struct oracle_asm_disk_label {
|
||||
char dummy[32];
|
||||
char dl_tag[8];
|
||||
char dl_id[24];
|
||||
};
|
||||
|
||||
#define ORACLE_ASM_DISK_LABEL_MARKED "ORCLDISK"
|
||||
#define ORACLE_ASM_DISK_LABEL_OFFSET 32
|
||||
|
||||
#define ISODCL(from, to) (to - from + 1)
|
||||
struct iso_volume_descriptor {
|
||||
char type[ISODCL(1,1)]; /* 711 */
|
||||
char id[ISODCL(2,6)];
|
||||
char version[ISODCL(7,7)];
|
||||
char data[ISODCL(8,2048)];
|
||||
};
|
||||
|
||||
/*
|
||||
* Byte swap functions
|
||||
*/
|
||||
#ifdef __GNUC__
|
||||
#define _INLINE_ static __inline__
|
||||
#else /* For Watcom C */
|
||||
#define _INLINE_ static inline
|
||||
#endif
|
||||
|
||||
static __u16 blkid_swab16(__u16 val);
|
||||
static __u32 blkid_swab32(__u32 val);
|
||||
static __u64 blkid_swab64(__u64 val);
|
||||
|
||||
#if ((defined __GNUC__) && \
|
||||
(defined(__i386__) || defined(__i486__) || defined(__i586__)))
|
||||
|
||||
#define _BLKID_HAVE_ASM_BITOPS_
|
||||
|
||||
_INLINE_ __u32 blkid_swab32(__u32 val)
|
||||
{
|
||||
#ifdef EXT2FS_REQUIRE_486
|
||||
__asm__("bswap %0" : "=r" (val) : "0" (val));
|
||||
#else
|
||||
__asm__("xchgb %b0,%h0\n\t" /* swap lower bytes */
|
||||
"rorl $16,%0\n\t" /* swap words */
|
||||
"xchgb %b0,%h0" /* swap higher bytes */
|
||||
:"=q" (val)
|
||||
: "0" (val));
|
||||
#endif
|
||||
return val;
|
||||
}
|
||||
|
||||
_INLINE_ __u16 blkid_swab16(__u16 val)
|
||||
{
|
||||
__asm__("xchgb %b0,%h0" /* swap bytes */ \
|
||||
: "=q" (val) \
|
||||
: "0" (val)); \
|
||||
return val;
|
||||
}
|
||||
|
||||
_INLINE_ __u64 blkid_swab64(__u64 val)
|
||||
{
|
||||
return blkid_swab32(val >> 32) |
|
||||
( ((__u64)blkid_swab32((__u32)val)) << 32 );
|
||||
}
|
||||
#endif
|
||||
|
||||
#if !defined(_BLKID_HAVE_ASM_BITOPS_)
|
||||
|
||||
_INLINE_ __u16 blkid_swab16(__u16 val)
|
||||
{
|
||||
return (val >> 8) | (val << 8);
|
||||
}
|
||||
|
||||
_INLINE_ __u32 blkid_swab32(__u32 val)
|
||||
{
|
||||
return (val>>24) | ((val>>8) & 0xFF00) |
|
||||
((val<<8) & 0xFF0000) | (val<<24);
|
||||
}
|
||||
|
||||
_INLINE_ __u64 blkid_swab64(__u64 val)
|
||||
{
|
||||
return blkid_swab32(val >> 32) |
|
||||
( ((__u64)blkid_swab32((__u32)val)) << 32 );
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
#if __BYTE_ORDER == __BIG_ENDIAN
|
||||
#define blkid_le16(x) blkid_swab16(x)
|
||||
#define blkid_le32(x) blkid_swab32(x)
|
||||
#define blkid_le64(x) blkid_swab64(x)
|
||||
#define blkid_be16(x) (x)
|
||||
#define blkid_be32(x) (x)
|
||||
#define blkid_be64(x) (x)
|
||||
#else
|
||||
#define blkid_le16(x) (x)
|
||||
#define blkid_le32(x) (x)
|
||||
#define blkid_le64(x) (x)
|
||||
#define blkid_be16(x) blkid_swab16(x)
|
||||
#define blkid_be32(x) blkid_swab32(x)
|
||||
#define blkid_be64(x) blkid_swab64(x)
|
||||
#endif
|
||||
|
||||
#undef _INLINE_
|
||||
|
||||
#endif /* _BLKID_PROBE_H */
|
462
e2fsprogs/old_e2fsprogs/blkid/read.c
Normal file
462
e2fsprogs/old_e2fsprogs/blkid/read.c
Normal file
@ -0,0 +1,462 @@
|
||||
/* vi: set sw=4 ts=4: */
|
||||
/*
|
||||
* read.c - read the blkid cache from disk, to avoid scanning all devices
|
||||
*
|
||||
* Copyright (C) 2001, 2003 Theodore Y. Ts'o
|
||||
* Copyright (C) 2001 Andreas Dilger
|
||||
*
|
||||
* %Begin-Header%
|
||||
* This file may be redistributed under the terms of the
|
||||
* GNU Lesser General Public License.
|
||||
* %End-Header%
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <ctype.h>
|
||||
#include <string.h>
|
||||
#include <time.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <fcntl.h>
|
||||
#include <unistd.h>
|
||||
#include <errno.h>
|
||||
|
||||
#include "blkidP.h"
|
||||
#include "../uuid/uuid.h"
|
||||
|
||||
#ifdef HAVE_STRTOULL
|
||||
#define __USE_ISOC9X
|
||||
#define STRTOULL strtoull /* defined in stdlib.h if you try hard enough */
|
||||
#else
|
||||
/* FIXME: need to support real strtoull here */
|
||||
#define STRTOULL strtoul
|
||||
#endif
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
#ifdef TEST_PROGRAM
|
||||
#define blkid_debug_dump_dev(dev) (debug_dump_dev(dev))
|
||||
static void debug_dump_dev(blkid_dev dev);
|
||||
#endif
|
||||
|
||||
/*
|
||||
* File format:
|
||||
*
|
||||
* <device [<NAME="value"> ...]>device_name</device>
|
||||
*
|
||||
* The following tags are required for each entry:
|
||||
* <ID="id"> unique (within this file) ID number of this device
|
||||
* <TIME="time"> (ascii time_t) time this entry was last read from disk
|
||||
* <TYPE="type"> (detected) type of filesystem/data for this partition
|
||||
*
|
||||
* The following tags may be present, depending on the device contents
|
||||
* <LABEL="label"> (user supplied) label (volume name, etc)
|
||||
* <UUID="uuid"> (generated) universally unique identifier (serial no)
|
||||
*/
|
||||
|
||||
static char *skip_over_blank(char *cp)
|
||||
{
|
||||
while (*cp && isspace(*cp))
|
||||
cp++;
|
||||
return cp;
|
||||
}
|
||||
|
||||
static char *skip_over_word(char *cp)
|
||||
{
|
||||
char ch;
|
||||
|
||||
while ((ch = *cp)) {
|
||||
/* If we see a backslash, skip the next character */
|
||||
if (ch == '\\') {
|
||||
cp++;
|
||||
if (*cp == '\0')
|
||||
break;
|
||||
cp++;
|
||||
continue;
|
||||
}
|
||||
if (isspace(ch) || ch == '<' || ch == '>')
|
||||
break;
|
||||
cp++;
|
||||
}
|
||||
return cp;
|
||||
}
|
||||
|
||||
static char *strip_line(char *line)
|
||||
{
|
||||
char *p;
|
||||
|
||||
line = skip_over_blank(line);
|
||||
|
||||
p = line + strlen(line) - 1;
|
||||
|
||||
while (*line) {
|
||||
if (isspace(*p))
|
||||
*p-- = '\0';
|
||||
else
|
||||
break;
|
||||
}
|
||||
|
||||
return line;
|
||||
}
|
||||
|
||||
/*
|
||||
* Start parsing a new line from the cache.
|
||||
*
|
||||
* line starts with "<device" return 1 -> continue parsing line
|
||||
* line starts with "<foo", empty, or # return 0 -> skip line
|
||||
* line starts with other, return -BLKID_ERR_CACHE -> error
|
||||
*/
|
||||
static int parse_start(char **cp)
|
||||
{
|
||||
char *p;
|
||||
|
||||
p = strip_line(*cp);
|
||||
|
||||
/* Skip comment or blank lines. We can't just NUL the first '#' char,
|
||||
* in case it is inside quotes, or escaped.
|
||||
*/
|
||||
if (*p == '\0' || *p == '#')
|
||||
return 0;
|
||||
|
||||
if (!strncmp(p, "<device", 7)) {
|
||||
DBG(DEBUG_READ, printf("found device header: %8s\n", p));
|
||||
p += 7;
|
||||
|
||||
*cp = p;
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (*p == '<')
|
||||
return 0;
|
||||
|
||||
return -BLKID_ERR_CACHE;
|
||||
}
|
||||
|
||||
/* Consume the remaining XML on the line (cosmetic only) */
|
||||
static int parse_end(char **cp)
|
||||
{
|
||||
*cp = skip_over_blank(*cp);
|
||||
|
||||
if (!strncmp(*cp, "</device>", 9)) {
|
||||
DBG(DEBUG_READ, printf("found device trailer %9s\n", *cp));
|
||||
*cp += 9;
|
||||
return 0;
|
||||
}
|
||||
|
||||
return -BLKID_ERR_CACHE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Allocate a new device struct with device name filled in. Will handle
|
||||
* finding the device on lines of the form:
|
||||
* <device foo=bar>devname</device>
|
||||
* <device>devname<foo>bar</foo></device>
|
||||
*/
|
||||
static int parse_dev(blkid_cache cache, blkid_dev *dev, char **cp)
|
||||
{
|
||||
char *start, *tmp, *end, *name;
|
||||
int ret;
|
||||
|
||||
if ((ret = parse_start(cp)) <= 0)
|
||||
return ret;
|
||||
|
||||
start = tmp = strchr(*cp, '>');
|
||||
if (!start) {
|
||||
DBG(DEBUG_READ,
|
||||
printf("blkid: short line parsing dev: %s\n", *cp));
|
||||
return -BLKID_ERR_CACHE;
|
||||
}
|
||||
start = skip_over_blank(start + 1);
|
||||
end = skip_over_word(start);
|
||||
|
||||
DBG(DEBUG_READ, printf("device should be %*s\n", end - start, start));
|
||||
|
||||
if (**cp == '>')
|
||||
*cp = end;
|
||||
else
|
||||
(*cp)++;
|
||||
|
||||
*tmp = '\0';
|
||||
|
||||
if (!(tmp = strrchr(end, '<')) || parse_end(&tmp) < 0) {
|
||||
DBG(DEBUG_READ,
|
||||
printf("blkid: missing </device> ending: %s\n", end));
|
||||
} else if (tmp)
|
||||
*tmp = '\0';
|
||||
|
||||
if (end - start <= 1) {
|
||||
DBG(DEBUG_READ, printf("blkid: empty device name: %s\n", *cp));
|
||||
return -BLKID_ERR_CACHE;
|
||||
}
|
||||
|
||||
name = blkid_strndup(start, end-start);
|
||||
if (name == NULL)
|
||||
return -BLKID_ERR_MEM;
|
||||
|
||||
DBG(DEBUG_READ, printf("found dev %s\n", name));
|
||||
|
||||
if (!(*dev = blkid_get_dev(cache, name, BLKID_DEV_CREATE)))
|
||||
return -BLKID_ERR_MEM;
|
||||
|
||||
free(name);
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* Extract a tag of the form NAME="value" from the line.
|
||||
*/
|
||||
static int parse_token(char **name, char **value, char **cp)
|
||||
{
|
||||
char *end;
|
||||
|
||||
if (!name || !value || !cp)
|
||||
return -BLKID_ERR_PARAM;
|
||||
|
||||
if (!(*value = strchr(*cp, '=')))
|
||||
return 0;
|
||||
|
||||
**value = '\0';
|
||||
*name = strip_line(*cp);
|
||||
*value = skip_over_blank(*value + 1);
|
||||
|
||||
if (**value == '"') {
|
||||
end = strchr(*value + 1, '"');
|
||||
if (!end) {
|
||||
DBG(DEBUG_READ,
|
||||
printf("unbalanced quotes at: %s\n", *value));
|
||||
*cp = *value;
|
||||
return -BLKID_ERR_CACHE;
|
||||
}
|
||||
(*value)++;
|
||||
*end = '\0';
|
||||
end++;
|
||||
} else {
|
||||
end = skip_over_word(*value);
|
||||
if (*end) {
|
||||
*end = '\0';
|
||||
end++;
|
||||
}
|
||||
}
|
||||
*cp = end;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* Extract a tag of the form <NAME>value</NAME> from the line.
|
||||
*/
|
||||
/*
|
||||
static int parse_xml(char **name, char **value, char **cp)
|
||||
{
|
||||
char *end;
|
||||
|
||||
if (!name || !value || !cp)
|
||||
return -BLKID_ERR_PARAM;
|
||||
|
||||
*name = strip_line(*cp);
|
||||
|
||||
if ((*name)[0] != '<' || (*name)[1] == '/')
|
||||
return 0;
|
||||
|
||||
FIXME: finish this.
|
||||
}
|
||||
*/
|
||||
|
||||
/*
|
||||
* Extract a tag from the line.
|
||||
*
|
||||
* Return 1 if a valid tag was found.
|
||||
* Return 0 if no tag found.
|
||||
* Return -ve error code.
|
||||
*/
|
||||
static int parse_tag(blkid_cache cache, blkid_dev dev, char **cp)
|
||||
{
|
||||
char *name;
|
||||
char *value;
|
||||
int ret;
|
||||
|
||||
if (!cache || !dev)
|
||||
return -BLKID_ERR_PARAM;
|
||||
|
||||
if ((ret = parse_token(&name, &value, cp)) <= 0 /* &&
|
||||
(ret = parse_xml(&name, &value, cp)) <= 0 */)
|
||||
return ret;
|
||||
|
||||
/* Some tags are stored directly in the device struct */
|
||||
if (!strcmp(name, "DEVNO"))
|
||||
dev->bid_devno = STRTOULL(value, 0, 0);
|
||||
else if (!strcmp(name, "PRI"))
|
||||
dev->bid_pri = strtol(value, 0, 0);
|
||||
else if (!strcmp(name, "TIME"))
|
||||
/* FIXME: need to parse a long long eventually */
|
||||
dev->bid_time = strtol(value, 0, 0);
|
||||
else
|
||||
ret = blkid_set_tag(dev, name, value, strlen(value));
|
||||
|
||||
DBG(DEBUG_READ, printf(" tag: %s=\"%s\"\n", name, value));
|
||||
|
||||
return ret < 0 ? ret : 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* Parse a single line of data, and return a newly allocated dev struct.
|
||||
* Add the new device to the cache struct, if one was read.
|
||||
*
|
||||
* Lines are of the form <device [TAG="value" ...]>/dev/foo</device>
|
||||
*
|
||||
* Returns -ve value on error.
|
||||
* Returns 0 otherwise.
|
||||
* If a valid device was read, *dev_p is non-NULL, otherwise it is NULL
|
||||
* (e.g. comment lines, unknown XML content, etc).
|
||||
*/
|
||||
static int blkid_parse_line(blkid_cache cache, blkid_dev *dev_p, char *cp)
|
||||
{
|
||||
blkid_dev dev;
|
||||
int ret;
|
||||
|
||||
if (!cache || !dev_p)
|
||||
return -BLKID_ERR_PARAM;
|
||||
|
||||
*dev_p = NULL;
|
||||
|
||||
DBG(DEBUG_READ, printf("line: %s\n", cp));
|
||||
|
||||
if ((ret = parse_dev(cache, dev_p, &cp)) <= 0)
|
||||
return ret;
|
||||
|
||||
dev = *dev_p;
|
||||
|
||||
while ((ret = parse_tag(cache, dev, &cp)) > 0) {
|
||||
;
|
||||
}
|
||||
|
||||
if (dev->bid_type == NULL) {
|
||||
DBG(DEBUG_READ,
|
||||
printf("blkid: device %s has no TYPE\n",dev->bid_name));
|
||||
blkid_free_dev(dev);
|
||||
}
|
||||
|
||||
DBG(DEBUG_READ, blkid_debug_dump_dev(dev));
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
* Parse the specified filename, and return the data in the supplied or
|
||||
* a newly allocated cache struct. If the file doesn't exist, return a
|
||||
* new empty cache struct.
|
||||
*/
|
||||
void blkid_read_cache(blkid_cache cache)
|
||||
{
|
||||
FILE *file;
|
||||
char buf[4096];
|
||||
int fd, lineno = 0;
|
||||
struct stat st;
|
||||
|
||||
if (!cache)
|
||||
return;
|
||||
|
||||
/*
|
||||
* If the file doesn't exist, then we just return an empty
|
||||
* struct so that the cache can be populated.
|
||||
*/
|
||||
if ((fd = open(cache->bic_filename, O_RDONLY)) < 0)
|
||||
return;
|
||||
if (fstat(fd, &st) < 0)
|
||||
goto errout;
|
||||
if ((st.st_mtime == cache->bic_ftime) ||
|
||||
(cache->bic_flags & BLKID_BIC_FL_CHANGED)) {
|
||||
DBG(DEBUG_CACHE, printf("skipping re-read of %s\n",
|
||||
cache->bic_filename));
|
||||
goto errout;
|
||||
}
|
||||
|
||||
DBG(DEBUG_CACHE, printf("reading cache file %s\n",
|
||||
cache->bic_filename));
|
||||
|
||||
file = fdopen(fd, "r");
|
||||
if (!file)
|
||||
goto errout;
|
||||
|
||||
while (fgets(buf, sizeof(buf), file)) {
|
||||
blkid_dev dev;
|
||||
unsigned int end;
|
||||
|
||||
lineno++;
|
||||
if (buf[0] == 0)
|
||||
continue;
|
||||
end = strlen(buf) - 1;
|
||||
/* Continue reading next line if it ends with a backslash */
|
||||
while (buf[end] == '\\' && end < sizeof(buf) - 2 &&
|
||||
fgets(buf + end, sizeof(buf) - end, file)) {
|
||||
end = strlen(buf) - 1;
|
||||
lineno++;
|
||||
}
|
||||
|
||||
if (blkid_parse_line(cache, &dev, buf) < 0) {
|
||||
DBG(DEBUG_READ,
|
||||
printf("blkid: bad format on line %d\n", lineno));
|
||||
continue;
|
||||
}
|
||||
}
|
||||
fclose(file);
|
||||
|
||||
/*
|
||||
* Initially we do not need to write out the cache file.
|
||||
*/
|
||||
cache->bic_flags &= ~BLKID_BIC_FL_CHANGED;
|
||||
cache->bic_ftime = st.st_mtime;
|
||||
|
||||
return;
|
||||
errout:
|
||||
close(fd);
|
||||
return;
|
||||
}
|
||||
|
||||
#ifdef TEST_PROGRAM
|
||||
static void debug_dump_dev(blkid_dev dev)
|
||||
{
|
||||
struct list_head *p;
|
||||
|
||||
if (!dev) {
|
||||
printf(" dev: NULL\n");
|
||||
return;
|
||||
}
|
||||
|
||||
printf(" dev: name = %s\n", dev->bid_name);
|
||||
printf(" dev: DEVNO=\"0x%0llx\"\n", dev->bid_devno);
|
||||
printf(" dev: TIME=\"%lu\"\n", dev->bid_time);
|
||||
printf(" dev: PRI=\"%d\"\n", dev->bid_pri);
|
||||
printf(" dev: flags = 0x%08X\n", dev->bid_flags);
|
||||
|
||||
list_for_each(p, &dev->bid_tags) {
|
||||
blkid_tag tag = list_entry(p, struct blkid_struct_tag, bit_tags);
|
||||
if (tag)
|
||||
printf(" tag: %s=\"%s\"\n", tag->bit_name,
|
||||
tag->bit_val);
|
||||
else
|
||||
printf(" tag: NULL\n");
|
||||
}
|
||||
puts("");
|
||||
}
|
||||
|
||||
int main(int argc, char**argv)
|
||||
{
|
||||
blkid_cache cache = NULL;
|
||||
int ret;
|
||||
|
||||
blkid_debug_mask = DEBUG_ALL;
|
||||
if (argc > 2) {
|
||||
fprintf(stderr, "Usage: %s [filename]\n"
|
||||
"Test parsing of the cache (filename)\n", argv[0]);
|
||||
exit(1);
|
||||
}
|
||||
if ((ret = blkid_get_cache(&cache, argv[1])) < 0)
|
||||
fprintf(stderr, "error %d reading cache file %s\n", ret,
|
||||
argv[1] ? argv[1] : BLKID_CACHE_FILE);
|
||||
|
||||
blkid_put_cache(cache);
|
||||
|
||||
return ret;
|
||||
}
|
||||
#endif
|
139
e2fsprogs/old_e2fsprogs/blkid/resolve.c
Normal file
139
e2fsprogs/old_e2fsprogs/blkid/resolve.c
Normal file
@ -0,0 +1,139 @@
|
||||
/* vi: set sw=4 ts=4: */
|
||||
/*
|
||||
* resolve.c - resolve names and tags into specific devices
|
||||
*
|
||||
* Copyright (C) 2001, 2003 Theodore Ts'o.
|
||||
* Copyright (C) 2001 Andreas Dilger
|
||||
*
|
||||
* %Begin-Header%
|
||||
* This file may be redistributed under the terms of the
|
||||
* GNU Lesser General Public License.
|
||||
* %End-Header%
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#ifdef HAVE_UNISTD_H
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
#include <stdlib.h>
|
||||
#include <fcntl.h>
|
||||
#include <string.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include "blkidP.h"
|
||||
#include "probe.h"
|
||||
|
||||
/*
|
||||
* Find a tagname (e.g. LABEL or UUID) on a specific device.
|
||||
*/
|
||||
char *blkid_get_tag_value(blkid_cache cache, const char *tagname,
|
||||
const char *devname)
|
||||
{
|
||||
blkid_tag found;
|
||||
blkid_dev dev;
|
||||
blkid_cache c = cache;
|
||||
char *ret = NULL;
|
||||
|
||||
DBG(DEBUG_RESOLVE, printf("looking for %s on %s\n", tagname, devname));
|
||||
|
||||
if (!devname)
|
||||
return NULL;
|
||||
|
||||
if (!cache) {
|
||||
if (blkid_get_cache(&c, NULL) < 0)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if ((dev = blkid_get_dev(c, devname, BLKID_DEV_NORMAL)) &&
|
||||
(found = blkid_find_tag_dev(dev, tagname)))
|
||||
ret = blkid_strdup(found->bit_val);
|
||||
|
||||
if (!cache)
|
||||
blkid_put_cache(c);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
* Locate a device name from a token (NAME=value string), or (name, value)
|
||||
* pair. In the case of a token, value is ignored. If the "token" is not
|
||||
* of the form "NAME=value" and there is no value given, then it is assumed
|
||||
* to be the actual devname and a copy is returned.
|
||||
*/
|
||||
char *blkid_get_devname(blkid_cache cache, const char *token,
|
||||
const char *value)
|
||||
{
|
||||
blkid_dev dev;
|
||||
blkid_cache c = cache;
|
||||
char *t = 0, *v = 0;
|
||||
char *ret = NULL;
|
||||
|
||||
if (!token)
|
||||
return NULL;
|
||||
|
||||
if (!cache) {
|
||||
if (blkid_get_cache(&c, NULL) < 0)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
DBG(DEBUG_RESOLVE,
|
||||
printf("looking for %s%s%s %s\n", token, value ? "=" : "",
|
||||
value ? value : "", cache ? "in cache" : "from disk"));
|
||||
|
||||
if (!value) {
|
||||
if (!strchr(token, '='))
|
||||
return blkid_strdup(token);
|
||||
blkid_parse_tag_string(token, &t, &v);
|
||||
if (!t || !v)
|
||||
goto errout;
|
||||
token = t;
|
||||
value = v;
|
||||
}
|
||||
|
||||
dev = blkid_find_dev_with_tag(c, token, value);
|
||||
if (!dev)
|
||||
goto errout;
|
||||
|
||||
ret = blkid_strdup(blkid_dev_devname(dev));
|
||||
|
||||
errout:
|
||||
free(t);
|
||||
free(v);
|
||||
if (!cache) {
|
||||
blkid_put_cache(c);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
#ifdef TEST_PROGRAM
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
char *value;
|
||||
blkid_cache cache;
|
||||
|
||||
blkid_debug_mask = DEBUG_ALL;
|
||||
if (argc != 2 && argc != 3) {
|
||||
fprintf(stderr, "Usage:\t%s tagname=value\n"
|
||||
"\t%s tagname devname\n"
|
||||
"Find which device holds a given token or\n"
|
||||
"Find what the value of a tag is in a device\n",
|
||||
argv[0], argv[0]);
|
||||
exit(1);
|
||||
}
|
||||
if (blkid_get_cache(&cache, bb_dev_null) < 0) {
|
||||
fprintf(stderr, "cannot get blkid cache\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if (argv[2]) {
|
||||
value = blkid_get_tag_value(cache, argv[1], argv[2]);
|
||||
printf("%s has tag %s=%s\n", argv[2], argv[1],
|
||||
value ? value : "<missing>");
|
||||
} else {
|
||||
value = blkid_get_devname(cache, argv[1], NULL);
|
||||
printf("%s has tag %s\n", value ? value : "<none>", argv[1]);
|
||||
}
|
||||
blkid_put_cache(cache);
|
||||
return value ? 0 : 1;
|
||||
}
|
||||
#endif
|
189
e2fsprogs/old_e2fsprogs/blkid/save.c
Normal file
189
e2fsprogs/old_e2fsprogs/blkid/save.c
Normal file
@ -0,0 +1,189 @@
|
||||
/* vi: set sw=4 ts=4: */
|
||||
/*
|
||||
* save.c - write the cache struct to disk
|
||||
*
|
||||
* Copyright (C) 2001 by Andreas Dilger
|
||||
* Copyright (C) 2003 Theodore Ts'o
|
||||
*
|
||||
* %Begin-Header%
|
||||
* This file may be redistributed under the terms of the
|
||||
* GNU Lesser General Public License.
|
||||
* %End-Header%
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/types.h>
|
||||
#ifdef HAVE_SYS_STAT_H
|
||||
#include <sys/stat.h>
|
||||
#endif
|
||||
#ifdef HAVE_SYS_MKDEV_H
|
||||
#include <sys/mkdev.h>
|
||||
#endif
|
||||
#ifdef HAVE_ERRNO_H
|
||||
#include <errno.h>
|
||||
#endif
|
||||
#include "blkidP.h"
|
||||
|
||||
static int save_dev(blkid_dev dev, FILE *file)
|
||||
{
|
||||
struct list_head *p;
|
||||
|
||||
if (!dev || dev->bid_name[0] != '/')
|
||||
return 0;
|
||||
|
||||
DBG(DEBUG_SAVE,
|
||||
printf("device %s, type %s\n", dev->bid_name, dev->bid_type));
|
||||
|
||||
fprintf(file,
|
||||
"<device DEVNO=\"0x%04lx\" TIME=\"%lu\"",
|
||||
(unsigned long) dev->bid_devno, dev->bid_time);
|
||||
if (dev->bid_pri)
|
||||
fprintf(file, " PRI=\"%d\"", dev->bid_pri);
|
||||
list_for_each(p, &dev->bid_tags) {
|
||||
blkid_tag tag = list_entry(p, struct blkid_struct_tag, bit_tags);
|
||||
fprintf(file, " %s=\"%s\"", tag->bit_name,tag->bit_val);
|
||||
}
|
||||
fprintf(file, ">%s</device>\n", dev->bid_name);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Write out the cache struct to the cache file on disk.
|
||||
*/
|
||||
int blkid_flush_cache(blkid_cache cache)
|
||||
{
|
||||
struct list_head *p;
|
||||
char *tmp = NULL;
|
||||
const char *opened = NULL;
|
||||
const char *filename;
|
||||
FILE *file = NULL;
|
||||
int fd, ret = 0;
|
||||
struct stat st;
|
||||
|
||||
if (!cache)
|
||||
return -BLKID_ERR_PARAM;
|
||||
|
||||
if (list_empty(&cache->bic_devs) ||
|
||||
!(cache->bic_flags & BLKID_BIC_FL_CHANGED)) {
|
||||
DBG(DEBUG_SAVE, printf("skipping cache file write\n"));
|
||||
return 0;
|
||||
}
|
||||
|
||||
filename = cache->bic_filename ? cache->bic_filename: BLKID_CACHE_FILE;
|
||||
|
||||
/* If we can't write to the cache file, then don't even try */
|
||||
if (((ret = stat(filename, &st)) < 0 && errno != ENOENT) ||
|
||||
(ret == 0 && access(filename, W_OK) < 0)) {
|
||||
DBG(DEBUG_SAVE,
|
||||
printf("can't write to cache file %s\n", filename));
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Try and create a temporary file in the same directory so
|
||||
* that in case of error we don't overwrite the cache file.
|
||||
* If the cache file doesn't yet exist, it isn't a regular
|
||||
* file (e.g. /dev/null or a socket), or we couldn't create
|
||||
* a temporary file then we open it directly.
|
||||
*/
|
||||
if (ret == 0 && S_ISREG(st.st_mode)) {
|
||||
tmp = xmalloc(strlen(filename) + 8);
|
||||
sprintf(tmp, "%s-XXXXXX", filename);
|
||||
fd = mkstemp(tmp);
|
||||
if (fd >= 0) {
|
||||
file = fdopen(fd, "w");
|
||||
opened = tmp;
|
||||
}
|
||||
fchmod(fd, 0644);
|
||||
}
|
||||
|
||||
if (!file) {
|
||||
file = fopen(filename, "w");
|
||||
opened = filename;
|
||||
}
|
||||
|
||||
DBG(DEBUG_SAVE,
|
||||
printf("writing cache file %s (really %s)\n",
|
||||
filename, opened));
|
||||
|
||||
if (!file) {
|
||||
ret = errno;
|
||||
goto errout;
|
||||
}
|
||||
|
||||
list_for_each(p, &cache->bic_devs) {
|
||||
blkid_dev dev = list_entry(p, struct blkid_struct_dev, bid_devs);
|
||||
if (!dev->bid_type)
|
||||
continue;
|
||||
if ((ret = save_dev(dev, file)) < 0)
|
||||
break;
|
||||
}
|
||||
|
||||
if (ret >= 0) {
|
||||
cache->bic_flags &= ~BLKID_BIC_FL_CHANGED;
|
||||
ret = 1;
|
||||
}
|
||||
|
||||
fclose(file);
|
||||
if (opened != filename) {
|
||||
if (ret < 0) {
|
||||
unlink(opened);
|
||||
DBG(DEBUG_SAVE,
|
||||
printf("unlinked temp cache %s\n", opened));
|
||||
} else {
|
||||
char *backup;
|
||||
|
||||
backup = xmalloc(strlen(filename) + 5);
|
||||
sprintf(backup, "%s.old", filename);
|
||||
unlink(backup);
|
||||
link(filename, backup);
|
||||
free(backup);
|
||||
rename(opened, filename);
|
||||
DBG(DEBUG_SAVE,
|
||||
printf("moved temp cache %s\n", opened));
|
||||
}
|
||||
}
|
||||
|
||||
errout:
|
||||
free(tmp);
|
||||
return ret;
|
||||
}
|
||||
|
||||
#ifdef TEST_PROGRAM
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
blkid_cache cache = NULL;
|
||||
int ret;
|
||||
|
||||
blkid_debug_mask = DEBUG_ALL;
|
||||
if (argc > 2) {
|
||||
fprintf(stderr, "Usage: %s [filename]\n"
|
||||
"Test loading/saving a cache (filename)\n", argv[0]);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if ((ret = blkid_get_cache(&cache, bb_dev_null)) != 0) {
|
||||
fprintf(stderr, "%s: error creating cache (%d)\n",
|
||||
argv[0], ret);
|
||||
exit(1);
|
||||
}
|
||||
if ((ret = blkid_probe_all(cache)) < 0) {
|
||||
fprintf(stderr, "error (%d) probing devices\n", ret);
|
||||
exit(1);
|
||||
}
|
||||
cache->bic_filename = blkid_strdup(argv[1]);
|
||||
|
||||
if ((ret = blkid_flush_cache(cache)) < 0) {
|
||||
fprintf(stderr, "error (%d) saving cache\n", ret);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
blkid_put_cache(cache);
|
||||
|
||||
return ret;
|
||||
}
|
||||
#endif
|
432
e2fsprogs/old_e2fsprogs/blkid/tag.c
Normal file
432
e2fsprogs/old_e2fsprogs/blkid/tag.c
Normal file
@ -0,0 +1,432 @@
|
||||
/* vi: set sw=4 ts=4: */
|
||||
/*
|
||||
* tag.c - allocation/initialization/free routines for tag structs
|
||||
*
|
||||
* Copyright (C) 2001 Andreas Dilger
|
||||
* Copyright (C) 2003 Theodore Ts'o
|
||||
*
|
||||
* %Begin-Header%
|
||||
* This file may be redistributed under the terms of the
|
||||
* GNU Lesser General Public License.
|
||||
* %End-Header%
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include "blkidP.h"
|
||||
|
||||
static blkid_tag blkid_new_tag(void)
|
||||
{
|
||||
blkid_tag tag;
|
||||
|
||||
if (!(tag = (blkid_tag) calloc(1, sizeof(struct blkid_struct_tag))))
|
||||
return NULL;
|
||||
|
||||
INIT_LIST_HEAD(&tag->bit_tags);
|
||||
INIT_LIST_HEAD(&tag->bit_names);
|
||||
|
||||
return tag;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_BLKID_DEBUG
|
||||
void blkid_debug_dump_tag(blkid_tag tag)
|
||||
{
|
||||
if (!tag) {
|
||||
printf(" tag: NULL\n");
|
||||
return;
|
||||
}
|
||||
|
||||
printf(" tag: %s=\"%s\"\n", tag->bit_name, tag->bit_val);
|
||||
}
|
||||
#endif
|
||||
|
||||
void blkid_free_tag(blkid_tag tag)
|
||||
{
|
||||
if (!tag)
|
||||
return;
|
||||
|
||||
DBG(DEBUG_TAG, printf(" freeing tag %s=%s\n", tag->bit_name,
|
||||
tag->bit_val ? tag->bit_val : "(NULL)"));
|
||||
DBG(DEBUG_TAG, blkid_debug_dump_tag(tag));
|
||||
|
||||
list_del(&tag->bit_tags); /* list of tags for this device */
|
||||
list_del(&tag->bit_names); /* list of tags with this type */
|
||||
|
||||
free(tag->bit_name);
|
||||
free(tag->bit_val);
|
||||
free(tag);
|
||||
}
|
||||
|
||||
/*
|
||||
* Find the desired tag on a device. If value is NULL, then the
|
||||
* first such tag is returned, otherwise return only exact tag if found.
|
||||
*/
|
||||
blkid_tag blkid_find_tag_dev(blkid_dev dev, const char *type)
|
||||
{
|
||||
struct list_head *p;
|
||||
|
||||
if (!dev || !type)
|
||||
return NULL;
|
||||
|
||||
list_for_each(p, &dev->bid_tags) {
|
||||
blkid_tag tmp = list_entry(p, struct blkid_struct_tag,
|
||||
bit_tags);
|
||||
|
||||
if (!strcmp(tmp->bit_name, type))
|
||||
return tmp;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* Find the desired tag type in the cache.
|
||||
* We return the head tag for this tag type.
|
||||
*/
|
||||
static blkid_tag blkid_find_head_cache(blkid_cache cache, const char *type)
|
||||
{
|
||||
blkid_tag head = NULL, tmp;
|
||||
struct list_head *p;
|
||||
|
||||
if (!cache || !type)
|
||||
return NULL;
|
||||
|
||||
list_for_each(p, &cache->bic_tags) {
|
||||
tmp = list_entry(p, struct blkid_struct_tag, bit_tags);
|
||||
if (!strcmp(tmp->bit_name, type)) {
|
||||
DBG(DEBUG_TAG,
|
||||
printf(" found cache tag head %s\n", type));
|
||||
head = tmp;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return head;
|
||||
}
|
||||
|
||||
/*
|
||||
* Set a tag on an existing device.
|
||||
*
|
||||
* If value is NULL, then delete the tagsfrom the device.
|
||||
*/
|
||||
int blkid_set_tag(blkid_dev dev, const char *name,
|
||||
const char *value, const int vlength)
|
||||
{
|
||||
blkid_tag t = 0, head = 0;
|
||||
char *val = 0;
|
||||
|
||||
if (!dev || !name)
|
||||
return -BLKID_ERR_PARAM;
|
||||
|
||||
if (!(val = blkid_strndup(value, vlength)) && value)
|
||||
return -BLKID_ERR_MEM;
|
||||
t = blkid_find_tag_dev(dev, name);
|
||||
if (!value) {
|
||||
blkid_free_tag(t);
|
||||
} else if (t) {
|
||||
if (!strcmp(t->bit_val, val)) {
|
||||
/* Same thing, exit */
|
||||
free(val);
|
||||
return 0;
|
||||
}
|
||||
free(t->bit_val);
|
||||
t->bit_val = val;
|
||||
} else {
|
||||
/* Existing tag not present, add to device */
|
||||
if (!(t = blkid_new_tag()))
|
||||
goto errout;
|
||||
t->bit_name = blkid_strdup(name);
|
||||
t->bit_val = val;
|
||||
t->bit_dev = dev;
|
||||
|
||||
list_add_tail(&t->bit_tags, &dev->bid_tags);
|
||||
|
||||
if (dev->bid_cache) {
|
||||
head = blkid_find_head_cache(dev->bid_cache,
|
||||
t->bit_name);
|
||||
if (!head) {
|
||||
head = blkid_new_tag();
|
||||
if (!head)
|
||||
goto errout;
|
||||
|
||||
DBG(DEBUG_TAG,
|
||||
printf(" creating new cache tag head %s\n", name));
|
||||
head->bit_name = blkid_strdup(name);
|
||||
if (!head->bit_name)
|
||||
goto errout;
|
||||
list_add_tail(&head->bit_tags,
|
||||
&dev->bid_cache->bic_tags);
|
||||
}
|
||||
list_add_tail(&t->bit_names, &head->bit_names);
|
||||
}
|
||||
}
|
||||
|
||||
/* Link common tags directly to the device struct */
|
||||
if (!strcmp(name, "TYPE"))
|
||||
dev->bid_type = val;
|
||||
else if (!strcmp(name, "LABEL"))
|
||||
dev->bid_label = val;
|
||||
else if (!strcmp(name, "UUID"))
|
||||
dev->bid_uuid = val;
|
||||
|
||||
if (dev->bid_cache)
|
||||
dev->bid_cache->bic_flags |= BLKID_BIC_FL_CHANGED;
|
||||
return 0;
|
||||
|
||||
errout:
|
||||
blkid_free_tag(t);
|
||||
if (!t)
|
||||
free(val);
|
||||
blkid_free_tag(head);
|
||||
return -BLKID_ERR_MEM;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Parse a "NAME=value" string. This is slightly different than
|
||||
* parse_token, because that will end an unquoted value at a space, while
|
||||
* this will assume that an unquoted value is the rest of the token (e.g.
|
||||
* if we are passed an already quoted string from the command-line we don't
|
||||
* have to both quote and escape quote so that the quotes make it to
|
||||
* us).
|
||||
*
|
||||
* Returns 0 on success, and -1 on failure.
|
||||
*/
|
||||
int blkid_parse_tag_string(const char *token, char **ret_type, char **ret_val)
|
||||
{
|
||||
char *name, *value, *cp;
|
||||
|
||||
DBG(DEBUG_TAG, printf("trying to parse '%s' as a tag\n", token));
|
||||
|
||||
if (!token || !(cp = strchr(token, '=')))
|
||||
return -1;
|
||||
|
||||
name = blkid_strdup(token);
|
||||
if (!name)
|
||||
return -1;
|
||||
value = name + (cp - token);
|
||||
*value++ = '\0';
|
||||
if (*value == '"' || *value == '\'') {
|
||||
char c = *value++;
|
||||
if (!(cp = strrchr(value, c)))
|
||||
goto errout; /* missing closing quote */
|
||||
*cp = '\0';
|
||||
}
|
||||
value = blkid_strdup(value);
|
||||
if (!value)
|
||||
goto errout;
|
||||
|
||||
*ret_type = name;
|
||||
*ret_val = value;
|
||||
|
||||
return 0;
|
||||
|
||||
errout:
|
||||
free(name);
|
||||
return -1;
|
||||
}
|
||||
|
||||
/*
|
||||
* Tag iteration routines for the public libblkid interface.
|
||||
*
|
||||
* These routines do not expose the list.h implementation, which are a
|
||||
* contamination of the namespace, and which force us to reveal far, far
|
||||
* too much of our internal implemenation. I'm not convinced I want
|
||||
* to keep list.h in the long term, anyway. It's fine for kernel
|
||||
* programming, but performance is not the #1 priority for this
|
||||
* library, and I really don't like the tradeoff of type-safety for
|
||||
* performance for this application. [tytso:20030125.2007EST]
|
||||
*/
|
||||
|
||||
/*
|
||||
* This series of functions iterate over all tags in a device
|
||||
*/
|
||||
#define TAG_ITERATE_MAGIC 0x01a5284c
|
||||
|
||||
struct blkid_struct_tag_iterate {
|
||||
int magic;
|
||||
blkid_dev dev;
|
||||
struct list_head *p;
|
||||
};
|
||||
|
||||
blkid_tag_iterate blkid_tag_iterate_begin(blkid_dev dev)
|
||||
{
|
||||
blkid_tag_iterate iter;
|
||||
|
||||
iter = xmalloc(sizeof(struct blkid_struct_tag_iterate));
|
||||
iter->magic = TAG_ITERATE_MAGIC;
|
||||
iter->dev = dev;
|
||||
iter->p = dev->bid_tags.next;
|
||||
return iter;
|
||||
}
|
||||
|
||||
/*
|
||||
* Return 0 on success, -1 on error
|
||||
*/
|
||||
extern int blkid_tag_next(blkid_tag_iterate iter,
|
||||
const char **type, const char **value)
|
||||
{
|
||||
blkid_tag tag;
|
||||
|
||||
*type = 0;
|
||||
*value = 0;
|
||||
if (!iter || iter->magic != TAG_ITERATE_MAGIC ||
|
||||
iter->p == &iter->dev->bid_tags)
|
||||
return -1;
|
||||
tag = list_entry(iter->p, struct blkid_struct_tag, bit_tags);
|
||||
*type = tag->bit_name;
|
||||
*value = tag->bit_val;
|
||||
iter->p = iter->p->next;
|
||||
return 0;
|
||||
}
|
||||
|
||||
void blkid_tag_iterate_end(blkid_tag_iterate iter)
|
||||
{
|
||||
if (!iter || iter->magic != TAG_ITERATE_MAGIC)
|
||||
return;
|
||||
iter->magic = 0;
|
||||
free(iter);
|
||||
}
|
||||
|
||||
/*
|
||||
* This function returns a device which matches a particular
|
||||
* type/value pair. If there is more than one device that matches the
|
||||
* search specification, it returns the one with the highest priority
|
||||
* value. This allows us to give preference to EVMS or LVM devices.
|
||||
*
|
||||
* XXX there should also be an interface which uses an iterator so we
|
||||
* can get all of the devices which match a type/value search parameter.
|
||||
*/
|
||||
extern blkid_dev blkid_find_dev_with_tag(blkid_cache cache,
|
||||
const char *type,
|
||||
const char *value)
|
||||
{
|
||||
blkid_tag head;
|
||||
blkid_dev dev;
|
||||
int pri;
|
||||
struct list_head *p;
|
||||
|
||||
if (!cache || !type || !value)
|
||||
return NULL;
|
||||
|
||||
blkid_read_cache(cache);
|
||||
|
||||
DBG(DEBUG_TAG, printf("looking for %s=%s in cache\n", type, value));
|
||||
|
||||
try_again:
|
||||
pri = -1;
|
||||
dev = 0;
|
||||
head = blkid_find_head_cache(cache, type);
|
||||
|
||||
if (head) {
|
||||
list_for_each(p, &head->bit_names) {
|
||||
blkid_tag tmp = list_entry(p, struct blkid_struct_tag,
|
||||
bit_names);
|
||||
|
||||
if (!strcmp(tmp->bit_val, value) &&
|
||||
tmp->bit_dev->bid_pri > pri) {
|
||||
dev = tmp->bit_dev;
|
||||
pri = dev->bid_pri;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (dev && !(dev->bid_flags & BLKID_BID_FL_VERIFIED)) {
|
||||
dev = blkid_verify(cache, dev);
|
||||
if (dev && (dev->bid_flags & BLKID_BID_FL_VERIFIED))
|
||||
goto try_again;
|
||||
}
|
||||
|
||||
if (!dev && !(cache->bic_flags & BLKID_BIC_FL_PROBED)) {
|
||||
if (blkid_probe_all(cache) < 0)
|
||||
return NULL;
|
||||
goto try_again;
|
||||
}
|
||||
return dev;
|
||||
}
|
||||
|
||||
#ifdef TEST_PROGRAM
|
||||
#ifdef HAVE_GETOPT_H
|
||||
#include <getopt.h>
|
||||
#else
|
||||
extern char *optarg;
|
||||
extern int optind;
|
||||
#endif
|
||||
|
||||
void usage(char *prog)
|
||||
{
|
||||
fprintf(stderr, "Usage: %s [-f blkid_file] [-m debug_mask] device "
|
||||
"[type value]\n",
|
||||
prog);
|
||||
fprintf(stderr, "\tList all tags for a device and exit\n", prog);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
blkid_tag_iterate iter;
|
||||
blkid_cache cache = NULL;
|
||||
blkid_dev dev;
|
||||
int c, ret, found;
|
||||
int flags = BLKID_DEV_FIND;
|
||||
char *tmp;
|
||||
char *file = NULL;
|
||||
char *devname = NULL;
|
||||
char *search_type = NULL;
|
||||
char *search_value = NULL;
|
||||
const char *type, *value;
|
||||
|
||||
while ((c = getopt (argc, argv, "m:f:")) != EOF)
|
||||
switch (c) {
|
||||
case 'f':
|
||||
file = optarg;
|
||||
break;
|
||||
case 'm':
|
||||
blkid_debug_mask = strtoul (optarg, &tmp, 0);
|
||||
if (*tmp) {
|
||||
fprintf(stderr, "Invalid debug mask: %d\n",
|
||||
optarg);
|
||||
exit(1);
|
||||
}
|
||||
break;
|
||||
case '?':
|
||||
usage(argv[0]);
|
||||
}
|
||||
if (argc > optind)
|
||||
devname = argv[optind++];
|
||||
if (argc > optind)
|
||||
search_type = argv[optind++];
|
||||
if (argc > optind)
|
||||
search_value = argv[optind++];
|
||||
if (!devname || (argc != optind))
|
||||
usage(argv[0]);
|
||||
|
||||
if ((ret = blkid_get_cache(&cache, file)) != 0) {
|
||||
fprintf(stderr, "%s: error creating cache (%d)\n",
|
||||
argv[0], ret);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
dev = blkid_get_dev(cache, devname, flags);
|
||||
if (!dev) {
|
||||
fprintf(stderr, "%s: cannot find device in blkid cache\n");
|
||||
exit(1);
|
||||
}
|
||||
if (search_type) {
|
||||
found = blkid_dev_has_tag(dev, search_type, search_value);
|
||||
printf("Device %s: (%s, %s) %s\n", blkid_dev_devname(dev),
|
||||
search_type, search_value ? search_value : "NULL",
|
||||
found ? "FOUND" : "NOT FOUND");
|
||||
return !found;
|
||||
}
|
||||
printf("Device %s...\n", blkid_dev_devname(dev));
|
||||
|
||||
iter = blkid_tag_iterate_begin(dev);
|
||||
while (blkid_tag_next(iter, &type, &value) == 0) {
|
||||
printf("\tTag %s has value %s\n", type, value);
|
||||
}
|
||||
blkid_tag_iterate_end(iter);
|
||||
|
||||
blkid_put_cache(cache);
|
||||
return 0;
|
||||
}
|
||||
#endif
|
219
e2fsprogs/old_e2fsprogs/chattr.c
Normal file
219
e2fsprogs/old_e2fsprogs/chattr.c
Normal file
@ -0,0 +1,219 @@
|
||||
/* vi: set sw=4 ts=4: */
|
||||
/*
|
||||
* chattr.c - Change file attributes on an ext2 file system
|
||||
*
|
||||
* Copyright (C) 1993, 1994 Remy Card <card@masi.ibp.fr>
|
||||
* Laboratoire MASI, Institut Blaise Pascal
|
||||
* Universite Pierre et Marie Curie (Paris VI)
|
||||
*
|
||||
* This file can be redistributed under the terms of the GNU General
|
||||
* Public License
|
||||
*/
|
||||
|
||||
/*
|
||||
* History:
|
||||
* 93/10/30 - Creation
|
||||
* 93/11/13 - Replace stat() calls by lstat() to avoid loops
|
||||
* 94/02/27 - Integrated in Ted's distribution
|
||||
* 98/12/29 - Ignore symlinks when working recursively (G M Sipe)
|
||||
* 98/12/29 - Display version info only when -V specified (G M Sipe)
|
||||
*/
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <dirent.h>
|
||||
#include <fcntl.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
#include <sys/param.h>
|
||||
#include <sys/stat.h>
|
||||
#include "ext2fs/ext2_fs.h"
|
||||
|
||||
#ifdef __GNUC__
|
||||
# define EXT2FS_ATTR(x) __attribute__(x)
|
||||
#else
|
||||
# define EXT2FS_ATTR(x)
|
||||
#endif
|
||||
|
||||
#include "e2fsbb.h"
|
||||
#include "e2p/e2p.h"
|
||||
|
||||
#define OPT_ADD 1
|
||||
#define OPT_REM 2
|
||||
#define OPT_SET 4
|
||||
#define OPT_SET_VER 8
|
||||
static int flags;
|
||||
static int recursive;
|
||||
|
||||
static unsigned long version;
|
||||
|
||||
static unsigned long af;
|
||||
static unsigned long rf;
|
||||
static unsigned long sf;
|
||||
|
||||
struct flags_char {
|
||||
unsigned long flag;
|
||||
char optchar;
|
||||
};
|
||||
|
||||
static const struct flags_char flags_array[] = {
|
||||
{ EXT2_NOATIME_FL, 'A' },
|
||||
{ EXT2_SYNC_FL, 'S' },
|
||||
{ EXT2_DIRSYNC_FL, 'D' },
|
||||
{ EXT2_APPEND_FL, 'a' },
|
||||
{ EXT2_COMPR_FL, 'c' },
|
||||
{ EXT2_NODUMP_FL, 'd' },
|
||||
{ EXT2_IMMUTABLE_FL, 'i' },
|
||||
{ EXT3_JOURNAL_DATA_FL, 'j' },
|
||||
{ EXT2_SECRM_FL, 's' },
|
||||
{ EXT2_UNRM_FL, 'u' },
|
||||
{ EXT2_NOTAIL_FL, 't' },
|
||||
{ EXT2_TOPDIR_FL, 'T' },
|
||||
{ 0, 0 }
|
||||
};
|
||||
|
||||
static unsigned long get_flag(char c)
|
||||
{
|
||||
const struct flags_char *fp;
|
||||
for (fp = flags_array; fp->flag; fp++)
|
||||
if (fp->optchar == c)
|
||||
return fp->flag;
|
||||
bb_show_usage();
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int decode_arg(char *arg)
|
||||
{
|
||||
unsigned long *fl;
|
||||
char opt = *arg++;
|
||||
|
||||
if (opt == '-') {
|
||||
flags |= OPT_REM;
|
||||
fl = &rf;
|
||||
} else if (opt == '+') {
|
||||
flags |= OPT_ADD;
|
||||
fl = ⁡
|
||||
} else if (opt == '=') {
|
||||
flags |= OPT_SET;
|
||||
fl = &sf;
|
||||
} else
|
||||
return EOF;
|
||||
|
||||
for (; *arg ; ++arg)
|
||||
(*fl) |= get_flag(*arg);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int chattr_dir_proc(const char *, struct dirent *, void *);
|
||||
|
||||
static void change_attributes(const char * name)
|
||||
{
|
||||
unsigned long fsflags;
|
||||
struct stat st;
|
||||
|
||||
if (lstat(name, &st) == -1) {
|
||||
bb_error_msg("stat %s failed", name);
|
||||
return;
|
||||
}
|
||||
if (S_ISLNK(st.st_mode) && recursive)
|
||||
return;
|
||||
|
||||
/* Don't try to open device files, fifos etc. We probably
|
||||
* ought to display an error if the file was explicitly given
|
||||
* on the command line (whether or not recursive was
|
||||
* requested). */
|
||||
if (!S_ISREG(st.st_mode) && !S_ISLNK(st.st_mode) && !S_ISDIR(st.st_mode))
|
||||
return;
|
||||
|
||||
if (flags & OPT_SET_VER)
|
||||
if (fsetversion(name, version) == -1)
|
||||
bb_error_msg("setting version on %s", name);
|
||||
|
||||
if (flags & OPT_SET) {
|
||||
fsflags = sf;
|
||||
} else {
|
||||
if (fgetflags(name, &fsflags) == -1) {
|
||||
bb_error_msg("reading flags on %s", name);
|
||||
goto skip_setflags;
|
||||
}
|
||||
if (flags & OPT_REM)
|
||||
fsflags &= ~rf;
|
||||
if (flags & OPT_ADD)
|
||||
fsflags |= af;
|
||||
if (!S_ISDIR(st.st_mode))
|
||||
fsflags &= ~EXT2_DIRSYNC_FL;
|
||||
}
|
||||
if (fsetflags(name, fsflags) == -1)
|
||||
bb_error_msg("setting flags on %s", name);
|
||||
|
||||
skip_setflags:
|
||||
if (S_ISDIR(st.st_mode) && recursive)
|
||||
iterate_on_dir(name, chattr_dir_proc, NULL);
|
||||
}
|
||||
|
||||
static int chattr_dir_proc(const char *dir_name, struct dirent *de,
|
||||
void *private EXT2FS_ATTR((unused)))
|
||||
{
|
||||
/*if (strcmp(de->d_name, ".") || strcmp(de->d_name, "..")) {*/
|
||||
if (de->d_name[0] == '.'
|
||||
&& (!de->d_name[1] || (de->d_name[1] == '.' && !de->d_name[2]))
|
||||
) {
|
||||
char *path = concat_subpath_file(dir_name, de->d_name);
|
||||
if (path) {
|
||||
change_attributes(path);
|
||||
free(path);
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int chattr_main(int argc, char **argv)
|
||||
{
|
||||
int i;
|
||||
char *arg;
|
||||
|
||||
/* parse the args */
|
||||
for (i = 1; i < argc; ++i) {
|
||||
arg = argv[i];
|
||||
|
||||
/* take care of -R and -v <version> */
|
||||
if (arg[0] == '-') {
|
||||
if (arg[1] == 'R' && arg[2] == '\0') {
|
||||
recursive = 1;
|
||||
continue;
|
||||
} else if (arg[1] == 'v' && arg[2] == '\0') {
|
||||
char *tmp;
|
||||
++i;
|
||||
if (i >= argc)
|
||||
bb_show_usage();
|
||||
version = strtol(argv[i], &tmp, 0);
|
||||
if (*tmp)
|
||||
bb_error_msg_and_die("bad version '%s'", arg);
|
||||
flags |= OPT_SET_VER;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
if (decode_arg(arg) == EOF)
|
||||
break;
|
||||
}
|
||||
|
||||
/* run sanity checks on all the arguments given us */
|
||||
if (i >= argc)
|
||||
bb_show_usage();
|
||||
if ((flags & OPT_SET) && ((flags & OPT_ADD) || (flags & OPT_REM)))
|
||||
bb_error_msg_and_die("= is incompatible with - and +");
|
||||
if ((rf & af) != 0)
|
||||
bb_error_msg_and_die("Can't set and unset a flag");
|
||||
if (!flags)
|
||||
bb_error_msg_and_die("Must use '-v', =, - or +");
|
||||
|
||||
/* now run chattr on all the files passed to us */
|
||||
while (i < argc)
|
||||
change_attributes(argv[i++]);
|
||||
|
||||
return EXIT_SUCCESS;
|
||||
}
|
43
e2fsprogs/old_e2fsprogs/e2fsbb.h
Normal file
43
e2fsprogs/old_e2fsprogs/e2fsbb.h
Normal file
@ -0,0 +1,43 @@
|
||||
/* vi: set sw=4 ts=4: */
|
||||
/*
|
||||
* File: e2fsbb.h
|
||||
*
|
||||
* Redefine a bunch of e2fsprogs stuff to use busybox routines
|
||||
* instead. This makes upgrade between e2fsprogs versions easy.
|
||||
*/
|
||||
|
||||
#ifndef __E2FSBB_H__
|
||||
#define __E2FSBB_H__ 1
|
||||
|
||||
#include "libbb.h"
|
||||
|
||||
/* version we've last synced against */
|
||||
#define E2FSPROGS_VERSION "1.38"
|
||||
#define E2FSPROGS_DATE "30-Jun-2005"
|
||||
|
||||
typedef long errcode_t;
|
||||
#define ERRCODE_RANGE 8
|
||||
#define error_message(code) strerror((int) (code & ((1<<ERRCODE_RANGE)-1)))
|
||||
|
||||
/* header defines */
|
||||
#define ENABLE_HTREE 1
|
||||
#define HAVE_ERRNO_H 1
|
||||
#define HAVE_EXT2_IOCTLS 1
|
||||
#define HAVE_LINUX_FD_H 1
|
||||
#define HAVE_MNTENT_H 1
|
||||
#define HAVE_NETINET_IN_H 1
|
||||
#define HAVE_NET_IF_H 1
|
||||
#define HAVE_SYS_IOCTL_H 1
|
||||
#define HAVE_SYS_MOUNT_H 1
|
||||
#define HAVE_SYS_QUEUE_H 1
|
||||
#define HAVE_SYS_STAT_H 1
|
||||
#define HAVE_SYS_TYPES_H 1
|
||||
#define HAVE_UNISTD_H 1
|
||||
|
||||
/* Endianness */
|
||||
#if BB_BIG_ENDIAN
|
||||
#define ENABLE_SWAPFS 1
|
||||
#define WORDS_BIGENDIAN 1
|
||||
#endif
|
||||
|
||||
#endif /* __E2FSBB_H__ */
|
13552
e2fsprogs/old_e2fsprogs/e2fsck.c
Normal file
13552
e2fsprogs/old_e2fsprogs/e2fsck.c
Normal file
File diff suppressed because it is too large
Load Diff
640
e2fsprogs/old_e2fsprogs/e2fsck.h
Normal file
640
e2fsprogs/old_e2fsprogs/e2fsck.h
Normal file
@ -0,0 +1,640 @@
|
||||
/* vi: set sw=4 ts=4: */
|
||||
#include <sys/types.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <stdlib.h>
|
||||
#include <time.h>
|
||||
#include <fcntl.h>
|
||||
#include <ctype.h>
|
||||
#include <setjmp.h>
|
||||
#include <errno.h>
|
||||
#include <getopt.h>
|
||||
#include <limits.h>
|
||||
#include <stddef.h>
|
||||
#include <assert.h>
|
||||
#include <signal.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/resource.h>
|
||||
#include <sys/param.h>
|
||||
#include <sys/mount.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <termios.h>
|
||||
#include <mntent.h>
|
||||
#include <dirent.h>
|
||||
#include "ext2fs/kernel-list.h"
|
||||
#include <sys/types.h>
|
||||
#include <linux/types.h>
|
||||
|
||||
/*
|
||||
* Now pull in the real linux/jfs.h definitions.
|
||||
*/
|
||||
#include "ext2fs/kernel-jbd.h"
|
||||
|
||||
|
||||
|
||||
#include "fsck.h"
|
||||
|
||||
#include "ext2fs/ext2_fs.h"
|
||||
#include "blkid/blkid.h"
|
||||
#include "ext2fs/ext2_ext_attr.h"
|
||||
#include "uuid/uuid.h"
|
||||
#include "busybox.h"
|
||||
|
||||
#ifdef HAVE_CONIO_H
|
||||
#undef HAVE_TERMIOS_H
|
||||
#include <conio.h>
|
||||
#define read_a_char() getch()
|
||||
#else
|
||||
#ifdef HAVE_TERMIOS_H
|
||||
#include <termios.h>
|
||||
#endif
|
||||
#endif
|
||||
|
||||
|
||||
/*
|
||||
* The last ext2fs revision level that this version of e2fsck is able to
|
||||
* support
|
||||
*/
|
||||
#define E2FSCK_CURRENT_REV 1
|
||||
|
||||
/* Used by the region allocation code */
|
||||
typedef __u32 region_addr_t;
|
||||
typedef struct region_struct *region_t;
|
||||
|
||||
struct dx_dirblock_info {
|
||||
int type;
|
||||
blk_t phys;
|
||||
int flags;
|
||||
blk_t parent;
|
||||
ext2_dirhash_t min_hash;
|
||||
ext2_dirhash_t max_hash;
|
||||
ext2_dirhash_t node_min_hash;
|
||||
ext2_dirhash_t node_max_hash;
|
||||
};
|
||||
|
||||
/*
|
||||
These defines are used in the type field of dx_dirblock_info
|
||||
*/
|
||||
|
||||
#define DX_DIRBLOCK_ROOT 1
|
||||
#define DX_DIRBLOCK_LEAF 2
|
||||
#define DX_DIRBLOCK_NODE 3
|
||||
|
||||
|
||||
/*
|
||||
The following defines are used in the 'flags' field of a dx_dirblock_info
|
||||
*/
|
||||
#define DX_FLAG_REFERENCED 1
|
||||
#define DX_FLAG_DUP_REF 2
|
||||
#define DX_FLAG_FIRST 4
|
||||
#define DX_FLAG_LAST 8
|
||||
|
||||
/*
|
||||
* E2fsck options
|
||||
*/
|
||||
#define E2F_OPT_READONLY 0x0001
|
||||
#define E2F_OPT_PREEN 0x0002
|
||||
#define E2F_OPT_YES 0x0004
|
||||
#define E2F_OPT_NO 0x0008
|
||||
#define E2F_OPT_TIME 0x0010
|
||||
#define E2F_OPT_CHECKBLOCKS 0x0040
|
||||
#define E2F_OPT_DEBUG 0x0080
|
||||
#define E2F_OPT_FORCE 0x0100
|
||||
#define E2F_OPT_WRITECHECK 0x0200
|
||||
#define E2F_OPT_COMPRESS_DIRS 0x0400
|
||||
|
||||
/*
|
||||
* E2fsck flags
|
||||
*/
|
||||
#define E2F_FLAG_ABORT 0x0001 /* Abort signaled */
|
||||
#define E2F_FLAG_CANCEL 0x0002 /* Cancel signaled */
|
||||
#define E2F_FLAG_SIGNAL_MASK 0x0003
|
||||
#define E2F_FLAG_RESTART 0x0004 /* Restart signaled */
|
||||
|
||||
#define E2F_FLAG_SETJMP_OK 0x0010 /* Setjmp valid for abort */
|
||||
|
||||
#define E2F_FLAG_PROG_BAR 0x0020 /* Progress bar on screen */
|
||||
#define E2F_FLAG_PROG_SUPPRESS 0x0040 /* Progress suspended */
|
||||
#define E2F_FLAG_JOURNAL_INODE 0x0080 /* Create a new ext3 journal inode */
|
||||
#define E2F_FLAG_SB_SPECIFIED 0x0100 /* The superblock was explicitly
|
||||
* specified by the user */
|
||||
#define E2F_FLAG_RESTARTED 0x0200 /* E2fsck has been restarted */
|
||||
#define E2F_FLAG_RESIZE_INODE 0x0400 /* Request to recreate resize inode */
|
||||
|
||||
|
||||
/*Don't know where these come from*/
|
||||
#define READ 0
|
||||
#define WRITE 1
|
||||
#define cpu_to_be32(n) htonl(n)
|
||||
#define be32_to_cpu(n) ntohl(n)
|
||||
|
||||
/*
|
||||
* We define a set of "latch groups"; these are problems which are
|
||||
* handled as a set. The user answers once for a particular latch
|
||||
* group.
|
||||
*/
|
||||
#define PR_LATCH_MASK 0x0ff0 /* Latch mask */
|
||||
#define PR_LATCH_BLOCK 0x0010 /* Latch for illegal blocks (pass 1) */
|
||||
#define PR_LATCH_BBLOCK 0x0020 /* Latch for bad block inode blocks (pass 1) */
|
||||
#define PR_LATCH_IBITMAP 0x0030 /* Latch for pass 5 inode bitmap proc. */
|
||||
#define PR_LATCH_BBITMAP 0x0040 /* Latch for pass 5 inode bitmap proc. */
|
||||
#define PR_LATCH_RELOC 0x0050 /* Latch for superblock relocate hint */
|
||||
#define PR_LATCH_DBLOCK 0x0060 /* Latch for pass 1b dup block headers */
|
||||
#define PR_LATCH_LOW_DTIME 0x0070 /* Latch for pass1 orphaned list refugees */
|
||||
#define PR_LATCH_TOOBIG 0x0080 /* Latch for file to big errors */
|
||||
#define PR_LATCH_OPTIMIZE_DIR 0x0090 /* Latch for optimize directories */
|
||||
|
||||
#define PR_LATCH(x) ((((x) & PR_LATCH_MASK) >> 4) - 1)
|
||||
|
||||
/*
|
||||
* Latch group descriptor flags
|
||||
*/
|
||||
#define PRL_YES 0x0001 /* Answer yes */
|
||||
#define PRL_NO 0x0002 /* Answer no */
|
||||
#define PRL_LATCHED 0x0004 /* The latch group is latched */
|
||||
#define PRL_SUPPRESS 0x0008 /* Suppress all latch group questions */
|
||||
|
||||
#define PRL_VARIABLE 0x000f /* All the flags that need to be reset */
|
||||
|
||||
/*
|
||||
* Pre-Pass 1 errors
|
||||
*/
|
||||
|
||||
#define PR_0_BB_NOT_GROUP 0x000001 /* Block bitmap not in group */
|
||||
#define PR_0_IB_NOT_GROUP 0x000002 /* Inode bitmap not in group */
|
||||
#define PR_0_ITABLE_NOT_GROUP 0x000003 /* Inode table not in group */
|
||||
#define PR_0_SB_CORRUPT 0x000004 /* Superblock corrupt */
|
||||
#define PR_0_FS_SIZE_WRONG 0x000005 /* Filesystem size is wrong */
|
||||
#define PR_0_NO_FRAGMENTS 0x000006 /* Fragments not supported */
|
||||
#define PR_0_BLOCKS_PER_GROUP 0x000007 /* Bad blocks_per_group */
|
||||
#define PR_0_FIRST_DATA_BLOCK 0x000008 /* Bad first_data_block */
|
||||
#define PR_0_ADD_UUID 0x000009 /* Adding UUID to filesystem */
|
||||
#define PR_0_RELOCATE_HINT 0x00000A /* Relocate hint */
|
||||
#define PR_0_MISC_CORRUPT_SUPER 0x00000B /* Miscellaneous superblock corruption */
|
||||
#define PR_0_GETSIZE_ERROR 0x00000C /* Error determing physical device size of filesystem */
|
||||
#define PR_0_INODE_COUNT_WRONG 0x00000D /* Inode count in the superblock incorrect */
|
||||
#define PR_0_HURD_CLEAR_FILETYPE 0x00000E /* The Hurd does not support the filetype feature */
|
||||
#define PR_0_JOURNAL_BAD_INODE 0x00000F /* The Hurd does not support the filetype feature */
|
||||
#define PR_0_JOURNAL_UNSUPP_MULTIFS 0x000010 /* The external journal has multiple filesystems (which we can't handle yet) */
|
||||
#define PR_0_CANT_FIND_JOURNAL 0x000011 /* Can't find external journal */
|
||||
#define PR_0_EXT_JOURNAL_BAD_SUPER 0x000012/* External journal has bad superblock */
|
||||
#define PR_0_JOURNAL_BAD_UUID 0x000013 /* Superblock has a bad journal UUID */
|
||||
#define PR_0_JOURNAL_UNSUPP_SUPER 0x000014 /* Journal has an unknown superblock type */
|
||||
#define PR_0_JOURNAL_BAD_SUPER 0x000015 /* Journal superblock is corrupt */
|
||||
#define PR_0_JOURNAL_HAS_JOURNAL 0x000016 /* Journal superblock is corrupt */
|
||||
#define PR_0_JOURNAL_RECOVER_SET 0x000017 /* Superblock has recovery flag set but no journal */
|
||||
#define PR_0_JOURNAL_RECOVERY_CLEAR 0x000018 /* Journal has data, but recovery flag is clear */
|
||||
#define PR_0_JOURNAL_RESET_JOURNAL 0x000019 /* Ask if we should clear the journal */
|
||||
#define PR_0_FS_REV_LEVEL 0x00001A /* Filesystem revision is 0, but feature flags are set */
|
||||
#define PR_0_ORPHAN_CLEAR_INODE 0x000020 /* Clearing orphan inode */
|
||||
#define PR_0_ORPHAN_ILLEGAL_BLOCK_NUM 0x000021 /* Illegal block found in orphaned inode */
|
||||
#define PR_0_ORPHAN_ALREADY_CLEARED_BLOCK 0x000022 /* Already cleared block found in orphaned inode */
|
||||
#define PR_0_ORPHAN_ILLEGAL_HEAD_INODE 0x000023 /* Illegal orphan inode in superblock */
|
||||
#define PR_0_ORPHAN_ILLEGAL_INODE 0x000024 /* Illegal inode in orphaned inode list */
|
||||
#define PR_0_JOURNAL_UNSUPP_ROCOMPAT 0x000025 /* Journal has unsupported read-only feature - abort */
|
||||
#define PR_0_JOURNAL_UNSUPP_INCOMPAT 0x000026 /* Journal has unsupported incompatible feature - abort */
|
||||
#define PR_0_JOURNAL_UNSUPP_VERSION 0x000027 /* Journal has unsupported version number */
|
||||
#define PR_0_MOVE_JOURNAL 0x000028 /* Moving journal to hidden file */
|
||||
#define PR_0_ERR_MOVE_JOURNAL 0x000029 /* Error moving journal */
|
||||
#define PR_0_CLEAR_V2_JOURNAL 0x00002A /* Clearing V2 journal superblock */
|
||||
#define PR_0_JOURNAL_RUN 0x00002B /* Run journal anyway */
|
||||
#define PR_0_JOURNAL_RUN_DEFAULT 0x00002C /* Run journal anyway by default */
|
||||
#define PR_0_BACKUP_JNL 0x00002D /* Backup journal inode blocks */
|
||||
#define PR_0_NONZERO_RESERVED_GDT_BLOCKS 0x00002E /* Reserved blocks w/o resize_inode */
|
||||
#define PR_0_CLEAR_RESIZE_INODE 0x00002F /* Resize_inode not enabled, but resize inode is non-zero */
|
||||
#define PR_0_RESIZE_INODE_INVALID 0x000030 /* Resize inode invalid */
|
||||
|
||||
/*
|
||||
* Pass 1 errors
|
||||
*/
|
||||
|
||||
#define PR_1_PASS_HEADER 0x010000 /* Pass 1: Checking inodes, blocks, and sizes */
|
||||
#define PR_1_ROOT_NO_DIR 0x010001 /* Root directory is not an inode */
|
||||
#define PR_1_ROOT_DTIME 0x010002 /* Root directory has dtime set */
|
||||
#define PR_1_RESERVED_BAD_MODE 0x010003 /* Reserved inode has bad mode */
|
||||
#define PR_1_ZERO_DTIME 0x010004 /* Deleted inode has zero dtime */
|
||||
#define PR_1_SET_DTIME 0x010005 /* Inode in use, but dtime set */
|
||||
#define PR_1_ZERO_LENGTH_DIR 0x010006 /* Zero-length directory */
|
||||
#define PR_1_BB_CONFLICT 0x010007 /* Block bitmap conflicts with some other fs block */
|
||||
#define PR_1_IB_CONFLICT 0x010008 /* Inode bitmap conflicts with some other fs block */
|
||||
#define PR_1_ITABLE_CONFLICT 0x010009 /* Inode table conflicts with some other fs block */
|
||||
#define PR_1_BB_BAD_BLOCK 0x01000A /* Block bitmap is on a bad block */
|
||||
#define PR_1_IB_BAD_BLOCK 0x01000B /* Inode bitmap is on a bad block */
|
||||
#define PR_1_BAD_I_SIZE 0x01000C /* Inode has incorrect i_size */
|
||||
#define PR_1_BAD_I_BLOCKS 0x01000D /* Inode has incorrect i_blocks */
|
||||
#define PR_1_ILLEGAL_BLOCK_NUM 0x01000E /* Illegal block number in inode */
|
||||
#define PR_1_BLOCK_OVERLAPS_METADATA 0x01000F /* Block number overlaps fs metadata */
|
||||
#define PR_1_INODE_BLOCK_LATCH 0x010010 /* Inode has illegal blocks (latch question) */
|
||||
#define PR_1_TOO_MANY_BAD_BLOCKS 0x010011 /* Too many bad blocks in inode */
|
||||
#define PR_1_BB_ILLEGAL_BLOCK_NUM 0x010012 /* Illegal block number in bad block inode */
|
||||
#define PR_1_INODE_BBLOCK_LATCH 0x010013 /* Bad block inode has illegal blocks (latch question) */
|
||||
#define PR_1_DUP_BLOCKS_PREENSTOP 0x010014 /* Duplicate or bad blocks in use! */
|
||||
#define PR_1_BBINODE_BAD_METABLOCK 0x010015 /* Bad block used as bad block indirect block */
|
||||
#define PR_1_BBINODE_BAD_METABLOCK_PROMPT 0x010016 /* Inconsistency can't be fixed prompt */
|
||||
#define PR_1_BAD_PRIMARY_BLOCK 0x010017 /* Bad primary block */
|
||||
#define PR_1_BAD_PRIMARY_BLOCK_PROMPT 0x010018 /* Bad primary block prompt */
|
||||
#define PR_1_BAD_PRIMARY_SUPERBLOCK 0x010019 /* Bad primary superblock */
|
||||
#define PR_1_BAD_PRIMARY_GROUP_DESCRIPTOR 0x01001A /* Bad primary block group descriptors */
|
||||
#define PR_1_BAD_SUPERBLOCK 0x01001B /* Bad superblock in group */
|
||||
#define PR_1_BAD_GROUP_DESCRIPTORS 0x01001C /* Bad block group descriptors in group */
|
||||
#define PR_1_PROGERR_CLAIMED_BLOCK 0x01001D /* Block claimed for no reason */
|
||||
#define PR_1_RELOC_BLOCK_ALLOCATE 0x01001E /* Error allocating blocks for relocating metadata */
|
||||
#define PR_1_RELOC_MEMORY_ALLOCATE 0x01001F /* Error allocating block buffer during relocation process */
|
||||
#define PR_1_RELOC_FROM_TO 0x010020 /* Relocating metadata group information from X to Y */
|
||||
#define PR_1_RELOC_TO 0x010021 /* Relocating metatdata group information to X */
|
||||
#define PR_1_RELOC_READ_ERR 0x010022 /* Block read error during relocation process */
|
||||
#define PR_1_RELOC_WRITE_ERR 0x010023 /* Block write error during relocation process */
|
||||
#define PR_1_ALLOCATE_IBITMAP_ERROR 0x010024 /* Error allocating inode bitmap */
|
||||
#define PR_1_ALLOCATE_BBITMAP_ERROR 0x010025 /* Error allocating block bitmap */
|
||||
#define PR_1_ALLOCATE_ICOUNT 0x010026 /* Error allocating icount structure */
|
||||
#define PR_1_ALLOCATE_DBCOUNT 0x010027 /* Error allocating dbcount */
|
||||
#define PR_1_ISCAN_ERROR 0x010028 /* Error while scanning inodes */
|
||||
#define PR_1_BLOCK_ITERATE 0x010029 /* Error while iterating over blocks */
|
||||
#define PR_1_ICOUNT_STORE 0x01002A /* Error while storing inode count information */
|
||||
#define PR_1_ADD_DBLOCK 0x01002B /* Error while storing directory block information */
|
||||
#define PR_1_READ_INODE 0x01002C /* Error while reading inode (for clearing) */
|
||||
#define PR_1_SUPPRESS_MESSAGES 0x01002D /* Suppress messages prompt */
|
||||
#define PR_1_SET_IMAGIC 0x01002F /* Imagic flag set on an inode when filesystem doesn't support it */
|
||||
#define PR_1_SET_IMMUTABLE 0x010030 /* Immutable flag set on a device or socket inode */
|
||||
#define PR_1_COMPR_SET 0x010031 /* Compression flag set on a non-compressed filesystem */
|
||||
#define PR_1_SET_NONZSIZE 0x010032 /* Non-zero size on on device, fifo or socket inode */
|
||||
#define PR_1_FS_REV_LEVEL 0x010033 /* Filesystem revision is 0, but feature flags are set */
|
||||
#define PR_1_JOURNAL_INODE_NOT_CLEAR 0x010034 /* Journal inode not in use, needs clearing */
|
||||
#define PR_1_JOURNAL_BAD_MODE 0x010035 /* Journal inode has wrong mode */
|
||||
#define PR_1_LOW_DTIME 0x010036 /* Inode that was part of orphan linked list */
|
||||
#define PR_1_ORPHAN_LIST_REFUGEES 0x010037 /* Latch question which asks how to deal with low dtime inodes */
|
||||
#define PR_1_ALLOCATE_REFCOUNT 0x010038 /* Error allocating refcount structure */
|
||||
#define PR_1_READ_EA_BLOCK 0x010039 /* Error reading Extended Attribute block */
|
||||
#define PR_1_BAD_EA_BLOCK 0x01003A /* Invalid Extended Attribute block */
|
||||
#define PR_1_EXTATTR_READ_ABORT 0x01003B /* Error reading Extended Attribute block while fixing refcount -- abort */
|
||||
#define PR_1_EXTATTR_REFCOUNT 0x01003C /* Extended attribute reference count incorrect */
|
||||
#define PR_1_EXTATTR_WRITE 0x01003D /* Error writing Extended Attribute block while fixing refcount */
|
||||
#define PR_1_EA_MULTI_BLOCK 0x01003E /* Multiple EA blocks not supported */
|
||||
#define PR_1_EA_ALLOC_REGION 0x01003F /* Error allocating EA region allocation structure */
|
||||
#define PR_1_EA_ALLOC_COLLISION 0x010040 /* Error EA allocation collision */
|
||||
#define PR_1_EA_BAD_NAME 0x010041 /* Bad extended attribute name */
|
||||
#define PR_1_EA_BAD_VALUE 0x010042 /* Bad extended attribute value */
|
||||
#define PR_1_INODE_TOOBIG 0x010043 /* Inode too big (latch question) */
|
||||
#define PR_1_TOOBIG_DIR 0x010044 /* Directory too big */
|
||||
#define PR_1_TOOBIG_REG 0x010045 /* Regular file too big */
|
||||
#define PR_1_TOOBIG_SYMLINK 0x010046 /* Symlink too big */
|
||||
#define PR_1_HTREE_SET 0x010047 /* INDEX_FL flag set on a non-HTREE filesystem */
|
||||
#define PR_1_HTREE_NODIR 0x010048 /* INDEX_FL flag set on a non-directory */
|
||||
#define PR_1_HTREE_BADROOT 0x010049 /* Invalid root node in HTREE directory */
|
||||
#define PR_1_HTREE_HASHV 0x01004A /* Unsupported hash version in HTREE directory */
|
||||
#define PR_1_HTREE_INCOMPAT 0x01004B /* Incompatible flag in HTREE root node */
|
||||
#define PR_1_HTREE_DEPTH 0x01004C /* HTREE too deep */
|
||||
#define PR_1_BB_FS_BLOCK 0x01004D /* Bad block has indirect block that conflicts with filesystem block */
|
||||
#define PR_1_RESIZE_INODE_CREATE 0x01004E /* Resize inode failed */
|
||||
#define PR_1_EXTRA_ISIZE 0x01004F /* inode->i_size is too long */
|
||||
#define PR_1_ATTR_NAME_LEN 0x010050 /* attribute name is too long */
|
||||
#define PR_1_ATTR_VALUE_OFFSET 0x010051 /* wrong EA value offset */
|
||||
#define PR_1_ATTR_VALUE_BLOCK 0x010052 /* wrong EA blocknumber */
|
||||
#define PR_1_ATTR_VALUE_SIZE 0x010053 /* wrong EA value size */
|
||||
#define PR_1_ATTR_HASH 0x010054 /* wrong EA hash value */
|
||||
|
||||
/*
|
||||
* Pass 1b errors
|
||||
*/
|
||||
|
||||
#define PR_1B_PASS_HEADER 0x011000 /* Pass 1B: Rescan for duplicate/bad blocks */
|
||||
#define PR_1B_DUP_BLOCK_HEADER 0x011001 /* Duplicate/bad block(s) header */
|
||||
#define PR_1B_DUP_BLOCK 0x011002 /* Duplicate/bad block(s) in inode */
|
||||
#define PR_1B_DUP_BLOCK_END 0x011003 /* Duplicate/bad block(s) end */
|
||||
#define PR_1B_ISCAN_ERROR 0x011004 /* Error while scanning inodes */
|
||||
#define PR_1B_ALLOCATE_IBITMAP_ERROR 0x011005 /* Error allocating inode bitmap */
|
||||
#define PR_1B_BLOCK_ITERATE 0x0110006 /* Error while iterating over blocks */
|
||||
#define PR_1B_ADJ_EA_REFCOUNT 0x0110007 /* Error adjusting EA refcount */
|
||||
#define PR_1C_PASS_HEADER 0x012000 /* Pass 1C: Scan directories for inodes with dup blocks. */
|
||||
#define PR_1D_PASS_HEADER 0x013000 /* Pass 1D: Reconciling duplicate blocks */
|
||||
#define PR_1D_DUP_FILE 0x013001 /* File has duplicate blocks */
|
||||
#define PR_1D_DUP_FILE_LIST 0x013002 /* List of files sharing duplicate blocks */
|
||||
#define PR_1D_SHARE_METADATA 0x013003 /* File sharing blocks with filesystem metadata */
|
||||
#define PR_1D_NUM_DUP_INODES 0x013004 /* Report of how many duplicate/bad inodes */
|
||||
#define PR_1D_DUP_BLOCKS_DEALT 0x013005 /* Duplicated blocks already reassigned or cloned. */
|
||||
#define PR_1D_CLONE_QUESTION 0x013006 /* Clone duplicate/bad blocks? */
|
||||
#define PR_1D_DELETE_QUESTION 0x013007 /* Delete file? */
|
||||
#define PR_1D_CLONE_ERROR 0x013008 /* Couldn't clone file (error) */
|
||||
|
||||
/*
|
||||
* Pass 2 errors
|
||||
*/
|
||||
|
||||
#define PR_2_PASS_HEADER 0x020000 /* Pass 2: Checking directory structure */
|
||||
#define PR_2_BAD_INODE_DOT 0x020001 /* Bad inode number for '.' */
|
||||
#define PR_2_BAD_INO 0x020002 /* Directory entry has bad inode number */
|
||||
#define PR_2_UNUSED_INODE 0x020003 /* Directory entry has deleted or unused inode */
|
||||
#define PR_2_LINK_DOT 0x020004 /* Directry entry is link to '.' */
|
||||
#define PR_2_BB_INODE 0x020005 /* Directory entry points to inode now located in a bad block */
|
||||
#define PR_2_LINK_DIR 0x020006 /* Directory entry contains a link to a directory */
|
||||
#define PR_2_LINK_ROOT 0x020007 /* Directory entry contains a link to the root directry */
|
||||
#define PR_2_BAD_NAME 0x020008 /* Directory entry has illegal characters in its name */
|
||||
#define PR_2_MISSING_DOT 0x020009 /* Missing '.' in directory inode */
|
||||
#define PR_2_MISSING_DOT_DOT 0x02000A /* Missing '..' in directory inode */
|
||||
#define PR_2_1ST_NOT_DOT 0x02000B /* First entry in directory inode doesn't contain '.' */
|
||||
#define PR_2_2ND_NOT_DOT_DOT 0x02000C /* Second entry in directory inode doesn't contain '..' */
|
||||
#define PR_2_FADDR_ZERO 0x02000D /* i_faddr should be zero */
|
||||
#define PR_2_FILE_ACL_ZERO 0x02000E /* i_file_acl should be zero */
|
||||
#define PR_2_DIR_ACL_ZERO 0x02000F /* i_dir_acl should be zero */
|
||||
#define PR_2_FRAG_ZERO 0x020010 /* i_frag should be zero */
|
||||
#define PR_2_FSIZE_ZERO 0x020011 /* i_fsize should be zero */
|
||||
#define PR_2_BAD_MODE 0x020012 /* inode has bad mode */
|
||||
#define PR_2_DIR_CORRUPTED 0x020013 /* directory corrupted */
|
||||
#define PR_2_FILENAME_LONG 0x020014 /* filename too long */
|
||||
#define PR_2_DIRECTORY_HOLE 0x020015 /* Directory inode has a missing block (hole) */
|
||||
#define PR_2_DOT_NULL_TERM 0x020016 /* '.' is not NULL terminated */
|
||||
#define PR_2_DOT_DOT_NULL_TERM 0x020017 /* '..' is not NULL terminated */
|
||||
#define PR_2_BAD_CHAR_DEV 0x020018 /* Illegal character device in inode */
|
||||
#define PR_2_BAD_BLOCK_DEV 0x020019 /* Illegal block device in inode */
|
||||
#define PR_2_DUP_DOT 0x02001A /* Duplicate '.' entry */
|
||||
#define PR_2_DUP_DOT_DOT 0x02001B /* Duplicate '..' entry */
|
||||
#define PR_2_NO_DIRINFO 0x02001C /* Internal error: couldn't find dir_info */
|
||||
#define PR_2_FINAL_RECLEN 0x02001D /* Final rec_len is wrong */
|
||||
#define PR_2_ALLOCATE_ICOUNT 0x02001E /* Error allocating icount structure */
|
||||
#define PR_2_DBLIST_ITERATE 0x02001F /* Error iterating over directory blocks */
|
||||
#define PR_2_READ_DIRBLOCK 0x020020 /* Error reading directory block */
|
||||
#define PR_2_WRITE_DIRBLOCK 0x020021 /* Error writing directory block */
|
||||
#define PR_2_ALLOC_DIRBOCK 0x020022 /* Error allocating new directory block */
|
||||
#define PR_2_DEALLOC_INODE 0x020023 /* Error deallocating inode */
|
||||
#define PR_2_SPLIT_DOT 0x020024 /* Directory entry for '.' is big. Split? */
|
||||
#define PR_2_BAD_FIFO 0x020025 /* Illegal FIFO */
|
||||
#define PR_2_BAD_SOCKET 0x020026 /* Illegal socket */
|
||||
#define PR_2_SET_FILETYPE 0x020027 /* Directory filetype not set */
|
||||
#define PR_2_BAD_FILETYPE 0x020028 /* Directory filetype incorrect */
|
||||
#define PR_2_CLEAR_FILETYPE 0x020029 /* Directory filetype set when it shouldn't be */
|
||||
#define PR_2_NULL_NAME 0x020030 /* Directory filename can't be zero-length */
|
||||
#define PR_2_INVALID_SYMLINK 0x020031 /* Invalid symlink */
|
||||
#define PR_2_FILE_ACL_BAD 0x020032 /* i_file_acl (extended attribute) is bad */
|
||||
#define PR_2_FEATURE_LARGE_FILES 0x020033 /* Filesystem contains large files, but has no such flag in sb */
|
||||
#define PR_2_HTREE_NOTREF 0x020034 /* Node in HTREE directory not referenced */
|
||||
#define PR_2_HTREE_DUPREF 0x020035 /* Node in HTREE directory referenced twice */
|
||||
#define PR_2_HTREE_MIN_HASH 0x020036 /* Node in HTREE directory has bad min hash */
|
||||
#define PR_2_HTREE_MAX_HASH 0x020037 /* Node in HTREE directory has bad max hash */
|
||||
#define PR_2_HTREE_CLEAR 0x020038 /* Clear invalid HTREE directory */
|
||||
#define PR_2_HTREE_BADBLK 0x02003A /* Bad block in htree interior node */
|
||||
#define PR_2_ADJ_EA_REFCOUNT 0x02003B /* Error adjusting EA refcount */
|
||||
#define PR_2_HTREE_BAD_ROOT 0x02003C /* Invalid HTREE root node */
|
||||
#define PR_2_HTREE_BAD_LIMIT 0x02003D /* Invalid HTREE limit */
|
||||
#define PR_2_HTREE_BAD_COUNT 0x02003E /* Invalid HTREE count */
|
||||
#define PR_2_HTREE_HASH_ORDER 0x02003F /* HTREE interior node has out-of-order hashes in table */
|
||||
#define PR_2_HTREE_BAD_DEPTH 0x020040 /* Node in HTREE directory has bad depth */
|
||||
#define PR_2_DUPLICATE_DIRENT 0x020041 /* Duplicate directory entry found */
|
||||
#define PR_2_NON_UNIQUE_FILE 0x020042 /* Non-unique filename found */
|
||||
#define PR_2_REPORT_DUP_DIRENT 0x020043 /* Duplicate directory entry found */
|
||||
|
||||
/*
|
||||
* Pass 3 errors
|
||||
*/
|
||||
|
||||
#define PR_3_PASS_HEADER 0x030000 /* Pass 3: Checking directory connectivity */
|
||||
#define PR_3_NO_ROOT_INODE 0x030001 /* Root inode not allocated */
|
||||
#define PR_3_EXPAND_LF_DIR 0x030002 /* No room in lost+found */
|
||||
#define PR_3_UNCONNECTED_DIR 0x030003 /* Unconnected directory inode */
|
||||
#define PR_3_NO_LF_DIR 0x030004 /* /lost+found not found */
|
||||
#define PR_3_BAD_DOT_DOT 0x030005 /* .. entry is incorrect */
|
||||
#define PR_3_NO_LPF 0x030006 /* Bad or non-existent /lost+found. Cannot reconnect */
|
||||
#define PR_3_CANT_EXPAND_LPF 0x030007 /* Could not expand /lost+found */
|
||||
#define PR_3_CANT_RECONNECT 0x030008 /* Could not reconnect inode */
|
||||
#define PR_3_ERR_FIND_LPF 0x030009 /* Error while trying to find /lost+found */
|
||||
#define PR_3_ERR_LPF_NEW_BLOCK 0x03000A /* Error in ext2fs_new_block while creating /lost+found */
|
||||
#define PR_3_ERR_LPF_NEW_INODE 0x03000B /* Error in ext2fs_new_inode while creating /lost+found */
|
||||
#define PR_3_ERR_LPF_NEW_DIR_BLOCK 0x03000C /* Error in ext2fs_new_dir_block while creating /lost+found */
|
||||
#define PR_3_ERR_LPF_WRITE_BLOCK 0x03000D /* Error while writing directory block for /lost+found */
|
||||
#define PR_3_ADJUST_INODE 0x03000E /* Error while adjusting inode count */
|
||||
#define PR_3_FIX_PARENT_ERR 0x03000F /* Couldn't fix parent directory -- error */
|
||||
#define PR_3_FIX_PARENT_NOFIND 0x030010 /* Couldn't fix parent directory -- couldn't find it */
|
||||
#define PR_3_ALLOCATE_IBITMAP_ERROR 0x030011 /* Error allocating inode bitmap */
|
||||
#define PR_3_CREATE_ROOT_ERROR 0x030012 /* Error creating root directory */
|
||||
#define PR_3_CREATE_LPF_ERROR 0x030013 /* Error creating lost and found directory */
|
||||
#define PR_3_ROOT_NOT_DIR_ABORT 0x030014 /* Root inode is not directory; aborting */
|
||||
#define PR_3_NO_ROOT_INODE_ABORT 0x030015 /* Cannot proceed without a root inode. */
|
||||
#define PR_3_NO_DIRINFO 0x030016 /* Internal error: couldn't find dir_info */
|
||||
#define PR_3_LPF_NOTDIR 0x030017 /* Lost+found is not a directory */
|
||||
|
||||
/*
|
||||
* Pass 3a --- rehashing diretories
|
||||
*/
|
||||
#define PR_3A_PASS_HEADER 0x031000 /* Pass 3a: Reindexing directories */
|
||||
#define PR_3A_OPTIMIZE_ITER 0x031001 /* Error iterating over directories */
|
||||
#define PR_3A_OPTIMIZE_DIR_ERR 0x031002 /* Error rehash directory */
|
||||
#define PR_3A_OPTIMIZE_DIR_HEADER 0x031003 /* Rehashing dir header */
|
||||
#define PR_3A_OPTIMIZE_DIR 0x031004 /* Rehashing directory %d */
|
||||
#define PR_3A_OPTIMIZE_DIR_END 0x031005 /* Rehashing dir end */
|
||||
|
||||
/*
|
||||
* Pass 4 errors
|
||||
*/
|
||||
|
||||
#define PR_4_PASS_HEADER 0x040000 /* Pass 4: Checking reference counts */
|
||||
#define PR_4_ZERO_LEN_INODE 0x040001 /* Unattached zero-length inode */
|
||||
#define PR_4_UNATTACHED_INODE 0x040002 /* Unattached inode */
|
||||
#define PR_4_BAD_REF_COUNT 0x040003 /* Inode ref count wrong */
|
||||
#define PR_4_INCONSISTENT_COUNT 0x040004 /* Inconsistent inode count information cached */
|
||||
|
||||
/*
|
||||
* Pass 5 errors
|
||||
*/
|
||||
|
||||
#define PR_5_PASS_HEADER 0x050000 /* Pass 5: Checking group summary information */
|
||||
#define PR_5_INODE_BMAP_PADDING 0x050001 /* Padding at end of inode bitmap is not set. */
|
||||
#define PR_5_BLOCK_BMAP_PADDING 0x050002 /* Padding at end of block bitmap is not set. */
|
||||
#define PR_5_BLOCK_BITMAP_HEADER 0x050003 /* Block bitmap differences header */
|
||||
#define PR_5_BLOCK_UNUSED 0x050004 /* Block not used, but marked in bitmap */
|
||||
#define PR_5_BLOCK_USED 0x050005 /* Block used, but not marked used in bitmap */
|
||||
#define PR_5_BLOCK_BITMAP_END 0x050006 /* Block bitmap differences end */
|
||||
#define PR_5_INODE_BITMAP_HEADER 0x050007 /* Inode bitmap differences header */
|
||||
#define PR_5_INODE_UNUSED 0x050008 /* Inode not used, but marked in bitmap */
|
||||
#define PR_5_INODE_USED 0x050009 /* Inode used, but not marked used in bitmap */
|
||||
#define PR_5_INODE_BITMAP_END 0x05000A /* Inode bitmap differences end */
|
||||
#define PR_5_FREE_INODE_COUNT_GROUP 0x05000B /* Free inodes count for group wrong */
|
||||
#define PR_5_FREE_DIR_COUNT_GROUP 0x05000C /* Directories count for group wrong */
|
||||
#define PR_5_FREE_INODE_COUNT 0x05000D /* Free inodes count wrong */
|
||||
#define PR_5_FREE_BLOCK_COUNT_GROUP 0x05000E /* Free blocks count for group wrong */
|
||||
#define PR_5_FREE_BLOCK_COUNT 0x05000F /* Free blocks count wrong */
|
||||
#define PR_5_BMAP_ENDPOINTS 0x050010 /* Programming error: bitmap endpoints don't match */
|
||||
#define PR_5_FUDGE_BITMAP_ERROR 0x050011 /* Internal error: fudging end of bitmap */
|
||||
#define PR_5_COPY_IBITMAP_ERROR 0x050012 /* Error copying in replacement inode bitmap */
|
||||
#define PR_5_COPY_BBITMAP_ERROR 0x050013 /* Error copying in replacement block bitmap */
|
||||
#define PR_5_BLOCK_RANGE_UNUSED 0x050014 /* Block range not used, but marked in bitmap */
|
||||
#define PR_5_BLOCK_RANGE_USED 0x050015 /* Block range used, but not marked used in bitmap */
|
||||
#define PR_5_INODE_RANGE_UNUSED 0x050016 /* Inode range not used, but marked in bitmap */
|
||||
#define PR_5_INODE_RANGE_USED 0x050017 /* Inode rangeused, but not marked used in bitmap */
|
||||
|
||||
|
||||
/*
|
||||
* The directory information structure; stores directory information
|
||||
* collected in earlier passes, to avoid disk i/o in fetching the
|
||||
* directory information.
|
||||
*/
|
||||
struct dir_info {
|
||||
ext2_ino_t ino; /* Inode number */
|
||||
ext2_ino_t dotdot; /* Parent according to '..' */
|
||||
ext2_ino_t parent; /* Parent according to treewalk */
|
||||
};
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* The indexed directory information structure; stores information for
|
||||
* directories which contain a hash tree index.
|
||||
*/
|
||||
struct dx_dir_info {
|
||||
ext2_ino_t ino; /* Inode number */
|
||||
int numblocks; /* number of blocks */
|
||||
int hashversion;
|
||||
short depth; /* depth of tree */
|
||||
struct dx_dirblock_info *dx_block; /* Array of size numblocks */
|
||||
};
|
||||
|
||||
/*
|
||||
* Define the extended attribute refcount structure
|
||||
*/
|
||||
typedef struct ea_refcount *ext2_refcount_t;
|
||||
|
||||
struct e2fsck_struct {
|
||||
ext2_filsys fs;
|
||||
const char *program_name;
|
||||
char *filesystem_name;
|
||||
char *device_name;
|
||||
char *io_options;
|
||||
int flags; /* E2fsck internal flags */
|
||||
int options;
|
||||
blk_t use_superblock; /* sb requested by user */
|
||||
blk_t superblock; /* sb used to open fs */
|
||||
int blocksize; /* blocksize */
|
||||
blk_t num_blocks; /* Total number of blocks */
|
||||
int mount_flags;
|
||||
blkid_cache blkid; /* blkid cache */
|
||||
|
||||
jmp_buf abort_loc;
|
||||
|
||||
unsigned long abort_code;
|
||||
|
||||
int (*progress)(e2fsck_t ctx, int pass, unsigned long cur,
|
||||
unsigned long max);
|
||||
|
||||
ext2fs_inode_bitmap inode_used_map; /* Inodes which are in use */
|
||||
ext2fs_inode_bitmap inode_bad_map; /* Inodes which are bad somehow */
|
||||
ext2fs_inode_bitmap inode_dir_map; /* Inodes which are directories */
|
||||
ext2fs_inode_bitmap inode_imagic_map; /* AFS inodes */
|
||||
ext2fs_inode_bitmap inode_reg_map; /* Inodes which are regular files*/
|
||||
|
||||
ext2fs_block_bitmap block_found_map; /* Blocks which are in use */
|
||||
ext2fs_block_bitmap block_dup_map; /* Blks referenced more than once */
|
||||
ext2fs_block_bitmap block_ea_map; /* Blocks which are used by EA's */
|
||||
|
||||
/*
|
||||
* Inode count arrays
|
||||
*/
|
||||
ext2_icount_t inode_count;
|
||||
ext2_icount_t inode_link_info;
|
||||
|
||||
ext2_refcount_t refcount;
|
||||
ext2_refcount_t refcount_extra;
|
||||
|
||||
/*
|
||||
* Array of flags indicating whether an inode bitmap, block
|
||||
* bitmap, or inode table is invalid
|
||||
*/
|
||||
int *invalid_inode_bitmap_flag;
|
||||
int *invalid_block_bitmap_flag;
|
||||
int *invalid_inode_table_flag;
|
||||
int invalid_bitmaps; /* There are invalid bitmaps/itable */
|
||||
|
||||
/*
|
||||
* Block buffer
|
||||
*/
|
||||
char *block_buf;
|
||||
|
||||
/*
|
||||
* For pass1_check_directory and pass1_get_blocks
|
||||
*/
|
||||
ext2_ino_t stashed_ino;
|
||||
struct ext2_inode *stashed_inode;
|
||||
|
||||
/*
|
||||
* Location of the lost and found directory
|
||||
*/
|
||||
ext2_ino_t lost_and_found;
|
||||
int bad_lost_and_found;
|
||||
|
||||
/*
|
||||
* Directory information
|
||||
*/
|
||||
int dir_info_count;
|
||||
int dir_info_size;
|
||||
struct dir_info *dir_info;
|
||||
|
||||
/*
|
||||
* Indexed directory information
|
||||
*/
|
||||
int dx_dir_info_count;
|
||||
int dx_dir_info_size;
|
||||
struct dx_dir_info *dx_dir_info;
|
||||
|
||||
/*
|
||||
* Directories to hash
|
||||
*/
|
||||
ext2_u32_list dirs_to_hash;
|
||||
|
||||
/*
|
||||
* Tuning parameters
|
||||
*/
|
||||
int process_inode_size;
|
||||
int inode_buffer_blocks;
|
||||
|
||||
/*
|
||||
* ext3 journal support
|
||||
*/
|
||||
io_channel journal_io;
|
||||
char *journal_name;
|
||||
|
||||
/*
|
||||
* How we display the progress update (for unix)
|
||||
*/
|
||||
int progress_fd;
|
||||
int progress_pos;
|
||||
int progress_last_percent;
|
||||
unsigned int progress_last_time;
|
||||
int interactive; /* Are we connected directly to a tty? */
|
||||
char start_meta[2], stop_meta[2];
|
||||
|
||||
/* File counts */
|
||||
int fs_directory_count;
|
||||
int fs_regular_count;
|
||||
int fs_blockdev_count;
|
||||
int fs_chardev_count;
|
||||
int fs_links_count;
|
||||
int fs_symlinks_count;
|
||||
int fs_fast_symlinks_count;
|
||||
int fs_fifo_count;
|
||||
int fs_total_count;
|
||||
int fs_sockets_count;
|
||||
int fs_ind_count;
|
||||
int fs_dind_count;
|
||||
int fs_tind_count;
|
||||
int fs_fragmented;
|
||||
int large_files;
|
||||
int fs_ext_attr_inodes;
|
||||
int fs_ext_attr_blocks;
|
||||
|
||||
int ext_attr_ver;
|
||||
|
||||
/*
|
||||
* For the use of callers of the e2fsck functions; not used by
|
||||
* e2fsck functions themselves.
|
||||
*/
|
||||
void *priv_data;
|
||||
};
|
||||
|
||||
|
||||
#define tid_gt(x, y) ((x - y) > 0)
|
||||
|
||||
static inline int tid_geq(tid_t x, tid_t y)
|
||||
{
|
||||
int difference = (x - y);
|
||||
return (difference >= 0);
|
||||
}
|
||||
|
||||
|
15
e2fsprogs/old_e2fsprogs/e2p/Kbuild
Normal file
15
e2fsprogs/old_e2fsprogs/e2p/Kbuild
Normal file
@ -0,0 +1,15 @@
|
||||
# Makefile for busybox
|
||||
#
|
||||
# Copyright (C) 1999-2005 by Erik Andersen <andersen@codepoet.org>
|
||||
#
|
||||
# Licensed under the GPL v2, see the file LICENSE in this tarball.
|
||||
|
||||
NEEDED-$(CONFIG_CHATTR) = y
|
||||
NEEDED-$(CONFIG_LSATTR) = y
|
||||
NEEDED-$(CONFIG_MKE2FS) = y
|
||||
NEEDED-$(CONFIG_TUNE2FS) = y
|
||||
|
||||
lib-y:=
|
||||
lib-$(NEEDED-y) += fgetsetflags.o fgetsetversion.o pf.o iod.o mntopts.o \
|
||||
feature.o ls.o uuid.o pe.o ostype.o ps.o hashstr.o \
|
||||
parse_num.o
|
64
e2fsprogs/old_e2fsprogs/e2p/e2p.h
Normal file
64
e2fsprogs/old_e2fsprogs/e2p/e2p.h
Normal file
@ -0,0 +1,64 @@
|
||||
/* vi: set sw=4 ts=4: */
|
||||
#include "busybox.h"
|
||||
#include <sys/types.h> /* Needed by dirent.h on netbsd */
|
||||
#include <stdio.h>
|
||||
#include <dirent.h>
|
||||
|
||||
#include "../ext2fs/ext2_fs.h"
|
||||
|
||||
#define E2P_FEATURE_COMPAT 0
|
||||
#define E2P_FEATURE_INCOMPAT 1
|
||||
#define E2P_FEATURE_RO_INCOMPAT 2
|
||||
#ifndef EXT3_FEATURE_INCOMPAT_EXTENTS
|
||||
#define EXT3_FEATURE_INCOMPAT_EXTENTS 0x0040
|
||||
#endif
|
||||
|
||||
/* `options' for print_flags() */
|
||||
|
||||
#define PFOPT_LONG 1 /* Must be 1 for compatibility with `int long_format'. */
|
||||
|
||||
/*int fgetversion (const char * name, unsigned long * version);*/
|
||||
/*int fsetversion (const char * name, unsigned long version);*/
|
||||
int fgetsetversion(const char * name, unsigned long * get_version, unsigned long set_version);
|
||||
#define fgetversion(name, version) fgetsetversion(name, version, 0)
|
||||
#define fsetversion(name, version) fgetsetversion(name, NULL, version)
|
||||
|
||||
/*int fgetflags (const char * name, unsigned long * flags);*/
|
||||
/*int fsetflags (const char * name, unsigned long flags);*/
|
||||
int fgetsetflags(const char * name, unsigned long * get_flags, unsigned long set_flags);
|
||||
#define fgetflags(name, flags) fgetsetflags(name, flags, 0)
|
||||
#define fsetflags(name, flags) fgetsetflags(name, NULL, flags)
|
||||
|
||||
int getflags (int fd, unsigned long * flags);
|
||||
int getversion (int fd, unsigned long * version);
|
||||
int iterate_on_dir (const char * dir_name,
|
||||
int (*func) (const char *, struct dirent *, void *),
|
||||
void * private);
|
||||
/*void list_super(struct ext2_super_block * s);*/
|
||||
void list_super2(struct ext2_super_block * s, FILE *f);
|
||||
#define list_super(s) list_super2(s, stdout)
|
||||
void print_fs_errors (FILE * f, unsigned short errors);
|
||||
void print_flags (FILE * f, unsigned long flags, unsigned options);
|
||||
void print_fs_state (FILE * f, unsigned short state);
|
||||
int setflags (int fd, unsigned long flags);
|
||||
int setversion (int fd, unsigned long version);
|
||||
|
||||
const char *e2p_feature2string(int compat, unsigned int mask);
|
||||
int e2p_string2feature(char *string, int *compat, unsigned int *mask);
|
||||
int e2p_edit_feature(const char *str, __u32 *compat_array, __u32 *ok_array);
|
||||
|
||||
int e2p_is_null_uuid(void *uu);
|
||||
void e2p_uuid_to_str(void *uu, char *out);
|
||||
const char *e2p_uuid2str(void *uu);
|
||||
|
||||
const char *e2p_hash2string(int num);
|
||||
int e2p_string2hash(char *string);
|
||||
|
||||
const char *e2p_mntopt2string(unsigned int mask);
|
||||
int e2p_string2mntopt(char *string, unsigned int *mask);
|
||||
int e2p_edit_mntopts(const char *str, __u32 *mntopts, __u32 ok);
|
||||
|
||||
unsigned long parse_num_blocks(const char *arg, int log_block_size);
|
||||
|
||||
char *e2p_os2string(int os_type);
|
||||
int e2p_string2os(char *str);
|
187
e2fsprogs/old_e2fsprogs/e2p/feature.c
Normal file
187
e2fsprogs/old_e2fsprogs/e2p/feature.c
Normal file
@ -0,0 +1,187 @@
|
||||
/* vi: set sw=4 ts=4: */
|
||||
/*
|
||||
* feature.c --- convert between features and strings
|
||||
*
|
||||
* Copyright (C) 1999 Theodore Ts'o <tytso@mit.edu>
|
||||
*
|
||||
* This file can be redistributed under the terms of the GNU Library General
|
||||
* Public License
|
||||
*
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <ctype.h>
|
||||
#include <errno.h>
|
||||
|
||||
#include "e2p.h"
|
||||
|
||||
struct feature {
|
||||
int compat;
|
||||
unsigned int mask;
|
||||
const char *string;
|
||||
};
|
||||
|
||||
static const struct feature feature_list[] = {
|
||||
{ E2P_FEATURE_COMPAT, EXT2_FEATURE_COMPAT_DIR_PREALLOC,
|
||||
"dir_prealloc" },
|
||||
{ E2P_FEATURE_COMPAT, EXT3_FEATURE_COMPAT_HAS_JOURNAL,
|
||||
"has_journal" },
|
||||
{ E2P_FEATURE_COMPAT, EXT2_FEATURE_COMPAT_IMAGIC_INODES,
|
||||
"imagic_inodes" },
|
||||
{ E2P_FEATURE_COMPAT, EXT2_FEATURE_COMPAT_EXT_ATTR,
|
||||
"ext_attr" },
|
||||
{ E2P_FEATURE_COMPAT, EXT2_FEATURE_COMPAT_DIR_INDEX,
|
||||
"dir_index" },
|
||||
{ E2P_FEATURE_COMPAT, EXT2_FEATURE_COMPAT_RESIZE_INODE,
|
||||
"resize_inode" },
|
||||
{ E2P_FEATURE_RO_INCOMPAT, EXT2_FEATURE_RO_COMPAT_SPARSE_SUPER,
|
||||
"sparse_super" },
|
||||
{ E2P_FEATURE_RO_INCOMPAT, EXT2_FEATURE_RO_COMPAT_LARGE_FILE,
|
||||
"large_file" },
|
||||
{ E2P_FEATURE_INCOMPAT, EXT2_FEATURE_INCOMPAT_COMPRESSION,
|
||||
"compression" },
|
||||
{ E2P_FEATURE_INCOMPAT, EXT2_FEATURE_INCOMPAT_FILETYPE,
|
||||
"filetype" },
|
||||
{ E2P_FEATURE_INCOMPAT, EXT3_FEATURE_INCOMPAT_RECOVER,
|
||||
"needs_recovery" },
|
||||
{ E2P_FEATURE_INCOMPAT, EXT3_FEATURE_INCOMPAT_JOURNAL_DEV,
|
||||
"journal_dev" },
|
||||
{ E2P_FEATURE_INCOMPAT, EXT3_FEATURE_INCOMPAT_EXTENTS,
|
||||
"extents" },
|
||||
{ E2P_FEATURE_INCOMPAT, EXT2_FEATURE_INCOMPAT_META_BG,
|
||||
"meta_bg" },
|
||||
{ 0, 0, 0 },
|
||||
};
|
||||
|
||||
const char *e2p_feature2string(int compat, unsigned int mask)
|
||||
{
|
||||
const struct feature *f;
|
||||
static char buf[20];
|
||||
char fchar;
|
||||
int fnum;
|
||||
|
||||
for (f = feature_list; f->string; f++) {
|
||||
if ((compat == f->compat) &&
|
||||
(mask == f->mask))
|
||||
return f->string;
|
||||
}
|
||||
switch (compat) {
|
||||
case E2P_FEATURE_COMPAT:
|
||||
fchar = 'C';
|
||||
break;
|
||||
case E2P_FEATURE_INCOMPAT:
|
||||
fchar = 'I';
|
||||
break;
|
||||
case E2P_FEATURE_RO_INCOMPAT:
|
||||
fchar = 'R';
|
||||
break;
|
||||
default:
|
||||
fchar = '?';
|
||||
break;
|
||||
}
|
||||
for (fnum = 0; mask >>= 1; fnum++);
|
||||
sprintf(buf, "FEATURE_%c%d", fchar, fnum);
|
||||
return buf;
|
||||
}
|
||||
|
||||
int e2p_string2feature(char *string, int *compat_type, unsigned int *mask)
|
||||
{
|
||||
const struct feature *f;
|
||||
char *eptr;
|
||||
int num;
|
||||
|
||||
for (f = feature_list; f->string; f++) {
|
||||
if (!strcasecmp(string, f->string)) {
|
||||
*compat_type = f->compat;
|
||||
*mask = f->mask;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
if (strncasecmp(string, "FEATURE_", 8))
|
||||
return 1;
|
||||
|
||||
switch (string[8]) {
|
||||
case 'c':
|
||||
case 'C':
|
||||
*compat_type = E2P_FEATURE_COMPAT;
|
||||
break;
|
||||
case 'i':
|
||||
case 'I':
|
||||
*compat_type = E2P_FEATURE_INCOMPAT;
|
||||
break;
|
||||
case 'r':
|
||||
case 'R':
|
||||
*compat_type = E2P_FEATURE_RO_INCOMPAT;
|
||||
break;
|
||||
default:
|
||||
return 1;
|
||||
}
|
||||
if (string[9] == 0)
|
||||
return 1;
|
||||
num = strtol(string+9, &eptr, 10);
|
||||
if (num > 32 || num < 0)
|
||||
return 1;
|
||||
if (*eptr)
|
||||
return 1;
|
||||
*mask = 1 << num;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline char *skip_over_blanks(char *cp)
|
||||
{
|
||||
while (*cp && isspace(*cp))
|
||||
cp++;
|
||||
return cp;
|
||||
}
|
||||
|
||||
static inline char *skip_over_word(char *cp)
|
||||
{
|
||||
while (*cp && !isspace(*cp) && *cp != ',')
|
||||
cp++;
|
||||
return cp;
|
||||
}
|
||||
|
||||
/*
|
||||
* Edit a feature set array as requested by the user. The ok_array,
|
||||
* if set, allows the application to limit what features the user is
|
||||
* allowed to set or clear using this function.
|
||||
*/
|
||||
int e2p_edit_feature(const char *str, __u32 *compat_array, __u32 *ok_array)
|
||||
{
|
||||
char *cp, *buf, *next;
|
||||
int neg;
|
||||
unsigned int mask;
|
||||
int compat_type;
|
||||
|
||||
buf = xstrdup(str);
|
||||
cp = buf;
|
||||
while (cp && *cp) {
|
||||
neg = 0;
|
||||
cp = skip_over_blanks(cp);
|
||||
next = skip_over_word(cp);
|
||||
if (*next == 0)
|
||||
next = 0;
|
||||
else
|
||||
*next = 0;
|
||||
switch (*cp) {
|
||||
case '-':
|
||||
case '^':
|
||||
neg++;
|
||||
case '+':
|
||||
cp++;
|
||||
break;
|
||||
}
|
||||
if (e2p_string2feature(cp, &compat_type, &mask))
|
||||
return 1;
|
||||
if (ok_array && !(ok_array[compat_type] & mask))
|
||||
return 1;
|
||||
if (neg)
|
||||
compat_array[compat_type] &= ~mask;
|
||||
else
|
||||
compat_array[compat_type] |= mask;
|
||||
cp = next ? next+1 : 0;
|
||||
}
|
||||
return 0;
|
||||
}
|
70
e2fsprogs/old_e2fsprogs/e2p/fgetsetflags.c
Normal file
70
e2fsprogs/old_e2fsprogs/e2p/fgetsetflags.c
Normal file
@ -0,0 +1,70 @@
|
||||
/* vi: set sw=4 ts=4: */
|
||||
/*
|
||||
* fgetflags.c - Get a file flags on an ext2 file system
|
||||
* fsetflags.c - Set a file flags on an ext2 file system
|
||||
*
|
||||
* Copyright (C) 1993, 1994 Remy Card <card@masi.ibp.fr>
|
||||
* Laboratoire MASI, Institut Blaise Pascal
|
||||
* Universite Pierre et Marie Curie (Paris VI)
|
||||
*
|
||||
* This file can be redistributed under the terms of the GNU Library General
|
||||
* Public License
|
||||
*/
|
||||
|
||||
/*
|
||||
* History:
|
||||
* 93/10/30 - Creation
|
||||
*/
|
||||
|
||||
#ifdef HAVE_ERRNO_H
|
||||
#include <errno.h>
|
||||
#endif
|
||||
#ifdef HAVE_UNISTD_H
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#ifdef HAVE_EXT2_IOCTLS
|
||||
#include <fcntl.h>
|
||||
#include <sys/ioctl.h>
|
||||
#endif
|
||||
|
||||
#include "e2p.h"
|
||||
|
||||
#ifdef O_LARGEFILE
|
||||
#define OPEN_FLAGS (O_RDONLY|O_NONBLOCK|O_LARGEFILE)
|
||||
#else
|
||||
#define OPEN_FLAGS (O_RDONLY|O_NONBLOCK)
|
||||
#endif
|
||||
|
||||
int fgetsetflags (const char * name, unsigned long * get_flags, unsigned long set_flags)
|
||||
{
|
||||
#ifdef HAVE_EXT2_IOCTLS
|
||||
struct stat buf;
|
||||
int fd, r, f, save_errno = 0;
|
||||
|
||||
if (!stat(name, &buf) &&
|
||||
!S_ISREG(buf.st_mode) && !S_ISDIR(buf.st_mode)) {
|
||||
goto notsupp;
|
||||
}
|
||||
fd = open (name, OPEN_FLAGS);
|
||||
if (fd == -1)
|
||||
return -1;
|
||||
if (!get_flags) {
|
||||
f = (int) set_flags;
|
||||
r = ioctl (fd, EXT2_IOC_SETFLAGS, &f);
|
||||
} else {
|
||||
r = ioctl (fd, EXT2_IOC_GETFLAGS, &f);
|
||||
*get_flags = f;
|
||||
}
|
||||
if (r == -1)
|
||||
save_errno = errno;
|
||||
close (fd);
|
||||
if (save_errno)
|
||||
errno = save_errno;
|
||||
return r;
|
||||
notsupp:
|
||||
#endif /* HAVE_EXT2_IOCTLS */
|
||||
errno = EOPNOTSUPP;
|
||||
return -1;
|
||||
}
|
70
e2fsprogs/old_e2fsprogs/e2p/fgetsetversion.c
Normal file
70
e2fsprogs/old_e2fsprogs/e2p/fgetsetversion.c
Normal file
@ -0,0 +1,70 @@
|
||||
/* vi: set sw=4 ts=4: */
|
||||
/*
|
||||
* fgetversion.c - Get a file version on an ext2 file system
|
||||
* fsetversion.c - Set a file version on an ext2 file system
|
||||
*
|
||||
*
|
||||
* Copyright (C) 1993, 1994 Remy Card <card@masi.ibp.fr>
|
||||
* Laboratoire MASI, Institut Blaise Pascal
|
||||
* Universite Pierre et Marie Curie (Paris VI)
|
||||
*
|
||||
* This file can be redistributed under the terms of the GNU Library General
|
||||
* Public License
|
||||
*/
|
||||
|
||||
/*
|
||||
* History:
|
||||
* 93/10/30 - Creation
|
||||
*/
|
||||
|
||||
#ifdef HAVE_ERRNO_H
|
||||
#include <errno.h>
|
||||
#endif
|
||||
#ifdef HAVE_UNISTD_H
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
#include <fcntl.h>
|
||||
#include <sys/ioctl.h>
|
||||
|
||||
#include "e2p.h"
|
||||
|
||||
#ifdef O_LARGEFILE
|
||||
#define OPEN_FLAGS (O_RDONLY|O_NONBLOCK|O_LARGEFILE)
|
||||
#else
|
||||
#define OPEN_FLAGS (O_RDONLY|O_NONBLOCK)
|
||||
#endif
|
||||
|
||||
/*
|
||||
To do fsetversion: unsigned long *ptr_version must be set to NULL.
|
||||
and unsigned long version must be set to a value
|
||||
To do fgetversion: unsigned long *ptr_version must NOT be set to NULL
|
||||
and unsigned long version is ignored.
|
||||
TITO.
|
||||
*/
|
||||
|
||||
int fgetsetversion (const char * name, unsigned long * get_version, unsigned long set_version)
|
||||
{
|
||||
#ifdef HAVE_EXT2_IOCTLS
|
||||
int fd, r, ver, save_errno = 0;
|
||||
|
||||
fd = open (name, OPEN_FLAGS);
|
||||
if (fd == -1)
|
||||
return -1;
|
||||
if (!get_version) {
|
||||
ver = (int) set_version;
|
||||
r = ioctl (fd, EXT2_IOC_SETVERSION, &ver);
|
||||
} else {
|
||||
r = ioctl (fd, EXT2_IOC_GETVERSION, &ver);
|
||||
*get_version = ver;
|
||||
}
|
||||
if (r == -1)
|
||||
save_errno = errno;
|
||||
close (fd);
|
||||
if (save_errno)
|
||||
errno = save_errno;
|
||||
return r;
|
||||
#else /* ! HAVE_EXT2_IOCTLS */
|
||||
errno = EOPNOTSUPP;
|
||||
return -1;
|
||||
#endif /* ! HAVE_EXT2_IOCTLS */
|
||||
}
|
70
e2fsprogs/old_e2fsprogs/e2p/hashstr.c
Normal file
70
e2fsprogs/old_e2fsprogs/e2p/hashstr.c
Normal file
@ -0,0 +1,70 @@
|
||||
/* vi: set sw=4 ts=4: */
|
||||
/*
|
||||
* feature.c --- convert between features and strings
|
||||
*
|
||||
* Copyright (C) 1999 Theodore Ts'o <tytso@mit.edu>
|
||||
*
|
||||
* This file can be redistributed under the terms of the GNU Library General
|
||||
* Public License
|
||||
*
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <ctype.h>
|
||||
#include <errno.h>
|
||||
|
||||
#include "e2p.h"
|
||||
|
||||
struct hash {
|
||||
int num;
|
||||
const char *string;
|
||||
};
|
||||
|
||||
static const struct hash hash_list[] = {
|
||||
{ EXT2_HASH_LEGACY, "legacy" },
|
||||
{ EXT2_HASH_HALF_MD4, "half_md4" },
|
||||
{ EXT2_HASH_TEA, "tea" },
|
||||
{ 0, 0 },
|
||||
};
|
||||
|
||||
const char *e2p_hash2string(int num)
|
||||
{
|
||||
const struct hash *p;
|
||||
static char buf[20];
|
||||
|
||||
for (p = hash_list; p->string; p++) {
|
||||
if (num == p->num)
|
||||
return p->string;
|
||||
}
|
||||
sprintf(buf, "HASHALG_%d", num);
|
||||
return buf;
|
||||
}
|
||||
|
||||
/*
|
||||
* Returns the hash algorithm, or -1 on error
|
||||
*/
|
||||
int e2p_string2hash(char *string)
|
||||
{
|
||||
const struct hash *p;
|
||||
char *eptr;
|
||||
int num;
|
||||
|
||||
for (p = hash_list; p->string; p++) {
|
||||
if (!strcasecmp(string, p->string)) {
|
||||
return p->num;
|
||||
}
|
||||
}
|
||||
if (strncasecmp(string, "HASHALG_", 8))
|
||||
return -1;
|
||||
|
||||
if (string[8] == 0)
|
||||
return -1;
|
||||
num = strtol(string+8, &eptr, 10);
|
||||
if (num > 255 || num < 0)
|
||||
return -1;
|
||||
if (*eptr)
|
||||
return -1;
|
||||
return num;
|
||||
}
|
52
e2fsprogs/old_e2fsprogs/e2p/iod.c
Normal file
52
e2fsprogs/old_e2fsprogs/e2p/iod.c
Normal file
@ -0,0 +1,52 @@
|
||||
/* vi: set sw=4 ts=4: */
|
||||
/*
|
||||
* iod.c - Iterate a function on each entry of a directory
|
||||
*
|
||||
* Copyright (C) 1993, 1994 Remy Card <card@masi.ibp.fr>
|
||||
* Laboratoire MASI, Institut Blaise Pascal
|
||||
* Universite Pierre et Marie Curie (Paris VI)
|
||||
*
|
||||
* This file can be redistributed under the terms of the GNU Library General
|
||||
* Public License
|
||||
*/
|
||||
|
||||
/*
|
||||
* History:
|
||||
* 93/10/30 - Creation
|
||||
*/
|
||||
|
||||
#include "e2p.h"
|
||||
#include <unistd.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
int iterate_on_dir (const char * dir_name,
|
||||
int (*func) (const char *, struct dirent *, void *),
|
||||
void * private)
|
||||
{
|
||||
DIR * dir;
|
||||
struct dirent *de, *dep;
|
||||
int max_len, len;
|
||||
|
||||
max_len = PATH_MAX + sizeof(struct dirent);
|
||||
de = xmalloc(max_len+1);
|
||||
memset(de, 0, max_len+1);
|
||||
|
||||
dir = opendir (dir_name);
|
||||
if (dir == NULL) {
|
||||
free(de);
|
||||
return -1;
|
||||
}
|
||||
while ((dep = readdir (dir))) {
|
||||
len = sizeof(struct dirent);
|
||||
if (len < dep->d_reclen)
|
||||
len = dep->d_reclen;
|
||||
if (len > max_len)
|
||||
len = max_len;
|
||||
memcpy(de, dep, len);
|
||||
(*func) (dir_name, de, private);
|
||||
}
|
||||
free(de);
|
||||
closedir(dir);
|
||||
return 0;
|
||||
}
|
273
e2fsprogs/old_e2fsprogs/e2p/ls.c
Normal file
273
e2fsprogs/old_e2fsprogs/e2p/ls.c
Normal file
@ -0,0 +1,273 @@
|
||||
/* vi: set sw=4 ts=4: */
|
||||
/*
|
||||
* ls.c - List the contents of an ext2fs superblock
|
||||
*
|
||||
* Copyright (C) 1992, 1993, 1994 Remy Card <card@masi.ibp.fr>
|
||||
* Laboratoire MASI, Institut Blaise Pascal
|
||||
* Universite Pierre et Marie Curie (Paris VI)
|
||||
*
|
||||
* Copyright (C) 1995, 1996, 1997 Theodore Ts'o <tytso@mit.edu>
|
||||
*
|
||||
* This file can be redistributed under the terms of the GNU Library General
|
||||
* Public License
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <sys/types.h>
|
||||
#include <string.h>
|
||||
#include <grp.h>
|
||||
#include <pwd.h>
|
||||
#include <time.h>
|
||||
|
||||
#include "e2p.h"
|
||||
|
||||
static void print_user(unsigned short uid, FILE *f)
|
||||
{
|
||||
struct passwd *pw = getpwuid(uid);
|
||||
fprintf(f, "%u (user %s)\n", uid,
|
||||
(pw == NULL ? "unknown" : pw->pw_name));
|
||||
}
|
||||
|
||||
static void print_group(unsigned short gid, FILE *f)
|
||||
{
|
||||
struct group *gr = getgrgid(gid);
|
||||
fprintf(f, "%u (group %s)\n", gid,
|
||||
(gr == NULL ? "unknown" : gr->gr_name));
|
||||
}
|
||||
|
||||
#define MONTH_INT (86400 * 30)
|
||||
#define WEEK_INT (86400 * 7)
|
||||
#define DAY_INT (86400)
|
||||
#define HOUR_INT (60 * 60)
|
||||
#define MINUTE_INT (60)
|
||||
|
||||
static const char *interval_string(unsigned int secs)
|
||||
{
|
||||
static char buf[256], tmp[80];
|
||||
int hr, min, num;
|
||||
|
||||
buf[0] = 0;
|
||||
|
||||
if (secs == 0)
|
||||
return "<none>";
|
||||
|
||||
if (secs >= MONTH_INT) {
|
||||
num = secs / MONTH_INT;
|
||||
secs -= num*MONTH_INT;
|
||||
sprintf(buf, "%d month%s", num, (num>1) ? "s" : "");
|
||||
}
|
||||
if (secs >= WEEK_INT) {
|
||||
num = secs / WEEK_INT;
|
||||
secs -= num*WEEK_INT;
|
||||
sprintf(tmp, "%s%d week%s", buf[0] ? ", " : "",
|
||||
num, (num>1) ? "s" : "");
|
||||
strcat(buf, tmp);
|
||||
}
|
||||
if (secs >= DAY_INT) {
|
||||
num = secs / DAY_INT;
|
||||
secs -= num*DAY_INT;
|
||||
sprintf(tmp, "%s%d day%s", buf[0] ? ", " : "",
|
||||
num, (num>1) ? "s" : "");
|
||||
strcat(buf, tmp);
|
||||
}
|
||||
if (secs > 0) {
|
||||
hr = secs / HOUR_INT;
|
||||
secs -= hr*HOUR_INT;
|
||||
min = secs / MINUTE_INT;
|
||||
secs -= min*MINUTE_INT;
|
||||
sprintf(tmp, "%s%d:%02d:%02d", buf[0] ? ", " : "",
|
||||
hr, min, secs);
|
||||
strcat(buf, tmp);
|
||||
}
|
||||
return buf;
|
||||
}
|
||||
|
||||
static void print_features(struct ext2_super_block * s, FILE *f)
|
||||
{
|
||||
#ifdef EXT2_DYNAMIC_REV
|
||||
int i, j, printed=0;
|
||||
__u32 *mask = &s->s_feature_compat, m;
|
||||
|
||||
fprintf(f, "Filesystem features: ");
|
||||
for (i=0; i <3; i++,mask++) {
|
||||
for (j=0,m=1; j < 32; j++, m<<=1) {
|
||||
if (*mask & m) {
|
||||
fprintf(f, " %s", e2p_feature2string(i, m));
|
||||
printed++;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (printed == 0)
|
||||
fprintf(f, " (none)");
|
||||
fprintf(f, "\n");
|
||||
#endif
|
||||
}
|
||||
|
||||
static void print_mntopts(struct ext2_super_block * s, FILE *f)
|
||||
{
|
||||
#ifdef EXT2_DYNAMIC_REV
|
||||
int i, printed=0;
|
||||
__u32 mask = s->s_default_mount_opts, m;
|
||||
|
||||
fprintf(f, "Default mount options: ");
|
||||
if (mask & EXT3_DEFM_JMODE) {
|
||||
fprintf(f, " %s", e2p_mntopt2string(mask & EXT3_DEFM_JMODE));
|
||||
printed++;
|
||||
}
|
||||
for (i=0,m=1; i < 32; i++, m<<=1) {
|
||||
if (m & EXT3_DEFM_JMODE)
|
||||
continue;
|
||||
if (mask & m) {
|
||||
fprintf(f, " %s", e2p_mntopt2string(m));
|
||||
printed++;
|
||||
}
|
||||
}
|
||||
if (printed == 0)
|
||||
fprintf(f, " (none)");
|
||||
fprintf(f, "\n");
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
#ifndef EXT2_INODE_SIZE
|
||||
#define EXT2_INODE_SIZE(s) sizeof(struct ext2_inode)
|
||||
#endif
|
||||
|
||||
#ifndef EXT2_GOOD_OLD_REV
|
||||
#define EXT2_GOOD_OLD_REV 0
|
||||
#endif
|
||||
|
||||
void list_super2(struct ext2_super_block * sb, FILE *f)
|
||||
{
|
||||
int inode_blocks_per_group;
|
||||
char buf[80], *str;
|
||||
time_t tm;
|
||||
|
||||
inode_blocks_per_group = (((sb->s_inodes_per_group *
|
||||
EXT2_INODE_SIZE(sb)) +
|
||||
EXT2_BLOCK_SIZE(sb) - 1) /
|
||||
EXT2_BLOCK_SIZE(sb));
|
||||
if (sb->s_volume_name[0]) {
|
||||
memset(buf, 0, sizeof(buf));
|
||||
strncpy(buf, sb->s_volume_name, sizeof(sb->s_volume_name));
|
||||
} else
|
||||
strcpy(buf, "<none>");
|
||||
fprintf(f, "Filesystem volume name: %s\n", buf);
|
||||
if (sb->s_last_mounted[0]) {
|
||||
memset(buf, 0, sizeof(buf));
|
||||
strncpy(buf, sb->s_last_mounted, sizeof(sb->s_last_mounted));
|
||||
} else
|
||||
strcpy(buf, "<not available>");
|
||||
fprintf(f,
|
||||
"Last mounted on: %s\n"
|
||||
"Filesystem UUID: %s\n"
|
||||
"Filesystem magic number: 0x%04X\n"
|
||||
"Filesystem revision #: %d",
|
||||
buf, e2p_uuid2str(sb->s_uuid), sb->s_magic, sb->s_rev_level);
|
||||
if (sb->s_rev_level == EXT2_GOOD_OLD_REV) {
|
||||
fprintf(f, " (original)\n");
|
||||
#ifdef EXT2_DYNAMIC_REV
|
||||
} else if (sb->s_rev_level == EXT2_DYNAMIC_REV) {
|
||||
fprintf(f, " (dynamic)\n");
|
||||
#endif
|
||||
} else
|
||||
fprintf(f, " (unknown)\n");
|
||||
print_features(sb, f);
|
||||
print_mntopts(sb, f);
|
||||
fprintf(f, "Filesystem state: ");
|
||||
print_fs_state (f, sb->s_state);
|
||||
fprintf(f, "\nErrors behavior: ");
|
||||
print_fs_errors(f, sb->s_errors);
|
||||
str = e2p_os2string(sb->s_creator_os);
|
||||
fprintf(f,
|
||||
"\n"
|
||||
"Filesystem OS type: %s\n"
|
||||
"Inode count: %u\n"
|
||||
"Block count: %u\n"
|
||||
"Reserved block count: %u\n"
|
||||
"Free blocks: %u\n"
|
||||
"Free inodes: %u\n"
|
||||
"First block: %u\n"
|
||||
"Block size: %u\n"
|
||||
"Fragment size: %u\n",
|
||||
str, sb->s_inodes_count, sb->s_blocks_count, sb->s_r_blocks_count,
|
||||
sb->s_free_blocks_count, sb->s_free_inodes_count,
|
||||
sb->s_first_data_block, EXT2_BLOCK_SIZE(sb), EXT2_FRAG_SIZE(sb));
|
||||
free(str);
|
||||
if (sb->s_reserved_gdt_blocks)
|
||||
fprintf(f, "Reserved GDT blocks: %u\n",
|
||||
sb->s_reserved_gdt_blocks);
|
||||
fprintf(f,
|
||||
"Blocks per group: %u\n"
|
||||
"Fragments per group: %u\n"
|
||||
"Inodes per group: %u\n"
|
||||
"Inode blocks per group: %u\n",
|
||||
sb->s_blocks_per_group, sb->s_frags_per_group,
|
||||
sb->s_inodes_per_group, inode_blocks_per_group);
|
||||
if (sb->s_first_meta_bg)
|
||||
fprintf(f, "First meta block group: %u\n",
|
||||
sb->s_first_meta_bg);
|
||||
if (sb->s_mkfs_time) {
|
||||
tm = sb->s_mkfs_time;
|
||||
fprintf(f, "Filesystem created: %s", ctime(&tm));
|
||||
}
|
||||
tm = sb->s_mtime;
|
||||
fprintf(f, "Last mount time: %s",
|
||||
sb->s_mtime ? ctime(&tm) : "n/a\n");
|
||||
tm = sb->s_wtime;
|
||||
fprintf(f,
|
||||
"Last write time: %s"
|
||||
"Mount count: %u\n"
|
||||
"Maximum mount count: %d\n",
|
||||
ctime(&tm), sb->s_mnt_count, sb->s_max_mnt_count);
|
||||
tm = sb->s_lastcheck;
|
||||
fprintf(f,
|
||||
"Last checked: %s"
|
||||
"Check interval: %u (%s)\n",
|
||||
ctime(&tm),
|
||||
sb->s_checkinterval, interval_string(sb->s_checkinterval));
|
||||
if (sb->s_checkinterval)
|
||||
{
|
||||
time_t next;
|
||||
|
||||
next = sb->s_lastcheck + sb->s_checkinterval;
|
||||
fprintf(f, "Next check after: %s", ctime(&next));
|
||||
}
|
||||
fprintf(f, "Reserved blocks uid: ");
|
||||
print_user(sb->s_def_resuid, f);
|
||||
fprintf(f, "Reserved blocks gid: ");
|
||||
print_group(sb->s_def_resgid, f);
|
||||
if (sb->s_rev_level >= EXT2_DYNAMIC_REV) {
|
||||
fprintf(f,
|
||||
"First inode: %d\n"
|
||||
"Inode size: %d\n",
|
||||
sb->s_first_ino, sb->s_inode_size);
|
||||
}
|
||||
if (!e2p_is_null_uuid(sb->s_journal_uuid))
|
||||
fprintf(f, "Journal UUID: %s\n",
|
||||
e2p_uuid2str(sb->s_journal_uuid));
|
||||
if (sb->s_journal_inum)
|
||||
fprintf(f, "Journal inode: %u\n",
|
||||
sb->s_journal_inum);
|
||||
if (sb->s_journal_dev)
|
||||
fprintf(f, "Journal device: 0x%04x\n",
|
||||
sb->s_journal_dev);
|
||||
if (sb->s_last_orphan)
|
||||
fprintf(f, "First orphan inode: %u\n",
|
||||
sb->s_last_orphan);
|
||||
if ((sb->s_feature_compat & EXT2_FEATURE_COMPAT_DIR_INDEX) ||
|
||||
sb->s_def_hash_version)
|
||||
fprintf(f, "Default directory hash: %s\n",
|
||||
e2p_hash2string(sb->s_def_hash_version));
|
||||
if (!e2p_is_null_uuid(sb->s_hash_seed))
|
||||
fprintf(f, "Directory Hash Seed: %s\n",
|
||||
e2p_uuid2str(sb->s_hash_seed));
|
||||
if (sb->s_jnl_backup_type) {
|
||||
fprintf(f, "Journal backup: ");
|
||||
if (sb->s_jnl_backup_type == 1)
|
||||
fprintf(f, "inode blocks\n");
|
||||
else
|
||||
fprintf(f, "type %u\n", sb->s_jnl_backup_type);
|
||||
}
|
||||
}
|
134
e2fsprogs/old_e2fsprogs/e2p/mntopts.c
Normal file
134
e2fsprogs/old_e2fsprogs/e2p/mntopts.c
Normal file
@ -0,0 +1,134 @@
|
||||
/* vi: set sw=4 ts=4: */
|
||||
/*
|
||||
* mountopts.c --- convert between default mount options and strings
|
||||
*
|
||||
* Copyright (C) 2002 Theodore Ts'o <tytso@mit.edu>
|
||||
*
|
||||
* This file can be redistributed under the terms of the GNU Library General
|
||||
* Public License
|
||||
*
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <ctype.h>
|
||||
#include <errno.h>
|
||||
|
||||
#include "e2p.h"
|
||||
|
||||
struct mntopt {
|
||||
unsigned int mask;
|
||||
const char *string;
|
||||
};
|
||||
|
||||
static const struct mntopt mntopt_list[] = {
|
||||
{ EXT2_DEFM_DEBUG, "debug" },
|
||||
{ EXT2_DEFM_BSDGROUPS, "bsdgroups" },
|
||||
{ EXT2_DEFM_XATTR_USER, "user_xattr" },
|
||||
{ EXT2_DEFM_ACL, "acl" },
|
||||
{ EXT2_DEFM_UID16, "uid16" },
|
||||
{ EXT3_DEFM_JMODE_DATA, "journal_data" },
|
||||
{ EXT3_DEFM_JMODE_ORDERED, "journal_data_ordered" },
|
||||
{ EXT3_DEFM_JMODE_WBACK, "journal_data_writeback" },
|
||||
{ 0, 0 },
|
||||
};
|
||||
|
||||
const char *e2p_mntopt2string(unsigned int mask)
|
||||
{
|
||||
const struct mntopt *f;
|
||||
static char buf[20];
|
||||
int fnum;
|
||||
|
||||
for (f = mntopt_list; f->string; f++) {
|
||||
if (mask == f->mask)
|
||||
return f->string;
|
||||
}
|
||||
for (fnum = 0; mask >>= 1; fnum++);
|
||||
sprintf(buf, "MNTOPT_%d", fnum);
|
||||
return buf;
|
||||
}
|
||||
|
||||
int e2p_string2mntopt(char *string, unsigned int *mask)
|
||||
{
|
||||
const struct mntopt *f;
|
||||
char *eptr;
|
||||
int num;
|
||||
|
||||
for (f = mntopt_list; f->string; f++) {
|
||||
if (!strcasecmp(string, f->string)) {
|
||||
*mask = f->mask;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
if (strncasecmp(string, "MNTOPT_", 8))
|
||||
return 1;
|
||||
|
||||
if (string[8] == 0)
|
||||
return 1;
|
||||
num = strtol(string+8, &eptr, 10);
|
||||
if (num > 32 || num < 0)
|
||||
return 1;
|
||||
if (*eptr)
|
||||
return 1;
|
||||
*mask = 1 << num;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static char *skip_over_blanks(char *cp)
|
||||
{
|
||||
while (*cp && isspace(*cp))
|
||||
cp++;
|
||||
return cp;
|
||||
}
|
||||
|
||||
static char *skip_over_word(char *cp)
|
||||
{
|
||||
while (*cp && !isspace(*cp) && *cp != ',')
|
||||
cp++;
|
||||
return cp;
|
||||
}
|
||||
|
||||
/*
|
||||
* Edit a mntopt set array as requested by the user. The ok
|
||||
* parameter, if non-zero, allows the application to limit what
|
||||
* mntopts the user is allowed to set or clear using this function.
|
||||
*/
|
||||
int e2p_edit_mntopts(const char *str, __u32 *mntopts, __u32 ok)
|
||||
{
|
||||
char *cp, *buf, *next;
|
||||
int neg;
|
||||
unsigned int mask;
|
||||
|
||||
buf = xstrdup(str);
|
||||
cp = buf;
|
||||
while (cp && *cp) {
|
||||
neg = 0;
|
||||
cp = skip_over_blanks(cp);
|
||||
next = skip_over_word(cp);
|
||||
if (*next == 0)
|
||||
next = 0;
|
||||
else
|
||||
*next = 0;
|
||||
switch (*cp) {
|
||||
case '-':
|
||||
case '^':
|
||||
neg++;
|
||||
case '+':
|
||||
cp++;
|
||||
break;
|
||||
}
|
||||
if (e2p_string2mntopt(cp, &mask))
|
||||
return 1;
|
||||
if (ok && !(ok & mask))
|
||||
return 1;
|
||||
if (mask & EXT3_DEFM_JMODE)
|
||||
*mntopts &= ~EXT3_DEFM_JMODE;
|
||||
if (neg)
|
||||
*mntopts &= ~mask;
|
||||
else
|
||||
*mntopts |= mask;
|
||||
cp = next ? next+1 : 0;
|
||||
}
|
||||
return 0;
|
||||
}
|
74
e2fsprogs/old_e2fsprogs/e2p/ostype.c
Normal file
74
e2fsprogs/old_e2fsprogs/e2p/ostype.c
Normal file
@ -0,0 +1,74 @@
|
||||
/* vi: set sw=4 ts=4: */
|
||||
/*
|
||||
* getostype.c - Get the Filesystem OS type
|
||||
*
|
||||
* Copyright (C) 2004,2005 Theodore Ts'o <tytso@mit.edu>
|
||||
*
|
||||
* This file can be redistributed under the terms of the GNU Library General
|
||||
* Public License
|
||||
*/
|
||||
|
||||
#include "e2p.h"
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
static const char * const os_tab[] =
|
||||
{ "Linux",
|
||||
"Hurd",
|
||||
"Masix",
|
||||
"FreeBSD",
|
||||
"Lites",
|
||||
0 };
|
||||
|
||||
/*
|
||||
* Convert an os_type to a string
|
||||
*/
|
||||
char *e2p_os2string(int os_type)
|
||||
{
|
||||
const char *os;
|
||||
char *ret;
|
||||
|
||||
if (os_type <= EXT2_OS_LITES)
|
||||
os = os_tab[os_type];
|
||||
else
|
||||
os = "(unknown os)";
|
||||
|
||||
ret = xstrdup(os);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
* Convert an os_type to a string
|
||||
*/
|
||||
int e2p_string2os(char *str)
|
||||
{
|
||||
const char * const *cpp;
|
||||
int i = 0;
|
||||
|
||||
for (cpp = os_tab; *cpp; cpp++, i++) {
|
||||
if (!strcasecmp(str, *cpp))
|
||||
return i;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
#ifdef TEST_PROGRAM
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
char *s;
|
||||
int i, os;
|
||||
|
||||
for (i=0; i <= EXT2_OS_LITES; i++) {
|
||||
s = e2p_os2string(i);
|
||||
os = e2p_string2os(s);
|
||||
printf("%d: %s (%d)\n", i, s, os);
|
||||
if (i != os) {
|
||||
fprintf(stderr, "Failure!\n");
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
exit(0);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
65
e2fsprogs/old_e2fsprogs/e2p/parse_num.c
Normal file
65
e2fsprogs/old_e2fsprogs/e2p/parse_num.c
Normal file
@ -0,0 +1,65 @@
|
||||
/* vi: set sw=4 ts=4: */
|
||||
/*
|
||||
* parse_num.c - Parse the number of blocks
|
||||
*
|
||||
* Copyright (C) 2004,2005 Theodore Ts'o <tytso@mit.edu>
|
||||
*
|
||||
* This file can be redistributed under the terms of the GNU Library General
|
||||
* Public License
|
||||
*/
|
||||
|
||||
#include "e2p.h"
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
unsigned long parse_num_blocks(const char *arg, int log_block_size)
|
||||
{
|
||||
char *p;
|
||||
unsigned long long num;
|
||||
|
||||
num = strtoull(arg, &p, 0);
|
||||
|
||||
if (p[0] && p[1])
|
||||
return 0;
|
||||
|
||||
switch (*p) { /* Using fall-through logic */
|
||||
case 'T': case 't':
|
||||
num <<= 10;
|
||||
case 'G': case 'g':
|
||||
num <<= 10;
|
||||
case 'M': case 'm':
|
||||
num <<= 10;
|
||||
case 'K': case 'k':
|
||||
num >>= log_block_size;
|
||||
break;
|
||||
case 's':
|
||||
num >>= 1;
|
||||
break;
|
||||
case '\0':
|
||||
break;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
return num;
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
#include <unistd.h>
|
||||
#include <stdio.h>
|
||||
|
||||
main(int argc, char **argv)
|
||||
{
|
||||
unsigned long num;
|
||||
int log_block_size = 0;
|
||||
|
||||
if (argc != 2) {
|
||||
fprintf(stderr, "Usage: %s arg\n", argv[0]);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
num = parse_num_blocks(argv[1], log_block_size);
|
||||
|
||||
printf("Parsed number: %lu\n", num);
|
||||
exit(0);
|
||||
}
|
||||
#endif
|
32
e2fsprogs/old_e2fsprogs/e2p/pe.c
Normal file
32
e2fsprogs/old_e2fsprogs/e2p/pe.c
Normal file
@ -0,0 +1,32 @@
|
||||
/* vi: set sw=4 ts=4: */
|
||||
/*
|
||||
* pe.c - Print a second extended filesystem errors behavior
|
||||
*
|
||||
* Copyright (C) 1992, 1993, 1994 Remy Card <card@masi.ibp.fr>
|
||||
* Laboratoire MASI, Institut Blaise Pascal
|
||||
* Universite Pierre et Marie Curie (Paris VI)
|
||||
*
|
||||
* This file can be redistributed under the terms of the GNU Library General
|
||||
* Public License
|
||||
*/
|
||||
|
||||
/*
|
||||
* History:
|
||||
* 94/01/09 - Creation
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#include "e2p.h"
|
||||
|
||||
void print_fs_errors(FILE *f, unsigned short errors)
|
||||
{
|
||||
char *disp = NULL;
|
||||
switch (errors) {
|
||||
case EXT2_ERRORS_CONTINUE: disp = "Continue"; break;
|
||||
case EXT2_ERRORS_RO: disp = "Remount read-only"; break;
|
||||
case EXT2_ERRORS_PANIC: disp = "Panic"; break;
|
||||
default: disp = "Unknown (continue)";
|
||||
}
|
||||
fprintf(f, disp);
|
||||
}
|
74
e2fsprogs/old_e2fsprogs/e2p/pf.c
Normal file
74
e2fsprogs/old_e2fsprogs/e2p/pf.c
Normal file
@ -0,0 +1,74 @@
|
||||
/* vi: set sw=4 ts=4: */
|
||||
/*
|
||||
* pf.c - Print file attributes on an ext2 file system
|
||||
*
|
||||
* Copyright (C) 1993, 1994 Remy Card <card@masi.ibp.fr>
|
||||
* Laboratoire MASI, Institut Blaise Pascal
|
||||
* Universite Pierre et Marie Curie (Paris VI)
|
||||
*
|
||||
* This file can be redistributed under the terms of the GNU Library General
|
||||
* Public License
|
||||
*/
|
||||
|
||||
/*
|
||||
* History:
|
||||
* 93/10/30 - Creation
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#include "e2p.h"
|
||||
|
||||
struct flags_name {
|
||||
unsigned long flag;
|
||||
const char *short_name;
|
||||
const char *long_name;
|
||||
};
|
||||
|
||||
static const struct flags_name flags_array[] = {
|
||||
{ EXT2_SECRM_FL, "s", "Secure_Deletion" },
|
||||
{ EXT2_UNRM_FL, "u" , "Undelete" },
|
||||
{ EXT2_SYNC_FL, "S", "Synchronous_Updates" },
|
||||
{ EXT2_DIRSYNC_FL, "D", "Synchronous_Directory_Updates" },
|
||||
{ EXT2_IMMUTABLE_FL, "i", "Immutable" },
|
||||
{ EXT2_APPEND_FL, "a", "Append_Only" },
|
||||
{ EXT2_NODUMP_FL, "d", "No_Dump" },
|
||||
{ EXT2_NOATIME_FL, "A", "No_Atime" },
|
||||
{ EXT2_COMPR_FL, "c", "Compression_Requested" },
|
||||
#ifdef ENABLE_COMPRESSION
|
||||
{ EXT2_COMPRBLK_FL, "B", "Compressed_File" },
|
||||
{ EXT2_DIRTY_FL, "Z", "Compressed_Dirty_File" },
|
||||
{ EXT2_NOCOMPR_FL, "X", "Compression_Raw_Access" },
|
||||
{ EXT2_ECOMPR_FL, "E", "Compression_Error" },
|
||||
#endif
|
||||
{ EXT3_JOURNAL_DATA_FL, "j", "Journaled_Data" },
|
||||
{ EXT2_INDEX_FL, "I", "Indexed_direcctory" },
|
||||
{ EXT2_NOTAIL_FL, "t", "No_Tailmerging" },
|
||||
{ EXT2_TOPDIR_FL, "T", "Top_of_Directory_Hierarchies" },
|
||||
{ 0, NULL, NULL }
|
||||
};
|
||||
|
||||
void print_flags (FILE * f, unsigned long flags, unsigned options)
|
||||
{
|
||||
int long_opt = (options & PFOPT_LONG);
|
||||
const struct flags_name *fp;
|
||||
int first = 1;
|
||||
|
||||
for (fp = flags_array; fp->flag != 0; fp++) {
|
||||
if (flags & fp->flag) {
|
||||
if (long_opt) {
|
||||
if (first)
|
||||
first = 0;
|
||||
else
|
||||
fputs(", ", f);
|
||||
fputs(fp->long_name, f);
|
||||
} else
|
||||
fputs(fp->short_name, f);
|
||||
} else {
|
||||
if (!long_opt)
|
||||
fputs("-", f);
|
||||
}
|
||||
}
|
||||
if (long_opt && first)
|
||||
fputs("---", f);
|
||||
}
|
27
e2fsprogs/old_e2fsprogs/e2p/ps.c
Normal file
27
e2fsprogs/old_e2fsprogs/e2p/ps.c
Normal file
@ -0,0 +1,27 @@
|
||||
/* vi: set sw=4 ts=4: */
|
||||
/*
|
||||
* ps.c - Print filesystem state
|
||||
*
|
||||
* Copyright (C) 1993, 1994 Remy Card <card@masi.ibp.fr>
|
||||
* Laboratoire MASI, Institut Blaise Pascal
|
||||
* Universite Pierre et Marie Curie (Paris VI)
|
||||
*
|
||||
* This file can be redistributed under the terms of the GNU Library General
|
||||
* Public License
|
||||
*/
|
||||
|
||||
/*
|
||||
* History:
|
||||
* 93/12/22 - Creation
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#include "e2p.h"
|
||||
|
||||
void print_fs_state(FILE *f, unsigned short state)
|
||||
{
|
||||
fprintf(f, (state & EXT2_VALID_FS ? " clean" : " not clean"));
|
||||
if (state & EXT2_ERROR_FS)
|
||||
fprintf(f, " with errors");
|
||||
}
|
78
e2fsprogs/old_e2fsprogs/e2p/uuid.c
Normal file
78
e2fsprogs/old_e2fsprogs/e2p/uuid.c
Normal file
@ -0,0 +1,78 @@
|
||||
/* vi: set sw=4 ts=4: */
|
||||
/*
|
||||
* uuid.c -- utility routines for manipulating UUID's.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include "../ext2fs/ext2_types.h"
|
||||
|
||||
#include "e2p.h"
|
||||
|
||||
struct uuid {
|
||||
__u32 time_low;
|
||||
__u16 time_mid;
|
||||
__u16 time_hi_and_version;
|
||||
__u16 clock_seq;
|
||||
__u8 node[6];
|
||||
};
|
||||
|
||||
/* Returns 1 if the uuid is the NULL uuid */
|
||||
int e2p_is_null_uuid(void *uu)
|
||||
{
|
||||
__u8 *cp;
|
||||
int i;
|
||||
|
||||
for (i=0, cp = uu; i < 16; i++)
|
||||
if (*cp)
|
||||
return 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
static void e2p_unpack_uuid(void *in, struct uuid *uu)
|
||||
{
|
||||
__u8 *ptr = in;
|
||||
__u32 tmp;
|
||||
|
||||
tmp = *ptr++;
|
||||
tmp = (tmp << 8) | *ptr++;
|
||||
tmp = (tmp << 8) | *ptr++;
|
||||
tmp = (tmp << 8) | *ptr++;
|
||||
uu->time_low = tmp;
|
||||
|
||||
tmp = *ptr++;
|
||||
tmp = (tmp << 8) | *ptr++;
|
||||
uu->time_mid = tmp;
|
||||
|
||||
tmp = *ptr++;
|
||||
tmp = (tmp << 8) | *ptr++;
|
||||
uu->time_hi_and_version = tmp;
|
||||
|
||||
tmp = *ptr++;
|
||||
tmp = (tmp << 8) | *ptr++;
|
||||
uu->clock_seq = tmp;
|
||||
|
||||
memcpy(uu->node, ptr, 6);
|
||||
}
|
||||
|
||||
void e2p_uuid_to_str(void *uu, char *out)
|
||||
{
|
||||
struct uuid uuid;
|
||||
|
||||
e2p_unpack_uuid(uu, &uuid);
|
||||
sprintf(out,
|
||||
"%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x",
|
||||
uuid.time_low, uuid.time_mid, uuid.time_hi_and_version,
|
||||
uuid.clock_seq >> 8, uuid.clock_seq & 0xFF,
|
||||
uuid.node[0], uuid.node[1], uuid.node[2],
|
||||
uuid.node[3], uuid.node[4], uuid.node[5]);
|
||||
}
|
||||
|
||||
const char *e2p_uuid2str(void *uu)
|
||||
{
|
||||
static char buf[80];
|
||||
if (e2p_is_null_uuid(uu))
|
||||
return "<none>";
|
||||
e2p_uuid_to_str(uu, buf);
|
||||
return buf;
|
||||
}
|
23
e2fsprogs/old_e2fsprogs/ext2fs/Kbuild
Normal file
23
e2fsprogs/old_e2fsprogs/ext2fs/Kbuild
Normal file
@ -0,0 +1,23 @@
|
||||
# Makefile for busybox
|
||||
#
|
||||
# Copyright (C) 1999-2005 by Erik Andersen <andersen@codepoet.org>
|
||||
#
|
||||
# Licensed under the GPL v2, see the file LICENSE in this tarball.
|
||||
|
||||
NEEDED-$(CONFIG_E2FSCK) = y
|
||||
NEEDED-$(CONFIG_FSCK) = y
|
||||
NEEDED-$(CONFIG_MKE2FS) = y
|
||||
NEEDED-$(CONFIG_TUNE2FS) = y
|
||||
|
||||
lib-y:=
|
||||
lib-$(NEEDED-y) += gen_bitmap.o bitops.o ismounted.o mkjournal.o unix_io.o \
|
||||
rw_bitmaps.o initialize.o bitmaps.o block.o \
|
||||
ind_block.o inode.o freefs.o alloc_stats.o closefs.o \
|
||||
openfs.o io_manager.o finddev.o read_bb.o alloc.o badblocks.o \
|
||||
getsize.o getsectsize.o alloc_tables.o read_bb_file.o mkdir.o \
|
||||
bb_inode.o newdir.o alloc_sb.o lookup.o dirblock.o expanddir.o \
|
||||
dir_iterate.o link.o res_gdt.o icount.o get_pathname.o dblist.o \
|
||||
dirhash.o version.o flushb.o unlink.o check_desc.o valid_blk.o \
|
||||
ext_attr.o bmap.o dblist_dir.o ext2fs_inline.o swapfs.o
|
||||
|
||||
CFLAGS += -include $(srctree)/e2fsprogs/e2fsbb.h
|
174
e2fsprogs/old_e2fsprogs/ext2fs/alloc.c
Normal file
174
e2fsprogs/old_e2fsprogs/ext2fs/alloc.c
Normal file
@ -0,0 +1,174 @@
|
||||
/* vi: set sw=4 ts=4: */
|
||||
/*
|
||||
* alloc.c --- allocate new inodes, blocks for ext2fs
|
||||
*
|
||||
* Copyright (C) 1993, 1994, 1995, 1996 Theodore Ts'o.
|
||||
*
|
||||
* %Begin-Header%
|
||||
* This file may be redistributed under the terms of the GNU Public
|
||||
* License.
|
||||
* %End-Header%
|
||||
*
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#if HAVE_UNISTD_H
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
#include <time.h>
|
||||
#include <string.h>
|
||||
#if HAVE_SYS_STAT_H
|
||||
#include <sys/stat.h>
|
||||
#endif
|
||||
#if HAVE_SYS_TYPES_H
|
||||
#include <sys/types.h>
|
||||
#endif
|
||||
|
||||
#include "ext2_fs.h"
|
||||
#include "ext2fs.h"
|
||||
|
||||
/*
|
||||
* Right now, just search forward from the parent directory's block
|
||||
* group to find the next free inode.
|
||||
*
|
||||
* Should have a special policy for directories.
|
||||
*/
|
||||
errcode_t ext2fs_new_inode(ext2_filsys fs, ext2_ino_t dir,
|
||||
int mode EXT2FS_ATTR((unused)),
|
||||
ext2fs_inode_bitmap map, ext2_ino_t *ret)
|
||||
{
|
||||
ext2_ino_t dir_group = 0;
|
||||
ext2_ino_t i;
|
||||
ext2_ino_t start_inode;
|
||||
|
||||
EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS);
|
||||
|
||||
if (!map)
|
||||
map = fs->inode_map;
|
||||
if (!map)
|
||||
return EXT2_ET_NO_INODE_BITMAP;
|
||||
|
||||
if (dir > 0)
|
||||
dir_group = (dir - 1) / EXT2_INODES_PER_GROUP(fs->super);
|
||||
|
||||
start_inode = (dir_group * EXT2_INODES_PER_GROUP(fs->super)) + 1;
|
||||
if (start_inode < EXT2_FIRST_INODE(fs->super))
|
||||
start_inode = EXT2_FIRST_INODE(fs->super);
|
||||
i = start_inode;
|
||||
|
||||
do {
|
||||
if (!ext2fs_fast_test_inode_bitmap(map, i))
|
||||
break;
|
||||
i++;
|
||||
if (i > fs->super->s_inodes_count)
|
||||
i = EXT2_FIRST_INODE(fs->super);
|
||||
} while (i != start_inode);
|
||||
|
||||
if (ext2fs_test_inode_bitmap(map, i))
|
||||
return EXT2_ET_INODE_ALLOC_FAIL;
|
||||
*ret = i;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Stupid algorithm --- we now just search forward starting from the
|
||||
* goal. Should put in a smarter one someday....
|
||||
*/
|
||||
errcode_t ext2fs_new_block(ext2_filsys fs, blk_t goal,
|
||||
ext2fs_block_bitmap map, blk_t *ret)
|
||||
{
|
||||
blk_t i;
|
||||
|
||||
EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS);
|
||||
|
||||
if (!map)
|
||||
map = fs->block_map;
|
||||
if (!map)
|
||||
return EXT2_ET_NO_BLOCK_BITMAP;
|
||||
if (!goal || (goal >= fs->super->s_blocks_count))
|
||||
goal = fs->super->s_first_data_block;
|
||||
i = goal;
|
||||
do {
|
||||
if (!ext2fs_fast_test_block_bitmap(map, i)) {
|
||||
*ret = i;
|
||||
return 0;
|
||||
}
|
||||
i++;
|
||||
if (i >= fs->super->s_blocks_count)
|
||||
i = fs->super->s_first_data_block;
|
||||
} while (i != goal);
|
||||
return EXT2_ET_BLOCK_ALLOC_FAIL;
|
||||
}
|
||||
|
||||
/*
|
||||
* This function zeros out the allocated block, and updates all of the
|
||||
* appropriate filesystem records.
|
||||
*/
|
||||
errcode_t ext2fs_alloc_block(ext2_filsys fs, blk_t goal,
|
||||
char *block_buf, blk_t *ret)
|
||||
{
|
||||
errcode_t retval;
|
||||
blk_t block;
|
||||
char *buf = 0;
|
||||
|
||||
if (!block_buf) {
|
||||
retval = ext2fs_get_mem(fs->blocksize, &buf);
|
||||
if (retval)
|
||||
return retval;
|
||||
block_buf = buf;
|
||||
}
|
||||
memset(block_buf, 0, fs->blocksize);
|
||||
|
||||
if (!fs->block_map) {
|
||||
retval = ext2fs_read_block_bitmap(fs);
|
||||
if (retval)
|
||||
goto fail;
|
||||
}
|
||||
|
||||
retval = ext2fs_new_block(fs, goal, 0, &block);
|
||||
if (retval)
|
||||
goto fail;
|
||||
|
||||
retval = io_channel_write_blk(fs->io, block, 1, block_buf);
|
||||
if (retval)
|
||||
goto fail;
|
||||
|
||||
ext2fs_block_alloc_stats(fs, block, +1);
|
||||
*ret = block;
|
||||
return 0;
|
||||
|
||||
fail:
|
||||
if (buf)
|
||||
ext2fs_free_mem(&buf);
|
||||
return retval;
|
||||
}
|
||||
|
||||
errcode_t ext2fs_get_free_blocks(ext2_filsys fs, blk_t start, blk_t finish,
|
||||
int num, ext2fs_block_bitmap map, blk_t *ret)
|
||||
{
|
||||
blk_t b = start;
|
||||
|
||||
EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS);
|
||||
|
||||
if (!map)
|
||||
map = fs->block_map;
|
||||
if (!map)
|
||||
return EXT2_ET_NO_BLOCK_BITMAP;
|
||||
if (!b)
|
||||
b = fs->super->s_first_data_block;
|
||||
if (!finish)
|
||||
finish = start;
|
||||
if (!num)
|
||||
num = 1;
|
||||
do {
|
||||
if (b+num-1 > fs->super->s_blocks_count)
|
||||
b = fs->super->s_first_data_block;
|
||||
if (ext2fs_fast_test_block_bitmap_range(map, b, num)) {
|
||||
*ret = b;
|
||||
return 0;
|
||||
}
|
||||
b++;
|
||||
} while (b != finish);
|
||||
return EXT2_ET_BLOCK_ALLOC_FAIL;
|
||||
}
|
||||
|
58
e2fsprogs/old_e2fsprogs/ext2fs/alloc_sb.c
Normal file
58
e2fsprogs/old_e2fsprogs/ext2fs/alloc_sb.c
Normal file
@ -0,0 +1,58 @@
|
||||
/* vi: set sw=4 ts=4: */
|
||||
/*
|
||||
* alloc_sb.c --- Allocate the superblock and block group descriptors for a
|
||||
* newly initialized filesystem. Used by mke2fs when initializing a filesystem
|
||||
*
|
||||
* Copyright (C) 1994, 1995, 1996, 2003 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>
|
||||
#if HAVE_UNISTD_H
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
#include <fcntl.h>
|
||||
#include <time.h>
|
||||
#if HAVE_SYS_STAT_H
|
||||
#include <sys/stat.h>
|
||||
#endif
|
||||
#if HAVE_SYS_TYPES_H
|
||||
#include <sys/types.h>
|
||||
#endif
|
||||
|
||||
#include "ext2_fs.h"
|
||||
#include "ext2fs.h"
|
||||
|
||||
int ext2fs_reserve_super_and_bgd(ext2_filsys fs,
|
||||
dgrp_t group,
|
||||
ext2fs_block_bitmap bmap)
|
||||
{
|
||||
blk_t super_blk, old_desc_blk, new_desc_blk;
|
||||
int j, old_desc_blocks, num_blocks;
|
||||
|
||||
num_blocks = ext2fs_super_and_bgd_loc(fs, group, &super_blk,
|
||||
&old_desc_blk, &new_desc_blk, 0);
|
||||
|
||||
if (fs->super->s_feature_incompat & EXT2_FEATURE_INCOMPAT_META_BG)
|
||||
old_desc_blocks = fs->super->s_first_meta_bg;
|
||||
else
|
||||
old_desc_blocks =
|
||||
fs->desc_blocks + fs->super->s_reserved_gdt_blocks;
|
||||
|
||||
if (super_blk || (group == 0))
|
||||
ext2fs_mark_block_bitmap(bmap, super_blk);
|
||||
|
||||
if (old_desc_blk) {
|
||||
for (j=0; j < old_desc_blocks; j++)
|
||||
ext2fs_mark_block_bitmap(bmap, old_desc_blk + j);
|
||||
}
|
||||
if (new_desc_blk)
|
||||
ext2fs_mark_block_bitmap(bmap, new_desc_blk);
|
||||
|
||||
return num_blocks;
|
||||
}
|
53
e2fsprogs/old_e2fsprogs/ext2fs/alloc_stats.c
Normal file
53
e2fsprogs/old_e2fsprogs/ext2fs/alloc_stats.c
Normal file
@ -0,0 +1,53 @@
|
||||
/* vi: set sw=4 ts=4: */
|
||||
/*
|
||||
* alloc_stats.c --- Update allocation statistics for ext2fs
|
||||
*
|
||||
* Copyright (C) 2001 Theodore Ts'o.
|
||||
*
|
||||
* %Begin-Header%
|
||||
* This file may be redistributed under the terms of the GNU Public
|
||||
* License.
|
||||
* %End-Header%
|
||||
*
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#include "ext2_fs.h"
|
||||
#include "ext2fs.h"
|
||||
|
||||
void ext2fs_inode_alloc_stats2(ext2_filsys fs, ext2_ino_t ino,
|
||||
int inuse, int isdir)
|
||||
{
|
||||
int group = ext2fs_group_of_ino(fs, ino);
|
||||
|
||||
if (inuse > 0)
|
||||
ext2fs_mark_inode_bitmap(fs->inode_map, ino);
|
||||
else
|
||||
ext2fs_unmark_inode_bitmap(fs->inode_map, ino);
|
||||
fs->group_desc[group].bg_free_inodes_count -= inuse;
|
||||
if (isdir)
|
||||
fs->group_desc[group].bg_used_dirs_count += inuse;
|
||||
fs->super->s_free_inodes_count -= inuse;
|
||||
ext2fs_mark_super_dirty(fs);
|
||||
ext2fs_mark_ib_dirty(fs);
|
||||
}
|
||||
|
||||
void ext2fs_inode_alloc_stats(ext2_filsys fs, ext2_ino_t ino, int inuse)
|
||||
{
|
||||
ext2fs_inode_alloc_stats2(fs, ino, inuse, 0);
|
||||
}
|
||||
|
||||
void ext2fs_block_alloc_stats(ext2_filsys fs, blk_t blk, int inuse)
|
||||
{
|
||||
int group = ext2fs_group_of_blk(fs, blk);
|
||||
|
||||
if (inuse > 0)
|
||||
ext2fs_mark_block_bitmap(fs->block_map, blk);
|
||||
else
|
||||
ext2fs_unmark_block_bitmap(fs->block_map, blk);
|
||||
fs->group_desc[group].bg_free_blocks_count -= inuse;
|
||||
fs->super->s_free_blocks_count -= inuse;
|
||||
ext2fs_mark_super_dirty(fs);
|
||||
ext2fs_mark_bb_dirty(fs);
|
||||
}
|
118
e2fsprogs/old_e2fsprogs/ext2fs/alloc_tables.c
Normal file
118
e2fsprogs/old_e2fsprogs/ext2fs/alloc_tables.c
Normal file
@ -0,0 +1,118 @@
|
||||
/* vi: set sw=4 ts=4: */
|
||||
/*
|
||||
* alloc_tables.c --- Allocate tables for a newly initialized
|
||||
* filesystem. Used by mke2fs when initializing a filesystem
|
||||
*
|
||||
* Copyright (C) 1996 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>
|
||||
#if HAVE_UNISTD_H
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
#include <fcntl.h>
|
||||
#include <time.h>
|
||||
#if HAVE_SYS_STAT_H
|
||||
#include <sys/stat.h>
|
||||
#endif
|
||||
#if HAVE_SYS_TYPES_H
|
||||
#include <sys/types.h>
|
||||
#endif
|
||||
|
||||
#include "ext2_fs.h"
|
||||
#include "ext2fs.h"
|
||||
|
||||
errcode_t ext2fs_allocate_group_table(ext2_filsys fs, dgrp_t group,
|
||||
ext2fs_block_bitmap bmap)
|
||||
{
|
||||
errcode_t retval;
|
||||
blk_t group_blk, start_blk, last_blk, new_blk, blk;
|
||||
int j;
|
||||
|
||||
group_blk = fs->super->s_first_data_block +
|
||||
(group * fs->super->s_blocks_per_group);
|
||||
|
||||
last_blk = group_blk + fs->super->s_blocks_per_group;
|
||||
if (last_blk >= fs->super->s_blocks_count)
|
||||
last_blk = fs->super->s_blocks_count - 1;
|
||||
|
||||
if (!bmap)
|
||||
bmap = fs->block_map;
|
||||
|
||||
/*
|
||||
* Allocate the block and inode bitmaps, if necessary
|
||||
*/
|
||||
if (fs->stride) {
|
||||
start_blk = group_blk + fs->inode_blocks_per_group;
|
||||
start_blk += ((fs->stride * group) %
|
||||
(last_blk - start_blk));
|
||||
if (start_blk > last_blk)
|
||||
start_blk = group_blk;
|
||||
} else
|
||||
start_blk = group_blk;
|
||||
|
||||
if (!fs->group_desc[group].bg_block_bitmap) {
|
||||
retval = ext2fs_get_free_blocks(fs, start_blk, last_blk,
|
||||
1, bmap, &new_blk);
|
||||
if (retval == EXT2_ET_BLOCK_ALLOC_FAIL)
|
||||
retval = ext2fs_get_free_blocks(fs, group_blk,
|
||||
last_blk, 1, bmap, &new_blk);
|
||||
if (retval)
|
||||
return retval;
|
||||
ext2fs_mark_block_bitmap(bmap, new_blk);
|
||||
fs->group_desc[group].bg_block_bitmap = new_blk;
|
||||
}
|
||||
|
||||
if (!fs->group_desc[group].bg_inode_bitmap) {
|
||||
retval = ext2fs_get_free_blocks(fs, start_blk, last_blk,
|
||||
1, bmap, &new_blk);
|
||||
if (retval == EXT2_ET_BLOCK_ALLOC_FAIL)
|
||||
retval = ext2fs_get_free_blocks(fs, group_blk,
|
||||
last_blk, 1, bmap, &new_blk);
|
||||
if (retval)
|
||||
return retval;
|
||||
ext2fs_mark_block_bitmap(bmap, new_blk);
|
||||
fs->group_desc[group].bg_inode_bitmap = new_blk;
|
||||
}
|
||||
|
||||
/*
|
||||
* Allocate the inode table
|
||||
*/
|
||||
if (!fs->group_desc[group].bg_inode_table) {
|
||||
retval = ext2fs_get_free_blocks(fs, group_blk, last_blk,
|
||||
fs->inode_blocks_per_group,
|
||||
bmap, &new_blk);
|
||||
if (retval)
|
||||
return retval;
|
||||
for (j=0, blk = new_blk;
|
||||
j < fs->inode_blocks_per_group;
|
||||
j++, blk++)
|
||||
ext2fs_mark_block_bitmap(bmap, blk);
|
||||
fs->group_desc[group].bg_inode_table = new_blk;
|
||||
}
|
||||
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
errcode_t ext2fs_allocate_tables(ext2_filsys fs)
|
||||
{
|
||||
errcode_t retval;
|
||||
dgrp_t i;
|
||||
|
||||
for (i = 0; i < fs->group_desc_count; i++) {
|
||||
retval = ext2fs_allocate_group_table(fs, i, fs->block_map);
|
||||
if (retval)
|
||||
return retval;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
328
e2fsprogs/old_e2fsprogs/ext2fs/badblocks.c
Normal file
328
e2fsprogs/old_e2fsprogs/ext2fs/badblocks.c
Normal file
@ -0,0 +1,328 @@
|
||||
/* vi: set sw=4 ts=4: */
|
||||
/*
|
||||
* badblocks.c --- routines to manipulate the bad block structure
|
||||
*
|
||||
* Copyright (C) 1994, 1995, 1996 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>
|
||||
#if HAVE_UNISTD_H
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
#include <fcntl.h>
|
||||
#include <time.h>
|
||||
#if HAVE_SYS_STAT_H
|
||||
#include <sys/stat.h>
|
||||
#endif
|
||||
#if HAVE_SYS_TYPES_H
|
||||
#include <sys/types.h>
|
||||
#endif
|
||||
|
||||
#include "ext2_fs.h"
|
||||
#include "ext2fsP.h"
|
||||
|
||||
/*
|
||||
* Helper function for making a badblocks list
|
||||
*/
|
||||
static errcode_t make_u32_list(int size, int num, __u32 *list,
|
||||
ext2_u32_list *ret)
|
||||
{
|
||||
ext2_u32_list bb;
|
||||
errcode_t retval;
|
||||
|
||||
retval = ext2fs_get_mem(sizeof(struct ext2_struct_u32_list), &bb);
|
||||
if (retval)
|
||||
return retval;
|
||||
memset(bb, 0, sizeof(struct ext2_struct_u32_list));
|
||||
bb->magic = EXT2_ET_MAGIC_BADBLOCKS_LIST;
|
||||
bb->size = size ? size : 10;
|
||||
bb->num = num;
|
||||
retval = ext2fs_get_mem(bb->size * sizeof(blk_t), &bb->list);
|
||||
if (!bb->list) {
|
||||
ext2fs_free_mem(&bb);
|
||||
return retval;
|
||||
}
|
||||
if (list)
|
||||
memcpy(bb->list, list, bb->size * sizeof(blk_t));
|
||||
else
|
||||
memset(bb->list, 0, bb->size * sizeof(blk_t));
|
||||
*ret = bb;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* This procedure creates an empty u32 list.
|
||||
*/
|
||||
errcode_t ext2fs_u32_list_create(ext2_u32_list *ret, int size)
|
||||
{
|
||||
return make_u32_list(size, 0, 0, ret);
|
||||
}
|
||||
|
||||
/*
|
||||
* This procedure creates an empty badblocks list.
|
||||
*/
|
||||
errcode_t ext2fs_badblocks_list_create(ext2_badblocks_list *ret, int size)
|
||||
{
|
||||
return make_u32_list(size, 0, 0, (ext2_badblocks_list *) ret);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* This procedure copies a badblocks list
|
||||
*/
|
||||
errcode_t ext2fs_u32_copy(ext2_u32_list src, ext2_u32_list *dest)
|
||||
{
|
||||
errcode_t retval;
|
||||
|
||||
retval = make_u32_list(src->size, src->num, src->list, dest);
|
||||
if (retval)
|
||||
return retval;
|
||||
(*dest)->badblocks_flags = src->badblocks_flags;
|
||||
return 0;
|
||||
}
|
||||
|
||||
errcode_t ext2fs_badblocks_copy(ext2_badblocks_list src,
|
||||
ext2_badblocks_list *dest)
|
||||
{
|
||||
return ext2fs_u32_copy((ext2_u32_list) src,
|
||||
(ext2_u32_list *) dest);
|
||||
}
|
||||
|
||||
/*
|
||||
* This procedure frees a badblocks list.
|
||||
*
|
||||
* (note: moved to closefs.c)
|
||||
*/
|
||||
|
||||
|
||||
/*
|
||||
* This procedure adds a block to a badblocks list.
|
||||
*/
|
||||
errcode_t ext2fs_u32_list_add(ext2_u32_list bb, __u32 blk)
|
||||
{
|
||||
errcode_t retval;
|
||||
int i, j;
|
||||
unsigned long old_size;
|
||||
|
||||
EXT2_CHECK_MAGIC(bb, EXT2_ET_MAGIC_BADBLOCKS_LIST);
|
||||
|
||||
if (bb->num >= bb->size) {
|
||||
old_size = bb->size * sizeof(__u32);
|
||||
bb->size += 100;
|
||||
retval = ext2fs_resize_mem(old_size, bb->size * sizeof(__u32),
|
||||
&bb->list);
|
||||
if (retval) {
|
||||
bb->size -= 100;
|
||||
return retval;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Add special case code for appending to the end of the list
|
||||
*/
|
||||
i = bb->num-1;
|
||||
if ((bb->num != 0) && (bb->list[i] == blk))
|
||||
return 0;
|
||||
if ((bb->num == 0) || (bb->list[i] < blk)) {
|
||||
bb->list[bb->num++] = blk;
|
||||
return 0;
|
||||
}
|
||||
|
||||
j = bb->num;
|
||||
for (i=0; i < bb->num; i++) {
|
||||
if (bb->list[i] == blk)
|
||||
return 0;
|
||||
if (bb->list[i] > blk) {
|
||||
j = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
for (i=bb->num; i > j; i--)
|
||||
bb->list[i] = bb->list[i-1];
|
||||
bb->list[j] = blk;
|
||||
bb->num++;
|
||||
return 0;
|
||||
}
|
||||
|
||||
errcode_t ext2fs_badblocks_list_add(ext2_badblocks_list bb, blk_t blk)
|
||||
{
|
||||
return ext2fs_u32_list_add((ext2_u32_list) bb, (__u32) blk);
|
||||
}
|
||||
|
||||
/*
|
||||
* This procedure finds a particular block is on a badblocks
|
||||
* list.
|
||||
*/
|
||||
int ext2fs_u32_list_find(ext2_u32_list bb, __u32 blk)
|
||||
{
|
||||
int low, high, mid;
|
||||
|
||||
if (bb->magic != EXT2_ET_MAGIC_BADBLOCKS_LIST)
|
||||
return -1;
|
||||
|
||||
if (bb->num == 0)
|
||||
return -1;
|
||||
|
||||
low = 0;
|
||||
high = bb->num-1;
|
||||
if (blk == bb->list[low])
|
||||
return low;
|
||||
if (blk == bb->list[high])
|
||||
return high;
|
||||
|
||||
while (low < high) {
|
||||
mid = (low+high)/2;
|
||||
if (mid == low || mid == high)
|
||||
break;
|
||||
if (blk == bb->list[mid])
|
||||
return mid;
|
||||
if (blk < bb->list[mid])
|
||||
high = mid;
|
||||
else
|
||||
low = mid;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
/*
|
||||
* This procedure tests to see if a particular block is on a badblocks
|
||||
* list.
|
||||
*/
|
||||
int ext2fs_u32_list_test(ext2_u32_list bb, __u32 blk)
|
||||
{
|
||||
if (ext2fs_u32_list_find(bb, blk) < 0)
|
||||
return 0;
|
||||
else
|
||||
return 1;
|
||||
}
|
||||
|
||||
int ext2fs_badblocks_list_test(ext2_badblocks_list bb, blk_t blk)
|
||||
{
|
||||
return ext2fs_u32_list_test((ext2_u32_list) bb, (__u32) blk);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Remove a block from the badblock list
|
||||
*/
|
||||
int ext2fs_u32_list_del(ext2_u32_list bb, __u32 blk)
|
||||
{
|
||||
int remloc, i;
|
||||
|
||||
if (bb->num == 0)
|
||||
return -1;
|
||||
|
||||
remloc = ext2fs_u32_list_find(bb, blk);
|
||||
if (remloc < 0)
|
||||
return -1;
|
||||
|
||||
for (i = remloc ; i < bb->num-1; i++)
|
||||
bb->list[i] = bb->list[i+1];
|
||||
bb->num--;
|
||||
return 0;
|
||||
}
|
||||
|
||||
void ext2fs_badblocks_list_del(ext2_u32_list bb, __u32 blk)
|
||||
{
|
||||
ext2fs_u32_list_del(bb, blk);
|
||||
}
|
||||
|
||||
errcode_t ext2fs_u32_list_iterate_begin(ext2_u32_list bb,
|
||||
ext2_u32_iterate *ret)
|
||||
{
|
||||
ext2_u32_iterate iter;
|
||||
errcode_t retval;
|
||||
|
||||
EXT2_CHECK_MAGIC(bb, EXT2_ET_MAGIC_BADBLOCKS_LIST);
|
||||
|
||||
retval = ext2fs_get_mem(sizeof(struct ext2_struct_u32_iterate), &iter);
|
||||
if (retval)
|
||||
return retval;
|
||||
|
||||
iter->magic = EXT2_ET_MAGIC_BADBLOCKS_ITERATE;
|
||||
iter->bb = bb;
|
||||
iter->ptr = 0;
|
||||
*ret = iter;
|
||||
return 0;
|
||||
}
|
||||
|
||||
errcode_t ext2fs_badblocks_list_iterate_begin(ext2_badblocks_list bb,
|
||||
ext2_badblocks_iterate *ret)
|
||||
{
|
||||
return ext2fs_u32_list_iterate_begin((ext2_u32_list) bb,
|
||||
(ext2_u32_iterate *) ret);
|
||||
}
|
||||
|
||||
|
||||
int ext2fs_u32_list_iterate(ext2_u32_iterate iter, __u32 *blk)
|
||||
{
|
||||
ext2_u32_list bb;
|
||||
|
||||
if (iter->magic != EXT2_ET_MAGIC_BADBLOCKS_ITERATE)
|
||||
return 0;
|
||||
|
||||
bb = iter->bb;
|
||||
|
||||
if (bb->magic != EXT2_ET_MAGIC_BADBLOCKS_LIST)
|
||||
return 0;
|
||||
|
||||
if (iter->ptr < bb->num) {
|
||||
*blk = bb->list[iter->ptr++];
|
||||
return 1;
|
||||
}
|
||||
*blk = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int ext2fs_badblocks_list_iterate(ext2_badblocks_iterate iter, blk_t *blk)
|
||||
{
|
||||
return ext2fs_u32_list_iterate((ext2_u32_iterate) iter,
|
||||
(__u32 *) blk);
|
||||
}
|
||||
|
||||
|
||||
void ext2fs_u32_list_iterate_end(ext2_u32_iterate iter)
|
||||
{
|
||||
if (!iter || (iter->magic != EXT2_ET_MAGIC_BADBLOCKS_ITERATE))
|
||||
return;
|
||||
|
||||
iter->bb = 0;
|
||||
ext2fs_free_mem(&iter);
|
||||
}
|
||||
|
||||
void ext2fs_badblocks_list_iterate_end(ext2_badblocks_iterate iter)
|
||||
{
|
||||
ext2fs_u32_list_iterate_end((ext2_u32_iterate) iter);
|
||||
}
|
||||
|
||||
|
||||
int ext2fs_u32_list_equal(ext2_u32_list bb1, ext2_u32_list bb2)
|
||||
{
|
||||
EXT2_CHECK_MAGIC(bb1, EXT2_ET_MAGIC_BADBLOCKS_LIST);
|
||||
EXT2_CHECK_MAGIC(bb2, EXT2_ET_MAGIC_BADBLOCKS_LIST);
|
||||
|
||||
if (bb1->num != bb2->num)
|
||||
return 0;
|
||||
|
||||
if (memcmp(bb1->list, bb2->list, bb1->num * sizeof(blk_t)) != 0)
|
||||
return 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
int ext2fs_badblocks_equal(ext2_badblocks_list bb1, ext2_badblocks_list bb2)
|
||||
{
|
||||
return ext2fs_u32_list_equal((ext2_u32_list) bb1,
|
||||
(ext2_u32_list) bb2);
|
||||
}
|
||||
|
||||
int ext2fs_u32_list_count(ext2_u32_list bb)
|
||||
{
|
||||
return bb->num;
|
||||
}
|
64
e2fsprogs/old_e2fsprogs/ext2fs/bb_compat.c
Normal file
64
e2fsprogs/old_e2fsprogs/ext2fs/bb_compat.c
Normal file
@ -0,0 +1,64 @@
|
||||
/* vi: set sw=4 ts=4: */
|
||||
/*
|
||||
* bb_compat.c --- compatibility badblocks routines
|
||||
*
|
||||
* Copyright (C) 1997 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>
|
||||
#if HAVE_UNISTD_H
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
#include <fcntl.h>
|
||||
#include <time.h>
|
||||
#if HAVE_SYS_STAT_H
|
||||
#include <sys/stat.h>
|
||||
#endif
|
||||
#if HAVE_SYS_TYPES_H
|
||||
#include <sys/types.h>
|
||||
#endif
|
||||
|
||||
#include "ext2_fs.h"
|
||||
#include "ext2fsP.h"
|
||||
|
||||
errcode_t badblocks_list_create(badblocks_list *ret, int size)
|
||||
{
|
||||
return ext2fs_badblocks_list_create(ret, size);
|
||||
}
|
||||
|
||||
void badblocks_list_free(badblocks_list bb)
|
||||
{
|
||||
ext2fs_badblocks_list_free(bb);
|
||||
}
|
||||
|
||||
errcode_t badblocks_list_add(badblocks_list bb, blk_t blk)
|
||||
{
|
||||
return ext2fs_badblocks_list_add(bb, blk);
|
||||
}
|
||||
|
||||
int badblocks_list_test(badblocks_list bb, blk_t blk)
|
||||
{
|
||||
return ext2fs_badblocks_list_test(bb, blk);
|
||||
}
|
||||
|
||||
errcode_t badblocks_list_iterate_begin(badblocks_list bb,
|
||||
badblocks_iterate *ret)
|
||||
{
|
||||
return ext2fs_badblocks_list_iterate_begin(bb, ret);
|
||||
}
|
||||
|
||||
int badblocks_list_iterate(badblocks_iterate iter, blk_t *blk)
|
||||
{
|
||||
return ext2fs_badblocks_list_iterate(iter, blk);
|
||||
}
|
||||
|
||||
void badblocks_list_iterate_end(badblocks_iterate iter)
|
||||
{
|
||||
ext2fs_badblocks_list_iterate_end(iter);
|
||||
}
|
268
e2fsprogs/old_e2fsprogs/ext2fs/bb_inode.c
Normal file
268
e2fsprogs/old_e2fsprogs/ext2fs/bb_inode.c
Normal file
@ -0,0 +1,268 @@
|
||||
/* vi: set sw=4 ts=4: */
|
||||
/*
|
||||
* bb_inode.c --- routines to update the bad block inode.
|
||||
*
|
||||
* WARNING: This routine modifies a lot of state in the filesystem; if
|
||||
* this routine returns an error, the bad block inode may be in an
|
||||
* inconsistent state.
|
||||
*
|
||||
* Copyright (C) 1994, 1995 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>
|
||||
#if HAVE_UNISTD_H
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
#include <fcntl.h>
|
||||
#include <time.h>
|
||||
#if HAVE_SYS_STAT_H
|
||||
#include <sys/stat.h>
|
||||
#endif
|
||||
#if HAVE_SYS_TYPES_H
|
||||
#include <sys/types.h>
|
||||
#endif
|
||||
|
||||
#include "ext2_fs.h"
|
||||
#include "ext2fs.h"
|
||||
|
||||
struct set_badblock_record {
|
||||
ext2_badblocks_iterate bb_iter;
|
||||
int bad_block_count;
|
||||
blk_t *ind_blocks;
|
||||
int max_ind_blocks;
|
||||
int ind_blocks_size;
|
||||
int ind_blocks_ptr;
|
||||
char *block_buf;
|
||||
errcode_t err;
|
||||
};
|
||||
|
||||
static int set_bad_block_proc(ext2_filsys fs, blk_t *block_nr,
|
||||
e2_blkcnt_t blockcnt,
|
||||
blk_t ref_block, int ref_offset,
|
||||
void *priv_data);
|
||||
static int clear_bad_block_proc(ext2_filsys fs, blk_t *block_nr,
|
||||
e2_blkcnt_t blockcnt,
|
||||
blk_t ref_block, int ref_offset,
|
||||
void *priv_data);
|
||||
|
||||
/*
|
||||
* Given a bad blocks bitmap, update the bad blocks inode to reflect
|
||||
* the map.
|
||||
*/
|
||||
errcode_t ext2fs_update_bb_inode(ext2_filsys fs, ext2_badblocks_list bb_list)
|
||||
{
|
||||
errcode_t retval;
|
||||
struct set_badblock_record rec;
|
||||
struct ext2_inode inode;
|
||||
|
||||
EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS);
|
||||
|
||||
if (!fs->block_map)
|
||||
return EXT2_ET_NO_BLOCK_BITMAP;
|
||||
|
||||
rec.bad_block_count = 0;
|
||||
rec.ind_blocks_size = rec.ind_blocks_ptr = 0;
|
||||
rec.max_ind_blocks = 10;
|
||||
retval = ext2fs_get_mem(rec.max_ind_blocks * sizeof(blk_t),
|
||||
&rec.ind_blocks);
|
||||
if (retval)
|
||||
return retval;
|
||||
memset(rec.ind_blocks, 0, rec.max_ind_blocks * sizeof(blk_t));
|
||||
retval = ext2fs_get_mem(fs->blocksize, &rec.block_buf);
|
||||
if (retval)
|
||||
goto cleanup;
|
||||
memset(rec.block_buf, 0, fs->blocksize);
|
||||
rec.err = 0;
|
||||
|
||||
/*
|
||||
* First clear the old bad blocks (while saving the indirect blocks)
|
||||
*/
|
||||
retval = ext2fs_block_iterate2(fs, EXT2_BAD_INO,
|
||||
BLOCK_FLAG_DEPTH_TRAVERSE, 0,
|
||||
clear_bad_block_proc, &rec);
|
||||
if (retval)
|
||||
goto cleanup;
|
||||
if (rec.err) {
|
||||
retval = rec.err;
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
/*
|
||||
* Now set the bad blocks!
|
||||
*
|
||||
* First, mark the bad blocks as used. This prevents a bad
|
||||
* block from being used as an indirecto block for the bad
|
||||
* block inode (!).
|
||||
*/
|
||||
if (bb_list) {
|
||||
retval = ext2fs_badblocks_list_iterate_begin(bb_list,
|
||||
&rec.bb_iter);
|
||||
if (retval)
|
||||
goto cleanup;
|
||||
retval = ext2fs_block_iterate2(fs, EXT2_BAD_INO,
|
||||
BLOCK_FLAG_APPEND, 0,
|
||||
set_bad_block_proc, &rec);
|
||||
ext2fs_badblocks_list_iterate_end(rec.bb_iter);
|
||||
if (retval)
|
||||
goto cleanup;
|
||||
if (rec.err) {
|
||||
retval = rec.err;
|
||||
goto cleanup;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Update the bad block inode's mod time and block count
|
||||
* field.
|
||||
*/
|
||||
retval = ext2fs_read_inode(fs, EXT2_BAD_INO, &inode);
|
||||
if (retval)
|
||||
goto cleanup;
|
||||
|
||||
inode.i_atime = inode.i_mtime = time(0);
|
||||
if (!inode.i_ctime)
|
||||
inode.i_ctime = time(0);
|
||||
inode.i_blocks = rec.bad_block_count * (fs->blocksize / 512);
|
||||
inode.i_size = rec.bad_block_count * fs->blocksize;
|
||||
|
||||
retval = ext2fs_write_inode(fs, EXT2_BAD_INO, &inode);
|
||||
if (retval)
|
||||
goto cleanup;
|
||||
|
||||
cleanup:
|
||||
ext2fs_free_mem(&rec.ind_blocks);
|
||||
ext2fs_free_mem(&rec.block_buf);
|
||||
return retval;
|
||||
}
|
||||
|
||||
/*
|
||||
* Helper function for update_bb_inode()
|
||||
*
|
||||
* Clear the bad blocks in the bad block inode, while saving the
|
||||
* indirect blocks.
|
||||
*/
|
||||
#ifdef __TURBOC__
|
||||
# pragma argsused
|
||||
#endif
|
||||
static int clear_bad_block_proc(ext2_filsys fs, blk_t *block_nr,
|
||||
e2_blkcnt_t blockcnt,
|
||||
blk_t ref_block EXT2FS_ATTR((unused)),
|
||||
int ref_offset EXT2FS_ATTR((unused)),
|
||||
void *priv_data)
|
||||
{
|
||||
struct set_badblock_record *rec = (struct set_badblock_record *)
|
||||
priv_data;
|
||||
errcode_t retval;
|
||||
unsigned long old_size;
|
||||
|
||||
if (!*block_nr)
|
||||
return 0;
|
||||
|
||||
/*
|
||||
* If the block number is outrageous, clear it and ignore it.
|
||||
*/
|
||||
if (*block_nr >= fs->super->s_blocks_count ||
|
||||
*block_nr < fs->super->s_first_data_block) {
|
||||
*block_nr = 0;
|
||||
return BLOCK_CHANGED;
|
||||
}
|
||||
|
||||
if (blockcnt < 0) {
|
||||
if (rec->ind_blocks_size >= rec->max_ind_blocks) {
|
||||
old_size = rec->max_ind_blocks * sizeof(blk_t);
|
||||
rec->max_ind_blocks += 10;
|
||||
retval = ext2fs_resize_mem(old_size,
|
||||
rec->max_ind_blocks * sizeof(blk_t),
|
||||
&rec->ind_blocks);
|
||||
if (retval) {
|
||||
rec->max_ind_blocks -= 10;
|
||||
rec->err = retval;
|
||||
return BLOCK_ABORT;
|
||||
}
|
||||
}
|
||||
rec->ind_blocks[rec->ind_blocks_size++] = *block_nr;
|
||||
}
|
||||
|
||||
/*
|
||||
* Mark the block as unused, and update accounting information
|
||||
*/
|
||||
ext2fs_block_alloc_stats(fs, *block_nr, -1);
|
||||
|
||||
*block_nr = 0;
|
||||
return BLOCK_CHANGED;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Helper function for update_bb_inode()
|
||||
*
|
||||
* Set the block list in the bad block inode, using the supplied bitmap.
|
||||
*/
|
||||
#ifdef __TURBOC__
|
||||
#pragma argsused
|
||||
#endif
|
||||
static int set_bad_block_proc(ext2_filsys fs, blk_t *block_nr,
|
||||
e2_blkcnt_t blockcnt,
|
||||
blk_t ref_block EXT2FS_ATTR((unused)),
|
||||
int ref_offset EXT2FS_ATTR((unused)),
|
||||
void *priv_data)
|
||||
{
|
||||
struct set_badblock_record *rec = (struct set_badblock_record *)
|
||||
priv_data;
|
||||
errcode_t retval;
|
||||
blk_t blk;
|
||||
|
||||
if (blockcnt >= 0) {
|
||||
/*
|
||||
* Get the next bad block.
|
||||
*/
|
||||
if (!ext2fs_badblocks_list_iterate(rec->bb_iter, &blk))
|
||||
return BLOCK_ABORT;
|
||||
rec->bad_block_count++;
|
||||
} else {
|
||||
/*
|
||||
* An indirect block; fetch a block from the
|
||||
* previously used indirect block list. The block
|
||||
* most be not marked as used; if so, get another one.
|
||||
* If we run out of reserved indirect blocks, allocate
|
||||
* a new one.
|
||||
*/
|
||||
retry:
|
||||
if (rec->ind_blocks_ptr < rec->ind_blocks_size) {
|
||||
blk = rec->ind_blocks[rec->ind_blocks_ptr++];
|
||||
if (ext2fs_test_block_bitmap(fs->block_map, blk))
|
||||
goto retry;
|
||||
} else {
|
||||
retval = ext2fs_new_block(fs, 0, 0, &blk);
|
||||
if (retval) {
|
||||
rec->err = retval;
|
||||
return BLOCK_ABORT;
|
||||
}
|
||||
}
|
||||
retval = io_channel_write_blk(fs->io, blk, 1, rec->block_buf);
|
||||
if (retval) {
|
||||
rec->err = retval;
|
||||
return BLOCK_ABORT;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Update block counts
|
||||
*/
|
||||
ext2fs_block_alloc_stats(fs, blk, +1);
|
||||
|
||||
*block_nr = blk;
|
||||
return BLOCK_CHANGED;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
213
e2fsprogs/old_e2fsprogs/ext2fs/bitmaps.c
Normal file
213
e2fsprogs/old_e2fsprogs/ext2fs/bitmaps.c
Normal file
@ -0,0 +1,213 @@
|
||||
/* vi: set sw=4 ts=4: */
|
||||
/*
|
||||
* bitmaps.c --- routines to read, write, and manipulate the inode and
|
||||
* block bitmaps.
|
||||
*
|
||||
* Copyright (C) 1993, 1994, 1995, 1996 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>
|
||||
#if HAVE_UNISTD_H
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
#include <fcntl.h>
|
||||
#include <time.h>
|
||||
#if HAVE_SYS_STAT_H
|
||||
#include <sys/stat.h>
|
||||
#endif
|
||||
#if HAVE_SYS_TYPES_H
|
||||
#include <sys/types.h>
|
||||
#endif
|
||||
|
||||
#include "ext2_fs.h"
|
||||
#include "ext2fs.h"
|
||||
|
||||
static errcode_t make_bitmap(__u32 start, __u32 end, __u32 real_end,
|
||||
const char *descr, char *init_map,
|
||||
ext2fs_generic_bitmap *ret)
|
||||
{
|
||||
ext2fs_generic_bitmap bitmap;
|
||||
errcode_t retval;
|
||||
size_t size;
|
||||
|
||||
retval = ext2fs_get_mem(sizeof(struct ext2fs_struct_generic_bitmap),
|
||||
&bitmap);
|
||||
if (retval)
|
||||
return retval;
|
||||
|
||||
bitmap->magic = EXT2_ET_MAGIC_GENERIC_BITMAP;
|
||||
bitmap->fs = NULL;
|
||||
bitmap->start = start;
|
||||
bitmap->end = end;
|
||||
bitmap->real_end = real_end;
|
||||
bitmap->base_error_code = EXT2_ET_BAD_GENERIC_MARK;
|
||||
if (descr) {
|
||||
retval = ext2fs_get_mem(strlen(descr)+1, &bitmap->description);
|
||||
if (retval) {
|
||||
ext2fs_free_mem(&bitmap);
|
||||
return retval;
|
||||
}
|
||||
strcpy(bitmap->description, descr);
|
||||
} else
|
||||
bitmap->description = 0;
|
||||
|
||||
size = (size_t) (((bitmap->real_end - bitmap->start) / 8) + 1);
|
||||
retval = ext2fs_get_mem(size, &bitmap->bitmap);
|
||||
if (retval) {
|
||||
ext2fs_free_mem(&bitmap->description);
|
||||
ext2fs_free_mem(&bitmap);
|
||||
return retval;
|
||||
}
|
||||
|
||||
if (init_map)
|
||||
memcpy(bitmap->bitmap, init_map, size);
|
||||
else
|
||||
memset(bitmap->bitmap, 0, size);
|
||||
*ret = bitmap;
|
||||
return 0;
|
||||
}
|
||||
|
||||
errcode_t ext2fs_allocate_generic_bitmap(__u32 start,
|
||||
__u32 end,
|
||||
__u32 real_end,
|
||||
const char *descr,
|
||||
ext2fs_generic_bitmap *ret)
|
||||
{
|
||||
return make_bitmap(start, end, real_end, descr, 0, ret);
|
||||
}
|
||||
|
||||
errcode_t ext2fs_copy_bitmap(ext2fs_generic_bitmap src,
|
||||
ext2fs_generic_bitmap *dest)
|
||||
{
|
||||
errcode_t retval;
|
||||
ext2fs_generic_bitmap new_map;
|
||||
|
||||
retval = make_bitmap(src->start, src->end, src->real_end,
|
||||
src->description, src->bitmap, &new_map);
|
||||
if (retval)
|
||||
return retval;
|
||||
new_map->magic = src->magic;
|
||||
new_map->fs = src->fs;
|
||||
new_map->base_error_code = src->base_error_code;
|
||||
*dest = new_map;
|
||||
return 0;
|
||||
}
|
||||
|
||||
void ext2fs_set_bitmap_padding(ext2fs_generic_bitmap map)
|
||||
{
|
||||
__u32 i, j;
|
||||
|
||||
for (i=map->end+1, j = i - map->start; i <= map->real_end; i++, j++)
|
||||
ext2fs_set_bit(j, map->bitmap);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
errcode_t ext2fs_allocate_inode_bitmap(ext2_filsys fs,
|
||||
const char *descr,
|
||||
ext2fs_inode_bitmap *ret)
|
||||
{
|
||||
ext2fs_inode_bitmap bitmap;
|
||||
errcode_t retval;
|
||||
__u32 start, end, real_end;
|
||||
|
||||
EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS);
|
||||
|
||||
fs->write_bitmaps = ext2fs_write_bitmaps;
|
||||
|
||||
start = 1;
|
||||
end = fs->super->s_inodes_count;
|
||||
real_end = (EXT2_INODES_PER_GROUP(fs->super) * fs->group_desc_count);
|
||||
|
||||
retval = ext2fs_allocate_generic_bitmap(start, end, real_end,
|
||||
descr, &bitmap);
|
||||
if (retval)
|
||||
return retval;
|
||||
|
||||
bitmap->magic = EXT2_ET_MAGIC_INODE_BITMAP;
|
||||
bitmap->fs = fs;
|
||||
bitmap->base_error_code = EXT2_ET_BAD_INODE_MARK;
|
||||
|
||||
*ret = bitmap;
|
||||
return 0;
|
||||
}
|
||||
|
||||
errcode_t ext2fs_allocate_block_bitmap(ext2_filsys fs,
|
||||
const char *descr,
|
||||
ext2fs_block_bitmap *ret)
|
||||
{
|
||||
ext2fs_block_bitmap bitmap;
|
||||
errcode_t retval;
|
||||
__u32 start, end, real_end;
|
||||
|
||||
EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS);
|
||||
|
||||
fs->write_bitmaps = ext2fs_write_bitmaps;
|
||||
|
||||
start = fs->super->s_first_data_block;
|
||||
end = fs->super->s_blocks_count-1;
|
||||
real_end = (EXT2_BLOCKS_PER_GROUP(fs->super)
|
||||
* fs->group_desc_count)-1 + start;
|
||||
|
||||
retval = ext2fs_allocate_generic_bitmap(start, end, real_end,
|
||||
descr, &bitmap);
|
||||
if (retval)
|
||||
return retval;
|
||||
|
||||
bitmap->magic = EXT2_ET_MAGIC_BLOCK_BITMAP;
|
||||
bitmap->fs = fs;
|
||||
bitmap->base_error_code = EXT2_ET_BAD_BLOCK_MARK;
|
||||
|
||||
*ret = bitmap;
|
||||
return 0;
|
||||
}
|
||||
|
||||
errcode_t ext2fs_fudge_inode_bitmap_end(ext2fs_inode_bitmap bitmap,
|
||||
ext2_ino_t end, ext2_ino_t *oend)
|
||||
{
|
||||
EXT2_CHECK_MAGIC(bitmap, EXT2_ET_MAGIC_INODE_BITMAP);
|
||||
|
||||
if (end > bitmap->real_end)
|
||||
return EXT2_ET_FUDGE_INODE_BITMAP_END;
|
||||
if (oend)
|
||||
*oend = bitmap->end;
|
||||
bitmap->end = end;
|
||||
return 0;
|
||||
}
|
||||
|
||||
errcode_t ext2fs_fudge_block_bitmap_end(ext2fs_block_bitmap bitmap,
|
||||
blk_t end, blk_t *oend)
|
||||
{
|
||||
EXT2_CHECK_MAGIC(bitmap, EXT2_ET_MAGIC_BLOCK_BITMAP);
|
||||
|
||||
if (end > bitmap->real_end)
|
||||
return EXT2_ET_FUDGE_BLOCK_BITMAP_END;
|
||||
if (oend)
|
||||
*oend = bitmap->end;
|
||||
bitmap->end = end;
|
||||
return 0;
|
||||
}
|
||||
|
||||
void ext2fs_clear_inode_bitmap(ext2fs_inode_bitmap bitmap)
|
||||
{
|
||||
if (!bitmap || (bitmap->magic != EXT2_ET_MAGIC_INODE_BITMAP))
|
||||
return;
|
||||
|
||||
memset(bitmap->bitmap, 0,
|
||||
(size_t) (((bitmap->real_end - bitmap->start) / 8) + 1));
|
||||
}
|
||||
|
||||
void ext2fs_clear_block_bitmap(ext2fs_block_bitmap bitmap)
|
||||
{
|
||||
if (!bitmap || (bitmap->magic != EXT2_ET_MAGIC_BLOCK_BITMAP))
|
||||
return;
|
||||
|
||||
memset(bitmap->bitmap, 0,
|
||||
(size_t) (((bitmap->real_end - bitmap->start) / 8) + 1));
|
||||
}
|
91
e2fsprogs/old_e2fsprogs/ext2fs/bitops.c
Normal file
91
e2fsprogs/old_e2fsprogs/ext2fs/bitops.c
Normal file
@ -0,0 +1,91 @@
|
||||
/* vi: set sw=4 ts=4: */
|
||||
/*
|
||||
* bitops.c --- Bitmap frobbing code. See bitops.h for the inlined
|
||||
* routines.
|
||||
*
|
||||
* Copyright (C) 1993, 1994, 1995, 1996 Theodore Ts'o.
|
||||
*
|
||||
* %Begin-Header%
|
||||
* This file may be redistributed under the terms of the GNU Public
|
||||
* License.
|
||||
* %End-Header%
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#if HAVE_SYS_TYPES_H
|
||||
#include <sys/types.h>
|
||||
#endif
|
||||
|
||||
#include "ext2_fs.h"
|
||||
#include "ext2fs.h"
|
||||
|
||||
#ifndef _EXT2_HAVE_ASM_BITOPS_
|
||||
|
||||
/*
|
||||
* For the benefit of those who are trying to port Linux to another
|
||||
* architecture, here are some C-language equivalents. You should
|
||||
* recode these in the native assmebly language, if at all possible.
|
||||
*
|
||||
* C language equivalents written by Theodore Ts'o, 9/26/92.
|
||||
* Modified by Pete A. Zaitcev 7/14/95 to be portable to big endian
|
||||
* systems, as well as non-32 bit systems.
|
||||
*/
|
||||
|
||||
int ext2fs_set_bit(unsigned int nr,void * addr)
|
||||
{
|
||||
int mask, retval;
|
||||
unsigned char *ADDR = (unsigned char *) addr;
|
||||
|
||||
ADDR += nr >> 3;
|
||||
mask = 1 << (nr & 0x07);
|
||||
retval = mask & *ADDR;
|
||||
*ADDR |= mask;
|
||||
return retval;
|
||||
}
|
||||
|
||||
int ext2fs_clear_bit(unsigned int nr, void * addr)
|
||||
{
|
||||
int mask, retval;
|
||||
unsigned char *ADDR = (unsigned char *) addr;
|
||||
|
||||
ADDR += nr >> 3;
|
||||
mask = 1 << (nr & 0x07);
|
||||
retval = mask & *ADDR;
|
||||
*ADDR &= ~mask;
|
||||
return retval;
|
||||
}
|
||||
|
||||
int ext2fs_test_bit(unsigned int nr, const void * addr)
|
||||
{
|
||||
int mask;
|
||||
const unsigned char *ADDR = (const unsigned char *) addr;
|
||||
|
||||
ADDR += nr >> 3;
|
||||
mask = 1 << (nr & 0x07);
|
||||
return (mask & *ADDR);
|
||||
}
|
||||
|
||||
#endif /* !_EXT2_HAVE_ASM_BITOPS_ */
|
||||
|
||||
void ext2fs_warn_bitmap(errcode_t errcode, unsigned long arg,
|
||||
const char *description)
|
||||
{
|
||||
#ifndef OMIT_COM_ERR
|
||||
if (description)
|
||||
bb_error_msg("#%lu for %s", arg, description);
|
||||
else
|
||||
bb_error_msg("#%lu", arg);
|
||||
#endif
|
||||
}
|
||||
|
||||
void ext2fs_warn_bitmap2(ext2fs_generic_bitmap bitmap,
|
||||
int code, unsigned long arg)
|
||||
{
|
||||
#ifndef OMIT_COM_ERR
|
||||
if (bitmap->description)
|
||||
bb_error_msg("#%lu for %s", arg, bitmap->description);
|
||||
else
|
||||
bb_error_msg("#%lu", arg);
|
||||
#endif
|
||||
}
|
||||
|
107
e2fsprogs/old_e2fsprogs/ext2fs/bitops.h
Normal file
107
e2fsprogs/old_e2fsprogs/ext2fs/bitops.h
Normal file
@ -0,0 +1,107 @@
|
||||
/* vi: set sw=4 ts=4: */
|
||||
/*
|
||||
* bitops.h --- Bitmap frobbing code. The byte swapping routines are
|
||||
* also included here.
|
||||
*
|
||||
* Copyright (C) 1993, 1994, 1995, 1996 Theodore Ts'o.
|
||||
*
|
||||
* %Begin-Header%
|
||||
* This file may be redistributed under the terms of the GNU Public
|
||||
* License.
|
||||
* %End-Header%
|
||||
*
|
||||
* i386 bitops operations taken from <asm/bitops.h>, Copyright 1992,
|
||||
* Linus Torvalds.
|
||||
*/
|
||||
|
||||
#include <string.h>
|
||||
#include <strings.h>
|
||||
|
||||
extern int ext2fs_set_bit(unsigned int nr,void * addr);
|
||||
extern int ext2fs_clear_bit(unsigned int nr, void * addr);
|
||||
extern int ext2fs_test_bit(unsigned int nr, const void * addr);
|
||||
extern __u16 ext2fs_swab16(__u16 val);
|
||||
extern __u32 ext2fs_swab32(__u32 val);
|
||||
|
||||
#ifdef WORDS_BIGENDIAN
|
||||
#define ext2fs_cpu_to_le32(x) ext2fs_swab32((x))
|
||||
#define ext2fs_le32_to_cpu(x) ext2fs_swab32((x))
|
||||
#define ext2fs_cpu_to_le16(x) ext2fs_swab16((x))
|
||||
#define ext2fs_le16_to_cpu(x) ext2fs_swab16((x))
|
||||
#define ext2fs_cpu_to_be32(x) ((__u32)(x))
|
||||
#define ext2fs_be32_to_cpu(x) ((__u32)(x))
|
||||
#define ext2fs_cpu_to_be16(x) ((__u16)(x))
|
||||
#define ext2fs_be16_to_cpu(x) ((__u16)(x))
|
||||
#else
|
||||
#define ext2fs_cpu_to_le32(x) ((__u32)(x))
|
||||
#define ext2fs_le32_to_cpu(x) ((__u32)(x))
|
||||
#define ext2fs_cpu_to_le16(x) ((__u16)(x))
|
||||
#define ext2fs_le16_to_cpu(x) ((__u16)(x))
|
||||
#define ext2fs_cpu_to_be32(x) ext2fs_swab32((x))
|
||||
#define ext2fs_be32_to_cpu(x) ext2fs_swab32((x))
|
||||
#define ext2fs_cpu_to_be16(x) ext2fs_swab16((x))
|
||||
#define ext2fs_be16_to_cpu(x) ext2fs_swab16((x))
|
||||
#endif
|
||||
|
||||
/*
|
||||
* EXT2FS bitmap manipulation routines.
|
||||
*/
|
||||
|
||||
/* Support for sending warning messages from the inline subroutines */
|
||||
extern const char *ext2fs_block_string;
|
||||
extern const char *ext2fs_inode_string;
|
||||
extern const char *ext2fs_mark_string;
|
||||
extern const char *ext2fs_unmark_string;
|
||||
extern const char *ext2fs_test_string;
|
||||
extern void ext2fs_warn_bitmap(errcode_t errcode, unsigned long arg,
|
||||
const char *description);
|
||||
extern void ext2fs_warn_bitmap2(ext2fs_generic_bitmap bitmap,
|
||||
int code, unsigned long arg);
|
||||
|
||||
extern int ext2fs_mark_block_bitmap(ext2fs_block_bitmap bitmap, blk_t block);
|
||||
extern int ext2fs_unmark_block_bitmap(ext2fs_block_bitmap bitmap,
|
||||
blk_t block);
|
||||
extern int ext2fs_test_block_bitmap(ext2fs_block_bitmap bitmap, blk_t block);
|
||||
|
||||
extern int ext2fs_mark_inode_bitmap(ext2fs_inode_bitmap bitmap, ext2_ino_t inode);
|
||||
extern int ext2fs_unmark_inode_bitmap(ext2fs_inode_bitmap bitmap,
|
||||
ext2_ino_t inode);
|
||||
extern int ext2fs_test_inode_bitmap(ext2fs_inode_bitmap bitmap, ext2_ino_t inode);
|
||||
|
||||
extern void ext2fs_fast_mark_block_bitmap(ext2fs_block_bitmap bitmap,
|
||||
blk_t block);
|
||||
extern void ext2fs_fast_unmark_block_bitmap(ext2fs_block_bitmap bitmap,
|
||||
blk_t block);
|
||||
extern int ext2fs_fast_test_block_bitmap(ext2fs_block_bitmap bitmap,
|
||||
blk_t block);
|
||||
|
||||
extern void ext2fs_fast_mark_inode_bitmap(ext2fs_inode_bitmap bitmap,
|
||||
ext2_ino_t inode);
|
||||
extern void ext2fs_fast_unmark_inode_bitmap(ext2fs_inode_bitmap bitmap,
|
||||
ext2_ino_t inode);
|
||||
extern int ext2fs_fast_test_inode_bitmap(ext2fs_inode_bitmap bitmap,
|
||||
ext2_ino_t inode);
|
||||
extern blk_t ext2fs_get_block_bitmap_start(ext2fs_block_bitmap bitmap);
|
||||
extern ext2_ino_t ext2fs_get_inode_bitmap_start(ext2fs_inode_bitmap bitmap);
|
||||
extern blk_t ext2fs_get_block_bitmap_end(ext2fs_block_bitmap bitmap);
|
||||
extern ext2_ino_t ext2fs_get_inode_bitmap_end(ext2fs_inode_bitmap bitmap);
|
||||
|
||||
extern void ext2fs_mark_block_bitmap_range(ext2fs_block_bitmap bitmap,
|
||||
blk_t block, int num);
|
||||
extern void ext2fs_unmark_block_bitmap_range(ext2fs_block_bitmap bitmap,
|
||||
blk_t block, int num);
|
||||
extern int ext2fs_test_block_bitmap_range(ext2fs_block_bitmap bitmap,
|
||||
blk_t block, int num);
|
||||
extern void ext2fs_fast_mark_block_bitmap_range(ext2fs_block_bitmap bitmap,
|
||||
blk_t block, int num);
|
||||
extern void ext2fs_fast_unmark_block_bitmap_range(ext2fs_block_bitmap bitmap,
|
||||
blk_t block, int num);
|
||||
extern int ext2fs_fast_test_block_bitmap_range(ext2fs_block_bitmap bitmap,
|
||||
blk_t block, int num);
|
||||
extern void ext2fs_set_bitmap_padding(ext2fs_generic_bitmap map);
|
||||
|
||||
/* These two routines moved to gen_bitmap.c */
|
||||
extern int ext2fs_mark_generic_bitmap(ext2fs_generic_bitmap bitmap,
|
||||
__u32 bitno);
|
||||
extern int ext2fs_unmark_generic_bitmap(ext2fs_generic_bitmap bitmap,
|
||||
blk_t bitno);
|
438
e2fsprogs/old_e2fsprogs/ext2fs/block.c
Normal file
438
e2fsprogs/old_e2fsprogs/ext2fs/block.c
Normal file
@ -0,0 +1,438 @@
|
||||
/* vi: set sw=4 ts=4: */
|
||||
/*
|
||||
* block.c --- iterate over all blocks in an inode
|
||||
*
|
||||
* Copyright (C) 1993, 1994, 1995, 1996 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>
|
||||
#if HAVE_UNISTD_H
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
|
||||
#include "ext2_fs.h"
|
||||
#include "ext2fs.h"
|
||||
|
||||
struct block_context {
|
||||
ext2_filsys fs;
|
||||
int (*func)(ext2_filsys fs,
|
||||
blk_t *blocknr,
|
||||
e2_blkcnt_t bcount,
|
||||
blk_t ref_blk,
|
||||
int ref_offset,
|
||||
void *priv_data);
|
||||
e2_blkcnt_t bcount;
|
||||
int bsize;
|
||||
int flags;
|
||||
errcode_t errcode;
|
||||
char *ind_buf;
|
||||
char *dind_buf;
|
||||
char *tind_buf;
|
||||
void *priv_data;
|
||||
};
|
||||
|
||||
static int block_iterate_ind(blk_t *ind_block, blk_t ref_block,
|
||||
int ref_offset, struct block_context *ctx)
|
||||
{
|
||||
int ret = 0, changed = 0;
|
||||
int i, flags, limit, offset;
|
||||
blk_t *block_nr;
|
||||
|
||||
limit = ctx->fs->blocksize >> 2;
|
||||
if (!(ctx->flags & BLOCK_FLAG_DEPTH_TRAVERSE) &&
|
||||
!(ctx->flags & BLOCK_FLAG_DATA_ONLY))
|
||||
ret = (*ctx->func)(ctx->fs, ind_block,
|
||||
BLOCK_COUNT_IND, ref_block,
|
||||
ref_offset, ctx->priv_data);
|
||||
if (!*ind_block || (ret & BLOCK_ABORT)) {
|
||||
ctx->bcount += limit;
|
||||
return ret;
|
||||
}
|
||||
if (*ind_block >= ctx->fs->super->s_blocks_count ||
|
||||
*ind_block < ctx->fs->super->s_first_data_block) {
|
||||
ctx->errcode = EXT2_ET_BAD_IND_BLOCK;
|
||||
ret |= BLOCK_ERROR;
|
||||
return ret;
|
||||
}
|
||||
ctx->errcode = ext2fs_read_ind_block(ctx->fs, *ind_block,
|
||||
ctx->ind_buf);
|
||||
if (ctx->errcode) {
|
||||
ret |= BLOCK_ERROR;
|
||||
return ret;
|
||||
}
|
||||
|
||||
block_nr = (blk_t *) ctx->ind_buf;
|
||||
offset = 0;
|
||||
if (ctx->flags & BLOCK_FLAG_APPEND) {
|
||||
for (i = 0; i < limit; i++, ctx->bcount++, block_nr++) {
|
||||
flags = (*ctx->func)(ctx->fs, block_nr, ctx->bcount,
|
||||
*ind_block, offset,
|
||||
ctx->priv_data);
|
||||
changed |= flags;
|
||||
if (flags & BLOCK_ABORT) {
|
||||
ret |= BLOCK_ABORT;
|
||||
break;
|
||||
}
|
||||
offset += sizeof(blk_t);
|
||||
}
|
||||
} else {
|
||||
for (i = 0; i < limit; i++, ctx->bcount++, block_nr++) {
|
||||
if (*block_nr == 0)
|
||||
continue;
|
||||
flags = (*ctx->func)(ctx->fs, block_nr, ctx->bcount,
|
||||
*ind_block, offset,
|
||||
ctx->priv_data);
|
||||
changed |= flags;
|
||||
if (flags & BLOCK_ABORT) {
|
||||
ret |= BLOCK_ABORT;
|
||||
break;
|
||||
}
|
||||
offset += sizeof(blk_t);
|
||||
}
|
||||
}
|
||||
if (changed & BLOCK_CHANGED) {
|
||||
ctx->errcode = ext2fs_write_ind_block(ctx->fs, *ind_block,
|
||||
ctx->ind_buf);
|
||||
if (ctx->errcode)
|
||||
ret |= BLOCK_ERROR | BLOCK_ABORT;
|
||||
}
|
||||
if ((ctx->flags & BLOCK_FLAG_DEPTH_TRAVERSE) &&
|
||||
!(ctx->flags & BLOCK_FLAG_DATA_ONLY) &&
|
||||
!(ret & BLOCK_ABORT))
|
||||
ret |= (*ctx->func)(ctx->fs, ind_block,
|
||||
BLOCK_COUNT_IND, ref_block,
|
||||
ref_offset, ctx->priv_data);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int block_iterate_dind(blk_t *dind_block, blk_t ref_block,
|
||||
int ref_offset, struct block_context *ctx)
|
||||
{
|
||||
int ret = 0, changed = 0;
|
||||
int i, flags, limit, offset;
|
||||
blk_t *block_nr;
|
||||
|
||||
limit = ctx->fs->blocksize >> 2;
|
||||
if (!(ctx->flags & (BLOCK_FLAG_DEPTH_TRAVERSE |
|
||||
BLOCK_FLAG_DATA_ONLY)))
|
||||
ret = (*ctx->func)(ctx->fs, dind_block,
|
||||
BLOCK_COUNT_DIND, ref_block,
|
||||
ref_offset, ctx->priv_data);
|
||||
if (!*dind_block || (ret & BLOCK_ABORT)) {
|
||||
ctx->bcount += limit*limit;
|
||||
return ret;
|
||||
}
|
||||
if (*dind_block >= ctx->fs->super->s_blocks_count ||
|
||||
*dind_block < ctx->fs->super->s_first_data_block) {
|
||||
ctx->errcode = EXT2_ET_BAD_DIND_BLOCK;
|
||||
ret |= BLOCK_ERROR;
|
||||
return ret;
|
||||
}
|
||||
ctx->errcode = ext2fs_read_ind_block(ctx->fs, *dind_block,
|
||||
ctx->dind_buf);
|
||||
if (ctx->errcode) {
|
||||
ret |= BLOCK_ERROR;
|
||||
return ret;
|
||||
}
|
||||
|
||||
block_nr = (blk_t *) ctx->dind_buf;
|
||||
offset = 0;
|
||||
if (ctx->flags & BLOCK_FLAG_APPEND) {
|
||||
for (i = 0; i < limit; i++, block_nr++) {
|
||||
flags = block_iterate_ind(block_nr,
|
||||
*dind_block, offset,
|
||||
ctx);
|
||||
changed |= flags;
|
||||
if (flags & (BLOCK_ABORT | BLOCK_ERROR)) {
|
||||
ret |= flags & (BLOCK_ABORT | BLOCK_ERROR);
|
||||
break;
|
||||
}
|
||||
offset += sizeof(blk_t);
|
||||
}
|
||||
} else {
|
||||
for (i = 0; i < limit; i++, block_nr++) {
|
||||
if (*block_nr == 0) {
|
||||
ctx->bcount += limit;
|
||||
continue;
|
||||
}
|
||||
flags = block_iterate_ind(block_nr,
|
||||
*dind_block, offset,
|
||||
ctx);
|
||||
changed |= flags;
|
||||
if (flags & (BLOCK_ABORT | BLOCK_ERROR)) {
|
||||
ret |= flags & (BLOCK_ABORT | BLOCK_ERROR);
|
||||
break;
|
||||
}
|
||||
offset += sizeof(blk_t);
|
||||
}
|
||||
}
|
||||
if (changed & BLOCK_CHANGED) {
|
||||
ctx->errcode = ext2fs_write_ind_block(ctx->fs, *dind_block,
|
||||
ctx->dind_buf);
|
||||
if (ctx->errcode)
|
||||
ret |= BLOCK_ERROR | BLOCK_ABORT;
|
||||
}
|
||||
if ((ctx->flags & BLOCK_FLAG_DEPTH_TRAVERSE) &&
|
||||
!(ctx->flags & BLOCK_FLAG_DATA_ONLY) &&
|
||||
!(ret & BLOCK_ABORT))
|
||||
ret |= (*ctx->func)(ctx->fs, dind_block,
|
||||
BLOCK_COUNT_DIND, ref_block,
|
||||
ref_offset, ctx->priv_data);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int block_iterate_tind(blk_t *tind_block, blk_t ref_block,
|
||||
int ref_offset, struct block_context *ctx)
|
||||
{
|
||||
int ret = 0, changed = 0;
|
||||
int i, flags, limit, offset;
|
||||
blk_t *block_nr;
|
||||
|
||||
limit = ctx->fs->blocksize >> 2;
|
||||
if (!(ctx->flags & (BLOCK_FLAG_DEPTH_TRAVERSE |
|
||||
BLOCK_FLAG_DATA_ONLY)))
|
||||
ret = (*ctx->func)(ctx->fs, tind_block,
|
||||
BLOCK_COUNT_TIND, ref_block,
|
||||
ref_offset, ctx->priv_data);
|
||||
if (!*tind_block || (ret & BLOCK_ABORT)) {
|
||||
ctx->bcount += limit*limit*limit;
|
||||
return ret;
|
||||
}
|
||||
if (*tind_block >= ctx->fs->super->s_blocks_count ||
|
||||
*tind_block < ctx->fs->super->s_first_data_block) {
|
||||
ctx->errcode = EXT2_ET_BAD_TIND_BLOCK;
|
||||
ret |= BLOCK_ERROR;
|
||||
return ret;
|
||||
}
|
||||
ctx->errcode = ext2fs_read_ind_block(ctx->fs, *tind_block,
|
||||
ctx->tind_buf);
|
||||
if (ctx->errcode) {
|
||||
ret |= BLOCK_ERROR;
|
||||
return ret;
|
||||
}
|
||||
|
||||
block_nr = (blk_t *) ctx->tind_buf;
|
||||
offset = 0;
|
||||
if (ctx->flags & BLOCK_FLAG_APPEND) {
|
||||
for (i = 0; i < limit; i++, block_nr++) {
|
||||
flags = block_iterate_dind(block_nr,
|
||||
*tind_block,
|
||||
offset, ctx);
|
||||
changed |= flags;
|
||||
if (flags & (BLOCK_ABORT | BLOCK_ERROR)) {
|
||||
ret |= flags & (BLOCK_ABORT | BLOCK_ERROR);
|
||||
break;
|
||||
}
|
||||
offset += sizeof(blk_t);
|
||||
}
|
||||
} else {
|
||||
for (i = 0; i < limit; i++, block_nr++) {
|
||||
if (*block_nr == 0) {
|
||||
ctx->bcount += limit*limit;
|
||||
continue;
|
||||
}
|
||||
flags = block_iterate_dind(block_nr,
|
||||
*tind_block,
|
||||
offset, ctx);
|
||||
changed |= flags;
|
||||
if (flags & (BLOCK_ABORT | BLOCK_ERROR)) {
|
||||
ret |= flags & (BLOCK_ABORT | BLOCK_ERROR);
|
||||
break;
|
||||
}
|
||||
offset += sizeof(blk_t);
|
||||
}
|
||||
}
|
||||
if (changed & BLOCK_CHANGED) {
|
||||
ctx->errcode = ext2fs_write_ind_block(ctx->fs, *tind_block,
|
||||
ctx->tind_buf);
|
||||
if (ctx->errcode)
|
||||
ret |= BLOCK_ERROR | BLOCK_ABORT;
|
||||
}
|
||||
if ((ctx->flags & BLOCK_FLAG_DEPTH_TRAVERSE) &&
|
||||
!(ctx->flags & BLOCK_FLAG_DATA_ONLY) &&
|
||||
!(ret & BLOCK_ABORT))
|
||||
ret |= (*ctx->func)(ctx->fs, tind_block,
|
||||
BLOCK_COUNT_TIND, ref_block,
|
||||
ref_offset, ctx->priv_data);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
errcode_t ext2fs_block_iterate2(ext2_filsys fs,
|
||||
ext2_ino_t ino,
|
||||
int flags,
|
||||
char *block_buf,
|
||||
int (*func)(ext2_filsys fs,
|
||||
blk_t *blocknr,
|
||||
e2_blkcnt_t blockcnt,
|
||||
blk_t ref_blk,
|
||||
int ref_offset,
|
||||
void *priv_data),
|
||||
void *priv_data)
|
||||
{
|
||||
int i;
|
||||
int got_inode = 0;
|
||||
int ret = 0;
|
||||
blk_t blocks[EXT2_N_BLOCKS]; /* directory data blocks */
|
||||
struct ext2_inode inode;
|
||||
errcode_t retval;
|
||||
struct block_context ctx;
|
||||
int limit;
|
||||
|
||||
EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS);
|
||||
|
||||
/*
|
||||
* Check to see if we need to limit large files
|
||||
*/
|
||||
if (flags & BLOCK_FLAG_NO_LARGE) {
|
||||
ctx.errcode = ext2fs_read_inode(fs, ino, &inode);
|
||||
if (ctx.errcode)
|
||||
return ctx.errcode;
|
||||
got_inode = 1;
|
||||
if (!LINUX_S_ISDIR(inode.i_mode) &&
|
||||
(inode.i_size_high != 0))
|
||||
return EXT2_ET_FILE_TOO_BIG;
|
||||
}
|
||||
|
||||
retval = ext2fs_get_blocks(fs, ino, blocks);
|
||||
if (retval)
|
||||
return retval;
|
||||
|
||||
limit = fs->blocksize >> 2;
|
||||
|
||||
ctx.fs = fs;
|
||||
ctx.func = func;
|
||||
ctx.priv_data = priv_data;
|
||||
ctx.flags = flags;
|
||||
ctx.bcount = 0;
|
||||
if (block_buf) {
|
||||
ctx.ind_buf = block_buf;
|
||||
} else {
|
||||
retval = ext2fs_get_mem(fs->blocksize * 3, &ctx.ind_buf);
|
||||
if (retval)
|
||||
return retval;
|
||||
}
|
||||
ctx.dind_buf = ctx.ind_buf + fs->blocksize;
|
||||
ctx.tind_buf = ctx.dind_buf + fs->blocksize;
|
||||
|
||||
/*
|
||||
* Iterate over the HURD translator block (if present)
|
||||
*/
|
||||
if ((fs->super->s_creator_os == EXT2_OS_HURD) &&
|
||||
!(flags & BLOCK_FLAG_DATA_ONLY)) {
|
||||
ctx.errcode = ext2fs_read_inode(fs, ino, &inode);
|
||||
if (ctx.errcode)
|
||||
goto abort_exit;
|
||||
got_inode = 1;
|
||||
if (inode.osd1.hurd1.h_i_translator) {
|
||||
ret |= (*ctx.func)(fs,
|
||||
&inode.osd1.hurd1.h_i_translator,
|
||||
BLOCK_COUNT_TRANSLATOR,
|
||||
0, 0, priv_data);
|
||||
if (ret & BLOCK_ABORT)
|
||||
goto abort_exit;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Iterate over normal data blocks
|
||||
*/
|
||||
for (i = 0; i < EXT2_NDIR_BLOCKS ; i++, ctx.bcount++) {
|
||||
if (blocks[i] || (flags & BLOCK_FLAG_APPEND)) {
|
||||
ret |= (*ctx.func)(fs, &blocks[i],
|
||||
ctx.bcount, 0, i, priv_data);
|
||||
if (ret & BLOCK_ABORT)
|
||||
goto abort_exit;
|
||||
}
|
||||
}
|
||||
if (*(blocks + EXT2_IND_BLOCK) || (flags & BLOCK_FLAG_APPEND)) {
|
||||
ret |= block_iterate_ind(blocks + EXT2_IND_BLOCK,
|
||||
0, EXT2_IND_BLOCK, &ctx);
|
||||
if (ret & BLOCK_ABORT)
|
||||
goto abort_exit;
|
||||
} else
|
||||
ctx.bcount += limit;
|
||||
if (*(blocks + EXT2_DIND_BLOCK) || (flags & BLOCK_FLAG_APPEND)) {
|
||||
ret |= block_iterate_dind(blocks + EXT2_DIND_BLOCK,
|
||||
0, EXT2_DIND_BLOCK, &ctx);
|
||||
if (ret & BLOCK_ABORT)
|
||||
goto abort_exit;
|
||||
} else
|
||||
ctx.bcount += limit * limit;
|
||||
if (*(blocks + EXT2_TIND_BLOCK) || (flags & BLOCK_FLAG_APPEND)) {
|
||||
ret |= block_iterate_tind(blocks + EXT2_TIND_BLOCK,
|
||||
0, EXT2_TIND_BLOCK, &ctx);
|
||||
if (ret & BLOCK_ABORT)
|
||||
goto abort_exit;
|
||||
}
|
||||
|
||||
abort_exit:
|
||||
if (ret & BLOCK_CHANGED) {
|
||||
if (!got_inode) {
|
||||
retval = ext2fs_read_inode(fs, ino, &inode);
|
||||
if (retval)
|
||||
return retval;
|
||||
}
|
||||
for (i=0; i < EXT2_N_BLOCKS; i++)
|
||||
inode.i_block[i] = blocks[i];
|
||||
retval = ext2fs_write_inode(fs, ino, &inode);
|
||||
if (retval)
|
||||
return retval;
|
||||
}
|
||||
|
||||
if (!block_buf)
|
||||
ext2fs_free_mem(&ctx.ind_buf);
|
||||
|
||||
return (ret & BLOCK_ERROR) ? ctx.errcode : 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Emulate the old ext2fs_block_iterate function!
|
||||
*/
|
||||
|
||||
struct xlate {
|
||||
int (*func)(ext2_filsys fs,
|
||||
blk_t *blocknr,
|
||||
int bcount,
|
||||
void *priv_data);
|
||||
void *real_private;
|
||||
};
|
||||
|
||||
#ifdef __TURBOC__
|
||||
# pragma argsused
|
||||
#endif
|
||||
static int xlate_func(ext2_filsys fs, blk_t *blocknr, e2_blkcnt_t blockcnt,
|
||||
blk_t ref_block EXT2FS_ATTR((unused)),
|
||||
int ref_offset EXT2FS_ATTR((unused)),
|
||||
void *priv_data)
|
||||
{
|
||||
struct xlate *xl = (struct xlate *) priv_data;
|
||||
|
||||
return (*xl->func)(fs, blocknr, (int) blockcnt, xl->real_private);
|
||||
}
|
||||
|
||||
errcode_t ext2fs_block_iterate(ext2_filsys fs,
|
||||
ext2_ino_t ino,
|
||||
int flags,
|
||||
char *block_buf,
|
||||
int (*func)(ext2_filsys fs,
|
||||
blk_t *blocknr,
|
||||
int blockcnt,
|
||||
void *priv_data),
|
||||
void *priv_data)
|
||||
{
|
||||
struct xlate xl;
|
||||
|
||||
xl.real_private = priv_data;
|
||||
xl.func = func;
|
||||
|
||||
return ext2fs_block_iterate2(fs, ino, BLOCK_FLAG_NO_LARGE | flags,
|
||||
block_buf, xlate_func, &xl);
|
||||
}
|
||||
|
264
e2fsprogs/old_e2fsprogs/ext2fs/bmap.c
Normal file
264
e2fsprogs/old_e2fsprogs/ext2fs/bmap.c
Normal file
@ -0,0 +1,264 @@
|
||||
/* vi: set sw=4 ts=4: */
|
||||
/*
|
||||
* bmap.c --- logical to physical block mapping
|
||||
*
|
||||
* Copyright (C) 1997 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>
|
||||
#if HAVE_UNISTD_H
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
|
||||
#include "ext2_fs.h"
|
||||
#include "ext2fs.h"
|
||||
|
||||
extern errcode_t ext2fs_bmap(ext2_filsys fs, ext2_ino_t ino,
|
||||
struct ext2_inode *inode,
|
||||
char *block_buf, int bmap_flags,
|
||||
blk_t block, blk_t *phys_blk);
|
||||
|
||||
#define inode_bmap(inode, nr) ((inode)->i_block[(nr)])
|
||||
|
||||
static errcode_t block_ind_bmap(ext2_filsys fs, int flags,
|
||||
blk_t ind, char *block_buf,
|
||||
int *blocks_alloc,
|
||||
blk_t nr, blk_t *ret_blk)
|
||||
{
|
||||
errcode_t retval;
|
||||
blk_t b;
|
||||
|
||||
if (!ind) {
|
||||
if (flags & BMAP_SET)
|
||||
return EXT2_ET_SET_BMAP_NO_IND;
|
||||
*ret_blk = 0;
|
||||
return 0;
|
||||
}
|
||||
retval = io_channel_read_blk(fs->io, ind, 1, block_buf);
|
||||
if (retval)
|
||||
return retval;
|
||||
|
||||
if (flags & BMAP_SET) {
|
||||
b = *ret_blk;
|
||||
#if BB_BIG_ENDIAN
|
||||
if ((fs->flags & EXT2_FLAG_SWAP_BYTES) ||
|
||||
(fs->flags & EXT2_FLAG_SWAP_BYTES_WRITE))
|
||||
b = ext2fs_swab32(b);
|
||||
#endif
|
||||
((blk_t *) block_buf)[nr] = b;
|
||||
return io_channel_write_blk(fs->io, ind, 1, block_buf);
|
||||
}
|
||||
|
||||
b = ((blk_t *) block_buf)[nr];
|
||||
|
||||
#if BB_BIG_ENDIAN
|
||||
if ((fs->flags & EXT2_FLAG_SWAP_BYTES) ||
|
||||
(fs->flags & EXT2_FLAG_SWAP_BYTES_READ))
|
||||
b = ext2fs_swab32(b);
|
||||
#endif
|
||||
|
||||
if (!b && (flags & BMAP_ALLOC)) {
|
||||
b = nr ? ((blk_t *) block_buf)[nr-1] : 0;
|
||||
retval = ext2fs_alloc_block(fs, b,
|
||||
block_buf + fs->blocksize, &b);
|
||||
if (retval)
|
||||
return retval;
|
||||
|
||||
#if BB_BIG_ENDIAN
|
||||
if ((fs->flags & EXT2_FLAG_SWAP_BYTES) ||
|
||||
(fs->flags & EXT2_FLAG_SWAP_BYTES_WRITE))
|
||||
((blk_t *) block_buf)[nr] = ext2fs_swab32(b);
|
||||
else
|
||||
#endif
|
||||
((blk_t *) block_buf)[nr] = b;
|
||||
|
||||
retval = io_channel_write_blk(fs->io, ind, 1, block_buf);
|
||||
if (retval)
|
||||
return retval;
|
||||
|
||||
(*blocks_alloc)++;
|
||||
}
|
||||
|
||||
*ret_blk = b;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static errcode_t block_dind_bmap(ext2_filsys fs, int flags,
|
||||
blk_t dind, char *block_buf,
|
||||
int *blocks_alloc,
|
||||
blk_t nr, blk_t *ret_blk)
|
||||
{
|
||||
blk_t b;
|
||||
errcode_t retval;
|
||||
blk_t addr_per_block;
|
||||
|
||||
addr_per_block = (blk_t) fs->blocksize >> 2;
|
||||
|
||||
retval = block_ind_bmap(fs, flags & ~BMAP_SET, dind, block_buf,
|
||||
blocks_alloc, nr / addr_per_block, &b);
|
||||
if (retval)
|
||||
return retval;
|
||||
retval = block_ind_bmap(fs, flags, b, block_buf, blocks_alloc,
|
||||
nr % addr_per_block, ret_blk);
|
||||
return retval;
|
||||
}
|
||||
|
||||
static errcode_t block_tind_bmap(ext2_filsys fs, int flags,
|
||||
blk_t tind, char *block_buf,
|
||||
int *blocks_alloc,
|
||||
blk_t nr, blk_t *ret_blk)
|
||||
{
|
||||
blk_t b;
|
||||
errcode_t retval;
|
||||
blk_t addr_per_block;
|
||||
|
||||
addr_per_block = (blk_t) fs->blocksize >> 2;
|
||||
|
||||
retval = block_dind_bmap(fs, flags & ~BMAP_SET, tind, block_buf,
|
||||
blocks_alloc, nr / addr_per_block, &b);
|
||||
if (retval)
|
||||
return retval;
|
||||
retval = block_ind_bmap(fs, flags, b, block_buf, blocks_alloc,
|
||||
nr % addr_per_block, ret_blk);
|
||||
return retval;
|
||||
}
|
||||
|
||||
errcode_t ext2fs_bmap(ext2_filsys fs, ext2_ino_t ino, struct ext2_inode *inode,
|
||||
char *block_buf, int bmap_flags, blk_t block,
|
||||
blk_t *phys_blk)
|
||||
{
|
||||
struct ext2_inode inode_buf;
|
||||
blk_t addr_per_block;
|
||||
blk_t b;
|
||||
char *buf = 0;
|
||||
errcode_t retval = 0;
|
||||
int blocks_alloc = 0, inode_dirty = 0;
|
||||
|
||||
if (!(bmap_flags & BMAP_SET))
|
||||
*phys_blk = 0;
|
||||
|
||||
/* Read inode structure if necessary */
|
||||
if (!inode) {
|
||||
retval = ext2fs_read_inode(fs, ino, &inode_buf);
|
||||
if (retval)
|
||||
return retval;
|
||||
inode = &inode_buf;
|
||||
}
|
||||
addr_per_block = (blk_t) fs->blocksize >> 2;
|
||||
|
||||
if (!block_buf) {
|
||||
retval = ext2fs_get_mem(fs->blocksize * 2, &buf);
|
||||
if (retval)
|
||||
return retval;
|
||||
block_buf = buf;
|
||||
}
|
||||
|
||||
if (block < EXT2_NDIR_BLOCKS) {
|
||||
if (bmap_flags & BMAP_SET) {
|
||||
b = *phys_blk;
|
||||
#if BB_BIG_ENDIAN
|
||||
if ((fs->flags & EXT2_FLAG_SWAP_BYTES) ||
|
||||
(fs->flags & EXT2_FLAG_SWAP_BYTES_READ))
|
||||
b = ext2fs_swab32(b);
|
||||
#endif
|
||||
inode_bmap(inode, block) = b;
|
||||
inode_dirty++;
|
||||
goto done;
|
||||
}
|
||||
|
||||
*phys_blk = inode_bmap(inode, block);
|
||||
b = block ? inode_bmap(inode, block-1) : 0;
|
||||
|
||||
if ((*phys_blk == 0) && (bmap_flags & BMAP_ALLOC)) {
|
||||
retval = ext2fs_alloc_block(fs, b, block_buf, &b);
|
||||
if (retval)
|
||||
goto done;
|
||||
inode_bmap(inode, block) = b;
|
||||
blocks_alloc++;
|
||||
*phys_blk = b;
|
||||
}
|
||||
goto done;
|
||||
}
|
||||
|
||||
/* Indirect block */
|
||||
block -= EXT2_NDIR_BLOCKS;
|
||||
if (block < addr_per_block) {
|
||||
b = inode_bmap(inode, EXT2_IND_BLOCK);
|
||||
if (!b) {
|
||||
if (!(bmap_flags & BMAP_ALLOC)) {
|
||||
if (bmap_flags & BMAP_SET)
|
||||
retval = EXT2_ET_SET_BMAP_NO_IND;
|
||||
goto done;
|
||||
}
|
||||
|
||||
b = inode_bmap(inode, EXT2_IND_BLOCK-1);
|
||||
retval = ext2fs_alloc_block(fs, b, block_buf, &b);
|
||||
if (retval)
|
||||
goto done;
|
||||
inode_bmap(inode, EXT2_IND_BLOCK) = b;
|
||||
blocks_alloc++;
|
||||
}
|
||||
retval = block_ind_bmap(fs, bmap_flags, b, block_buf,
|
||||
&blocks_alloc, block, phys_blk);
|
||||
goto done;
|
||||
}
|
||||
|
||||
/* Doubly indirect block */
|
||||
block -= addr_per_block;
|
||||
if (block < addr_per_block * addr_per_block) {
|
||||
b = inode_bmap(inode, EXT2_DIND_BLOCK);
|
||||
if (!b) {
|
||||
if (!(bmap_flags & BMAP_ALLOC)) {
|
||||
if (bmap_flags & BMAP_SET)
|
||||
retval = EXT2_ET_SET_BMAP_NO_IND;
|
||||
goto done;
|
||||
}
|
||||
|
||||
b = inode_bmap(inode, EXT2_IND_BLOCK);
|
||||
retval = ext2fs_alloc_block(fs, b, block_buf, &b);
|
||||
if (retval)
|
||||
goto done;
|
||||
inode_bmap(inode, EXT2_DIND_BLOCK) = b;
|
||||
blocks_alloc++;
|
||||
}
|
||||
retval = block_dind_bmap(fs, bmap_flags, b, block_buf,
|
||||
&blocks_alloc, block, phys_blk);
|
||||
goto done;
|
||||
}
|
||||
|
||||
/* Triply indirect block */
|
||||
block -= addr_per_block * addr_per_block;
|
||||
b = inode_bmap(inode, EXT2_TIND_BLOCK);
|
||||
if (!b) {
|
||||
if (!(bmap_flags & BMAP_ALLOC)) {
|
||||
if (bmap_flags & BMAP_SET)
|
||||
retval = EXT2_ET_SET_BMAP_NO_IND;
|
||||
goto done;
|
||||
}
|
||||
|
||||
b = inode_bmap(inode, EXT2_DIND_BLOCK);
|
||||
retval = ext2fs_alloc_block(fs, b, block_buf, &b);
|
||||
if (retval)
|
||||
goto done;
|
||||
inode_bmap(inode, EXT2_TIND_BLOCK) = b;
|
||||
blocks_alloc++;
|
||||
}
|
||||
retval = block_tind_bmap(fs, bmap_flags, b, block_buf,
|
||||
&blocks_alloc, block, phys_blk);
|
||||
done:
|
||||
ext2fs_free_mem(&buf);
|
||||
if ((retval == 0) && (blocks_alloc || inode_dirty)) {
|
||||
inode->i_blocks += (blocks_alloc * fs->blocksize) / 512;
|
||||
retval = ext2fs_write_inode(fs, ino, inode);
|
||||
}
|
||||
return retval;
|
||||
}
|
||||
|
||||
|
||||
|
156
e2fsprogs/old_e2fsprogs/ext2fs/bmove.c
Normal file
156
e2fsprogs/old_e2fsprogs/ext2fs/bmove.c
Normal file
@ -0,0 +1,156 @@
|
||||
/* vi: set sw=4 ts=4: */
|
||||
/*
|
||||
* bmove.c --- Move blocks around to make way for a particular
|
||||
* filesystem structure.
|
||||
*
|
||||
* Copyright (C) 1997 Theodore Ts'o. This file may be redistributed
|
||||
* under the terms of the GNU Public License.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#if HAVE_UNISTD_H
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
#if HAVE_SYS_TYPES_H
|
||||
#include <sys/types.h>
|
||||
#endif
|
||||
|
||||
#include "ext2_fs.h"
|
||||
#include "ext2fsP.h"
|
||||
|
||||
struct process_block_struct {
|
||||
ext2_ino_t ino;
|
||||
struct ext2_inode * inode;
|
||||
ext2fs_block_bitmap reserve;
|
||||
ext2fs_block_bitmap alloc_map;
|
||||
errcode_t error;
|
||||
char *buf;
|
||||
int add_dir;
|
||||
int flags;
|
||||
};
|
||||
|
||||
static int process_block(ext2_filsys fs, blk_t *block_nr,
|
||||
e2_blkcnt_t blockcnt, blk_t ref_block,
|
||||
int ref_offset, void *priv_data)
|
||||
{
|
||||
struct process_block_struct *pb;
|
||||
errcode_t retval;
|
||||
int ret;
|
||||
blk_t block, orig;
|
||||
|
||||
pb = (struct process_block_struct *) priv_data;
|
||||
block = orig = *block_nr;
|
||||
ret = 0;
|
||||
|
||||
/*
|
||||
* Let's see if this is one which we need to relocate
|
||||
*/
|
||||
if (ext2fs_test_block_bitmap(pb->reserve, block)) {
|
||||
do {
|
||||
if (++block >= fs->super->s_blocks_count)
|
||||
block = fs->super->s_first_data_block;
|
||||
if (block == orig) {
|
||||
pb->error = EXT2_ET_BLOCK_ALLOC_FAIL;
|
||||
return BLOCK_ABORT;
|
||||
}
|
||||
} while (ext2fs_test_block_bitmap(pb->reserve, block) ||
|
||||
ext2fs_test_block_bitmap(pb->alloc_map, block));
|
||||
|
||||
retval = io_channel_read_blk(fs->io, orig, 1, pb->buf);
|
||||
if (retval) {
|
||||
pb->error = retval;
|
||||
return BLOCK_ABORT;
|
||||
}
|
||||
retval = io_channel_write_blk(fs->io, block, 1, pb->buf);
|
||||
if (retval) {
|
||||
pb->error = retval;
|
||||
return BLOCK_ABORT;
|
||||
}
|
||||
*block_nr = block;
|
||||
ext2fs_mark_block_bitmap(pb->alloc_map, block);
|
||||
ret = BLOCK_CHANGED;
|
||||
if (pb->flags & EXT2_BMOVE_DEBUG)
|
||||
printf("ino=%ld, blockcnt=%lld, %d->%d\n", pb->ino,
|
||||
blockcnt, orig, block);
|
||||
}
|
||||
if (pb->add_dir) {
|
||||
retval = ext2fs_add_dir_block(fs->dblist, pb->ino,
|
||||
block, (int) blockcnt);
|
||||
if (retval) {
|
||||
pb->error = retval;
|
||||
ret |= BLOCK_ABORT;
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
errcode_t ext2fs_move_blocks(ext2_filsys fs,
|
||||
ext2fs_block_bitmap reserve,
|
||||
ext2fs_block_bitmap alloc_map,
|
||||
int flags)
|
||||
{
|
||||
ext2_ino_t ino;
|
||||
struct ext2_inode inode;
|
||||
errcode_t retval;
|
||||
struct process_block_struct pb;
|
||||
ext2_inode_scan scan;
|
||||
char *block_buf;
|
||||
|
||||
retval = ext2fs_open_inode_scan(fs, 0, &scan);
|
||||
if (retval)
|
||||
return retval;
|
||||
|
||||
pb.reserve = reserve;
|
||||
pb.error = 0;
|
||||
pb.alloc_map = alloc_map ? alloc_map : fs->block_map;
|
||||
pb.flags = flags;
|
||||
|
||||
retval = ext2fs_get_mem(fs->blocksize * 4, &block_buf);
|
||||
if (retval)
|
||||
return retval;
|
||||
pb.buf = block_buf + fs->blocksize * 3;
|
||||
|
||||
/*
|
||||
* If GET_DBLIST is set in the flags field, then we should
|
||||
* gather directory block information while we're doing the
|
||||
* block move.
|
||||
*/
|
||||
if (flags & EXT2_BMOVE_GET_DBLIST) {
|
||||
ext2fs_free_dblist(fs->dblist);
|
||||
fs->dblist = NULL;
|
||||
retval = ext2fs_init_dblist(fs, 0);
|
||||
if (retval)
|
||||
return retval;
|
||||
}
|
||||
|
||||
retval = ext2fs_get_next_inode(scan, &ino, &inode);
|
||||
if (retval)
|
||||
return retval;
|
||||
|
||||
while (ino) {
|
||||
if ((inode.i_links_count == 0) ||
|
||||
!ext2fs_inode_has_valid_blocks(&inode))
|
||||
goto next;
|
||||
|
||||
pb.ino = ino;
|
||||
pb.inode = &inode;
|
||||
|
||||
pb.add_dir = (LINUX_S_ISDIR(inode.i_mode) &&
|
||||
flags & EXT2_BMOVE_GET_DBLIST);
|
||||
|
||||
retval = ext2fs_block_iterate2(fs, ino, 0, block_buf,
|
||||
process_block, &pb);
|
||||
if (retval)
|
||||
return retval;
|
||||
if (pb.error)
|
||||
return pb.error;
|
||||
|
||||
next:
|
||||
retval = ext2fs_get_next_inode(scan, &ino, &inode);
|
||||
if (retval == EXT2_ET_BAD_BLOCK_IN_INODE_TABLE)
|
||||
goto next;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
87
e2fsprogs/old_e2fsprogs/ext2fs/brel.h
Normal file
87
e2fsprogs/old_e2fsprogs/ext2fs/brel.h
Normal file
@ -0,0 +1,87 @@
|
||||
/* vi: set sw=4 ts=4: */
|
||||
/*
|
||||
* brel.h
|
||||
*
|
||||
* Copyright (C) 1996, 1997 Theodore Ts'o.
|
||||
*
|
||||
* %Begin-Header%
|
||||
* This file may be redistributed under the terms of the GNU Public
|
||||
* License.
|
||||
* %End-Header%
|
||||
*/
|
||||
|
||||
struct ext2_block_relocate_entry {
|
||||
blk_t new;
|
||||
__s16 offset;
|
||||
__u16 flags;
|
||||
union {
|
||||
blk_t block_ref;
|
||||
ext2_ino_t inode_ref;
|
||||
} owner;
|
||||
};
|
||||
|
||||
#define RELOCATE_TYPE_REF 0x0007
|
||||
#define RELOCATE_BLOCK_REF 0x0001
|
||||
#define RELOCATE_INODE_REF 0x0002
|
||||
|
||||
typedef struct ext2_block_relocation_table *ext2_brel;
|
||||
|
||||
struct ext2_block_relocation_table {
|
||||
__u32 magic;
|
||||
char *name;
|
||||
blk_t current;
|
||||
void *priv_data;
|
||||
|
||||
/*
|
||||
* Add a block relocation entry.
|
||||
*/
|
||||
errcode_t (*put)(ext2_brel brel, blk_t old,
|
||||
struct ext2_block_relocate_entry *ent);
|
||||
|
||||
/*
|
||||
* Get a block relocation entry.
|
||||
*/
|
||||
errcode_t (*get)(ext2_brel brel, blk_t old,
|
||||
struct ext2_block_relocate_entry *ent);
|
||||
|
||||
/*
|
||||
* Initialize for iterating over the block relocation entries.
|
||||
*/
|
||||
errcode_t (*start_iter)(ext2_brel brel);
|
||||
|
||||
/*
|
||||
* The iterator function for the inode relocation entries.
|
||||
* Returns an inode number of 0 when out of entries.
|
||||
*/
|
||||
errcode_t (*next)(ext2_brel brel, blk_t *old,
|
||||
struct ext2_block_relocate_entry *ent);
|
||||
|
||||
/*
|
||||
* Move the inode relocation table from one block number to
|
||||
* another.
|
||||
*/
|
||||
errcode_t (*move)(ext2_brel brel, blk_t old, blk_t new);
|
||||
|
||||
/*
|
||||
* Remove a block relocation entry.
|
||||
*/
|
||||
errcode_t (*delete)(ext2_brel brel, blk_t old);
|
||||
|
||||
|
||||
/*
|
||||
* Free the block relocation table.
|
||||
*/
|
||||
errcode_t (*free)(ext2_brel brel);
|
||||
};
|
||||
|
||||
errcode_t ext2fs_brel_memarray_create(char *name, blk_t max_block,
|
||||
ext2_brel *brel);
|
||||
|
||||
#define ext2fs_brel_put(brel, old, ent) ((brel)->put((brel), old, ent))
|
||||
#define ext2fs_brel_get(brel, old, ent) ((brel)->get((brel), old, ent))
|
||||
#define ext2fs_brel_start_iter(brel) ((brel)->start_iter((brel)))
|
||||
#define ext2fs_brel_next(brel, old, ent) ((brel)->next((brel), old, ent))
|
||||
#define ext2fs_brel_move(brel, old, new) ((brel)->move((brel), old, new))
|
||||
#define ext2fs_brel_delete(brel, old) ((brel)->delete((brel), old))
|
||||
#define ext2fs_brel_free(brel) ((brel)->free((brel)))
|
||||
|
196
e2fsprogs/old_e2fsprogs/ext2fs/brel_ma.c
Normal file
196
e2fsprogs/old_e2fsprogs/ext2fs/brel_ma.c
Normal file
@ -0,0 +1,196 @@
|
||||
/* vi: set sw=4 ts=4: */
|
||||
/*
|
||||
* brel_ma.c
|
||||
*
|
||||
* Copyright (C) 1996, 1997 Theodore Ts'o.
|
||||
*
|
||||
* TODO: rewrite to not use a direct array!!! (Fortunately this
|
||||
* module isn't really used yet.)
|
||||
*
|
||||
* %Begin-Header%
|
||||
* This file may be redistributed under the terms of the GNU Public
|
||||
* License.
|
||||
* %End-Header%
|
||||
*/
|
||||
|
||||
#include <fcntl.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#if HAVE_UNISTD_H
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
#if HAVE_ERRNO_H
|
||||
#include <errno.h>
|
||||
#endif
|
||||
|
||||
#include "ext2_fs.h"
|
||||
#include "ext2fs.h"
|
||||
#include "brel.h"
|
||||
|
||||
static errcode_t bma_put(ext2_brel brel, blk_t old,
|
||||
struct ext2_block_relocate_entry *ent);
|
||||
static errcode_t bma_get(ext2_brel brel, blk_t old,
|
||||
struct ext2_block_relocate_entry *ent);
|
||||
static errcode_t bma_start_iter(ext2_brel brel);
|
||||
static errcode_t bma_next(ext2_brel brel, blk_t *old,
|
||||
struct ext2_block_relocate_entry *ent);
|
||||
static errcode_t bma_move(ext2_brel brel, blk_t old, blk_t new);
|
||||
static errcode_t bma_delete(ext2_brel brel, blk_t old);
|
||||
static errcode_t bma_free(ext2_brel brel);
|
||||
|
||||
struct brel_ma {
|
||||
__u32 magic;
|
||||
blk_t max_block;
|
||||
struct ext2_block_relocate_entry *entries;
|
||||
};
|
||||
|
||||
errcode_t ext2fs_brel_memarray_create(char *name, blk_t max_block,
|
||||
ext2_brel *new_brel)
|
||||
{
|
||||
ext2_brel brel = 0;
|
||||
errcode_t retval;
|
||||
struct brel_ma *ma = 0;
|
||||
size_t size;
|
||||
|
||||
*new_brel = 0;
|
||||
|
||||
/*
|
||||
* Allocate memory structures
|
||||
*/
|
||||
retval = ext2fs_get_mem(sizeof(struct ext2_block_relocation_table),
|
||||
&brel);
|
||||
if (retval)
|
||||
goto errout;
|
||||
memset(brel, 0, sizeof(struct ext2_block_relocation_table));
|
||||
|
||||
retval = ext2fs_get_mem(strlen(name)+1, &brel->name);
|
||||
if (retval)
|
||||
goto errout;
|
||||
strcpy(brel->name, name);
|
||||
|
||||
retval = ext2fs_get_mem(sizeof(struct brel_ma), &ma);
|
||||
if (retval)
|
||||
goto errout;
|
||||
memset(ma, 0, sizeof(struct brel_ma));
|
||||
brel->priv_data = ma;
|
||||
|
||||
size = (size_t) (sizeof(struct ext2_block_relocate_entry) *
|
||||
(max_block+1));
|
||||
retval = ext2fs_get_mem(size, &ma->entries);
|
||||
if (retval)
|
||||
goto errout;
|
||||
memset(ma->entries, 0, size);
|
||||
ma->max_block = max_block;
|
||||
|
||||
/*
|
||||
* Fill in the brel data structure
|
||||
*/
|
||||
brel->put = bma_put;
|
||||
brel->get = bma_get;
|
||||
brel->start_iter = bma_start_iter;
|
||||
brel->next = bma_next;
|
||||
brel->move = bma_move;
|
||||
brel->delete = bma_delete;
|
||||
brel->free = bma_free;
|
||||
|
||||
*new_brel = brel;
|
||||
return 0;
|
||||
|
||||
errout:
|
||||
bma_free(brel);
|
||||
return retval;
|
||||
}
|
||||
|
||||
static errcode_t bma_put(ext2_brel brel, blk_t old,
|
||||
struct ext2_block_relocate_entry *ent)
|
||||
{
|
||||
struct brel_ma *ma;
|
||||
|
||||
ma = brel->priv_data;
|
||||
if (old > ma->max_block)
|
||||
return EXT2_ET_INVALID_ARGUMENT;
|
||||
ma->entries[(unsigned)old] = *ent;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static errcode_t bma_get(ext2_brel brel, blk_t old,
|
||||
struct ext2_block_relocate_entry *ent)
|
||||
{
|
||||
struct brel_ma *ma;
|
||||
|
||||
ma = brel->priv_data;
|
||||
if (old > ma->max_block)
|
||||
return EXT2_ET_INVALID_ARGUMENT;
|
||||
if (ma->entries[(unsigned)old].new == 0)
|
||||
return ENOENT;
|
||||
*ent = ma->entries[old];
|
||||
return 0;
|
||||
}
|
||||
|
||||
static errcode_t bma_start_iter(ext2_brel brel)
|
||||
{
|
||||
brel->current = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static errcode_t bma_next(ext2_brel brel, blk_t *old,
|
||||
struct ext2_block_relocate_entry *ent)
|
||||
{
|
||||
struct brel_ma *ma;
|
||||
|
||||
ma = brel->priv_data;
|
||||
while (++brel->current < ma->max_block) {
|
||||
if (ma->entries[(unsigned)brel->current].new == 0)
|
||||
continue;
|
||||
*old = brel->current;
|
||||
*ent = ma->entries[(unsigned)brel->current];
|
||||
return 0;
|
||||
}
|
||||
*old = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static errcode_t bma_move(ext2_brel brel, blk_t old, blk_t new)
|
||||
{
|
||||
struct brel_ma *ma;
|
||||
|
||||
ma = brel->priv_data;
|
||||
if ((old > ma->max_block) || (new > ma->max_block))
|
||||
return EXT2_ET_INVALID_ARGUMENT;
|
||||
if (ma->entries[(unsigned)old].new == 0)
|
||||
return ENOENT;
|
||||
ma->entries[(unsigned)new] = ma->entries[old];
|
||||
ma->entries[(unsigned)old].new = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static errcode_t bma_delete(ext2_brel brel, blk_t old)
|
||||
{
|
||||
struct brel_ma *ma;
|
||||
|
||||
ma = brel->priv_data;
|
||||
if (old > ma->max_block)
|
||||
return EXT2_ET_INVALID_ARGUMENT;
|
||||
if (ma->entries[(unsigned)old].new == 0)
|
||||
return ENOENT;
|
||||
ma->entries[(unsigned)old].new = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static errcode_t bma_free(ext2_brel brel)
|
||||
{
|
||||
struct brel_ma *ma;
|
||||
|
||||
if (!brel)
|
||||
return 0;
|
||||
|
||||
ma = brel->priv_data;
|
||||
|
||||
if (ma) {
|
||||
ext2fs_free_mem(&ma->entries);
|
||||
ext2fs_free_mem(&ma);
|
||||
}
|
||||
ext2fs_free_mem(&brel->name);
|
||||
ext2fs_free_mem(&brel);
|
||||
return 0;
|
||||
}
|
69
e2fsprogs/old_e2fsprogs/ext2fs/check_desc.c
Normal file
69
e2fsprogs/old_e2fsprogs/ext2fs/check_desc.c
Normal file
@ -0,0 +1,69 @@
|
||||
/* vi: set sw=4 ts=4: */
|
||||
/*
|
||||
* check_desc.c --- Check the group descriptors of an ext2 filesystem
|
||||
*
|
||||
* Copyright (C) 1993, 1994, 1995, 1996 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>
|
||||
#if HAVE_UNISTD_H
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
#include <fcntl.h>
|
||||
#include <time.h>
|
||||
#if HAVE_SYS_STAT_H
|
||||
#include <sys/stat.h>
|
||||
#endif
|
||||
#if HAVE_SYS_TYPES_H
|
||||
#include <sys/types.h>
|
||||
#endif
|
||||
|
||||
#include "ext2_fs.h"
|
||||
#include "ext2fs.h"
|
||||
|
||||
/*
|
||||
* This routine sanity checks the group descriptors
|
||||
*/
|
||||
errcode_t ext2fs_check_desc(ext2_filsys fs)
|
||||
{
|
||||
dgrp_t i;
|
||||
blk_t block = fs->super->s_first_data_block;
|
||||
blk_t next;
|
||||
|
||||
EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS);
|
||||
|
||||
for (i = 0; i < fs->group_desc_count; i++) {
|
||||
next = block + fs->super->s_blocks_per_group;
|
||||
/*
|
||||
* Check to make sure block bitmap for group is
|
||||
* located within the group.
|
||||
*/
|
||||
if (fs->group_desc[i].bg_block_bitmap < block ||
|
||||
fs->group_desc[i].bg_block_bitmap >= next)
|
||||
return EXT2_ET_GDESC_BAD_BLOCK_MAP;
|
||||
/*
|
||||
* Check to make sure inode bitmap for group is
|
||||
* located within the group
|
||||
*/
|
||||
if (fs->group_desc[i].bg_inode_bitmap < block ||
|
||||
fs->group_desc[i].bg_inode_bitmap >= next)
|
||||
return EXT2_ET_GDESC_BAD_INODE_MAP;
|
||||
/*
|
||||
* Check to make sure inode table for group is located
|
||||
* within the group
|
||||
*/
|
||||
if (fs->group_desc[i].bg_inode_table < block ||
|
||||
((fs->group_desc[i].bg_inode_table +
|
||||
fs->inode_blocks_per_group) >= next))
|
||||
return EXT2_ET_GDESC_BAD_INODE_TABLE;
|
||||
|
||||
block = next;
|
||||
}
|
||||
return 0;
|
||||
}
|
381
e2fsprogs/old_e2fsprogs/ext2fs/closefs.c
Normal file
381
e2fsprogs/old_e2fsprogs/ext2fs/closefs.c
Normal file
@ -0,0 +1,381 @@
|
||||
/* vi: set sw=4 ts=4: */
|
||||
/*
|
||||
* closefs.c --- close an ext2 filesystem
|
||||
*
|
||||
* Copyright (C) 1993, 1994, 1995, 1996 Theodore Ts'o.
|
||||
*
|
||||
* %Begin-Header%
|
||||
* This file may be redistributed under the terms of the GNU Public
|
||||
* License.
|
||||
* %End-Header%
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#if HAVE_UNISTD_H
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
#include <time.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "ext2_fs.h"
|
||||
#include "ext2fsP.h"
|
||||
|
||||
static int test_root(int a, int b)
|
||||
{
|
||||
if (a == 0)
|
||||
return 1;
|
||||
while (1) {
|
||||
if (a == 1)
|
||||
return 1;
|
||||
if (a % b)
|
||||
return 0;
|
||||
a = a / b;
|
||||
}
|
||||
}
|
||||
|
||||
int ext2fs_bg_has_super(ext2_filsys fs, int group_block)
|
||||
{
|
||||
if (!(fs->super->s_feature_ro_compat &
|
||||
EXT2_FEATURE_RO_COMPAT_SPARSE_SUPER))
|
||||
return 1;
|
||||
|
||||
if (test_root(group_block, 3) || (test_root(group_block, 5)) ||
|
||||
test_root(group_block, 7))
|
||||
return 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int ext2fs_super_and_bgd_loc(ext2_filsys fs,
|
||||
dgrp_t group,
|
||||
blk_t *ret_super_blk,
|
||||
blk_t *ret_old_desc_blk,
|
||||
blk_t *ret_new_desc_blk,
|
||||
int *ret_meta_bg)
|
||||
{
|
||||
blk_t group_block, super_blk = 0, old_desc_blk = 0, new_desc_blk = 0;
|
||||
unsigned int meta_bg, meta_bg_size;
|
||||
int numblocks, has_super;
|
||||
int old_desc_blocks;
|
||||
|
||||
group_block = fs->super->s_first_data_block +
|
||||
(group * fs->super->s_blocks_per_group);
|
||||
|
||||
if (fs->super->s_feature_incompat & EXT2_FEATURE_INCOMPAT_META_BG)
|
||||
old_desc_blocks = fs->super->s_first_meta_bg;
|
||||
else
|
||||
old_desc_blocks =
|
||||
fs->desc_blocks + fs->super->s_reserved_gdt_blocks;
|
||||
|
||||
if (group == fs->group_desc_count-1) {
|
||||
numblocks = (fs->super->s_blocks_count -
|
||||
fs->super->s_first_data_block) %
|
||||
fs->super->s_blocks_per_group;
|
||||
if (!numblocks)
|
||||
numblocks = fs->super->s_blocks_per_group;
|
||||
} else
|
||||
numblocks = fs->super->s_blocks_per_group;
|
||||
|
||||
has_super = ext2fs_bg_has_super(fs, group);
|
||||
|
||||
if (has_super) {
|
||||
super_blk = group_block;
|
||||
numblocks--;
|
||||
}
|
||||
meta_bg_size = (fs->blocksize / sizeof (struct ext2_group_desc));
|
||||
meta_bg = group / meta_bg_size;
|
||||
|
||||
if (!(fs->super->s_feature_incompat & EXT2_FEATURE_INCOMPAT_META_BG) ||
|
||||
(meta_bg < fs->super->s_first_meta_bg)) {
|
||||
if (has_super) {
|
||||
old_desc_blk = group_block + 1;
|
||||
numblocks -= old_desc_blocks;
|
||||
}
|
||||
} else {
|
||||
if (((group % meta_bg_size) == 0) ||
|
||||
((group % meta_bg_size) == 1) ||
|
||||
((group % meta_bg_size) == (meta_bg_size-1))) {
|
||||
if (has_super)
|
||||
has_super = 1;
|
||||
new_desc_blk = group_block + has_super;
|
||||
numblocks--;
|
||||
}
|
||||
}
|
||||
|
||||
numblocks -= 2 + fs->inode_blocks_per_group;
|
||||
|
||||
if (ret_super_blk)
|
||||
*ret_super_blk = super_blk;
|
||||
if (ret_old_desc_blk)
|
||||
*ret_old_desc_blk = old_desc_blk;
|
||||
if (ret_new_desc_blk)
|
||||
*ret_new_desc_blk = new_desc_blk;
|
||||
if (ret_meta_bg)
|
||||
*ret_meta_bg = meta_bg;
|
||||
return numblocks;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* This function forces out the primary superblock. We need to only
|
||||
* write out those fields which we have changed, since if the
|
||||
* filesystem is mounted, it may have changed some of the other
|
||||
* fields.
|
||||
*
|
||||
* It takes as input a superblock which has already been byte swapped
|
||||
* (if necessary).
|
||||
*
|
||||
*/
|
||||
static errcode_t write_primary_superblock(ext2_filsys fs,
|
||||
struct ext2_super_block *super)
|
||||
{
|
||||
__u16 *old_super, *new_super;
|
||||
int check_idx, write_idx, size;
|
||||
errcode_t retval;
|
||||
|
||||
if (!fs->io->manager->write_byte || !fs->orig_super) {
|
||||
io_channel_set_blksize(fs->io, SUPERBLOCK_OFFSET);
|
||||
retval = io_channel_write_blk(fs->io, 1, -SUPERBLOCK_SIZE,
|
||||
super);
|
||||
io_channel_set_blksize(fs->io, fs->blocksize);
|
||||
return retval;
|
||||
}
|
||||
|
||||
old_super = (__u16 *) fs->orig_super;
|
||||
new_super = (__u16 *) super;
|
||||
|
||||
for (check_idx = 0; check_idx < SUPERBLOCK_SIZE/2; check_idx++) {
|
||||
if (old_super[check_idx] == new_super[check_idx])
|
||||
continue;
|
||||
write_idx = check_idx;
|
||||
for (check_idx++; check_idx < SUPERBLOCK_SIZE/2; check_idx++)
|
||||
if (old_super[check_idx] == new_super[check_idx])
|
||||
break;
|
||||
size = 2 * (check_idx - write_idx);
|
||||
retval = io_channel_write_byte(fs->io,
|
||||
SUPERBLOCK_OFFSET + (2 * write_idx), size,
|
||||
new_super + write_idx);
|
||||
if (retval)
|
||||
return retval;
|
||||
}
|
||||
memcpy(fs->orig_super, super, SUPERBLOCK_SIZE);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Updates the revision to EXT2_DYNAMIC_REV
|
||||
*/
|
||||
void ext2fs_update_dynamic_rev(ext2_filsys fs)
|
||||
{
|
||||
struct ext2_super_block *sb = fs->super;
|
||||
|
||||
if (sb->s_rev_level > EXT2_GOOD_OLD_REV)
|
||||
return;
|
||||
|
||||
sb->s_rev_level = EXT2_DYNAMIC_REV;
|
||||
sb->s_first_ino = EXT2_GOOD_OLD_FIRST_INO;
|
||||
sb->s_inode_size = EXT2_GOOD_OLD_INODE_SIZE;
|
||||
/* s_uuid is handled by e2fsck already */
|
||||
/* other fields should be left alone */
|
||||
}
|
||||
|
||||
static errcode_t write_backup_super(ext2_filsys fs, dgrp_t group,
|
||||
blk_t group_block,
|
||||
struct ext2_super_block *super_shadow)
|
||||
{
|
||||
dgrp_t sgrp = group;
|
||||
|
||||
if (sgrp > ((1 << 16) - 1))
|
||||
sgrp = (1 << 16) - 1;
|
||||
#if BB_BIG_ENDIAN
|
||||
if (fs->flags & EXT2_FLAG_SWAP_BYTES)
|
||||
super_shadow->s_block_group_nr = ext2fs_swab16(sgrp);
|
||||
else
|
||||
#endif
|
||||
fs->super->s_block_group_nr = sgrp;
|
||||
|
||||
return io_channel_write_blk(fs->io, group_block, -SUPERBLOCK_SIZE,
|
||||
super_shadow);
|
||||
}
|
||||
|
||||
|
||||
errcode_t ext2fs_flush(ext2_filsys fs)
|
||||
{
|
||||
dgrp_t i;
|
||||
blk_t group_block;
|
||||
errcode_t retval;
|
||||
unsigned long fs_state;
|
||||
struct ext2_super_block *super_shadow = 0;
|
||||
struct ext2_group_desc *group_shadow = 0;
|
||||
char *group_ptr;
|
||||
int old_desc_blocks;
|
||||
#if BB_BIG_ENDIAN
|
||||
dgrp_t j;
|
||||
struct ext2_group_desc *s, *t;
|
||||
#endif
|
||||
|
||||
EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS);
|
||||
|
||||
fs_state = fs->super->s_state;
|
||||
|
||||
fs->super->s_wtime = time(NULL);
|
||||
fs->super->s_block_group_nr = 0;
|
||||
#if BB_BIG_ENDIAN
|
||||
if (fs->flags & EXT2_FLAG_SWAP_BYTES) {
|
||||
retval = EXT2_ET_NO_MEMORY;
|
||||
retval = ext2fs_get_mem(SUPERBLOCK_SIZE, &super_shadow);
|
||||
if (retval)
|
||||
goto errout;
|
||||
retval = ext2fs_get_mem((size_t)(fs->blocksize *
|
||||
fs->desc_blocks),
|
||||
&group_shadow);
|
||||
if (retval)
|
||||
goto errout;
|
||||
memset(group_shadow, 0, (size_t) fs->blocksize *
|
||||
fs->desc_blocks);
|
||||
|
||||
/* swap the group descriptors */
|
||||
for (j=0, s=fs->group_desc, t=group_shadow;
|
||||
j < fs->group_desc_count; j++, t++, s++) {
|
||||
*t = *s;
|
||||
ext2fs_swap_group_desc(t);
|
||||
}
|
||||
} else {
|
||||
super_shadow = fs->super;
|
||||
group_shadow = fs->group_desc;
|
||||
}
|
||||
#else
|
||||
super_shadow = fs->super;
|
||||
group_shadow = fs->group_desc;
|
||||
#endif
|
||||
|
||||
/*
|
||||
* If this is an external journal device, don't write out the
|
||||
* block group descriptors or any of the backup superblocks
|
||||
*/
|
||||
if (fs->super->s_feature_incompat &
|
||||
EXT3_FEATURE_INCOMPAT_JOURNAL_DEV)
|
||||
goto write_primary_superblock_only;
|
||||
|
||||
/*
|
||||
* Set the state of the FS to be non-valid. (The state has
|
||||
* already been backed up earlier, and will be restored after
|
||||
* we write out the backup superblocks.)
|
||||
*/
|
||||
fs->super->s_state &= ~EXT2_VALID_FS;
|
||||
#if BB_BIG_ENDIAN
|
||||
if (fs->flags & EXT2_FLAG_SWAP_BYTES) {
|
||||
*super_shadow = *fs->super;
|
||||
ext2fs_swap_super(super_shadow);
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Write out the master group descriptors, and the backup
|
||||
* superblocks and group descriptors.
|
||||
*/
|
||||
group_block = fs->super->s_first_data_block;
|
||||
group_ptr = (char *) group_shadow;
|
||||
if (fs->super->s_feature_incompat & EXT2_FEATURE_INCOMPAT_META_BG)
|
||||
old_desc_blocks = fs->super->s_first_meta_bg;
|
||||
else
|
||||
old_desc_blocks = fs->desc_blocks;
|
||||
|
||||
for (i = 0; i < fs->group_desc_count; i++) {
|
||||
blk_t super_blk, old_desc_blk, new_desc_blk;
|
||||
int meta_bg;
|
||||
|
||||
ext2fs_super_and_bgd_loc(fs, i, &super_blk, &old_desc_blk,
|
||||
&new_desc_blk, &meta_bg);
|
||||
|
||||
if (!(fs->flags & EXT2_FLAG_MASTER_SB_ONLY) &&i && super_blk) {
|
||||
retval = write_backup_super(fs, i, super_blk,
|
||||
super_shadow);
|
||||
if (retval)
|
||||
goto errout;
|
||||
}
|
||||
if (fs->flags & EXT2_FLAG_SUPER_ONLY)
|
||||
continue;
|
||||
if ((old_desc_blk) &&
|
||||
(!(fs->flags & EXT2_FLAG_MASTER_SB_ONLY) || (i == 0))) {
|
||||
retval = io_channel_write_blk(fs->io,
|
||||
old_desc_blk, old_desc_blocks, group_ptr);
|
||||
if (retval)
|
||||
goto errout;
|
||||
}
|
||||
if (new_desc_blk) {
|
||||
retval = io_channel_write_blk(fs->io, new_desc_blk,
|
||||
1, group_ptr + (meta_bg*fs->blocksize));
|
||||
if (retval)
|
||||
goto errout;
|
||||
}
|
||||
}
|
||||
fs->super->s_block_group_nr = 0;
|
||||
fs->super->s_state = fs_state;
|
||||
#if BB_BIG_ENDIAN
|
||||
if (fs->flags & EXT2_FLAG_SWAP_BYTES) {
|
||||
*super_shadow = *fs->super;
|
||||
ext2fs_swap_super(super_shadow);
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* If the write_bitmaps() function is present, call it to
|
||||
* flush the bitmaps. This is done this way so that a simple
|
||||
* program that doesn't mess with the bitmaps doesn't need to
|
||||
* drag in the bitmaps.c code.
|
||||
*/
|
||||
if (fs->write_bitmaps) {
|
||||
retval = fs->write_bitmaps(fs);
|
||||
if (retval)
|
||||
goto errout;
|
||||
}
|
||||
|
||||
write_primary_superblock_only:
|
||||
/*
|
||||
* Write out master superblock. This has to be done
|
||||
* separately, since it is located at a fixed location
|
||||
* (SUPERBLOCK_OFFSET). We flush all other pending changes
|
||||
* out to disk first, just to avoid a race condition with an
|
||||
* insy-tinsy window....
|
||||
*/
|
||||
retval = io_channel_flush(fs->io);
|
||||
retval = write_primary_superblock(fs, super_shadow);
|
||||
if (retval)
|
||||
goto errout;
|
||||
|
||||
fs->flags &= ~EXT2_FLAG_DIRTY;
|
||||
|
||||
retval = io_channel_flush(fs->io);
|
||||
errout:
|
||||
fs->super->s_state = fs_state;
|
||||
if (fs->flags & EXT2_FLAG_SWAP_BYTES) {
|
||||
if (super_shadow)
|
||||
ext2fs_free_mem(&super_shadow);
|
||||
if (group_shadow)
|
||||
ext2fs_free_mem(&group_shadow);
|
||||
}
|
||||
return retval;
|
||||
}
|
||||
|
||||
errcode_t ext2fs_close(ext2_filsys fs)
|
||||
{
|
||||
errcode_t retval;
|
||||
|
||||
EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS);
|
||||
|
||||
if (fs->flags & EXT2_FLAG_DIRTY) {
|
||||
retval = ext2fs_flush(fs);
|
||||
if (retval)
|
||||
return retval;
|
||||
}
|
||||
if (fs->write_bitmaps) {
|
||||
retval = fs->write_bitmaps(fs);
|
||||
if (retval)
|
||||
return retval;
|
||||
}
|
||||
ext2fs_free(fs);
|
||||
return 0;
|
||||
}
|
||||
|
73
e2fsprogs/old_e2fsprogs/ext2fs/cmp_bitmaps.c
Normal file
73
e2fsprogs/old_e2fsprogs/ext2fs/cmp_bitmaps.c
Normal file
@ -0,0 +1,73 @@
|
||||
/* vi: set sw=4 ts=4: */
|
||||
/*
|
||||
* cmp_bitmaps.c --- routines to compare inode and block bitmaps.
|
||||
*
|
||||
* Copyright (C) 1995 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>
|
||||
#if HAVE_UNISTD_H
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
#include <fcntl.h>
|
||||
#include <time.h>
|
||||
#if HAVE_SYS_STAT_H
|
||||
#include <sys/stat.h>
|
||||
#endif
|
||||
#if HAVE_SYS_TYPES_H
|
||||
#include <sys/types.h>
|
||||
#endif
|
||||
|
||||
#include "ext2_fs.h"
|
||||
#include "ext2fs.h"
|
||||
|
||||
errcode_t ext2fs_compare_block_bitmap(ext2fs_block_bitmap bm1,
|
||||
ext2fs_block_bitmap bm2)
|
||||
{
|
||||
blk_t i;
|
||||
|
||||
EXT2_CHECK_MAGIC(bm1, EXT2_ET_MAGIC_BLOCK_BITMAP);
|
||||
EXT2_CHECK_MAGIC(bm2, EXT2_ET_MAGIC_BLOCK_BITMAP);
|
||||
|
||||
if ((bm1->start != bm2->start) ||
|
||||
(bm1->end != bm2->end) ||
|
||||
(memcmp(bm1->bitmap, bm2->bitmap,
|
||||
(size_t) (bm1->end - bm1->start)/8)))
|
||||
return EXT2_ET_NEQ_BLOCK_BITMAP;
|
||||
|
||||
for (i = bm1->end - ((bm1->end - bm1->start) % 8); i <= bm1->end; i++)
|
||||
if (ext2fs_fast_test_block_bitmap(bm1, i) !=
|
||||
ext2fs_fast_test_block_bitmap(bm2, i))
|
||||
return EXT2_ET_NEQ_BLOCK_BITMAP;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
errcode_t ext2fs_compare_inode_bitmap(ext2fs_inode_bitmap bm1,
|
||||
ext2fs_inode_bitmap bm2)
|
||||
{
|
||||
ext2_ino_t i;
|
||||
|
||||
EXT2_CHECK_MAGIC(bm1, EXT2_ET_MAGIC_INODE_BITMAP);
|
||||
EXT2_CHECK_MAGIC(bm2, EXT2_ET_MAGIC_INODE_BITMAP);
|
||||
|
||||
if ((bm1->start != bm2->start) ||
|
||||
(bm1->end != bm2->end) ||
|
||||
(memcmp(bm1->bitmap, bm2->bitmap,
|
||||
(size_t) (bm1->end - bm1->start)/8)))
|
||||
return EXT2_ET_NEQ_INODE_BITMAP;
|
||||
|
||||
for (i = bm1->end - ((bm1->end - bm1->start) % 8); i <= bm1->end; i++)
|
||||
if (ext2fs_fast_test_inode_bitmap(bm1, i) !=
|
||||
ext2fs_fast_test_inode_bitmap(bm2, i))
|
||||
return EXT2_ET_NEQ_INODE_BITMAP;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
260
e2fsprogs/old_e2fsprogs/ext2fs/dblist.c
Normal file
260
e2fsprogs/old_e2fsprogs/ext2fs/dblist.c
Normal file
@ -0,0 +1,260 @@
|
||||
/* vi: set sw=4 ts=4: */
|
||||
/*
|
||||
* 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>
|
||||
#if HAVE_UNISTD_H
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
#include <string.h>
|
||||
#include <time.h>
|
||||
|
||||
#include "ext2_fs.h"
|
||||
#include "ext2fsP.h"
|
||||
|
||||
static int 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, ext2_ino_t *ret_num_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++) {
|
||||
if (fs->group_desc[i].bg_used_dirs_count > max_dirs)
|
||||
num_dirs += max_dirs / 8;
|
||||
else
|
||||
num_dirs += fs->group_desc[i].bg_used_dirs_count;
|
||||
}
|
||||
if (num_dirs > fs->super->s_inodes_count)
|
||||
num_dirs = fs->super->s_inodes_count;
|
||||
|
||||
*ret_num_dirs = num_dirs;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* helper function for making a new directory block list (for
|
||||
* initialize and copy).
|
||||
*/
|
||||
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)
|
||||
{
|
||||
ext2_dblist dblist;
|
||||
errcode_t retval;
|
||||
size_t len;
|
||||
|
||||
EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS);
|
||||
|
||||
if ((ret_dblist == 0) && fs->dblist &&
|
||||
(fs->dblist->magic == EXT2_ET_MAGIC_DBLIST))
|
||||
return 0;
|
||||
|
||||
retval = ext2fs_get_mem(sizeof(struct ext2_struct_dblist), &dblist);
|
||||
if (retval)
|
||||
return retval;
|
||||
memset(dblist, 0, sizeof(struct ext2_struct_dblist));
|
||||
|
||||
dblist->magic = EXT2_ET_MAGIC_DBLIST;
|
||||
dblist->fs = fs;
|
||||
if (size)
|
||||
dblist->size = size;
|
||||
else {
|
||||
retval = ext2fs_get_num_dirs(fs, &dblist->size);
|
||||
if (retval)
|
||||
goto cleanup;
|
||||
dblist->size = (dblist->size * 2) + 12;
|
||||
}
|
||||
len = (size_t) sizeof(struct ext2_db_entry) * dblist->size;
|
||||
dblist->count = count;
|
||||
retval = ext2fs_get_mem(len, &dblist->list);
|
||||
if (retval)
|
||||
goto cleanup;
|
||||
|
||||
if (list)
|
||||
memcpy(dblist->list, list, len);
|
||||
else
|
||||
memset(dblist->list, 0, len);
|
||||
if (ret_dblist)
|
||||
*ret_dblist = dblist;
|
||||
else
|
||||
fs->dblist = dblist;
|
||||
return 0;
|
||||
cleanup:
|
||||
ext2fs_free_mem(&dblist);
|
||||
return retval;
|
||||
}
|
||||
|
||||
/*
|
||||
* Initialize a directory block list
|
||||
*/
|
||||
errcode_t ext2fs_init_dblist(ext2_filsys fs, ext2_dblist *ret_dblist)
|
||||
{
|
||||
ext2_dblist dblist;
|
||||
errcode_t retval;
|
||||
|
||||
retval = make_dblist(fs, 0, 0, 0, &dblist);
|
||||
if (retval)
|
||||
return retval;
|
||||
|
||||
dblist->sorted = 1;
|
||||
if (ret_dblist)
|
||||
*ret_dblist = dblist;
|
||||
else
|
||||
fs->dblist = dblist;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Copy a directory block list
|
||||
*/
|
||||
errcode_t ext2fs_copy_dblist(ext2_dblist src, ext2_dblist *dest)
|
||||
{
|
||||
ext2_dblist dblist;
|
||||
errcode_t retval;
|
||||
|
||||
retval = make_dblist(src->fs, src->size, src->count, src->list,
|
||||
&dblist);
|
||||
if (retval)
|
||||
return retval;
|
||||
dblist->sorted = src->sorted;
|
||||
*dest = dblist;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Close a directory block list
|
||||
*
|
||||
* (moved to closefs.c)
|
||||
*/
|
||||
|
||||
|
||||
/*
|
||||
* Add a directory block to the directory block list
|
||||
*/
|
||||
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) {
|
||||
old_size = dblist->size * sizeof(struct ext2_db_entry);
|
||||
dblist->size += 100;
|
||||
retval = ext2fs_resize_mem(old_size, (size_t) dblist->size *
|
||||
sizeof(struct ext2_db_entry),
|
||||
&dblist->list);
|
||||
if (retval) {
|
||||
dblist->size -= 100;
|
||||
return retval;
|
||||
}
|
||||
}
|
||||
new_entry = dblist->list + ( (int) dblist->count++);
|
||||
new_entry->blk = blk;
|
||||
new_entry->ino = ino;
|
||||
new_entry->blockcnt = blockcnt;
|
||||
|
||||
dblist->sorted = 0;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Change the directory block to the directory block list
|
||||
*/
|
||||
errcode_t ext2fs_set_dir_block(ext2_dblist dblist, ext2_ino_t ino, blk_t blk,
|
||||
int blockcnt)
|
||||
{
|
||||
dgrp_t i;
|
||||
|
||||
EXT2_CHECK_MAGIC(dblist, EXT2_ET_MAGIC_DBLIST);
|
||||
|
||||
for (i=0; i < dblist->count; i++) {
|
||||
if ((dblist->list[i].ino != ino) ||
|
||||
(dblist->list[i].blockcnt != blockcnt))
|
||||
continue;
|
||||
dblist->list[i].blk = blk;
|
||||
dblist->sorted = 0;
|
||||
return 0;
|
||||
}
|
||||
return EXT2_ET_DB_NOT_FOUND;
|
||||
}
|
||||
|
||||
void ext2fs_dblist_sort(ext2_dblist dblist,
|
||||
int (*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
|
||||
*/
|
||||
errcode_t ext2fs_dblist_iterate(ext2_dblist dblist,
|
||||
int (*func)(ext2_filsys fs,
|
||||
struct ext2_db_entry *db_info,
|
||||
void *priv_data),
|
||||
void *priv_data)
|
||||
{
|
||||
ext2_ino_t i;
|
||||
int ret;
|
||||
|
||||
EXT2_CHECK_MAGIC(dblist, EXT2_ET_MAGIC_DBLIST);
|
||||
|
||||
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;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int dir_block_cmp(const void *a, const void *b)
|
||||
{
|
||||
const struct ext2_db_entry *db_a =
|
||||
(const struct ext2_db_entry *) a;
|
||||
const struct ext2_db_entry *db_b =
|
||||
(const struct ext2_db_entry *) b;
|
||||
|
||||
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) (db_a->blockcnt - db_b->blockcnt);
|
||||
}
|
||||
|
||||
int ext2fs_dblist_count(ext2_dblist dblist)
|
||||
{
|
||||
return (int) dblist->count;
|
||||
}
|
76
e2fsprogs/old_e2fsprogs/ext2fs/dblist_dir.c
Normal file
76
e2fsprogs/old_e2fsprogs/ext2fs/dblist_dir.c
Normal file
@ -0,0 +1,76 @@
|
||||
/* vi: set sw=4 ts=4: */
|
||||
/*
|
||||
* dblist_dir.c --- iterate by directory entry
|
||||
*
|
||||
* 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>
|
||||
#if HAVE_UNISTD_H
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
#include <string.h>
|
||||
#include <time.h>
|
||||
|
||||
#include "ext2_fs.h"
|
||||
#include "ext2fsP.h"
|
||||
|
||||
static int db_dir_proc(ext2_filsys fs, struct ext2_db_entry *db_info,
|
||||
void *priv_data);
|
||||
|
||||
errcode_t ext2fs_dblist_dir_iterate(ext2_dblist dblist,
|
||||
int flags,
|
||||
char *block_buf,
|
||||
int (*func)(ext2_ino_t dir,
|
||||
int entry,
|
||||
struct ext2_dir_entry *dirent,
|
||||
int offset,
|
||||
int blocksize,
|
||||
char *buf,
|
||||
void *priv_data),
|
||||
void *priv_data)
|
||||
{
|
||||
errcode_t retval;
|
||||
struct dir_context ctx;
|
||||
|
||||
EXT2_CHECK_MAGIC(dblist, EXT2_ET_MAGIC_DBLIST);
|
||||
|
||||
ctx.dir = 0;
|
||||
ctx.flags = flags;
|
||||
if (block_buf)
|
||||
ctx.buf = block_buf;
|
||||
else {
|
||||
retval = ext2fs_get_mem(dblist->fs->blocksize, &ctx.buf);
|
||||
if (retval)
|
||||
return retval;
|
||||
}
|
||||
ctx.func = func;
|
||||
ctx.priv_data = priv_data;
|
||||
ctx.errcode = 0;
|
||||
|
||||
retval = ext2fs_dblist_iterate(dblist, db_dir_proc, &ctx);
|
||||
|
||||
if (!block_buf)
|
||||
ext2fs_free_mem(&ctx.buf);
|
||||
if (retval)
|
||||
return retval;
|
||||
return ctx.errcode;
|
||||
}
|
||||
|
||||
static int db_dir_proc(ext2_filsys fs, struct ext2_db_entry *db_info,
|
||||
void *priv_data)
|
||||
{
|
||||
struct dir_context *ctx;
|
||||
|
||||
ctx = (struct dir_context *) priv_data;
|
||||
ctx->dir = db_info->ino;
|
||||
|
||||
return ext2fs_process_dir_block(fs, &db_info->blk,
|
||||
db_info->blockcnt, 0, 0, priv_data);
|
||||
}
|
220
e2fsprogs/old_e2fsprogs/ext2fs/dir_iterate.c
Normal file
220
e2fsprogs/old_e2fsprogs/ext2fs/dir_iterate.c
Normal file
@ -0,0 +1,220 @@
|
||||
/* vi: set sw=4 ts=4: */
|
||||
/*
|
||||
* dir_iterate.c --- ext2fs directory iteration operations
|
||||
*
|
||||
* Copyright (C) 1993, 1994, 1994, 1995, 1996, 1997 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>
|
||||
#if HAVE_UNISTD_H
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
#if HAVE_ERRNO_H
|
||||
#include <errno.h>
|
||||
#endif
|
||||
|
||||
#include "ext2_fs.h"
|
||||
#include "ext2fsP.h"
|
||||
|
||||
/*
|
||||
* This function checks to see whether or not a potential deleted
|
||||
* directory entry looks valid. What we do is check the deleted entry
|
||||
* and each successive entry to make sure that they all look valid and
|
||||
* that the last deleted entry ends at the beginning of the next
|
||||
* undeleted entry. Returns 1 if the deleted entry looks valid, zero
|
||||
* if not valid.
|
||||
*/
|
||||
static int ext2fs_validate_entry(char *buf, int offset, int final_offset)
|
||||
{
|
||||
struct ext2_dir_entry *dirent;
|
||||
|
||||
while (offset < final_offset) {
|
||||
dirent = (struct ext2_dir_entry *)(buf + offset);
|
||||
offset += dirent->rec_len;
|
||||
if ((dirent->rec_len < 8) ||
|
||||
((dirent->rec_len % 4) != 0) ||
|
||||
(((dirent->name_len & 0xFF)+8) > dirent->rec_len))
|
||||
return 0;
|
||||
}
|
||||
return (offset == final_offset);
|
||||
}
|
||||
|
||||
errcode_t ext2fs_dir_iterate2(ext2_filsys fs,
|
||||
ext2_ino_t dir,
|
||||
int flags,
|
||||
char *block_buf,
|
||||
int (*func)(ext2_ino_t dir,
|
||||
int entry,
|
||||
struct ext2_dir_entry *dirent,
|
||||
int offset,
|
||||
int blocksize,
|
||||
char *buf,
|
||||
void *priv_data),
|
||||
void *priv_data)
|
||||
{
|
||||
struct dir_context ctx;
|
||||
errcode_t retval;
|
||||
|
||||
EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS);
|
||||
|
||||
retval = ext2fs_check_directory(fs, dir);
|
||||
if (retval)
|
||||
return retval;
|
||||
|
||||
ctx.dir = dir;
|
||||
ctx.flags = flags;
|
||||
if (block_buf)
|
||||
ctx.buf = block_buf;
|
||||
else {
|
||||
retval = ext2fs_get_mem(fs->blocksize, &ctx.buf);
|
||||
if (retval)
|
||||
return retval;
|
||||
}
|
||||
ctx.func = func;
|
||||
ctx.priv_data = priv_data;
|
||||
ctx.errcode = 0;
|
||||
retval = ext2fs_block_iterate2(fs, dir, 0, 0,
|
||||
ext2fs_process_dir_block, &ctx);
|
||||
if (!block_buf)
|
||||
ext2fs_free_mem(&ctx.buf);
|
||||
if (retval)
|
||||
return retval;
|
||||
return ctx.errcode;
|
||||
}
|
||||
|
||||
struct xlate {
|
||||
int (*func)(struct ext2_dir_entry *dirent,
|
||||
int offset,
|
||||
int blocksize,
|
||||
char *buf,
|
||||
void *priv_data);
|
||||
void *real_private;
|
||||
};
|
||||
|
||||
static int xlate_func(ext2_ino_t dir EXT2FS_ATTR((unused)),
|
||||
int entry EXT2FS_ATTR((unused)),
|
||||
struct ext2_dir_entry *dirent, int offset,
|
||||
int blocksize, char *buf, void *priv_data)
|
||||
{
|
||||
struct xlate *xl = (struct xlate *) priv_data;
|
||||
|
||||
return (*xl->func)(dirent, offset, blocksize, buf, xl->real_private);
|
||||
}
|
||||
|
||||
extern errcode_t ext2fs_dir_iterate(ext2_filsys fs,
|
||||
ext2_ino_t dir,
|
||||
int flags,
|
||||
char *block_buf,
|
||||
int (*func)(struct ext2_dir_entry *dirent,
|
||||
int offset,
|
||||
int blocksize,
|
||||
char *buf,
|
||||
void *priv_data),
|
||||
void *priv_data)
|
||||
{
|
||||
struct xlate xl;
|
||||
|
||||
xl.real_private = priv_data;
|
||||
xl.func = func;
|
||||
|
||||
return ext2fs_dir_iterate2(fs, dir, flags, block_buf,
|
||||
xlate_func, &xl);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Helper function which is private to this module. Used by
|
||||
* ext2fs_dir_iterate() and ext2fs_dblist_dir_iterate()
|
||||
*/
|
||||
int ext2fs_process_dir_block(ext2_filsys fs,
|
||||
blk_t *blocknr,
|
||||
e2_blkcnt_t blockcnt,
|
||||
blk_t ref_block EXT2FS_ATTR((unused)),
|
||||
int ref_offset EXT2FS_ATTR((unused)),
|
||||
void *priv_data)
|
||||
{
|
||||
struct dir_context *ctx = (struct dir_context *) priv_data;
|
||||
unsigned int offset = 0;
|
||||
unsigned int next_real_entry = 0;
|
||||
int ret = 0;
|
||||
int changed = 0;
|
||||
int do_abort = 0;
|
||||
int entry, size;
|
||||
struct ext2_dir_entry *dirent;
|
||||
|
||||
if (blockcnt < 0)
|
||||
return 0;
|
||||
|
||||
entry = blockcnt ? DIRENT_OTHER_FILE : DIRENT_DOT_FILE;
|
||||
|
||||
ctx->errcode = ext2fs_read_dir_block(fs, *blocknr, ctx->buf);
|
||||
if (ctx->errcode)
|
||||
return BLOCK_ABORT;
|
||||
|
||||
while (offset < fs->blocksize) {
|
||||
dirent = (struct ext2_dir_entry *) (ctx->buf + offset);
|
||||
if (((offset + dirent->rec_len) > fs->blocksize) ||
|
||||
(dirent->rec_len < 8) ||
|
||||
((dirent->rec_len % 4) != 0) ||
|
||||
(((dirent->name_len & 0xFF)+8) > dirent->rec_len)) {
|
||||
ctx->errcode = EXT2_ET_DIR_CORRUPTED;
|
||||
return BLOCK_ABORT;
|
||||
}
|
||||
if (!dirent->inode &&
|
||||
!(ctx->flags & DIRENT_FLAG_INCLUDE_EMPTY))
|
||||
goto next;
|
||||
|
||||
ret = (ctx->func)(ctx->dir,
|
||||
(next_real_entry > offset) ?
|
||||
DIRENT_DELETED_FILE : entry,
|
||||
dirent, offset,
|
||||
fs->blocksize, ctx->buf,
|
||||
ctx->priv_data);
|
||||
if (entry < DIRENT_OTHER_FILE)
|
||||
entry++;
|
||||
|
||||
if (ret & DIRENT_CHANGED)
|
||||
changed++;
|
||||
if (ret & DIRENT_ABORT) {
|
||||
do_abort++;
|
||||
break;
|
||||
}
|
||||
next:
|
||||
if (next_real_entry == offset)
|
||||
next_real_entry += dirent->rec_len;
|
||||
|
||||
if (ctx->flags & DIRENT_FLAG_INCLUDE_REMOVED) {
|
||||
size = ((dirent->name_len & 0xFF) + 11) & ~3;
|
||||
|
||||
if (dirent->rec_len != size) {
|
||||
unsigned int final_offset;
|
||||
|
||||
final_offset = offset + dirent->rec_len;
|
||||
offset += size;
|
||||
while (offset < final_offset &&
|
||||
!ext2fs_validate_entry(ctx->buf,
|
||||
offset,
|
||||
final_offset))
|
||||
offset += 4;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
offset += dirent->rec_len;
|
||||
}
|
||||
|
||||
if (changed) {
|
||||
ctx->errcode = ext2fs_write_dir_block(fs, *blocknr, ctx->buf);
|
||||
if (ctx->errcode)
|
||||
return BLOCK_ABORT;
|
||||
}
|
||||
if (do_abort)
|
||||
return BLOCK_ABORT;
|
||||
return 0;
|
||||
}
|
||||
|
133
e2fsprogs/old_e2fsprogs/ext2fs/dirblock.c
Normal file
133
e2fsprogs/old_e2fsprogs/ext2fs/dirblock.c
Normal file
@ -0,0 +1,133 @@
|
||||
/* vi: set sw=4 ts=4: */
|
||||
/*
|
||||
* dirblock.c --- directory block routines.
|
||||
*
|
||||
* Copyright (C) 1995, 1996 Theodore Ts'o.
|
||||
*
|
||||
* %Begin-Header%
|
||||
* This file may be redistributed under the terms of the GNU Public
|
||||
* License.
|
||||
* %End-Header%
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#if HAVE_UNISTD_H
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
#include <string.h>
|
||||
#include <time.h>
|
||||
|
||||
#include "ext2_fs.h"
|
||||
#include "ext2fs.h"
|
||||
|
||||
errcode_t ext2fs_read_dir_block2(ext2_filsys fs, blk_t block,
|
||||
void *buf, int flags EXT2FS_ATTR((unused)))
|
||||
{
|
||||
errcode_t retval;
|
||||
char *p, *end;
|
||||
struct ext2_dir_entry *dirent;
|
||||
unsigned int name_len, rec_len;
|
||||
#if BB_BIG_ENDIAN
|
||||
unsigned int do_swap;
|
||||
#endif
|
||||
|
||||
retval = io_channel_read_blk(fs->io, block, 1, buf);
|
||||
if (retval)
|
||||
return retval;
|
||||
#if BB_BIG_ENDIAN
|
||||
do_swap = (fs->flags & (EXT2_FLAG_SWAP_BYTES|
|
||||
EXT2_FLAG_SWAP_BYTES_READ)) != 0;
|
||||
#endif
|
||||
p = (char *) buf;
|
||||
end = (char *) buf + fs->blocksize;
|
||||
while (p < end-8) {
|
||||
dirent = (struct ext2_dir_entry *) p;
|
||||
#if BB_BIG_ENDIAN
|
||||
if (do_swap) {
|
||||
dirent->inode = ext2fs_swab32(dirent->inode);
|
||||
dirent->rec_len = ext2fs_swab16(dirent->rec_len);
|
||||
dirent->name_len = ext2fs_swab16(dirent->name_len);
|
||||
}
|
||||
#endif
|
||||
name_len = dirent->name_len;
|
||||
#ifdef WORDS_BIGENDIAN
|
||||
if (flags & EXT2_DIRBLOCK_V2_STRUCT)
|
||||
dirent->name_len = ext2fs_swab16(dirent->name_len);
|
||||
#endif
|
||||
rec_len = dirent->rec_len;
|
||||
if ((rec_len < 8) || (rec_len % 4)) {
|
||||
rec_len = 8;
|
||||
retval = EXT2_ET_DIR_CORRUPTED;
|
||||
}
|
||||
if (((name_len & 0xFF) + 8) > dirent->rec_len)
|
||||
retval = EXT2_ET_DIR_CORRUPTED;
|
||||
p += rec_len;
|
||||
}
|
||||
return retval;
|
||||
}
|
||||
|
||||
errcode_t ext2fs_read_dir_block(ext2_filsys fs, blk_t block,
|
||||
void *buf)
|
||||
{
|
||||
return ext2fs_read_dir_block2(fs, block, buf, 0);
|
||||
}
|
||||
|
||||
|
||||
errcode_t ext2fs_write_dir_block2(ext2_filsys fs, blk_t block,
|
||||
void *inbuf, int flags EXT2FS_ATTR((unused)))
|
||||
{
|
||||
#if BB_BIG_ENDIAN
|
||||
int do_swap = 0;
|
||||
errcode_t retval;
|
||||
char *p, *end;
|
||||
char *buf = 0;
|
||||
struct ext2_dir_entry *dirent;
|
||||
|
||||
if ((fs->flags & EXT2_FLAG_SWAP_BYTES) ||
|
||||
(fs->flags & EXT2_FLAG_SWAP_BYTES_WRITE))
|
||||
do_swap = 1;
|
||||
|
||||
#ifndef WORDS_BIGENDIAN
|
||||
if (!do_swap)
|
||||
return io_channel_write_blk(fs->io, block, 1, (char *) inbuf);
|
||||
#endif
|
||||
|
||||
retval = ext2fs_get_mem(fs->blocksize, &buf);
|
||||
if (retval)
|
||||
return retval;
|
||||
memcpy(buf, inbuf, fs->blocksize);
|
||||
p = buf;
|
||||
end = buf + fs->blocksize;
|
||||
while (p < end) {
|
||||
dirent = (struct ext2_dir_entry *) p;
|
||||
if ((dirent->rec_len < 8) ||
|
||||
(dirent->rec_len % 4)) {
|
||||
ext2fs_free_mem(&buf);
|
||||
return EXT2_ET_DIR_CORRUPTED;
|
||||
}
|
||||
p += dirent->rec_len;
|
||||
if (do_swap) {
|
||||
dirent->inode = ext2fs_swab32(dirent->inode);
|
||||
dirent->rec_len = ext2fs_swab16(dirent->rec_len);
|
||||
dirent->name_len = ext2fs_swab16(dirent->name_len);
|
||||
}
|
||||
#ifdef WORDS_BIGENDIAN
|
||||
if (flags & EXT2_DIRBLOCK_V2_STRUCT)
|
||||
dirent->name_len = ext2fs_swab16(dirent->name_len);
|
||||
#endif
|
||||
}
|
||||
retval = io_channel_write_blk(fs->io, block, 1, buf);
|
||||
ext2fs_free_mem(&buf);
|
||||
return retval;
|
||||
#else
|
||||
return io_channel_write_blk(fs->io, block, 1, (char *) inbuf);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
errcode_t ext2fs_write_dir_block(ext2_filsys fs, blk_t block,
|
||||
void *inbuf)
|
||||
{
|
||||
return ext2fs_write_dir_block2(fs, block, inbuf, 0);
|
||||
}
|
||||
|
234
e2fsprogs/old_e2fsprogs/ext2fs/dirhash.c
Normal file
234
e2fsprogs/old_e2fsprogs/ext2fs/dirhash.c
Normal file
@ -0,0 +1,234 @@
|
||||
/* vi: set sw=4 ts=4: */
|
||||
/*
|
||||
* dirhash.c -- Calculate the hash of a directory entry
|
||||
*
|
||||
* Copyright (c) 2001 Daniel Phillips
|
||||
*
|
||||
* Copyright (c) 2002 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 "ext2_fs.h"
|
||||
#include "ext2fs.h"
|
||||
|
||||
/*
|
||||
* Keyed 32-bit hash function using TEA in a Davis-Meyer function
|
||||
* H0 = Key
|
||||
* Hi = E Mi(Hi-1) + Hi-1
|
||||
*
|
||||
* (see Applied Cryptography, 2nd edition, p448).
|
||||
*
|
||||
* Jeremy Fitzhardinge <jeremy@zip.com.au> 1998
|
||||
*
|
||||
* This code is made available under the terms of the GPL
|
||||
*/
|
||||
#define DELTA 0x9E3779B9
|
||||
|
||||
static void TEA_transform(__u32 buf[4], __u32 const in[])
|
||||
{
|
||||
__u32 sum = 0;
|
||||
__u32 b0 = buf[0], b1 = buf[1];
|
||||
__u32 a = in[0], b = in[1], c = in[2], d = in[3];
|
||||
int n = 16;
|
||||
|
||||
do {
|
||||
sum += DELTA;
|
||||
b0 += ((b1 << 4)+a) ^ (b1+sum) ^ ((b1 >> 5)+b);
|
||||
b1 += ((b0 << 4)+c) ^ (b0+sum) ^ ((b0 >> 5)+d);
|
||||
} while(--n);
|
||||
|
||||
buf[0] += b0;
|
||||
buf[1] += b1;
|
||||
}
|
||||
|
||||
/* F, G and H are basic MD4 functions: selection, majority, parity */
|
||||
#define F(x, y, z) ((z) ^ ((x) & ((y) ^ (z))))
|
||||
#define G(x, y, z) (((x) & (y)) + (((x) ^ (y)) & (z)))
|
||||
#define H(x, y, z) ((x) ^ (y) ^ (z))
|
||||
|
||||
/*
|
||||
* The generic round function. The application is so specific that
|
||||
* we don't bother protecting all the arguments with parens, as is generally
|
||||
* good macro practice, in favor of extra legibility.
|
||||
* Rotation is separate from addition to prevent recomputation
|
||||
*/
|
||||
#define ROUND(f, a, b, c, d, x, s) \
|
||||
(a += f(b, c, d) + x, a = (a << s) | (a >> (32-s)))
|
||||
#define K1 0
|
||||
#define K2 013240474631UL
|
||||
#define K3 015666365641UL
|
||||
|
||||
/*
|
||||
* Basic cut-down MD4 transform. Returns only 32 bits of result.
|
||||
*/
|
||||
static void halfMD4Transform (__u32 buf[4], __u32 const in[])
|
||||
{
|
||||
__u32 a = buf[0], b = buf[1], c = buf[2], d = buf[3];
|
||||
|
||||
/* Round 1 */
|
||||
ROUND(F, a, b, c, d, in[0] + K1, 3);
|
||||
ROUND(F, d, a, b, c, in[1] + K1, 7);
|
||||
ROUND(F, c, d, a, b, in[2] + K1, 11);
|
||||
ROUND(F, b, c, d, a, in[3] + K1, 19);
|
||||
ROUND(F, a, b, c, d, in[4] + K1, 3);
|
||||
ROUND(F, d, a, b, c, in[5] + K1, 7);
|
||||
ROUND(F, c, d, a, b, in[6] + K1, 11);
|
||||
ROUND(F, b, c, d, a, in[7] + K1, 19);
|
||||
|
||||
/* Round 2 */
|
||||
ROUND(G, a, b, c, d, in[1] + K2, 3);
|
||||
ROUND(G, d, a, b, c, in[3] + K2, 5);
|
||||
ROUND(G, c, d, a, b, in[5] + K2, 9);
|
||||
ROUND(G, b, c, d, a, in[7] + K2, 13);
|
||||
ROUND(G, a, b, c, d, in[0] + K2, 3);
|
||||
ROUND(G, d, a, b, c, in[2] + K2, 5);
|
||||
ROUND(G, c, d, a, b, in[4] + K2, 9);
|
||||
ROUND(G, b, c, d, a, in[6] + K2, 13);
|
||||
|
||||
/* Round 3 */
|
||||
ROUND(H, a, b, c, d, in[3] + K3, 3);
|
||||
ROUND(H, d, a, b, c, in[7] + K3, 9);
|
||||
ROUND(H, c, d, a, b, in[2] + K3, 11);
|
||||
ROUND(H, b, c, d, a, in[6] + K3, 15);
|
||||
ROUND(H, a, b, c, d, in[1] + K3, 3);
|
||||
ROUND(H, d, a, b, c, in[5] + K3, 9);
|
||||
ROUND(H, c, d, a, b, in[0] + K3, 11);
|
||||
ROUND(H, b, c, d, a, in[4] + K3, 15);
|
||||
|
||||
buf[0] += a;
|
||||
buf[1] += b;
|
||||
buf[2] += c;
|
||||
buf[3] += d;
|
||||
}
|
||||
|
||||
#undef ROUND
|
||||
#undef F
|
||||
#undef G
|
||||
#undef H
|
||||
#undef K1
|
||||
#undef K2
|
||||
#undef K3
|
||||
|
||||
/* The old legacy hash */
|
||||
static ext2_dirhash_t dx_hack_hash (const char *name, int len)
|
||||
{
|
||||
__u32 hash0 = 0x12a3fe2d, hash1 = 0x37abe8f9;
|
||||
while (len--) {
|
||||
__u32 hash = hash1 + (hash0 ^ (*name++ * 7152373));
|
||||
|
||||
if (hash & 0x80000000) hash -= 0x7fffffff;
|
||||
hash1 = hash0;
|
||||
hash0 = hash;
|
||||
}
|
||||
return (hash0 << 1);
|
||||
}
|
||||
|
||||
static void str2hashbuf(const char *msg, int len, __u32 *buf, int num)
|
||||
{
|
||||
__u32 pad, val;
|
||||
int i;
|
||||
|
||||
pad = (__u32)len | ((__u32)len << 8);
|
||||
pad |= pad << 16;
|
||||
|
||||
val = pad;
|
||||
if (len > num*4)
|
||||
len = num * 4;
|
||||
for (i=0; i < len; i++) {
|
||||
if ((i % 4) == 0)
|
||||
val = pad;
|
||||
val = msg[i] + (val << 8);
|
||||
if ((i % 4) == 3) {
|
||||
*buf++ = val;
|
||||
val = pad;
|
||||
num--;
|
||||
}
|
||||
}
|
||||
if (--num >= 0)
|
||||
*buf++ = val;
|
||||
while (--num >= 0)
|
||||
*buf++ = pad;
|
||||
}
|
||||
|
||||
/*
|
||||
* Returns the hash of a filename. If len is 0 and name is NULL, then
|
||||
* this function can be used to test whether or not a hash version is
|
||||
* supported.
|
||||
*
|
||||
* The seed is an 4 longword (32 bits) "secret" which can be used to
|
||||
* uniquify a hash. If the seed is all zero's, then some default seed
|
||||
* may be used.
|
||||
*
|
||||
* A particular hash version specifies whether or not the seed is
|
||||
* represented, and whether or not the returned hash is 32 bits or 64
|
||||
* bits. 32 bit hashes will return 0 for the minor hash.
|
||||
*/
|
||||
errcode_t ext2fs_dirhash(int version, const char *name, int len,
|
||||
const __u32 *seed,
|
||||
ext2_dirhash_t *ret_hash,
|
||||
ext2_dirhash_t *ret_minor_hash)
|
||||
{
|
||||
__u32 hash;
|
||||
__u32 minor_hash = 0;
|
||||
const char *p;
|
||||
int i;
|
||||
__u32 in[8], buf[4];
|
||||
|
||||
/* Initialize the default seed for the hash checksum functions */
|
||||
buf[0] = 0x67452301;
|
||||
buf[1] = 0xefcdab89;
|
||||
buf[2] = 0x98badcfe;
|
||||
buf[3] = 0x10325476;
|
||||
|
||||
/* Check to see if the seed is all zero's */
|
||||
if (seed) {
|
||||
for (i=0; i < 4; i++) {
|
||||
if (seed[i])
|
||||
break;
|
||||
}
|
||||
if (i < 4)
|
||||
memcpy(buf, seed, sizeof(buf));
|
||||
}
|
||||
|
||||
switch (version) {
|
||||
case EXT2_HASH_LEGACY:
|
||||
hash = dx_hack_hash(name, len);
|
||||
break;
|
||||
case EXT2_HASH_HALF_MD4:
|
||||
p = name;
|
||||
while (len > 0) {
|
||||
str2hashbuf(p, len, in, 8);
|
||||
halfMD4Transform(buf, in);
|
||||
len -= 32;
|
||||
p += 32;
|
||||
}
|
||||
minor_hash = buf[2];
|
||||
hash = buf[1];
|
||||
break;
|
||||
case EXT2_HASH_TEA:
|
||||
p = name;
|
||||
while (len > 0) {
|
||||
str2hashbuf(p, len, in, 4);
|
||||
TEA_transform(buf, in);
|
||||
len -= 16;
|
||||
p += 16;
|
||||
}
|
||||
hash = buf[0];
|
||||
minor_hash = buf[1];
|
||||
break;
|
||||
default:
|
||||
*ret_hash = 0;
|
||||
return EXT2_ET_DIRHASH_UNSUPP;
|
||||
}
|
||||
*ret_hash = hash & ~1;
|
||||
if (ret_minor_hash)
|
||||
*ret_minor_hash = minor_hash;
|
||||
return 0;
|
||||
}
|
97
e2fsprogs/old_e2fsprogs/ext2fs/dupfs.c
Normal file
97
e2fsprogs/old_e2fsprogs/ext2fs/dupfs.c
Normal file
@ -0,0 +1,97 @@
|
||||
/* vi: set sw=4 ts=4: */
|
||||
/*
|
||||
* dupfs.c --- duplicate a ext2 filesystem handle
|
||||
*
|
||||
* Copyright (C) 1997, 1998, 2001, 2003, 2005 by Theodore Ts'o.
|
||||
*
|
||||
* %Begin-Header%
|
||||
* This file may be redistributed under the terms of the GNU Public
|
||||
* License.
|
||||
* %End-Header%
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#if HAVE_UNISTD_H
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
#include <time.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "ext2_fs.h"
|
||||
#include "ext2fsP.h"
|
||||
|
||||
errcode_t ext2fs_dup_handle(ext2_filsys src, ext2_filsys *dest)
|
||||
{
|
||||
ext2_filsys fs;
|
||||
errcode_t retval;
|
||||
|
||||
EXT2_CHECK_MAGIC(src, EXT2_ET_MAGIC_EXT2FS_FILSYS);
|
||||
|
||||
retval = ext2fs_get_mem(sizeof(struct struct_ext2_filsys), &fs);
|
||||
if (retval)
|
||||
return retval;
|
||||
|
||||
*fs = *src;
|
||||
fs->device_name = 0;
|
||||
fs->super = 0;
|
||||
fs->orig_super = 0;
|
||||
fs->group_desc = 0;
|
||||
fs->inode_map = 0;
|
||||
fs->block_map = 0;
|
||||
fs->badblocks = 0;
|
||||
fs->dblist = 0;
|
||||
|
||||
io_channel_bumpcount(fs->io);
|
||||
if (fs->icache)
|
||||
fs->icache->refcount++;
|
||||
|
||||
retval = ext2fs_get_mem(strlen(src->device_name)+1, &fs->device_name);
|
||||
if (retval)
|
||||
goto errout;
|
||||
strcpy(fs->device_name, src->device_name);
|
||||
|
||||
retval = ext2fs_get_mem(SUPERBLOCK_SIZE, &fs->super);
|
||||
if (retval)
|
||||
goto errout;
|
||||
memcpy(fs->super, src->super, SUPERBLOCK_SIZE);
|
||||
|
||||
retval = ext2fs_get_mem(SUPERBLOCK_SIZE, &fs->orig_super);
|
||||
if (retval)
|
||||
goto errout;
|
||||
memcpy(fs->orig_super, src->orig_super, SUPERBLOCK_SIZE);
|
||||
|
||||
retval = ext2fs_get_mem((size_t) fs->desc_blocks * fs->blocksize,
|
||||
&fs->group_desc);
|
||||
if (retval)
|
||||
goto errout;
|
||||
memcpy(fs->group_desc, src->group_desc,
|
||||
(size_t) fs->desc_blocks * fs->blocksize);
|
||||
|
||||
if (src->inode_map) {
|
||||
retval = ext2fs_copy_bitmap(src->inode_map, &fs->inode_map);
|
||||
if (retval)
|
||||
goto errout;
|
||||
}
|
||||
if (src->block_map) {
|
||||
retval = ext2fs_copy_bitmap(src->block_map, &fs->block_map);
|
||||
if (retval)
|
||||
goto errout;
|
||||
}
|
||||
if (src->badblocks) {
|
||||
retval = ext2fs_badblocks_copy(src->badblocks, &fs->badblocks);
|
||||
if (retval)
|
||||
goto errout;
|
||||
}
|
||||
if (src->dblist) {
|
||||
retval = ext2fs_copy_dblist(src->dblist, &fs->dblist);
|
||||
if (retval)
|
||||
goto errout;
|
||||
}
|
||||
*dest = fs;
|
||||
return 0;
|
||||
errout:
|
||||
ext2fs_free(fs);
|
||||
return retval;
|
||||
|
||||
}
|
||||
|
52
e2fsprogs/old_e2fsprogs/ext2fs/e2image.h
Normal file
52
e2fsprogs/old_e2fsprogs/ext2fs/e2image.h
Normal file
@ -0,0 +1,52 @@
|
||||
/* vi: set sw=4 ts=4: */
|
||||
/*
|
||||
* e2image.h --- header file describing the ext2 image format
|
||||
*
|
||||
* Copyright (C) 2000 Theodore Ts'o.
|
||||
*
|
||||
* Note: this uses the POSIX IO interfaces, unlike most of the other
|
||||
* functions in this library. So sue me.
|
||||
*
|
||||
* %Begin-Header%
|
||||
* This file may be redistributed under the terms of the GNU Public
|
||||
* License.
|
||||
* %End-Header%
|
||||
*/
|
||||
|
||||
|
||||
struct ext2_image_hdr {
|
||||
__u32 magic_number; /* This must be EXT2_ET_MAGIC_E2IMAGE */
|
||||
char magic_descriptor[16]; /* "Ext2 Image 1.0", w/ null padding */
|
||||
char fs_hostname[64];/* Hostname of machine of image */
|
||||
char fs_netaddr[32]; /* Network address */
|
||||
__u32 fs_netaddr_type;/* 0 = IPV4, 1 = IPV6, etc. */
|
||||
__u32 fs_device; /* Device number of image */
|
||||
char fs_device_name[64]; /* Device name */
|
||||
char fs_uuid[16]; /* UUID of filesystem */
|
||||
__u32 fs_blocksize; /* Block size of the filesystem */
|
||||
__u32 fs_reserved[8];
|
||||
|
||||
__u32 image_device; /* Device number of image file */
|
||||
__u32 image_inode; /* Inode number of image file */
|
||||
__u32 image_time; /* Time of image creation */
|
||||
__u32 image_reserved[8];
|
||||
|
||||
__u32 offset_super; /* Byte offset of the sb and descriptors */
|
||||
__u32 offset_inode; /* Byte offset of the inode table */
|
||||
__u32 offset_inodemap; /* Byte offset of the inode bitmaps */
|
||||
__u32 offset_blockmap; /* Byte offset of the inode bitmaps */
|
||||
__u32 offset_reserved[8];
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
127
e2fsprogs/old_e2fsprogs/ext2fs/expanddir.c
Normal file
127
e2fsprogs/old_e2fsprogs/ext2fs/expanddir.c
Normal file
@ -0,0 +1,127 @@
|
||||
/* vi: set sw=4 ts=4: */
|
||||
/*
|
||||
* expand.c --- expand an ext2fs directory
|
||||
*
|
||||
* Copyright (C) 1993, 1994, 1995, 1996, 1997, 1998, 1999 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>
|
||||
#if HAVE_UNISTD_H
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
|
||||
#include "ext2_fs.h"
|
||||
#include "ext2fs.h"
|
||||
|
||||
struct expand_dir_struct {
|
||||
int done;
|
||||
int newblocks;
|
||||
errcode_t err;
|
||||
};
|
||||
|
||||
static int expand_dir_proc(ext2_filsys fs,
|
||||
blk_t *blocknr,
|
||||
e2_blkcnt_t blockcnt,
|
||||
blk_t ref_block EXT2FS_ATTR((unused)),
|
||||
int ref_offset EXT2FS_ATTR((unused)),
|
||||
void *priv_data)
|
||||
{
|
||||
struct expand_dir_struct *es = (struct expand_dir_struct *) priv_data;
|
||||
blk_t new_blk;
|
||||
static blk_t last_blk = 0;
|
||||
char *block;
|
||||
errcode_t retval;
|
||||
|
||||
if (*blocknr) {
|
||||
last_blk = *blocknr;
|
||||
return 0;
|
||||
}
|
||||
retval = ext2fs_new_block(fs, last_blk, 0, &new_blk);
|
||||
if (retval) {
|
||||
es->err = retval;
|
||||
return BLOCK_ABORT;
|
||||
}
|
||||
if (blockcnt > 0) {
|
||||
retval = ext2fs_new_dir_block(fs, 0, 0, &block);
|
||||
if (retval) {
|
||||
es->err = retval;
|
||||
return BLOCK_ABORT;
|
||||
}
|
||||
es->done = 1;
|
||||
retval = ext2fs_write_dir_block(fs, new_blk, block);
|
||||
} else {
|
||||
retval = ext2fs_get_mem(fs->blocksize, &block);
|
||||
if (retval) {
|
||||
es->err = retval;
|
||||
return BLOCK_ABORT;
|
||||
}
|
||||
memset(block, 0, fs->blocksize);
|
||||
retval = io_channel_write_blk(fs->io, new_blk, 1, block);
|
||||
}
|
||||
if (retval) {
|
||||
es->err = retval;
|
||||
return BLOCK_ABORT;
|
||||
}
|
||||
ext2fs_free_mem(&block);
|
||||
*blocknr = new_blk;
|
||||
ext2fs_block_alloc_stats(fs, new_blk, +1);
|
||||
es->newblocks++;
|
||||
|
||||
if (es->done)
|
||||
return (BLOCK_CHANGED | BLOCK_ABORT);
|
||||
else
|
||||
return BLOCK_CHANGED;
|
||||
}
|
||||
|
||||
errcode_t ext2fs_expand_dir(ext2_filsys fs, ext2_ino_t dir)
|
||||
{
|
||||
errcode_t retval;
|
||||
struct expand_dir_struct es;
|
||||
struct ext2_inode inode;
|
||||
|
||||
EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS);
|
||||
|
||||
if (!(fs->flags & EXT2_FLAG_RW))
|
||||
return EXT2_ET_RO_FILSYS;
|
||||
|
||||
if (!fs->block_map)
|
||||
return EXT2_ET_NO_BLOCK_BITMAP;
|
||||
|
||||
retval = ext2fs_check_directory(fs, dir);
|
||||
if (retval)
|
||||
return retval;
|
||||
|
||||
es.done = 0;
|
||||
es.err = 0;
|
||||
es.newblocks = 0;
|
||||
|
||||
retval = ext2fs_block_iterate2(fs, dir, BLOCK_FLAG_APPEND,
|
||||
0, expand_dir_proc, &es);
|
||||
|
||||
if (es.err)
|
||||
return es.err;
|
||||
if (!es.done)
|
||||
return EXT2_ET_EXPAND_DIR_ERR;
|
||||
|
||||
/*
|
||||
* Update the size and block count fields in the inode.
|
||||
*/
|
||||
retval = ext2fs_read_inode(fs, dir, &inode);
|
||||
if (retval)
|
||||
return retval;
|
||||
|
||||
inode.i_size += fs->blocksize;
|
||||
inode.i_blocks += (fs->blocksize / 512) * es.newblocks;
|
||||
|
||||
retval = ext2fs_write_inode(fs, dir, &inode);
|
||||
if (retval)
|
||||
return retval;
|
||||
|
||||
return 0;
|
||||
}
|
116
e2fsprogs/old_e2fsprogs/ext2fs/ext2_err.h
Normal file
116
e2fsprogs/old_e2fsprogs/ext2fs/ext2_err.h
Normal file
@ -0,0 +1,116 @@
|
||||
/* vi: set sw=4 ts=4: */
|
||||
/*
|
||||
* ext2_err.h:
|
||||
* This file is automatically generated; please do not edit it.
|
||||
*/
|
||||
|
||||
#define EXT2_ET_BASE (2133571328L)
|
||||
#define EXT2_ET_MAGIC_EXT2FS_FILSYS (2133571329L)
|
||||
#define EXT2_ET_MAGIC_BADBLOCKS_LIST (2133571330L)
|
||||
#define EXT2_ET_MAGIC_BADBLOCKS_ITERATE (2133571331L)
|
||||
#define EXT2_ET_MAGIC_INODE_SCAN (2133571332L)
|
||||
#define EXT2_ET_MAGIC_IO_CHANNEL (2133571333L)
|
||||
#define EXT2_ET_MAGIC_UNIX_IO_CHANNEL (2133571334L)
|
||||
#define EXT2_ET_MAGIC_IO_MANAGER (2133571335L)
|
||||
#define EXT2_ET_MAGIC_BLOCK_BITMAP (2133571336L)
|
||||
#define EXT2_ET_MAGIC_INODE_BITMAP (2133571337L)
|
||||
#define EXT2_ET_MAGIC_GENERIC_BITMAP (2133571338L)
|
||||
#define EXT2_ET_MAGIC_TEST_IO_CHANNEL (2133571339L)
|
||||
#define EXT2_ET_MAGIC_DBLIST (2133571340L)
|
||||
#define EXT2_ET_MAGIC_ICOUNT (2133571341L)
|
||||
#define EXT2_ET_MAGIC_PQ_IO_CHANNEL (2133571342L)
|
||||
#define EXT2_ET_MAGIC_EXT2_FILE (2133571343L)
|
||||
#define EXT2_ET_MAGIC_E2IMAGE (2133571344L)
|
||||
#define EXT2_ET_MAGIC_INODE_IO_CHANNEL (2133571345L)
|
||||
#define EXT2_ET_MAGIC_RESERVED_9 (2133571346L)
|
||||
#define EXT2_ET_BAD_MAGIC (2133571347L)
|
||||
#define EXT2_ET_REV_TOO_HIGH (2133571348L)
|
||||
#define EXT2_ET_RO_FILSYS (2133571349L)
|
||||
#define EXT2_ET_GDESC_READ (2133571350L)
|
||||
#define EXT2_ET_GDESC_WRITE (2133571351L)
|
||||
#define EXT2_ET_GDESC_BAD_BLOCK_MAP (2133571352L)
|
||||
#define EXT2_ET_GDESC_BAD_INODE_MAP (2133571353L)
|
||||
#define EXT2_ET_GDESC_BAD_INODE_TABLE (2133571354L)
|
||||
#define EXT2_ET_INODE_BITMAP_WRITE (2133571355L)
|
||||
#define EXT2_ET_INODE_BITMAP_READ (2133571356L)
|
||||
#define EXT2_ET_BLOCK_BITMAP_WRITE (2133571357L)
|
||||
#define EXT2_ET_BLOCK_BITMAP_READ (2133571358L)
|
||||
#define EXT2_ET_INODE_TABLE_WRITE (2133571359L)
|
||||
#define EXT2_ET_INODE_TABLE_READ (2133571360L)
|
||||
#define EXT2_ET_NEXT_INODE_READ (2133571361L)
|
||||
#define EXT2_ET_UNEXPECTED_BLOCK_SIZE (2133571362L)
|
||||
#define EXT2_ET_DIR_CORRUPTED (2133571363L)
|
||||
#define EXT2_ET_SHORT_READ (2133571364L)
|
||||
#define EXT2_ET_SHORT_WRITE (2133571365L)
|
||||
#define EXT2_ET_DIR_NO_SPACE (2133571366L)
|
||||
#define EXT2_ET_NO_INODE_BITMAP (2133571367L)
|
||||
#define EXT2_ET_NO_BLOCK_BITMAP (2133571368L)
|
||||
#define EXT2_ET_BAD_INODE_NUM (2133571369L)
|
||||
#define EXT2_ET_BAD_BLOCK_NUM (2133571370L)
|
||||
#define EXT2_ET_EXPAND_DIR_ERR (2133571371L)
|
||||
#define EXT2_ET_TOOSMALL (2133571372L)
|
||||
#define EXT2_ET_BAD_BLOCK_MARK (2133571373L)
|
||||
#define EXT2_ET_BAD_BLOCK_UNMARK (2133571374L)
|
||||
#define EXT2_ET_BAD_BLOCK_TEST (2133571375L)
|
||||
#define EXT2_ET_BAD_INODE_MARK (2133571376L)
|
||||
#define EXT2_ET_BAD_INODE_UNMARK (2133571377L)
|
||||
#define EXT2_ET_BAD_INODE_TEST (2133571378L)
|
||||
#define EXT2_ET_FUDGE_BLOCK_BITMAP_END (2133571379L)
|
||||
#define EXT2_ET_FUDGE_INODE_BITMAP_END (2133571380L)
|
||||
#define EXT2_ET_BAD_IND_BLOCK (2133571381L)
|
||||
#define EXT2_ET_BAD_DIND_BLOCK (2133571382L)
|
||||
#define EXT2_ET_BAD_TIND_BLOCK (2133571383L)
|
||||
#define EXT2_ET_NEQ_BLOCK_BITMAP (2133571384L)
|
||||
#define EXT2_ET_NEQ_INODE_BITMAP (2133571385L)
|
||||
#define EXT2_ET_BAD_DEVICE_NAME (2133571386L)
|
||||
#define EXT2_ET_MISSING_INODE_TABLE (2133571387L)
|
||||
#define EXT2_ET_CORRUPT_SUPERBLOCK (2133571388L)
|
||||
#define EXT2_ET_BAD_GENERIC_MARK (2133571389L)
|
||||
#define EXT2_ET_BAD_GENERIC_UNMARK (2133571390L)
|
||||
#define EXT2_ET_BAD_GENERIC_TEST (2133571391L)
|
||||
#define EXT2_ET_SYMLINK_LOOP (2133571392L)
|
||||
#define EXT2_ET_CALLBACK_NOTHANDLED (2133571393L)
|
||||
#define EXT2_ET_BAD_BLOCK_IN_INODE_TABLE (2133571394L)
|
||||
#define EXT2_ET_UNSUPP_FEATURE (2133571395L)
|
||||
#define EXT2_ET_RO_UNSUPP_FEATURE (2133571396L)
|
||||
#define EXT2_ET_LLSEEK_FAILED (2133571397L)
|
||||
#define EXT2_ET_NO_MEMORY (2133571398L)
|
||||
#define EXT2_ET_INVALID_ARGUMENT (2133571399L)
|
||||
#define EXT2_ET_BLOCK_ALLOC_FAIL (2133571400L)
|
||||
#define EXT2_ET_INODE_ALLOC_FAIL (2133571401L)
|
||||
#define EXT2_ET_NO_DIRECTORY (2133571402L)
|
||||
#define EXT2_ET_TOO_MANY_REFS (2133571403L)
|
||||
#define EXT2_ET_FILE_NOT_FOUND (2133571404L)
|
||||
#define EXT2_ET_FILE_RO (2133571405L)
|
||||
#define EXT2_ET_DB_NOT_FOUND (2133571406L)
|
||||
#define EXT2_ET_DIR_EXISTS (2133571407L)
|
||||
#define EXT2_ET_UNIMPLEMENTED (2133571408L)
|
||||
#define EXT2_ET_CANCEL_REQUESTED (2133571409L)
|
||||
#define EXT2_ET_FILE_TOO_BIG (2133571410L)
|
||||
#define EXT2_ET_JOURNAL_NOT_BLOCK (2133571411L)
|
||||
#define EXT2_ET_NO_JOURNAL_SB (2133571412L)
|
||||
#define EXT2_ET_JOURNAL_TOO_SMALL (2133571413L)
|
||||
#define EXT2_ET_JOURNAL_UNSUPP_VERSION (2133571414L)
|
||||
#define EXT2_ET_LOAD_EXT_JOURNAL (2133571415L)
|
||||
#define EXT2_ET_NO_JOURNAL (2133571416L)
|
||||
#define EXT2_ET_DIRHASH_UNSUPP (2133571417L)
|
||||
#define EXT2_ET_BAD_EA_BLOCK_NUM (2133571418L)
|
||||
#define EXT2_ET_TOO_MANY_INODES (2133571419L)
|
||||
#define EXT2_ET_NOT_IMAGE_FILE (2133571420L)
|
||||
#define EXT2_ET_RES_GDT_BLOCKS (2133571421L)
|
||||
#define EXT2_ET_RESIZE_INODE_CORRUPT (2133571422L)
|
||||
#define EXT2_ET_SET_BMAP_NO_IND (2133571423L)
|
||||
|
||||
#if 0
|
||||
extern const struct error_table et_ext2_error_table;
|
||||
extern void initialize_ext2_error_table(void);
|
||||
|
||||
/* For compatibility with Heimdal */
|
||||
extern void initialize_ext2_error_table_r(struct et_list **list);
|
||||
|
||||
#define ERROR_TABLE_BASE_ext2 (2133571328L)
|
||||
|
||||
/* for compatibility with older versions... */
|
||||
#define init_ext2_err_tbl initialize_ext2_error_table
|
||||
#define ext2_err_base ERROR_TABLE_BASE_ext2
|
||||
#endif
|
53
e2fsprogs/old_e2fsprogs/ext2fs/ext2_ext_attr.h
Normal file
53
e2fsprogs/old_e2fsprogs/ext2fs/ext2_ext_attr.h
Normal file
@ -0,0 +1,53 @@
|
||||
/* vi: set sw=4 ts=4: */
|
||||
/*
|
||||
File: linux/ext2_ext_attr.h
|
||||
|
||||
On-disk format of extended attributes for the ext2 filesystem.
|
||||
|
||||
(C) 2000 Andreas Gruenbacher, <a.gruenbacher@computer.org>
|
||||
*/
|
||||
|
||||
/* Magic value in attribute blocks */
|
||||
#define EXT2_EXT_ATTR_MAGIC_v1 0xEA010000
|
||||
#define EXT2_EXT_ATTR_MAGIC 0xEA020000
|
||||
|
||||
/* Maximum number of references to one attribute block */
|
||||
#define EXT2_EXT_ATTR_REFCOUNT_MAX 1024
|
||||
|
||||
struct ext2_ext_attr_header {
|
||||
__u32 h_magic; /* magic number for identification */
|
||||
__u32 h_refcount; /* reference count */
|
||||
__u32 h_blocks; /* number of disk blocks used */
|
||||
__u32 h_hash; /* hash value of all attributes */
|
||||
__u32 h_reserved[4]; /* zero right now */
|
||||
};
|
||||
|
||||
struct ext2_ext_attr_entry {
|
||||
__u8 e_name_len; /* length of name */
|
||||
__u8 e_name_index; /* attribute name index */
|
||||
__u16 e_value_offs; /* offset in disk block of value */
|
||||
__u32 e_value_block; /* disk block attribute is stored on (n/i) */
|
||||
__u32 e_value_size; /* size of attribute value */
|
||||
__u32 e_hash; /* hash value of name and value */
|
||||
};
|
||||
|
||||
#define EXT2_EXT_ATTR_PAD_BITS 2
|
||||
#define EXT2_EXT_ATTR_PAD (1<<EXT2_EXT_ATTR_PAD_BITS)
|
||||
#define EXT2_EXT_ATTR_ROUND (EXT2_EXT_ATTR_PAD-1)
|
||||
#define EXT2_EXT_ATTR_LEN(name_len) \
|
||||
(((name_len) + EXT2_EXT_ATTR_ROUND + \
|
||||
sizeof(struct ext2_ext_attr_entry)) & ~EXT2_EXT_ATTR_ROUND)
|
||||
#define EXT2_EXT_ATTR_NEXT(entry) \
|
||||
( (struct ext2_ext_attr_entry *)( \
|
||||
(char *)(entry) + EXT2_EXT_ATTR_LEN((entry)->e_name_len)) )
|
||||
#define EXT2_EXT_ATTR_SIZE(size) \
|
||||
(((size) + EXT2_EXT_ATTR_ROUND) & ~EXT2_EXT_ATTR_ROUND)
|
||||
#define EXT2_EXT_IS_LAST_ENTRY(entry) (*((__u32 *)(entry)) == 0UL)
|
||||
#define EXT2_EXT_ATTR_NAME(entry) \
|
||||
(((char *) (entry)) + sizeof(struct ext2_ext_attr_entry))
|
||||
#define EXT2_XATTR_LEN(name_len) \
|
||||
(((name_len) + EXT2_EXT_ATTR_ROUND + \
|
||||
sizeof(struct ext2_xattr_entry)) & ~EXT2_EXT_ATTR_ROUND)
|
||||
#define EXT2_XATTR_SIZE(size) \
|
||||
(((size) + EXT2_EXT_ATTR_ROUND) & ~EXT2_EXT_ATTR_ROUND)
|
||||
|
570
e2fsprogs/old_e2fsprogs/ext2fs/ext2_fs.h
Normal file
570
e2fsprogs/old_e2fsprogs/ext2fs/ext2_fs.h
Normal file
@ -0,0 +1,570 @@
|
||||
/* vi: set sw=4 ts=4: */
|
||||
/*
|
||||
* linux/include/linux/ext2_fs.h
|
||||
*
|
||||
* Copyright (C) 1992, 1993, 1994, 1995
|
||||
* Remy Card (card@masi.ibp.fr)
|
||||
* Laboratoire MASI - Institut Blaise Pascal
|
||||
* Universite Pierre et Marie Curie (Paris VI)
|
||||
*
|
||||
* from
|
||||
*
|
||||
* linux/include/linux/minix_fs.h
|
||||
*
|
||||
* Copyright (C) 1991, 1992 Linus Torvalds
|
||||
*/
|
||||
|
||||
#ifndef _LINUX_EXT2_FS_H
|
||||
#define _LINUX_EXT2_FS_H
|
||||
|
||||
#include "ext2_types.h" /* Changed from linux/types.h */
|
||||
|
||||
/*
|
||||
* Special inode numbers
|
||||
*/
|
||||
#define EXT2_BAD_INO 1 /* Bad blocks inode */
|
||||
#define EXT2_ROOT_INO 2 /* Root inode */
|
||||
#define EXT2_ACL_IDX_INO 3 /* ACL inode */
|
||||
#define EXT2_ACL_DATA_INO 4 /* ACL inode */
|
||||
#define EXT2_BOOT_LOADER_INO 5 /* Boot loader inode */
|
||||
#define EXT2_UNDEL_DIR_INO 6 /* Undelete directory inode */
|
||||
#define EXT2_RESIZE_INO 7 /* Reserved group descriptors inode */
|
||||
#define EXT2_JOURNAL_INO 8 /* Journal inode */
|
||||
|
||||
/* First non-reserved inode for old ext2 filesystems */
|
||||
#define EXT2_GOOD_OLD_FIRST_INO 11
|
||||
|
||||
/*
|
||||
* The second extended file system magic number
|
||||
*/
|
||||
#define EXT2_SUPER_MAGIC 0xEF53
|
||||
|
||||
/* Assume that user mode programs are passing in an ext2fs superblock, not
|
||||
* a kernel struct super_block. This will allow us to call the feature-test
|
||||
* macros from user land. */
|
||||
#define EXT2_SB(sb) (sb)
|
||||
|
||||
/*
|
||||
* Maximal count of links to a file
|
||||
*/
|
||||
#define EXT2_LINK_MAX 32000
|
||||
|
||||
/*
|
||||
* Macro-instructions used to manage several block sizes
|
||||
*/
|
||||
#define EXT2_MIN_BLOCK_LOG_SIZE 10 /* 1024 */
|
||||
#define EXT2_MAX_BLOCK_LOG_SIZE 16 /* 65536 */
|
||||
#define EXT2_MIN_BLOCK_SIZE (1 << EXT2_MIN_BLOCK_LOG_SIZE)
|
||||
#define EXT2_MAX_BLOCK_SIZE (1 << EXT2_MAX_BLOCK_LOG_SIZE)
|
||||
#define EXT2_BLOCK_SIZE(s) (EXT2_MIN_BLOCK_SIZE << (s)->s_log_block_size)
|
||||
#define EXT2_BLOCK_SIZE_BITS(s) ((s)->s_log_block_size + 10)
|
||||
#define EXT2_INODE_SIZE(s) (((s)->s_rev_level == EXT2_GOOD_OLD_REV) ? \
|
||||
EXT2_GOOD_OLD_INODE_SIZE : (s)->s_inode_size)
|
||||
#define EXT2_FIRST_INO(s) (((s)->s_rev_level == EXT2_GOOD_OLD_REV) ? \
|
||||
EXT2_GOOD_OLD_FIRST_INO : (s)->s_first_ino)
|
||||
#define EXT2_ADDR_PER_BLOCK(s) (EXT2_BLOCK_SIZE(s) / sizeof(__u32))
|
||||
|
||||
/*
|
||||
* Macro-instructions used to manage fragments
|
||||
*/
|
||||
#define EXT2_MIN_FRAG_SIZE EXT2_MIN_BLOCK_SIZE
|
||||
#define EXT2_MAX_FRAG_SIZE EXT2_MAX_BLOCK_SIZE
|
||||
#define EXT2_MIN_FRAG_LOG_SIZE EXT2_MIN_BLOCK_LOG_SIZE
|
||||
# define EXT2_FRAG_SIZE(s) (EXT2_MIN_FRAG_SIZE << (s)->s_log_frag_size)
|
||||
# define EXT2_FRAGS_PER_BLOCK(s) (EXT2_BLOCK_SIZE(s) / EXT2_FRAG_SIZE(s))
|
||||
|
||||
/*
|
||||
* ACL structures
|
||||
*/
|
||||
struct ext2_acl_header /* Header of Access Control Lists */
|
||||
{
|
||||
__u32 aclh_size;
|
||||
__u32 aclh_file_count;
|
||||
__u32 aclh_acle_count;
|
||||
__u32 aclh_first_acle;
|
||||
};
|
||||
|
||||
struct ext2_acl_entry /* Access Control List Entry */
|
||||
{
|
||||
__u32 acle_size;
|
||||
__u16 acle_perms; /* Access permissions */
|
||||
__u16 acle_type; /* Type of entry */
|
||||
__u16 acle_tag; /* User or group identity */
|
||||
__u16 acle_pad1;
|
||||
__u32 acle_next; /* Pointer on next entry for the */
|
||||
/* same inode or on next free entry */
|
||||
};
|
||||
|
||||
/*
|
||||
* Structure of a blocks group descriptor
|
||||
*/
|
||||
struct ext2_group_desc
|
||||
{
|
||||
__u32 bg_block_bitmap; /* Blocks bitmap block */
|
||||
__u32 bg_inode_bitmap; /* Inodes bitmap block */
|
||||
__u32 bg_inode_table; /* Inodes table block */
|
||||
__u16 bg_free_blocks_count; /* Free blocks count */
|
||||
__u16 bg_free_inodes_count; /* Free inodes count */
|
||||
__u16 bg_used_dirs_count; /* Directories count */
|
||||
__u16 bg_pad;
|
||||
__u32 bg_reserved[3];
|
||||
};
|
||||
|
||||
/*
|
||||
* Data structures used by the directory indexing feature
|
||||
*
|
||||
* Note: all of the multibyte integer fields are little endian.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Note: dx_root_info is laid out so that if it should somehow get
|
||||
* overlaid by a dirent the two low bits of the hash version will be
|
||||
* zero. Therefore, the hash version mod 4 should never be 0.
|
||||
* Sincerely, the paranoia department.
|
||||
*/
|
||||
struct ext2_dx_root_info {
|
||||
__u32 reserved_zero;
|
||||
__u8 hash_version; /* 0 now, 1 at release */
|
||||
__u8 info_length; /* 8 */
|
||||
__u8 indirect_levels;
|
||||
__u8 unused_flags;
|
||||
};
|
||||
|
||||
#define EXT2_HASH_LEGACY 0
|
||||
#define EXT2_HASH_HALF_MD4 1
|
||||
#define EXT2_HASH_TEA 2
|
||||
|
||||
#define EXT2_HASH_FLAG_INCOMPAT 0x1
|
||||
|
||||
struct ext2_dx_entry {
|
||||
__u32 hash;
|
||||
__u32 block;
|
||||
};
|
||||
|
||||
struct ext2_dx_countlimit {
|
||||
__u16 limit;
|
||||
__u16 count;
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
* Macro-instructions used to manage group descriptors
|
||||
*/
|
||||
#define EXT2_BLOCKS_PER_GROUP(s) (EXT2_SB(s)->s_blocks_per_group)
|
||||
#define EXT2_INODES_PER_GROUP(s) (EXT2_SB(s)->s_inodes_per_group)
|
||||
#define EXT2_INODES_PER_BLOCK(s) (EXT2_BLOCK_SIZE(s)/EXT2_INODE_SIZE(s))
|
||||
/* limits imposed by 16-bit value gd_free_{blocks,inode}_count */
|
||||
#define EXT2_MAX_BLOCKS_PER_GROUP(s) ((1 << 16) - 8)
|
||||
#define EXT2_MAX_INODES_PER_GROUP(s) ((1 << 16) - EXT2_INODES_PER_BLOCK(s))
|
||||
#define EXT2_DESC_PER_BLOCK(s) (EXT2_BLOCK_SIZE(s) / sizeof (struct ext2_group_desc))
|
||||
|
||||
/*
|
||||
* Constants relative to the data blocks
|
||||
*/
|
||||
#define EXT2_NDIR_BLOCKS 12
|
||||
#define EXT2_IND_BLOCK EXT2_NDIR_BLOCKS
|
||||
#define EXT2_DIND_BLOCK (EXT2_IND_BLOCK + 1)
|
||||
#define EXT2_TIND_BLOCK (EXT2_DIND_BLOCK + 1)
|
||||
#define EXT2_N_BLOCKS (EXT2_TIND_BLOCK + 1)
|
||||
|
||||
/*
|
||||
* Inode flags
|
||||
*/
|
||||
#define EXT2_SECRM_FL 0x00000001 /* Secure deletion */
|
||||
#define EXT2_UNRM_FL 0x00000002 /* Undelete */
|
||||
#define EXT2_COMPR_FL 0x00000004 /* Compress file */
|
||||
#define EXT2_SYNC_FL 0x00000008 /* Synchronous updates */
|
||||
#define EXT2_IMMUTABLE_FL 0x00000010 /* Immutable file */
|
||||
#define EXT2_APPEND_FL 0x00000020 /* writes to file may only append */
|
||||
#define EXT2_NODUMP_FL 0x00000040 /* do not dump file */
|
||||
#define EXT2_NOATIME_FL 0x00000080 /* do not update atime */
|
||||
/* Reserved for compression usage... */
|
||||
#define EXT2_DIRTY_FL 0x00000100
|
||||
#define EXT2_COMPRBLK_FL 0x00000200 /* One or more compressed clusters */
|
||||
#define EXT2_NOCOMPR_FL 0x00000400 /* Access raw compressed data */
|
||||
#define EXT2_ECOMPR_FL 0x00000800 /* Compression error */
|
||||
/* End compression flags --- maybe not all used */
|
||||
#define EXT2_BTREE_FL 0x00001000 /* btree format dir */
|
||||
#define EXT2_INDEX_FL 0x00001000 /* hash-indexed directory */
|
||||
#define EXT2_IMAGIC_FL 0x00002000
|
||||
#define EXT3_JOURNAL_DATA_FL 0x00004000 /* file data should be journaled */
|
||||
#define EXT2_NOTAIL_FL 0x00008000 /* file tail should not be merged */
|
||||
#define EXT2_DIRSYNC_FL 0x00010000 /* Synchronous directory modifications */
|
||||
#define EXT2_TOPDIR_FL 0x00020000 /* Top of directory hierarchies*/
|
||||
#define EXT3_EXTENTS_FL 0x00080000 /* Inode uses extents */
|
||||
#define EXT2_RESERVED_FL 0x80000000 /* reserved for ext2 lib */
|
||||
|
||||
#define EXT2_FL_USER_VISIBLE 0x0003DFFF /* User visible flags */
|
||||
#define EXT2_FL_USER_MODIFIABLE 0x000080FF /* User modifiable flags */
|
||||
|
||||
/*
|
||||
* ioctl commands
|
||||
*/
|
||||
#define EXT2_IOC_GETFLAGS _IOR('f', 1, long)
|
||||
#define EXT2_IOC_SETFLAGS _IOW('f', 2, long)
|
||||
#define EXT2_IOC_GETVERSION _IOR('v', 1, long)
|
||||
#define EXT2_IOC_SETVERSION _IOW('v', 2, long)
|
||||
|
||||
/*
|
||||
* Structure of an inode on the disk
|
||||
*/
|
||||
struct ext2_inode {
|
||||
__u16 i_mode; /* File mode */
|
||||
__u16 i_uid; /* Low 16 bits of Owner Uid */
|
||||
__u32 i_size; /* Size in bytes */
|
||||
__u32 i_atime; /* Access time */
|
||||
__u32 i_ctime; /* Creation time */
|
||||
__u32 i_mtime; /* Modification time */
|
||||
__u32 i_dtime; /* Deletion Time */
|
||||
__u16 i_gid; /* Low 16 bits of Group Id */
|
||||
__u16 i_links_count; /* Links count */
|
||||
__u32 i_blocks; /* Blocks count */
|
||||
__u32 i_flags; /* File flags */
|
||||
union {
|
||||
struct {
|
||||
__u32 l_i_reserved1;
|
||||
} linux1;
|
||||
struct {
|
||||
__u32 h_i_translator;
|
||||
} hurd1;
|
||||
struct {
|
||||
__u32 m_i_reserved1;
|
||||
} masix1;
|
||||
} osd1; /* OS dependent 1 */
|
||||
__u32 i_block[EXT2_N_BLOCKS];/* Pointers to blocks */
|
||||
__u32 i_generation; /* File version (for NFS) */
|
||||
__u32 i_file_acl; /* File ACL */
|
||||
__u32 i_dir_acl; /* Directory ACL */
|
||||
__u32 i_faddr; /* Fragment address */
|
||||
union {
|
||||
struct {
|
||||
__u8 l_i_frag; /* Fragment number */
|
||||
__u8 l_i_fsize; /* Fragment size */
|
||||
__u16 i_pad1;
|
||||
__u16 l_i_uid_high; /* these 2 fields */
|
||||
__u16 l_i_gid_high; /* were reserved2[0] */
|
||||
__u32 l_i_reserved2;
|
||||
} linux2;
|
||||
struct {
|
||||
__u8 h_i_frag; /* Fragment number */
|
||||
__u8 h_i_fsize; /* Fragment size */
|
||||
__u16 h_i_mode_high;
|
||||
__u16 h_i_uid_high;
|
||||
__u16 h_i_gid_high;
|
||||
__u32 h_i_author;
|
||||
} hurd2;
|
||||
struct {
|
||||
__u8 m_i_frag; /* Fragment number */
|
||||
__u8 m_i_fsize; /* Fragment size */
|
||||
__u16 m_pad1;
|
||||
__u32 m_i_reserved2[2];
|
||||
} masix2;
|
||||
} osd2; /* OS dependent 2 */
|
||||
};
|
||||
|
||||
/*
|
||||
* Permanent part of an large inode on the disk
|
||||
*/
|
||||
struct ext2_inode_large {
|
||||
__u16 i_mode; /* File mode */
|
||||
__u16 i_uid; /* Low 16 bits of Owner Uid */
|
||||
__u32 i_size; /* Size in bytes */
|
||||
__u32 i_atime; /* Access time */
|
||||
__u32 i_ctime; /* Creation time */
|
||||
__u32 i_mtime; /* Modification time */
|
||||
__u32 i_dtime; /* Deletion Time */
|
||||
__u16 i_gid; /* Low 16 bits of Group Id */
|
||||
__u16 i_links_count; /* Links count */
|
||||
__u32 i_blocks; /* Blocks count */
|
||||
__u32 i_flags; /* File flags */
|
||||
union {
|
||||
struct {
|
||||
__u32 l_i_reserved1;
|
||||
} linux1;
|
||||
struct {
|
||||
__u32 h_i_translator;
|
||||
} hurd1;
|
||||
struct {
|
||||
__u32 m_i_reserved1;
|
||||
} masix1;
|
||||
} osd1; /* OS dependent 1 */
|
||||
__u32 i_block[EXT2_N_BLOCKS];/* Pointers to blocks */
|
||||
__u32 i_generation; /* File version (for NFS) */
|
||||
__u32 i_file_acl; /* File ACL */
|
||||
__u32 i_dir_acl; /* Directory ACL */
|
||||
__u32 i_faddr; /* Fragment address */
|
||||
union {
|
||||
struct {
|
||||
__u8 l_i_frag; /* Fragment number */
|
||||
__u8 l_i_fsize; /* Fragment size */
|
||||
__u16 i_pad1;
|
||||
__u16 l_i_uid_high; /* these 2 fields */
|
||||
__u16 l_i_gid_high; /* were reserved2[0] */
|
||||
__u32 l_i_reserved2;
|
||||
} linux2;
|
||||
struct {
|
||||
__u8 h_i_frag; /* Fragment number */
|
||||
__u8 h_i_fsize; /* Fragment size */
|
||||
__u16 h_i_mode_high;
|
||||
__u16 h_i_uid_high;
|
||||
__u16 h_i_gid_high;
|
||||
__u32 h_i_author;
|
||||
} hurd2;
|
||||
struct {
|
||||
__u8 m_i_frag; /* Fragment number */
|
||||
__u8 m_i_fsize; /* Fragment size */
|
||||
__u16 m_pad1;
|
||||
__u32 m_i_reserved2[2];
|
||||
} masix2;
|
||||
} osd2; /* OS dependent 2 */
|
||||
__u16 i_extra_isize;
|
||||
__u16 i_pad1;
|
||||
};
|
||||
|
||||
#define i_size_high i_dir_acl
|
||||
|
||||
/*
|
||||
* File system states
|
||||
*/
|
||||
#define EXT2_VALID_FS 0x0001 /* Unmounted cleanly */
|
||||
#define EXT2_ERROR_FS 0x0002 /* Errors detected */
|
||||
|
||||
/*
|
||||
* Mount flags
|
||||
*/
|
||||
#define EXT2_MOUNT_CHECK 0x0001 /* Do mount-time checks */
|
||||
#define EXT2_MOUNT_GRPID 0x0004 /* Create files with directory's group */
|
||||
#define EXT2_MOUNT_DEBUG 0x0008 /* Some debugging messages */
|
||||
#define EXT2_MOUNT_ERRORS_CONT 0x0010 /* Continue on errors */
|
||||
#define EXT2_MOUNT_ERRORS_RO 0x0020 /* Remount fs ro on errors */
|
||||
#define EXT2_MOUNT_ERRORS_PANIC 0x0040 /* Panic on errors */
|
||||
#define EXT2_MOUNT_MINIX_DF 0x0080 /* Mimics the Minix statfs */
|
||||
#define EXT2_MOUNT_NO_UID32 0x0200 /* Disable 32-bit UIDs */
|
||||
|
||||
#define clear_opt(o, opt) o &= ~EXT2_MOUNT_##opt
|
||||
#define set_opt(o, opt) o |= EXT2_MOUNT_##opt
|
||||
#define test_opt(sb, opt) (EXT2_SB(sb)->s_mount_opt & \
|
||||
EXT2_MOUNT_##opt)
|
||||
/*
|
||||
* Maximal mount counts between two filesystem checks
|
||||
*/
|
||||
#define EXT2_DFL_MAX_MNT_COUNT 20 /* Allow 20 mounts */
|
||||
#define EXT2_DFL_CHECKINTERVAL 0 /* Don't use interval check */
|
||||
|
||||
/*
|
||||
* Behaviour when detecting errors
|
||||
*/
|
||||
#define EXT2_ERRORS_CONTINUE 1 /* Continue execution */
|
||||
#define EXT2_ERRORS_RO 2 /* Remount fs read-only */
|
||||
#define EXT2_ERRORS_PANIC 3 /* Panic */
|
||||
#define EXT2_ERRORS_DEFAULT EXT2_ERRORS_CONTINUE
|
||||
|
||||
/*
|
||||
* Structure of the super block
|
||||
*/
|
||||
struct ext2_super_block {
|
||||
__u32 s_inodes_count; /* Inodes count */
|
||||
__u32 s_blocks_count; /* Blocks count */
|
||||
__u32 s_r_blocks_count; /* Reserved blocks count */
|
||||
__u32 s_free_blocks_count; /* Free blocks count */
|
||||
__u32 s_free_inodes_count; /* Free inodes count */
|
||||
__u32 s_first_data_block; /* First Data Block */
|
||||
__u32 s_log_block_size; /* Block size */
|
||||
__s32 s_log_frag_size; /* Fragment size */
|
||||
__u32 s_blocks_per_group; /* # Blocks per group */
|
||||
__u32 s_frags_per_group; /* # Fragments per group */
|
||||
__u32 s_inodes_per_group; /* # Inodes per group */
|
||||
__u32 s_mtime; /* Mount time */
|
||||
__u32 s_wtime; /* Write time */
|
||||
__u16 s_mnt_count; /* Mount count */
|
||||
__s16 s_max_mnt_count; /* Maximal mount count */
|
||||
__u16 s_magic; /* Magic signature */
|
||||
__u16 s_state; /* File system state */
|
||||
__u16 s_errors; /* Behaviour when detecting errors */
|
||||
__u16 s_minor_rev_level; /* minor revision level */
|
||||
__u32 s_lastcheck; /* time of last check */
|
||||
__u32 s_checkinterval; /* max. time between checks */
|
||||
__u32 s_creator_os; /* OS */
|
||||
__u32 s_rev_level; /* Revision level */
|
||||
__u16 s_def_resuid; /* Default uid for reserved blocks */
|
||||
__u16 s_def_resgid; /* Default gid for reserved blocks */
|
||||
/*
|
||||
* These fields are for EXT2_DYNAMIC_REV superblocks only.
|
||||
*
|
||||
* Note: the difference between the compatible feature set and
|
||||
* the incompatible feature set is that if there is a bit set
|
||||
* in the incompatible feature set that the kernel doesn't
|
||||
* know about, it should refuse to mount the filesystem.
|
||||
*
|
||||
* e2fsck's requirements are more strict; if it doesn't know
|
||||
* about a feature in either the compatible or incompatible
|
||||
* feature set, it must abort and not try to meddle with
|
||||
* things it doesn't understand...
|
||||
*/
|
||||
__u32 s_first_ino; /* First non-reserved inode */
|
||||
__u16 s_inode_size; /* size of inode structure */
|
||||
__u16 s_block_group_nr; /* block group # of this superblock */
|
||||
__u32 s_feature_compat; /* compatible feature set */
|
||||
__u32 s_feature_incompat; /* incompatible feature set */
|
||||
__u32 s_feature_ro_compat; /* readonly-compatible feature set */
|
||||
__u8 s_uuid[16]; /* 128-bit uuid for volume */
|
||||
char s_volume_name[16]; /* volume name */
|
||||
char s_last_mounted[64]; /* directory where last mounted */
|
||||
__u32 s_algorithm_usage_bitmap; /* For compression */
|
||||
/*
|
||||
* Performance hints. Directory preallocation should only
|
||||
* happen if the EXT2_FEATURE_COMPAT_DIR_PREALLOC flag is on.
|
||||
*/
|
||||
__u8 s_prealloc_blocks; /* Nr of blocks to try to preallocate*/
|
||||
__u8 s_prealloc_dir_blocks; /* Nr to preallocate for dirs */
|
||||
__u16 s_reserved_gdt_blocks; /* Per group table for online growth */
|
||||
/*
|
||||
* Journaling support valid if EXT2_FEATURE_COMPAT_HAS_JOURNAL set.
|
||||
*/
|
||||
__u8 s_journal_uuid[16]; /* uuid of journal superblock */
|
||||
__u32 s_journal_inum; /* inode number of journal file */
|
||||
__u32 s_journal_dev; /* device number of journal file */
|
||||
__u32 s_last_orphan; /* start of list of inodes to delete */
|
||||
__u32 s_hash_seed[4]; /* HTREE hash seed */
|
||||
__u8 s_def_hash_version; /* Default hash version to use */
|
||||
__u8 s_jnl_backup_type; /* Default type of journal backup */
|
||||
__u16 s_reserved_word_pad;
|
||||
__u32 s_default_mount_opts;
|
||||
__u32 s_first_meta_bg; /* First metablock group */
|
||||
__u32 s_mkfs_time; /* When the filesystem was created */
|
||||
__u32 s_jnl_blocks[17]; /* Backup of the journal inode */
|
||||
__u32 s_reserved[172]; /* Padding to the end of the block */
|
||||
};
|
||||
|
||||
/*
|
||||
* Codes for operating systems
|
||||
*/
|
||||
#define EXT2_OS_LINUX 0
|
||||
#define EXT2_OS_HURD 1
|
||||
#define EXT2_OS_MASIX 2
|
||||
#define EXT2_OS_FREEBSD 3
|
||||
#define EXT2_OS_LITES 4
|
||||
|
||||
/*
|
||||
* Revision levels
|
||||
*/
|
||||
#define EXT2_GOOD_OLD_REV 0 /* The good old (original) format */
|
||||
#define EXT2_DYNAMIC_REV 1 /* V2 format w/ dynamic inode sizes */
|
||||
|
||||
#define EXT2_CURRENT_REV EXT2_GOOD_OLD_REV
|
||||
#define EXT2_MAX_SUPP_REV EXT2_DYNAMIC_REV
|
||||
|
||||
#define EXT2_GOOD_OLD_INODE_SIZE 128
|
||||
|
||||
/*
|
||||
* Journal inode backup types
|
||||
*/
|
||||
#define EXT3_JNL_BACKUP_BLOCKS 1
|
||||
|
||||
/*
|
||||
* Feature set definitions
|
||||
*/
|
||||
|
||||
#define EXT2_HAS_COMPAT_FEATURE(sb,mask) \
|
||||
( EXT2_SB(sb)->s_feature_compat & (mask) )
|
||||
#define EXT2_HAS_RO_COMPAT_FEATURE(sb,mask) \
|
||||
( EXT2_SB(sb)->s_feature_ro_compat & (mask) )
|
||||
#define EXT2_HAS_INCOMPAT_FEATURE(sb,mask) \
|
||||
( EXT2_SB(sb)->s_feature_incompat & (mask) )
|
||||
|
||||
#define EXT2_FEATURE_COMPAT_DIR_PREALLOC 0x0001
|
||||
#define EXT2_FEATURE_COMPAT_IMAGIC_INODES 0x0002
|
||||
#define EXT3_FEATURE_COMPAT_HAS_JOURNAL 0x0004
|
||||
#define EXT2_FEATURE_COMPAT_EXT_ATTR 0x0008
|
||||
#define EXT2_FEATURE_COMPAT_RESIZE_INODE 0x0010
|
||||
#define EXT2_FEATURE_COMPAT_DIR_INDEX 0x0020
|
||||
|
||||
#define EXT2_FEATURE_RO_COMPAT_SPARSE_SUPER 0x0001
|
||||
#define EXT2_FEATURE_RO_COMPAT_LARGE_FILE 0x0002
|
||||
/* #define EXT2_FEATURE_RO_COMPAT_BTREE_DIR 0x0004 not used */
|
||||
|
||||
#define EXT2_FEATURE_INCOMPAT_COMPRESSION 0x0001
|
||||
#define EXT2_FEATURE_INCOMPAT_FILETYPE 0x0002
|
||||
#define EXT3_FEATURE_INCOMPAT_RECOVER 0x0004 /* Needs recovery */
|
||||
#define EXT3_FEATURE_INCOMPAT_JOURNAL_DEV 0x0008 /* Journal device */
|
||||
#define EXT2_FEATURE_INCOMPAT_META_BG 0x0010
|
||||
#define EXT3_FEATURE_INCOMPAT_EXTENTS 0x0040
|
||||
|
||||
|
||||
#define EXT2_FEATURE_COMPAT_SUPP 0
|
||||
#define EXT2_FEATURE_INCOMPAT_SUPP (EXT2_FEATURE_INCOMPAT_FILETYPE)
|
||||
#define EXT2_FEATURE_RO_COMPAT_SUPP (EXT2_FEATURE_RO_COMPAT_SPARSE_SUPER| \
|
||||
EXT2_FEATURE_RO_COMPAT_LARGE_FILE| \
|
||||
EXT2_FEATURE_RO_COMPAT_BTREE_DIR)
|
||||
|
||||
/*
|
||||
* Default values for user and/or group using reserved blocks
|
||||
*/
|
||||
#define EXT2_DEF_RESUID 0
|
||||
#define EXT2_DEF_RESGID 0
|
||||
|
||||
/*
|
||||
* Default mount options
|
||||
*/
|
||||
#define EXT2_DEFM_DEBUG 0x0001
|
||||
#define EXT2_DEFM_BSDGROUPS 0x0002
|
||||
#define EXT2_DEFM_XATTR_USER 0x0004
|
||||
#define EXT2_DEFM_ACL 0x0008
|
||||
#define EXT2_DEFM_UID16 0x0010
|
||||
#define EXT3_DEFM_JMODE 0x0060
|
||||
#define EXT3_DEFM_JMODE_DATA 0x0020
|
||||
#define EXT3_DEFM_JMODE_ORDERED 0x0040
|
||||
#define EXT3_DEFM_JMODE_WBACK 0x0060
|
||||
|
||||
/*
|
||||
* Structure of a directory entry
|
||||
*/
|
||||
#define EXT2_NAME_LEN 255
|
||||
|
||||
struct ext2_dir_entry {
|
||||
__u32 inode; /* Inode number */
|
||||
__u16 rec_len; /* Directory entry length */
|
||||
__u16 name_len; /* Name length */
|
||||
char name[EXT2_NAME_LEN]; /* File name */
|
||||
};
|
||||
|
||||
/*
|
||||
* The new version of the directory entry. Since EXT2 structures are
|
||||
* stored in intel byte order, and the name_len field could never be
|
||||
* bigger than 255 chars, it's safe to reclaim the extra byte for the
|
||||
* file_type field.
|
||||
*/
|
||||
struct ext2_dir_entry_2 {
|
||||
__u32 inode; /* Inode number */
|
||||
__u16 rec_len; /* Directory entry length */
|
||||
__u8 name_len; /* Name length */
|
||||
__u8 file_type;
|
||||
char name[EXT2_NAME_LEN]; /* File name */
|
||||
};
|
||||
|
||||
/*
|
||||
* Ext2 directory file types. Only the low 3 bits are used. The
|
||||
* other bits are reserved for now.
|
||||
*/
|
||||
#define EXT2_FT_UNKNOWN 0
|
||||
#define EXT2_FT_REG_FILE 1
|
||||
#define EXT2_FT_DIR 2
|
||||
#define EXT2_FT_CHRDEV 3
|
||||
#define EXT2_FT_BLKDEV 4
|
||||
#define EXT2_FT_FIFO 5
|
||||
#define EXT2_FT_SOCK 6
|
||||
#define EXT2_FT_SYMLINK 7
|
||||
|
||||
#define EXT2_FT_MAX 8
|
||||
|
||||
/*
|
||||
* EXT2_DIR_PAD defines the directory entries boundaries
|
||||
*
|
||||
* NOTE: It must be a multiple of 4
|
||||
*/
|
||||
#define EXT2_DIR_PAD 4
|
||||
#define EXT2_DIR_ROUND (EXT2_DIR_PAD - 1)
|
||||
#define EXT2_DIR_REC_LEN(name_len) (((name_len) + 8 + EXT2_DIR_ROUND) & \
|
||||
~EXT2_DIR_ROUND)
|
||||
|
||||
#endif /* _LINUX_EXT2_FS_H */
|
114
e2fsprogs/old_e2fsprogs/ext2fs/ext2_io.h
Normal file
114
e2fsprogs/old_e2fsprogs/ext2fs/ext2_io.h
Normal file
@ -0,0 +1,114 @@
|
||||
/* vi: set sw=4 ts=4: */
|
||||
/*
|
||||
* io.h --- the I/O manager abstraction
|
||||
*
|
||||
* Copyright (C) 1993, 1994, 1995, 1996 Theodore Ts'o.
|
||||
*
|
||||
* %Begin-Header%
|
||||
* This file may be redistributed under the terms of the GNU Public
|
||||
* License.
|
||||
* %End-Header%
|
||||
*/
|
||||
|
||||
#ifndef _EXT2FS_EXT2_IO_H
|
||||
#define _EXT2FS_EXT2_IO_H
|
||||
|
||||
/*
|
||||
* ext2_loff_t is defined here since unix_io.c needs it.
|
||||
*/
|
||||
#if defined(__GNUC__) || defined(HAS_LONG_LONG)
|
||||
typedef long long ext2_loff_t;
|
||||
#else
|
||||
typedef long ext2_loff_t;
|
||||
#endif
|
||||
|
||||
/* llseek.c */
|
||||
/* ext2_loff_t ext2fs_llseek (int, ext2_loff_t, int); */
|
||||
#ifdef CONFIG_LFS
|
||||
# define ext2fs_llseek lseek64
|
||||
#else
|
||||
# define ext2fs_llseek lseek
|
||||
#endif
|
||||
|
||||
typedef struct struct_io_manager *io_manager;
|
||||
typedef struct struct_io_channel *io_channel;
|
||||
|
||||
#define CHANNEL_FLAGS_WRITETHROUGH 0x01
|
||||
|
||||
struct struct_io_channel {
|
||||
errcode_t magic;
|
||||
io_manager manager;
|
||||
char *name;
|
||||
int block_size;
|
||||
errcode_t (*read_error)(io_channel channel,
|
||||
unsigned long block,
|
||||
int count,
|
||||
void *data,
|
||||
size_t size,
|
||||
int actual_bytes_read,
|
||||
errcode_t error);
|
||||
errcode_t (*write_error)(io_channel channel,
|
||||
unsigned long block,
|
||||
int count,
|
||||
const void *data,
|
||||
size_t size,
|
||||
int actual_bytes_written,
|
||||
errcode_t error);
|
||||
int refcount;
|
||||
int flags;
|
||||
int reserved[14];
|
||||
void *private_data;
|
||||
void *app_data;
|
||||
};
|
||||
|
||||
struct struct_io_manager {
|
||||
errcode_t magic;
|
||||
const char *name;
|
||||
errcode_t (*open)(const char *name, int flags, io_channel *channel);
|
||||
errcode_t (*close)(io_channel channel);
|
||||
errcode_t (*set_blksize)(io_channel channel, int blksize);
|
||||
errcode_t (*read_blk)(io_channel channel, unsigned long block,
|
||||
int count, void *data);
|
||||
errcode_t (*write_blk)(io_channel channel, unsigned long block,
|
||||
int count, const void *data);
|
||||
errcode_t (*flush)(io_channel channel);
|
||||
errcode_t (*write_byte)(io_channel channel, unsigned long offset,
|
||||
int count, const void *data);
|
||||
errcode_t (*set_option)(io_channel channel, const char *option,
|
||||
const char *arg);
|
||||
int reserved[14];
|
||||
};
|
||||
|
||||
#define IO_FLAG_RW 1
|
||||
|
||||
/*
|
||||
* Convenience functions....
|
||||
*/
|
||||
#define io_channel_close(c) ((c)->manager->close((c)))
|
||||
#define io_channel_set_blksize(c,s) ((c)->manager->set_blksize((c),s))
|
||||
#define io_channel_read_blk(c,b,n,d) ((c)->manager->read_blk((c),b,n,d))
|
||||
#define io_channel_write_blk(c,b,n,d) ((c)->manager->write_blk((c),b,n,d))
|
||||
#define io_channel_flush(c) ((c)->manager->flush((c)))
|
||||
#define io_channel_bumpcount(c) ((c)->refcount++)
|
||||
|
||||
/* io_manager.c */
|
||||
extern errcode_t io_channel_set_options(io_channel channel,
|
||||
const char *options);
|
||||
extern errcode_t io_channel_write_byte(io_channel channel,
|
||||
unsigned long offset,
|
||||
int count, const void *data);
|
||||
|
||||
/* unix_io.c */
|
||||
extern io_manager unix_io_manager;
|
||||
|
||||
/* test_io.c */
|
||||
extern io_manager test_io_manager, test_io_backing_manager;
|
||||
extern void (*test_io_cb_read_blk)
|
||||
(unsigned long block, int count, errcode_t err);
|
||||
extern void (*test_io_cb_write_blk)
|
||||
(unsigned long block, int count, errcode_t err);
|
||||
extern void (*test_io_cb_set_blksize)
|
||||
(int blksize, errcode_t err);
|
||||
|
||||
#endif /* _EXT2FS_EXT2_IO_H */
|
||||
|
2
e2fsprogs/old_e2fsprogs/ext2fs/ext2_types.h
Normal file
2
e2fsprogs/old_e2fsprogs/ext2fs/ext2_types.h
Normal file
@ -0,0 +1,2 @@
|
||||
/* vi: set sw=4 ts=4: */
|
||||
#include <linux/types.h>
|
923
e2fsprogs/old_e2fsprogs/ext2fs/ext2fs.h
Normal file
923
e2fsprogs/old_e2fsprogs/ext2fs/ext2fs.h
Normal file
@ -0,0 +1,923 @@
|
||||
/* vi: set sw=4 ts=4: */
|
||||
/*
|
||||
* ext2fs.h --- ext2fs
|
||||
*
|
||||
* Copyright (C) 1993, 1994, 1995, 1996 Theodore Ts'o.
|
||||
*
|
||||
* %Begin-Header%
|
||||
* This file may be redistributed under the terms of the GNU Public
|
||||
* License.
|
||||
* %End-Header%
|
||||
*/
|
||||
|
||||
#ifndef _EXT2FS_EXT2FS_H
|
||||
#define _EXT2FS_EXT2FS_H
|
||||
|
||||
|
||||
#define EXT2FS_ATTR(x)
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Where the master copy of the superblock is located, and how big
|
||||
* superblocks are supposed to be. We define SUPERBLOCK_SIZE because
|
||||
* the size of the superblock structure is not necessarily trustworthy
|
||||
* (some versions have the padding set up so that the superblock is
|
||||
* 1032 bytes long).
|
||||
*/
|
||||
#define SUPERBLOCK_OFFSET 1024
|
||||
#define SUPERBLOCK_SIZE 1024
|
||||
|
||||
/*
|
||||
* The last ext2fs revision level that this version of the library is
|
||||
* able to support.
|
||||
*/
|
||||
#define EXT2_LIB_CURRENT_REV EXT2_DYNAMIC_REV
|
||||
|
||||
#ifdef HAVE_SYS_TYPES_H
|
||||
#include <sys/types.h>
|
||||
#endif
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "ext2_types.h"
|
||||
#include "ext2_fs.h"
|
||||
|
||||
typedef __u32 ext2_ino_t;
|
||||
typedef __u32 blk_t;
|
||||
typedef __u32 dgrp_t;
|
||||
typedef __u32 ext2_off_t;
|
||||
typedef __s64 e2_blkcnt_t;
|
||||
typedef __u32 ext2_dirhash_t;
|
||||
|
||||
#include "ext2_io.h"
|
||||
#include "ext2_err.h"
|
||||
|
||||
typedef struct struct_ext2_filsys *ext2_filsys;
|
||||
|
||||
struct ext2fs_struct_generic_bitmap {
|
||||
errcode_t magic;
|
||||
ext2_filsys fs;
|
||||
__u32 start, end;
|
||||
__u32 real_end;
|
||||
char * description;
|
||||
char * bitmap;
|
||||
errcode_t base_error_code;
|
||||
__u32 reserved[7];
|
||||
};
|
||||
|
||||
#define EXT2FS_MARK_ERROR 0
|
||||
#define EXT2FS_UNMARK_ERROR 1
|
||||
#define EXT2FS_TEST_ERROR 2
|
||||
|
||||
typedef struct ext2fs_struct_generic_bitmap *ext2fs_generic_bitmap;
|
||||
typedef struct ext2fs_struct_generic_bitmap *ext2fs_inode_bitmap;
|
||||
typedef struct ext2fs_struct_generic_bitmap *ext2fs_block_bitmap;
|
||||
|
||||
#define EXT2_FIRST_INODE(s) EXT2_FIRST_INO(s)
|
||||
|
||||
/*
|
||||
* badblocks list definitions
|
||||
*/
|
||||
|
||||
typedef struct ext2_struct_u32_list *ext2_badblocks_list;
|
||||
typedef struct ext2_struct_u32_iterate *ext2_badblocks_iterate;
|
||||
|
||||
typedef struct ext2_struct_u32_list *ext2_u32_list;
|
||||
typedef struct ext2_struct_u32_iterate *ext2_u32_iterate;
|
||||
|
||||
/* old */
|
||||
typedef struct ext2_struct_u32_list *badblocks_list;
|
||||
typedef struct ext2_struct_u32_iterate *badblocks_iterate;
|
||||
|
||||
#define BADBLOCKS_FLAG_DIRTY 1
|
||||
|
||||
/*
|
||||
* ext2_dblist structure and abstractions (see dblist.c)
|
||||
*/
|
||||
struct ext2_db_entry {
|
||||
ext2_ino_t ino;
|
||||
blk_t blk;
|
||||
int blockcnt;
|
||||
};
|
||||
|
||||
typedef struct ext2_struct_dblist *ext2_dblist;
|
||||
|
||||
#define DBLIST_ABORT 1
|
||||
|
||||
/*
|
||||
* ext2_fileio definitions
|
||||
*/
|
||||
|
||||
#define EXT2_FILE_WRITE 0x0001
|
||||
#define EXT2_FILE_CREATE 0x0002
|
||||
|
||||
#define EXT2_FILE_MASK 0x00FF
|
||||
|
||||
#define EXT2_FILE_BUF_DIRTY 0x4000
|
||||
#define EXT2_FILE_BUF_VALID 0x2000
|
||||
|
||||
typedef struct ext2_file *ext2_file_t;
|
||||
|
||||
#define EXT2_SEEK_SET 0
|
||||
#define EXT2_SEEK_CUR 1
|
||||
#define EXT2_SEEK_END 2
|
||||
|
||||
/*
|
||||
* Flags for the ext2_filsys structure and for ext2fs_open()
|
||||
*/
|
||||
#define EXT2_FLAG_RW 0x01
|
||||
#define EXT2_FLAG_CHANGED 0x02
|
||||
#define EXT2_FLAG_DIRTY 0x04
|
||||
#define EXT2_FLAG_VALID 0x08
|
||||
#define EXT2_FLAG_IB_DIRTY 0x10
|
||||
#define EXT2_FLAG_BB_DIRTY 0x20
|
||||
#define EXT2_FLAG_SWAP_BYTES 0x40
|
||||
#define EXT2_FLAG_SWAP_BYTES_READ 0x80
|
||||
#define EXT2_FLAG_SWAP_BYTES_WRITE 0x100
|
||||
#define EXT2_FLAG_MASTER_SB_ONLY 0x200
|
||||
#define EXT2_FLAG_FORCE 0x400
|
||||
#define EXT2_FLAG_SUPER_ONLY 0x800
|
||||
#define EXT2_FLAG_JOURNAL_DEV_OK 0x1000
|
||||
#define EXT2_FLAG_IMAGE_FILE 0x2000
|
||||
|
||||
/*
|
||||
* Special flag in the ext2 inode i_flag field that means that this is
|
||||
* a new inode. (So that ext2_write_inode() can clear extra fields.)
|
||||
*/
|
||||
#define EXT2_NEW_INODE_FL 0x80000000
|
||||
|
||||
/*
|
||||
* Flags for mkjournal
|
||||
*
|
||||
* EXT2_MKJOURNAL_V1_SUPER Make a (deprecated) V1 journal superblock
|
||||
*/
|
||||
#define EXT2_MKJOURNAL_V1_SUPER 0x0000001
|
||||
|
||||
struct struct_ext2_filsys {
|
||||
errcode_t magic;
|
||||
io_channel io;
|
||||
int flags;
|
||||
char * device_name;
|
||||
struct ext2_super_block * super;
|
||||
unsigned int blocksize;
|
||||
int fragsize;
|
||||
dgrp_t group_desc_count;
|
||||
unsigned long desc_blocks;
|
||||
struct ext2_group_desc * group_desc;
|
||||
int inode_blocks_per_group;
|
||||
ext2fs_inode_bitmap inode_map;
|
||||
ext2fs_block_bitmap block_map;
|
||||
errcode_t (*get_blocks)(ext2_filsys fs, ext2_ino_t ino, blk_t *blocks);
|
||||
errcode_t (*check_directory)(ext2_filsys fs, ext2_ino_t ino);
|
||||
errcode_t (*write_bitmaps)(ext2_filsys fs);
|
||||
errcode_t (*read_inode)(ext2_filsys fs, ext2_ino_t ino,
|
||||
struct ext2_inode *inode);
|
||||
errcode_t (*write_inode)(ext2_filsys fs, ext2_ino_t ino,
|
||||
struct ext2_inode *inode);
|
||||
ext2_badblocks_list badblocks;
|
||||
ext2_dblist dblist;
|
||||
__u32 stride; /* for mke2fs */
|
||||
struct ext2_super_block * orig_super;
|
||||
struct ext2_image_hdr * image_header;
|
||||
__u32 umask;
|
||||
/*
|
||||
* Reserved for future expansion
|
||||
*/
|
||||
__u32 reserved[8];
|
||||
|
||||
/*
|
||||
* Reserved for the use of the calling application.
|
||||
*/
|
||||
void * priv_data;
|
||||
|
||||
/*
|
||||
* Inode cache
|
||||
*/
|
||||
struct ext2_inode_cache *icache;
|
||||
io_channel image_io;
|
||||
};
|
||||
|
||||
#include "bitops.h"
|
||||
|
||||
/*
|
||||
* Return flags for the block iterator functions
|
||||
*/
|
||||
#define BLOCK_CHANGED 1
|
||||
#define BLOCK_ABORT 2
|
||||
#define BLOCK_ERROR 4
|
||||
|
||||
/*
|
||||
* Block interate flags
|
||||
*
|
||||
* BLOCK_FLAG_APPEND, or BLOCK_FLAG_HOLE, indicates that the interator
|
||||
* function should be called on blocks where the block number is zero.
|
||||
* This is used by ext2fs_expand_dir() to be able to add a new block
|
||||
* to an inode. It can also be used for programs that want to be able
|
||||
* to deal with files that contain "holes".
|
||||
*
|
||||
* BLOCK_FLAG_TRAVERSE indicates that the iterator function for the
|
||||
* indirect, doubly indirect, etc. blocks should be called after all
|
||||
* of the blocks containined in the indirect blocks are processed.
|
||||
* This is useful if you are going to be deallocating blocks from an
|
||||
* inode.
|
||||
*
|
||||
* BLOCK_FLAG_DATA_ONLY indicates that the iterator function should be
|
||||
* called for data blocks only.
|
||||
*
|
||||
* BLOCK_FLAG_NO_LARGE is for internal use only. It informs
|
||||
* ext2fs_block_iterate2 that large files won't be accepted.
|
||||
*/
|
||||
#define BLOCK_FLAG_APPEND 1
|
||||
#define BLOCK_FLAG_HOLE 1
|
||||
#define BLOCK_FLAG_DEPTH_TRAVERSE 2
|
||||
#define BLOCK_FLAG_DATA_ONLY 4
|
||||
|
||||
#define BLOCK_FLAG_NO_LARGE 0x1000
|
||||
|
||||
/*
|
||||
* Magic "block count" return values for the block iterator function.
|
||||
*/
|
||||
#define BLOCK_COUNT_IND (-1)
|
||||
#define BLOCK_COUNT_DIND (-2)
|
||||
#define BLOCK_COUNT_TIND (-3)
|
||||
#define BLOCK_COUNT_TRANSLATOR (-4)
|
||||
|
||||
#if 0
|
||||
/*
|
||||
* Flags for ext2fs_move_blocks
|
||||
*/
|
||||
#define EXT2_BMOVE_GET_DBLIST 0x0001
|
||||
#define EXT2_BMOVE_DEBUG 0x0002
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Flags for directory block reading and writing functions
|
||||
*/
|
||||
#define EXT2_DIRBLOCK_V2_STRUCT 0x0001
|
||||
|
||||
/*
|
||||
* Return flags for the directory iterator functions
|
||||
*/
|
||||
#define DIRENT_CHANGED 1
|
||||
#define DIRENT_ABORT 2
|
||||
#define DIRENT_ERROR 3
|
||||
|
||||
/*
|
||||
* Directory iterator flags
|
||||
*/
|
||||
|
||||
#define DIRENT_FLAG_INCLUDE_EMPTY 1
|
||||
#define DIRENT_FLAG_INCLUDE_REMOVED 2
|
||||
|
||||
#define DIRENT_DOT_FILE 1
|
||||
#define DIRENT_DOT_DOT_FILE 2
|
||||
#define DIRENT_OTHER_FILE 3
|
||||
#define DIRENT_DELETED_FILE 4
|
||||
|
||||
/*
|
||||
* Inode scan definitions
|
||||
*/
|
||||
typedef struct ext2_struct_inode_scan *ext2_inode_scan;
|
||||
|
||||
/*
|
||||
* ext2fs_scan flags
|
||||
*/
|
||||
#define EXT2_SF_CHK_BADBLOCKS 0x0001
|
||||
#define EXT2_SF_BAD_INODE_BLK 0x0002
|
||||
#define EXT2_SF_BAD_EXTRA_BYTES 0x0004
|
||||
#define EXT2_SF_SKIP_MISSING_ITABLE 0x0008
|
||||
|
||||
/*
|
||||
* ext2fs_check_if_mounted flags
|
||||
*/
|
||||
#define EXT2_MF_MOUNTED 1
|
||||
#define EXT2_MF_ISROOT 2
|
||||
#define EXT2_MF_READONLY 4
|
||||
#define EXT2_MF_SWAP 8
|
||||
#define EXT2_MF_BUSY 16
|
||||
|
||||
/*
|
||||
* Ext2/linux mode flags. We define them here so that we don't need
|
||||
* to depend on the OS's sys/stat.h, since we may be compiling on a
|
||||
* non-Linux system.
|
||||
*/
|
||||
#define LINUX_S_IFMT 00170000
|
||||
#define LINUX_S_IFSOCK 0140000
|
||||
#define LINUX_S_IFLNK 0120000
|
||||
#define LINUX_S_IFREG 0100000
|
||||
#define LINUX_S_IFBLK 0060000
|
||||
#define LINUX_S_IFDIR 0040000
|
||||
#define LINUX_S_IFCHR 0020000
|
||||
#define LINUX_S_IFIFO 0010000
|
||||
#define LINUX_S_ISUID 0004000
|
||||
#define LINUX_S_ISGID 0002000
|
||||
#define LINUX_S_ISVTX 0001000
|
||||
|
||||
#define LINUX_S_IRWXU 00700
|
||||
#define LINUX_S_IRUSR 00400
|
||||
#define LINUX_S_IWUSR 00200
|
||||
#define LINUX_S_IXUSR 00100
|
||||
|
||||
#define LINUX_S_IRWXG 00070
|
||||
#define LINUX_S_IRGRP 00040
|
||||
#define LINUX_S_IWGRP 00020
|
||||
#define LINUX_S_IXGRP 00010
|
||||
|
||||
#define LINUX_S_IRWXO 00007
|
||||
#define LINUX_S_IROTH 00004
|
||||
#define LINUX_S_IWOTH 00002
|
||||
#define LINUX_S_IXOTH 00001
|
||||
|
||||
#define LINUX_S_ISLNK(m) (((m) & LINUX_S_IFMT) == LINUX_S_IFLNK)
|
||||
#define LINUX_S_ISREG(m) (((m) & LINUX_S_IFMT) == LINUX_S_IFREG)
|
||||
#define LINUX_S_ISDIR(m) (((m) & LINUX_S_IFMT) == LINUX_S_IFDIR)
|
||||
#define LINUX_S_ISCHR(m) (((m) & LINUX_S_IFMT) == LINUX_S_IFCHR)
|
||||
#define LINUX_S_ISBLK(m) (((m) & LINUX_S_IFMT) == LINUX_S_IFBLK)
|
||||
#define LINUX_S_ISFIFO(m) (((m) & LINUX_S_IFMT) == LINUX_S_IFIFO)
|
||||
#define LINUX_S_ISSOCK(m) (((m) & LINUX_S_IFMT) == LINUX_S_IFSOCK)
|
||||
|
||||
/*
|
||||
* ext2 size of an inode
|
||||
*/
|
||||
#define EXT2_I_SIZE(i) ((i)->i_size | ((__u64) (i)->i_size_high << 32))
|
||||
|
||||
/*
|
||||
* ext2_icount_t abstraction
|
||||
*/
|
||||
#define EXT2_ICOUNT_OPT_INCREMENT 0x01
|
||||
|
||||
typedef struct ext2_icount *ext2_icount_t;
|
||||
|
||||
/*
|
||||
* Flags for ext2fs_bmap
|
||||
*/
|
||||
#define BMAP_ALLOC 0x0001
|
||||
#define BMAP_SET 0x0002
|
||||
|
||||
/*
|
||||
* Flags for imager.c functions
|
||||
*/
|
||||
#define IMAGER_FLAG_INODEMAP 1
|
||||
#define IMAGER_FLAG_SPARSEWRITE 2
|
||||
|
||||
/*
|
||||
* For checking structure magic numbers...
|
||||
*/
|
||||
|
||||
#define EXT2_CHECK_MAGIC(struct, code) \
|
||||
if ((struct)->magic != (code)) return (code)
|
||||
|
||||
|
||||
/*
|
||||
* For ext2 compression support
|
||||
*/
|
||||
#define EXT2FS_COMPRESSED_BLKADDR ((blk_t) 0xffffffff)
|
||||
#define HOLE_BLKADDR(_b) ((_b) == 0 || (_b) == EXT2FS_COMPRESSED_BLKADDR)
|
||||
|
||||
/*
|
||||
* Features supported by this version of the library
|
||||
*/
|
||||
#define EXT2_LIB_FEATURE_COMPAT_SUPP (EXT2_FEATURE_COMPAT_DIR_PREALLOC|\
|
||||
EXT2_FEATURE_COMPAT_IMAGIC_INODES|\
|
||||
EXT3_FEATURE_COMPAT_HAS_JOURNAL|\
|
||||
EXT2_FEATURE_COMPAT_RESIZE_INODE|\
|
||||
EXT2_FEATURE_COMPAT_DIR_INDEX|\
|
||||
EXT2_FEATURE_COMPAT_EXT_ATTR)
|
||||
|
||||
/* This #ifdef is temporary until compression is fully supported */
|
||||
#ifdef ENABLE_COMPRESSION
|
||||
#ifndef I_KNOW_THAT_COMPRESSION_IS_EXPERIMENTAL
|
||||
/* If the below warning bugs you, then have
|
||||
`CPPFLAGS=-DI_KNOW_THAT_COMPRESSION_IS_EXPERIMENTAL' in your
|
||||
environment at configure time. */
|
||||
#warning "Compression support is experimental"
|
||||
#endif
|
||||
#define EXT2_LIB_FEATURE_INCOMPAT_SUPP (EXT2_FEATURE_INCOMPAT_FILETYPE|\
|
||||
EXT2_FEATURE_INCOMPAT_COMPRESSION|\
|
||||
EXT3_FEATURE_INCOMPAT_JOURNAL_DEV|\
|
||||
EXT2_FEATURE_INCOMPAT_META_BG|\
|
||||
EXT3_FEATURE_INCOMPAT_RECOVER)
|
||||
#else
|
||||
#define EXT2_LIB_FEATURE_INCOMPAT_SUPP (EXT2_FEATURE_INCOMPAT_FILETYPE|\
|
||||
EXT3_FEATURE_INCOMPAT_JOURNAL_DEV|\
|
||||
EXT2_FEATURE_INCOMPAT_META_BG|\
|
||||
EXT3_FEATURE_INCOMPAT_RECOVER)
|
||||
#endif
|
||||
#define EXT2_LIB_FEATURE_RO_COMPAT_SUPP (EXT2_FEATURE_RO_COMPAT_SPARSE_SUPER|\
|
||||
EXT2_FEATURE_RO_COMPAT_LARGE_FILE)
|
||||
/*
|
||||
* function prototypes
|
||||
*/
|
||||
|
||||
/* alloc.c */
|
||||
extern errcode_t ext2fs_new_inode(ext2_filsys fs, ext2_ino_t dir, int mode,
|
||||
ext2fs_inode_bitmap map, ext2_ino_t *ret);
|
||||
extern errcode_t ext2fs_new_block(ext2_filsys fs, blk_t goal,
|
||||
ext2fs_block_bitmap map, blk_t *ret);
|
||||
extern errcode_t ext2fs_get_free_blocks(ext2_filsys fs, blk_t start,
|
||||
blk_t finish, int num,
|
||||
ext2fs_block_bitmap map,
|
||||
blk_t *ret);
|
||||
extern errcode_t ext2fs_alloc_block(ext2_filsys fs, blk_t goal,
|
||||
char *block_buf, blk_t *ret);
|
||||
|
||||
/* alloc_sb.c */
|
||||
extern int ext2fs_reserve_super_and_bgd(ext2_filsys fs,
|
||||
dgrp_t group,
|
||||
ext2fs_block_bitmap bmap);
|
||||
|
||||
/* alloc_stats.c */
|
||||
void ext2fs_inode_alloc_stats(ext2_filsys fs, ext2_ino_t ino, int inuse);
|
||||
void ext2fs_inode_alloc_stats2(ext2_filsys fs, ext2_ino_t ino,
|
||||
int inuse, int isdir);
|
||||
void ext2fs_block_alloc_stats(ext2_filsys fs, blk_t blk, int inuse);
|
||||
|
||||
/* alloc_tables.c */
|
||||
extern errcode_t ext2fs_allocate_tables(ext2_filsys fs);
|
||||
extern errcode_t ext2fs_allocate_group_table(ext2_filsys fs, dgrp_t group,
|
||||
ext2fs_block_bitmap bmap);
|
||||
|
||||
/* badblocks.c */
|
||||
extern errcode_t ext2fs_u32_list_create(ext2_u32_list *ret, int size);
|
||||
extern errcode_t ext2fs_u32_list_add(ext2_u32_list bb, __u32 blk);
|
||||
extern int ext2fs_u32_list_find(ext2_u32_list bb, __u32 blk);
|
||||
extern int ext2fs_u32_list_test(ext2_u32_list bb, blk_t blk);
|
||||
extern errcode_t ext2fs_u32_list_iterate_begin(ext2_u32_list bb,
|
||||
ext2_u32_iterate *ret);
|
||||
extern int ext2fs_u32_list_iterate(ext2_u32_iterate iter, blk_t *blk);
|
||||
extern void ext2fs_u32_list_iterate_end(ext2_u32_iterate iter);
|
||||
extern errcode_t ext2fs_u32_copy(ext2_u32_list src, ext2_u32_list *dest);
|
||||
extern int ext2fs_u32_list_equal(ext2_u32_list bb1, ext2_u32_list bb2);
|
||||
|
||||
extern errcode_t ext2fs_badblocks_list_create(ext2_badblocks_list *ret,
|
||||
int size);
|
||||
extern errcode_t ext2fs_badblocks_list_add(ext2_badblocks_list bb,
|
||||
blk_t blk);
|
||||
extern int ext2fs_badblocks_list_test(ext2_badblocks_list bb,
|
||||
blk_t blk);
|
||||
extern int ext2fs_u32_list_del(ext2_u32_list bb, __u32 blk);
|
||||
extern void ext2fs_badblocks_list_del(ext2_u32_list bb, __u32 blk);
|
||||
extern errcode_t
|
||||
ext2fs_badblocks_list_iterate_begin(ext2_badblocks_list bb,
|
||||
ext2_badblocks_iterate *ret);
|
||||
extern int ext2fs_badblocks_list_iterate(ext2_badblocks_iterate iter,
|
||||
blk_t *blk);
|
||||
extern void ext2fs_badblocks_list_iterate_end(ext2_badblocks_iterate iter);
|
||||
extern errcode_t ext2fs_badblocks_copy(ext2_badblocks_list src,
|
||||
ext2_badblocks_list *dest);
|
||||
extern int ext2fs_badblocks_equal(ext2_badblocks_list bb1,
|
||||
ext2_badblocks_list bb2);
|
||||
extern int ext2fs_u32_list_count(ext2_u32_list bb);
|
||||
|
||||
/* bb_compat */
|
||||
extern errcode_t badblocks_list_create(badblocks_list *ret, int size);
|
||||
extern errcode_t badblocks_list_add(badblocks_list bb, blk_t blk);
|
||||
extern int badblocks_list_test(badblocks_list bb, blk_t blk);
|
||||
extern errcode_t badblocks_list_iterate_begin(badblocks_list bb,
|
||||
badblocks_iterate *ret);
|
||||
extern int badblocks_list_iterate(badblocks_iterate iter, blk_t *blk);
|
||||
extern void badblocks_list_iterate_end(badblocks_iterate iter);
|
||||
extern void badblocks_list_free(badblocks_list bb);
|
||||
|
||||
/* bb_inode.c */
|
||||
extern errcode_t ext2fs_update_bb_inode(ext2_filsys fs,
|
||||
ext2_badblocks_list bb_list);
|
||||
|
||||
/* bitmaps.c */
|
||||
extern errcode_t ext2fs_write_inode_bitmap(ext2_filsys fs);
|
||||
extern errcode_t ext2fs_write_block_bitmap (ext2_filsys fs);
|
||||
extern errcode_t ext2fs_read_inode_bitmap (ext2_filsys fs);
|
||||
extern errcode_t ext2fs_read_block_bitmap(ext2_filsys fs);
|
||||
extern errcode_t ext2fs_allocate_generic_bitmap(__u32 start,
|
||||
__u32 end,
|
||||
__u32 real_end,
|
||||
const char *descr,
|
||||
ext2fs_generic_bitmap *ret);
|
||||
extern errcode_t ext2fs_allocate_block_bitmap(ext2_filsys fs,
|
||||
const char *descr,
|
||||
ext2fs_block_bitmap *ret);
|
||||
extern errcode_t ext2fs_allocate_inode_bitmap(ext2_filsys fs,
|
||||
const char *descr,
|
||||
ext2fs_inode_bitmap *ret);
|
||||
extern errcode_t ext2fs_fudge_inode_bitmap_end(ext2fs_inode_bitmap bitmap,
|
||||
ext2_ino_t end, ext2_ino_t *oend);
|
||||
extern errcode_t ext2fs_fudge_block_bitmap_end(ext2fs_block_bitmap bitmap,
|
||||
blk_t end, blk_t *oend);
|
||||
extern void ext2fs_clear_inode_bitmap(ext2fs_inode_bitmap bitmap);
|
||||
extern void ext2fs_clear_block_bitmap(ext2fs_block_bitmap bitmap);
|
||||
extern errcode_t ext2fs_read_bitmaps(ext2_filsys fs);
|
||||
extern errcode_t ext2fs_write_bitmaps(ext2_filsys fs);
|
||||
|
||||
/* block.c */
|
||||
extern errcode_t ext2fs_block_iterate(ext2_filsys fs,
|
||||
ext2_ino_t ino,
|
||||
int flags,
|
||||
char *block_buf,
|
||||
int (*func)(ext2_filsys fs,
|
||||
blk_t *blocknr,
|
||||
int blockcnt,
|
||||
void *priv_data),
|
||||
void *priv_data);
|
||||
errcode_t ext2fs_block_iterate2(ext2_filsys fs,
|
||||
ext2_ino_t ino,
|
||||
int flags,
|
||||
char *block_buf,
|
||||
int (*func)(ext2_filsys fs,
|
||||
blk_t *blocknr,
|
||||
e2_blkcnt_t blockcnt,
|
||||
blk_t ref_blk,
|
||||
int ref_offset,
|
||||
void *priv_data),
|
||||
void *priv_data);
|
||||
|
||||
/* bmap.c */
|
||||
extern errcode_t ext2fs_bmap(ext2_filsys fs, ext2_ino_t ino,
|
||||
struct ext2_inode *inode,
|
||||
char *block_buf, int bmap_flags,
|
||||
blk_t block, blk_t *phys_blk);
|
||||
|
||||
|
||||
#if 0
|
||||
/* bmove.c */
|
||||
extern errcode_t ext2fs_move_blocks(ext2_filsys fs,
|
||||
ext2fs_block_bitmap reserve,
|
||||
ext2fs_block_bitmap alloc_map,
|
||||
int flags);
|
||||
#endif
|
||||
|
||||
/* check_desc.c */
|
||||
extern errcode_t ext2fs_check_desc(ext2_filsys fs);
|
||||
|
||||
/* closefs.c */
|
||||
extern errcode_t ext2fs_close(ext2_filsys fs);
|
||||
extern errcode_t ext2fs_flush(ext2_filsys fs);
|
||||
extern int ext2fs_bg_has_super(ext2_filsys fs, int group_block);
|
||||
extern int ext2fs_super_and_bgd_loc(ext2_filsys fs,
|
||||
dgrp_t group,
|
||||
blk_t *ret_super_blk,
|
||||
blk_t *ret_old_desc_blk,
|
||||
blk_t *ret_new_desc_blk,
|
||||
int *ret_meta_bg);
|
||||
extern void ext2fs_update_dynamic_rev(ext2_filsys fs);
|
||||
|
||||
/* cmp_bitmaps.c */
|
||||
extern errcode_t ext2fs_compare_block_bitmap(ext2fs_block_bitmap bm1,
|
||||
ext2fs_block_bitmap bm2);
|
||||
extern errcode_t ext2fs_compare_inode_bitmap(ext2fs_inode_bitmap bm1,
|
||||
ext2fs_inode_bitmap bm2);
|
||||
|
||||
/* dblist.c */
|
||||
|
||||
extern errcode_t ext2fs_get_num_dirs(ext2_filsys fs, ext2_ino_t *ret_num_dirs);
|
||||
extern errcode_t ext2fs_init_dblist(ext2_filsys fs, ext2_dblist *ret_dblist);
|
||||
extern errcode_t ext2fs_add_dir_block(ext2_dblist dblist, ext2_ino_t ino,
|
||||
blk_t blk, int blockcnt);
|
||||
extern void ext2fs_dblist_sort(ext2_dblist dblist,
|
||||
int (*sortfunc)(const void *,
|
||||
const void *));
|
||||
extern errcode_t ext2fs_dblist_iterate(ext2_dblist dblist,
|
||||
int (*func)(ext2_filsys fs, struct ext2_db_entry *db_info,
|
||||
void *priv_data),
|
||||
void *priv_data);
|
||||
extern errcode_t ext2fs_set_dir_block(ext2_dblist dblist, ext2_ino_t ino,
|
||||
blk_t blk, int blockcnt);
|
||||
extern errcode_t ext2fs_copy_dblist(ext2_dblist src,
|
||||
ext2_dblist *dest);
|
||||
extern int ext2fs_dblist_count(ext2_dblist dblist);
|
||||
|
||||
/* dblist_dir.c */
|
||||
extern errcode_t
|
||||
ext2fs_dblist_dir_iterate(ext2_dblist dblist,
|
||||
int flags,
|
||||
char *block_buf,
|
||||
int (*func)(ext2_ino_t dir,
|
||||
int entry,
|
||||
struct ext2_dir_entry *dirent,
|
||||
int offset,
|
||||
int blocksize,
|
||||
char *buf,
|
||||
void *priv_data),
|
||||
void *priv_data);
|
||||
|
||||
/* dirblock.c */
|
||||
extern errcode_t ext2fs_read_dir_block(ext2_filsys fs, blk_t block,
|
||||
void *buf);
|
||||
extern errcode_t ext2fs_read_dir_block2(ext2_filsys fs, blk_t block,
|
||||
void *buf, int flags);
|
||||
extern errcode_t ext2fs_write_dir_block(ext2_filsys fs, blk_t block,
|
||||
void *buf);
|
||||
extern errcode_t ext2fs_write_dir_block2(ext2_filsys fs, blk_t block,
|
||||
void *buf, int flags);
|
||||
|
||||
/* dirhash.c */
|
||||
extern errcode_t ext2fs_dirhash(int version, const char *name, int len,
|
||||
const __u32 *seed,
|
||||
ext2_dirhash_t *ret_hash,
|
||||
ext2_dirhash_t *ret_minor_hash);
|
||||
|
||||
|
||||
/* dir_iterate.c */
|
||||
extern errcode_t ext2fs_dir_iterate(ext2_filsys fs,
|
||||
ext2_ino_t dir,
|
||||
int flags,
|
||||
char *block_buf,
|
||||
int (*func)(struct ext2_dir_entry *dirent,
|
||||
int offset,
|
||||
int blocksize,
|
||||
char *buf,
|
||||
void *priv_data),
|
||||
void *priv_data);
|
||||
extern errcode_t ext2fs_dir_iterate2(ext2_filsys fs,
|
||||
ext2_ino_t dir,
|
||||
int flags,
|
||||
char *block_buf,
|
||||
int (*func)(ext2_ino_t dir,
|
||||
int entry,
|
||||
struct ext2_dir_entry *dirent,
|
||||
int offset,
|
||||
int blocksize,
|
||||
char *buf,
|
||||
void *priv_data),
|
||||
void *priv_data);
|
||||
|
||||
/* dupfs.c */
|
||||
extern errcode_t ext2fs_dup_handle(ext2_filsys src, ext2_filsys *dest);
|
||||
|
||||
/* expanddir.c */
|
||||
extern errcode_t ext2fs_expand_dir(ext2_filsys fs, ext2_ino_t dir);
|
||||
|
||||
/* ext_attr.c */
|
||||
extern errcode_t ext2fs_read_ext_attr(ext2_filsys fs, blk_t block, void *buf);
|
||||
extern errcode_t ext2fs_write_ext_attr(ext2_filsys fs, blk_t block,
|
||||
void *buf);
|
||||
extern errcode_t ext2fs_adjust_ea_refcount(ext2_filsys fs, blk_t blk,
|
||||
char *block_buf,
|
||||
int adjust, __u32 *newcount);
|
||||
|
||||
/* fileio.c */
|
||||
extern errcode_t ext2fs_file_open2(ext2_filsys fs, ext2_ino_t ino,
|
||||
struct ext2_inode *inode,
|
||||
int flags, ext2_file_t *ret);
|
||||
extern errcode_t ext2fs_file_open(ext2_filsys fs, ext2_ino_t ino,
|
||||
int flags, ext2_file_t *ret);
|
||||
extern ext2_filsys ext2fs_file_get_fs(ext2_file_t file);
|
||||
extern errcode_t ext2fs_file_close(ext2_file_t file);
|
||||
extern errcode_t ext2fs_file_flush(ext2_file_t file);
|
||||
extern errcode_t ext2fs_file_read(ext2_file_t file, void *buf,
|
||||
unsigned int wanted, unsigned int *got);
|
||||
extern errcode_t ext2fs_file_write(ext2_file_t file, const void *buf,
|
||||
unsigned int nbytes, unsigned int *written);
|
||||
extern errcode_t ext2fs_file_llseek(ext2_file_t file, __u64 offset,
|
||||
int whence, __u64 *ret_pos);
|
||||
extern errcode_t ext2fs_file_lseek(ext2_file_t file, ext2_off_t offset,
|
||||
int whence, ext2_off_t *ret_pos);
|
||||
errcode_t ext2fs_file_get_lsize(ext2_file_t file, __u64 *ret_size);
|
||||
extern ext2_off_t ext2fs_file_get_size(ext2_file_t file);
|
||||
extern errcode_t ext2fs_file_set_size(ext2_file_t file, ext2_off_t size);
|
||||
|
||||
/* finddev.c */
|
||||
extern char *ext2fs_find_block_device(dev_t device);
|
||||
|
||||
/* flushb.c */
|
||||
extern errcode_t ext2fs_sync_device(int fd, int flushb);
|
||||
|
||||
/* freefs.c */
|
||||
extern void ext2fs_free(ext2_filsys fs);
|
||||
extern void ext2fs_free_generic_bitmap(ext2fs_inode_bitmap bitmap);
|
||||
extern void ext2fs_free_block_bitmap(ext2fs_block_bitmap bitmap);
|
||||
extern void ext2fs_free_inode_bitmap(ext2fs_inode_bitmap bitmap);
|
||||
extern void ext2fs_free_dblist(ext2_dblist dblist);
|
||||
extern void ext2fs_badblocks_list_free(ext2_badblocks_list bb);
|
||||
extern void ext2fs_u32_list_free(ext2_u32_list bb);
|
||||
|
||||
/* getsize.c */
|
||||
extern errcode_t ext2fs_get_device_size(const char *file, int blocksize,
|
||||
blk_t *retblocks);
|
||||
|
||||
/* getsectsize.c */
|
||||
errcode_t ext2fs_get_device_sectsize(const char *file, int *sectsize);
|
||||
|
||||
/* imager.c */
|
||||
extern errcode_t ext2fs_image_inode_write(ext2_filsys fs, int fd, int flags);
|
||||
extern errcode_t ext2fs_image_inode_read(ext2_filsys fs, int fd, int flags);
|
||||
extern errcode_t ext2fs_image_super_write(ext2_filsys fs, int fd, int flags);
|
||||
extern errcode_t ext2fs_image_super_read(ext2_filsys fs, int fd, int flags);
|
||||
extern errcode_t ext2fs_image_bitmap_write(ext2_filsys fs, int fd, int flags);
|
||||
extern errcode_t ext2fs_image_bitmap_read(ext2_filsys fs, int fd, int flags);
|
||||
|
||||
/* ind_block.c */
|
||||
errcode_t ext2fs_read_ind_block(ext2_filsys fs, blk_t blk, void *buf);
|
||||
errcode_t ext2fs_write_ind_block(ext2_filsys fs, blk_t blk, void *buf);
|
||||
|
||||
/* initialize.c */
|
||||
extern errcode_t ext2fs_initialize(const char *name, int flags,
|
||||
struct ext2_super_block *param,
|
||||
io_manager manager, ext2_filsys *ret_fs);
|
||||
|
||||
/* icount.c */
|
||||
extern void ext2fs_free_icount(ext2_icount_t icount);
|
||||
extern errcode_t ext2fs_create_icount2(ext2_filsys fs, int flags,
|
||||
unsigned int size,
|
||||
ext2_icount_t hint, ext2_icount_t *ret);
|
||||
extern errcode_t ext2fs_create_icount(ext2_filsys fs, int flags,
|
||||
unsigned int size,
|
||||
ext2_icount_t *ret);
|
||||
extern errcode_t ext2fs_icount_fetch(ext2_icount_t icount, ext2_ino_t ino,
|
||||
__u16 *ret);
|
||||
extern errcode_t ext2fs_icount_increment(ext2_icount_t icount, ext2_ino_t ino,
|
||||
__u16 *ret);
|
||||
extern errcode_t ext2fs_icount_decrement(ext2_icount_t icount, ext2_ino_t ino,
|
||||
__u16 *ret);
|
||||
extern errcode_t ext2fs_icount_store(ext2_icount_t icount, ext2_ino_t ino,
|
||||
__u16 count);
|
||||
extern ext2_ino_t ext2fs_get_icount_size(ext2_icount_t icount);
|
||||
errcode_t ext2fs_icount_validate(ext2_icount_t icount, FILE *);
|
||||
|
||||
/* inode.c */
|
||||
extern errcode_t ext2fs_flush_icache(ext2_filsys fs);
|
||||
extern errcode_t ext2fs_get_next_inode_full(ext2_inode_scan scan,
|
||||
ext2_ino_t *ino,
|
||||
struct ext2_inode *inode,
|
||||
int bufsize);
|
||||
extern errcode_t ext2fs_open_inode_scan(ext2_filsys fs, int buffer_blocks,
|
||||
ext2_inode_scan *ret_scan);
|
||||
extern void ext2fs_close_inode_scan(ext2_inode_scan scan);
|
||||
extern errcode_t ext2fs_get_next_inode(ext2_inode_scan scan, ext2_ino_t *ino,
|
||||
struct ext2_inode *inode);
|
||||
extern errcode_t ext2fs_inode_scan_goto_blockgroup(ext2_inode_scan scan,
|
||||
int group);
|
||||
extern void ext2fs_set_inode_callback
|
||||
(ext2_inode_scan scan,
|
||||
errcode_t (*done_group)(ext2_filsys fs,
|
||||
dgrp_t group,
|
||||
void * priv_data),
|
||||
void *done_group_data);
|
||||
extern int ext2fs_inode_scan_flags(ext2_inode_scan scan, int set_flags,
|
||||
int clear_flags);
|
||||
extern errcode_t ext2fs_read_inode_full(ext2_filsys fs, ext2_ino_t ino,
|
||||
struct ext2_inode * inode,
|
||||
int bufsize);
|
||||
extern errcode_t ext2fs_read_inode (ext2_filsys fs, ext2_ino_t ino,
|
||||
struct ext2_inode * inode);
|
||||
extern errcode_t ext2fs_write_inode_full(ext2_filsys fs, ext2_ino_t ino,
|
||||
struct ext2_inode * inode,
|
||||
int bufsize);
|
||||
extern errcode_t ext2fs_write_inode(ext2_filsys fs, ext2_ino_t ino,
|
||||
struct ext2_inode * inode);
|
||||
extern errcode_t ext2fs_write_new_inode(ext2_filsys fs, ext2_ino_t ino,
|
||||
struct ext2_inode * inode);
|
||||
extern errcode_t ext2fs_get_blocks(ext2_filsys fs, ext2_ino_t ino, blk_t *blocks);
|
||||
extern errcode_t ext2fs_check_directory(ext2_filsys fs, ext2_ino_t ino);
|
||||
|
||||
/* inode_io.c */
|
||||
extern io_manager inode_io_manager;
|
||||
extern errcode_t ext2fs_inode_io_intern(ext2_filsys fs, ext2_ino_t ino,
|
||||
char **name);
|
||||
extern errcode_t ext2fs_inode_io_intern2(ext2_filsys fs, ext2_ino_t ino,
|
||||
struct ext2_inode *inode,
|
||||
char **name);
|
||||
|
||||
/* ismounted.c */
|
||||
extern errcode_t ext2fs_check_if_mounted(const char *file, int *mount_flags);
|
||||
extern errcode_t ext2fs_check_mount_point(const char *device, int *mount_flags,
|
||||
char *mtpt, int mtlen);
|
||||
|
||||
/* namei.c */
|
||||
extern errcode_t ext2fs_lookup(ext2_filsys fs, ext2_ino_t dir, const char *name,
|
||||
int namelen, char *buf, ext2_ino_t *inode);
|
||||
extern errcode_t ext2fs_namei(ext2_filsys fs, ext2_ino_t root, ext2_ino_t cwd,
|
||||
const char *name, ext2_ino_t *inode);
|
||||
errcode_t ext2fs_namei_follow(ext2_filsys fs, ext2_ino_t root, ext2_ino_t cwd,
|
||||
const char *name, ext2_ino_t *inode);
|
||||
extern errcode_t ext2fs_follow_link(ext2_filsys fs, ext2_ino_t root, ext2_ino_t cwd,
|
||||
ext2_ino_t inode, ext2_ino_t *res_inode);
|
||||
|
||||
/* native.c */
|
||||
int ext2fs_native_flag(void);
|
||||
|
||||
/* newdir.c */
|
||||
extern errcode_t ext2fs_new_dir_block(ext2_filsys fs, ext2_ino_t dir_ino,
|
||||
ext2_ino_t parent_ino, char **block);
|
||||
|
||||
/* mkdir.c */
|
||||
extern errcode_t ext2fs_mkdir(ext2_filsys fs, ext2_ino_t parent, ext2_ino_t inum,
|
||||
const char *name);
|
||||
|
||||
/* mkjournal.c */
|
||||
extern errcode_t ext2fs_create_journal_superblock(ext2_filsys fs,
|
||||
__u32 size, int flags,
|
||||
char **ret_jsb);
|
||||
extern errcode_t ext2fs_add_journal_device(ext2_filsys fs,
|
||||
ext2_filsys journal_dev);
|
||||
extern errcode_t ext2fs_add_journal_inode(ext2_filsys fs, blk_t size,
|
||||
int flags);
|
||||
|
||||
/* openfs.c */
|
||||
extern errcode_t ext2fs_open(const char *name, int flags, int superblock,
|
||||
unsigned int block_size, io_manager manager,
|
||||
ext2_filsys *ret_fs);
|
||||
extern errcode_t ext2fs_open2(const char *name, const char *io_options,
|
||||
int flags, int superblock,
|
||||
unsigned int block_size, io_manager manager,
|
||||
ext2_filsys *ret_fs);
|
||||
extern blk_t ext2fs_descriptor_block_loc(ext2_filsys fs, blk_t group_block,
|
||||
dgrp_t i);
|
||||
errcode_t ext2fs_get_data_io(ext2_filsys fs, io_channel *old_io);
|
||||
errcode_t ext2fs_set_data_io(ext2_filsys fs, io_channel new_io);
|
||||
errcode_t ext2fs_rewrite_to_io(ext2_filsys fs, io_channel new_io);
|
||||
|
||||
/* get_pathname.c */
|
||||
extern errcode_t ext2fs_get_pathname(ext2_filsys fs, ext2_ino_t dir, ext2_ino_t ino,
|
||||
char **name);
|
||||
|
||||
/* link.c */
|
||||
errcode_t ext2fs_link(ext2_filsys fs, ext2_ino_t dir, const char *name,
|
||||
ext2_ino_t ino, int flags);
|
||||
errcode_t ext2fs_unlink(ext2_filsys fs, ext2_ino_t dir, const char *name,
|
||||
ext2_ino_t ino, int flags);
|
||||
|
||||
/* read_bb.c */
|
||||
extern errcode_t ext2fs_read_bb_inode(ext2_filsys fs,
|
||||
ext2_badblocks_list *bb_list);
|
||||
|
||||
/* read_bb_file.c */
|
||||
extern errcode_t ext2fs_read_bb_FILE2(ext2_filsys fs, FILE *f,
|
||||
ext2_badblocks_list *bb_list,
|
||||
void *priv_data,
|
||||
void (*invalid)(ext2_filsys fs,
|
||||
blk_t blk,
|
||||
char *badstr,
|
||||
void *priv_data));
|
||||
extern errcode_t ext2fs_read_bb_FILE(ext2_filsys fs, FILE *f,
|
||||
ext2_badblocks_list *bb_list,
|
||||
void (*invalid)(ext2_filsys fs,
|
||||
blk_t blk));
|
||||
|
||||
/* res_gdt.c */
|
||||
extern errcode_t ext2fs_create_resize_inode(ext2_filsys fs);
|
||||
|
||||
/* rs_bitmap.c */
|
||||
extern errcode_t ext2fs_resize_generic_bitmap(__u32 new_end,
|
||||
__u32 new_real_end,
|
||||
ext2fs_generic_bitmap bmap);
|
||||
extern errcode_t ext2fs_resize_inode_bitmap(__u32 new_end, __u32 new_real_end,
|
||||
ext2fs_inode_bitmap bmap);
|
||||
extern errcode_t ext2fs_resize_block_bitmap(__u32 new_end, __u32 new_real_end,
|
||||
ext2fs_block_bitmap bmap);
|
||||
extern errcode_t ext2fs_copy_bitmap(ext2fs_generic_bitmap src,
|
||||
ext2fs_generic_bitmap *dest);
|
||||
|
||||
/* swapfs.c */
|
||||
extern void ext2fs_swap_ext_attr(char *to, char *from, int bufsize,
|
||||
int has_header);
|
||||
extern void ext2fs_swap_super(struct ext2_super_block * super);
|
||||
extern void ext2fs_swap_group_desc(struct ext2_group_desc *gdp);
|
||||
extern void ext2fs_swap_inode_full(ext2_filsys fs, struct ext2_inode_large *t,
|
||||
struct ext2_inode_large *f, int hostorder,
|
||||
int bufsize);
|
||||
extern void ext2fs_swap_inode(ext2_filsys fs,struct ext2_inode *t,
|
||||
struct ext2_inode *f, int hostorder);
|
||||
|
||||
/* valid_blk.c */
|
||||
extern int ext2fs_inode_has_valid_blocks(struct ext2_inode *inode);
|
||||
|
||||
/* version.c */
|
||||
extern int ext2fs_parse_version_string(const char *ver_string);
|
||||
extern int ext2fs_get_library_version(const char **ver_string,
|
||||
const char **date_string);
|
||||
|
||||
/* write_bb_file.c */
|
||||
extern errcode_t ext2fs_write_bb_FILE(ext2_badblocks_list bb_list,
|
||||
unsigned int flags,
|
||||
FILE *f);
|
||||
|
||||
|
||||
/* inline functions */
|
||||
extern errcode_t ext2fs_get_mem(unsigned long size, void *ptr);
|
||||
extern errcode_t ext2fs_free_mem(void *ptr);
|
||||
extern errcode_t ext2fs_resize_mem(unsigned long old_size,
|
||||
unsigned long size, void *ptr);
|
||||
extern void ext2fs_mark_super_dirty(ext2_filsys fs);
|
||||
extern void ext2fs_mark_changed(ext2_filsys fs);
|
||||
extern int ext2fs_test_changed(ext2_filsys fs);
|
||||
extern void ext2fs_mark_valid(ext2_filsys fs);
|
||||
extern void ext2fs_unmark_valid(ext2_filsys fs);
|
||||
extern int ext2fs_test_valid(ext2_filsys fs);
|
||||
extern void ext2fs_mark_ib_dirty(ext2_filsys fs);
|
||||
extern void ext2fs_mark_bb_dirty(ext2_filsys fs);
|
||||
extern int ext2fs_test_ib_dirty(ext2_filsys fs);
|
||||
extern int ext2fs_test_bb_dirty(ext2_filsys fs);
|
||||
extern int ext2fs_group_of_blk(ext2_filsys fs, blk_t blk);
|
||||
extern int ext2fs_group_of_ino(ext2_filsys fs, ext2_ino_t ino);
|
||||
extern blk_t ext2fs_inode_data_blocks(ext2_filsys fs,
|
||||
struct ext2_inode *inode);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* _EXT2FS_EXT2FS_H */
|
89
e2fsprogs/old_e2fsprogs/ext2fs/ext2fsP.h
Normal file
89
e2fsprogs/old_e2fsprogs/ext2fs/ext2fsP.h
Normal file
@ -0,0 +1,89 @@
|
||||
/* vi: set sw=4 ts=4: */
|
||||
/*
|
||||
* ext2fsP.h --- private header file for ext2 library
|
||||
*
|
||||
* Copyright (C) 1997 Theodore Ts'o.
|
||||
*
|
||||
* %Begin-Header%
|
||||
* This file may be redistributed under the terms of the GNU Public
|
||||
* License.
|
||||
* %End-Header%
|
||||
*/
|
||||
|
||||
#include "ext2fs.h"
|
||||
|
||||
/*
|
||||
* Badblocks list
|
||||
*/
|
||||
struct ext2_struct_u32_list {
|
||||
int magic;
|
||||
int num;
|
||||
int size;
|
||||
__u32 *list;
|
||||
int badblocks_flags;
|
||||
};
|
||||
|
||||
struct ext2_struct_u32_iterate {
|
||||
int magic;
|
||||
ext2_u32_list bb;
|
||||
int ptr;
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
* Directory block iterator definition
|
||||
*/
|
||||
struct ext2_struct_dblist {
|
||||
int magic;
|
||||
ext2_filsys fs;
|
||||
ext2_ino_t size;
|
||||
ext2_ino_t count;
|
||||
int sorted;
|
||||
struct ext2_db_entry * list;
|
||||
};
|
||||
|
||||
/*
|
||||
* For directory iterators
|
||||
*/
|
||||
struct dir_context {
|
||||
ext2_ino_t dir;
|
||||
int flags;
|
||||
char *buf;
|
||||
int (*func)(ext2_ino_t dir,
|
||||
int entry,
|
||||
struct ext2_dir_entry *dirent,
|
||||
int offset,
|
||||
int blocksize,
|
||||
char *buf,
|
||||
void *priv_data);
|
||||
void *priv_data;
|
||||
errcode_t errcode;
|
||||
};
|
||||
|
||||
/*
|
||||
* Inode cache structure
|
||||
*/
|
||||
struct ext2_inode_cache {
|
||||
void * buffer;
|
||||
blk_t buffer_blk;
|
||||
int cache_last;
|
||||
int cache_size;
|
||||
int refcount;
|
||||
struct ext2_inode_cache_ent *cache;
|
||||
};
|
||||
|
||||
struct ext2_inode_cache_ent {
|
||||
ext2_ino_t ino;
|
||||
struct ext2_inode inode;
|
||||
};
|
||||
|
||||
/* Function prototypes */
|
||||
|
||||
extern int ext2fs_process_dir_block(ext2_filsys fs,
|
||||
blk_t *blocknr,
|
||||
e2_blkcnt_t blockcnt,
|
||||
blk_t ref_block,
|
||||
int ref_offset,
|
||||
void *priv_data);
|
||||
|
||||
|
367
e2fsprogs/old_e2fsprogs/ext2fs/ext2fs_inline.c
Normal file
367
e2fsprogs/old_e2fsprogs/ext2fs/ext2fs_inline.c
Normal file
@ -0,0 +1,367 @@
|
||||
/* vi: set sw=4 ts=4: */
|
||||
/*
|
||||
* ext2fs.h --- ext2fs
|
||||
*
|
||||
* Copyright (C) 1993, 1994, 1995, 1996 Theodore Ts'o.
|
||||
*
|
||||
* %Begin-Header%
|
||||
* This file may be redistributed under the terms of the GNU Public
|
||||
* License.
|
||||
* %End-Header%
|
||||
*/
|
||||
|
||||
#include "ext2fs.h"
|
||||
#include "bitops.h"
|
||||
#include <string.h>
|
||||
|
||||
/*
|
||||
* Allocate memory
|
||||
*/
|
||||
errcode_t ext2fs_get_mem(unsigned long size, void *ptr)
|
||||
{
|
||||
void **pp = (void **)ptr;
|
||||
|
||||
*pp = malloc(size);
|
||||
if (!*pp)
|
||||
return EXT2_ET_NO_MEMORY;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Free memory
|
||||
*/
|
||||
errcode_t ext2fs_free_mem(void *ptr)
|
||||
{
|
||||
void **pp = (void **)ptr;
|
||||
|
||||
free(*pp);
|
||||
*pp = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Resize memory
|
||||
*/
|
||||
errcode_t ext2fs_resize_mem(unsigned long EXT2FS_ATTR((unused)) old_size,
|
||||
unsigned long size, void *ptr)
|
||||
{
|
||||
void *p;
|
||||
|
||||
/* Use "memcpy" for pointer assignments here to avoid problems
|
||||
* with C99 strict type aliasing rules. */
|
||||
memcpy(&p, ptr, sizeof (p));
|
||||
p = realloc(p, size);
|
||||
if (!p)
|
||||
return EXT2_ET_NO_MEMORY;
|
||||
memcpy(ptr, &p, sizeof (p));
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Mark a filesystem superblock as dirty
|
||||
*/
|
||||
void ext2fs_mark_super_dirty(ext2_filsys fs)
|
||||
{
|
||||
fs->flags |= EXT2_FLAG_DIRTY | EXT2_FLAG_CHANGED;
|
||||
}
|
||||
|
||||
/*
|
||||
* Mark a filesystem as changed
|
||||
*/
|
||||
void ext2fs_mark_changed(ext2_filsys fs)
|
||||
{
|
||||
fs->flags |= EXT2_FLAG_CHANGED;
|
||||
}
|
||||
|
||||
/*
|
||||
* Check to see if a filesystem has changed
|
||||
*/
|
||||
int ext2fs_test_changed(ext2_filsys fs)
|
||||
{
|
||||
return (fs->flags & EXT2_FLAG_CHANGED);
|
||||
}
|
||||
|
||||
/*
|
||||
* Mark a filesystem as valid
|
||||
*/
|
||||
void ext2fs_mark_valid(ext2_filsys fs)
|
||||
{
|
||||
fs->flags |= EXT2_FLAG_VALID;
|
||||
}
|
||||
|
||||
/*
|
||||
* Mark a filesystem as NOT valid
|
||||
*/
|
||||
void ext2fs_unmark_valid(ext2_filsys fs)
|
||||
{
|
||||
fs->flags &= ~EXT2_FLAG_VALID;
|
||||
}
|
||||
|
||||
/*
|
||||
* Check to see if a filesystem is valid
|
||||
*/
|
||||
int ext2fs_test_valid(ext2_filsys fs)
|
||||
{
|
||||
return (fs->flags & EXT2_FLAG_VALID);
|
||||
}
|
||||
|
||||
/*
|
||||
* Mark the inode bitmap as dirty
|
||||
*/
|
||||
void ext2fs_mark_ib_dirty(ext2_filsys fs)
|
||||
{
|
||||
fs->flags |= EXT2_FLAG_IB_DIRTY | EXT2_FLAG_CHANGED;
|
||||
}
|
||||
|
||||
/*
|
||||
* Mark the block bitmap as dirty
|
||||
*/
|
||||
void ext2fs_mark_bb_dirty(ext2_filsys fs)
|
||||
{
|
||||
fs->flags |= EXT2_FLAG_BB_DIRTY | EXT2_FLAG_CHANGED;
|
||||
}
|
||||
|
||||
/*
|
||||
* Check to see if a filesystem's inode bitmap is dirty
|
||||
*/
|
||||
int ext2fs_test_ib_dirty(ext2_filsys fs)
|
||||
{
|
||||
return (fs->flags & EXT2_FLAG_IB_DIRTY);
|
||||
}
|
||||
|
||||
/*
|
||||
* Check to see if a filesystem's block bitmap is dirty
|
||||
*/
|
||||
int ext2fs_test_bb_dirty(ext2_filsys fs)
|
||||
{
|
||||
return (fs->flags & EXT2_FLAG_BB_DIRTY);
|
||||
}
|
||||
|
||||
/*
|
||||
* Return the group # of a block
|
||||
*/
|
||||
int ext2fs_group_of_blk(ext2_filsys fs, blk_t blk)
|
||||
{
|
||||
return (blk - fs->super->s_first_data_block) /
|
||||
fs->super->s_blocks_per_group;
|
||||
}
|
||||
|
||||
/*
|
||||
* Return the group # of an inode number
|
||||
*/
|
||||
int ext2fs_group_of_ino(ext2_filsys fs, ext2_ino_t ino)
|
||||
{
|
||||
return (ino - 1) / fs->super->s_inodes_per_group;
|
||||
}
|
||||
|
||||
blk_t ext2fs_inode_data_blocks(ext2_filsys fs,
|
||||
struct ext2_inode *inode)
|
||||
{
|
||||
return inode->i_blocks -
|
||||
(inode->i_file_acl ? fs->blocksize >> 9 : 0);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
__u16 ext2fs_swab16(__u16 val)
|
||||
{
|
||||
return (val >> 8) | (val << 8);
|
||||
}
|
||||
|
||||
__u32 ext2fs_swab32(__u32 val)
|
||||
{
|
||||
return ((val>>24) | ((val>>8)&0xFF00) |
|
||||
((val<<8)&0xFF0000) | (val<<24));
|
||||
}
|
||||
|
||||
int ext2fs_test_generic_bitmap(ext2fs_generic_bitmap bitmap,
|
||||
blk_t bitno);
|
||||
|
||||
int ext2fs_test_generic_bitmap(ext2fs_generic_bitmap bitmap,
|
||||
blk_t bitno)
|
||||
{
|
||||
if ((bitno < bitmap->start) || (bitno > bitmap->end)) {
|
||||
ext2fs_warn_bitmap2(bitmap, EXT2FS_TEST_ERROR, bitno);
|
||||
return 0;
|
||||
}
|
||||
return ext2fs_test_bit(bitno - bitmap->start, bitmap->bitmap);
|
||||
}
|
||||
|
||||
int ext2fs_mark_block_bitmap(ext2fs_block_bitmap bitmap,
|
||||
blk_t block)
|
||||
{
|
||||
return ext2fs_mark_generic_bitmap((ext2fs_generic_bitmap)
|
||||
bitmap,
|
||||
block);
|
||||
}
|
||||
|
||||
int ext2fs_unmark_block_bitmap(ext2fs_block_bitmap bitmap,
|
||||
blk_t block)
|
||||
{
|
||||
return ext2fs_unmark_generic_bitmap((ext2fs_generic_bitmap) bitmap,
|
||||
block);
|
||||
}
|
||||
|
||||
int ext2fs_test_block_bitmap(ext2fs_block_bitmap bitmap,
|
||||
blk_t block)
|
||||
{
|
||||
return ext2fs_test_generic_bitmap((ext2fs_generic_bitmap) bitmap,
|
||||
block);
|
||||
}
|
||||
|
||||
int ext2fs_mark_inode_bitmap(ext2fs_inode_bitmap bitmap,
|
||||
ext2_ino_t inode)
|
||||
{
|
||||
return ext2fs_mark_generic_bitmap((ext2fs_generic_bitmap) bitmap,
|
||||
inode);
|
||||
}
|
||||
|
||||
int ext2fs_unmark_inode_bitmap(ext2fs_inode_bitmap bitmap,
|
||||
ext2_ino_t inode)
|
||||
{
|
||||
return ext2fs_unmark_generic_bitmap((ext2fs_generic_bitmap) bitmap,
|
||||
inode);
|
||||
}
|
||||
|
||||
int ext2fs_test_inode_bitmap(ext2fs_inode_bitmap bitmap,
|
||||
ext2_ino_t inode)
|
||||
{
|
||||
return ext2fs_test_generic_bitmap((ext2fs_generic_bitmap) bitmap,
|
||||
inode);
|
||||
}
|
||||
|
||||
void ext2fs_fast_mark_block_bitmap(ext2fs_block_bitmap bitmap,
|
||||
blk_t block)
|
||||
{
|
||||
ext2fs_set_bit(block - bitmap->start, bitmap->bitmap);
|
||||
}
|
||||
|
||||
void ext2fs_fast_unmark_block_bitmap(ext2fs_block_bitmap bitmap,
|
||||
blk_t block)
|
||||
{
|
||||
ext2fs_clear_bit(block - bitmap->start, bitmap->bitmap);
|
||||
}
|
||||
|
||||
int ext2fs_fast_test_block_bitmap(ext2fs_block_bitmap bitmap,
|
||||
blk_t block)
|
||||
{
|
||||
return ext2fs_test_bit(block - bitmap->start, bitmap->bitmap);
|
||||
}
|
||||
|
||||
void ext2fs_fast_mark_inode_bitmap(ext2fs_inode_bitmap bitmap,
|
||||
ext2_ino_t inode)
|
||||
{
|
||||
ext2fs_set_bit(inode - bitmap->start, bitmap->bitmap);
|
||||
}
|
||||
|
||||
void ext2fs_fast_unmark_inode_bitmap(ext2fs_inode_bitmap bitmap,
|
||||
ext2_ino_t inode)
|
||||
{
|
||||
ext2fs_clear_bit(inode - bitmap->start, bitmap->bitmap);
|
||||
}
|
||||
|
||||
int ext2fs_fast_test_inode_bitmap(ext2fs_inode_bitmap bitmap,
|
||||
ext2_ino_t inode)
|
||||
{
|
||||
return ext2fs_test_bit(inode - bitmap->start, bitmap->bitmap);
|
||||
}
|
||||
|
||||
blk_t ext2fs_get_block_bitmap_start(ext2fs_block_bitmap bitmap)
|
||||
{
|
||||
return bitmap->start;
|
||||
}
|
||||
|
||||
ext2_ino_t ext2fs_get_inode_bitmap_start(ext2fs_inode_bitmap bitmap)
|
||||
{
|
||||
return bitmap->start;
|
||||
}
|
||||
|
||||
blk_t ext2fs_get_block_bitmap_end(ext2fs_block_bitmap bitmap)
|
||||
{
|
||||
return bitmap->end;
|
||||
}
|
||||
|
||||
ext2_ino_t ext2fs_get_inode_bitmap_end(ext2fs_inode_bitmap bitmap)
|
||||
{
|
||||
return bitmap->end;
|
||||
}
|
||||
|
||||
int ext2fs_test_block_bitmap_range(ext2fs_block_bitmap bitmap,
|
||||
blk_t block, int num)
|
||||
{
|
||||
int i;
|
||||
|
||||
if ((block < bitmap->start) || (block+num-1 > bitmap->end)) {
|
||||
ext2fs_warn_bitmap(EXT2_ET_BAD_BLOCK_TEST,
|
||||
block, bitmap->description);
|
||||
return 0;
|
||||
}
|
||||
for (i=0; i < num; i++) {
|
||||
if (ext2fs_fast_test_block_bitmap(bitmap, block+i))
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
int ext2fs_fast_test_block_bitmap_range(ext2fs_block_bitmap bitmap,
|
||||
blk_t block, int num)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i=0; i < num; i++) {
|
||||
if (ext2fs_fast_test_block_bitmap(bitmap, block+i))
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
void ext2fs_mark_block_bitmap_range(ext2fs_block_bitmap bitmap,
|
||||
blk_t block, int num)
|
||||
{
|
||||
int i;
|
||||
|
||||
if ((block < bitmap->start) || (block+num-1 > bitmap->end)) {
|
||||
ext2fs_warn_bitmap(EXT2_ET_BAD_BLOCK_MARK, block,
|
||||
bitmap->description);
|
||||
return;
|
||||
}
|
||||
for (i=0; i < num; i++)
|
||||
ext2fs_set_bit(block + i - bitmap->start, bitmap->bitmap);
|
||||
}
|
||||
|
||||
void ext2fs_fast_mark_block_bitmap_range(ext2fs_block_bitmap bitmap,
|
||||
blk_t block, int num)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i=0; i < num; i++)
|
||||
ext2fs_set_bit(block + i - bitmap->start, bitmap->bitmap);
|
||||
}
|
||||
|
||||
void ext2fs_unmark_block_bitmap_range(ext2fs_block_bitmap bitmap,
|
||||
blk_t block, int num)
|
||||
{
|
||||
int i;
|
||||
|
||||
if ((block < bitmap->start) || (block+num-1 > bitmap->end)) {
|
||||
ext2fs_warn_bitmap(EXT2_ET_BAD_BLOCK_UNMARK, block,
|
||||
bitmap->description);
|
||||
return;
|
||||
}
|
||||
for (i=0; i < num; i++)
|
||||
ext2fs_clear_bit(block + i - bitmap->start, bitmap->bitmap);
|
||||
}
|
||||
|
||||
void ext2fs_fast_unmark_block_bitmap_range(ext2fs_block_bitmap bitmap,
|
||||
blk_t block, int num)
|
||||
{
|
||||
int i;
|
||||
for (i=0; i < num; i++)
|
||||
ext2fs_clear_bit(block + i - bitmap->start, bitmap->bitmap);
|
||||
}
|
101
e2fsprogs/old_e2fsprogs/ext2fs/ext_attr.c
Normal file
101
e2fsprogs/old_e2fsprogs/ext2fs/ext_attr.c
Normal file
@ -0,0 +1,101 @@
|
||||
/* vi: set sw=4 ts=4: */
|
||||
/*
|
||||
* ext_attr.c --- extended attribute blocks
|
||||
*
|
||||
* Copyright (C) 2001 Andreas Gruenbacher, <a.gruenbacher@computer.org>
|
||||
*
|
||||
* Copyright (C) 2002 Theodore Ts'o.
|
||||
*
|
||||
* %Begin-Header%
|
||||
* This file may be redistributed under the terms of the GNU Public
|
||||
* License.
|
||||
* %End-Header%
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <unistd.h>
|
||||
#include <string.h>
|
||||
#include <time.h>
|
||||
|
||||
#include "ext2_fs.h"
|
||||
#include "ext2_ext_attr.h"
|
||||
#include "ext2fs.h"
|
||||
|
||||
errcode_t ext2fs_read_ext_attr(ext2_filsys fs, blk_t block, void *buf)
|
||||
{
|
||||
errcode_t retval;
|
||||
|
||||
retval = io_channel_read_blk(fs->io, block, 1, buf);
|
||||
if (retval)
|
||||
return retval;
|
||||
#if BB_BIG_ENDIAN
|
||||
if ((fs->flags & (EXT2_FLAG_SWAP_BYTES|
|
||||
EXT2_FLAG_SWAP_BYTES_READ)) != 0)
|
||||
ext2fs_swap_ext_attr(buf, buf, fs->blocksize, 1);
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
errcode_t ext2fs_write_ext_attr(ext2_filsys fs, blk_t block, void *inbuf)
|
||||
{
|
||||
errcode_t retval;
|
||||
char *write_buf;
|
||||
char *buf = NULL;
|
||||
|
||||
if (BB_BIG_ENDIAN && ((fs->flags & EXT2_FLAG_SWAP_BYTES) ||
|
||||
(fs->flags & EXT2_FLAG_SWAP_BYTES_WRITE))) {
|
||||
retval = ext2fs_get_mem(fs->blocksize, &buf);
|
||||
if (retval)
|
||||
return retval;
|
||||
write_buf = buf;
|
||||
ext2fs_swap_ext_attr(buf, inbuf, fs->blocksize, 1);
|
||||
} else
|
||||
write_buf = (char *) inbuf;
|
||||
retval = io_channel_write_blk(fs->io, block, 1, write_buf);
|
||||
if (buf)
|
||||
ext2fs_free_mem(&buf);
|
||||
if (!retval)
|
||||
ext2fs_mark_changed(fs);
|
||||
return retval;
|
||||
}
|
||||
|
||||
/*
|
||||
* This function adjusts the reference count of the EA block.
|
||||
*/
|
||||
errcode_t ext2fs_adjust_ea_refcount(ext2_filsys fs, blk_t blk,
|
||||
char *block_buf, int adjust,
|
||||
__u32 *newcount)
|
||||
{
|
||||
errcode_t retval;
|
||||
struct ext2_ext_attr_header *header;
|
||||
char *buf = 0;
|
||||
|
||||
if ((blk >= fs->super->s_blocks_count) ||
|
||||
(blk < fs->super->s_first_data_block))
|
||||
return EXT2_ET_BAD_EA_BLOCK_NUM;
|
||||
|
||||
if (!block_buf) {
|
||||
retval = ext2fs_get_mem(fs->blocksize, &buf);
|
||||
if (retval)
|
||||
return retval;
|
||||
block_buf = buf;
|
||||
}
|
||||
|
||||
retval = ext2fs_read_ext_attr(fs, blk, block_buf);
|
||||
if (retval)
|
||||
goto errout;
|
||||
|
||||
header = (struct ext2_ext_attr_header *) block_buf;
|
||||
header->h_refcount += adjust;
|
||||
if (newcount)
|
||||
*newcount = header->h_refcount;
|
||||
|
||||
retval = ext2fs_write_ext_attr(fs, blk, block_buf);
|
||||
if (retval)
|
||||
goto errout;
|
||||
|
||||
errout:
|
||||
if (buf)
|
||||
ext2fs_free_mem(&buf);
|
||||
return retval;
|
||||
}
|
377
e2fsprogs/old_e2fsprogs/ext2fs/fileio.c
Normal file
377
e2fsprogs/old_e2fsprogs/ext2fs/fileio.c
Normal file
@ -0,0 +1,377 @@
|
||||
/* vi: set sw=4 ts=4: */
|
||||
/*
|
||||
* fileio.c --- Simple file I/O routines
|
||||
*
|
||||
* Copyright (C) 1997 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>
|
||||
#if HAVE_UNISTD_H
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
|
||||
#include "ext2_fs.h"
|
||||
#include "ext2fs.h"
|
||||
|
||||
struct ext2_file {
|
||||
errcode_t magic;
|
||||
ext2_filsys fs;
|
||||
ext2_ino_t ino;
|
||||
struct ext2_inode inode;
|
||||
int flags;
|
||||
__u64 pos;
|
||||
blk_t blockno;
|
||||
blk_t physblock;
|
||||
char *buf;
|
||||
};
|
||||
|
||||
#define BMAP_BUFFER (file->buf + fs->blocksize)
|
||||
|
||||
errcode_t ext2fs_file_open2(ext2_filsys fs, ext2_ino_t ino,
|
||||
struct ext2_inode *inode,
|
||||
int flags, ext2_file_t *ret)
|
||||
{
|
||||
ext2_file_t file;
|
||||
errcode_t retval;
|
||||
|
||||
/*
|
||||
* Don't let caller create or open a file for writing if the
|
||||
* filesystem is read-only.
|
||||
*/
|
||||
if ((flags & (EXT2_FILE_WRITE | EXT2_FILE_CREATE)) &&
|
||||
!(fs->flags & EXT2_FLAG_RW))
|
||||
return EXT2_ET_RO_FILSYS;
|
||||
|
||||
retval = ext2fs_get_mem(sizeof(struct ext2_file), &file);
|
||||
if (retval)
|
||||
return retval;
|
||||
|
||||
memset(file, 0, sizeof(struct ext2_file));
|
||||
file->magic = EXT2_ET_MAGIC_EXT2_FILE;
|
||||
file->fs = fs;
|
||||
file->ino = ino;
|
||||
file->flags = flags & EXT2_FILE_MASK;
|
||||
|
||||
if (inode) {
|
||||
memcpy(&file->inode, inode, sizeof(struct ext2_inode));
|
||||
} else {
|
||||
retval = ext2fs_read_inode(fs, ino, &file->inode);
|
||||
if (retval)
|
||||
goto fail;
|
||||
}
|
||||
|
||||
retval = ext2fs_get_mem(fs->blocksize * 3, &file->buf);
|
||||
if (retval)
|
||||
goto fail;
|
||||
|
||||
*ret = file;
|
||||
return 0;
|
||||
|
||||
fail:
|
||||
ext2fs_free_mem(&file->buf);
|
||||
ext2fs_free_mem(&file);
|
||||
return retval;
|
||||
}
|
||||
|
||||
errcode_t ext2fs_file_open(ext2_filsys fs, ext2_ino_t ino,
|
||||
int flags, ext2_file_t *ret)
|
||||
{
|
||||
return ext2fs_file_open2(fs, ino, NULL, flags, ret);
|
||||
}
|
||||
|
||||
/*
|
||||
* This function returns the filesystem handle of a file from the structure
|
||||
*/
|
||||
ext2_filsys ext2fs_file_get_fs(ext2_file_t file)
|
||||
{
|
||||
if (file->magic != EXT2_ET_MAGIC_EXT2_FILE)
|
||||
return 0;
|
||||
return file->fs;
|
||||
}
|
||||
|
||||
/*
|
||||
* This function flushes the dirty block buffer out to disk if
|
||||
* necessary.
|
||||
*/
|
||||
errcode_t ext2fs_file_flush(ext2_file_t file)
|
||||
{
|
||||
errcode_t retval;
|
||||
ext2_filsys fs;
|
||||
|
||||
EXT2_CHECK_MAGIC(file, EXT2_ET_MAGIC_EXT2_FILE);
|
||||
fs = file->fs;
|
||||
|
||||
if (!(file->flags & EXT2_FILE_BUF_VALID) ||
|
||||
!(file->flags & EXT2_FILE_BUF_DIRTY))
|
||||
return 0;
|
||||
|
||||
/*
|
||||
* OK, the physical block hasn't been allocated yet.
|
||||
* Allocate it.
|
||||
*/
|
||||
if (!file->physblock) {
|
||||
retval = ext2fs_bmap(fs, file->ino, &file->inode,
|
||||
BMAP_BUFFER, file->ino ? BMAP_ALLOC : 0,
|
||||
file->blockno, &file->physblock);
|
||||
if (retval)
|
||||
return retval;
|
||||
}
|
||||
|
||||
retval = io_channel_write_blk(fs->io, file->physblock,
|
||||
1, file->buf);
|
||||
if (retval)
|
||||
return retval;
|
||||
|
||||
file->flags &= ~EXT2_FILE_BUF_DIRTY;
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
/*
|
||||
* This function synchronizes the file's block buffer and the current
|
||||
* file position, possibly invalidating block buffer if necessary
|
||||
*/
|
||||
static errcode_t sync_buffer_position(ext2_file_t file)
|
||||
{
|
||||
blk_t b;
|
||||
errcode_t retval;
|
||||
|
||||
b = file->pos / file->fs->blocksize;
|
||||
if (b != file->blockno) {
|
||||
retval = ext2fs_file_flush(file);
|
||||
if (retval)
|
||||
return retval;
|
||||
file->flags &= ~EXT2_FILE_BUF_VALID;
|
||||
}
|
||||
file->blockno = b;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* This function loads the file's block buffer with valid data from
|
||||
* the disk as necessary.
|
||||
*
|
||||
* If dontfill is true, then skip initializing the buffer since we're
|
||||
* going to be replacing its entire contents anyway. If set, then the
|
||||
* function basically only sets file->physblock and EXT2_FILE_BUF_VALID
|
||||
*/
|
||||
#define DONTFILL 1
|
||||
static errcode_t load_buffer(ext2_file_t file, int dontfill)
|
||||
{
|
||||
ext2_filsys fs = file->fs;
|
||||
errcode_t retval;
|
||||
|
||||
if (!(file->flags & EXT2_FILE_BUF_VALID)) {
|
||||
retval = ext2fs_bmap(fs, file->ino, &file->inode,
|
||||
BMAP_BUFFER, 0, file->blockno,
|
||||
&file->physblock);
|
||||
if (retval)
|
||||
return retval;
|
||||
if (!dontfill) {
|
||||
if (file->physblock) {
|
||||
retval = io_channel_read_blk(fs->io,
|
||||
file->physblock,
|
||||
1, file->buf);
|
||||
if (retval)
|
||||
return retval;
|
||||
} else
|
||||
memset(file->buf, 0, fs->blocksize);
|
||||
}
|
||||
file->flags |= EXT2_FILE_BUF_VALID;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
errcode_t ext2fs_file_close(ext2_file_t file)
|
||||
{
|
||||
errcode_t retval;
|
||||
|
||||
EXT2_CHECK_MAGIC(file, EXT2_ET_MAGIC_EXT2_FILE);
|
||||
|
||||
retval = ext2fs_file_flush(file);
|
||||
|
||||
ext2fs_free_mem(&file->buf);
|
||||
ext2fs_free_mem(&file);
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
|
||||
errcode_t ext2fs_file_read(ext2_file_t file, void *buf,
|
||||
unsigned int wanted, unsigned int *got)
|
||||
{
|
||||
ext2_filsys fs;
|
||||
errcode_t retval = 0;
|
||||
unsigned int start, c, count = 0;
|
||||
__u64 left;
|
||||
char *ptr = (char *) buf;
|
||||
|
||||
EXT2_CHECK_MAGIC(file, EXT2_ET_MAGIC_EXT2_FILE);
|
||||
fs = file->fs;
|
||||
|
||||
while ((file->pos < EXT2_I_SIZE(&file->inode)) && (wanted > 0)) {
|
||||
retval = sync_buffer_position(file);
|
||||
if (retval)
|
||||
goto fail;
|
||||
retval = load_buffer(file, 0);
|
||||
if (retval)
|
||||
goto fail;
|
||||
|
||||
start = file->pos % fs->blocksize;
|
||||
c = fs->blocksize - start;
|
||||
if (c > wanted)
|
||||
c = wanted;
|
||||
left = EXT2_I_SIZE(&file->inode) - file->pos ;
|
||||
if (c > left)
|
||||
c = left;
|
||||
|
||||
memcpy(ptr, file->buf+start, c);
|
||||
file->pos += c;
|
||||
ptr += c;
|
||||
count += c;
|
||||
wanted -= c;
|
||||
}
|
||||
|
||||
fail:
|
||||
if (got)
|
||||
*got = count;
|
||||
return retval;
|
||||
}
|
||||
|
||||
|
||||
errcode_t ext2fs_file_write(ext2_file_t file, const void *buf,
|
||||
unsigned int nbytes, unsigned int *written)
|
||||
{
|
||||
ext2_filsys fs;
|
||||
errcode_t retval = 0;
|
||||
unsigned int start, c, count = 0;
|
||||
const char *ptr = (const char *) buf;
|
||||
|
||||
EXT2_CHECK_MAGIC(file, EXT2_ET_MAGIC_EXT2_FILE);
|
||||
fs = file->fs;
|
||||
|
||||
if (!(file->flags & EXT2_FILE_WRITE))
|
||||
return EXT2_ET_FILE_RO;
|
||||
|
||||
while (nbytes > 0) {
|
||||
retval = sync_buffer_position(file);
|
||||
if (retval)
|
||||
goto fail;
|
||||
|
||||
start = file->pos % fs->blocksize;
|
||||
c = fs->blocksize - start;
|
||||
if (c > nbytes)
|
||||
c = nbytes;
|
||||
|
||||
/*
|
||||
* We only need to do a read-modify-update cycle if
|
||||
* we're doing a partial write.
|
||||
*/
|
||||
retval = load_buffer(file, (c == fs->blocksize));
|
||||
if (retval)
|
||||
goto fail;
|
||||
|
||||
file->flags |= EXT2_FILE_BUF_DIRTY;
|
||||
memcpy(file->buf+start, ptr, c);
|
||||
file->pos += c;
|
||||
ptr += c;
|
||||
count += c;
|
||||
nbytes -= c;
|
||||
}
|
||||
|
||||
fail:
|
||||
if (written)
|
||||
*written = count;
|
||||
return retval;
|
||||
}
|
||||
|
||||
errcode_t ext2fs_file_llseek(ext2_file_t file, __u64 offset,
|
||||
int whence, __u64 *ret_pos)
|
||||
{
|
||||
EXT2_CHECK_MAGIC(file, EXT2_ET_MAGIC_EXT2_FILE);
|
||||
|
||||
if (whence == EXT2_SEEK_SET)
|
||||
file->pos = offset;
|
||||
else if (whence == EXT2_SEEK_CUR)
|
||||
file->pos += offset;
|
||||
else if (whence == EXT2_SEEK_END)
|
||||
file->pos = EXT2_I_SIZE(&file->inode) + offset;
|
||||
else
|
||||
return EXT2_ET_INVALID_ARGUMENT;
|
||||
|
||||
if (ret_pos)
|
||||
*ret_pos = file->pos;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
errcode_t ext2fs_file_lseek(ext2_file_t file, ext2_off_t offset,
|
||||
int whence, ext2_off_t *ret_pos)
|
||||
{
|
||||
__u64 loffset, ret_loffset;
|
||||
errcode_t retval;
|
||||
|
||||
loffset = offset;
|
||||
retval = ext2fs_file_llseek(file, loffset, whence, &ret_loffset);
|
||||
if (ret_pos)
|
||||
*ret_pos = (ext2_off_t) ret_loffset;
|
||||
return retval;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* This function returns the size of the file, according to the inode
|
||||
*/
|
||||
errcode_t ext2fs_file_get_lsize(ext2_file_t file, __u64 *ret_size)
|
||||
{
|
||||
if (file->magic != EXT2_ET_MAGIC_EXT2_FILE)
|
||||
return EXT2_ET_MAGIC_EXT2_FILE;
|
||||
*ret_size = EXT2_I_SIZE(&file->inode);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* This function returns the size of the file, according to the inode
|
||||
*/
|
||||
ext2_off_t ext2fs_file_get_size(ext2_file_t file)
|
||||
{
|
||||
__u64 size;
|
||||
|
||||
if (ext2fs_file_get_lsize(file, &size))
|
||||
return 0;
|
||||
if ((size >> 32) != 0)
|
||||
return 0;
|
||||
return size;
|
||||
}
|
||||
|
||||
/*
|
||||
* This function sets the size of the file, truncating it if necessary
|
||||
*
|
||||
* XXX still need to call truncate
|
||||
*/
|
||||
errcode_t ext2fs_file_set_size(ext2_file_t file, ext2_off_t size)
|
||||
{
|
||||
errcode_t retval;
|
||||
EXT2_CHECK_MAGIC(file, EXT2_ET_MAGIC_EXT2_FILE);
|
||||
|
||||
file->inode.i_size = size;
|
||||
file->inode.i_size_high = 0;
|
||||
if (file->ino) {
|
||||
retval = ext2fs_write_inode(file->fs, file->ino, &file->inode);
|
||||
if (retval)
|
||||
return retval;
|
||||
}
|
||||
|
||||
/*
|
||||
* XXX truncate inode if necessary
|
||||
*/
|
||||
|
||||
return 0;
|
||||
}
|
199
e2fsprogs/old_e2fsprogs/ext2fs/finddev.c
Normal file
199
e2fsprogs/old_e2fsprogs/ext2fs/finddev.c
Normal file
@ -0,0 +1,199 @@
|
||||
/* vi: set sw=4 ts=4: */
|
||||
/*
|
||||
* finddev.c -- this routine attempts to find a particular device in
|
||||
* /dev
|
||||
*
|
||||
* Copyright (C) 2000 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>
|
||||
#ifdef HAVE_UNISTD_H
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#ifdef HAVE_SYS_TYPES_H
|
||||
#include <sys/types.h>
|
||||
#endif
|
||||
#ifdef HAVE_SYS_STAT_H
|
||||
#include <sys/stat.h>
|
||||
#endif
|
||||
#include <dirent.h>
|
||||
#ifdef HAVE_ERRNO_H
|
||||
#include <errno.h>
|
||||
#endif
|
||||
#ifdef HAVE_SYS_MKDEV_H
|
||||
#include <sys/mkdev.h>
|
||||
#endif
|
||||
|
||||
#include "ext2_fs.h"
|
||||
#include "ext2fs.h"
|
||||
|
||||
struct dir_list {
|
||||
char *name;
|
||||
struct dir_list *next;
|
||||
};
|
||||
|
||||
/*
|
||||
* This function adds an entry to the directory list
|
||||
*/
|
||||
static void add_to_dirlist(const char *name, struct dir_list **list)
|
||||
{
|
||||
struct dir_list *dp;
|
||||
|
||||
dp = xmalloc(sizeof(struct dir_list));
|
||||
dp->name = xmalloc(strlen(name)+1);
|
||||
strcpy(dp->name, name);
|
||||
dp->next = *list;
|
||||
*list = dp;
|
||||
}
|
||||
|
||||
/*
|
||||
* This function frees a directory list
|
||||
*/
|
||||
static void free_dirlist(struct dir_list **list)
|
||||
{
|
||||
struct dir_list *dp, *next;
|
||||
|
||||
for (dp = *list; dp; dp = next) {
|
||||
next = dp->next;
|
||||
free(dp->name);
|
||||
free(dp);
|
||||
}
|
||||
*list = 0;
|
||||
}
|
||||
|
||||
static int scan_dir(char *dir_name, dev_t device, struct dir_list **list,
|
||||
char **ret_path)
|
||||
{
|
||||
DIR *dir;
|
||||
struct dirent *dp;
|
||||
char path[1024], *cp;
|
||||
int dirlen;
|
||||
struct stat st;
|
||||
|
||||
dirlen = strlen(dir_name);
|
||||
if ((dir = opendir(dir_name)) == NULL)
|
||||
return errno;
|
||||
dp = readdir(dir);
|
||||
while (dp) {
|
||||
if (dirlen + strlen(dp->d_name) + 2 >= sizeof(path))
|
||||
goto skip_to_next;
|
||||
if (dp->d_name[0] == '.' &&
|
||||
((dp->d_name[1] == 0) ||
|
||||
((dp->d_name[1] == '.') && (dp->d_name[2] == 0))))
|
||||
goto skip_to_next;
|
||||
sprintf(path, "%s/%s", dir_name, dp->d_name);
|
||||
if (stat(path, &st) < 0)
|
||||
goto skip_to_next;
|
||||
if (S_ISDIR(st.st_mode))
|
||||
add_to_dirlist(path, list);
|
||||
if (S_ISBLK(st.st_mode) && st.st_rdev == device) {
|
||||
cp = xmalloc(strlen(path)+1);
|
||||
strcpy(cp, path);
|
||||
*ret_path = cp;
|
||||
goto success;
|
||||
}
|
||||
skip_to_next:
|
||||
dp = readdir(dir);
|
||||
}
|
||||
success:
|
||||
closedir(dir);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* This function finds the pathname to a block device with a given
|
||||
* device number. It returns a pointer to allocated memory to the
|
||||
* pathname on success, and NULL on failure.
|
||||
*/
|
||||
char *ext2fs_find_block_device(dev_t device)
|
||||
{
|
||||
struct dir_list *list = 0, *new_list = 0;
|
||||
struct dir_list *current;
|
||||
char *ret_path = 0;
|
||||
|
||||
/*
|
||||
* Add the starting directories to search...
|
||||
*/
|
||||
add_to_dirlist("/devices", &list);
|
||||
add_to_dirlist("/devfs", &list);
|
||||
add_to_dirlist("/dev", &list);
|
||||
|
||||
while (list) {
|
||||
current = list;
|
||||
list = list->next;
|
||||
#ifdef DEBUG
|
||||
printf("Scanning directory %s\n", current->name);
|
||||
#endif
|
||||
scan_dir(current->name, device, &new_list, &ret_path);
|
||||
free(current->name);
|
||||
free(current);
|
||||
if (ret_path)
|
||||
break;
|
||||
/*
|
||||
* If we're done checking at this level, descend to
|
||||
* the next level of subdirectories. (breadth-first)
|
||||
*/
|
||||
if (list == 0) {
|
||||
list = new_list;
|
||||
new_list = 0;
|
||||
}
|
||||
}
|
||||
free_dirlist(&list);
|
||||
free_dirlist(&new_list);
|
||||
return ret_path;
|
||||
}
|
||||
|
||||
|
||||
#ifdef DEBUG
|
||||
int main(int argc, char** argv)
|
||||
{
|
||||
char *devname, *tmp;
|
||||
int major, minor;
|
||||
dev_t device;
|
||||
const char *errmsg = "Cannot parse %s: %s\n";
|
||||
|
||||
if ((argc != 2) && (argc != 3)) {
|
||||
fprintf(stderr, "Usage: %s device_number\n", argv[0]);
|
||||
fprintf(stderr, "\t: %s major minor\n", argv[0]);
|
||||
exit(1);
|
||||
}
|
||||
if (argc == 2) {
|
||||
device = strtoul(argv[1], &tmp, 0);
|
||||
if (*tmp) {
|
||||
fprintf(stderr, errmsg, "device number", argv[1]);
|
||||
exit(1);
|
||||
}
|
||||
} else {
|
||||
major = strtoul(argv[1], &tmp, 0);
|
||||
if (*tmp) {
|
||||
fprintf(stderr, errmsg, "major number", argv[1]);
|
||||
exit(1);
|
||||
}
|
||||
minor = strtoul(argv[2], &tmp, 0);
|
||||
if (*tmp) {
|
||||
fprintf(stderr, errmsg, "minor number", argv[2]);
|
||||
exit(1);
|
||||
}
|
||||
device = makedev(major, minor);
|
||||
printf("Looking for device 0x%04x (%d:%d)\n", device,
|
||||
major, minor);
|
||||
}
|
||||
devname = ext2fs_find_block_device(device);
|
||||
if (devname) {
|
||||
printf("Found device! %s\n", devname);
|
||||
free(devname);
|
||||
} else {
|
||||
printf("Cannot find device.\n");
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif
|
83
e2fsprogs/old_e2fsprogs/ext2fs/flushb.c
Normal file
83
e2fsprogs/old_e2fsprogs/ext2fs/flushb.c
Normal file
@ -0,0 +1,83 @@
|
||||
/* vi: set sw=4 ts=4: */
|
||||
/*
|
||||
* flushb.c --- Hides system-dependent information for both syncing a
|
||||
* device to disk and to flush any buffers from disk cache.
|
||||
*
|
||||
* Copyright (C) 2000 Theodore Ts'o.
|
||||
*
|
||||
* %Begin-Header%
|
||||
* This file may be redistributed under the terms of the GNU Public
|
||||
* License.
|
||||
* %End-Header%
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#if HAVE_ERRNO_H
|
||||
#include <errno.h>
|
||||
#endif
|
||||
#if HAVE_UNISTD_H
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
#if HAVE_SYS_IOCTL_H
|
||||
#include <sys/ioctl.h>
|
||||
#endif
|
||||
#if HAVE_SYS_MOUNT_H
|
||||
#include <sys/param.h>
|
||||
#include <sys/mount.h> /* This may define BLKFLSBUF */
|
||||
#endif
|
||||
|
||||
#include "ext2_fs.h"
|
||||
#include "ext2fs.h"
|
||||
|
||||
/*
|
||||
* For Linux, define BLKFLSBUF and FDFLUSH if necessary, since
|
||||
* not all portable header file does so for us. This really should be
|
||||
* fixed in the glibc header files. (Recent glibcs appear to define
|
||||
* BLKFLSBUF in sys/mount.h, but FDFLUSH still doesn't seem to be
|
||||
* defined anywhere portable.) Until then....
|
||||
*/
|
||||
#ifdef __linux__
|
||||
#ifndef BLKFLSBUF
|
||||
#define BLKFLSBUF _IO(0x12,97) /* flush buffer cache */
|
||||
#endif
|
||||
#ifndef FDFLUSH
|
||||
#define FDFLUSH _IO(2,0x4b) /* flush floppy disk */
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/*
|
||||
* This function will sync a device/file, and optionally attempt to
|
||||
* flush the buffer cache. The latter is basically only useful for
|
||||
* system benchmarks and for torturing systems in burn-in tests. :)
|
||||
*/
|
||||
errcode_t ext2fs_sync_device(int fd, int flushb)
|
||||
{
|
||||
/*
|
||||
* We always sync the device in case we're running on old
|
||||
* kernels for which we can lose data if we don't. (There
|
||||
* still is a race condition for those kernels, but this
|
||||
* reduces it greatly.)
|
||||
*/
|
||||
if (fsync (fd) == -1)
|
||||
return errno;
|
||||
|
||||
if (flushb) {
|
||||
|
||||
#ifdef BLKFLSBUF
|
||||
if (ioctl (fd, BLKFLSBUF, 0) == 0)
|
||||
return 0;
|
||||
#else
|
||||
#ifdef __GNUC__
|
||||
# warning BLKFLSBUF not defined
|
||||
#endif /* __GNUC__ */
|
||||
#endif
|
||||
#ifdef FDFLUSH
|
||||
ioctl (fd, FDFLUSH, 0); /* In case this is a floppy */
|
||||
#else
|
||||
#ifdef __GNUC__
|
||||
# warning FDFLUSH not defined
|
||||
#endif /* __GNUC__ */
|
||||
#endif
|
||||
}
|
||||
return 0;
|
||||
}
|
128
e2fsprogs/old_e2fsprogs/ext2fs/freefs.c
Normal file
128
e2fsprogs/old_e2fsprogs/ext2fs/freefs.c
Normal file
@ -0,0 +1,128 @@
|
||||
/* vi: set sw=4 ts=4: */
|
||||
/*
|
||||
* freefs.c --- free an ext2 filesystem
|
||||
*
|
||||
* Copyright (C) 1993, 1994, 1995, 1996 Theodore Ts'o.
|
||||
*
|
||||
* %Begin-Header%
|
||||
* This file may be redistributed under the terms of the GNU Public
|
||||
* License.
|
||||
* %End-Header%
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#if HAVE_UNISTD_H
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
|
||||
#include "ext2_fs.h"
|
||||
#include "ext2fsP.h"
|
||||
|
||||
static void ext2fs_free_inode_cache(struct ext2_inode_cache *icache);
|
||||
|
||||
void ext2fs_free(ext2_filsys fs)
|
||||
{
|
||||
if (!fs || (fs->magic != EXT2_ET_MAGIC_EXT2FS_FILSYS))
|
||||
return;
|
||||
if (fs->image_io != fs->io) {
|
||||
if (fs->image_io)
|
||||
io_channel_close(fs->image_io);
|
||||
}
|
||||
if (fs->io) {
|
||||
io_channel_close(fs->io);
|
||||
}
|
||||
ext2fs_free_mem(&fs->device_name);
|
||||
ext2fs_free_mem(&fs->super);
|
||||
ext2fs_free_mem(&fs->orig_super);
|
||||
ext2fs_free_mem(&fs->group_desc);
|
||||
ext2fs_free_block_bitmap(fs->block_map);
|
||||
ext2fs_free_inode_bitmap(fs->inode_map);
|
||||
|
||||
ext2fs_badblocks_list_free(fs->badblocks);
|
||||
fs->badblocks = 0;
|
||||
|
||||
ext2fs_free_dblist(fs->dblist);
|
||||
|
||||
if (fs->icache)
|
||||
ext2fs_free_inode_cache(fs->icache);
|
||||
|
||||
fs->magic = 0;
|
||||
|
||||
ext2fs_free_mem(&fs);
|
||||
}
|
||||
|
||||
void ext2fs_free_generic_bitmap(ext2fs_inode_bitmap bitmap)
|
||||
{
|
||||
if (!bitmap || (bitmap->magic != EXT2_ET_MAGIC_GENERIC_BITMAP))
|
||||
return;
|
||||
|
||||
bitmap->magic = 0;
|
||||
ext2fs_free_mem(&bitmap->description);
|
||||
ext2fs_free_mem(&bitmap->bitmap);
|
||||
ext2fs_free_mem(&bitmap);
|
||||
}
|
||||
|
||||
void ext2fs_free_inode_bitmap(ext2fs_inode_bitmap bitmap)
|
||||
{
|
||||
if (!bitmap || (bitmap->magic != EXT2_ET_MAGIC_INODE_BITMAP))
|
||||
return;
|
||||
|
||||
bitmap->magic = EXT2_ET_MAGIC_GENERIC_BITMAP;
|
||||
ext2fs_free_generic_bitmap(bitmap);
|
||||
}
|
||||
|
||||
void ext2fs_free_block_bitmap(ext2fs_block_bitmap bitmap)
|
||||
{
|
||||
if (!bitmap || (bitmap->magic != EXT2_ET_MAGIC_BLOCK_BITMAP))
|
||||
return;
|
||||
|
||||
bitmap->magic = EXT2_ET_MAGIC_GENERIC_BITMAP;
|
||||
ext2fs_free_generic_bitmap(bitmap);
|
||||
}
|
||||
|
||||
/*
|
||||
* Free the inode cache structure
|
||||
*/
|
||||
static void ext2fs_free_inode_cache(struct ext2_inode_cache *icache)
|
||||
{
|
||||
if (--icache->refcount)
|
||||
return;
|
||||
ext2fs_free_mem(&icache->buffer);
|
||||
ext2fs_free_mem(&icache->cache);
|
||||
icache->buffer_blk = 0;
|
||||
ext2fs_free_mem(&icache);
|
||||
}
|
||||
|
||||
/*
|
||||
* This procedure frees a badblocks list.
|
||||
*/
|
||||
void ext2fs_u32_list_free(ext2_u32_list bb)
|
||||
{
|
||||
if (!bb || bb->magic != EXT2_ET_MAGIC_BADBLOCKS_LIST)
|
||||
return;
|
||||
|
||||
ext2fs_free_mem(&bb->list);
|
||||
ext2fs_free_mem(&bb);
|
||||
}
|
||||
|
||||
void ext2fs_badblocks_list_free(ext2_badblocks_list bb)
|
||||
{
|
||||
ext2fs_u32_list_free((ext2_u32_list) bb);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Free a directory block list
|
||||
*/
|
||||
void ext2fs_free_dblist(ext2_dblist dblist)
|
||||
{
|
||||
if (!dblist || (dblist->magic != EXT2_ET_MAGIC_DBLIST))
|
||||
return;
|
||||
|
||||
ext2fs_free_mem(&dblist->list);
|
||||
if (dblist->fs && dblist->fs->dblist == dblist)
|
||||
dblist->fs->dblist = 0;
|
||||
dblist->magic = 0;
|
||||
ext2fs_free_mem(&dblist);
|
||||
}
|
||||
|
49
e2fsprogs/old_e2fsprogs/ext2fs/gen_bitmap.c
Normal file
49
e2fsprogs/old_e2fsprogs/ext2fs/gen_bitmap.c
Normal file
@ -0,0 +1,49 @@
|
||||
/* vi: set sw=4 ts=4: */
|
||||
/*
|
||||
* gen_bitmap.c --- Generic bitmap routines that used to be inlined.
|
||||
*
|
||||
* Copyright (C) 2001 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>
|
||||
#if HAVE_UNISTD_H
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
#include <fcntl.h>
|
||||
#include <time.h>
|
||||
#if HAVE_SYS_STAT_H
|
||||
#include <sys/stat.h>
|
||||
#endif
|
||||
#if HAVE_SYS_TYPES_H
|
||||
#include <sys/types.h>
|
||||
#endif
|
||||
|
||||
#include "ext2_fs.h"
|
||||
#include "ext2fs.h"
|
||||
|
||||
int ext2fs_mark_generic_bitmap(ext2fs_generic_bitmap bitmap,
|
||||
__u32 bitno)
|
||||
{
|
||||
if ((bitno < bitmap->start) || (bitno > bitmap->end)) {
|
||||
ext2fs_warn_bitmap2(bitmap, EXT2FS_MARK_ERROR, bitno);
|
||||
return 0;
|
||||
}
|
||||
return ext2fs_set_bit(bitno - bitmap->start, bitmap->bitmap);
|
||||
}
|
||||
|
||||
int ext2fs_unmark_generic_bitmap(ext2fs_generic_bitmap bitmap,
|
||||
blk_t bitno)
|
||||
{
|
||||
if ((bitno < bitmap->start) || (bitno > bitmap->end)) {
|
||||
ext2fs_warn_bitmap2(bitmap, EXT2FS_UNMARK_ERROR, bitno);
|
||||
return 0;
|
||||
}
|
||||
return ext2fs_clear_bit(bitno - bitmap->start, bitmap->bitmap);
|
||||
}
|
157
e2fsprogs/old_e2fsprogs/ext2fs/get_pathname.c
Normal file
157
e2fsprogs/old_e2fsprogs/ext2fs/get_pathname.c
Normal file
@ -0,0 +1,157 @@
|
||||
/* vi: set sw=4 ts=4: */
|
||||
/*
|
||||
* get_pathname.c --- do directry/inode -> name translation
|
||||
*
|
||||
* Copyright (C) 1993, 1994, 1995 Theodore Ts'o.
|
||||
*
|
||||
* %Begin-Header%
|
||||
* This file may be redistributed under the terms of the GNU Public
|
||||
* License.
|
||||
* %End-Header%
|
||||
*
|
||||
* ext2fs_get_pathname(fs, dir, ino, name)
|
||||
*
|
||||
* This function translates takes two inode numbers into a
|
||||
* string, placing the result in <name>. <dir> is the containing
|
||||
* directory inode, and <ino> is the inode number itself. If
|
||||
* <ino> is zero, then ext2fs_get_pathname will return pathname
|
||||
* of the the directory <dir>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#if HAVE_UNISTD_H
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
|
||||
#include "ext2_fs.h"
|
||||
#include "ext2fs.h"
|
||||
|
||||
struct get_pathname_struct {
|
||||
ext2_ino_t search_ino;
|
||||
ext2_ino_t parent;
|
||||
char *name;
|
||||
errcode_t errcode;
|
||||
};
|
||||
|
||||
#ifdef __TURBOC__
|
||||
# pragma argsused
|
||||
#endif
|
||||
static int get_pathname_proc(struct ext2_dir_entry *dirent,
|
||||
int offset EXT2FS_ATTR((unused)),
|
||||
int blocksize EXT2FS_ATTR((unused)),
|
||||
char *buf EXT2FS_ATTR((unused)),
|
||||
void *priv_data)
|
||||
{
|
||||
struct get_pathname_struct *gp;
|
||||
errcode_t retval;
|
||||
|
||||
gp = (struct get_pathname_struct *) priv_data;
|
||||
|
||||
if (((dirent->name_len & 0xFF) == 2) &&
|
||||
!strncmp(dirent->name, "..", 2))
|
||||
gp->parent = dirent->inode;
|
||||
if (dirent->inode == gp->search_ino) {
|
||||
retval = ext2fs_get_mem((dirent->name_len & 0xFF) + 1,
|
||||
&gp->name);
|
||||
if (retval) {
|
||||
gp->errcode = retval;
|
||||
return DIRENT_ABORT;
|
||||
}
|
||||
strncpy(gp->name, dirent->name, (dirent->name_len & 0xFF));
|
||||
gp->name[dirent->name_len & 0xFF] = '\0';
|
||||
return DIRENT_ABORT;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static errcode_t ext2fs_get_pathname_int(ext2_filsys fs, ext2_ino_t dir,
|
||||
ext2_ino_t ino, int maxdepth,
|
||||
char *buf, char **name)
|
||||
{
|
||||
struct get_pathname_struct gp;
|
||||
char *parent_name, *ret;
|
||||
errcode_t retval;
|
||||
|
||||
if (dir == ino) {
|
||||
retval = ext2fs_get_mem(2, name);
|
||||
if (retval)
|
||||
return retval;
|
||||
strcpy(*name, (dir == EXT2_ROOT_INO) ? "/" : ".");
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!dir || (maxdepth < 0)) {
|
||||
retval = ext2fs_get_mem(4, name);
|
||||
if (retval)
|
||||
return retval;
|
||||
strcpy(*name, "...");
|
||||
return 0;
|
||||
}
|
||||
|
||||
gp.search_ino = ino;
|
||||
gp.parent = 0;
|
||||
gp.name = 0;
|
||||
gp.errcode = 0;
|
||||
|
||||
retval = ext2fs_dir_iterate(fs, dir, 0, buf, get_pathname_proc, &gp);
|
||||
if (retval)
|
||||
goto cleanup;
|
||||
if (gp.errcode) {
|
||||
retval = gp.errcode;
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
retval = ext2fs_get_pathname_int(fs, gp.parent, dir, maxdepth-1,
|
||||
buf, &parent_name);
|
||||
if (retval)
|
||||
goto cleanup;
|
||||
if (!ino) {
|
||||
*name = parent_name;
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (gp.name)
|
||||
retval = ext2fs_get_mem(strlen(parent_name)+strlen(gp.name)+2,
|
||||
&ret);
|
||||
else
|
||||
retval = ext2fs_get_mem(strlen(parent_name)+5, &ret);
|
||||
if (retval)
|
||||
goto cleanup;
|
||||
|
||||
ret[0] = 0;
|
||||
if (parent_name[1])
|
||||
strcat(ret, parent_name);
|
||||
strcat(ret, "/");
|
||||
if (gp.name)
|
||||
strcat(ret, gp.name);
|
||||
else
|
||||
strcat(ret, "???");
|
||||
*name = ret;
|
||||
ext2fs_free_mem(&parent_name);
|
||||
retval = 0;
|
||||
|
||||
cleanup:
|
||||
ext2fs_free_mem(&gp.name);
|
||||
return retval;
|
||||
}
|
||||
|
||||
errcode_t ext2fs_get_pathname(ext2_filsys fs, ext2_ino_t dir, ext2_ino_t ino,
|
||||
char **name)
|
||||
{
|
||||
char *buf;
|
||||
errcode_t retval;
|
||||
|
||||
EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS);
|
||||
|
||||
retval = ext2fs_get_mem(fs->blocksize, &buf);
|
||||
if (retval)
|
||||
return retval;
|
||||
if (dir == ino)
|
||||
ino = 0;
|
||||
retval = ext2fs_get_pathname_int(fs, dir, ino, 32, buf, name);
|
||||
ext2fs_free_mem(&buf);
|
||||
return retval;
|
||||
|
||||
}
|
58
e2fsprogs/old_e2fsprogs/ext2fs/getsectsize.c
Normal file
58
e2fsprogs/old_e2fsprogs/ext2fs/getsectsize.c
Normal file
@ -0,0 +1,58 @@
|
||||
/* vi: set sw=4 ts=4: */
|
||||
/*
|
||||
* getsectsize.c --- get the sector size of a device.
|
||||
*
|
||||
* Copyright (C) 1995, 1995 Theodore Ts'o.
|
||||
* Copyright (C) 2003 VMware, Inc.
|
||||
*
|
||||
* %Begin-Header%
|
||||
* This file may be redistributed under the terms of the GNU Public
|
||||
* License.
|
||||
* %End-Header%
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#if HAVE_UNISTD_H
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
#if HAVE_ERRNO_H
|
||||
#include <errno.h>
|
||||
#endif
|
||||
#include <fcntl.h>
|
||||
#ifdef HAVE_LINUX_FD_H
|
||||
#include <sys/ioctl.h>
|
||||
#include <linux/fd.h>
|
||||
#endif
|
||||
|
||||
#if defined(__linux__) && defined(_IO) && !defined(BLKSSZGET)
|
||||
#define BLKSSZGET _IO(0x12,104)/* get block device sector size */
|
||||
#endif
|
||||
|
||||
#include "ext2_fs.h"
|
||||
#include "ext2fs.h"
|
||||
|
||||
/*
|
||||
* Returns the number of blocks in a partition
|
||||
*/
|
||||
errcode_t ext2fs_get_device_sectsize(const char *file, int *sectsize)
|
||||
{
|
||||
int fd;
|
||||
|
||||
#ifdef CONFIG_LFS
|
||||
fd = open64(file, O_RDONLY);
|
||||
#else
|
||||
fd = open(file, O_RDONLY);
|
||||
#endif
|
||||
if (fd < 0)
|
||||
return errno;
|
||||
|
||||
#ifdef BLKSSZGET
|
||||
if (ioctl(fd, BLKSSZGET, sectsize) >= 0) {
|
||||
close(fd);
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
*sectsize = 0;
|
||||
close(fd);
|
||||
return 0;
|
||||
}
|
291
e2fsprogs/old_e2fsprogs/ext2fs/getsize.c
Normal file
291
e2fsprogs/old_e2fsprogs/ext2fs/getsize.c
Normal file
@ -0,0 +1,291 @@
|
||||
/* vi: set sw=4 ts=4: */
|
||||
/*
|
||||
* getsize.c --- get the size of a partition.
|
||||
*
|
||||
* Copyright (C) 1995, 1995 Theodore Ts'o.
|
||||
* Copyright (C) 2003 VMware, Inc.
|
||||
*
|
||||
* Windows version of ext2fs_get_device_size by Chris Li, VMware.
|
||||
*
|
||||
* %Begin-Header%
|
||||
* This file may be redistributed under the terms of the GNU Public
|
||||
* License.
|
||||
* %End-Header%
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#if HAVE_UNISTD_H
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
#if HAVE_ERRNO_H
|
||||
#include <errno.h>
|
||||
#endif
|
||||
#include <fcntl.h>
|
||||
#ifdef HAVE_SYS_IOCTL_H
|
||||
#include <sys/ioctl.h>
|
||||
#endif
|
||||
#ifdef HAVE_LINUX_FD_H
|
||||
#include <linux/fd.h>
|
||||
#endif
|
||||
#ifdef HAVE_SYS_DISKLABEL_H
|
||||
#include <sys/disklabel.h>
|
||||
#endif
|
||||
#ifdef HAVE_SYS_DISK_H
|
||||
#ifdef HAVE_SYS_QUEUE_H
|
||||
#include <sys/queue.h> /* for LIST_HEAD */
|
||||
#endif
|
||||
#include <sys/disk.h>
|
||||
#endif
|
||||
#ifdef __linux__
|
||||
#include <sys/utsname.h>
|
||||
#endif
|
||||
|
||||
#if defined(__linux__) && defined(_IO) && !defined(BLKGETSIZE)
|
||||
#define BLKGETSIZE _IO(0x12,96) /* return device size */
|
||||
#endif
|
||||
|
||||
#if defined(__linux__) && defined(_IOR) && !defined(BLKGETSIZE64)
|
||||
#define BLKGETSIZE64 _IOR(0x12,114,size_t) /* return device size in bytes (u64 *arg) */
|
||||
#endif
|
||||
|
||||
#ifdef APPLE_DARWIN
|
||||
#define BLKGETSIZE DKIOCGETBLOCKCOUNT32
|
||||
#endif /* APPLE_DARWIN */
|
||||
|
||||
#include "ext2_fs.h"
|
||||
#include "ext2fs.h"
|
||||
|
||||
#if defined(__CYGWIN__) || defined (WIN32)
|
||||
#include <windows.h>
|
||||
#include <winioctl.h>
|
||||
|
||||
#if (_WIN32_WINNT >= 0x0500)
|
||||
#define HAVE_GET_FILE_SIZE_EX 1
|
||||
#endif
|
||||
|
||||
errcode_t ext2fs_get_device_size(const char *file, int blocksize,
|
||||
blk_t *retblocks)
|
||||
{
|
||||
HANDLE dev;
|
||||
PARTITION_INFORMATION pi;
|
||||
DISK_GEOMETRY gi;
|
||||
DWORD retbytes;
|
||||
#ifdef HAVE_GET_FILE_SIZE_EX
|
||||
LARGE_INTEGER filesize;
|
||||
#else
|
||||
DWORD filesize;
|
||||
#endif /* HAVE_GET_FILE_SIZE_EX */
|
||||
|
||||
dev = CreateFile(file, GENERIC_READ,
|
||||
FILE_SHARE_READ | FILE_SHARE_WRITE ,
|
||||
NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
|
||||
|
||||
if (dev == INVALID_HANDLE_VALUE)
|
||||
return EBADF;
|
||||
if (DeviceIoControl(dev, IOCTL_DISK_GET_PARTITION_INFO,
|
||||
&pi, sizeof(PARTITION_INFORMATION),
|
||||
&pi, sizeof(PARTITION_INFORMATION),
|
||||
&retbytes, NULL)) {
|
||||
|
||||
*retblocks = pi.PartitionLength.QuadPart / blocksize;
|
||||
|
||||
} else if (DeviceIoControl(dev, IOCTL_DISK_GET_DRIVE_GEOMETRY,
|
||||
&gi, sizeof(DISK_GEOMETRY),
|
||||
&gi, sizeof(DISK_GEOMETRY),
|
||||
&retbytes, NULL)) {
|
||||
|
||||
*retblocks = gi.BytesPerSector *
|
||||
gi.SectorsPerTrack *
|
||||
gi.TracksPerCylinder *
|
||||
gi.Cylinders.QuadPart / blocksize;
|
||||
|
||||
#ifdef HAVE_GET_FILE_SIZE_EX
|
||||
} else if (GetFileSizeEx(dev, &filesize)) {
|
||||
*retblocks = filesize.QuadPart / blocksize;
|
||||
}
|
||||
#else
|
||||
} else {
|
||||
filesize = GetFileSize(dev, NULL);
|
||||
if (INVALID_FILE_SIZE != filesize) {
|
||||
*retblocks = filesize / blocksize;
|
||||
}
|
||||
}
|
||||
#endif /* HAVE_GET_FILE_SIZE_EX */
|
||||
|
||||
CloseHandle(dev);
|
||||
return 0;
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
static int valid_offset (int fd, ext2_loff_t offset)
|
||||
{
|
||||
char ch;
|
||||
|
||||
if (ext2fs_llseek (fd, offset, 0) < 0)
|
||||
return 0;
|
||||
if (read (fd, &ch, 1) < 1)
|
||||
return 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* Returns the number of blocks in a partition
|
||||
*/
|
||||
errcode_t ext2fs_get_device_size(const char *file, int blocksize,
|
||||
blk_t *retblocks)
|
||||
{
|
||||
int fd;
|
||||
int valid_blkgetsize64 = 1;
|
||||
#ifdef __linux__
|
||||
struct utsname ut;
|
||||
#endif
|
||||
unsigned long long size64;
|
||||
unsigned long size;
|
||||
ext2_loff_t high, low;
|
||||
#ifdef FDGETPRM
|
||||
struct floppy_struct this_floppy;
|
||||
#endif
|
||||
#ifdef HAVE_SYS_DISKLABEL_H
|
||||
int part;
|
||||
struct disklabel lab;
|
||||
struct partition *pp;
|
||||
char ch;
|
||||
#endif /* HAVE_SYS_DISKLABEL_H */
|
||||
|
||||
#ifdef CONFIG_LFS
|
||||
fd = open64(file, O_RDONLY);
|
||||
#else
|
||||
fd = open(file, O_RDONLY);
|
||||
#endif
|
||||
if (fd < 0)
|
||||
return errno;
|
||||
|
||||
#ifdef DKIOCGETBLOCKCOUNT /* For Apple Darwin */
|
||||
if (ioctl(fd, DKIOCGETBLOCKCOUNT, &size64) >= 0) {
|
||||
if ((sizeof(*retblocks) < sizeof(unsigned long long))
|
||||
&& ((size64 / (blocksize / 512)) > 0xFFFFFFFF))
|
||||
return EFBIG;
|
||||
close(fd);
|
||||
*retblocks = size64 / (blocksize / 512);
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef BLKGETSIZE64
|
||||
#ifdef __linux__
|
||||
if ((uname(&ut) == 0) &&
|
||||
((ut.release[0] == '2') && (ut.release[1] == '.') &&
|
||||
(ut.release[2] < '6') && (ut.release[3] == '.')))
|
||||
valid_blkgetsize64 = 0;
|
||||
#endif
|
||||
if (valid_blkgetsize64 &&
|
||||
ioctl(fd, BLKGETSIZE64, &size64) >= 0) {
|
||||
if ((sizeof(*retblocks) < sizeof(unsigned long long))
|
||||
&& ((size64 / blocksize) > 0xFFFFFFFF))
|
||||
return EFBIG;
|
||||
close(fd);
|
||||
*retblocks = size64 / blocksize;
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef BLKGETSIZE
|
||||
if (ioctl(fd, BLKGETSIZE, &size) >= 0) {
|
||||
close(fd);
|
||||
*retblocks = size / (blocksize / 512);
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef FDGETPRM
|
||||
if (ioctl(fd, FDGETPRM, &this_floppy) >= 0) {
|
||||
close(fd);
|
||||
*retblocks = this_floppy.size / (blocksize / 512);
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_SYS_DISKLABEL_H
|
||||
#if defined(DIOCGMEDIASIZE)
|
||||
{
|
||||
off_t ms;
|
||||
u_int bs;
|
||||
if (ioctl(fd, DIOCGMEDIASIZE, &ms) >= 0) {
|
||||
*retblocks = ms / blocksize;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
#elif defined(DIOCGDINFO)
|
||||
/* old disklabel interface */
|
||||
part = strlen(file) - 1;
|
||||
if (part >= 0) {
|
||||
ch = file[part];
|
||||
if (isdigit(ch))
|
||||
part = 0;
|
||||
else if (ch >= 'a' && ch <= 'h')
|
||||
part = ch - 'a';
|
||||
else
|
||||
part = -1;
|
||||
}
|
||||
if (part >= 0 && (ioctl(fd, DIOCGDINFO, (char *)&lab) >= 0)) {
|
||||
pp = &lab.d_partitions[part];
|
||||
if (pp->p_size) {
|
||||
close(fd);
|
||||
*retblocks = pp->p_size / (blocksize / 512);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
#endif /* defined(DIOCG*) */
|
||||
#endif /* HAVE_SYS_DISKLABEL_H */
|
||||
|
||||
/*
|
||||
* OK, we couldn't figure it out by using a specialized ioctl,
|
||||
* which is generally the best way. So do binary search to
|
||||
* find the size of the partition.
|
||||
*/
|
||||
low = 0;
|
||||
for (high = 1024; valid_offset (fd, high); high *= 2)
|
||||
low = high;
|
||||
while (low < high - 1)
|
||||
{
|
||||
const ext2_loff_t mid = (low + high) / 2;
|
||||
|
||||
if (valid_offset (fd, mid))
|
||||
low = mid;
|
||||
else
|
||||
high = mid;
|
||||
}
|
||||
valid_offset (fd, 0);
|
||||
close(fd);
|
||||
size64 = low + 1;
|
||||
if ((sizeof(*retblocks) < sizeof(unsigned long long))
|
||||
&& ((size64 / blocksize) > 0xFFFFFFFF))
|
||||
return EFBIG;
|
||||
*retblocks = size64 / blocksize;
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif /* WIN32 */
|
||||
|
||||
#ifdef DEBUG
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
blk_t blocks;
|
||||
int retval;
|
||||
|
||||
if (argc < 2) {
|
||||
fprintf(stderr, "Usage: %s device\n", argv[0]);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
retval = ext2fs_get_device_size(argv[1], 1024, &blocks);
|
||||
if (retval) {
|
||||
com_err(argv[0], retval,
|
||||
"while calling ext2fs_get_device_size");
|
||||
exit(1);
|
||||
}
|
||||
printf("Device %s has %d 1k blocks.\n", argv[1], blocks);
|
||||
exit(0);
|
||||
}
|
||||
#endif
|
467
e2fsprogs/old_e2fsprogs/ext2fs/icount.c
Normal file
467
e2fsprogs/old_e2fsprogs/ext2fs/icount.c
Normal file
@ -0,0 +1,467 @@
|
||||
/* vi: set sw=4 ts=4: */
|
||||
/*
|
||||
* icount.c --- an efficient inode count abstraction
|
||||
*
|
||||
* Copyright (C) 1997 Theodore Ts'o.
|
||||
*
|
||||
* %Begin-Header%
|
||||
* This file may be redistributed under the terms of the GNU Public
|
||||
* License.
|
||||
* %End-Header%
|
||||
*/
|
||||
|
||||
#if HAVE_UNISTD_H
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include "ext2_fs.h"
|
||||
#include "ext2fs.h"
|
||||
|
||||
/*
|
||||
* The data storage strategy used by icount relies on the observation
|
||||
* that most inode counts are either zero (for non-allocated inodes),
|
||||
* one (for most files), and only a few that are two or more
|
||||
* (directories and files that are linked to more than one directory).
|
||||
*
|
||||
* Also, e2fsck tends to load the icount data sequentially.
|
||||
*
|
||||
* So, we use an inode bitmap to indicate which inodes have a count of
|
||||
* one, and then use a sorted list to store the counts for inodes
|
||||
* which are greater than one.
|
||||
*
|
||||
* We also use an optional bitmap to indicate which inodes are already
|
||||
* in the sorted list, to speed up the use of this abstraction by
|
||||
* e2fsck's pass 2. Pass 2 increments inode counts as it finds them,
|
||||
* so this extra bitmap avoids searching the sorted list to see if a
|
||||
* particular inode is on the sorted list already.
|
||||
*/
|
||||
|
||||
struct ext2_icount_el {
|
||||
ext2_ino_t ino;
|
||||
__u16 count;
|
||||
};
|
||||
|
||||
struct ext2_icount {
|
||||
errcode_t magic;
|
||||
ext2fs_inode_bitmap single;
|
||||
ext2fs_inode_bitmap multiple;
|
||||
ext2_ino_t count;
|
||||
ext2_ino_t size;
|
||||
ext2_ino_t num_inodes;
|
||||
ext2_ino_t cursor;
|
||||
struct ext2_icount_el *list;
|
||||
};
|
||||
|
||||
void ext2fs_free_icount(ext2_icount_t icount)
|
||||
{
|
||||
if (!icount)
|
||||
return;
|
||||
|
||||
icount->magic = 0;
|
||||
ext2fs_free_mem(&icount->list);
|
||||
ext2fs_free_inode_bitmap(icount->single);
|
||||
ext2fs_free_inode_bitmap(icount->multiple);
|
||||
ext2fs_free_mem(&icount);
|
||||
}
|
||||
|
||||
errcode_t ext2fs_create_icount2(ext2_filsys fs, int flags, unsigned int size,
|
||||
ext2_icount_t hint, ext2_icount_t *ret)
|
||||
{
|
||||
ext2_icount_t icount;
|
||||
errcode_t retval;
|
||||
size_t bytes;
|
||||
ext2_ino_t i;
|
||||
|
||||
if (hint) {
|
||||
EXT2_CHECK_MAGIC(hint, EXT2_ET_MAGIC_ICOUNT);
|
||||
if (hint->size > size)
|
||||
size = (size_t) hint->size;
|
||||
}
|
||||
|
||||
retval = ext2fs_get_mem(sizeof(struct ext2_icount), &icount);
|
||||
if (retval)
|
||||
return retval;
|
||||
memset(icount, 0, sizeof(struct ext2_icount));
|
||||
|
||||
retval = ext2fs_allocate_inode_bitmap(fs, 0,
|
||||
&icount->single);
|
||||
if (retval)
|
||||
goto errout;
|
||||
|
||||
if (flags & EXT2_ICOUNT_OPT_INCREMENT) {
|
||||
retval = ext2fs_allocate_inode_bitmap(fs, 0,
|
||||
&icount->multiple);
|
||||
if (retval)
|
||||
goto errout;
|
||||
} else
|
||||
icount->multiple = 0;
|
||||
|
||||
if (size) {
|
||||
icount->size = size;
|
||||
} else {
|
||||
/*
|
||||
* Figure out how many special case inode counts we will
|
||||
* have. We know we will need one for each directory;
|
||||
* we also need to reserve some extra room for file links
|
||||
*/
|
||||
retval = ext2fs_get_num_dirs(fs, &icount->size);
|
||||
if (retval)
|
||||
goto errout;
|
||||
icount->size += fs->super->s_inodes_count / 50;
|
||||
}
|
||||
|
||||
bytes = (size_t) (icount->size * sizeof(struct ext2_icount_el));
|
||||
retval = ext2fs_get_mem(bytes, &icount->list);
|
||||
if (retval)
|
||||
goto errout;
|
||||
memset(icount->list, 0, bytes);
|
||||
|
||||
icount->magic = EXT2_ET_MAGIC_ICOUNT;
|
||||
icount->count = 0;
|
||||
icount->cursor = 0;
|
||||
icount->num_inodes = fs->super->s_inodes_count;
|
||||
|
||||
/*
|
||||
* Populate the sorted list with those entries which were
|
||||
* found in the hint icount (since those are ones which will
|
||||
* likely need to be in the sorted list this time around).
|
||||
*/
|
||||
if (hint) {
|
||||
for (i=0; i < hint->count; i++)
|
||||
icount->list[i].ino = hint->list[i].ino;
|
||||
icount->count = hint->count;
|
||||
}
|
||||
|
||||
*ret = icount;
|
||||
return 0;
|
||||
|
||||
errout:
|
||||
ext2fs_free_icount(icount);
|
||||
return retval;
|
||||
}
|
||||
|
||||
errcode_t ext2fs_create_icount(ext2_filsys fs, int flags,
|
||||
unsigned int size,
|
||||
ext2_icount_t *ret)
|
||||
{
|
||||
return ext2fs_create_icount2(fs, flags, size, 0, ret);
|
||||
}
|
||||
|
||||
/*
|
||||
* insert_icount_el() --- Insert a new entry into the sorted list at a
|
||||
* specified position.
|
||||
*/
|
||||
static struct ext2_icount_el *insert_icount_el(ext2_icount_t icount,
|
||||
ext2_ino_t ino, int pos)
|
||||
{
|
||||
struct ext2_icount_el *el;
|
||||
errcode_t retval;
|
||||
ext2_ino_t new_size = 0;
|
||||
int num;
|
||||
|
||||
if (icount->count >= icount->size) {
|
||||
if (icount->count) {
|
||||
new_size = icount->list[(unsigned)icount->count-1].ino;
|
||||
new_size = (ext2_ino_t) (icount->count *
|
||||
((float) icount->num_inodes / new_size));
|
||||
}
|
||||
if (new_size < (icount->size + 100))
|
||||
new_size = icount->size + 100;
|
||||
retval = ext2fs_resize_mem((size_t) icount->size *
|
||||
sizeof(struct ext2_icount_el),
|
||||
(size_t) new_size *
|
||||
sizeof(struct ext2_icount_el),
|
||||
&icount->list);
|
||||
if (retval)
|
||||
return 0;
|
||||
icount->size = new_size;
|
||||
}
|
||||
num = (int) icount->count - pos;
|
||||
if (num < 0)
|
||||
return 0; /* should never happen */
|
||||
if (num) {
|
||||
memmove(&icount->list[pos+1], &icount->list[pos],
|
||||
sizeof(struct ext2_icount_el) * num);
|
||||
}
|
||||
icount->count++;
|
||||
el = &icount->list[pos];
|
||||
el->count = 0;
|
||||
el->ino = ino;
|
||||
return el;
|
||||
}
|
||||
|
||||
/*
|
||||
* get_icount_el() --- given an inode number, try to find icount
|
||||
* information in the sorted list. If the create flag is set,
|
||||
* and we can't find an entry, create one in the sorted list.
|
||||
*/
|
||||
static struct ext2_icount_el *get_icount_el(ext2_icount_t icount,
|
||||
ext2_ino_t ino, int create)
|
||||
{
|
||||
float range;
|
||||
int low, high, mid;
|
||||
ext2_ino_t lowval, highval;
|
||||
|
||||
if (!icount || !icount->list)
|
||||
return 0;
|
||||
|
||||
if (create && ((icount->count == 0) ||
|
||||
(ino > icount->list[(unsigned)icount->count-1].ino))) {
|
||||
return insert_icount_el(icount, ino, (unsigned) icount->count);
|
||||
}
|
||||
if (icount->count == 0)
|
||||
return 0;
|
||||
|
||||
if (icount->cursor >= icount->count)
|
||||
icount->cursor = 0;
|
||||
if (ino == icount->list[icount->cursor].ino)
|
||||
return &icount->list[icount->cursor++];
|
||||
low = 0;
|
||||
high = (int) icount->count-1;
|
||||
while (low <= high) {
|
||||
if (low == high)
|
||||
mid = low;
|
||||
else {
|
||||
/* Interpolate for efficiency */
|
||||
lowval = icount->list[low].ino;
|
||||
highval = icount->list[high].ino;
|
||||
|
||||
if (ino < lowval)
|
||||
range = 0;
|
||||
else if (ino > highval)
|
||||
range = 1;
|
||||
else
|
||||
range = ((float) (ino - lowval)) /
|
||||
(highval - lowval);
|
||||
mid = low + ((int) (range * (high-low)));
|
||||
}
|
||||
if (ino == icount->list[mid].ino) {
|
||||
icount->cursor = mid+1;
|
||||
return &icount->list[mid];
|
||||
}
|
||||
if (ino < icount->list[mid].ino)
|
||||
high = mid-1;
|
||||
else
|
||||
low = mid+1;
|
||||
}
|
||||
/*
|
||||
* If we need to create a new entry, it should be right at
|
||||
* low (where high will be left at low-1).
|
||||
*/
|
||||
if (create)
|
||||
return insert_icount_el(icount, ino, low);
|
||||
return 0;
|
||||
}
|
||||
|
||||
errcode_t ext2fs_icount_validate(ext2_icount_t icount, FILE *out)
|
||||
{
|
||||
errcode_t ret = 0;
|
||||
unsigned int i;
|
||||
const char *bad = "bad icount";
|
||||
|
||||
EXT2_CHECK_MAGIC(icount, EXT2_ET_MAGIC_ICOUNT);
|
||||
|
||||
if (icount->count > icount->size) {
|
||||
fprintf(out, "%s: count > size\n", bad);
|
||||
return EXT2_ET_INVALID_ARGUMENT;
|
||||
}
|
||||
for (i=1; i < icount->count; i++) {
|
||||
if (icount->list[i-1].ino >= icount->list[i].ino) {
|
||||
fprintf(out, "%s: list[%d].ino=%u, list[%d].ino=%u\n",
|
||||
bad, i-1, icount->list[i-1].ino,
|
||||
i, icount->list[i].ino);
|
||||
ret = EXT2_ET_INVALID_ARGUMENT;
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
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_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;
|
||||
}
|
||||
|
||||
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_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;
|
||||
}
|
||||
|
||||
ext2_ino_t ext2fs_get_icount_size(ext2_icount_t icount)
|
||||
{
|
||||
if (!icount || icount->magic != EXT2_ET_MAGIC_ICOUNT)
|
||||
return 0;
|
||||
|
||||
return icount->size;
|
||||
}
|
377
e2fsprogs/old_e2fsprogs/ext2fs/imager.c
Normal file
377
e2fsprogs/old_e2fsprogs/ext2fs/imager.c
Normal file
@ -0,0 +1,377 @@
|
||||
/* vi: set sw=4 ts=4: */
|
||||
/*
|
||||
* image.c --- writes out the critical parts of the filesystem as a
|
||||
* flat file.
|
||||
*
|
||||
* Copyright (C) 2000 Theodore Ts'o.
|
||||
*
|
||||
* Note: this uses the POSIX IO interfaces, unlike most of the other
|
||||
* functions in this library. So sue me.
|
||||
*
|
||||
* %Begin-Header%
|
||||
* This file may be redistributed under the terms of the GNU Public
|
||||
* License.
|
||||
* %End-Header%
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#if HAVE_UNISTD_H
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
#if HAVE_ERRNO_H
|
||||
#include <errno.h>
|
||||
#endif
|
||||
#include <fcntl.h>
|
||||
#include <time.h>
|
||||
#if HAVE_SYS_STAT_H
|
||||
#include <sys/stat.h>
|
||||
#endif
|
||||
#if HAVE_SYS_TYPES_H
|
||||
#include <sys/types.h>
|
||||
#endif
|
||||
|
||||
#include "ext2_fs.h"
|
||||
#include "ext2fs.h"
|
||||
|
||||
#ifndef HAVE_TYPE_SSIZE_T
|
||||
typedef int ssize_t;
|
||||
#endif
|
||||
|
||||
/*
|
||||
* This function returns 1 if the specified block is all zeros
|
||||
*/
|
||||
static int check_zero_block(char *buf, int blocksize)
|
||||
{
|
||||
char *cp = buf;
|
||||
int left = blocksize;
|
||||
|
||||
while (left > 0) {
|
||||
if (*cp++)
|
||||
return 0;
|
||||
left--;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* Write the inode table out as a single block.
|
||||
*/
|
||||
#define BUF_BLOCKS 32
|
||||
|
||||
errcode_t ext2fs_image_inode_write(ext2_filsys fs, int fd, int flags)
|
||||
{
|
||||
unsigned int group, left, c, d;
|
||||
char *buf, *cp;
|
||||
blk_t blk;
|
||||
ssize_t actual;
|
||||
errcode_t retval;
|
||||
|
||||
buf = xmalloc(fs->blocksize * BUF_BLOCKS);
|
||||
|
||||
for (group = 0; group < fs->group_desc_count; group++) {
|
||||
blk = fs->group_desc[(unsigned)group].bg_inode_table;
|
||||
if (!blk)
|
||||
return EXT2_ET_MISSING_INODE_TABLE;
|
||||
left = fs->inode_blocks_per_group;
|
||||
while (left) {
|
||||
c = BUF_BLOCKS;
|
||||
if (c > left)
|
||||
c = left;
|
||||
retval = io_channel_read_blk(fs->io, blk, c, buf);
|
||||
if (retval)
|
||||
goto errout;
|
||||
cp = buf;
|
||||
while (c) {
|
||||
if (!(flags & IMAGER_FLAG_SPARSEWRITE)) {
|
||||
d = c;
|
||||
goto skip_sparse;
|
||||
}
|
||||
/* Skip zero blocks */
|
||||
if (check_zero_block(cp, fs->blocksize)) {
|
||||
c--;
|
||||
blk++;
|
||||
left--;
|
||||
cp += fs->blocksize;
|
||||
lseek(fd, fs->blocksize, SEEK_CUR);
|
||||
continue;
|
||||
}
|
||||
/* Find non-zero blocks */
|
||||
for (d=1; d < c; d++) {
|
||||
if (check_zero_block(cp + d*fs->blocksize, fs->blocksize))
|
||||
break;
|
||||
}
|
||||
skip_sparse:
|
||||
actual = write(fd, cp, fs->blocksize * d);
|
||||
if (actual == -1) {
|
||||
retval = errno;
|
||||
goto errout;
|
||||
}
|
||||
if (actual != (ssize_t) (fs->blocksize * d)) {
|
||||
retval = EXT2_ET_SHORT_WRITE;
|
||||
goto errout;
|
||||
}
|
||||
blk += d;
|
||||
left -= d;
|
||||
cp += fs->blocksize * d;
|
||||
c -= d;
|
||||
}
|
||||
}
|
||||
}
|
||||
retval = 0;
|
||||
|
||||
errout:
|
||||
free(buf);
|
||||
return retval;
|
||||
}
|
||||
|
||||
/*
|
||||
* Read in the inode table and stuff it into place
|
||||
*/
|
||||
errcode_t ext2fs_image_inode_read(ext2_filsys fs, int fd,
|
||||
int flags EXT2FS_ATTR((unused)))
|
||||
{
|
||||
unsigned int group, c, left;
|
||||
char *buf;
|
||||
blk_t blk;
|
||||
ssize_t actual;
|
||||
errcode_t retval;
|
||||
|
||||
buf = xmalloc(fs->blocksize * BUF_BLOCKS);
|
||||
|
||||
for (group = 0; group < fs->group_desc_count; group++) {
|
||||
blk = fs->group_desc[(unsigned)group].bg_inode_table;
|
||||
if (!blk) {
|
||||
retval = EXT2_ET_MISSING_INODE_TABLE;
|
||||
goto errout;
|
||||
}
|
||||
left = fs->inode_blocks_per_group;
|
||||
while (left) {
|
||||
c = BUF_BLOCKS;
|
||||
if (c > left)
|
||||
c = left;
|
||||
actual = read(fd, buf, fs->blocksize * c);
|
||||
if (actual == -1) {
|
||||
retval = errno;
|
||||
goto errout;
|
||||
}
|
||||
if (actual != (ssize_t) (fs->blocksize * c)) {
|
||||
retval = EXT2_ET_SHORT_READ;
|
||||
goto errout;
|
||||
}
|
||||
retval = io_channel_write_blk(fs->io, blk, c, buf);
|
||||
if (retval)
|
||||
goto errout;
|
||||
|
||||
blk += c;
|
||||
left -= c;
|
||||
}
|
||||
}
|
||||
retval = ext2fs_flush_icache(fs);
|
||||
|
||||
errout:
|
||||
free(buf);
|
||||
return retval;
|
||||
}
|
||||
|
||||
/*
|
||||
* Write out superblock and group descriptors
|
||||
*/
|
||||
errcode_t ext2fs_image_super_write(ext2_filsys fs, int fd,
|
||||
int flags EXT2FS_ATTR((unused)))
|
||||
{
|
||||
char *buf, *cp;
|
||||
ssize_t actual;
|
||||
errcode_t retval;
|
||||
|
||||
buf = xmalloc(fs->blocksize);
|
||||
|
||||
/*
|
||||
* Write out the superblock
|
||||
*/
|
||||
memset(buf, 0, fs->blocksize);
|
||||
memcpy(buf, fs->super, SUPERBLOCK_SIZE);
|
||||
actual = write(fd, buf, fs->blocksize);
|
||||
if (actual == -1) {
|
||||
retval = errno;
|
||||
goto errout;
|
||||
}
|
||||
if (actual != (ssize_t) fs->blocksize) {
|
||||
retval = EXT2_ET_SHORT_WRITE;
|
||||
goto errout;
|
||||
}
|
||||
|
||||
/*
|
||||
* Now write out the block group descriptors
|
||||
*/
|
||||
cp = (char *) fs->group_desc;
|
||||
actual = write(fd, cp, fs->blocksize * fs->desc_blocks);
|
||||
if (actual == -1) {
|
||||
retval = errno;
|
||||
goto errout;
|
||||
}
|
||||
if (actual != (ssize_t) (fs->blocksize * fs->desc_blocks)) {
|
||||
retval = EXT2_ET_SHORT_WRITE;
|
||||
goto errout;
|
||||
}
|
||||
|
||||
retval = 0;
|
||||
|
||||
errout:
|
||||
free(buf);
|
||||
return retval;
|
||||
}
|
||||
|
||||
/*
|
||||
* Read the superblock and group descriptors and overwrite them.
|
||||
*/
|
||||
errcode_t ext2fs_image_super_read(ext2_filsys fs, int fd,
|
||||
int flags EXT2FS_ATTR((unused)))
|
||||
{
|
||||
char *buf;
|
||||
ssize_t actual, size;
|
||||
errcode_t retval;
|
||||
|
||||
size = fs->blocksize * (fs->group_desc_count + 1);
|
||||
buf = xmalloc(size);
|
||||
|
||||
/*
|
||||
* Read it all in.
|
||||
*/
|
||||
actual = read(fd, buf, size);
|
||||
if (actual == -1) {
|
||||
retval = errno;
|
||||
goto errout;
|
||||
}
|
||||
if (actual != size) {
|
||||
retval = EXT2_ET_SHORT_READ;
|
||||
goto errout;
|
||||
}
|
||||
|
||||
/*
|
||||
* Now copy in the superblock and group descriptors
|
||||
*/
|
||||
memcpy(fs->super, buf, SUPERBLOCK_SIZE);
|
||||
|
||||
memcpy(fs->group_desc, buf + fs->blocksize,
|
||||
fs->blocksize * fs->group_desc_count);
|
||||
|
||||
retval = 0;
|
||||
|
||||
errout:
|
||||
free(buf);
|
||||
return retval;
|
||||
}
|
||||
|
||||
/*
|
||||
* Write the block/inode bitmaps.
|
||||
*/
|
||||
errcode_t ext2fs_image_bitmap_write(ext2_filsys fs, int fd, int flags)
|
||||
{
|
||||
char *ptr;
|
||||
int c, size;
|
||||
char zero_buf[1024];
|
||||
ssize_t actual;
|
||||
errcode_t retval;
|
||||
|
||||
if (flags & IMAGER_FLAG_INODEMAP) {
|
||||
if (!fs->inode_map) {
|
||||
retval = ext2fs_read_inode_bitmap(fs);
|
||||
if (retval)
|
||||
return retval;
|
||||
}
|
||||
ptr = fs->inode_map->bitmap;
|
||||
size = (EXT2_INODES_PER_GROUP(fs->super) / 8);
|
||||
} else {
|
||||
if (!fs->block_map) {
|
||||
retval = ext2fs_read_block_bitmap(fs);
|
||||
if (retval)
|
||||
return retval;
|
||||
}
|
||||
ptr = fs->block_map->bitmap;
|
||||
size = EXT2_BLOCKS_PER_GROUP(fs->super) / 8;
|
||||
}
|
||||
size = size * fs->group_desc_count;
|
||||
|
||||
actual = write(fd, ptr, size);
|
||||
if (actual == -1) {
|
||||
retval = errno;
|
||||
goto errout;
|
||||
}
|
||||
if (actual != size) {
|
||||
retval = EXT2_ET_SHORT_WRITE;
|
||||
goto errout;
|
||||
}
|
||||
size = size % fs->blocksize;
|
||||
memset(zero_buf, 0, sizeof(zero_buf));
|
||||
if (size) {
|
||||
size = fs->blocksize - size;
|
||||
while (size) {
|
||||
c = size;
|
||||
if (c > (int) sizeof(zero_buf))
|
||||
c = sizeof(zero_buf);
|
||||
actual = write(fd, zero_buf, c);
|
||||
if (actual == -1) {
|
||||
retval = errno;
|
||||
goto errout;
|
||||
}
|
||||
if (actual != c) {
|
||||
retval = EXT2_ET_SHORT_WRITE;
|
||||
goto errout;
|
||||
}
|
||||
size -= c;
|
||||
}
|
||||
}
|
||||
retval = 0;
|
||||
errout:
|
||||
return retval;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Read the block/inode bitmaps.
|
||||
*/
|
||||
errcode_t ext2fs_image_bitmap_read(ext2_filsys fs, int fd, int flags)
|
||||
{
|
||||
char *ptr, *buf = 0;
|
||||
int size;
|
||||
ssize_t actual;
|
||||
errcode_t retval;
|
||||
|
||||
if (flags & IMAGER_FLAG_INODEMAP) {
|
||||
if (!fs->inode_map) {
|
||||
retval = ext2fs_read_inode_bitmap(fs);
|
||||
if (retval)
|
||||
return retval;
|
||||
}
|
||||
ptr = fs->inode_map->bitmap;
|
||||
size = (EXT2_INODES_PER_GROUP(fs->super) / 8);
|
||||
} else {
|
||||
if (!fs->block_map) {
|
||||
retval = ext2fs_read_block_bitmap(fs);
|
||||
if (retval)
|
||||
return retval;
|
||||
}
|
||||
ptr = fs->block_map->bitmap;
|
||||
size = EXT2_BLOCKS_PER_GROUP(fs->super) / 8;
|
||||
}
|
||||
size = size * fs->group_desc_count;
|
||||
|
||||
buf = xmalloc(size);
|
||||
|
||||
actual = read(fd, buf, size);
|
||||
if (actual == -1) {
|
||||
retval = errno;
|
||||
goto errout;
|
||||
}
|
||||
if (actual != size) {
|
||||
retval = EXT2_ET_SHORT_WRITE;
|
||||
goto errout;
|
||||
}
|
||||
memcpy(ptr, buf, size);
|
||||
|
||||
retval = 0;
|
||||
errout:
|
||||
free(buf);
|
||||
return retval;
|
||||
}
|
71
e2fsprogs/old_e2fsprogs/ext2fs/ind_block.c
Normal file
71
e2fsprogs/old_e2fsprogs/ext2fs/ind_block.c
Normal file
@ -0,0 +1,71 @@
|
||||
/* vi: set sw=4 ts=4: */
|
||||
/*
|
||||
* ind_block.c --- indirect block I/O routines
|
||||
*
|
||||
* Copyright (C) 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000,
|
||||
* 2001, 2002, 2003, 2004, 2005 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>
|
||||
#if HAVE_UNISTD_H
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
|
||||
#include "ext2_fs.h"
|
||||
#include "ext2fs.h"
|
||||
|
||||
errcode_t ext2fs_read_ind_block(ext2_filsys fs, blk_t blk, void *buf)
|
||||
{
|
||||
errcode_t retval;
|
||||
#if BB_BIG_ENDIAN
|
||||
blk_t *block_nr;
|
||||
int i;
|
||||
int limit = fs->blocksize >> 2;
|
||||
#endif
|
||||
|
||||
if ((fs->flags & EXT2_FLAG_IMAGE_FILE) &&
|
||||
(fs->io != fs->image_io))
|
||||
memset(buf, 0, fs->blocksize);
|
||||
else {
|
||||
retval = io_channel_read_blk(fs->io, blk, 1, buf);
|
||||
if (retval)
|
||||
return retval;
|
||||
}
|
||||
#if BB_BIG_ENDIAN
|
||||
if (fs->flags & (EXT2_FLAG_SWAP_BYTES | EXT2_FLAG_SWAP_BYTES_READ)) {
|
||||
block_nr = (blk_t *) buf;
|
||||
for (i = 0; i < limit; i++, block_nr++)
|
||||
*block_nr = ext2fs_swab32(*block_nr);
|
||||
}
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
errcode_t ext2fs_write_ind_block(ext2_filsys fs, blk_t blk, void *buf)
|
||||
{
|
||||
#if BB_BIG_ENDIAN
|
||||
blk_t *block_nr;
|
||||
int i;
|
||||
int limit = fs->blocksize >> 2;
|
||||
#endif
|
||||
|
||||
if (fs->flags & EXT2_FLAG_IMAGE_FILE)
|
||||
return 0;
|
||||
|
||||
#if BB_BIG_ENDIAN
|
||||
if (fs->flags & (EXT2_FLAG_SWAP_BYTES | EXT2_FLAG_SWAP_BYTES_WRITE)) {
|
||||
block_nr = (blk_t *) buf;
|
||||
for (i = 0; i < limit; i++, block_nr++)
|
||||
*block_nr = ext2fs_swab32(*block_nr);
|
||||
}
|
||||
#endif
|
||||
return io_channel_write_blk(fs->io, blk, 1, buf);
|
||||
}
|
||||
|
||||
|
388
e2fsprogs/old_e2fsprogs/ext2fs/initialize.c
Normal file
388
e2fsprogs/old_e2fsprogs/ext2fs/initialize.c
Normal file
@ -0,0 +1,388 @@
|
||||
/* vi: set sw=4 ts=4: */
|
||||
/*
|
||||
* initialize.c --- initialize a filesystem handle given superblock
|
||||
* parameters. Used by mke2fs when initializing a filesystem.
|
||||
*
|
||||
* Copyright (C) 1994, 1995, 1996 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>
|
||||
#if HAVE_UNISTD_H
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
#include <fcntl.h>
|
||||
#include <time.h>
|
||||
#if HAVE_SYS_STAT_H
|
||||
#include <sys/stat.h>
|
||||
#endif
|
||||
#if HAVE_SYS_TYPES_H
|
||||
#include <sys/types.h>
|
||||
#endif
|
||||
|
||||
#include "ext2_fs.h"
|
||||
#include "ext2fs.h"
|
||||
|
||||
#if defined(__linux__) && defined(EXT2_OS_LINUX)
|
||||
#define CREATOR_OS EXT2_OS_LINUX
|
||||
#else
|
||||
#if defined(__GNU__) && defined(EXT2_OS_HURD)
|
||||
#define CREATOR_OS EXT2_OS_HURD
|
||||
#else
|
||||
#if defined(__FreeBSD__) && defined(EXT2_OS_FREEBSD)
|
||||
#define CREATOR_OS EXT2_OS_FREEBSD
|
||||
#else
|
||||
#if defined(LITES) && defined(EXT2_OS_LITES)
|
||||
#define CREATOR_OS EXT2_OS_LITES
|
||||
#else
|
||||
#define CREATOR_OS EXT2_OS_LINUX /* by default */
|
||||
#endif /* defined(LITES) && defined(EXT2_OS_LITES) */
|
||||
#endif /* defined(__FreeBSD__) && defined(EXT2_OS_FREEBSD) */
|
||||
#endif /* defined(__GNU__) && defined(EXT2_OS_HURD) */
|
||||
#endif /* defined(__linux__) && defined(EXT2_OS_LINUX) */
|
||||
|
||||
/*
|
||||
* Note we override the kernel include file's idea of what the default
|
||||
* check interval (never) should be. It's a good idea to check at
|
||||
* least *occasionally*, specially since servers will never rarely get
|
||||
* to reboot, since Linux is so robust these days. :-)
|
||||
*
|
||||
* 180 days (six months) seems like a good value.
|
||||
*/
|
||||
#ifdef EXT2_DFL_CHECKINTERVAL
|
||||
#undef EXT2_DFL_CHECKINTERVAL
|
||||
#endif
|
||||
#define EXT2_DFL_CHECKINTERVAL (86400L * 180L)
|
||||
|
||||
/*
|
||||
* Calculate the number of GDT blocks to reserve for online filesystem growth.
|
||||
* The absolute maximum number of GDT blocks we can reserve is determined by
|
||||
* the number of block pointers that can fit into a single block.
|
||||
*/
|
||||
static int calc_reserved_gdt_blocks(ext2_filsys fs)
|
||||
{
|
||||
struct ext2_super_block *sb = fs->super;
|
||||
unsigned long bpg = sb->s_blocks_per_group;
|
||||
unsigned int gdpb = fs->blocksize / sizeof(struct ext2_group_desc);
|
||||
unsigned long max_blocks = 0xffffffff;
|
||||
unsigned long rsv_groups;
|
||||
int rsv_gdb;
|
||||
|
||||
/* We set it at 1024x the current filesystem size, or
|
||||
* the upper block count limit (2^32), whichever is lower.
|
||||
*/
|
||||
if (sb->s_blocks_count < max_blocks / 1024)
|
||||
max_blocks = sb->s_blocks_count * 1024;
|
||||
rsv_groups = (max_blocks - sb->s_first_data_block + bpg - 1) / bpg;
|
||||
rsv_gdb = (rsv_groups + gdpb - 1) / gdpb - fs->desc_blocks;
|
||||
if (rsv_gdb > EXT2_ADDR_PER_BLOCK(sb))
|
||||
rsv_gdb = EXT2_ADDR_PER_BLOCK(sb);
|
||||
#ifdef RES_GDT_DEBUG
|
||||
printf("max_blocks %lu, rsv_groups = %lu, rsv_gdb = %lu\n",
|
||||
max_blocks, rsv_groups, rsv_gdb);
|
||||
#endif
|
||||
|
||||
return rsv_gdb;
|
||||
}
|
||||
|
||||
errcode_t ext2fs_initialize(const char *name, int flags,
|
||||
struct ext2_super_block *param,
|
||||
io_manager manager, ext2_filsys *ret_fs)
|
||||
{
|
||||
ext2_filsys fs;
|
||||
errcode_t retval;
|
||||
struct ext2_super_block *super;
|
||||
int frags_per_block;
|
||||
unsigned int rem;
|
||||
unsigned int overhead = 0;
|
||||
blk_t group_block;
|
||||
unsigned int ipg;
|
||||
dgrp_t i;
|
||||
blk_t numblocks;
|
||||
int rsv_gdt;
|
||||
char *buf;
|
||||
|
||||
if (!param || !param->s_blocks_count)
|
||||
return EXT2_ET_INVALID_ARGUMENT;
|
||||
|
||||
retval = ext2fs_get_mem(sizeof(struct struct_ext2_filsys), &fs);
|
||||
if (retval)
|
||||
return retval;
|
||||
|
||||
memset(fs, 0, sizeof(struct struct_ext2_filsys));
|
||||
fs->magic = EXT2_ET_MAGIC_EXT2FS_FILSYS;
|
||||
fs->flags = flags | EXT2_FLAG_RW;
|
||||
fs->umask = 022;
|
||||
#ifdef WORDS_BIGENDIAN
|
||||
fs->flags |= EXT2_FLAG_SWAP_BYTES;
|
||||
#endif
|
||||
retval = manager->open(name, IO_FLAG_RW, &fs->io);
|
||||
if (retval)
|
||||
goto cleanup;
|
||||
fs->image_io = fs->io;
|
||||
fs->io->app_data = fs;
|
||||
retval = ext2fs_get_mem(strlen(name)+1, &fs->device_name);
|
||||
if (retval)
|
||||
goto cleanup;
|
||||
|
||||
strcpy(fs->device_name, name);
|
||||
retval = ext2fs_get_mem(SUPERBLOCK_SIZE, &super);
|
||||
if (retval)
|
||||
goto cleanup;
|
||||
fs->super = super;
|
||||
|
||||
memset(super, 0, SUPERBLOCK_SIZE);
|
||||
|
||||
#define set_field(field, default) (super->field = param->field ? \
|
||||
param->field : (default))
|
||||
|
||||
super->s_magic = EXT2_SUPER_MAGIC;
|
||||
super->s_state = EXT2_VALID_FS;
|
||||
|
||||
set_field(s_log_block_size, 0); /* default blocksize: 1024 bytes */
|
||||
set_field(s_log_frag_size, 0); /* default fragsize: 1024 bytes */
|
||||
set_field(s_first_data_block, super->s_log_block_size ? 0 : 1);
|
||||
set_field(s_max_mnt_count, EXT2_DFL_MAX_MNT_COUNT);
|
||||
set_field(s_errors, EXT2_ERRORS_DEFAULT);
|
||||
set_field(s_feature_compat, 0);
|
||||
set_field(s_feature_incompat, 0);
|
||||
set_field(s_feature_ro_compat, 0);
|
||||
set_field(s_first_meta_bg, 0);
|
||||
if (super->s_feature_incompat & ~EXT2_LIB_FEATURE_INCOMPAT_SUPP) {
|
||||
retval = EXT2_ET_UNSUPP_FEATURE;
|
||||
goto cleanup;
|
||||
}
|
||||
if (super->s_feature_ro_compat & ~EXT2_LIB_FEATURE_RO_COMPAT_SUPP) {
|
||||
retval = EXT2_ET_RO_UNSUPP_FEATURE;
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
set_field(s_rev_level, EXT2_GOOD_OLD_REV);
|
||||
if (super->s_rev_level >= EXT2_DYNAMIC_REV) {
|
||||
set_field(s_first_ino, EXT2_GOOD_OLD_FIRST_INO);
|
||||
set_field(s_inode_size, EXT2_GOOD_OLD_INODE_SIZE);
|
||||
}
|
||||
|
||||
set_field(s_checkinterval, EXT2_DFL_CHECKINTERVAL);
|
||||
super->s_mkfs_time = super->s_lastcheck = time(NULL);
|
||||
|
||||
super->s_creator_os = CREATOR_OS;
|
||||
|
||||
fs->blocksize = EXT2_BLOCK_SIZE(super);
|
||||
fs->fragsize = EXT2_FRAG_SIZE(super);
|
||||
frags_per_block = fs->blocksize / fs->fragsize;
|
||||
|
||||
/* default: (fs->blocksize*8) blocks/group, up to 2^16 (GDT limit) */
|
||||
set_field(s_blocks_per_group, fs->blocksize * 8);
|
||||
if (super->s_blocks_per_group > EXT2_MAX_BLOCKS_PER_GROUP(super))
|
||||
super->s_blocks_per_group = EXT2_MAX_BLOCKS_PER_GROUP(super);
|
||||
super->s_frags_per_group = super->s_blocks_per_group * frags_per_block;
|
||||
|
||||
super->s_blocks_count = param->s_blocks_count;
|
||||
super->s_r_blocks_count = param->s_r_blocks_count;
|
||||
if (super->s_r_blocks_count >= param->s_blocks_count) {
|
||||
retval = EXT2_ET_INVALID_ARGUMENT;
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
/*
|
||||
* If we're creating an external journal device, we don't need
|
||||
* to bother with the rest.
|
||||
*/
|
||||
if (super->s_feature_incompat & EXT3_FEATURE_INCOMPAT_JOURNAL_DEV) {
|
||||
fs->group_desc_count = 0;
|
||||
ext2fs_mark_super_dirty(fs);
|
||||
*ret_fs = fs;
|
||||
return 0;
|
||||
}
|
||||
|
||||
retry:
|
||||
fs->group_desc_count = (super->s_blocks_count -
|
||||
super->s_first_data_block +
|
||||
EXT2_BLOCKS_PER_GROUP(super) - 1)
|
||||
/ EXT2_BLOCKS_PER_GROUP(super);
|
||||
if (fs->group_desc_count == 0) {
|
||||
retval = EXT2_ET_TOOSMALL;
|
||||
goto cleanup;
|
||||
}
|
||||
fs->desc_blocks = (fs->group_desc_count +
|
||||
EXT2_DESC_PER_BLOCK(super) - 1)
|
||||
/ EXT2_DESC_PER_BLOCK(super);
|
||||
|
||||
i = fs->blocksize >= 4096 ? 1 : 4096 / fs->blocksize;
|
||||
set_field(s_inodes_count, super->s_blocks_count / i);
|
||||
|
||||
/*
|
||||
* Make sure we have at least EXT2_FIRST_INO + 1 inodes, so
|
||||
* that we have enough inodes for the filesystem(!)
|
||||
*/
|
||||
if (super->s_inodes_count < EXT2_FIRST_INODE(super)+1)
|
||||
super->s_inodes_count = EXT2_FIRST_INODE(super)+1;
|
||||
|
||||
/*
|
||||
* There should be at least as many inodes as the user
|
||||
* requested. Figure out how many inodes per group that
|
||||
* should be. But make sure that we don't allocate more than
|
||||
* one bitmap's worth of inodes each group.
|
||||
*/
|
||||
ipg = (super->s_inodes_count + fs->group_desc_count - 1) /
|
||||
fs->group_desc_count;
|
||||
if (ipg > fs->blocksize * 8) {
|
||||
if (super->s_blocks_per_group >= 256) {
|
||||
/* Try again with slightly different parameters */
|
||||
super->s_blocks_per_group -= 8;
|
||||
super->s_blocks_count = param->s_blocks_count;
|
||||
super->s_frags_per_group = super->s_blocks_per_group *
|
||||
frags_per_block;
|
||||
goto retry;
|
||||
} else
|
||||
return EXT2_ET_TOO_MANY_INODES;
|
||||
}
|
||||
|
||||
if (ipg > (unsigned) EXT2_MAX_INODES_PER_GROUP(super))
|
||||
ipg = EXT2_MAX_INODES_PER_GROUP(super);
|
||||
|
||||
super->s_inodes_per_group = ipg;
|
||||
if (super->s_inodes_count > ipg * fs->group_desc_count)
|
||||
super->s_inodes_count = ipg * fs->group_desc_count;
|
||||
|
||||
/*
|
||||
* Make sure the number of inodes per group completely fills
|
||||
* the inode table blocks in the descriptor. If not, add some
|
||||
* additional inodes/group. Waste not, want not...
|
||||
*/
|
||||
fs->inode_blocks_per_group = (((super->s_inodes_per_group *
|
||||
EXT2_INODE_SIZE(super)) +
|
||||
EXT2_BLOCK_SIZE(super) - 1) /
|
||||
EXT2_BLOCK_SIZE(super));
|
||||
super->s_inodes_per_group = ((fs->inode_blocks_per_group *
|
||||
EXT2_BLOCK_SIZE(super)) /
|
||||
EXT2_INODE_SIZE(super));
|
||||
/*
|
||||
* Finally, make sure the number of inodes per group is a
|
||||
* multiple of 8. This is needed to simplify the bitmap
|
||||
* splicing code.
|
||||
*/
|
||||
super->s_inodes_per_group &= ~7;
|
||||
fs->inode_blocks_per_group = (((super->s_inodes_per_group *
|
||||
EXT2_INODE_SIZE(super)) +
|
||||
EXT2_BLOCK_SIZE(super) - 1) /
|
||||
EXT2_BLOCK_SIZE(super));
|
||||
|
||||
/*
|
||||
* adjust inode count to reflect the adjusted inodes_per_group
|
||||
*/
|
||||
super->s_inodes_count = super->s_inodes_per_group *
|
||||
fs->group_desc_count;
|
||||
super->s_free_inodes_count = super->s_inodes_count;
|
||||
|
||||
/*
|
||||
* check the number of reserved group descriptor table blocks
|
||||
*/
|
||||
if (super->s_feature_compat & EXT2_FEATURE_COMPAT_RESIZE_INODE)
|
||||
rsv_gdt = calc_reserved_gdt_blocks(fs);
|
||||
else
|
||||
rsv_gdt = 0;
|
||||
set_field(s_reserved_gdt_blocks, rsv_gdt);
|
||||
if (super->s_reserved_gdt_blocks > EXT2_ADDR_PER_BLOCK(super)) {
|
||||
retval = EXT2_ET_RES_GDT_BLOCKS;
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
/*
|
||||
* Overhead is the number of bookkeeping blocks per group. It
|
||||
* includes the superblock backup, the group descriptor
|
||||
* backups, the inode bitmap, the block bitmap, and the inode
|
||||
* table.
|
||||
*/
|
||||
|
||||
overhead = (int) (2 + fs->inode_blocks_per_group);
|
||||
|
||||
if (ext2fs_bg_has_super(fs, fs->group_desc_count - 1))
|
||||
overhead += 1 + fs->desc_blocks + super->s_reserved_gdt_blocks;
|
||||
|
||||
/* This can only happen if the user requested too many inodes */
|
||||
if (overhead > super->s_blocks_per_group)
|
||||
return EXT2_ET_TOO_MANY_INODES;
|
||||
|
||||
/*
|
||||
* See if the last group is big enough to support the
|
||||
* necessary data structures. If not, we need to get rid of
|
||||
* it.
|
||||
*/
|
||||
rem = ((super->s_blocks_count - super->s_first_data_block) %
|
||||
super->s_blocks_per_group);
|
||||
if ((fs->group_desc_count == 1) && rem && (rem < overhead))
|
||||
return EXT2_ET_TOOSMALL;
|
||||
if (rem && (rem < overhead+50)) {
|
||||
super->s_blocks_count -= rem;
|
||||
goto retry;
|
||||
}
|
||||
|
||||
/*
|
||||
* At this point we know how big the filesystem will be. So
|
||||
* we can do any and all allocations that depend on the block
|
||||
* count.
|
||||
*/
|
||||
|
||||
retval = ext2fs_get_mem(strlen(fs->device_name) + 80, &buf);
|
||||
if (retval)
|
||||
goto cleanup;
|
||||
|
||||
sprintf(buf, "block bitmap for %s", fs->device_name);
|
||||
retval = ext2fs_allocate_block_bitmap(fs, buf, &fs->block_map);
|
||||
if (retval)
|
||||
goto cleanup;
|
||||
|
||||
sprintf(buf, "inode bitmap for %s", fs->device_name);
|
||||
retval = ext2fs_allocate_inode_bitmap(fs, buf, &fs->inode_map);
|
||||
if (retval)
|
||||
goto cleanup;
|
||||
|
||||
ext2fs_free_mem(&buf);
|
||||
|
||||
retval = ext2fs_get_mem((size_t) fs->desc_blocks * fs->blocksize,
|
||||
&fs->group_desc);
|
||||
if (retval)
|
||||
goto cleanup;
|
||||
|
||||
memset(fs->group_desc, 0, (size_t) fs->desc_blocks * fs->blocksize);
|
||||
|
||||
/*
|
||||
* Reserve the superblock and group descriptors for each
|
||||
* group, and fill in the correct group statistics for group.
|
||||
* Note that although the block bitmap, inode bitmap, and
|
||||
* inode table have not been allocated (and in fact won't be
|
||||
* by this routine), they are accounted for nevertheless.
|
||||
*/
|
||||
group_block = super->s_first_data_block;
|
||||
super->s_free_blocks_count = 0;
|
||||
for (i = 0; i < fs->group_desc_count; i++) {
|
||||
numblocks = ext2fs_reserve_super_and_bgd(fs, i, fs->block_map);
|
||||
|
||||
super->s_free_blocks_count += numblocks;
|
||||
fs->group_desc[i].bg_free_blocks_count = numblocks;
|
||||
fs->group_desc[i].bg_free_inodes_count =
|
||||
fs->super->s_inodes_per_group;
|
||||
fs->group_desc[i].bg_used_dirs_count = 0;
|
||||
|
||||
group_block += super->s_blocks_per_group;
|
||||
}
|
||||
|
||||
ext2fs_mark_super_dirty(fs);
|
||||
ext2fs_mark_bb_dirty(fs);
|
||||
ext2fs_mark_ib_dirty(fs);
|
||||
|
||||
io_channel_set_blksize(fs->io, fs->blocksize);
|
||||
|
||||
*ret_fs = fs;
|
||||
return 0;
|
||||
cleanup:
|
||||
ext2fs_free(fs);
|
||||
return retval;
|
||||
}
|
33
e2fsprogs/old_e2fsprogs/ext2fs/inline.c
Normal file
33
e2fsprogs/old_e2fsprogs/ext2fs/inline.c
Normal file
@ -0,0 +1,33 @@
|
||||
/* vi: set sw=4 ts=4: */
|
||||
/*
|
||||
* inline.c --- Includes the inlined functions defined in the header
|
||||
* files as standalone functions, in case the application program
|
||||
* is compiled with inlining turned off.
|
||||
*
|
||||
* Copyright (C) 1993, 1994 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>
|
||||
#if HAVE_UNISTD_H
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
#include <fcntl.h>
|
||||
#include <time.h>
|
||||
#if HAVE_SYS_STAT_H
|
||||
#include <sys/stat.h>
|
||||
#endif
|
||||
#if HAVE_SYS_TYPES_H
|
||||
#include <sys/types.h>
|
||||
#endif
|
||||
|
||||
#include "ext2_fs.h"
|
||||
#define INCLUDE_INLINE_FUNCS
|
||||
#include "ext2fs.h"
|
||||
|
768
e2fsprogs/old_e2fsprogs/ext2fs/inode.c
Normal file
768
e2fsprogs/old_e2fsprogs/ext2fs/inode.c
Normal file
@ -0,0 +1,768 @@
|
||||
/* vi: set sw=4 ts=4: */
|
||||
/*
|
||||
* inode.c --- utility routines to read and write inodes
|
||||
*
|
||||
* Copyright (C) 1993, 1994, 1995, 1996, 1997 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>
|
||||
#if HAVE_UNISTD_H
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
#if HAVE_ERRNO_H
|
||||
#include <errno.h>
|
||||
#endif
|
||||
#if HAVE_SYS_STAT_H
|
||||
#include <sys/stat.h>
|
||||
#endif
|
||||
#if HAVE_SYS_TYPES_H
|
||||
#include <sys/types.h>
|
||||
#endif
|
||||
|
||||
#include "ext2_fs.h"
|
||||
#include "ext2fsP.h"
|
||||
#include "e2image.h"
|
||||
|
||||
struct ext2_struct_inode_scan {
|
||||
errcode_t magic;
|
||||
ext2_filsys fs;
|
||||
ext2_ino_t current_inode;
|
||||
blk_t current_block;
|
||||
dgrp_t current_group;
|
||||
ext2_ino_t inodes_left;
|
||||
blk_t blocks_left;
|
||||
dgrp_t groups_left;
|
||||
blk_t inode_buffer_blocks;
|
||||
char * inode_buffer;
|
||||
int inode_size;
|
||||
char * ptr;
|
||||
int bytes_left;
|
||||
char *temp_buffer;
|
||||
errcode_t (*done_group)(ext2_filsys fs,
|
||||
dgrp_t group,
|
||||
void * priv_data);
|
||||
void * done_group_data;
|
||||
int bad_block_ptr;
|
||||
int scan_flags;
|
||||
int reserved[6];
|
||||
};
|
||||
|
||||
/*
|
||||
* This routine flushes the icache, if it exists.
|
||||
*/
|
||||
errcode_t ext2fs_flush_icache(ext2_filsys fs)
|
||||
{
|
||||
int i;
|
||||
|
||||
if (!fs->icache)
|
||||
return 0;
|
||||
|
||||
for (i=0; i < fs->icache->cache_size; i++)
|
||||
fs->icache->cache[i].ino = 0;
|
||||
|
||||
fs->icache->buffer_blk = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static errcode_t create_icache(ext2_filsys fs)
|
||||
{
|
||||
errcode_t retval;
|
||||
|
||||
if (fs->icache)
|
||||
return 0;
|
||||
retval = ext2fs_get_mem(sizeof(struct ext2_inode_cache), &fs->icache);
|
||||
if (retval)
|
||||
return retval;
|
||||
|
||||
memset(fs->icache, 0, sizeof(struct ext2_inode_cache));
|
||||
retval = ext2fs_get_mem(fs->blocksize, &fs->icache->buffer);
|
||||
if (retval) {
|
||||
ext2fs_free_mem(&fs->icache);
|
||||
return retval;
|
||||
}
|
||||
fs->icache->buffer_blk = 0;
|
||||
fs->icache->cache_last = -1;
|
||||
fs->icache->cache_size = 4;
|
||||
fs->icache->refcount = 1;
|
||||
retval = ext2fs_get_mem(sizeof(struct ext2_inode_cache_ent)
|
||||
* fs->icache->cache_size,
|
||||
&fs->icache->cache);
|
||||
if (retval) {
|
||||
ext2fs_free_mem(&fs->icache->buffer);
|
||||
ext2fs_free_mem(&fs->icache);
|
||||
return retval;
|
||||
}
|
||||
ext2fs_flush_icache(fs);
|
||||
return 0;
|
||||
}
|
||||
|
||||
errcode_t ext2fs_open_inode_scan(ext2_filsys fs, int buffer_blocks,
|
||||
ext2_inode_scan *ret_scan)
|
||||
{
|
||||
ext2_inode_scan scan;
|
||||
errcode_t retval;
|
||||
errcode_t (*save_get_blocks)(ext2_filsys f, ext2_ino_t ino, blk_t *blocks);
|
||||
|
||||
EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS);
|
||||
|
||||
/*
|
||||
* If fs->badblocks isn't set, then set it --- since the inode
|
||||
* scanning functions require it.
|
||||
*/
|
||||
if (fs->badblocks == 0) {
|
||||
/*
|
||||
* Temporarly save fs->get_blocks and set it to zero,
|
||||
* for compatibility with old e2fsck's.
|
||||
*/
|
||||
save_get_blocks = fs->get_blocks;
|
||||
fs->get_blocks = 0;
|
||||
retval = ext2fs_read_bb_inode(fs, &fs->badblocks);
|
||||
if (retval) {
|
||||
ext2fs_badblocks_list_free(fs->badblocks);
|
||||
fs->badblocks = 0;
|
||||
}
|
||||
fs->get_blocks = save_get_blocks;
|
||||
}
|
||||
|
||||
retval = ext2fs_get_mem(sizeof(struct ext2_struct_inode_scan), &scan);
|
||||
if (retval)
|
||||
return retval;
|
||||
memset(scan, 0, sizeof(struct ext2_struct_inode_scan));
|
||||
|
||||
scan->magic = EXT2_ET_MAGIC_INODE_SCAN;
|
||||
scan->fs = fs;
|
||||
scan->inode_size = EXT2_INODE_SIZE(fs->super);
|
||||
scan->bytes_left = 0;
|
||||
scan->current_group = 0;
|
||||
scan->groups_left = fs->group_desc_count - 1;
|
||||
scan->inode_buffer_blocks = buffer_blocks ? buffer_blocks : 8;
|
||||
scan->current_block = scan->fs->
|
||||
group_desc[scan->current_group].bg_inode_table;
|
||||
scan->inodes_left = EXT2_INODES_PER_GROUP(scan->fs->super);
|
||||
scan->blocks_left = scan->fs->inode_blocks_per_group;
|
||||
retval = ext2fs_get_mem((size_t) (scan->inode_buffer_blocks *
|
||||
fs->blocksize),
|
||||
&scan->inode_buffer);
|
||||
scan->done_group = 0;
|
||||
scan->done_group_data = 0;
|
||||
scan->bad_block_ptr = 0;
|
||||
if (retval) {
|
||||
ext2fs_free_mem(&scan);
|
||||
return retval;
|
||||
}
|
||||
retval = ext2fs_get_mem(scan->inode_size, &scan->temp_buffer);
|
||||
if (retval) {
|
||||
ext2fs_free_mem(&scan->inode_buffer);
|
||||
ext2fs_free_mem(&scan);
|
||||
return retval;
|
||||
}
|
||||
if (scan->fs->badblocks && scan->fs->badblocks->num)
|
||||
scan->scan_flags |= EXT2_SF_CHK_BADBLOCKS;
|
||||
*ret_scan = scan;
|
||||
return 0;
|
||||
}
|
||||
|
||||
void ext2fs_close_inode_scan(ext2_inode_scan scan)
|
||||
{
|
||||
if (!scan || (scan->magic != EXT2_ET_MAGIC_INODE_SCAN))
|
||||
return;
|
||||
|
||||
ext2fs_free_mem(&scan->inode_buffer);
|
||||
scan->inode_buffer = NULL;
|
||||
ext2fs_free_mem(&scan->temp_buffer);
|
||||
scan->temp_buffer = NULL;
|
||||
ext2fs_free_mem(&scan);
|
||||
return;
|
||||
}
|
||||
|
||||
void ext2fs_set_inode_callback(ext2_inode_scan scan,
|
||||
errcode_t (*done_group)(ext2_filsys fs,
|
||||
dgrp_t group,
|
||||
void * priv_data),
|
||||
void *done_group_data)
|
||||
{
|
||||
if (!scan || (scan->magic != EXT2_ET_MAGIC_INODE_SCAN))
|
||||
return;
|
||||
|
||||
scan->done_group = done_group;
|
||||
scan->done_group_data = done_group_data;
|
||||
}
|
||||
|
||||
int ext2fs_inode_scan_flags(ext2_inode_scan scan, int set_flags,
|
||||
int clear_flags)
|
||||
{
|
||||
int old_flags;
|
||||
|
||||
if (!scan || (scan->magic != EXT2_ET_MAGIC_INODE_SCAN))
|
||||
return 0;
|
||||
|
||||
old_flags = scan->scan_flags;
|
||||
scan->scan_flags &= ~clear_flags;
|
||||
scan->scan_flags |= set_flags;
|
||||
return old_flags;
|
||||
}
|
||||
|
||||
/*
|
||||
* This function is called by ext2fs_get_next_inode when it needs to
|
||||
* get ready to read in a new blockgroup.
|
||||
*/
|
||||
static errcode_t get_next_blockgroup(ext2_inode_scan scan)
|
||||
{
|
||||
scan->current_group++;
|
||||
scan->groups_left--;
|
||||
|
||||
scan->current_block = scan->fs->
|
||||
group_desc[scan->current_group].bg_inode_table;
|
||||
|
||||
scan->current_inode = scan->current_group *
|
||||
EXT2_INODES_PER_GROUP(scan->fs->super);
|
||||
|
||||
scan->bytes_left = 0;
|
||||
scan->inodes_left = EXT2_INODES_PER_GROUP(scan->fs->super);
|
||||
scan->blocks_left = scan->fs->inode_blocks_per_group;
|
||||
return 0;
|
||||
}
|
||||
|
||||
errcode_t ext2fs_inode_scan_goto_blockgroup(ext2_inode_scan scan,
|
||||
int group)
|
||||
{
|
||||
scan->current_group = group - 1;
|
||||
scan->groups_left = scan->fs->group_desc_count - group;
|
||||
return get_next_blockgroup(scan);
|
||||
}
|
||||
|
||||
/*
|
||||
* This function is called by get_next_blocks() to check for bad
|
||||
* blocks in the inode table.
|
||||
*
|
||||
* This function assumes that badblocks_list->list is sorted in
|
||||
* increasing order.
|
||||
*/
|
||||
static errcode_t check_for_inode_bad_blocks(ext2_inode_scan scan,
|
||||
blk_t *num_blocks)
|
||||
{
|
||||
blk_t blk = scan->current_block;
|
||||
badblocks_list bb = scan->fs->badblocks;
|
||||
|
||||
/*
|
||||
* If the inode table is missing, then obviously there are no
|
||||
* bad blocks. :-)
|
||||
*/
|
||||
if (blk == 0)
|
||||
return 0;
|
||||
|
||||
/*
|
||||
* If the current block is greater than the bad block listed
|
||||
* in the bad block list, then advance the pointer until this
|
||||
* is no longer the case. If we run out of bad blocks, then
|
||||
* we don't need to do any more checking!
|
||||
*/
|
||||
while (blk > bb->list[scan->bad_block_ptr]) {
|
||||
if (++scan->bad_block_ptr >= bb->num) {
|
||||
scan->scan_flags &= ~EXT2_SF_CHK_BADBLOCKS;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* If the current block is equal to the bad block listed in
|
||||
* the bad block list, then handle that one block specially.
|
||||
* (We could try to handle runs of bad blocks, but that
|
||||
* only increases CPU efficiency by a small amount, at the
|
||||
* expense of a huge expense of code complexity, and for an
|
||||
* uncommon case at that.)
|
||||
*/
|
||||
if (blk == bb->list[scan->bad_block_ptr]) {
|
||||
scan->scan_flags |= EXT2_SF_BAD_INODE_BLK;
|
||||
*num_blocks = 1;
|
||||
if (++scan->bad_block_ptr >= bb->num)
|
||||
scan->scan_flags &= ~EXT2_SF_CHK_BADBLOCKS;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* If there is a bad block in the range that we're about to
|
||||
* read in, adjust the number of blocks to read so that we we
|
||||
* don't read in the bad block. (Then the next block to read
|
||||
* will be the bad block, which is handled in the above case.)
|
||||
*/
|
||||
if ((blk + *num_blocks) > bb->list[scan->bad_block_ptr])
|
||||
*num_blocks = (int) (bb->list[scan->bad_block_ptr] - blk);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* This function is called by ext2fs_get_next_inode when it needs to
|
||||
* read in more blocks from the current blockgroup's inode table.
|
||||
*/
|
||||
static errcode_t get_next_blocks(ext2_inode_scan scan)
|
||||
{
|
||||
blk_t num_blocks;
|
||||
errcode_t retval;
|
||||
|
||||
/*
|
||||
* Figure out how many blocks to read; we read at most
|
||||
* inode_buffer_blocks, and perhaps less if there aren't that
|
||||
* many blocks left to read.
|
||||
*/
|
||||
num_blocks = scan->inode_buffer_blocks;
|
||||
if (num_blocks > scan->blocks_left)
|
||||
num_blocks = scan->blocks_left;
|
||||
|
||||
/*
|
||||
* If the past block "read" was a bad block, then mark the
|
||||
* left-over extra bytes as also being bad.
|
||||
*/
|
||||
if (scan->scan_flags & EXT2_SF_BAD_INODE_BLK) {
|
||||
if (scan->bytes_left)
|
||||
scan->scan_flags |= EXT2_SF_BAD_EXTRA_BYTES;
|
||||
scan->scan_flags &= ~EXT2_SF_BAD_INODE_BLK;
|
||||
}
|
||||
|
||||
/*
|
||||
* Do inode bad block processing, if necessary.
|
||||
*/
|
||||
if (scan->scan_flags & EXT2_SF_CHK_BADBLOCKS) {
|
||||
retval = check_for_inode_bad_blocks(scan, &num_blocks);
|
||||
if (retval)
|
||||
return retval;
|
||||
}
|
||||
|
||||
if ((scan->scan_flags & EXT2_SF_BAD_INODE_BLK) ||
|
||||
(scan->current_block == 0)) {
|
||||
memset(scan->inode_buffer, 0,
|
||||
(size_t) num_blocks * scan->fs->blocksize);
|
||||
} else {
|
||||
retval = io_channel_read_blk(scan->fs->io,
|
||||
scan->current_block,
|
||||
(int) num_blocks,
|
||||
scan->inode_buffer);
|
||||
if (retval)
|
||||
return EXT2_ET_NEXT_INODE_READ;
|
||||
}
|
||||
scan->ptr = scan->inode_buffer;
|
||||
scan->bytes_left = num_blocks * scan->fs->blocksize;
|
||||
|
||||
scan->blocks_left -= num_blocks;
|
||||
if (scan->current_block)
|
||||
scan->current_block += num_blocks;
|
||||
return 0;
|
||||
}
|
||||
|
||||
errcode_t ext2fs_get_next_inode_full(ext2_inode_scan scan, ext2_ino_t *ino,
|
||||
struct ext2_inode *inode, int bufsize)
|
||||
{
|
||||
errcode_t retval;
|
||||
int extra_bytes = 0;
|
||||
|
||||
EXT2_CHECK_MAGIC(scan, EXT2_ET_MAGIC_INODE_SCAN);
|
||||
|
||||
/*
|
||||
* Do we need to start reading a new block group?
|
||||
*/
|
||||
if (scan->inodes_left <= 0) {
|
||||
force_new_group:
|
||||
if (scan->done_group) {
|
||||
retval = (scan->done_group)
|
||||
(scan->fs, scan->current_group,
|
||||
scan->done_group_data);
|
||||
if (retval)
|
||||
return retval;
|
||||
}
|
||||
if (scan->groups_left <= 0) {
|
||||
*ino = 0;
|
||||
return 0;
|
||||
}
|
||||
retval = get_next_blockgroup(scan);
|
||||
if (retval)
|
||||
return retval;
|
||||
}
|
||||
/*
|
||||
* This is done outside the above if statement so that the
|
||||
* check can be done for block group #0.
|
||||
*/
|
||||
if (scan->current_block == 0) {
|
||||
if (scan->scan_flags & EXT2_SF_SKIP_MISSING_ITABLE) {
|
||||
goto force_new_group;
|
||||
} else
|
||||
return EXT2_ET_MISSING_INODE_TABLE;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Have we run out of space in the inode buffer? If so, we
|
||||
* need to read in more blocks.
|
||||
*/
|
||||
if (scan->bytes_left < scan->inode_size) {
|
||||
memcpy(scan->temp_buffer, scan->ptr, scan->bytes_left);
|
||||
extra_bytes = scan->bytes_left;
|
||||
|
||||
retval = get_next_blocks(scan);
|
||||
if (retval)
|
||||
return retval;
|
||||
#if 0
|
||||
/*
|
||||
* XXX test Need check for used inode somehow.
|
||||
* (Note: this is hard.)
|
||||
*/
|
||||
if (is_empty_scan(scan))
|
||||
goto force_new_group;
|
||||
#endif
|
||||
}
|
||||
|
||||
retval = 0;
|
||||
if (extra_bytes) {
|
||||
memcpy(scan->temp_buffer+extra_bytes, scan->ptr,
|
||||
scan->inode_size - extra_bytes);
|
||||
scan->ptr += scan->inode_size - extra_bytes;
|
||||
scan->bytes_left -= scan->inode_size - extra_bytes;
|
||||
|
||||
#if BB_BIG_ENDIAN
|
||||
if ((scan->fs->flags & EXT2_FLAG_SWAP_BYTES) ||
|
||||
(scan->fs->flags & EXT2_FLAG_SWAP_BYTES_READ))
|
||||
ext2fs_swap_inode_full(scan->fs,
|
||||
(struct ext2_inode_large *) inode,
|
||||
(struct ext2_inode_large *) scan->temp_buffer,
|
||||
0, bufsize);
|
||||
else
|
||||
#endif
|
||||
*inode = *((struct ext2_inode *) scan->temp_buffer);
|
||||
if (scan->scan_flags & EXT2_SF_BAD_EXTRA_BYTES)
|
||||
retval = EXT2_ET_BAD_BLOCK_IN_INODE_TABLE;
|
||||
scan->scan_flags &= ~EXT2_SF_BAD_EXTRA_BYTES;
|
||||
} else {
|
||||
#if BB_BIG_ENDIAN
|
||||
if ((scan->fs->flags & EXT2_FLAG_SWAP_BYTES) ||
|
||||
(scan->fs->flags & EXT2_FLAG_SWAP_BYTES_READ))
|
||||
ext2fs_swap_inode_full(scan->fs,
|
||||
(struct ext2_inode_large *) inode,
|
||||
(struct ext2_inode_large *) scan->ptr,
|
||||
0, bufsize);
|
||||
else
|
||||
#endif
|
||||
memcpy(inode, scan->ptr, bufsize);
|
||||
scan->ptr += scan->inode_size;
|
||||
scan->bytes_left -= scan->inode_size;
|
||||
if (scan->scan_flags & EXT2_SF_BAD_INODE_BLK)
|
||||
retval = EXT2_ET_BAD_BLOCK_IN_INODE_TABLE;
|
||||
}
|
||||
|
||||
scan->inodes_left--;
|
||||
scan->current_inode++;
|
||||
*ino = scan->current_inode;
|
||||
return retval;
|
||||
}
|
||||
|
||||
errcode_t ext2fs_get_next_inode(ext2_inode_scan scan, ext2_ino_t *ino,
|
||||
struct ext2_inode *inode)
|
||||
{
|
||||
return ext2fs_get_next_inode_full(scan, ino, inode,
|
||||
sizeof(struct ext2_inode));
|
||||
}
|
||||
|
||||
/*
|
||||
* Functions to read and write a single inode.
|
||||
*/
|
||||
errcode_t ext2fs_read_inode_full(ext2_filsys fs, ext2_ino_t ino,
|
||||
struct ext2_inode * inode, int bufsize)
|
||||
{
|
||||
unsigned long group, block, block_nr, offset;
|
||||
char *ptr;
|
||||
errcode_t retval;
|
||||
int clen, i, inodes_per_block, length;
|
||||
io_channel io;
|
||||
|
||||
EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS);
|
||||
|
||||
/* Check to see if user has an override function */
|
||||
if (fs->read_inode) {
|
||||
retval = (fs->read_inode)(fs, ino, inode);
|
||||
if (retval != EXT2_ET_CALLBACK_NOTHANDLED)
|
||||
return retval;
|
||||
}
|
||||
/* Create inode cache if not present */
|
||||
if (!fs->icache) {
|
||||
retval = create_icache(fs);
|
||||
if (retval)
|
||||
return retval;
|
||||
}
|
||||
/* Check to see if it's in the inode cache */
|
||||
if (bufsize == sizeof(struct ext2_inode)) {
|
||||
/* only old good inode can be retrieve from the cache */
|
||||
for (i=0; i < fs->icache->cache_size; i++) {
|
||||
if (fs->icache->cache[i].ino == ino) {
|
||||
*inode = fs->icache->cache[i].inode;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
if ((ino == 0) || (ino > fs->super->s_inodes_count))
|
||||
return EXT2_ET_BAD_INODE_NUM;
|
||||
if (fs->flags & EXT2_FLAG_IMAGE_FILE) {
|
||||
inodes_per_block = fs->blocksize / EXT2_INODE_SIZE(fs->super);
|
||||
block_nr = fs->image_header->offset_inode / fs->blocksize;
|
||||
block_nr += (ino - 1) / inodes_per_block;
|
||||
offset = ((ino - 1) % inodes_per_block) *
|
||||
EXT2_INODE_SIZE(fs->super);
|
||||
io = fs->image_io;
|
||||
} else {
|
||||
group = (ino - 1) / EXT2_INODES_PER_GROUP(fs->super);
|
||||
offset = ((ino - 1) % EXT2_INODES_PER_GROUP(fs->super)) *
|
||||
EXT2_INODE_SIZE(fs->super);
|
||||
block = offset >> EXT2_BLOCK_SIZE_BITS(fs->super);
|
||||
if (!fs->group_desc[(unsigned)group].bg_inode_table)
|
||||
return EXT2_ET_MISSING_INODE_TABLE;
|
||||
block_nr = fs->group_desc[(unsigned)group].bg_inode_table +
|
||||
block;
|
||||
io = fs->io;
|
||||
}
|
||||
offset &= (EXT2_BLOCK_SIZE(fs->super) - 1);
|
||||
|
||||
length = EXT2_INODE_SIZE(fs->super);
|
||||
if (bufsize < length)
|
||||
length = bufsize;
|
||||
|
||||
ptr = (char *) inode;
|
||||
while (length) {
|
||||
clen = length;
|
||||
if ((offset + length) > fs->blocksize)
|
||||
clen = fs->blocksize - offset;
|
||||
|
||||
if (block_nr != fs->icache->buffer_blk) {
|
||||
retval = io_channel_read_blk(io, block_nr, 1,
|
||||
fs->icache->buffer);
|
||||
if (retval)
|
||||
return retval;
|
||||
fs->icache->buffer_blk = block_nr;
|
||||
}
|
||||
|
||||
memcpy(ptr, ((char *) fs->icache->buffer) + (unsigned) offset,
|
||||
clen);
|
||||
|
||||
offset = 0;
|
||||
length -= clen;
|
||||
ptr += clen;
|
||||
block_nr++;
|
||||
}
|
||||
|
||||
#if BB_BIG_ENDIAN
|
||||
if ((fs->flags & EXT2_FLAG_SWAP_BYTES) ||
|
||||
(fs->flags & EXT2_FLAG_SWAP_BYTES_READ))
|
||||
ext2fs_swap_inode_full(fs, (struct ext2_inode_large *) inode,
|
||||
(struct ext2_inode_large *) inode,
|
||||
0, length);
|
||||
#endif
|
||||
|
||||
/* Update the inode cache */
|
||||
fs->icache->cache_last = (fs->icache->cache_last + 1) %
|
||||
fs->icache->cache_size;
|
||||
fs->icache->cache[fs->icache->cache_last].ino = ino;
|
||||
fs->icache->cache[fs->icache->cache_last].inode = *inode;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
errcode_t ext2fs_read_inode(ext2_filsys fs, ext2_ino_t ino,
|
||||
struct ext2_inode * inode)
|
||||
{
|
||||
return ext2fs_read_inode_full(fs, ino, inode,
|
||||
sizeof(struct ext2_inode));
|
||||
}
|
||||
|
||||
errcode_t ext2fs_write_inode_full(ext2_filsys fs, ext2_ino_t ino,
|
||||
struct ext2_inode * inode, int bufsize)
|
||||
{
|
||||
unsigned long group, block, block_nr, offset;
|
||||
errcode_t retval = 0;
|
||||
struct ext2_inode_large temp_inode, *w_inode;
|
||||
char *ptr;
|
||||
int clen, i, length;
|
||||
|
||||
EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS);
|
||||
|
||||
/* Check to see if user provided an override function */
|
||||
if (fs->write_inode) {
|
||||
retval = (fs->write_inode)(fs, ino, inode);
|
||||
if (retval != EXT2_ET_CALLBACK_NOTHANDLED)
|
||||
return retval;
|
||||
}
|
||||
|
||||
/* Check to see if the inode cache needs to be updated */
|
||||
if (fs->icache) {
|
||||
for (i=0; i < fs->icache->cache_size; i++) {
|
||||
if (fs->icache->cache[i].ino == ino) {
|
||||
fs->icache->cache[i].inode = *inode;
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
retval = create_icache(fs);
|
||||
if (retval)
|
||||
return retval;
|
||||
}
|
||||
|
||||
if (!(fs->flags & EXT2_FLAG_RW))
|
||||
return EXT2_ET_RO_FILSYS;
|
||||
|
||||
if ((ino == 0) || (ino > fs->super->s_inodes_count))
|
||||
return EXT2_ET_BAD_INODE_NUM;
|
||||
|
||||
length = bufsize;
|
||||
if (length < EXT2_INODE_SIZE(fs->super))
|
||||
length = EXT2_INODE_SIZE(fs->super);
|
||||
|
||||
if (length > (int) sizeof(struct ext2_inode_large)) {
|
||||
w_inode = xmalloc(length);
|
||||
} else
|
||||
w_inode = &temp_inode;
|
||||
memset(w_inode, 0, length);
|
||||
|
||||
#if BB_BIG_ENDIAN
|
||||
if ((fs->flags & EXT2_FLAG_SWAP_BYTES) ||
|
||||
(fs->flags & EXT2_FLAG_SWAP_BYTES_WRITE))
|
||||
ext2fs_swap_inode_full(fs, w_inode,
|
||||
(struct ext2_inode_large *) inode,
|
||||
1, bufsize);
|
||||
else
|
||||
#endif
|
||||
memcpy(w_inode, inode, bufsize);
|
||||
|
||||
group = (ino - 1) / EXT2_INODES_PER_GROUP(fs->super);
|
||||
offset = ((ino - 1) % EXT2_INODES_PER_GROUP(fs->super)) *
|
||||
EXT2_INODE_SIZE(fs->super);
|
||||
block = offset >> EXT2_BLOCK_SIZE_BITS(fs->super);
|
||||
if (!fs->group_desc[(unsigned) group].bg_inode_table)
|
||||
return EXT2_ET_MISSING_INODE_TABLE;
|
||||
block_nr = fs->group_desc[(unsigned) group].bg_inode_table + block;
|
||||
|
||||
offset &= (EXT2_BLOCK_SIZE(fs->super) - 1);
|
||||
|
||||
length = EXT2_INODE_SIZE(fs->super);
|
||||
if (length > bufsize)
|
||||
length = bufsize;
|
||||
|
||||
ptr = (char *) w_inode;
|
||||
|
||||
while (length) {
|
||||
clen = length;
|
||||
if ((offset + length) > fs->blocksize)
|
||||
clen = fs->blocksize - offset;
|
||||
|
||||
if (fs->icache->buffer_blk != block_nr) {
|
||||
retval = io_channel_read_blk(fs->io, block_nr, 1,
|
||||
fs->icache->buffer);
|
||||
if (retval)
|
||||
goto errout;
|
||||
fs->icache->buffer_blk = block_nr;
|
||||
}
|
||||
|
||||
|
||||
memcpy((char *) fs->icache->buffer + (unsigned) offset,
|
||||
ptr, clen);
|
||||
|
||||
retval = io_channel_write_blk(fs->io, block_nr, 1,
|
||||
fs->icache->buffer);
|
||||
if (retval)
|
||||
goto errout;
|
||||
|
||||
offset = 0;
|
||||
ptr += clen;
|
||||
length -= clen;
|
||||
block_nr++;
|
||||
}
|
||||
|
||||
fs->flags |= EXT2_FLAG_CHANGED;
|
||||
errout:
|
||||
if (w_inode && w_inode != &temp_inode)
|
||||
free(w_inode);
|
||||
return retval;
|
||||
}
|
||||
|
||||
errcode_t ext2fs_write_inode(ext2_filsys fs, ext2_ino_t ino,
|
||||
struct ext2_inode *inode)
|
||||
{
|
||||
return ext2fs_write_inode_full(fs, ino, inode,
|
||||
sizeof(struct ext2_inode));
|
||||
}
|
||||
|
||||
/*
|
||||
* This function should be called when writing a new inode. It makes
|
||||
* sure that extra part of large inodes is initialized properly.
|
||||
*/
|
||||
errcode_t ext2fs_write_new_inode(ext2_filsys fs, ext2_ino_t ino,
|
||||
struct ext2_inode *inode)
|
||||
{
|
||||
struct ext2_inode *buf;
|
||||
int size = EXT2_INODE_SIZE(fs->super);
|
||||
struct ext2_inode_large *large_inode;
|
||||
|
||||
if (size == sizeof(struct ext2_inode))
|
||||
return ext2fs_write_inode_full(fs, ino, inode,
|
||||
sizeof(struct ext2_inode));
|
||||
|
||||
buf = xmalloc(size);
|
||||
|
||||
memset(buf, 0, size);
|
||||
*buf = *inode;
|
||||
|
||||
large_inode = (struct ext2_inode_large *) buf;
|
||||
large_inode->i_extra_isize = sizeof(struct ext2_inode_large) -
|
||||
EXT2_GOOD_OLD_INODE_SIZE;
|
||||
|
||||
return ext2fs_write_inode_full(fs, ino, buf, size);
|
||||
}
|
||||
|
||||
|
||||
errcode_t ext2fs_get_blocks(ext2_filsys fs, ext2_ino_t ino, blk_t *blocks)
|
||||
{
|
||||
struct ext2_inode inode;
|
||||
int i;
|
||||
errcode_t retval;
|
||||
|
||||
EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS);
|
||||
|
||||
if (ino > fs->super->s_inodes_count)
|
||||
return EXT2_ET_BAD_INODE_NUM;
|
||||
|
||||
if (fs->get_blocks) {
|
||||
if (!(*fs->get_blocks)(fs, ino, blocks))
|
||||
return 0;
|
||||
}
|
||||
retval = ext2fs_read_inode(fs, ino, &inode);
|
||||
if (retval)
|
||||
return retval;
|
||||
for (i=0; i < EXT2_N_BLOCKS; i++)
|
||||
blocks[i] = inode.i_block[i];
|
||||
return 0;
|
||||
}
|
||||
|
||||
errcode_t ext2fs_check_directory(ext2_filsys fs, ext2_ino_t ino)
|
||||
{
|
||||
struct ext2_inode inode;
|
||||
errcode_t retval;
|
||||
|
||||
EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS);
|
||||
|
||||
if (ino > fs->super->s_inodes_count)
|
||||
return EXT2_ET_BAD_INODE_NUM;
|
||||
|
||||
if (fs->check_directory) {
|
||||
retval = (fs->check_directory)(fs, ino);
|
||||
if (retval != EXT2_ET_CALLBACK_NOTHANDLED)
|
||||
return retval;
|
||||
}
|
||||
retval = ext2fs_read_inode(fs, ino, &inode);
|
||||
if (retval)
|
||||
return retval;
|
||||
if (!LINUX_S_ISDIR(inode.i_mode))
|
||||
return EXT2_ET_NO_DIRECTORY;
|
||||
return 0;
|
||||
}
|
||||
|
271
e2fsprogs/old_e2fsprogs/ext2fs/inode_io.c
Normal file
271
e2fsprogs/old_e2fsprogs/ext2fs/inode_io.c
Normal file
@ -0,0 +1,271 @@
|
||||
/* vi: set sw=4 ts=4: */
|
||||
/*
|
||||
* inode_io.c --- This is allows an inode in an ext2 filesystem image
|
||||
* to be accessed via the I/O manager interface.
|
||||
*
|
||||
* Copyright (C) 2002 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>
|
||||
#if HAVE_UNISTD_H
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
#if HAVE_ERRNO_H
|
||||
#include <errno.h>
|
||||
#endif
|
||||
#include <time.h>
|
||||
|
||||
#include "ext2_fs.h"
|
||||
#include "ext2fs.h"
|
||||
|
||||
/*
|
||||
* For checking structure magic numbers...
|
||||
*/
|
||||
|
||||
#define EXT2_CHECK_MAGIC(struct, code) \
|
||||
if ((struct)->magic != (code)) return (code)
|
||||
|
||||
struct inode_private_data {
|
||||
int magic;
|
||||
char name[32];
|
||||
ext2_file_t file;
|
||||
ext2_filsys fs;
|
||||
ext2_ino_t ino;
|
||||
struct ext2_inode inode;
|
||||
int flags;
|
||||
struct inode_private_data *next;
|
||||
};
|
||||
|
||||
#define CHANNEL_HAS_INODE 0x8000
|
||||
|
||||
static struct inode_private_data *top_intern;
|
||||
static int ino_unique = 0;
|
||||
|
||||
static errcode_t inode_open(const char *name, int flags, io_channel *channel);
|
||||
static errcode_t inode_close(io_channel channel);
|
||||
static errcode_t inode_set_blksize(io_channel channel, int blksize);
|
||||
static errcode_t inode_read_blk(io_channel channel, unsigned long block,
|
||||
int count, void *data);
|
||||
static errcode_t inode_write_blk(io_channel channel, unsigned long block,
|
||||
int count, const void *data);
|
||||
static errcode_t inode_flush(io_channel channel);
|
||||
static errcode_t inode_write_byte(io_channel channel, unsigned long offset,
|
||||
int size, const void *data);
|
||||
|
||||
static struct struct_io_manager struct_inode_manager = {
|
||||
EXT2_ET_MAGIC_IO_MANAGER,
|
||||
"Inode I/O Manager",
|
||||
inode_open,
|
||||
inode_close,
|
||||
inode_set_blksize,
|
||||
inode_read_blk,
|
||||
inode_write_blk,
|
||||
inode_flush,
|
||||
inode_write_byte
|
||||
};
|
||||
|
||||
io_manager inode_io_manager = &struct_inode_manager;
|
||||
|
||||
errcode_t ext2fs_inode_io_intern2(ext2_filsys fs, ext2_ino_t ino,
|
||||
struct ext2_inode *inode,
|
||||
char **name)
|
||||
{
|
||||
struct inode_private_data *data;
|
||||
errcode_t retval;
|
||||
|
||||
if ((retval = ext2fs_get_mem(sizeof(struct inode_private_data),
|
||||
&data)))
|
||||
return retval;
|
||||
data->magic = EXT2_ET_MAGIC_INODE_IO_CHANNEL;
|
||||
sprintf(data->name, "%u:%d", ino, ino_unique++);
|
||||
data->file = 0;
|
||||
data->fs = fs;
|
||||
data->ino = ino;
|
||||
data->flags = 0;
|
||||
if (inode) {
|
||||
memcpy(&data->inode, inode, sizeof(struct ext2_inode));
|
||||
data->flags |= CHANNEL_HAS_INODE;
|
||||
}
|
||||
data->next = top_intern;
|
||||
top_intern = data;
|
||||
*name = data->name;
|
||||
return 0;
|
||||
}
|
||||
|
||||
errcode_t ext2fs_inode_io_intern(ext2_filsys fs, ext2_ino_t ino,
|
||||
char **name)
|
||||
{
|
||||
return ext2fs_inode_io_intern2(fs, ino, NULL, name);
|
||||
}
|
||||
|
||||
|
||||
static errcode_t inode_open(const char *name, int flags, io_channel *channel)
|
||||
{
|
||||
io_channel io = NULL;
|
||||
struct inode_private_data *prev, *data = NULL;
|
||||
errcode_t retval;
|
||||
int open_flags;
|
||||
|
||||
if (name == 0)
|
||||
return EXT2_ET_BAD_DEVICE_NAME;
|
||||
|
||||
for (data = top_intern, prev = NULL; data;
|
||||
prev = data, data = data->next)
|
||||
if (strcmp(name, data->name) == 0)
|
||||
break;
|
||||
if (!data)
|
||||
return ENOENT;
|
||||
if (prev)
|
||||
prev->next = data->next;
|
||||
else
|
||||
top_intern = data->next;
|
||||
|
||||
retval = ext2fs_get_mem(sizeof(struct struct_io_channel), &io);
|
||||
if (retval)
|
||||
goto cleanup;
|
||||
memset(io, 0, sizeof(struct struct_io_channel));
|
||||
|
||||
io->magic = EXT2_ET_MAGIC_IO_CHANNEL;
|
||||
io->manager = inode_io_manager;
|
||||
retval = ext2fs_get_mem(strlen(name)+1, &io->name);
|
||||
if (retval)
|
||||
goto cleanup;
|
||||
|
||||
strcpy(io->name, name);
|
||||
io->private_data = data;
|
||||
io->block_size = 1024;
|
||||
io->read_error = 0;
|
||||
io->write_error = 0;
|
||||
io->refcount = 1;
|
||||
|
||||
open_flags = (flags & IO_FLAG_RW) ? EXT2_FILE_WRITE : 0;
|
||||
retval = ext2fs_file_open2(data->fs, data->ino,
|
||||
(data->flags & CHANNEL_HAS_INODE) ?
|
||||
&data->inode : 0, open_flags,
|
||||
&data->file);
|
||||
if (retval)
|
||||
goto cleanup;
|
||||
|
||||
*channel = io;
|
||||
return 0;
|
||||
|
||||
cleanup:
|
||||
if (data) {
|
||||
ext2fs_free_mem(&data);
|
||||
}
|
||||
if (io)
|
||||
ext2fs_free_mem(&io);
|
||||
return retval;
|
||||
}
|
||||
|
||||
static errcode_t inode_close(io_channel channel)
|
||||
{
|
||||
struct inode_private_data *data;
|
||||
errcode_t retval = 0;
|
||||
|
||||
EXT2_CHECK_MAGIC(channel, EXT2_ET_MAGIC_IO_CHANNEL);
|
||||
data = (struct inode_private_data *) channel->private_data;
|
||||
EXT2_CHECK_MAGIC(data, EXT2_ET_MAGIC_INODE_IO_CHANNEL);
|
||||
|
||||
if (--channel->refcount > 0)
|
||||
return 0;
|
||||
|
||||
retval = ext2fs_file_close(data->file);
|
||||
|
||||
ext2fs_free_mem(&channel->private_data);
|
||||
if (channel->name)
|
||||
ext2fs_free_mem(&channel->name);
|
||||
ext2fs_free_mem(&channel);
|
||||
return retval;
|
||||
}
|
||||
|
||||
static errcode_t inode_set_blksize(io_channel channel, int blksize)
|
||||
{
|
||||
struct inode_private_data *data;
|
||||
|
||||
EXT2_CHECK_MAGIC(channel, EXT2_ET_MAGIC_IO_CHANNEL);
|
||||
data = (struct inode_private_data *) channel->private_data;
|
||||
EXT2_CHECK_MAGIC(data, EXT2_ET_MAGIC_INODE_IO_CHANNEL);
|
||||
|
||||
channel->block_size = blksize;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static errcode_t inode_read_blk(io_channel channel, unsigned long block,
|
||||
int count, void *buf)
|
||||
{
|
||||
struct inode_private_data *data;
|
||||
errcode_t retval;
|
||||
|
||||
EXT2_CHECK_MAGIC(channel, EXT2_ET_MAGIC_IO_CHANNEL);
|
||||
data = (struct inode_private_data *) channel->private_data;
|
||||
EXT2_CHECK_MAGIC(data, EXT2_ET_MAGIC_INODE_IO_CHANNEL);
|
||||
|
||||
if ((retval = ext2fs_file_lseek(data->file,
|
||||
block * channel->block_size,
|
||||
EXT2_SEEK_SET, 0)))
|
||||
return retval;
|
||||
|
||||
count = (count < 0) ? -count : (count * channel->block_size);
|
||||
|
||||
return ext2fs_file_read(data->file, buf, count, 0);
|
||||
}
|
||||
|
||||
static errcode_t inode_write_blk(io_channel channel, unsigned long block,
|
||||
int count, const void *buf)
|
||||
{
|
||||
struct inode_private_data *data;
|
||||
errcode_t retval;
|
||||
|
||||
EXT2_CHECK_MAGIC(channel, EXT2_ET_MAGIC_IO_CHANNEL);
|
||||
data = (struct inode_private_data *) channel->private_data;
|
||||
EXT2_CHECK_MAGIC(data, EXT2_ET_MAGIC_INODE_IO_CHANNEL);
|
||||
|
||||
if ((retval = ext2fs_file_lseek(data->file,
|
||||
block * channel->block_size,
|
||||
EXT2_SEEK_SET, 0)))
|
||||
return retval;
|
||||
|
||||
count = (count < 0) ? -count : (count * channel->block_size);
|
||||
|
||||
return ext2fs_file_write(data->file, buf, count, 0);
|
||||
}
|
||||
|
||||
static errcode_t inode_write_byte(io_channel channel, unsigned long offset,
|
||||
int size, const void *buf)
|
||||
{
|
||||
struct inode_private_data *data;
|
||||
errcode_t retval = 0;
|
||||
|
||||
EXT2_CHECK_MAGIC(channel, EXT2_ET_MAGIC_IO_CHANNEL);
|
||||
data = (struct inode_private_data *) channel->private_data;
|
||||
EXT2_CHECK_MAGIC(data, EXT2_ET_MAGIC_INODE_IO_CHANNEL);
|
||||
|
||||
if ((retval = ext2fs_file_lseek(data->file, offset,
|
||||
EXT2_SEEK_SET, 0)))
|
||||
return retval;
|
||||
|
||||
return ext2fs_file_write(data->file, buf, size, 0);
|
||||
}
|
||||
|
||||
/*
|
||||
* Flush data buffers to disk.
|
||||
*/
|
||||
static errcode_t inode_flush(io_channel channel)
|
||||
{
|
||||
struct inode_private_data *data;
|
||||
|
||||
EXT2_CHECK_MAGIC(channel, EXT2_ET_MAGIC_IO_CHANNEL);
|
||||
data = (struct inode_private_data *) channel->private_data;
|
||||
EXT2_CHECK_MAGIC(data, EXT2_ET_MAGIC_INODE_IO_CHANNEL);
|
||||
|
||||
return ext2fs_file_flush(data->file);
|
||||
}
|
||||
|
70
e2fsprogs/old_e2fsprogs/ext2fs/io_manager.c
Normal file
70
e2fsprogs/old_e2fsprogs/ext2fs/io_manager.c
Normal file
@ -0,0 +1,70 @@
|
||||
/* vi: set sw=4 ts=4: */
|
||||
/*
|
||||
* io_manager.c --- the I/O manager abstraction
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#if HAVE_UNISTD_H
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
#include <fcntl.h>
|
||||
#include <time.h>
|
||||
#if HAVE_SYS_STAT_H
|
||||
#include <sys/stat.h>
|
||||
#endif
|
||||
#if HAVE_SYS_TYPES_H
|
||||
#include <sys/types.h>
|
||||
#endif
|
||||
|
||||
#include "ext2_fs.h"
|
||||
#include "ext2fs.h"
|
||||
|
||||
errcode_t io_channel_set_options(io_channel channel, const char *opts)
|
||||
{
|
||||
errcode_t retval = 0;
|
||||
char *next, *ptr, *options, *arg;
|
||||
|
||||
EXT2_CHECK_MAGIC(channel, EXT2_ET_MAGIC_IO_CHANNEL);
|
||||
|
||||
if (!opts)
|
||||
return 0;
|
||||
|
||||
if (!channel->manager->set_option)
|
||||
return EXT2_ET_INVALID_ARGUMENT;
|
||||
|
||||
options = malloc(strlen(opts)+1);
|
||||
if (!options)
|
||||
return EXT2_ET_NO_MEMORY;
|
||||
strcpy(options, opts);
|
||||
ptr = options;
|
||||
|
||||
while (ptr && *ptr) {
|
||||
next = strchr(ptr, '&');
|
||||
if (next)
|
||||
*next++ = 0;
|
||||
|
||||
arg = strchr(ptr, '=');
|
||||
if (arg)
|
||||
*arg++ = 0;
|
||||
|
||||
retval = (channel->manager->set_option)(channel, ptr, arg);
|
||||
if (retval)
|
||||
break;
|
||||
ptr = next;
|
||||
}
|
||||
free(options);
|
||||
return retval;
|
||||
}
|
||||
|
||||
errcode_t io_channel_write_byte(io_channel channel, unsigned long offset,
|
||||
int count, const void *data)
|
||||
{
|
||||
EXT2_CHECK_MAGIC(channel, EXT2_ET_MAGIC_IO_CHANNEL);
|
||||
|
||||
if (channel->manager->write_byte)
|
||||
return channel->manager->write_byte(channel, offset,
|
||||
count, data);
|
||||
|
||||
return EXT2_ET_UNIMPLEMENTED;
|
||||
}
|
115
e2fsprogs/old_e2fsprogs/ext2fs/irel.h
Normal file
115
e2fsprogs/old_e2fsprogs/ext2fs/irel.h
Normal file
@ -0,0 +1,115 @@
|
||||
/* vi: set sw=4 ts=4: */
|
||||
/*
|
||||
* irel.h
|
||||
*
|
||||
* Copyright (C) 1996, 1997 Theodore Ts'o.
|
||||
*
|
||||
* %Begin-Header%
|
||||
* This file may be redistributed under the terms of the GNU Public
|
||||
* License.
|
||||
* %End-Header%
|
||||
*/
|
||||
|
||||
struct ext2_inode_reference {
|
||||
blk_t block;
|
||||
__u16 offset;
|
||||
};
|
||||
|
||||
struct ext2_inode_relocate_entry {
|
||||
ext2_ino_t new;
|
||||
ext2_ino_t orig;
|
||||
__u16 flags;
|
||||
__u16 max_refs;
|
||||
};
|
||||
|
||||
typedef struct ext2_inode_relocation_table *ext2_irel;
|
||||
|
||||
struct ext2_inode_relocation_table {
|
||||
__u32 magic;
|
||||
char *name;
|
||||
ext2_ino_t current;
|
||||
void *priv_data;
|
||||
|
||||
/*
|
||||
* Add an inode relocation entry.
|
||||
*/
|
||||
errcode_t (*put)(ext2_irel irel, ext2_ino_t old,
|
||||
struct ext2_inode_relocate_entry *ent);
|
||||
/*
|
||||
* Get an inode relocation entry.
|
||||
*/
|
||||
errcode_t (*get)(ext2_irel irel, ext2_ino_t old,
|
||||
struct ext2_inode_relocate_entry *ent);
|
||||
|
||||
/*
|
||||
* Get an inode relocation entry by its original inode number
|
||||
*/
|
||||
errcode_t (*get_by_orig)(ext2_irel irel, ext2_ino_t orig, ext2_ino_t *old,
|
||||
struct ext2_inode_relocate_entry *ent);
|
||||
|
||||
/*
|
||||
* Initialize for iterating over the inode relocation entries.
|
||||
*/
|
||||
errcode_t (*start_iter)(ext2_irel irel);
|
||||
|
||||
/*
|
||||
* The iterator function for the inode relocation entries.
|
||||
* Returns an inode number of 0 when out of entries.
|
||||
*/
|
||||
errcode_t (*next)(ext2_irel irel, ext2_ino_t *old,
|
||||
struct ext2_inode_relocate_entry *ent);
|
||||
|
||||
/*
|
||||
* Add an inode reference (i.e., note the fact that a
|
||||
* particular block/offset contains a reference to an inode)
|
||||
*/
|
||||
errcode_t (*add_ref)(ext2_irel irel, ext2_ino_t ino,
|
||||
struct ext2_inode_reference *ref);
|
||||
|
||||
/*
|
||||
* Initialize for iterating over the inode references for a
|
||||
* particular inode.
|
||||
*/
|
||||
errcode_t (*start_iter_ref)(ext2_irel irel, ext2_ino_t ino);
|
||||
|
||||
/*
|
||||
* The iterator function for the inode references for an
|
||||
* inode. The references for only one inode can be interator
|
||||
* over at a time, as the iterator state is stored in ext2_irel.
|
||||
*/
|
||||
errcode_t (*next_ref)(ext2_irel irel,
|
||||
struct ext2_inode_reference *ref);
|
||||
|
||||
/*
|
||||
* Move the inode relocation table from one inode number to
|
||||
* another. Note that the inode references also must move.
|
||||
*/
|
||||
errcode_t (*move)(ext2_irel irel, ext2_ino_t old, ext2_ino_t new);
|
||||
|
||||
/*
|
||||
* Remove an inode relocation entry, along with all of the
|
||||
* inode references.
|
||||
*/
|
||||
errcode_t (*delete)(ext2_irel irel, ext2_ino_t old);
|
||||
|
||||
/*
|
||||
* Free the inode relocation table.
|
||||
*/
|
||||
errcode_t (*free)(ext2_irel irel);
|
||||
};
|
||||
|
||||
errcode_t ext2fs_irel_memarray_create(char *name, ext2_ino_t max_inode,
|
||||
ext2_irel *irel);
|
||||
|
||||
#define ext2fs_irel_put(irel, old, ent) ((irel)->put((irel), old, ent))
|
||||
#define ext2fs_irel_get(irel, old, ent) ((irel)->get((irel), old, ent))
|
||||
#define ext2fs_irel_get_by_orig(irel, orig, old, ent) \
|
||||
((irel)->get_by_orig((irel), orig, old, ent))
|
||||
#define ext2fs_irel_start_iter(irel) ((irel)->start_iter((irel)))
|
||||
#define ext2fs_irel_next(irel, old, ent) ((irel)->next((irel), old, ent))
|
||||
#define ext2fs_irel_add_ref(irel, ino, ref) ((irel)->add_ref((irel), ino, ref))
|
||||
#define ext2fs_irel_start_iter_ref(irel, ino) ((irel)->start_iter_ref((irel), ino))
|
||||
#define ext2fs_irel_next_ref(irel, ref) ((irel)->next_ref((irel), ref))
|
||||
#define ext2fs_irel_move(irel, old, new) ((irel)->move((irel), old, new))
|
||||
#define ext2fs_irel_delete(irel, old) ((irel)->delete((irel), old))
|
||||
#define ext2fs_irel_free(irel) ((irel)->free((irel)))
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user