9
0
Fork 0

remove uncompilable filesystems

This commit is contained in:
Sascha Hauer 2007-09-21 14:02:08 +02:00
parent a83669c197
commit 9a365ade16
31 changed files with 0 additions and 9701 deletions

View File

@ -1,52 +0,0 @@
#
# (C) Copyright 2006
# Wolfgang Denk, DENX Software Engineering, wd@denx.de.
#
# (C) Copyright 2003
# Pavel Bartusek, Sysgo Real-Time Solutions AG, pba@sysgo.de
#
#
# See file CREDITS for list of people who contributed to this
# project.
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License as
# published by the Free Software Foundation; either version 2 of
# the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston,
# MA 02111-1307 USA
#
include $(TOPDIR)/config.mk
LIB = $(obj)libext2fs.a
AOBJS =
COBJS = ext2fs.o dev.o
SRCS := $(AOBJS:.o=.S) $(COBJS:.o=.c)
OBJS := $(addprefix $(obj),$(AOBJS) $(COBJS))
#CPPFLAGS +=
all: $(LIB) $(AOBJS)
$(LIB): $(obj).depend $(OBJS)
$(AR) $(ARFLAGS) $@ $(OBJS)
#########################################################################
# defines $(obj).depend target
include $(SRCTREE)/rules.mk
sinclude $(obj).depend
#########################################################################

View File

@ -1,126 +0,0 @@
/*
* (C) Copyright 2004
* esd gmbh <www.esd-electronics.com>
* Reinhard Arlt <reinhard.arlt@esd-electronics.com>
*
* based on code of fs/reiserfs/dev.c by
*
* (C) Copyright 2003 - 2004
* Sysgo AG, <www.elinos.com>, Pavel Bartusek <pba@sysgo.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include <common.h>
#if (CONFIG_COMMANDS & CFG_CMD_EXT2)
#include <config.h>
#include <ext2fs.h>
static block_dev_desc_t *ext2fs_block_dev_desc;
static disk_partition_t part_info;
int ext2fs_set_blk_dev (block_dev_desc_t * rbdd, int part)
{
ext2fs_block_dev_desc = rbdd;
if (part == 0) {
/* disk doesn't use partition table */
part_info.start = 0;
part_info.size = rbdd->lba;
part_info.blksz = rbdd->blksz;
} else {
if (get_partition_info
(ext2fs_block_dev_desc, part, &part_info)) {
return 0;
}
}
return (part_info.size);
}
int ext2fs_devread (int sector, int byte_offset, int byte_len, char *buf) {
char sec_buf[SECTOR_SIZE];
unsigned block_len;
/*
* Check partition boundaries
*/
if ((sector < 0)
|| ((sector + ((byte_offset + byte_len - 1) >> SECTOR_BITS)) >=
part_info.size)) {
/* errnum = ERR_OUTSIDE_PART; */
printf (" ** ext2fs_devread() read outside partition sector %d\n", sector);
return (0);
}
/*
* Get the read to the beginning of a partition.
*/
sector += byte_offset >> SECTOR_BITS;
byte_offset &= SECTOR_SIZE - 1;
debug (" <%d, %d, %d>\n", sector, byte_offset, byte_len);
if (ext2fs_block_dev_desc == NULL) {
printf ("** Invalid Block Device Descriptor (NULL)\n");
return (0);
}
if (byte_offset != 0) {
/* read first part which isn't aligned with start of sector */
if (ext2fs_block_dev_desc->
block_read (ext2fs_block_dev_desc->dev,
part_info.start + sector, 1,
(unsigned long *) sec_buf) != 1) {
printf (" ** ext2fs_devread() read error **\n");
return (0);
}
memcpy (buf, sec_buf + byte_offset,
min (SECTOR_SIZE - byte_offset, byte_len));
buf += min (SECTOR_SIZE - byte_offset, byte_len);
byte_len -= min (SECTOR_SIZE - byte_offset, byte_len);
sector++;
}
/* read sector aligned part */
block_len = byte_len & ~(SECTOR_SIZE - 1);
if (ext2fs_block_dev_desc->block_read (ext2fs_block_dev_desc->dev,
part_info.start + sector,
block_len / SECTOR_SIZE,
(unsigned long *) buf) !=
block_len / SECTOR_SIZE) {
printf (" ** ext2fs_devread() read error - block\n");
return (0);
}
buf += block_len;
byte_len -= block_len;
sector += block_len / SECTOR_SIZE;
if (byte_len != 0) {
/* read rest of data which are not in whole sector */
if (ext2fs_block_dev_desc->
block_read (ext2fs_block_dev_desc->dev,
part_info.start + sector, 1,
(unsigned long *) sec_buf) != 1) {
printf (" ** ext2fs_devread() read error - last part\n");
return (0);
}
memcpy (buf, sec_buf, byte_len);
}
return (1);
}
#endif /* CFG_CMD_EXT2FS */

View File

@ -1,878 +0,0 @@
/*
* (C) Copyright 2004
* esd gmbh <www.esd-electronics.com>
* Reinhard Arlt <reinhard.arlt@esd-electronics.com>
*
* based on code from grub2 fs/ext2.c and fs/fshelp.c by
*
* GRUB -- GRand Unified Bootloader
* Copyright (C) 2003, 2004 Free Software Foundation, Inc.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include <common.h>
#if (CONFIG_COMMANDS & CFG_CMD_EXT2)
#include <ext2fs.h>
#include <malloc.h>
#include <asm/byteorder.h>
extern int ext2fs_devread (int sector, int byte_offset, int byte_len,
char *buf);
/* Magic value used to identify an ext2 filesystem. */
#define EXT2_MAGIC 0xEF53
/* Amount of indirect blocks in an inode. */
#define INDIRECT_BLOCKS 12
/* Maximum lenght of a pathname. */
#define EXT2_PATH_MAX 4096
/* Maximum nesting of symlinks, used to prevent a loop. */
#define EXT2_MAX_SYMLINKCNT 8
/* Filetype used in directory entry. */
#define FILETYPE_UNKNOWN 0
#define FILETYPE_REG 1
#define FILETYPE_DIRECTORY 2
#define FILETYPE_SYMLINK 7
/* Filetype information as used in inodes. */
#define FILETYPE_INO_MASK 0170000
#define FILETYPE_INO_REG 0100000
#define FILETYPE_INO_DIRECTORY 0040000
#define FILETYPE_INO_SYMLINK 0120000
/* Bits used as offset in sector */
#define DISK_SECTOR_BITS 9
/* Log2 size of ext2 block in 512 blocks. */
#define LOG2_EXT2_BLOCK_SIZE(data) (__le32_to_cpu (data->sblock.log2_block_size) + 1)
/* Log2 size of ext2 block in bytes. */
#define LOG2_BLOCK_SIZE(data) (__le32_to_cpu (data->sblock.log2_block_size) + 10)
/* The size of an ext2 block in bytes. */
#define EXT2_BLOCK_SIZE(data) (1 << LOG2_BLOCK_SIZE(data))
/* The ext2 superblock. */
struct ext2_sblock {
uint32_t total_inodes;
uint32_t total_blocks;
uint32_t reserved_blocks;
uint32_t free_blocks;
uint32_t free_inodes;
uint32_t first_data_block;
uint32_t log2_block_size;
uint32_t log2_fragment_size;
uint32_t blocks_per_group;
uint32_t fragments_per_group;
uint32_t inodes_per_group;
uint32_t mtime;
uint32_t utime;
uint16_t mnt_count;
uint16_t max_mnt_count;
uint16_t magic;
uint16_t fs_state;
uint16_t error_handling;
uint16_t minor_revision_level;
uint32_t lastcheck;
uint32_t checkinterval;
uint32_t creator_os;
uint32_t revision_level;
uint16_t uid_reserved;
uint16_t gid_reserved;
uint32_t first_inode;
uint16_t inode_size;
uint16_t block_group_number;
uint32_t feature_compatibility;
uint32_t feature_incompat;
uint32_t feature_ro_compat;
uint32_t unique_id[4];
char volume_name[16];
char last_mounted_on[64];
uint32_t compression_info;
};
/* The ext2 blockgroup. */
struct ext2_block_group {
uint32_t block_id;
uint32_t inode_id;
uint32_t inode_table_id;
uint16_t free_blocks;
uint16_t free_inodes;
uint16_t pad;
uint32_t reserved[3];
};
/* The ext2 inode. */
struct ext2_inode {
uint16_t mode;
uint16_t uid;
uint32_t size;
uint32_t atime;
uint32_t ctime;
uint32_t mtime;
uint32_t dtime;
uint16_t gid;
uint16_t nlinks;
uint32_t blockcnt; /* Blocks of 512 bytes!! */
uint32_t flags;
uint32_t osd1;
union {
struct datablocks {
uint32_t dir_blocks[INDIRECT_BLOCKS];
uint32_t indir_block;
uint32_t double_indir_block;
uint32_t tripple_indir_block;
} blocks;
char symlink[60];
} b;
uint32_t version;
uint32_t acl;
uint32_t dir_acl;
uint32_t fragment_addr;
uint32_t osd2[3];
};
/* The header of an ext2 directory entry. */
struct ext2_dirent {
uint32_t inode;
uint16_t direntlen;
uint8_t namelen;
uint8_t filetype;
};
struct ext2fs_node {
struct ext2_data *data;
struct ext2_inode inode;
int ino;
int inode_read;
};
/* Information about a "mounted" ext2 filesystem. */
struct ext2_data {
struct ext2_sblock sblock;
struct ext2_inode *inode;
struct ext2fs_node diropen;
};
typedef struct ext2fs_node *ext2fs_node_t;
struct ext2_data *ext2fs_root = NULL;
ext2fs_node_t ext2fs_file = NULL;
int symlinknest = 0;
uint32_t *indir1_block = NULL;
int indir1_size = 0;
int indir1_blkno = -1;
uint32_t *indir2_block = NULL;
int indir2_size = 0;
int indir2_blkno = -1;
static int ext2fs_blockgroup
(struct ext2_data *data, int group, struct ext2_block_group *blkgrp) {
#ifdef DEBUG
printf ("ext2fs read blockgroup\n");
#endif
return (ext2fs_devread
(((__le32_to_cpu (data->sblock.first_data_block) +
1) << LOG2_EXT2_BLOCK_SIZE (data)),
group * sizeof (struct ext2_block_group),
sizeof (struct ext2_block_group), (char *) blkgrp));
}
static int ext2fs_read_inode
(struct ext2_data *data, int ino, struct ext2_inode *inode) {
struct ext2_block_group blkgrp;
struct ext2_sblock *sblock = &data->sblock;
int inodes_per_block;
int status;
unsigned int blkno;
unsigned int blkoff;
/* It is easier to calculate if the first inode is 0. */
ino--;
#ifdef DEBUG
printf ("ext2fs read inode %d\n", ino);
#endif
status = ext2fs_blockgroup (data,
ino /
__le32_to_cpu (sblock->inodes_per_group),
&blkgrp);
if (status == 0) {
return (0);
}
inodes_per_block = EXT2_BLOCK_SIZE (data) / 128;
blkno = (ino % __le32_to_cpu (sblock->inodes_per_group)) /
inodes_per_block;
blkoff = (ino % __le32_to_cpu (sblock->inodes_per_group)) %
inodes_per_block;
#ifdef DEBUG
printf ("ext2fs read inode blkno %d blkoff %d\n", blkno, blkoff);
#endif
/* Read the inode. */
status = ext2fs_devread (((__le32_to_cpu (blkgrp.inode_table_id) +
blkno) << LOG2_EXT2_BLOCK_SIZE (data)),
sizeof (struct ext2_inode) * blkoff,
sizeof (struct ext2_inode), (char *) inode);
if (status == 0) {
return (0);
}
return (1);
}
void ext2fs_free_node (ext2fs_node_t node, ext2fs_node_t currroot) {
if ((node != &ext2fs_root->diropen) && (node != currroot)) {
free (node);
}
}
static int ext2fs_read_block (ext2fs_node_t node, int fileblock) {
struct ext2_data *data = node->data;
struct ext2_inode *inode = &node->inode;
int blknr;
int blksz = EXT2_BLOCK_SIZE (data);
int log2_blksz = LOG2_EXT2_BLOCK_SIZE (data);
int status;
/* Direct blocks. */
if (fileblock < INDIRECT_BLOCKS) {
blknr = __le32_to_cpu (inode->b.blocks.dir_blocks[fileblock]);
}
/* Indirect. */
else if (fileblock < (INDIRECT_BLOCKS + (blksz / 4))) {
if (indir1_block == NULL) {
indir1_block = (uint32_t *) malloc (blksz);
if (indir1_block == NULL) {
printf ("** ext2fs read block (indir 1) malloc failed. **\n");
return (-1);
}
indir1_size = blksz;
indir1_blkno = -1;
}
if (blksz != indir1_size) {
free (indir1_block);
indir1_block = NULL;
indir1_size = 0;
indir1_blkno = -1;
indir1_block = (uint32_t *) malloc (blksz);
if (indir1_block == NULL) {
printf ("** ext2fs read block (indir 1) malloc failed. **\n");
return (-1);
}
indir1_size = blksz;
}
if ((__le32_to_cpu (inode->b.blocks.indir_block) <<
log2_blksz) != indir1_blkno) {
status = ext2fs_devread (__le32_to_cpu(inode->b.blocks.indir_block) << log2_blksz,
0, blksz,
(char *) indir1_block);
if (status == 0) {
printf ("** ext2fs read block (indir 1) failed. **\n");
return (0);
}
indir1_blkno =
__le32_to_cpu (inode->b.blocks.
indir_block) << log2_blksz;
}
blknr = __le32_to_cpu (indir1_block
[fileblock - INDIRECT_BLOCKS]);
}
/* Double indirect. */
else if (fileblock <
(INDIRECT_BLOCKS + (blksz / 4 * (blksz / 4 + 1)))) {
unsigned int perblock = blksz / 4;
unsigned int rblock = fileblock - (INDIRECT_BLOCKS
+ blksz / 4);
if (indir1_block == NULL) {
indir1_block = (uint32_t *) malloc (blksz);
if (indir1_block == NULL) {
printf ("** ext2fs read block (indir 2 1) malloc failed. **\n");
return (-1);
}
indir1_size = blksz;
indir1_blkno = -1;
}
if (blksz != indir1_size) {
free (indir1_block);
indir1_block = NULL;
indir1_size = 0;
indir1_blkno = -1;
indir1_block = (uint32_t *) malloc (blksz);
if (indir1_block == NULL) {
printf ("** ext2fs read block (indir 2 1) malloc failed. **\n");
return (-1);
}
indir1_size = blksz;
}
if ((__le32_to_cpu (inode->b.blocks.double_indir_block) <<
log2_blksz) != indir1_blkno) {
status = ext2fs_devread (__le32_to_cpu(inode->b.blocks.double_indir_block) << log2_blksz,
0, blksz,
(char *) indir1_block);
if (status == 0) {
printf ("** ext2fs read block (indir 2 1) failed. **\n");
return (-1);
}
indir1_blkno =
__le32_to_cpu (inode->b.blocks.double_indir_block) << log2_blksz;
}
if (indir2_block == NULL) {
indir2_block = (uint32_t *) malloc (blksz);
if (indir2_block == NULL) {
printf ("** ext2fs read block (indir 2 2) malloc failed. **\n");
return (-1);
}
indir2_size = blksz;
indir2_blkno = -1;
}
if (blksz != indir2_size) {
free (indir2_block);
indir2_block = NULL;
indir2_size = 0;
indir2_blkno = -1;
indir2_block = (uint32_t *) malloc (blksz);
if (indir2_block == NULL) {
printf ("** ext2fs read block (indir 2 2) malloc failed. **\n");
return (-1);
}
indir2_size = blksz;
}
if ((__le32_to_cpu (indir1_block[rblock / perblock]) <<
log2_blksz) != indir1_blkno) {
status = ext2fs_devread (__le32_to_cpu(indir1_block[rblock / perblock]) << log2_blksz,
0, blksz,
(char *) indir2_block);
if (status == 0) {
printf ("** ext2fs read block (indir 2 2) failed. **\n");
return (-1);
}
indir2_blkno =
__le32_to_cpu (indir1_block[rblock / perblock]) << log2_blksz;
}
blknr = __le32_to_cpu (indir2_block[rblock % perblock]);
}
/* Tripple indirect. */
else {
printf ("** ext2fs doesn't support tripple indirect blocks. **\n");
return (-1);
}
#ifdef DEBUG
printf ("ext2fs_read_block %08x\n", blknr);
#endif
return (blknr);
}
int ext2fs_read_file
(ext2fs_node_t node, int pos, unsigned int len, char *buf) {
int i;
int blockcnt;
int log2blocksize = LOG2_EXT2_BLOCK_SIZE (node->data);
int blocksize = 1 << (log2blocksize + DISK_SECTOR_BITS);
unsigned int filesize = __le32_to_cpu(node->inode.size);
/* Adjust len so it we can't read past the end of the file. */
if (len > filesize) {
len = filesize;
}
blockcnt = ((len + pos) + blocksize - 1) / blocksize;
for (i = pos / blocksize; i < blockcnt; i++) {
int blknr;
int blockoff = pos % blocksize;
int blockend = blocksize;
int skipfirst = 0;
blknr = ext2fs_read_block (node, i);
if (blknr < 0) {
return (-1);
}
blknr = blknr << log2blocksize;
/* Last block. */
if (i == blockcnt - 1) {
blockend = (len + pos) % blocksize;
/* The last portion is exactly blocksize. */
if (!blockend) {
blockend = blocksize;
}
}
/* First block. */
if (i == pos / blocksize) {
skipfirst = blockoff;
blockend -= skipfirst;
}
/* If the block number is 0 this block is not stored on disk but
is zero filled instead. */
if (blknr) {
int status;
status = ext2fs_devread (blknr, skipfirst, blockend, buf);
if (status == 0) {
return (-1);
}
} else {
memset (buf, blocksize - skipfirst, 0);
}
buf += blocksize - skipfirst;
}
return (len);
}
static int ext2fs_iterate_dir (ext2fs_node_t dir, char *name, ext2fs_node_t * fnode, int *ftype)
{
unsigned int fpos = 0;
int status;
struct ext2fs_node *diro = (struct ext2fs_node *) dir;
#ifdef DEBUG
if (name != NULL)
printf ("Iterate dir %s\n", name);
#endif /* of DEBUG */
if (!diro->inode_read) {
status = ext2fs_read_inode (diro->data, diro->ino,
&diro->inode);
if (status == 0) {
return (0);
}
}
/* Search the file. */
while (fpos < __le32_to_cpu (diro->inode.size)) {
struct ext2_dirent dirent;
status = ext2fs_read_file (diro, fpos,
sizeof (struct ext2_dirent),
(char *) &dirent);
if (status < 1) {
return (0);
}
if (dirent.namelen != 0) {
char filename[dirent.namelen + 1];
ext2fs_node_t fdiro;
int type = FILETYPE_UNKNOWN;
status = ext2fs_read_file (diro,
fpos + sizeof (struct ext2_dirent),
dirent.namelen, filename);
if (status < 1) {
return (0);
}
fdiro = malloc (sizeof (struct ext2fs_node));
if (!fdiro) {
return (0);
}
fdiro->data = diro->data;
fdiro->ino = __le32_to_cpu (dirent.inode);
filename[dirent.namelen] = '\0';
if (dirent.filetype != FILETYPE_UNKNOWN) {
fdiro->inode_read = 0;
if (dirent.filetype == FILETYPE_DIRECTORY) {
type = FILETYPE_DIRECTORY;
} else if (dirent.filetype ==
FILETYPE_SYMLINK) {
type = FILETYPE_SYMLINK;
} else if (dirent.filetype == FILETYPE_REG) {
type = FILETYPE_REG;
}
} else {
/* The filetype can not be read from the dirent, get it from inode */
status = ext2fs_read_inode (diro->data,
__le32_to_cpu(dirent.inode),
&fdiro->inode);
if (status == 0) {
free (fdiro);
return (0);
}
fdiro->inode_read = 1;
if ((__le16_to_cpu (fdiro->inode.mode) &
FILETYPE_INO_MASK) ==
FILETYPE_INO_DIRECTORY) {
type = FILETYPE_DIRECTORY;
} else if ((__le16_to_cpu (fdiro->inode.mode)
& FILETYPE_INO_MASK) ==
FILETYPE_INO_SYMLINK) {
type = FILETYPE_SYMLINK;
} else if ((__le16_to_cpu (fdiro->inode.mode)
& FILETYPE_INO_MASK) ==
FILETYPE_INO_REG) {
type = FILETYPE_REG;
}
}
#ifdef DEBUG
printf ("iterate >%s<\n", filename);
#endif /* of DEBUG */
if ((name != NULL) && (fnode != NULL)
&& (ftype != NULL)) {
if (strcmp (filename, name) == 0) {
*ftype = type;
*fnode = fdiro;
return (1);
}
} else {
if (fdiro->inode_read == 0) {
status = ext2fs_read_inode (diro->data,
__le32_to_cpu (dirent.inode),
&fdiro->inode);
if (status == 0) {
free (fdiro);
return (0);
}
fdiro->inode_read = 1;
}
switch (type) {
case FILETYPE_DIRECTORY:
printf ("<DIR> ");
break;
case FILETYPE_SYMLINK:
printf ("<SYM> ");
break;
case FILETYPE_REG:
printf (" ");
break;
default:
printf ("< ? > ");
break;
}
printf ("%10d %s\n",
__le32_to_cpu (fdiro->inode.size),
filename);
}
free (fdiro);
}
fpos += __le16_to_cpu (dirent.direntlen);
}
return (0);
}
static char *ext2fs_read_symlink (ext2fs_node_t node) {
char *symlink;
struct ext2fs_node *diro = node;
int status;
if (!diro->inode_read) {
status = ext2fs_read_inode (diro->data, diro->ino,
&diro->inode);
if (status == 0) {
return (0);
}
}
symlink = malloc (__le32_to_cpu (diro->inode.size) + 1);
if (!symlink) {
return (0);
}
/* If the filesize of the symlink is bigger than
60 the symlink is stored in a separate block,
otherwise it is stored in the inode. */
if (__le32_to_cpu (diro->inode.size) <= 60) {
strncpy (symlink, diro->inode.b.symlink,
__le32_to_cpu (diro->inode.size));
} else {
status = ext2fs_read_file (diro, 0,
__le32_to_cpu (diro->inode.size),
symlink);
if (status == 0) {
free (symlink);
return (0);
}
}
symlink[__le32_to_cpu (diro->inode.size)] = '\0';
return (symlink);
}
int ext2fs_find_file1
(const char *currpath,
ext2fs_node_t currroot, ext2fs_node_t * currfound, int *foundtype) {
char fpath[strlen (currpath) + 1];
char *name = fpath;
char *next;
int status;
int type = FILETYPE_DIRECTORY;
ext2fs_node_t currnode = currroot;
ext2fs_node_t oldnode = currroot;
strncpy (fpath, currpath, strlen (currpath) + 1);
/* Remove all leading slashes. */
while (*name == '/') {
name++;
}
if (!*name) {
*currfound = currnode;
return (1);
}
for (;;) {
int found;
/* Extract the actual part from the pathname. */
next = strchr (name, '/');
if (next) {
/* Remove all leading slashes. */
while (*next == '/') {
*(next++) = '\0';
}
}
/* At this point it is expected that the current node is a directory, check if this is true. */
if (type != FILETYPE_DIRECTORY) {
ext2fs_free_node (currnode, currroot);
return (0);
}
oldnode = currnode;
/* Iterate over the directory. */
found = ext2fs_iterate_dir (currnode, name, &currnode, &type);
if (found == 0) {
return (0);
}
if (found == -1) {
break;
}
/* Read in the symlink and follow it. */
if (type == FILETYPE_SYMLINK) {
char *symlink;
/* Test if the symlink does not loop. */
if (++symlinknest == 8) {
ext2fs_free_node (currnode, currroot);
ext2fs_free_node (oldnode, currroot);
return (0);
}
symlink = ext2fs_read_symlink (currnode);
ext2fs_free_node (currnode, currroot);
if (!symlink) {
ext2fs_free_node (oldnode, currroot);
return (0);
}
#ifdef DEBUG
printf ("Got symlink >%s<\n", symlink);
#endif /* of DEBUG */
/* The symlink is an absolute path, go back to the root inode. */
if (symlink[0] == '/') {
ext2fs_free_node (oldnode, currroot);
oldnode = &ext2fs_root->diropen;
}
/* Lookup the node the symlink points to. */
status = ext2fs_find_file1 (symlink, oldnode,
&currnode, &type);
free (symlink);
if (status == 0) {
ext2fs_free_node (oldnode, currroot);
return (0);
}
}
ext2fs_free_node (oldnode, currroot);
/* Found the node! */
if (!next || *next == '\0') {
*currfound = currnode;
*foundtype = type;
return (1);
}
name = next;
}
return (-1);
}
int ext2fs_find_file
(const char *path,
ext2fs_node_t rootnode, ext2fs_node_t * foundnode, int expecttype) {
int status;
int foundtype = FILETYPE_DIRECTORY;
symlinknest = 0;
if (!path) {
return (0);
}
status = ext2fs_find_file1 (path, rootnode, foundnode, &foundtype);
if (status == 0) {
return (0);
}
/* Check if the node that was found was of the expected type. */
if ((expecttype == FILETYPE_REG) && (foundtype != expecttype)) {
return (0);
} else if ((expecttype == FILETYPE_DIRECTORY)
&& (foundtype != expecttype)) {
return (0);
}
return (1);
}
int ext2fs_ls (char *dirname) {
ext2fs_node_t dirnode;
int status;
if (ext2fs_root == NULL) {
return (0);
}
status = ext2fs_find_file (dirname, &ext2fs_root->diropen, &dirnode,
FILETYPE_DIRECTORY);
if (status != 1) {
printf ("** Can not find directory. **\n");
return (1);
}
ext2fs_iterate_dir (dirnode, NULL, NULL, NULL);
ext2fs_free_node (dirnode, &ext2fs_root->diropen);
return (0);
}
int ext2fs_open (char *filename) {
ext2fs_node_t fdiro = NULL;
int status;
int len;
if (ext2fs_root == NULL) {
return (-1);
}
ext2fs_file = NULL;
status = ext2fs_find_file (filename, &ext2fs_root->diropen, &fdiro,
FILETYPE_REG);
if (status == 0) {
goto fail;
}
if (!fdiro->inode_read) {
status = ext2fs_read_inode (fdiro->data, fdiro->ino,
&fdiro->inode);
if (status == 0) {
goto fail;
}
}
len = __le32_to_cpu (fdiro->inode.size);
ext2fs_file = fdiro;
return (len);
fail:
ext2fs_free_node (fdiro, &ext2fs_root->diropen);
return (-1);
}
int ext2fs_close (void
) {
if ((ext2fs_file != NULL) && (ext2fs_root != NULL)) {
ext2fs_free_node (ext2fs_file, &ext2fs_root->diropen);
ext2fs_file = NULL;
}
if (ext2fs_root != NULL) {
free (ext2fs_root);
ext2fs_root = NULL;
}
if (indir1_block != NULL) {
free (indir1_block);
indir1_block = NULL;
indir1_size = 0;
indir1_blkno = -1;
}
if (indir2_block != NULL) {
free (indir2_block);
indir2_block = NULL;
indir2_size = 0;
indir2_blkno = -1;
}
return (0);
}
int ext2fs_read (char *buf, unsigned len) {
int status;
if (ext2fs_root == NULL) {
return (0);
}
if (ext2fs_file == NULL) {
return (0);
}
status = ext2fs_read_file (ext2fs_file, 0, len, buf);
return (status);
}
int ext2fs_mount (unsigned part_length) {
struct ext2_data *data;
int status;
data = malloc (sizeof (struct ext2_data));
if (!data) {
return (0);
}
/* Read the superblock. */
status = ext2fs_devread (1 * 2, 0, sizeof (struct ext2_sblock),
(char *) &data->sblock);
if (status == 0) {
goto fail;
}
/* Make sure this is an ext2 filesystem. */
if (__le16_to_cpu (data->sblock.magic) != EXT2_MAGIC) {
goto fail;
}
data->diropen.data = data;
data->diropen.ino = 2;
data->diropen.inode_read = 1;
data->inode = &data->diropen.inode;
status = ext2fs_read_inode (data, 2, data->inode);
if (status == 0) {
goto fail;
}
ext2fs_root = data;
return (1);
fail:
printf ("Failed to mount ext2 filesystem...\n");
free (data);
ext2fs_root = NULL;
return (0);
}
#endif /* CFG_CMD_EXT2FS */

View File

@ -1,45 +0,0 @@
#
#
# See file CREDITS for list of people who contributed to this
# project.
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License as
# published by the Free Software Foundation; either version 2 of
# the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston,
# MA 02111-1307 USA
#
include $(TOPDIR)/config.mk
LIB = $(obj)libfat.a
AOBJS =
COBJS = fat.o file.o
SRCS := $(AOBJS:.o=.S) $(COBJS:.o=.c)
OBJS := $(addprefix $(obj),$(AOBJS) $(COBJS))
all: $(LIB) $(AOBJS)
$(LIB): $(obj).depend $(OBJS)
$(AR) $(ARFLAGS) $@ $(OBJS)
#########################################################################
# defines $(obj).depend target
include $(SRCTREE)/rules.mk
sinclude $(obj).depend
#########################################################################

File diff suppressed because it is too large Load Diff

View File

@ -1,208 +0,0 @@
/*
* file.c
*
* Mini "VFS" by Marcus Sundberg
*
* 2002-07-28 - rjones@nexus-tech.net - ported to ppcboot v1.1.6
* 2003-03-10 - kharris@nexus-tech.net - ported to uboot
*
* See file CREDITS for list of people who contributed to this
* project.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of
* the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
* MA 02111-1307 USA
*/
#include <common.h>
#include <config.h>
#include <malloc.h>
#include <fat.h>
#include <linux/stat.h>
#include <linux/time.h>
#if (CONFIG_COMMANDS & CFG_CMD_FAT)
/* Supported filesystems */
static const struct filesystem filesystems[] = {
{ file_fat_detectfs, file_fat_ls, file_fat_read, "FAT" },
};
#define NUM_FILESYS (sizeof(filesystems)/sizeof(struct filesystem))
/* The filesystem which was last detected */
static int current_filesystem = FSTYPE_NONE;
/* The current working directory */
#define CWD_LEN 511
char file_cwd[CWD_LEN+1] = "/";
const char *
file_getfsname(int idx)
{
if (idx < 0 || idx >= NUM_FILESYS) return NULL;
return filesystems[idx].name;
}
static void
pathcpy(char *dest, const char *src)
{
char *origdest = dest;
do {
if (dest-file_cwd >= CWD_LEN) {
*dest = '\0';
return;
}
*(dest) = *(src);
if (*src == '\0') {
if (dest-- != origdest && ISDIRDELIM(*dest)) {
*dest = '\0';
}
return;
}
++dest;
if (ISDIRDELIM(*src)) {
while (ISDIRDELIM(*src)) src++;
} else {
src++;
}
} while (1);
}
int
file_cd(const char *path)
{
if (ISDIRDELIM(*path)) {
while (ISDIRDELIM(*path)) path++;
strncpy(file_cwd+1, path, CWD_LEN-1);
} else {
const char *origpath = path;
char *tmpstr = file_cwd;
int back = 0;
while (*tmpstr != '\0') tmpstr++;
do {
tmpstr--;
} while (ISDIRDELIM(*tmpstr));
while (*path == '.') {
path++;
while (*path == '.') {
path++;
back++;
}
if (*path != '\0' && !ISDIRDELIM(*path)) {
path = origpath;
back = 0;
break;
}
while (ISDIRDELIM(*path)) path++;
origpath = path;
}
while (back--) {
/* Strip off path component */
while (!ISDIRDELIM(*tmpstr)) {
tmpstr--;
}
if (tmpstr == file_cwd) {
/* Incremented again right after the loop. */
tmpstr--;
break;
}
/* Skip delimiters */
while (ISDIRDELIM(*tmpstr)) tmpstr--;
}
tmpstr++;
if (*path == '\0') {
if (tmpstr == file_cwd) {
*tmpstr = '/';
tmpstr++;
}
*tmpstr = '\0';
return 0;
}
*tmpstr = '/';
pathcpy(tmpstr+1, path);
}
return 0;
}
int
file_detectfs(void)
{
int i;
current_filesystem = FSTYPE_NONE;
for (i = 0; i < NUM_FILESYS; i++) {
if (filesystems[i].detect() == 0) {
strcpy(file_cwd, "/");
current_filesystem = i;
break;
}
}
return current_filesystem;
}
int
file_ls(const char *dir)
{
char fullpath[1024];
const char *arg;
if (current_filesystem == FSTYPE_NONE) {
printf("Can't list files without a filesystem!\n");
return -1;
}
if (ISDIRDELIM(*dir)) {
arg = dir;
} else {
sprintf(fullpath, "%s/%s", file_cwd, dir);
arg = fullpath;
}
return filesystems[current_filesystem].ls(arg);
}
long
file_read(const char *filename, void *buffer, unsigned long maxsize)
{
char fullpath[1024];
const char *arg;
if (current_filesystem == FSTYPE_NONE) {
printf("Can't load file without a filesystem!\n");
return -1;
}
if (ISDIRDELIM(*filename)) {
arg = filename;
} else {
sprintf(fullpath, "%s/%s", file_cwd, filename);
arg = fullpath;
}
return filesystems[current_filesystem].read(arg, buffer, maxsize);
}
#endif /* #if (CONFIG_COMMANDS & CFG_CMD_FAT) */

View File

@ -1,54 +0,0 @@
#
# (C) Copyright 2006
# Wolfgang Denk, DENX Software Engineering, wd@denx.de.
#
# (C) Copyright 2002
# Stäubli Faverges - <www.staubli.com>
# Pierre AUBERT p.aubert@staubli.com
#
#
# See file CREDITS for list of people who contributed to this
# project.
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License as
# published by the Free Software Foundation; either version 2 of
# the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston,
# MA 02111-1307 USA
#
include $(TOPDIR)/config.mk
LIB = $(obj)libfdos.a
AOBJS =
COBJS = fat.o vfat.o dev.o fdos.o fs.o subdir.o
SRCS := $(AOBJS:.o=.S) $(COBJS:.o=.c)
OBJS := $(addprefix $(obj),$(AOBJS) $(COBJS))
#CPPFLAGS +=
all: $(LIB) $(AOBJS)
$(LIB): $(obj).depend $(OBJS)
$(AR) $(ARFLAGS) $@ $(OBJS)
#########################################################################
# defines $(obj).depend target
include $(SRCTREE)/rules.mk
sinclude $(obj).depend
#########################################################################

View File

@ -1,195 +0,0 @@
/*
* (C) Copyright 2002
* Stäubli Faverges - <www.staubli.com>
* Pierre AUBERT p.aubert@staubli.com
*
* See file CREDITS for list of people who contributed to this
* project.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of
* the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
* MA 02111-1307 USA
*/
#include <common.h>
#include <config.h>
#include "dos.h"
#include "fdos.h"
#if (CONFIG_COMMANDS & CFG_CMD_FDOS)
#define NB_HEADS 2
#define NB_TRACKS 80
#define NB_SECTORS 18
static int lastwhere;
/*-----------------------------------------------------------------------------
* dev_open --
*-----------------------------------------------------------------------------
*/
int dev_open (void)
{
lastwhere = 0;
return (0);
}
/*-----------------------------------------------------------------------------
* dev_read -- len and where are sectors number
*-----------------------------------------------------------------------------
*/
int dev_read (void *buffer, int where, int len)
{
PRINTF ("dev_read (len = %d, where = %d)\n", len, where);
/* Si on ne desire pas lire a la position courante, il faut un seek */
if (where != lastwhere) {
if (!fdc_fdos_seek (where)) {
PRINTF ("seek error in dev_read");
lastwhere = -1;
return (-1);
}
}
if (!fdc_fdos_read (buffer, len)) {
PRINTF ("read error\n");
lastwhere = -1;
return (-1);
}
lastwhere = where + len;
return (0);
}
/*-----------------------------------------------------------------------------
* check_dev -- verify the diskette format
*-----------------------------------------------------------------------------
*/
int check_dev (BootSector_t *boot, Fs_t *fs)
{
unsigned int heads, sectors, tracks;
int BootP, Infp0, InfpX, InfTm;
int sect_per_track;
/* Display Boot header */
PRINTF ("Jump to boot code 0x%02x 0x%02x 0x%02x\n",
boot -> jump [0], boot -> jump [1], boot -> jump[2]);
PRINTF ("OEM name & version '%*.*s'\n",
BANNER_LG, BANNER_LG, boot -> banner );
PRINTF ("Bytes per sector hopefully 512 %d\n",
__le16_to_cpu (boot -> secsiz));
PRINTF ("Cluster size in sectors %d\n",
boot -> clsiz);
PRINTF ("Number of reserved (boot) sectors %d\n",
__le16_to_cpu (boot -> nrsvsect));
PRINTF ("Number of FAT tables hopefully 2 %d\n",
boot -> nfat);
PRINTF ("Number of directory slots %d\n",
__le16_to_cpu (boot -> dirents));
PRINTF ("Total sectors on disk %d\n",
__le16_to_cpu (boot -> psect));
PRINTF ("Media descriptor=first byte of FAT %d\n",
boot -> descr);
PRINTF ("Sectors in FAT %d\n",
__le16_to_cpu (boot -> fatlen));
PRINTF ("Sectors/track %d\n",
__le16_to_cpu (boot -> nsect));
PRINTF ("Heads %d\n",
__le16_to_cpu (boot -> nheads));
PRINTF ("number of hidden sectors %d\n",
__le32_to_cpu (boot -> nhs));
PRINTF ("big total sectors %d\n",
__le32_to_cpu (boot -> bigsect));
PRINTF ("physical drive ? %d\n",
boot -> physdrive);
PRINTF ("reserved %d\n",
boot -> reserved);
PRINTF ("dos > 4.0 diskette %d\n",
boot -> dos4);
PRINTF ("serial number %d\n",
__le32_to_cpu (boot -> serial));
PRINTF ("disk label %*.*s\n",
LABEL_LG, LABEL_LG, boot -> label);
PRINTF ("FAT type %8.8s\n",
boot -> fat_type);
PRINTF ("reserved by 2M %d\n",
boot -> res_2m);
PRINTF ("2M checksum (not used) %d\n",
boot -> CheckSum);
PRINTF ("2MF format version %d\n",
boot -> fmt_2mf);
PRINTF ("1 if write track after format %d\n",
boot -> wt);
PRINTF ("data transfer rate on track 0 %d\n",
boot -> rate_0);
PRINTF ("data transfer rate on track<>0 %d\n",
boot -> rate_any);
PRINTF ("offset to boot program %d\n",
__le16_to_cpu (boot -> BootP));
PRINTF ("T1: information for track 0 %d\n",
__le16_to_cpu (boot -> Infp0));
PRINTF ("T2: information for track<>0 %d\n",
__le16_to_cpu (boot -> InfpX));
PRINTF ("T3: track sectors size table %d\n",
__le16_to_cpu (boot -> InfTm));
PRINTF ("Format date 0x%04x\n",
__le16_to_cpu (boot -> DateF));
PRINTF ("Format time 0x%04x\n",
__le16_to_cpu (boot -> TimeF));
/* information is extracted from boot sector */
heads = __le16_to_cpu (boot -> nheads);
sectors = __le16_to_cpu (boot -> nsect);
fs -> tot_sectors = __le32_to_cpu (boot -> bigsect);
if (__le16_to_cpu (boot -> psect) != 0) {
fs -> tot_sectors = __le16_to_cpu (boot -> psect);
}
sect_per_track = heads * sectors;
tracks = (fs -> tot_sectors + sect_per_track - 1) / sect_per_track;
BootP = __le16_to_cpu (boot -> BootP);
Infp0 = __le16_to_cpu (boot -> Infp0);
InfpX = __le16_to_cpu (boot -> InfpX);
InfTm = __le16_to_cpu (boot -> InfTm);
if (boot -> dos4 == EXTENDED_BOOT &&
strncmp( boot->banner,"2M", 2 ) == 0 &&
BootP < SZ_STD_SECTOR &&
Infp0 < SZ_STD_SECTOR &&
InfpX < SZ_STD_SECTOR &&
InfTm < SZ_STD_SECTOR &&
BootP >= InfTm + 2 &&
InfTm >= InfpX &&
InfpX >= Infp0 &&
Infp0 >= 76 ) {
return (-1);
}
if (heads != NB_HEADS ||
tracks != NB_TRACKS ||
sectors != NB_SECTORS ||
__le16_to_cpu (boot -> secsiz) != SZ_STD_SECTOR ||
fs -> tot_sectors == 0 ||
(fs -> tot_sectors % sectors) != 0) {
return (-1);
}
return (0);
}
#endif

View File

@ -1,175 +0,0 @@
/*
* (C) Copyright 2002
* Stäubli Faverges - <www.staubli.com>
* Pierre AUBERT p.aubert@staubli.com
*
* See file CREDITS for list of people who contributed to this
* project.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of
* the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
* MA 02111-1307 USA
*/
#ifndef _DOS_H_
#define _DOS_H_
/* Definitions for Dos diskettes */
/* General definitions */
#define SZ_STD_SECTOR 512 /* Standard sector size */
#define MDIR_SIZE 32 /* Direntry size */
#define FAT_BITS 12 /* Diskette use 12 bits fat */
#define MAX_PATH 128 /* Max size of the MSDOS PATH */
#define MAX_DIR_SECS 64 /* Taille max d'un repertoire (en */
/* secteurs) */
/* Misc. definitions */
#define DELMARK '\xe5'
#define EXTENDED_BOOT (0x29)
#define MEDIA_STD (0xf0)
#define JUMP_0_1 (0xe9)
#define JUMP_0_2 (0xeb)
/* Boot size is 256 bytes, but we need to read almost a sector, then
assume bootsize is 512 */
#define BOOTSIZE 512
/* Fat definitions for 12 bits fat */
#define FAT12_MAX_NB 4086
#define FAT12_LAST 0x0ff6
#define FAT12_END 0x0fff
/* file attributes */
#define ATTR_READONLY 0x01
#define ATTR_HIDDEN 0x02
#define ATTR_SYSTEM 0x04
#define ATTR_VOLUME 0x08
#define ATTR_DIRECTORY 0x10
#define ATTR_ARCHIVE 0x20
#define ATTR_VSE 0x0f
/* Name format */
#define EXTCASE 0x10
#define BASECASE 0x8
/* Definition of the boot sector */
#define BANNER_LG 8
#define LABEL_LG 11
typedef struct bootsector
{
unsigned char jump [3]; /* 0 Jump to boot code */
char banner [BANNER_LG]; /* 3 OEM name & version */
unsigned short secsiz; /* 11 Bytes per sector hopefully 512 */
unsigned char clsiz; /* 13 Cluster size in sectors */
unsigned short nrsvsect; /* 14 Number of reserved (boot) sectors */
unsigned char nfat; /* 16 Number of FAT tables hopefully 2 */
unsigned short dirents; /* 17 Number of directory slots */
unsigned short psect; /* 19 Total sectors on disk */
unsigned char descr; /* 21 Media descriptor=first byte of FAT */
unsigned short fatlen; /* 22 Sectors in FAT */
unsigned short nsect; /* 24 Sectors/track */
unsigned short nheads; /* 26 Heads */
unsigned int nhs; /* 28 number of hidden sectors */
unsigned int bigsect; /* 32 big total sectors */
unsigned char physdrive; /* 36 physical drive ? */
unsigned char reserved; /* 37 reserved */
unsigned char dos4; /* 38 dos > 4.0 diskette */
unsigned int serial; /* 39 serial number */
char label [LABEL_LG]; /* 43 disk label */
char fat_type [8]; /* 54 FAT type */
unsigned char res_2m; /* 62 reserved by 2M */
unsigned char CheckSum; /* 63 2M checksum (not used) */
unsigned char fmt_2mf; /* 64 2MF format version */
unsigned char wt; /* 65 1 if write track after format */
unsigned char rate_0; /* 66 data transfer rate on track 0 */
unsigned char rate_any; /* 67 data transfer rate on track<>0 */
unsigned short BootP; /* 68 offset to boot program */
unsigned short Infp0; /* 70 T1: information for track 0 */
unsigned short InfpX; /* 72 T2: information for track<>0 */
unsigned short InfTm; /* 74 T3: track sectors size table */
unsigned short DateF; /* 76 Format date */
unsigned short TimeF; /* 78 Format time */
unsigned char junk [BOOTSIZE - 80]; /* 80 remaining data */
} __attribute__ ((packed)) BootSector_t;
/* Structure d'une entree de repertoire */
typedef struct directory {
char name [8]; /* file name */
char ext [3]; /* file extension */
unsigned char attr; /* attribute byte */
unsigned char Case; /* case of short filename */
unsigned char reserved [9]; /* ?? */
unsigned char time [2]; /* time stamp */
unsigned char date [2]; /* date stamp */
unsigned short start; /* starting cluster number */
unsigned int size; /* size of the file */
} __attribute__ ((packed)) Directory_t;
#define MAX_VFAT_SUBENTRIES 20
#define VSE_NAMELEN 13
#define VSE1SIZE 5
#define VSE2SIZE 6
#define VSE3SIZE 2
#define VBUFSIZE ((MAX_VFAT_SUBENTRIES * VSE_NAMELEN) + 1)
#define MAX_VNAMELEN (255)
#define VSE_PRESENT 0x01
#define VSE_LAST 0x40
#define VSE_MASK 0x1f
/* Flag used by vfat_lookup */
#define DO_OPEN 1
#define ACCEPT_PLAIN 0x20
#define ACCEPT_DIR 0x10
#define ACCEPT_LABEL 0x08
#define SINGLE 2
#define MATCH_ANY 0x40
struct vfat_subentry {
unsigned char id; /* VSE_LAST pour la fin, VSE_MASK */
/* pour un VSE */
char text1 [VSE1SIZE * 2]; /* Caracteres encodes sur 16 bits */
unsigned char attribute; /* 0x0f pour les VFAT */
unsigned char hash1; /* toujours 0 */
unsigned char sum; /* Checksum du nom court */
char text2 [VSE2SIZE * 2]; /* Caracteres encodes sur 16 bits */
unsigned char sector_l; /* 0 pour les VFAT */
unsigned char sector_u; /* 0 pour les VFAT */
char text3 [VSE3SIZE * 2]; /* Caracteres encodes sur 16 bits */
} __attribute__ ((packed)) ;
struct vfat_state {
char name [VBUFSIZE];
int status; /* is now a bit map of 32 bits */
int subentries;
unsigned char sum; /* no need to remember the sum for each */
/* entry, it is the same anyways */
} __attribute__ ((packed)) ;
/* Conversion macros */
#define DOS_YEAR(dir) (((dir)->date[1] >> 1) + 1980)
#define DOS_MONTH(dir) (((((dir)->date[1]&0x1) << 3) + ((dir)->date[0] >> 5)))
#define DOS_DAY(dir) ((dir)->date[0] & 0x1f)
#define DOS_HOUR(dir) ((dir)->time[1] >> 3)
#define DOS_MINUTE(dir) (((((dir)->time[1]&0x7) << 3) + ((dir)->time[0] >> 5)))
#define DOS_SEC(dir) (((dir)->time[0] & 0x1f) * 2)
#endif

View File

@ -1,142 +0,0 @@
/*
* (C) Copyright 2002
* Stäubli Faverges - <www.staubli.com>
* Pierre AUBERT p.aubert@staubli.com
*
* See file CREDITS for list of people who contributed to this
* project.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of
* the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
* MA 02111-1307 USA
*/
#include <common.h>
#include <config.h>
#include <malloc.h>
#if (CONFIG_COMMANDS & CFG_CMD_FDOS)
#include "dos.h"
#include "fdos.h"
/*-----------------------------------------------------------------------------
* fat_decode --
*-----------------------------------------------------------------------------
*/
unsigned int fat_decode (Fs_t *fs, unsigned int num)
{
unsigned int start = num * 3 / 2;
unsigned char *address = fs -> fat_buf + start;
if (num < 2 || start + 1 > (fs -> fat_len * SZ_STD_SECTOR))
return 1;
if (num & 1)
return ((address [1] & 0xff) << 4) | ((address [0] & 0xf0 ) >> 4);
else
return ((address [1] & 0xf) << 8) | (address [0] & 0xff );
}
/*-----------------------------------------------------------------------------
* check_fat --
*-----------------------------------------------------------------------------
*/
static int check_fat (Fs_t *fs)
{
int i, f;
/* Cluster verification */
for (i = 3 ; i < fs -> num_clus; i++){
f = fat_decode (fs, i);
if (f < FAT12_LAST && f > fs -> num_clus){
/* Wrong cluster number detected */
return (-1);
}
}
return (0);
}
/*-----------------------------------------------------------------------------
* read_one_fat --
*-----------------------------------------------------------------------------
*/
static int read_one_fat (BootSector_t *boot, Fs_t *fs, int nfat)
{
if (dev_read (fs -> fat_buf,
(fs -> fat_start + nfat * fs -> fat_len),
fs -> fat_len) < 0) {
return (-1);
}
if (fs -> fat_buf [0] || fs -> fat_buf [1] || fs -> fat_buf [2]) {
if ((fs -> fat_buf [0] != boot -> descr &&
(fs -> fat_buf [0] != 0xf9 || boot -> descr != MEDIA_STD)) ||
fs -> fat_buf [0] < MEDIA_STD){
/* Unknown Media */
return (-1);
}
if (fs -> fat_buf [1] != 0xff || fs -> fat_buf [2] != 0xff){
/* FAT doesn't start with good values */
return (-1);
}
}
if (fs -> num_clus >= FAT12_MAX_NB) {
/* Too much clusters */
return (-1);
}
return check_fat (fs);
}
/*-----------------------------------------------------------------------------
* read_fat --
*-----------------------------------------------------------------------------
*/
int read_fat (BootSector_t *boot, Fs_t *fs)
{
unsigned int buflen;
int i;
/* Allocate Fat Buffer */
buflen = fs -> fat_len * SZ_STD_SECTOR;
if (fs -> fat_buf) {
free (fs -> fat_buf);
}
if ((fs -> fat_buf = malloc (buflen)) == NULL) {
return (-1);
}
/* Try to read each Fat */
for (i = 0; i< fs -> nb_fat; i++){
if (read_one_fat (boot, fs, i) == 0) {
/* Fat is OK */
fs -> num_fat = i;
break;
}
}
if (i == fs -> nb_fat){
return (-1);
}
if (fs -> fat_len > (((fs -> num_clus + 2) *
(FAT_BITS / 4) -1 ) / 2 /
SZ_STD_SECTOR + 1)) {
return (-1);
}
return (0);
}
#endif

View File

@ -1,175 +0,0 @@
/*
* (C) Copyright 2002
* Stäubli Faverges - <www.staubli.com>
* Pierre AUBERT p.aubert@staubli.com
*
* See file CREDITS for list of people who contributed to this
* project.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of
* the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
* MA 02111-1307 USA
*/
#include <common.h>
#include <config.h>
#if (CONFIG_COMMANDS & CFG_CMD_FDOS)
#include <malloc.h>
#include "dos.h"
#include "fdos.h"
const char *month [] = {"Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"};
Fs_t fs;
File_t file;
/*-----------------------------------------------------------------------------
* dos_open --
*-----------------------------------------------------------------------------
*/
int dos_open(char *name)
{
int lg;
int entry;
char *fname;
/* We need to suppress the " char around the name */
if (name [0] == '"') {
name ++;
}
lg = strlen (name);
if (name [lg - 1] == '"') {
name [lg - 1] = '\0';
}
/* Open file system */
if (fs_init (&fs) < 0) {
return -1;
}
/* Init the file descriptor */
file.name = name;
file.fs = &fs;
/* find the subdirectory containing the file */
if (open_subdir (&file) < 0) {
return (-1);
}
fname = basename (name);
/* if we try to open root directory */
if (*fname == '\0') {
file.file = file.subdir;
return (0);
}
/* find the file in the subdir */
entry = 0;
if (vfat_lookup (&file.subdir,
file.fs,
&file.file.dir,
&entry,
0,
fname,
ACCEPT_DIR | ACCEPT_PLAIN | SINGLE | DO_OPEN,
0,
&file.file) != 0) {
/* File not found */
printf ("File not found\n");
return (-1);
}
return 0;
}
/*-----------------------------------------------------------------------------
* dos_read --
*-----------------------------------------------------------------------------
*/
int dos_read (ulong addr)
{
int read = 0, nb;
/* Try to boot a directory ? */
if (file.file.dir.attr & (ATTR_DIRECTORY | ATTR_VOLUME)) {
printf ("Unable to boot %s !!\n", file.name);
return (-1);
}
while (read < file.file.FileSize) {
PRINTF ("read_file (%ld)\n", (file.file.FileSize - read));
nb = read_file (&fs,
&file.file,
(char *)addr + read,
read,
(file.file.FileSize - read));
PRINTF ("read_file -> %d\n", nb);
if (nb < 0) {
printf ("read error\n");
return (-1);
}
read += nb;
}
return (read);
}
/*-----------------------------------------------------------------------------
* dos_dir --
*-----------------------------------------------------------------------------
*/
int dos_dir (void)
{
int entry;
Directory_t dir;
char *name;
if ((file.file.dir.attr & ATTR_DIRECTORY) == 0) {
printf ("%s: not a directory !!\n", file.name);
return (1);
}
entry = 0;
if ((name = malloc (MAX_VNAMELEN + 1)) == NULL) {
PRINTF ("Allcation error\n");
return (1);
}
while (vfat_lookup (&file.file,
file.fs,
&dir,
&entry,
0,
NULL,
ACCEPT_DIR | ACCEPT_PLAIN | MATCH_ANY,
name,
NULL) == 0) {
/* Display file info */
printf ("%3.3s %9d %s %02d %04d %02d:%02d:%02d %s\n",
(dir.attr & ATTR_DIRECTORY) ? "dir" : " ",
__le32_to_cpu (dir.size),
month [DOS_MONTH (&dir) - 1],
DOS_DAY (&dir),
DOS_YEAR (&dir),
DOS_HOUR (&dir),
DOS_MINUTE (&dir),
DOS_SEC (&dir),
name);
}
free (name);
return (0);
}
#endif

View File

@ -1,116 +0,0 @@
/*
* (C) Copyright 2002
* Stäubli Faverges - <www.staubli.com>
* Pierre AUBERT p.aubert@staubli.com
*
* See file CREDITS for list of people who contributed to this
* project.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of
* the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
* MA 02111-1307 USA
*/
#ifndef _FDOS_H_
#define _FDOS_H_
#undef FDOS_DEBUG
#ifdef FDOS_DEBUG
#define PRINTF(fmt,args...) printf (fmt ,##args)
#else
#define PRINTF(fmt,args...)
#endif
/* Data structure describing media */
typedef struct fs
{
unsigned long tot_sectors;
int cluster_size;
int num_clus;
int fat_start;
int fat_len;
int nb_fat;
int num_fat;
int dir_start;
int dir_len;
unsigned char *fat_buf;
} Fs_t;
/* Data structure describing one file system slot */
typedef struct slot {
int (*map) (struct fs *fs,
struct slot *file,
int where,
int *len);
unsigned long FileSize;
unsigned short int FirstAbsCluNr;
unsigned short int PreviousAbsCluNr;
unsigned short int PreviousRelCluNr;
Directory_t dir;
} Slot_t;
typedef struct file {
char *name;
int Case;
Fs_t *fs;
Slot_t subdir;
Slot_t file;
} File_t;
/* dev.c */
int dev_read (void *buffer, int where, int len);
int dev_open (void);
int check_dev (BootSector_t *boot, Fs_t *fs);
/* fat.c */
unsigned int fat_decode (Fs_t *fs, unsigned int num);
int read_fat (BootSector_t *boot, Fs_t *fs);
/* vfat.c */
int vfat_lookup (Slot_t *dir,
Fs_t *fs,
Directory_t *dirent,
int *entry,
int *vfat_start,
char *filename,
int flags,
char *outname,
Slot_t *file);
/* subdir.c */
char *basename (char *name);
int open_subdir (File_t *desc);
int open_file (Slot_t *file, Directory_t *dir);
int read_file (Fs_t *fs,
Slot_t *file,
char *buf,
int where,
int len);
void init_subdir (void);
/* fs.c */
int fs_init (Fs_t *fs);
#endif

View File

@ -1,118 +0,0 @@
/*
* (C) Copyright 2002
* Stäubli Faverges - <www.staubli.com>
* Pierre AUBERT p.aubert@staubli.com
*
* See file CREDITS for list of people who contributed to this
* project.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of
* the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
* MA 02111-1307 USA
*/
#include <common.h>
#include <config.h>
#include <malloc.h>
#if (CONFIG_COMMANDS & CFG_CMD_FDOS)
#include "dos.h"
#include "fdos.h"
/*-----------------------------------------------------------------------------
* fill_fs -- Read info on file system
*-----------------------------------------------------------------------------
*/
static int fill_fs (BootSector_t *boot, Fs_t *fs)
{
fs -> fat_start = __le16_to_cpu (boot -> nrsvsect);
fs -> fat_len = __le16_to_cpu (boot -> fatlen);
fs -> nb_fat = boot -> nfat;
fs -> dir_start = fs -> fat_start + fs -> nb_fat * fs -> fat_len;
fs -> dir_len = __le16_to_cpu (boot -> dirents) * MDIR_SIZE / SZ_STD_SECTOR;
fs -> cluster_size = boot -> clsiz;
fs -> num_clus = (fs -> tot_sectors - fs -> dir_start - fs -> dir_len) / fs -> cluster_size;
return (0);
}
/*-----------------------------------------------------------------------------
* fs_init --
*-----------------------------------------------------------------------------
*/
int fs_init (Fs_t *fs)
{
BootSector_t *boot;
/* Initialize physical device */
if (dev_open () < 0) {
PRINTF ("Unable to initialize the fdc\n");
return (-1);
}
init_subdir ();
/* Allocate space for read the boot sector */
if ((boot = (BootSector_t *)malloc (sizeof (BootSector_t))) == NULL) {
PRINTF ("Unable to allocate space for boot sector\n");
return (-1);
}
/* read boot sector */
if (dev_read (boot, 0, 1)){
PRINTF ("Error during boot sector read\n");
free (boot);
return (-1);
}
/* we verify it'a a DOS diskette */
if (boot -> jump [0] != JUMP_0_1 && boot -> jump [0] != JUMP_0_2) {
PRINTF ("Not a DOS diskette\n");
free (boot);
return (-1);
}
if (boot -> descr < MEDIA_STD) {
/* We handle only recent medias (type F0) */
PRINTF ("unrecognized diskette type\n");
free (boot);
return (-1);
}
if (check_dev (boot, fs) < 0) {
PRINTF ("Bad diskette\n");
free (boot);
return (-1);
}
if (fill_fs (boot, fs) < 0) {
free (boot);
return (-1);
}
/* Read FAT */
if (read_fat (boot, fs) < 0) {
free (boot);
return (-1);
}
free (boot);
return (0);
}
#endif

View File

@ -1,348 +0,0 @@
/*
* (C) Copyright 2002
* Stäubli Faverges - <www.staubli.com>
* Pierre AUBERT p.aubert@staubli.com
*
* See file CREDITS for list of people who contributed to this
* project.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of
* the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
* MA 02111-1307 USA
*/
#include <common.h>
#include <config.h>
#include <malloc.h>
#if (CONFIG_COMMANDS & CFG_CMD_FDOS)
#include "dos.h"
#include "fdos.h"
static int cache_sect;
static unsigned char cache [SZ_STD_SECTOR];
#define min(x,y) ((x)<(y)?(x):(y))
static int descend (Slot_t *parent,
Fs_t *fs,
char *path);
/*-----------------------------------------------------------------------------
* init_subdir --
*-----------------------------------------------------------------------------
*/
void init_subdir (void)
{
cache_sect = -1;
}
/*-----------------------------------------------------------------------------
* basename --
*-----------------------------------------------------------------------------
*/
char *basename (char *name)
{
register char *cptr;
if (!name || !*name) {
return ("");
}
for (cptr= name; *cptr++; );
while (--cptr >= name) {
if (*cptr == '/') {
return (cptr + 1);
}
}
return(name);
}
/*-----------------------------------------------------------------------------
* root_map --
*-----------------------------------------------------------------------------
*/
static int root_map (Fs_t *fs, Slot_t *file, int where, int *len)
{
*len = min (*len, fs -> dir_len * SZ_STD_SECTOR - where);
if (*len < 0 ) {
*len = 0;
return (-1);
}
return fs -> dir_start * SZ_STD_SECTOR + where;
}
/*-----------------------------------------------------------------------------
* normal_map --
*-----------------------------------------------------------------------------
*/
static int normal_map (Fs_t *fs, Slot_t *file, int where, int *len)
{
int offset;
int NrClu;
unsigned short RelCluNr;
unsigned short CurCluNr;
unsigned short NewCluNr;
unsigned short AbsCluNr;
int clus_size;
clus_size = fs -> cluster_size * SZ_STD_SECTOR;
offset = where % clus_size;
*len = min (*len, file -> FileSize - where);
if (*len < 0 ) {
*len = 0;
return (0);
}
if (file -> FirstAbsCluNr < 2){
*len = 0;
return (0);
}
RelCluNr = where / clus_size;
if (RelCluNr >= file -> PreviousRelCluNr){
CurCluNr = file -> PreviousRelCluNr;
AbsCluNr = file -> PreviousAbsCluNr;
} else {
CurCluNr = 0;
AbsCluNr = file -> FirstAbsCluNr;
}
NrClu = (offset + *len - 1) / clus_size;
while (CurCluNr <= RelCluNr + NrClu) {
if (CurCluNr == RelCluNr){
/* we have reached the beginning of our zone. Save
* coordinates */
file -> PreviousRelCluNr = RelCluNr;
file -> PreviousAbsCluNr = AbsCluNr;
}
NewCluNr = fat_decode (fs, AbsCluNr);
if (NewCluNr == 1 || NewCluNr == 0) {
PRINTF("Fat problem while decoding %d %x\n",
AbsCluNr, NewCluNr);
return (-1);
}
if (CurCluNr == RelCluNr + NrClu) {
break;
}
if (CurCluNr < RelCluNr && NewCluNr == FAT12_END) {
*len = 0;
return 0;
}
if (CurCluNr >= RelCluNr && NewCluNr != AbsCluNr + 1)
break;
CurCluNr++;
AbsCluNr = NewCluNr;
}
*len = min (*len, (1 + CurCluNr - RelCluNr) * clus_size - offset);
return (((file -> PreviousAbsCluNr - 2) * fs -> cluster_size +
fs -> dir_start + fs -> dir_len) *
SZ_STD_SECTOR + offset);
}
/*-----------------------------------------------------------------------------
* open_subdir -- open the subdir containing the file
*-----------------------------------------------------------------------------
*/
int open_subdir (File_t *desc)
{
char *pathname;
char *tmp, *s, *path;
char terminator;
if ((pathname = (char *)malloc (MAX_PATH)) == NULL) {
return (-1);
}
strcpy (pathname, desc -> name);
/* Suppress file name */
tmp = basename (pathname);
*tmp = '\0';
/* root directory init */
desc -> subdir.FirstAbsCluNr = 0;
desc -> subdir.FileSize = -1;
desc -> subdir.map = root_map;
desc -> subdir.dir.attr = ATTR_DIRECTORY;
tmp = pathname;
for (s = tmp; ; ++s) {
if (*s == '/' || *s == '\0') {
path = tmp;
terminator = *s;
*s = '\0';
if (s != tmp && strcmp (path,".")) {
if (descend (&desc -> subdir, desc -> fs, path) < 0) {
free (pathname);
return (-1);
}
}
if (terminator == 0) {
break;
}
tmp = s + 1;
}
}
free (pathname);
return (0);
}
/*-----------------------------------------------------------------------------
* descend --
*-----------------------------------------------------------------------------
*/
static int descend (Slot_t *parent,
Fs_t *fs,
char *path)
{
int entry;
Slot_t SubDir;
if(path[0] == '\0' || strcmp (path, ".") == 0) {
return (0);
}
entry = 0;
if (vfat_lookup (parent,
fs,
&(SubDir.dir),
&entry,
0,
path,
ACCEPT_DIR | SINGLE | DO_OPEN,
0,
&SubDir) == 0) {
*parent = SubDir;
return (0);
}
if (strcmp(path, "..") == 0) {
parent -> FileSize = -1;
parent -> FirstAbsCluNr = 0;
parent -> map = root_map;
return (0);
}
return (-1);
}
/*-----------------------------------------------------------------------------
* open_file --
*-----------------------------------------------------------------------------
*/
int open_file (Slot_t *file, Directory_t *dir)
{
int first;
unsigned long size;
first = __le16_to_cpu (dir -> start);
if(first == 0 &&
(dir -> attr & ATTR_DIRECTORY) != 0) {
file -> FirstAbsCluNr = 0;
file -> FileSize = -1;
file -> map = root_map;
return (0);
}
if ((dir -> attr & ATTR_DIRECTORY) != 0) {
size = (1UL << 31) - 1;
}
else {
size = __le32_to_cpu (dir -> size);
}
file -> map = normal_map;
file -> FirstAbsCluNr = first;
file -> PreviousRelCluNr = 0xffff;
file -> FileSize = size;
return (0);
}
/*-----------------------------------------------------------------------------
* read_file --
*-----------------------------------------------------------------------------
*/
int read_file (Fs_t *fs,
Slot_t *file,
char *buf,
int where,
int len)
{
int pos;
int read, nb, sect, offset;
pos = file -> map (fs, file, where, &len);
if (pos < 0) {
return -1;
}
if (len == 0) {
return (0);
}
/* Compute sector number */
sect = pos / SZ_STD_SECTOR;
offset = pos % SZ_STD_SECTOR;
read = 0;
if (offset) {
/* Read doesn't start at the sector beginning. We need to use our */
/* cache */
if (sect != cache_sect) {
if (dev_read (cache, sect, 1) < 0) {
return (-1);
}
cache_sect = sect;
}
nb = min (len, SZ_STD_SECTOR - offset);
memcpy (buf, cache + offset, nb);
read += nb;
len -= nb;
sect += 1;
}
if (len > SZ_STD_SECTOR) {
nb = (len - 1) / SZ_STD_SECTOR;
if (dev_read (buf + read, sect, nb) < 0) {
return ((read) ? read : -1);
}
/* update sector position */
sect += nb;
/* Update byte position */
nb *= SZ_STD_SECTOR;
read += nb;
len -= nb;
}
if (len) {
if (sect != cache_sect) {
if (dev_read (cache, sect, 1) < 0) {
return ((read) ? read : -1);
cache_sect = -1;
}
cache_sect = sect;
}
memcpy (buf + read, cache, len);
read += len;
}
return (read);
}
#endif

View File

@ -1,357 +0,0 @@
/*
* (C) Copyright 2002
* Stäubli Faverges - <www.staubli.com>
* Pierre AUBERT p.aubert@staubli.com
*
* See file CREDITS for list of people who contributed to this
* project.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of
* the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
* MA 02111-1307 USA
*/
#include <common.h>
#include <config.h>
#if (CONFIG_COMMANDS & CFG_CMD_FDOS)
#include <linux/ctype.h>
#include "dos.h"
#include "fdos.h"
static int dir_read (Fs_t *fs,
Slot_t *dir,
Directory_t *dirent,
int num,
struct vfat_state *v);
static int unicode_read (char *in, char *out, int num);
static int match (const char *s, const char *p);
static unsigned char sum_shortname (char *name);
static int check_vfat (struct vfat_state *v, Directory_t *dir);
static char *conv_name (char *name, char *ext, char Case, char *ans);
/*-----------------------------------------------------------------------------
* clear_vfat --
*-----------------------------------------------------------------------------
*/
static void clear_vfat (struct vfat_state *v)
{
v -> subentries = 0;
v -> status = 0;
}
/*-----------------------------------------------------------------------------
* vfat_lookup --
*-----------------------------------------------------------------------------
*/
int vfat_lookup (Slot_t *dir,
Fs_t *fs,
Directory_t *dirent,
int *entry,
int *vfat_start,
char *filename,
int flags,
char *outname,
Slot_t *file)
{
int found;
struct vfat_state vfat;
char newfile [VSE_NAMELEN];
int vfat_present = 0;
if (*entry == -1) {
return -1;
}
found = 0;
clear_vfat (&vfat);
while (1) {
if (dir_read (fs, dir, dirent, *entry, &vfat) < 0) {
if (vfat_start) {
*vfat_start = *entry;
}
break;
}
(*entry)++;
/* Empty slot */
if (dirent -> name[0] == '\0'){
if (vfat_start == 0) {
break;
}
continue;
}
if (dirent -> attr == ATTR_VSE) {
/* VSE entry, continue */
continue;
}
if ( (dirent -> name [0] == DELMARK) ||
((dirent -> attr & ATTR_DIRECTORY) != 0 &&
(flags & ACCEPT_DIR) == 0) ||
((dirent -> attr & ATTR_VOLUME) != 0 &&
(flags & ACCEPT_LABEL) == 0) ||
(((dirent -> attr & (ATTR_DIRECTORY | ATTR_VOLUME)) == 0) &&
(flags & ACCEPT_PLAIN) == 0)) {
clear_vfat (&vfat);
continue;
}
vfat_present = check_vfat (&vfat, dirent);
if (vfat_start) {
*vfat_start = *entry - 1;
if (vfat_present) {
*vfat_start -= vfat.subentries;
}
}
if (dirent -> attr & ATTR_VOLUME) {
strncpy (newfile, dirent -> name, 8);
newfile [8] = '\0';
strncat (newfile, dirent -> ext, 3);
newfile [11] = '\0';
}
else {
conv_name (dirent -> name, dirent -> ext, dirent -> Case, newfile);
}
if (flags & MATCH_ANY) {
found = 1;
break;
}
if ((vfat_present && match (vfat.name, filename)) ||
(match (newfile, filename))) {
found = 1;
break;
}
clear_vfat (&vfat);
}
if (found) {
if ((flags & DO_OPEN) && file) {
if (open_file (file, dirent) < 0) {
return (-1);
}
}
if (outname) {
if (vfat_present) {
strcpy (outname, vfat.name);
}
else {
strcpy (outname, newfile);
}
}
return (0); /* File found */
} else {
*entry = -1;
return -1; /* File not found */
}
}
/*-----------------------------------------------------------------------------
* dir_read -- Read one directory entry
*-----------------------------------------------------------------------------
*/
static int dir_read (Fs_t *fs,
Slot_t *dir,
Directory_t *dirent,
int num,
struct vfat_state *v)
{
/* read the directory entry */
if (read_file (fs,
dir,
(char *)dirent,
num * MDIR_SIZE,
MDIR_SIZE) != MDIR_SIZE) {
return (-1);
}
if (v && (dirent -> attr == ATTR_VSE)) {
struct vfat_subentry *vse;
unsigned char id, last_flag;
char *c;
vse = (struct vfat_subentry *) dirent;
id = vse -> id & VSE_MASK;
last_flag = (vse -> id & VSE_LAST);
if (id > MAX_VFAT_SUBENTRIES) {
/* Invalid VSE entry */
return (-1);
}
/* Decode VSE */
if(v -> sum != vse -> sum) {
clear_vfat (v);
v -> sum = vse -> sum;
}
v -> status |= 1 << (id - 1);
if (last_flag) {
v -> subentries = id;
}
c = &(v -> name [VSE_NAMELEN * (id - 1)]);
c += unicode_read (vse->text1, c, VSE1SIZE);
c += unicode_read (vse->text2, c, VSE2SIZE);
c += unicode_read (vse->text3, c, VSE3SIZE);
if (last_flag) {
*c = '\0'; /* Null terminate long name */
}
}
return (0);
}
/*-----------------------------------------------------------------------------
* unicode_read --
*-----------------------------------------------------------------------------
*/
static int unicode_read (char *in, char *out, int num)
{
int j;
for (j = 0; j < num; ++j) {
if (in [1])
*out = '_';
else
*out = in [0];
out ++;
in += 2;
}
return num;
}
/*-----------------------------------------------------------------------------
* match --
*-----------------------------------------------------------------------------
*/
static int match (const char *s, const char *p)
{
for (; *p != '\0'; ) {
if (toupper (*s) != toupper (*p)) {
return (0);
}
p++;
s++;
}
if (*s != '\0') {
return (0);
}
else {
return (1);
}
}
/*-----------------------------------------------------------------------------
* sum_shortname --
*-----------------------------------------------------------------------------
*/
static unsigned char sum_shortname (char *name)
{
unsigned char sum;
int j;
for (j = sum = 0; j < 11; ++j) {
sum = ((sum & 1) ? 0x80 : 0) + (sum >> 1) +
(name [j] ? name [j] : ' ');
}
return (sum);
}
/*-----------------------------------------------------------------------------
* check_vfat --
* Return 1 if long name is valid, 0 else
*-----------------------------------------------------------------------------
*/
static int check_vfat (struct vfat_state *v, Directory_t *dir)
{
char name[12];
if (v -> subentries == 0) {
return 0;
}
strncpy (name, dir -> name, 8);
strncpy (name + 8, dir -> ext, 3);
name [11] = '\0';
if (v -> sum != sum_shortname (name)) {
return 0;
}
if( (v -> status & ((1 << v -> subentries) - 1)) !=
(1 << v -> subentries) - 1) {
return 0;
}
v->name [VSE_NAMELEN * v -> subentries] = 0;
return 1;
}
/*-----------------------------------------------------------------------------
* conv_name --
*-----------------------------------------------------------------------------
*/
static char *conv_name (char *name, char *ext, char Case, char *ans)
{
char tname [9], text [4];
int i;
i = 0;
while (i < 8 && name [i] != ' ' && name [i] != '\0') {
tname [i] = name [i];
i++;
}
tname [i] = '\0';
if (Case & BASECASE) {
for (i = 0; i < 8 && tname [i]; i++) {
tname [i] = tolower (tname [i]);
}
}
i = 0;
while (i < 3 && ext [i] != ' ' && ext [i] != '\0') {
text [i] = ext [i];
i++;
}
text [i] = '\0';
if (Case & EXTCASE){
for (i = 0; i < 3 && text [i]; i++) {
text [i] = tolower (text [i]);
}
}
if (*text) {
strcpy (ans, tname);
strcat (ans, ".");
strcat (ans, text);
}
else {
strcpy(ans, tname);
}
return (ans);
}
#endif

View File

@ -1,50 +0,0 @@
#
# (C) Copyright 2000-2006
# Wolfgang Denk, DENX Software Engineering, wd@denx.de.
#
# See file CREDITS for list of people who contributed to this
# project.
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License as
# published by the Free Software Foundation; either version 2 of
# the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston,
# MA 02111-1307 USA
#
include $(TOPDIR)/config.mk
LIB = $(obj)libjffs2.a
AOBJS =
COBJS = jffs2_1pass.o compr_rtime.o compr_rubin.o compr_zlib.o mini_inflate.o
COBJS += compr_lzo.o compr_lzari.o
SRCS := $(AOBJS:.o=.S) $(COBJS:.o=.c)
OBJS := $(addprefix $(obj),$(AOBJS) $(COBJS))
#CPPFLAGS +=
all: $(LIB) $(AOBJS)
$(LIB): $(obj).depend $(OBJS)
$(AR) $(ARFLAGS) $@ $(OBJS)
#########################################################################
# defines $(obj).depend target
include $(SRCTREE)/rules.mk
sinclude $(obj).depend
#########################################################################

View File

@ -1,262 +0,0 @@
/*
* JFFS2 -- Journalling Flash File System, Version 2.
*
* Copyright (C) 2004 Patrik Kluba,
* University of Szeged, Hungary
*
* For licensing information, see the file 'LICENCE' in the
* jffs2 directory.
*
* $Id: compr_lzari.c,v 1.3 2004/06/23 16:34:39 havasi Exp $
*
*/
/*
Lempel-Ziv-Arithmetic coding compression module for jffs2
Based on the LZARI source included in LDS (lossless datacompression sources)
*/
/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 4; tab-width: 4 -*- */
/*
Original copyright follows:
**************************************************************
LZARI.C -- A Data Compression Program
(tab = 4 spaces)
**************************************************************
4/7/1989 Haruhiko Okumura
Use, distribute, and modify this program freely.
Please send me your improved versions.
PC-VAN SCIENCE
NIFTY-Serve PAF01022
CompuServe 74050,1022
**************************************************************
LZARI.C (c)1989 by Haruyasu Yoshizaki, Haruhiko Okumura, and Kenji Rikitake.
All rights reserved. Permission granted for non-commercial use.
*/
/*
2004-02-18 pajko <pajko(AT)halom(DOT)u-szeged(DOT)hu>
Removed unused variables and fixed no return value
2004-02-16 pajko <pajko(AT)halom(DOT)u-szeged(DOT)hu>
Initial release
*/
#include <config.h>
#if ((CONFIG_COMMANDS & CFG_CMD_JFFS2) && defined(CONFIG_JFFS2_LZO_LZARI))
#include <linux/stddef.h>
#include <jffs2/jffs2.h>
#define N 4096 /* size of ring buffer */
#define F 60 /* upper limit for match_length */
#define THRESHOLD 2 /* encode string into position and length
if match_length is greater than this */
#define NIL N /* index for root of binary search trees */
static unsigned char
text_buf[N + F - 1]; /* ring buffer of size N,
with extra F-1 bytes to facilitate string comparison */
/********** Arithmetic Compression **********/
/* If you are not familiar with arithmetic compression, you should read
I. E. Witten, R. M. Neal, and J. G. Cleary,
Communications of the ACM, Vol. 30, pp. 520-540 (1987),
from which much have been borrowed. */
#define M 15
/* Q1 (= 2 to the M) must be sufficiently large, but not so
large as the unsigned long 4 * Q1 * (Q1 - 1) overflows. */
#define Q1 (1UL << M)
#define Q2 (2 * Q1)
#define Q3 (3 * Q1)
#define Q4 (4 * Q1)
#define MAX_CUM (Q1 - 1)
#define N_CHAR (256 - THRESHOLD + F)
/* character code = 0, 1, ..., N_CHAR - 1 */
static unsigned long char_to_sym[N_CHAR], sym_to_char[N_CHAR + 1];
static unsigned long
sym_freq[N_CHAR + 1], /* frequency for symbols */
sym_cum[N_CHAR + 1], /* cumulative freq for symbols */
position_cum[N + 1]; /* cumulative freq for positions */
static void StartModel(void) /* Initialize model */
{
unsigned long ch, sym, i;
sym_cum[N_CHAR] = 0;
for (sym = N_CHAR; sym >= 1; sym--) {
ch = sym - 1;
char_to_sym[ch] = sym; sym_to_char[sym] = ch;
sym_freq[sym] = 1;
sym_cum[sym - 1] = sym_cum[sym] + sym_freq[sym];
}
sym_freq[0] = 0; /* sentinel (!= sym_freq[1]) */
position_cum[N] = 0;
for (i = N; i >= 1; i--)
position_cum[i - 1] = position_cum[i] + 10000 / (i + 200);
/* empirical distribution function (quite tentative) */
/* Please devise a better mechanism! */
}
static void UpdateModel(unsigned long sym)
{
unsigned long c, ch_i, ch_sym;
unsigned long i;
if (sym_cum[0] >= MAX_CUM) {
c = 0;
for (i = N_CHAR; i > 0; i--) {
sym_cum[i] = c;
c += (sym_freq[i] = (sym_freq[i] + 1) >> 1);
}
sym_cum[0] = c;
}
for (i = sym; sym_freq[i] == sym_freq[i - 1]; i--) ;
if (i < sym) {
ch_i = sym_to_char[i]; ch_sym = sym_to_char[sym];
sym_to_char[i] = ch_sym; sym_to_char[sym] = ch_i;
char_to_sym[ch_i] = sym; char_to_sym[ch_sym] = i;
}
sym_freq[i]++;
while (--i > 0) sym_cum[i]++;
sym_cum[0]++;
}
static unsigned long BinarySearchSym(unsigned long x)
/* 1 if x >= sym_cum[1],
N_CHAR if sym_cum[N_CHAR] > x,
i such that sym_cum[i - 1] > x >= sym_cum[i] otherwise */
{
unsigned long i, j, k;
i = 1; j = N_CHAR;
while (i < j) {
k = (i + j) / 2;
if (sym_cum[k] > x) i = k + 1; else j = k;
}
return i;
}
unsigned long BinarySearchPos(unsigned long x)
/* 0 if x >= position_cum[1],
N - 1 if position_cum[N] > x,
i such that position_cum[i] > x >= position_cum[i + 1] otherwise */
{
unsigned long i, j, k;
i = 1; j = N;
while (i < j) {
k = (i + j) / 2;
if (position_cum[k] > x) i = k + 1; else j = k;
}
return i - 1;
}
static int Decode(unsigned char *srcbuf, unsigned char *dstbuf, unsigned long srclen,
unsigned long dstlen) /* Just the reverse of Encode(). */
{
unsigned long i, r, j, k, c, range, sym;
unsigned char *ip, *op;
unsigned char *srcend = srcbuf + srclen;
unsigned char *dstend = dstbuf + dstlen;
unsigned char buffer = 0;
unsigned char mask = 0;
unsigned long low = 0;
unsigned long high = Q4;
unsigned long value = 0;
ip = srcbuf;
op = dstbuf;
for (i = 0; i < M + 2; i++) {
value *= 2;
if ((mask >>= 1) == 0) {
buffer = (ip >= srcend) ? 0 : *(ip++);
mask = 128;
}
value += ((buffer & mask) != 0);
}
StartModel();
for (i = 0; i < N - F; i++) text_buf[i] = ' ';
r = N - F;
while (op < dstend) {
range = high - low;
sym = BinarySearchSym((unsigned long)
(((value - low + 1) * sym_cum[0] - 1) / range));
high = low + (range * sym_cum[sym - 1]) / sym_cum[0];
low += (range * sym_cum[sym ]) / sym_cum[0];
for ( ; ; ) {
if (low >= Q2) {
value -= Q2; low -= Q2; high -= Q2;
} else if (low >= Q1 && high <= Q3) {
value -= Q1; low -= Q1; high -= Q1;
} else if (high > Q2) break;
low += low; high += high;
value *= 2;
if ((mask >>= 1) == 0) {
buffer = (ip >= srcend) ? 0 : *(ip++);
mask = 128;
}
value += ((buffer & mask) != 0);
}
c = sym_to_char[sym];
UpdateModel(sym);
if (c < 256) {
if (op >= dstend) return -1;
*(op++) = c;
text_buf[r++] = c;
r &= (N - 1);
} else {
j = c - 255 + THRESHOLD;
range = high - low;
i = BinarySearchPos((unsigned long)
(((value - low + 1) * position_cum[0] - 1) / range));
high = low + (range * position_cum[i ]) / position_cum[0];
low += (range * position_cum[i + 1]) / position_cum[0];
for ( ; ; ) {
if (low >= Q2) {
value -= Q2; low -= Q2; high -= Q2;
} else if (low >= Q1 && high <= Q3) {
value -= Q1; low -= Q1; high -= Q1;
} else if (high > Q2) break;
low += low; high += high;
value *= 2;
if ((mask >>= 1) == 0) {
buffer = (ip >= srcend) ? 0 : *(ip++);
mask = 128;
}
value += ((buffer & mask) != 0);
}
i = (r - i - 1) & (N - 1);
for (k = 0; k < j; k++) {
c = text_buf[(i + k) & (N - 1)];
if (op >= dstend) return -1;
*(op++) = c;
text_buf[r++] = c;
r &= (N - 1);
}
}
}
return 0;
}
int lzari_decompress(unsigned char *data_in, unsigned char *cpage_out,
u32 srclen, u32 destlen)
{
return Decode(data_in, cpage_out, srclen, destlen);
}
#endif /* ((CONFIG_COMMANDS & CFG_CMD_JFFS2) && defined(CONFIG_JFFS2_LZO_LZARI)) */

View File

@ -1,405 +0,0 @@
/*
* JFFS2 -- Journalling Flash File System, Version 2.
*
* Copyright (C) 2004 Patrik Kluba,
* University of Szeged, Hungary
*
* For licensing information, see the file 'LICENCE' in the
* jffs2 directory.
*
* $Id: compr_lzo.c,v 1.3 2004/06/23 16:34:39 havasi Exp $
*
*/
/*
LZO1X-1 (and -999) compression module for jffs2
based on the original LZO sources
*/
/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 4; tab-width: 4 -*- */
/*
Original copyright notice follows:
lzo1x_9x.c -- implementation of the LZO1X-999 compression algorithm
lzo_ptr.h -- low-level pointer constructs
lzo_swd.ch -- sliding window dictionary
lzoconf.h -- configuration for the LZO real-time data compression library
lzo_mchw.ch -- matching functions using a window
minilzo.c -- mini subset of the LZO real-time data compression library
config1x.h -- configuration for the LZO1X algorithm
lzo1x.h -- public interface of the LZO1X compression algorithm
These files are part of the LZO real-time data compression library.
Copyright (C) 1996-2002 Markus Franz Xaver Johannes Oberhumer
All Rights Reserved.
The LZO library is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License as
published by the Free Software Foundation; either version 2 of
the License, or (at your option) any later version.
The LZO library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with the LZO library; see the file COPYING.
If not, write to the Free Software Foundation, Inc.,
59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
Markus F.X.J. Oberhumer
<markus@oberhumer.com>
*/
/*
2004-02-16 pajko <pajko(AT)halom(DOT)u-szeged(DOT)hu>
Initial release
-removed all 16 bit code
-all sensitive data will be on 4 byte boundary
-removed check parts for library use
-removed all but LZO1X-* compression
*/
#include <config.h>
#if ((CONFIG_COMMANDS & CFG_CMD_JFFS2) && defined(CONFIG_JFFS2_LZO_LZARI))
#include <linux/stddef.h>
#include <jffs2/jffs2.h>
#include <jffs2/compr_rubin.h>
/* Integral types that have *exactly* the same number of bits as a lzo_voidp */
typedef unsigned long lzo_ptr_t;
typedef long lzo_sptr_t;
/* data type definitions */
#define U32 unsigned long
#define S32 signed long
#define I32 long
#define U16 unsigned short
#define S16 signed short
#define I16 short
#define U8 unsigned char
#define S8 signed char
#define I8 char
#define M1_MAX_OFFSET 0x0400
#define M2_MAX_OFFSET 0x0800
#define M3_MAX_OFFSET 0x4000
#define M4_MAX_OFFSET 0xbfff
#define __COPY4(dst,src) * (lzo_uint32p)(dst) = * (const lzo_uint32p)(src)
#define COPY4(dst,src) __COPY4((lzo_ptr_t)(dst),(lzo_ptr_t)(src))
#define TEST_IP (ip < ip_end)
#define TEST_OP (op <= op_end)
#define NEED_IP(x) \
if ((lzo_uint)(ip_end - ip) < (lzo_uint)(x)) goto input_overrun
#define NEED_OP(x) \
if ((lzo_uint)(op_end - op) < (lzo_uint)(x)) goto output_overrun
#define TEST_LOOKBEHIND(m_pos,out) if (m_pos < out) goto lookbehind_overrun
typedef U32 lzo_uint32;
typedef I32 lzo_int32;
typedef U32 lzo_uint;
typedef I32 lzo_int;
typedef int lzo_bool;
#define lzo_byte U8
#define lzo_bytep U8 *
#define lzo_charp char *
#define lzo_voidp void *
#define lzo_shortp short *
#define lzo_ushortp unsigned short *
#define lzo_uint32p lzo_uint32 *
#define lzo_int32p lzo_int32 *
#define lzo_uintp lzo_uint *
#define lzo_intp lzo_int *
#define lzo_voidpp lzo_voidp *
#define lzo_bytepp lzo_bytep *
#define lzo_sizeof_dict_t sizeof(lzo_bytep)
#define LZO_E_OK 0
#define LZO_E_ERROR (-1)
#define LZO_E_OUT_OF_MEMORY (-2) /* not used right now */
#define LZO_E_NOT_COMPRESSIBLE (-3) /* not used right now */
#define LZO_E_INPUT_OVERRUN (-4)
#define LZO_E_OUTPUT_OVERRUN (-5)
#define LZO_E_LOOKBEHIND_OVERRUN (-6)
#define LZO_E_EOF_NOT_FOUND (-7)
#define LZO_E_INPUT_NOT_CONSUMED (-8)
#define PTR(a) ((lzo_ptr_t) (a))
#define PTR_LINEAR(a) PTR(a)
#define PTR_ALIGNED_4(a) ((PTR_LINEAR(a) & 3) == 0)
#define PTR_ALIGNED_8(a) ((PTR_LINEAR(a) & 7) == 0)
#define PTR_ALIGNED2_4(a,b) (((PTR_LINEAR(a) | PTR_LINEAR(b)) & 3) == 0)
#define PTR_ALIGNED2_8(a,b) (((PTR_LINEAR(a) | PTR_LINEAR(b)) & 7) == 0)
#define PTR_LT(a,b) (PTR(a) < PTR(b))
#define PTR_GE(a,b) (PTR(a) >= PTR(b))
#define PTR_DIFF(a,b) ((lzo_ptrdiff_t) (PTR(a) - PTR(b)))
#define pd(a,b) ((lzo_uint) ((a)-(b)))
typedef ptrdiff_t lzo_ptrdiff_t;
static int
lzo1x_decompress (const lzo_byte * in, lzo_uint in_len,
lzo_byte * out, lzo_uintp out_len, lzo_voidp wrkmem)
{
register lzo_byte *op;
register const lzo_byte *ip;
register lzo_uint t;
register const lzo_byte *m_pos;
const lzo_byte *const ip_end = in + in_len;
lzo_byte *const op_end = out + *out_len;
*out_len = 0;
op = out;
ip = in;
if (*ip > 17)
{
t = *ip++ - 17;
if (t < 4)
goto match_next;
NEED_OP (t);
NEED_IP (t + 1);
do
*op++ = *ip++;
while (--t > 0);
goto first_literal_run;
}
while (TEST_IP && TEST_OP)
{
t = *ip++;
if (t >= 16)
goto match;
if (t == 0)
{
NEED_IP (1);
while (*ip == 0)
{
t += 255;
ip++;
NEED_IP (1);
}
t += 15 + *ip++;
}
NEED_OP (t + 3);
NEED_IP (t + 4);
if (PTR_ALIGNED2_4 (op, ip))
{
COPY4 (op, ip);
op += 4;
ip += 4;
if (--t > 0)
{
if (t >= 4)
{
do
{
COPY4 (op, ip);
op += 4;
ip += 4;
t -= 4;
}
while (t >= 4);
if (t > 0)
do
*op++ = *ip++;
while (--t > 0);
}
else
do
*op++ = *ip++;
while (--t > 0);
}
}
else
{
*op++ = *ip++;
*op++ = *ip++;
*op++ = *ip++;
do
*op++ = *ip++;
while (--t > 0);
}
first_literal_run:
t = *ip++;
if (t >= 16)
goto match;
m_pos = op - (1 + M2_MAX_OFFSET);
m_pos -= t >> 2;
m_pos -= *ip++ << 2;
TEST_LOOKBEHIND (m_pos, out);
NEED_OP (3);
*op++ = *m_pos++;
*op++ = *m_pos++;
*op++ = *m_pos;
goto match_done;
while (TEST_IP && TEST_OP)
{
match:
if (t >= 64)
{
m_pos = op - 1;
m_pos -= (t >> 2) & 7;
m_pos -= *ip++ << 3;
t = (t >> 5) - 1;
TEST_LOOKBEHIND (m_pos, out);
NEED_OP (t + 3 - 1);
goto copy_match;
}
else if (t >= 32)
{
t &= 31;
if (t == 0)
{
NEED_IP (1);
while (*ip == 0)
{
t += 255;
ip++;
NEED_IP (1);
}
t += 31 + *ip++;
}
m_pos = op - 1;
m_pos -= (ip[0] >> 2) + (ip[1] << 6);
ip += 2;
}
else if (t >= 16)
{
m_pos = op;
m_pos -= (t & 8) << 11;
t &= 7;
if (t == 0)
{
NEED_IP (1);
while (*ip == 0)
{
t += 255;
ip++;
NEED_IP (1);
}
t += 7 + *ip++;
}
m_pos -= (ip[0] >> 2) + (ip[1] << 6);
ip += 2;
if (m_pos == op)
goto eof_found;
m_pos -= 0x4000;
}
else
{
m_pos = op - 1;
m_pos -= t >> 2;
m_pos -= *ip++ << 2;
TEST_LOOKBEHIND (m_pos, out);
NEED_OP (2);
*op++ = *m_pos++;
*op++ = *m_pos;
goto match_done;
}
TEST_LOOKBEHIND (m_pos, out);
NEED_OP (t + 3 - 1);
if (t >= 2 * 4 - (3 - 1)
&& PTR_ALIGNED2_4 (op, m_pos))
{
COPY4 (op, m_pos);
op += 4;
m_pos += 4;
t -= 4 - (3 - 1);
do
{
COPY4 (op, m_pos);
op += 4;
m_pos += 4;
t -= 4;
}
while (t >= 4);
if (t > 0)
do
*op++ = *m_pos++;
while (--t > 0);
}
else
{
copy_match:
*op++ = *m_pos++;
*op++ = *m_pos++;
do
*op++ = *m_pos++;
while (--t > 0);
}
match_done:
t = ip[-2] & 3;
if (t == 0)
break;
match_next:
NEED_OP (t);
NEED_IP (t + 1);
do
*op++ = *ip++;
while (--t > 0);
t = *ip++;
}
}
*out_len = op - out;
return LZO_E_EOF_NOT_FOUND;
eof_found:
*out_len = op - out;
return (ip == ip_end ? LZO_E_OK :
(ip <
ip_end ? LZO_E_INPUT_NOT_CONSUMED : LZO_E_INPUT_OVERRUN));
input_overrun:
*out_len = op - out;
return LZO_E_INPUT_OVERRUN;
output_overrun:
*out_len = op - out;
return LZO_E_OUTPUT_OVERRUN;
lookbehind_overrun:
*out_len = op - out;
return LZO_E_LOOKBEHIND_OVERRUN;
}
int lzo_decompress(unsigned char *data_in, unsigned char *cpage_out,
u32 srclen, u32 destlen)
{
lzo_uint outlen = destlen;
return lzo1x_decompress (data_in, srclen, cpage_out, &outlen, NULL);
}
#endif /* ((CONFIG_COMMANDS & CFG_CMD_JFFS2) && defined(CONFIG_JFFS2_LZO_LZARI)) */

View File

@ -1,91 +0,0 @@
/*
* JFFS2 -- Journalling Flash File System, Version 2.
*
* Copyright (C) 2001 Red Hat, Inc.
*
* Created by Arjan van de Ven <arjanv@redhat.com>
*
* The original JFFS, from which the design for JFFS2 was derived,
* was designed and implemented by Axis Communications AB.
*
* The contents of this file are subject to the Red Hat eCos Public
* License Version 1.1 (the "Licence"); you may not use this file
* except in compliance with the Licence. You may obtain a copy of
* the Licence at http://www.redhat.com/
*
* Software distributed under the Licence is distributed on an "AS IS"
* basis, WITHOUT WARRANTY OF ANY KIND, either express or implied.
* See the Licence for the specific language governing rights and
* limitations under the Licence.
*
* The Original Code is JFFS2 - Journalling Flash File System, version 2
*
* Alternatively, the contents of this file may be used under the
* terms of the GNU General Public License version 2 (the "GPL"), in
* which case the provisions of the GPL are applicable instead of the
* above. If you wish to allow the use of your version of this file
* only under the terms of the GPL and not to allow others to use your
* version of this file under the RHEPL, indicate your decision by
* deleting the provisions above and replace them with the notice and
* other provisions required by the GPL. If you do not delete the
* provisions above, a recipient may use your version of this file
* under either the RHEPL or the GPL.
*
* $Id: compr_rtime.c,v 1.2 2002/01/24 22:58:42 rfeany Exp $
*
*
* Very simple lz77-ish encoder.
*
* Theory of operation: Both encoder and decoder have a list of "last
* occurances" for every possible source-value; after sending the
* first source-byte, the second byte indicated the "run" length of
* matches
*
* The algorithm is intended to only send "whole bytes", no bit-messing.
*
*/
#include <config.h>
#if (CONFIG_COMMANDS & CFG_CMD_JFFS2)
#include <jffs2/jffs2.h>
void rtime_decompress(unsigned char *data_in, unsigned char *cpage_out,
u32 srclen, u32 destlen)
{
int positions[256];
int outpos;
int pos;
int i;
outpos = pos = 0;
for (i = 0; i < 256; positions[i++] = 0);
while (outpos<destlen) {
unsigned char value;
int backoffs;
int repeat;
value = data_in[pos++];
cpage_out[outpos++] = value; /* first the verbatim copied byte */
repeat = data_in[pos++];
backoffs = positions[value];
positions[value]=outpos;
if (repeat) {
if (backoffs + repeat >= outpos) {
while(repeat) {
cpage_out[outpos++] = cpage_out[backoffs++];
repeat--;
}
} else {
for (i = 0; i < repeat; i++)
*(cpage_out + outpos + i) = *(cpage_out + backoffs + i);
outpos+=repeat;
}
}
}
}
#endif /* CFG_CMD_JFFS2 */

View File

@ -1,126 +0,0 @@
/*
* JFFS2 -- Journalling Flash File System, Version 2.
*
* Copyright (C) 2001 Red Hat, Inc.
*
* Created by Arjan van de Ven <arjanv@redhat.com>
*
* Heavily modified by Russ Dill <Russ.Dill@asu.edu> in an attempt at
* a little more speed.
*
* The original JFFS, from which the design for JFFS2 was derived,
* was designed and implemented by Axis Communications AB.
*
* The contents of this file are subject to the Red Hat eCos Public
* License Version 1.1 (the "Licence"); you may not use this file
* except in compliance with the Licence. You may obtain a copy of
* the Licence at http://www.redhat.com/
*
* Software distributed under the Licence is distributed on an "AS IS"
* basis, WITHOUT WARRANTY OF ANY KIND, either express or implied.
* See the Licence for the specific language governing rights and
* limitations under the Licence.
*
* The Original Code is JFFS2 - Journalling Flash File System, version 2
*
* Alternatively, the contents of this file may be used under the
* terms of the GNU General Public License version 2 (the "GPL"), in
* which case the provisions of the GPL are applicable instead of the
* above. If you wish to allow the use of your version of this file
* only under the terms of the GPL and not to allow others to use your
* version of this file under the RHEPL, indicate your decision by
* deleting the provisions above and replace them with the notice and
* other provisions required by the GPL. If you do not delete the
* provisions above, a recipient may use your version of this file
* under either the RHEPL or the GPL.
*
* $Id: compr_rubin.c,v 1.2 2002/01/24 22:58:42 rfeany Exp $
*
*/
#include <config.h>
#if (CONFIG_COMMANDS & CFG_CMD_JFFS2)
#include <jffs2/jffs2.h>
#include <jffs2/compr_rubin.h>
void rubin_do_decompress(unsigned char *bits, unsigned char *in,
unsigned char *page_out, __u32 destlen)
{
register char *curr = (char *)page_out;
char *end = (char *)(page_out + destlen);
register unsigned long temp;
register unsigned long result;
register unsigned long p;
register unsigned long q;
register unsigned long rec_q;
register unsigned long bit;
register long i0;
unsigned long i;
/* init_pushpull */
temp = *(u32 *) in;
bit = 16;
/* init_rubin */
q = 0;
p = (long) (2 * UPPER_BIT_RUBIN);
/* init_decode */
rec_q = (in[0] << 8) | in[1];
while (curr < end) {
/* in byte */
result = 0;
for (i = 0; i < 8; i++) {
/* decode */
while ((q & UPPER_BIT_RUBIN) || ((p + q) <= UPPER_BIT_RUBIN)) {
q &= ~UPPER_BIT_RUBIN;
q <<= 1;
p <<= 1;
rec_q &= ~UPPER_BIT_RUBIN;
rec_q <<= 1;
rec_q |= (temp >> (bit++ ^ 7)) & 1;
if (bit > 31) {
u32 *p = (u32 *)in;
bit = 0;
temp = *(++p);
in = (unsigned char *)p;
}
}
i0 = (bits[i] * p) >> 8;
if (i0 <= 0) i0 = 1;
/* if it fails, it fails, we have our crc
if (i0 >= p) i0 = p - 1; */
result >>= 1;
if (rec_q < q + i0) {
/* result |= 0x00; */
p = i0;
} else {
result |= 0x80;
p -= i0;
q += i0;
}
}
*(curr++) = result;
}
}
void dynrubin_decompress(unsigned char *data_in, unsigned char *cpage_out,
unsigned long sourcelen, unsigned long dstlen)
{
unsigned char bits[8];
int c;
for (c=0; c<8; c++)
bits[c] = (256 - data_in[c]);
rubin_do_decompress(bits, data_in+8, cpage_out, dstlen);
}
#endif /* CFG_CMD_JFFS2 */

View File

@ -1,52 +0,0 @@
/*
* JFFS2 -- Journalling Flash File System, Version 2.
*
* Copyright (C) 2001 Red Hat, Inc.
*
* Created by David Woodhouse <dwmw2@cambridge.redhat.com>
*
* The original JFFS, from which the design for JFFS2 was derived,
* was designed and implemented by Axis Communications AB.
*
* The contents of this file are subject to the Red Hat eCos Public
* License Version 1.1 (the "Licence"); you may not use this file
* except in compliance with the Licence. You may obtain a copy of
* the Licence at http://www.redhat.com/
*
* Software distributed under the Licence is distributed on an "AS IS"
* basis, WITHOUT WARRANTY OF ANY KIND, either express or implied.
* See the Licence for the specific language governing rights and
* limitations under the Licence.
*
* The Original Code is JFFS2 - Journalling Flash File System, version 2
*
* Alternatively, the contents of this file may be used under the
* terms of the GNU General Public License version 2 (the "GPL"), in
* which case the provisions of the GPL are applicable instead of the
* above. If you wish to allow the use of your version of this file
* only under the terms of the GPL and not to allow others to use your
* version of this file under the RHEPL, indicate your decision by
* deleting the provisions above and replace them with the notice and
* other provisions required by the GPL. If you do not delete the
* provisions above, a recipient may use your version of this file
* under either the RHEPL or the GPL.
*
* $Id: compr_zlib.c,v 1.2 2002/01/24 22:58:42 rfeany Exp $
*
*/
#include <common.h>
#include <config.h>
#if (CONFIG_COMMANDS & CFG_CMD_JFFS2)
#include <jffs2/jffs2.h>
#include <jffs2/mini_inflate.h>
long zlib_decompress(unsigned char *data_in, unsigned char *cpage_out,
__u32 srclen, __u32 destlen)
{
return (decompress_block(cpage_out, data_in + 2, ldr_memcpy));
}
#endif /* CFG_CMD_JFFS2 */

File diff suppressed because it is too large Load Diff

View File

@ -1,966 +0,0 @@
#include <common.h>
#if !defined(CFG_NAND_LEGACY) && (CONFIG_COMMANDS & CFG_CMD_JFFS2)
#include <malloc.h>
#include <linux/stat.h>
#include <linux/time.h>
#include <jffs2/jffs2.h>
#include <jffs2/jffs2_1pass.h>
#include <nand.h>
#include "jffs2_nand_private.h"
#define NODE_CHUNK 1024 /* size of memory allocation chunk in b_nodes */
/* Debugging switches */
#undef DEBUG_DIRENTS /* print directory entry list after scan */
#undef DEBUG_FRAGMENTS /* print fragment list after scan */
#undef DEBUG /* enable debugging messages */
#ifdef DEBUG
# define DEBUGF(fmt,args...) printf(fmt ,##args)
#else
# define DEBUGF(fmt,args...)
#endif
static nand_info_t *nand;
/* Compression names */
static char *compr_names[] = {
"NONE",
"ZERO",
"RTIME",
"RUBINMIPS",
"COPY",
"DYNRUBIN",
"ZLIB",
#if defined(CONFIG_JFFS2_LZO_LZARI)
"LZO",
"LZARI",
#endif
};
/* Spinning wheel */
static char spinner[] = { '|', '/', '-', '\\' };
/* Memory management */
struct mem_block {
unsigned index;
struct mem_block *next;
char nodes[0];
};
static void
free_nodes(struct b_list *list)
{
while (list->listMemBase != NULL) {
struct mem_block *next = list->listMemBase->next;
free(list->listMemBase);
list->listMemBase = next;
}
}
static struct b_node *
add_node(struct b_list *list, int size)
{
u32 index = 0;
struct mem_block *memBase;
struct b_node *b;
memBase = list->listMemBase;
if (memBase != NULL)
index = memBase->index;
if (memBase == NULL || index >= NODE_CHUNK) {
/* we need more space before we continue */
memBase = mmalloc(sizeof(struct mem_block) + NODE_CHUNK * size);
if (memBase == NULL) {
putstr("add_node: malloc failed\n");
return NULL;
}
memBase->next = list->listMemBase;
index = 0;
}
/* now we have room to add it. */
b = (struct b_node *)&memBase->nodes[size * index];
index ++;
memBase->index = index;
list->listMemBase = memBase;
list->listCount++;
return b;
}
static struct b_node *
insert_node(struct b_list *list, struct b_node *new)
{
#ifdef CFG_JFFS2_SORT_FRAGMENTS
struct b_node *b, *prev;
if (list->listTail != NULL && list->listCompare(new, list->listTail))
prev = list->listTail;
else if (list->listLast != NULL && list->listCompare(new, list->listLast))
prev = list->listLast;
else
prev = NULL;
for (b = (prev ? prev->next : list->listHead);
b != NULL && list->listCompare(new, b);
prev = b, b = b->next) {
list->listLoops++;
}
if (b != NULL)
list->listLast = prev;
if (b != NULL) {
new->next = b;
if (prev != NULL)
prev->next = new;
else
list->listHead = new;
} else
#endif
{
new->next = (struct b_node *) NULL;
if (list->listTail != NULL) {
list->listTail->next = new;
list->listTail = new;
} else {
list->listTail = list->listHead = new;
}
}
return new;
}
static struct b_node *
insert_inode(struct b_list *list, struct jffs2_raw_inode *node, u32 offset)
{
struct b_inode *new;
if (!(new = (struct b_inode *)add_node(list, sizeof(struct b_inode)))) {
putstr("add_node failed!\r\n");
return NULL;
}
new->offset = offset;
new->version = node->version;
new->ino = node->ino;
new->isize = node->isize;
new->csize = node->csize;
return insert_node(list, (struct b_node *)new);
}
static struct b_node *
insert_dirent(struct b_list *list, struct jffs2_raw_dirent *node, u32 offset)
{
struct b_dirent *new;
if (!(new = (struct b_dirent *)add_node(list, sizeof(struct b_dirent)))) {
putstr("add_node failed!\r\n");
return NULL;
}
new->offset = offset;
new->version = node->version;
new->pino = node->pino;
new->ino = node->ino;
new->nhash = full_name_hash(node->name, node->nsize);
new->nsize = node->nsize;
new->type = node->type;
return insert_node(list, (struct b_node *)new);
}
#ifdef CFG_JFFS2_SORT_FRAGMENTS
/* Sort data entries with the latest version last, so that if there
* is overlapping data the latest version will be used.
*/
static int compare_inodes(struct b_node *new, struct b_node *old)
{
struct jffs2_raw_inode ojNew;
struct jffs2_raw_inode ojOld;
struct jffs2_raw_inode *jNew =
(struct jffs2_raw_inode *)get_fl_mem(new->offset, sizeof(ojNew), &ojNew);
struct jffs2_raw_inode *jOld =
(struct jffs2_raw_inode *)get_fl_mem(old->offset, sizeof(ojOld), &ojOld);
return jNew->version > jOld->version;
}
/* Sort directory entries so all entries in the same directory
* with the same name are grouped together, with the latest version
* last. This makes it easy to eliminate all but the latest version
* by marking the previous version dead by setting the inode to 0.
*/
static int compare_dirents(struct b_node *new, struct b_node *old)
{
struct jffs2_raw_dirent ojNew;
struct jffs2_raw_dirent ojOld;
struct jffs2_raw_dirent *jNew =
(struct jffs2_raw_dirent *)get_fl_mem(new->offset, sizeof(ojNew), &ojNew);
struct jffs2_raw_dirent *jOld =
(struct jffs2_raw_dirent *)get_fl_mem(old->offset, sizeof(ojOld), &ojOld);
int cmp;
/* ascending sort by pino */
if (jNew->pino != jOld->pino)
return jNew->pino > jOld->pino;
/* pino is the same, so use ascending sort by nsize, so
* we don't do strncmp unless we really must.
*/
if (jNew->nsize != jOld->nsize)
return jNew->nsize > jOld->nsize;
/* length is also the same, so use ascending sort by name
*/
cmp = strncmp(jNew->name, jOld->name, jNew->nsize);
if (cmp != 0)
return cmp > 0;
/* we have duplicate names in this directory, so use ascending
* sort by version
*/
if (jNew->version > jOld->version) {
/* since jNew is newer, we know jOld is not valid, so
* mark it with inode 0 and it will not be used
*/
jOld->ino = 0;
return 1;
}
return 0;
}
#endif
static u32
jffs_init_1pass_list(struct part_info *part)
{
struct b_lists *pL;
if (part->jffs2_priv != NULL) {
pL = (struct b_lists *)part->jffs2_priv;
free_nodes(&pL->frag);
free_nodes(&pL->dir);
free(pL);
}
if (NULL != (part->jffs2_priv = malloc(sizeof(struct b_lists)))) {
pL = (struct b_lists *)part->jffs2_priv;
memset(pL, 0, sizeof(*pL));
#ifdef CFG_JFFS2_SORT_FRAGMENTS
pL->dir.listCompare = compare_dirents;
pL->frag.listCompare = compare_inodes;
#endif
}
return 0;
}
/* find the inode from the slashless name given a parent */
static long
jffs2_1pass_read_inode(struct b_lists *pL, u32 ino, char *dest,
struct stat *stat)
{
struct b_inode *jNode;
u32 totalSize = 0;
u32 latestVersion = 0;
long ret;
#ifdef CFG_JFFS2_SORT_FRAGMENTS
/* Find file size before loading any data, so fragments that
* start past the end of file can be ignored. A fragment
* that is partially in the file is loaded, so extra data may
* be loaded up to the next 4K boundary above the file size.
* This shouldn't cause trouble when loading kernel images, so
* we will live with it.
*/
for (jNode = (struct b_inode *)pL->frag.listHead; jNode; jNode = jNode->next) {
if ((ino == jNode->ino)) {
/* get actual file length from the newest node */
if (jNode->version >= latestVersion) {
totalSize = jNode->isize;
latestVersion = jNode->version;
}
}
}
#endif
for (jNode = (struct b_inode *)pL->frag.listHead; jNode; jNode = jNode->next) {
if ((ino != jNode->ino))
continue;
#ifndef CFG_JFFS2_SORT_FRAGMENTS
/* get actual file length from the newest node */
if (jNode->version >= latestVersion) {
totalSize = jNode->isize;
latestVersion = jNode->version;
}
#endif
if (dest || stat) {
char *src, *dst;
char data[4096 + sizeof(struct jffs2_raw_inode)];
struct jffs2_raw_inode *inode;
size_t len;
inode = (struct jffs2_raw_inode *)&data;
len = sizeof(struct jffs2_raw_inode);
if (dest)
len += jNode->csize;
nand_read(nand, jNode->offset, &len, inode);
/* ignore data behind latest known EOF */
if (inode->offset > totalSize)
continue;
if (stat) {
stat->st_mtime = inode->mtime;
stat->st_mode = inode->mode;
stat->st_ino = inode->ino;
stat->st_size = totalSize;
}
if (!dest)
continue;
src = ((char *) inode) + sizeof(struct jffs2_raw_inode);
dst = (char *) (dest + inode->offset);
switch (inode->compr) {
case JFFS2_COMPR_NONE:
ret = 0;
memcpy(dst, src, inode->dsize);
break;
case JFFS2_COMPR_ZERO:
ret = 0;
memset(dst, 0, inode->dsize);
break;
case JFFS2_COMPR_RTIME:
ret = 0;
rtime_decompress(src, dst, inode->csize, inode->dsize);
break;
case JFFS2_COMPR_DYNRUBIN:
/* this is slow but it works */
ret = 0;
dynrubin_decompress(src, dst, inode->csize, inode->dsize);
break;
case JFFS2_COMPR_ZLIB:
ret = zlib_decompress(src, dst, inode->csize, inode->dsize);
break;
#if defined(CONFIG_JFFS2_LZO_LZARI)
case JFFS2_COMPR_LZO:
ret = lzo_decompress(src, dst, inode->csize, inode->dsize);
break;
case JFFS2_COMPR_LZARI:
ret = lzari_decompress(src, dst, inode->csize, inode->dsize);
break;
#endif
default:
/* unknown */
putLabeledWord("UNKOWN COMPRESSION METHOD = ", inode->compr);
return -1;
}
}
}
return totalSize;
}
/* find the inode from the slashless name given a parent */
static u32
jffs2_1pass_find_inode(struct b_lists * pL, const char *name, u32 pino)
{
struct b_dirent *jDir;
int len = strlen(name); /* name is assumed slash free */
unsigned int nhash = full_name_hash(name, len);
u32 version = 0;
u32 inode = 0;
/* we need to search all and return the inode with the highest version */
for (jDir = (struct b_dirent *)pL->dir.listHead; jDir; jDir = jDir->next) {
if ((pino == jDir->pino) && (jDir->ino) && /* 0 for unlink */
(len == jDir->nsize) && (nhash == jDir->nhash)) {
/* TODO: compare name */
if (jDir->version < version)
continue;
if (jDir->version == version && inode != 0) {
/* I'm pretty sure this isn't legal */
putstr(" ** ERROR ** ");
/* putnstr(jDir->name, jDir->nsize); */
/* putLabeledWord(" has dup version =", version); */
}
inode = jDir->ino;
version = jDir->version;
}
}
return inode;
}
static inline void dump_stat(struct stat *st, const char *name)
{
char str[20];
char s[64], *p;
if (st->st_mtime == (time_t)(-1)) /* some ctimes really hate -1 */
st->st_mtime = 1;
ctime_r(&st->st_mtime, s/*,64*/); /* newlib ctime doesn't have buflen */
if ((p = strchr(s,'\n')) != NULL) *p = '\0';
if ((p = strchr(s,'\r')) != NULL) *p = '\0';
/*
printf("%6lo %s %8ld %s %s\n", st->st_mode, mkmodestr(st->st_mode, str),
st->st_size, s, name);
*/
printf(" %s %8ld %s %s", mkmodestr(st->st_mode,str), st->st_size, s, name);
}
static inline int
dump_inode(struct b_lists *pL, struct b_dirent *d, struct b_inode *i)
{
char fname[JFFS2_MAX_NAME_LEN + 1];
struct stat st;
size_t len;
if(!d || !i) return -1;
len = d->nsize;
nand_read(nand, d->offset + sizeof(struct jffs2_raw_dirent),
&len, &fname);
fname[d->nsize] = '\0';
memset(&st, 0, sizeof(st));
jffs2_1pass_read_inode(pL, i->ino, NULL, &st);
dump_stat(&st, fname);
/* FIXME
if (d->type == DT_LNK) {
unsigned char *src = (unsigned char *) (&i[1]);
putstr(" -> ");
putnstr(src, (int)i->dsize);
}
*/
putstr("\r\n");
return 0;
}
/* list inodes with the given pino */
static u32
jffs2_1pass_list_inodes(struct b_lists * pL, u32 pino)
{
struct b_dirent *jDir;
u32 i_version = 0;
for (jDir = (struct b_dirent *)pL->dir.listHead; jDir; jDir = jDir->next) {
if ((pino == jDir->pino) && (jDir->ino)) { /* ino=0 -> unlink */
struct b_inode *jNode = (struct b_inode *)pL->frag.listHead;
struct b_inode *i = NULL;
while (jNode) {
if (jNode->ino == jDir->ino && jNode->version >= i_version) {
i_version = jNode->version;
i = jNode;
}
jNode = jNode->next;
}
dump_inode(pL, jDir, i);
}
}
return pino;
}
static u32
jffs2_1pass_search_inode(struct b_lists * pL, const char *fname, u32 pino)
{
int i;
char tmp[256];
char working_tmp[256];
char *c;
/* discard any leading slash */
i = 0;
while (fname[i] == '/')
i++;
strcpy(tmp, &fname[i]);
while ((c = (char *) strchr(tmp, '/'))) /* we are still dired searching */
{
strncpy(working_tmp, tmp, c - tmp);
working_tmp[c - tmp] = '\0';
for (i = 0; i < strlen(c) - 1; i++)
tmp[i] = c[i + 1];
tmp[i] = '\0';
if (!(pino = jffs2_1pass_find_inode(pL, working_tmp, pino))) {
putstr("find_inode failed for name=");
putstr(working_tmp);
putstr("\r\n");
return 0;
}
}
/* this is for the bare filename, directories have already been mapped */
if (!(pino = jffs2_1pass_find_inode(pL, tmp, pino))) {
putstr("find_inode failed for name=");
putstr(tmp);
putstr("\r\n");
return 0;
}
return pino;
}
static u32
jffs2_1pass_resolve_inode(struct b_lists * pL, u32 ino)
{
struct b_dirent *jDir;
struct b_inode *jNode;
u8 jDirFoundType = 0;
u32 jDirFoundIno = 0;
u32 jDirFoundPino = 0;
char tmp[JFFS2_MAX_NAME_LEN + 1];
u32 version = 0;
u32 pino;
/* we need to search all and return the inode with the highest version */
for (jDir = (struct b_dirent *)pL->dir.listHead; jDir; jDir = jDir->next) {
if (ino == jDir->ino) {
if (jDir->version < version)
continue;
if (jDir->version == version && jDirFoundType) {
/* I'm pretty sure this isn't legal */
putstr(" ** ERROR ** ");
/* putnstr(jDir->name, jDir->nsize); */
/* putLabeledWord(" has dup version (resolve) = ", */
/* version); */
}
jDirFoundType = jDir->type;
jDirFoundIno = jDir->ino;
jDirFoundPino = jDir->pino;
version = jDir->version;
}
}
/* now we found the right entry again. (shoulda returned inode*) */
if (jDirFoundType != DT_LNK)
return jDirFoundIno;
/* it's a soft link so we follow it again. */
for (jNode = (struct b_inode *)pL->frag.listHead; jNode; jNode = jNode->next) {
if (jNode->ino == jDirFoundIno) {
size_t len = jNode->csize;
nand_read(nand, jNode->offset + sizeof(struct jffs2_raw_inode), &len, &tmp);
tmp[jNode->csize] = '\0';
break;
}
}
/* ok so the name of the new file to find is in tmp */
/* if it starts with a slash it is root based else shared dirs */
if (tmp[0] == '/')
pino = 1;
else
pino = jDirFoundPino;
return jffs2_1pass_search_inode(pL, tmp, pino);
}
static u32
jffs2_1pass_search_list_inodes(struct b_lists * pL, const char *fname, u32 pino)
{
int i;
char tmp[256];
char working_tmp[256];
char *c;
/* discard any leading slash */
i = 0;
while (fname[i] == '/')
i++;
strcpy(tmp, &fname[i]);
working_tmp[0] = '\0';
while ((c = (char *) strchr(tmp, '/'))) /* we are still dired searching */
{
strncpy(working_tmp, tmp, c - tmp);
working_tmp[c - tmp] = '\0';
for (i = 0; i < strlen(c) - 1; i++)
tmp[i] = c[i + 1];
tmp[i] = '\0';
/* only a failure if we arent looking at top level */
if (!(pino = jffs2_1pass_find_inode(pL, working_tmp, pino)) &&
(working_tmp[0])) {
putstr("find_inode failed for name=");
putstr(working_tmp);
putstr("\r\n");
return 0;
}
}
if (tmp[0] && !(pino = jffs2_1pass_find_inode(pL, tmp, pino))) {
putstr("find_inode failed for name=");
putstr(tmp);
putstr("\r\n");
return 0;
}
/* this is for the bare filename, directories have already been mapped */
if (!(pino = jffs2_1pass_list_inodes(pL, pino))) {
putstr("find_inode failed for name=");
putstr(tmp);
putstr("\r\n");
return 0;
}
return pino;
}
unsigned char
jffs2_1pass_rescan_needed(struct part_info *part)
{
struct b_node *b;
struct jffs2_unknown_node onode;
struct jffs2_unknown_node *node;
struct b_lists *pL = (struct b_lists *)part->jffs2_priv;
if (part->jffs2_priv == 0){
DEBUGF ("rescan: First time in use\n");
return 1;
}
/* if we have no list, we need to rescan */
if (pL->frag.listCount == 0) {
DEBUGF ("rescan: fraglist zero\n");
return 1;
}
/* or if we are scanning a new partition */
if (pL->partOffset != part->offset) {
DEBUGF ("rescan: different partition\n");
return 1;
}
/* FIXME */
return 0;
}
#ifdef DEBUG_FRAGMENTS
static void
dump_fragments(struct b_lists *pL)
{
struct b_node *b;
struct jffs2_raw_inode ojNode;
struct jffs2_raw_inode *jNode;
putstr("\r\n\r\n******The fragment Entries******\r\n");
b = pL->frag.listHead;
while (b) {
jNode = (struct jffs2_raw_inode *) get_fl_mem(b->offset,
sizeof(ojNode), &ojNode);
putLabeledWord("\r\n\tbuild_list: FLASH_OFFSET = ", b->offset);
putLabeledWord("\tbuild_list: totlen = ", jNode->totlen);
putLabeledWord("\tbuild_list: inode = ", jNode->ino);
putLabeledWord("\tbuild_list: version = ", jNode->version);
putLabeledWord("\tbuild_list: isize = ", jNode->isize);
putLabeledWord("\tbuild_list: atime = ", jNode->atime);
putLabeledWord("\tbuild_list: offset = ", jNode->offset);
putLabeledWord("\tbuild_list: csize = ", jNode->csize);
putLabeledWord("\tbuild_list: dsize = ", jNode->dsize);
putLabeledWord("\tbuild_list: compr = ", jNode->compr);
putLabeledWord("\tbuild_list: usercompr = ", jNode->usercompr);
putLabeledWord("\tbuild_list: flags = ", jNode->flags);
putLabeledWord("\tbuild_list: offset = ", b->offset); /* FIXME: ? [RS] */
b = b->next;
}
}
#endif
#ifdef DEBUG_DIRENTS
static void
dump_dirents(struct b_lists *pL)
{
struct b_node *b;
struct jffs2_raw_dirent *jDir;
putstr("\r\n\r\n******The directory Entries******\r\n");
b = pL->dir.listHead;
while (b) {
jDir = (struct jffs2_raw_dirent *) get_node_mem(b->offset);
putstr("\r\n");
putnstr(jDir->name, jDir->nsize);
putLabeledWord("\r\n\tbuild_list: magic = ", jDir->magic);
putLabeledWord("\tbuild_list: nodetype = ", jDir->nodetype);
putLabeledWord("\tbuild_list: hdr_crc = ", jDir->hdr_crc);
putLabeledWord("\tbuild_list: pino = ", jDir->pino);
putLabeledWord("\tbuild_list: version = ", jDir->version);
putLabeledWord("\tbuild_list: ino = ", jDir->ino);
putLabeledWord("\tbuild_list: mctime = ", jDir->mctime);
putLabeledWord("\tbuild_list: nsize = ", jDir->nsize);
putLabeledWord("\tbuild_list: type = ", jDir->type);
putLabeledWord("\tbuild_list: node_crc = ", jDir->node_crc);
putLabeledWord("\tbuild_list: name_crc = ", jDir->name_crc);
putLabeledWord("\tbuild_list: offset = ", b->offset); /* FIXME: ? [RS] */
b = b->next;
put_fl_mem(jDir);
}
}
#endif
static int
jffs2_fill_scan_buf(nand_info_t *nand, unsigned char *buf,
unsigned ofs, unsigned len)
{
int ret;
unsigned olen;
olen = len;
ret = nand_read(nand, ofs, &olen, buf);
if (ret) {
printf("nand_read(0x%x bytes from 0x%x) returned %d\n", len, ofs, ret);
return ret;
}
if (olen < len) {
printf("Read at 0x%x gave only 0x%x bytes\n", ofs, olen);
return -1;
}
return 0;
}
#define EMPTY_SCAN_SIZE 1024
static u32
jffs2_1pass_build_lists(struct part_info * part)
{
struct b_lists *pL;
struct jffs2_unknown_node *node;
unsigned nr_blocks, sectorsize, ofs, offset;
char *buf;
int i;
u32 counter = 0;
u32 counter4 = 0;
u32 counterF = 0;
u32 counterN = 0;
struct mtdids *id = part->dev->id;
nand = nand_info + id->num;
/* if we are building a list we need to refresh the cache. */
jffs_init_1pass_list(part);
pL = (struct b_lists *)part->jffs2_priv;
pL->partOffset = part->offset;
puts ("Scanning JFFS2 FS: ");
sectorsize = nand->erasesize;
nr_blocks = part->size / sectorsize;
buf = malloc(sectorsize);
if (!buf)
return 0;
for (i = 0; i < nr_blocks; i++) {
printf("\b\b%c ", spinner[counter++ % sizeof(spinner)]);
offset = part->offset + i * sectorsize;
if (nand_block_isbad(nand, offset))
continue;
if (jffs2_fill_scan_buf(nand, buf, offset, EMPTY_SCAN_SIZE))
return 0;
ofs = 0;
/* Scan only 4KiB of 0xFF before declaring it's empty */
while (ofs < EMPTY_SCAN_SIZE && *(uint32_t *)(&buf[ofs]) == 0xFFFFFFFF)
ofs += 4;
if (ofs == EMPTY_SCAN_SIZE)
continue;
if (jffs2_fill_scan_buf(nand, buf + EMPTY_SCAN_SIZE, offset + EMPTY_SCAN_SIZE, sectorsize - EMPTY_SCAN_SIZE))
return 0;
offset += ofs;
while (ofs < sectorsize - sizeof(struct jffs2_unknown_node)) {
node = (struct jffs2_unknown_node *)&buf[ofs];
if (node->magic != JFFS2_MAGIC_BITMASK || !hdr_crc(node)) {
offset += 4;
ofs += 4;
counter4++;
continue;
}
/* if its a fragment add it */
if (node->nodetype == JFFS2_NODETYPE_INODE &&
inode_crc((struct jffs2_raw_inode *) node)) {
if (insert_inode(&pL->frag, (struct jffs2_raw_inode *) node,
offset) == NULL) {
return 0;
}
} else if (node->nodetype == JFFS2_NODETYPE_DIRENT &&
dirent_crc((struct jffs2_raw_dirent *) node) &&
dirent_name_crc((struct jffs2_raw_dirent *) node)) {
if (! (counterN%100))
puts ("\b\b. ");
if (insert_dirent(&pL->dir, (struct jffs2_raw_dirent *) node,
offset) == NULL) {
return 0;
}
counterN++;
} else if (node->nodetype == JFFS2_NODETYPE_CLEANMARKER) {
if (node->totlen != sizeof(struct jffs2_unknown_node))
printf("OOPS Cleanmarker has bad size "
"%d != %d\n", node->totlen,
sizeof(struct jffs2_unknown_node));
} else if (node->nodetype == JFFS2_NODETYPE_PADDING) {
if (node->totlen < sizeof(struct jffs2_unknown_node))
printf("OOPS Padding has bad size "
"%d < %d\n", node->totlen,
sizeof(struct jffs2_unknown_node));
} else {
printf("Unknown node type: %x len %d "
"offset 0x%x\n", node->nodetype,
node->totlen, offset);
}
offset += ((node->totlen + 3) & ~3);
ofs += ((node->totlen + 3) & ~3);
counterF++;
}
}
putstr("\b\b done.\r\n"); /* close off the dots */
#ifdef DEBUG_DIRENTS
dump_dirents(pL);
#endif
#ifdef DEBUG_FRAGMENTS
dump_fragments(pL);
#endif
/* give visual feedback that we are done scanning the flash */
led_blink(0x0, 0x0, 0x1, 0x1); /* off, forever, on 100ms, off 100ms */
free(buf);
return 1;
}
static u32
jffs2_1pass_fill_info(struct b_lists * pL, struct b_jffs2_info * piL)
{
struct b_node *b;
struct jffs2_raw_inode ojNode;
struct jffs2_raw_inode *jNode;
int i;
for (i = 0; i < JFFS2_NUM_COMPR; i++) {
piL->compr_info[i].num_frags = 0;
piL->compr_info[i].compr_sum = 0;
piL->compr_info[i].decompr_sum = 0;
}
/* FIXME
b = pL->frag.listHead;
while (b) {
jNode = (struct jffs2_raw_inode *) get_fl_mem(b->offset,
sizeof(ojNode), &ojNode);
if (jNode->compr < JFFS2_NUM_COMPR) {
piL->compr_info[jNode->compr].num_frags++;
piL->compr_info[jNode->compr].compr_sum += jNode->csize;
piL->compr_info[jNode->compr].decompr_sum += jNode->dsize;
}
b = b->next;
}
*/
return 0;
}
static struct b_lists *
jffs2_get_list(struct part_info * part, const char *who)
{
if (jffs2_1pass_rescan_needed(part)) {
if (!jffs2_1pass_build_lists(part)) {
printf("%s: Failed to scan JFFSv2 file structure\n", who);
return NULL;
}
}
return (struct b_lists *)part->jffs2_priv;
}
/* Print directory / file contents */
u32
jffs2_1pass_ls(struct part_info * part, const char *fname)
{
struct b_lists *pl;
long ret = 0;
u32 inode;
if (! (pl = jffs2_get_list(part, "ls")))
return 0;
if (! (inode = jffs2_1pass_search_list_inodes(pl, fname, 1))) {
putstr("ls: Failed to scan jffs2 file structure\r\n");
return 0;
}
return ret;
}
/* Load a file from flash into memory. fname can be a full path */
u32
jffs2_1pass_load(char *dest, struct part_info * part, const char *fname)
{
struct b_lists *pl;
long ret = 0;
u32 inode;
if (! (pl = jffs2_get_list(part, "load")))
return 0;
if (! (inode = jffs2_1pass_search_inode(pl, fname, 1))) {
putstr("load: Failed to find inode\r\n");
return 0;
}
/* Resolve symlinks */
if (! (inode = jffs2_1pass_resolve_inode(pl, inode))) {
putstr("load: Failed to resolve inode structure\r\n");
return 0;
}
if ((ret = jffs2_1pass_read_inode(pl, inode, dest, NULL)) < 0) {
putstr("load: Failed to read inode\r\n");
return 0;
}
DEBUGF ("load: loaded '%s' to 0x%lx (%ld bytes)\n", fname,
(unsigned long) dest, ret);
return ret;
}
/* Return information about the fs on this partition */
u32
jffs2_1pass_info(struct part_info * part)
{
struct b_jffs2_info info;
struct b_lists *pl;
int i;
if (! (pl = jffs2_get_list(part, "info")))
return 0;
jffs2_1pass_fill_info(pl, &info);
for (i = 0; i < JFFS2_NUM_COMPR; i++) {
printf ("Compression: %s\n"
"\tfrag count: %d\n"
"\tcompressed sum: %d\n"
"\tuncompressed sum: %d\n",
compr_names[i],
info.compr_info[i].num_frags,
info.compr_info[i].compr_sum,
info.compr_info[i].decompr_sum);
}
return 1;
}
#endif /* CFG_CMD_JFFS2 */

View File

@ -1,126 +0,0 @@
#ifndef jffs2_private_h
#define jffs2_private_h
#include <jffs2/jffs2.h>
struct b_node {
struct b_node *next;
};
struct b_inode {
struct b_inode *next;
u32 offset; /* physical offset to beginning of real inode */
u32 version;
u32 ino;
u32 isize;
u32 csize;
};
struct b_dirent {
struct b_dirent *next;
u32 offset; /* physical offset to beginning of real dirent */
u32 version;
u32 pino;
u32 ino;
unsigned int nhash;
unsigned char nsize;
unsigned char type;
};
struct b_list {
struct b_node *listTail;
struct b_node *listHead;
unsigned int listCount;
struct mem_block *listMemBase;
};
struct b_lists {
char *partOffset;
struct b_list dir;
struct b_list frag;
};
struct b_compr_info {
u32 num_frags;
u32 compr_sum;
u32 decompr_sum;
};
struct b_jffs2_info {
struct b_compr_info compr_info[JFFS2_NUM_COMPR];
};
static inline int
hdr_crc(struct jffs2_unknown_node *node)
{
u32 crc = crc32_no_comp(0, (unsigned char *)node, sizeof(struct jffs2_unknown_node) - 4);
if (node->hdr_crc != crc) {
return 0;
} else {
return 1;
}
}
static inline int
dirent_crc(struct jffs2_raw_dirent *node)
{
if (node->node_crc != crc32_no_comp(0, (unsigned char *)node, sizeof(struct jffs2_raw_dirent) - 8)) {
return 0;
} else {
return 1;
}
}
static inline int
dirent_name_crc(struct jffs2_raw_dirent *node)
{
if (node->name_crc != crc32_no_comp(0, (unsigned char *)&(node->name), node->nsize)) {
return 0;
} else {
return 1;
}
}
static inline int
inode_crc(struct jffs2_raw_inode *node)
{
if (node->node_crc != crc32_no_comp(0, (unsigned char *)node, sizeof(struct jffs2_raw_inode) - 8)) {
return 0;
} else {
return 1;
}
}
/* Borrowed from include/linux/dcache.h */
/* Name hashing routines. Initial hash value */
/* Hash courtesy of the R5 hash in reiserfs modulo sign bits */
#define init_name_hash() 0
/* partial hash update function. Assume roughly 4 bits per character */
static inline unsigned long
partial_name_hash(unsigned long c, unsigned long prevhash)
{
return (prevhash + (c << 4) + (c >> 4)) * 11;
}
/*
* Finally: cut down the number of bits to a int value (and try to avoid
* losing bits)
*/
static inline unsigned long end_name_hash(unsigned long hash)
{
return (unsigned int) hash;
}
/* Compute the hash for a name string. */
static inline unsigned int
full_name_hash(const unsigned char *name, unsigned int len)
{
unsigned long hash = init_name_hash();
while (len--)
hash = partial_name_hash(*name++, hash);
return end_name_hash(hash);
}
#endif /* jffs2_private.h */

View File

@ -1,93 +0,0 @@
#ifndef jffs2_private_h
#define jffs2_private_h
#include <jffs2/jffs2.h>
struct b_node {
u32 offset;
struct b_node *next;
};
struct b_list {
struct b_node *listTail;
struct b_node *listHead;
#ifdef CFG_JFFS2_SORT_FRAGMENTS
struct b_node *listLast;
int (*listCompare)(struct b_node *new, struct b_node *node);
u32 listLoops;
#endif
u32 listCount;
struct mem_block *listMemBase;
};
struct b_lists {
struct b_list dir;
struct b_list frag;
};
struct b_compr_info {
u32 num_frags;
u32 compr_sum;
u32 decompr_sum;
};
struct b_jffs2_info {
struct b_compr_info compr_info[JFFS2_NUM_COMPR];
};
static inline int
hdr_crc(struct jffs2_unknown_node *node)
{
u32 crc = crc32_no_comp(0, (unsigned char *)node, sizeof(struct jffs2_unknown_node) - 4);
if (node->hdr_crc != crc) {
return 0;
} else {
return 1;
}
}
static inline int
dirent_crc(struct jffs2_raw_dirent *node)
{
if (node->node_crc != crc32_no_comp(0, (unsigned char *)node, sizeof(struct jffs2_raw_dirent) - 8)) {
return 0;
} else {
return 1;
}
}
static inline int
dirent_name_crc(struct jffs2_raw_dirent *node)
{
if (node->name_crc != crc32_no_comp(0, (unsigned char *)&(node->name), node->nsize)) {
return 0;
} else {
return 1;
}
}
static inline int
inode_crc(struct jffs2_raw_inode *node)
{
if (node->node_crc != crc32_no_comp(0, (unsigned char *)node, sizeof(struct jffs2_raw_inode) - 8)) {
return 0;
} else {
return 1;
}
}
static inline int
data_crc(struct jffs2_raw_inode *node)
{
if (node->data_crc != crc32_no_comp(0, (unsigned char *)
((int) &node->node_crc + sizeof (node->node_crc)),
node->csize)) {
return 0;
} else {
return 1;
}
}
#endif /* jffs2_private.h */

View File

@ -1,389 +0,0 @@
/*-------------------------------------------------------------------------
* Filename: mini_inflate.c
* Version: $Id: mini_inflate.c,v 1.3 2002/01/24 22:58:42 rfeany Exp $
* Copyright: Copyright (C) 2001, Russ Dill
* Author: Russ Dill <Russ.Dill@asu.edu>
* Description: Mini inflate implementation (RFC 1951)
*-----------------------------------------------------------------------*/
/*
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
*/
#include <config.h>
#if (CONFIG_COMMANDS & CFG_CMD_JFFS2)
#include <jffs2/mini_inflate.h>
/* The order that the code lengths in section 3.2.7 are in */
static unsigned char huffman_order[] = {16, 17, 18, 0, 8, 7, 9, 6, 10, 5,
11, 4, 12, 3, 13, 2, 14, 1, 15};
inline void cramfs_memset(int *s, const int c, size n)
{
n--;
for (;n > 0; n--) s[n] = c;
s[0] = c;
}
/* associate a stream with a block of data and reset the stream */
static void init_stream(struct bitstream *stream, unsigned char *data,
void *(*inflate_memcpy)(void *, const void *, size))
{
stream->error = NO_ERROR;
stream->memcpy = inflate_memcpy;
stream->decoded = 0;
stream->data = data;
stream->bit = 0; /* The first bit of the stream is the lsb of the
* first byte */
/* really sorry about all this initialization, think of a better way,
* let me know and it will get cleaned up */
stream->codes.bits = 8;
stream->codes.num_symbols = 19;
stream->codes.lengths = stream->code_lengths;
stream->codes.symbols = stream->code_symbols;
stream->codes.count = stream->code_count;
stream->codes.first = stream->code_first;
stream->codes.pos = stream->code_pos;
stream->lengths.bits = 16;
stream->lengths.num_symbols = 288;
stream->lengths.lengths = stream->length_lengths;
stream->lengths.symbols = stream->length_symbols;
stream->lengths.count = stream->length_count;
stream->lengths.first = stream->length_first;
stream->lengths.pos = stream->length_pos;
stream->distance.bits = 16;
stream->distance.num_symbols = 32;
stream->distance.lengths = stream->distance_lengths;
stream->distance.symbols = stream->distance_symbols;
stream->distance.count = stream->distance_count;
stream->distance.first = stream->distance_first;
stream->distance.pos = stream->distance_pos;
}
/* pull 'bits' bits out of the stream. The last bit pulled it returned as the
* msb. (section 3.1.1)
*/
inline unsigned long pull_bits(struct bitstream *stream,
const unsigned int bits)
{
unsigned long ret;
int i;
ret = 0;
for (i = 0; i < bits; i++) {
ret += ((*(stream->data) >> stream->bit) & 1) << i;
/* if, before incrementing, we are on bit 7,
* go to the lsb of the next byte */
if (stream->bit++ == 7) {
stream->bit = 0;
stream->data++;
}
}
return ret;
}
inline int pull_bit(struct bitstream *stream)
{
int ret = ((*(stream->data) >> stream->bit) & 1);
if (stream->bit++ == 7) {
stream->bit = 0;
stream->data++;
}
return ret;
}
/* discard bits up to the next whole byte */
static void discard_bits(struct bitstream *stream)
{
if (stream->bit != 0) {
stream->bit = 0;
stream->data++;
}
}
/* No decompression, the data is all literals (section 3.2.4) */
static void decompress_none(struct bitstream *stream, unsigned char *dest)
{
unsigned int length;
discard_bits(stream);
length = *(stream->data++);
length += *(stream->data++) << 8;
pull_bits(stream, 16); /* throw away the inverse of the size */
stream->decoded += length;
stream->memcpy(dest, stream->data, length);
stream->data += length;
}
/* Read in a symbol from the stream (section 3.2.2) */
static int read_symbol(struct bitstream *stream, struct huffman_set *set)
{
int bits = 0;
int code = 0;
while (!(set->count[bits] && code < set->first[bits] +
set->count[bits])) {
code = (code << 1) + pull_bit(stream);
if (++bits > set->bits) {
/* error decoding (corrupted data?) */
stream->error = CODE_NOT_FOUND;
return -1;
}
}
return set->symbols[set->pos[bits] + code - set->first[bits]];
}
/* decompress a stream of data encoded with the passed length and distance
* huffman codes */
static void decompress_huffman(struct bitstream *stream, unsigned char *dest)
{
struct huffman_set *lengths = &(stream->lengths);
struct huffman_set *distance = &(stream->distance);
int symbol, length, dist, i;
do {
if ((symbol = read_symbol(stream, lengths)) < 0) return;
if (symbol < 256) {
*(dest++) = symbol; /* symbol is a literal */
stream->decoded++;
} else if (symbol > 256) {
/* Determine the length of the repitition
* (section 3.2.5) */
if (symbol < 265) length = symbol - 254;
else if (symbol == 285) length = 258;
else {
length = pull_bits(stream, (symbol - 261) >> 2);
length += (4 << ((symbol - 261) >> 2)) + 3;
length += ((symbol - 1) % 4) <<
((symbol - 261) >> 2);
}
/* Determine how far back to go */
if ((symbol = read_symbol(stream, distance)) < 0)
return;
if (symbol < 4) dist = symbol + 1;
else {
dist = pull_bits(stream, (symbol - 2) >> 1);
dist += (2 << ((symbol - 2) >> 1)) + 1;
dist += (symbol % 2) << ((symbol - 2) >> 1);
}
stream->decoded += length;
for (i = 0; i < length; i++) {
*dest = dest[-dist];
dest++;
}
}
} while (symbol != 256); /* 256 is the end of the data block */
}
/* Fill the lookup tables (section 3.2.2) */
static void fill_code_tables(struct huffman_set *set)
{
int code = 0, i, length;
/* fill in the first code of each bit length, and the pos pointer */
set->pos[0] = 0;
for (i = 1; i < set->bits; i++) {
code = (code + set->count[i - 1]) << 1;
set->first[i] = code;
set->pos[i] = set->pos[i - 1] + set->count[i - 1];
}
/* Fill in the table of symbols in order of their huffman code */
for (i = 0; i < set->num_symbols; i++) {
if ((length = set->lengths[i]))
set->symbols[set->pos[length]++] = i;
}
/* reset the pos pointer */
for (i = 1; i < set->bits; i++) set->pos[i] -= set->count[i];
}
static void init_code_tables(struct huffman_set *set)
{
cramfs_memset(set->lengths, 0, set->num_symbols);
cramfs_memset(set->count, 0, set->bits);
cramfs_memset(set->first, 0, set->bits);
}
/* read in the huffman codes for dynamic decoding (section 3.2.7) */
static void decompress_dynamic(struct bitstream *stream, unsigned char *dest)
{
/* I tried my best to minimize the memory footprint here, while still
* keeping up performance. I really dislike the _lengths[] tables, but
* I see no way of eliminating them without a sizable performance
* impact. The first struct table keeps track of stats on each bit
* length. The _length table keeps a record of the bit length of each
* symbol. The _symbols table is for looking up symbols by the huffman
* code (the pos element points to the first place in the symbol table
* where that bit length occurs). I also hate the initization of these
* structs, if someone knows how to compact these, lemme know. */
struct huffman_set *codes = &(stream->codes);
struct huffman_set *lengths = &(stream->lengths);
struct huffman_set *distance = &(stream->distance);
int hlit = pull_bits(stream, 5) + 257;
int hdist = pull_bits(stream, 5) + 1;
int hclen = pull_bits(stream, 4) + 4;
int length, curr_code, symbol, i, last_code;
last_code = 0;
init_code_tables(codes);
init_code_tables(lengths);
init_code_tables(distance);
/* fill in the count of each bit length' as well as the lengths
* table */
for (i = 0; i < hclen; i++) {
length = pull_bits(stream, 3);
codes->lengths[huffman_order[i]] = length;
if (length) codes->count[length]++;
}
fill_code_tables(codes);
/* Do the same for the length codes, being carefull of wrap through
* to the distance table */
curr_code = 0;
while (curr_code < hlit) {
if ((symbol = read_symbol(stream, codes)) < 0) return;
if (symbol == 0) {
curr_code++;
last_code = 0;
} else if (symbol < 16) { /* Literal length */
lengths->lengths[curr_code] = last_code = symbol;
lengths->count[symbol]++;
curr_code++;
} else if (symbol == 16) { /* repeat the last symbol 3 - 6
* times */
length = 3 + pull_bits(stream, 2);
for (;length; length--, curr_code++)
if (curr_code < hlit) {
lengths->lengths[curr_code] =
last_code;
lengths->count[last_code]++;
} else { /* wrap to the distance table */
distance->lengths[curr_code - hlit] =
last_code;
distance->count[last_code]++;
}
} else if (symbol == 17) { /* repeat a bit length 0 */
curr_code += 3 + pull_bits(stream, 3);
last_code = 0;
} else { /* same, but more times */
curr_code += 11 + pull_bits(stream, 7);
last_code = 0;
}
}
fill_code_tables(lengths);
/* Fill the distance table, don't need to worry about wrapthrough
* here */
curr_code -= hlit;
while (curr_code < hdist) {
if ((symbol = read_symbol(stream, codes)) < 0) return;
if (symbol == 0) {
curr_code++;
last_code = 0;
} else if (symbol < 16) {
distance->lengths[curr_code] = last_code = symbol;
distance->count[symbol]++;
curr_code++;
} else if (symbol == 16) {
length = 3 + pull_bits(stream, 2);
for (;length; length--, curr_code++) {
distance->lengths[curr_code] =
last_code;
distance->count[last_code]++;
}
} else if (symbol == 17) {
curr_code += 3 + pull_bits(stream, 3);
last_code = 0;
} else {
curr_code += 11 + pull_bits(stream, 7);
last_code = 0;
}
}
fill_code_tables(distance);
decompress_huffman(stream, dest);
}
/* fill in the length and distance huffman codes for fixed encoding
* (section 3.2.6) */
static void decompress_fixed(struct bitstream *stream, unsigned char *dest)
{
/* let gcc fill in the initial values */
struct huffman_set *lengths = &(stream->lengths);
struct huffman_set *distance = &(stream->distance);
cramfs_memset(lengths->count, 0, 16);
cramfs_memset(lengths->first, 0, 16);
cramfs_memset(lengths->lengths, 8, 144);
cramfs_memset(lengths->lengths + 144, 9, 112);
cramfs_memset(lengths->lengths + 256, 7, 24);
cramfs_memset(lengths->lengths + 280, 8, 8);
lengths->count[7] = 24;
lengths->count[8] = 152;
lengths->count[9] = 112;
cramfs_memset(distance->count, 0, 16);
cramfs_memset(distance->first, 0, 16);
cramfs_memset(distance->lengths, 5, 32);
distance->count[5] = 32;
fill_code_tables(lengths);
fill_code_tables(distance);
decompress_huffman(stream, dest);
}
/* returns the number of bytes decoded, < 0 if there was an error. Note that
* this function assumes that the block starts on a byte boundry
* (non-compliant, but I don't see where this would happen). section 3.2.3 */
long decompress_block(unsigned char *dest, unsigned char *source,
void *(*inflate_memcpy)(void *, const void *, size))
{
int bfinal, btype;
struct bitstream stream;
init_stream(&stream, source, inflate_memcpy);
do {
bfinal = pull_bit(&stream);
btype = pull_bits(&stream, 2);
if (btype == NO_COMP) decompress_none(&stream, dest + stream.decoded);
else if (btype == DYNAMIC_COMP)
decompress_dynamic(&stream, dest + stream.decoded);
else if (btype == FIXED_COMP) decompress_fixed(&stream, dest + stream.decoded);
else stream.error = COMP_UNKNOWN;
} while (!bfinal && !stream.error);
return stream.error ? -stream.error : stream.decoded;
}
#endif /* CFG_CMD_JFFS2 */

View File

@ -1,52 +0,0 @@
#
# (C) Copyright 2006
# Wolfgang Denk, DENX Software Engineering, wd@denx.de.
#
# (C) Copyright 2003
# Pavel Bartusek, Sysgo Real-Time Solutions AG, pba@sysgo.de
#
#
# See file CREDITS for list of people who contributed to this
# project.
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License as
# published by the Free Software Foundation; either version 2 of
# the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston,
# MA 02111-1307 USA
#
include $(TOPDIR)/config.mk
LIB = $(obj)libreiserfs.a
AOBJS =
COBJS = reiserfs.o dev.o mode_string.o
SRCS := $(AOBJS:.o=.S) $(COBJS:.o=.c)
OBJS := $(addprefix $(obj),$(AOBJS) $(COBJS))
#CPPFLAGS +=
all: $(LIB) $(AOBJS)
$(LIB): $(obj).depend $(OBJS)
$(AR) $(ARFLAGS) $@ $(OBJS)
#########################################################################
# defines $(obj).depend target
include $(SRCTREE)/rules.mk
sinclude $(obj).depend
#########################################################################

View File

@ -1,123 +0,0 @@
/*
* (C) Copyright 2003 - 2004
* Sysgo AG, <www.elinos.com>, Pavel Bartusek <pba@sysgo.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include <common.h>
#if (CONFIG_COMMANDS & CFG_CMD_REISER)
#include <config.h>
#include <reiserfs.h>
#include "reiserfs_private.h"
static block_dev_desc_t *reiserfs_block_dev_desc;
static disk_partition_t part_info;
int reiserfs_set_blk_dev(block_dev_desc_t *rbdd, int part)
{
reiserfs_block_dev_desc = rbdd;
if (part == 0) {
/* disk doesn't use partition table */
part_info.start = 0;
part_info.size = rbdd->lba;
part_info.blksz = rbdd->blksz;
} else {
if (get_partition_info (reiserfs_block_dev_desc, part, &part_info)) {
return 0;
}
}
return (part_info.size);
}
int reiserfs_devread (int sector, int byte_offset, int byte_len, char *buf)
{
char sec_buf[SECTOR_SIZE];
unsigned block_len;
/*
unsigned len = byte_len;
u8 *start = buf;
*/
/*
* Check partition boundaries
*/
if (sector < 0
|| ((sector + ((byte_offset + byte_len - 1) >> SECTOR_BITS))
>= part_info.size)) {
/* errnum = ERR_OUTSIDE_PART; */
printf (" ** reiserfs_devread() read outside partition\n");
return 0;
}
/*
* Get the read to the beginning of a partition.
*/
sector += byte_offset >> SECTOR_BITS;
byte_offset &= SECTOR_SIZE - 1;
#if defined(DEBUG)
printf (" <%d, %d, %d> ", sector, byte_offset, byte_len);
#endif
if (reiserfs_block_dev_desc == NULL)
return 0;
if (byte_offset != 0) {
/* read first part which isn't aligned with start of sector */
if (reiserfs_block_dev_desc->block_read(reiserfs_block_dev_desc->dev,
part_info.start+sector, 1, (unsigned long *)sec_buf) != 1) {
printf (" ** reiserfs_devread() read error\n");
return 0;
}
memcpy(buf, sec_buf+byte_offset, min(SECTOR_SIZE-byte_offset, byte_len));
buf+=min(SECTOR_SIZE-byte_offset, byte_len);
byte_len-=min(SECTOR_SIZE-byte_offset, byte_len);
sector++;
}
/* read sector aligned part */
block_len = byte_len & ~(SECTOR_SIZE-1);
if (reiserfs_block_dev_desc->block_read(reiserfs_block_dev_desc->dev,
part_info.start+sector, block_len/SECTOR_SIZE, (unsigned long *)buf) !=
block_len/SECTOR_SIZE) {
printf (" ** reiserfs_devread() read error - block\n");
return 0;
}
buf+=block_len;
byte_len-=block_len;
sector+= block_len/SECTOR_SIZE;
if ( byte_len != 0 ) {
/* read rest of data which are not in whole sector */
if (reiserfs_block_dev_desc->block_read(reiserfs_block_dev_desc->dev,
part_info.start+sector, 1, (unsigned long *)sec_buf) != 1) {
printf (" ** reiserfs_devread() read error - last part\n");
return 0;
}
memcpy(buf, sec_buf, byte_len);
}
return 1;
}
#endif /* CFG_CMD_REISERFS */

View File

@ -1,142 +0,0 @@
/* vi: set sw=4 ts=4: */
/*
* mode_string implementation for busybox
*
* Copyright (C) 2003 Manuel Novoa III <mjn3@codepoet.org>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
*/
/* Aug 13, 2003
* Fix a bug reported by junkio@cox.net involving the mode_chars index.
*/
#include <common.h>
#if (CONFIG_COMMANDS & CFG_CMD_REISER)
#include <linux/stat.h>
#if ( S_ISUID != 04000 ) || ( S_ISGID != 02000 ) || ( S_ISVTX != 01000 ) \
|| ( S_IRUSR != 00400 ) || ( S_IWUSR != 00200 ) || ( S_IXUSR != 00100 ) \
|| ( S_IRGRP != 00040 ) || ( S_IWGRP != 00020 ) || ( S_IXGRP != 00010 ) \
|| ( S_IROTH != 00004 ) || ( S_IWOTH != 00002 ) || ( S_IXOTH != 00001 )
#error permission bitflag value assumption(s) violated!
#endif
#if ( S_IFSOCK!= 0140000 ) || ( S_IFLNK != 0120000 ) \
|| ( S_IFREG != 0100000 ) || ( S_IFBLK != 0060000 ) \
|| ( S_IFDIR != 0040000 ) || ( S_IFCHR != 0020000 ) \
|| ( S_IFIFO != 0010000 )
#warning mode type bitflag value assumption(s) violated! falling back to larger version
#if (S_IRWXU | S_IRWXG | S_IRWXO | S_ISUID | S_ISGID | S_ISVTX) == 07777
#undef mode_t
#define mode_t unsigned short
#endif
static const mode_t mode_flags[] = {
S_IRUSR, S_IWUSR, S_IXUSR, S_ISUID,
S_IRGRP, S_IWGRP, S_IXGRP, S_ISGID,
S_IROTH, S_IWOTH, S_IXOTH, S_ISVTX
};
/* The static const char arrays below are duplicated for the two cases
* because moving them ahead of the mode_flags declaration cause a text
* size increase with the gcc version I'm using. */
/* The previous version used "0pcCd?bB-?l?s???". However, the '0', 'C',
* and 'B' types don't appear to be available on linux. So I removed them. */
static const char type_chars[16] = "?pc?d?b?-?l?s???";
/* 0123456789abcdef */
static const char mode_chars[7] = "rwxSTst";
const char *bb_mode_string(int mode)
{
static char buf[12];
char *p = buf;
int i, j, k;
*p = type_chars[ (mode >> 12) & 0xf ];
i = 0;
do {
j = k = 0;
do {
*++p = '-';
if (mode & mode_flags[i+j]) {
*p = mode_chars[j];
k = j;
}
} while (++j < 3);
if (mode & mode_flags[i+j]) {
*p = mode_chars[3 + (k & 2) + ((i&8) >> 3)];
}
i += 4;
} while (i < 12);
/* Note: We don't bother with nul termination because bss initialization
* should have taken care of that for us. If the user scribbled in buf
* memory, they deserve whatever happens. But we'll at least assert. */
if (buf[10] != 0) return NULL;
return buf;
}
#else
/* The previous version used "0pcCd?bB-?l?s???". However, the '0', 'C',
* and 'B' types don't appear to be available on linux. So I removed them. */
static const char type_chars[16] = "?pc?d?b?-?l?s???";
/* 0123456789abcdef */
static const char mode_chars[7] = "rwxSTst";
const char *bb_mode_string(int mode)
{
static char buf[12];
char *p = buf;
int i, j, k, m;
*p = type_chars[ (mode >> 12) & 0xf ];
i = 0;
m = 0400;
do {
j = k = 0;
do {
*++p = '-';
if (mode & m) {
*p = mode_chars[j];
k = j;
}
m >>= 1;
} while (++j < 3);
++i;
if (mode & (010000 >> i)) {
*p = mode_chars[3 + (k & 2) + (i == 3)];
}
} while (i < 3);
/* Note: We don't bother with nul termination because bss initialization
* should have taken care of that for us. If the user scribbled in buf
* memory, they deserve whatever happens. But we'll at least assert. */
if (buf[10] != 0) return NULL;
return buf;
}
#endif
#endif /* CFG_CMD_REISER */

View File

@ -1,978 +0,0 @@
/*
* Copyright 2000-2002 by Hans Reiser, licensing governed by reiserfs/README
*
* GRUB -- GRand Unified Bootloader
* Copyright (C) 2000, 2001 Free Software Foundation, Inc.
*
* (C) Copyright 2003 - 2004
* Sysgo AG, <www.elinos.com>, Pavel Bartusek <pba@sysgo.com>
*
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
/* An implementation for the ReiserFS filesystem ported from GRUB.
* Some parts of this code (mainly the structures and defines) are
* from the original reiser fs code, as found in the linux kernel.
*/
#include <common.h>
#if (CONFIG_COMMANDS & CFG_CMD_REISER)
#include <malloc.h>
#include <linux/ctype.h>
#include <linux/time.h>
#include <asm/byteorder.h>
#include <reiserfs.h>
#include "reiserfs_private.h"
#undef REISERDEBUG
/* Some parts of this code (mainly the structures and defines) are
* from the original reiser fs code, as found in the linux kernel.
*/
static char fsys_buf[FSYS_BUFLEN];
static reiserfs_error_t errnum = ERR_NONE;
static int print_possibilities;
static unsigned int filepos, filemax;
static int
substring (const char *s1, const char *s2)
{
while (*s1 == *s2)
{
/* The strings match exactly. */
if (! *(s1++))
return 0;
s2 ++;
}
/* S1 is a substring of S2. */
if (*s1 == 0)
return -1;
/* S1 isn't a substring. */
return 1;
}
static void sd_print_item (struct item_head * ih, char * item)
{
char filetime[30];
time_t ttime;
if (stat_data_v1 (ih)) {
struct stat_data_v1 * sd = (struct stat_data_v1 *)item;
ttime = sd_v1_mtime(sd);
ctime_r(&ttime, filetime);
printf ("%-10s %4hd %6d %6d %9d %24.24s",
bb_mode_string(sd_v1_mode(sd)), sd_v1_nlink(sd),sd_v1_uid(sd), sd_v1_gid(sd),
sd_v1_size(sd), filetime);
} else {
struct stat_data * sd = (struct stat_data *)item;
ttime = sd_v2_mtime(sd);
ctime_r(&ttime, filetime);
printf ("%-10s %4d %6d %6d %9d %24.24s",
bb_mode_string(sd_v2_mode(sd)), sd_v2_nlink(sd),sd_v2_uid(sd),sd_v2_gid(sd),
(__u32) sd_v2_size(sd), filetime);
}
}
static int
journal_read (int block, int len, char *buffer)
{
return reiserfs_devread ((INFO->journal_block + block) << INFO->blocksize_shift,
0, len, buffer);
}
/* Read a block from ReiserFS file system, taking the journal into
* account. If the block nr is in the journal, the block from the
* journal taken.
*/
static int
block_read (unsigned int blockNr, int start, int len, char *buffer)
{
int transactions = INFO->journal_transactions;
int desc_block = INFO->journal_first_desc;
int journal_mask = INFO->journal_block_count - 1;
int translatedNr = blockNr;
__u32 *journal_table = JOURNAL_START;
while (transactions-- > 0)
{
int i = 0;
int j_len;
if (__le32_to_cpu(*journal_table) != 0xffffffff)
{
/* Search for the blockNr in cached journal */
j_len = __le32_to_cpu(*journal_table++);
while (i++ < j_len)
{
if (__le32_to_cpu(*journal_table++) == blockNr)
{
journal_table += j_len - i;
goto found;
}
}
}
else
{
/* This is the end of cached journal marker. The remaining
* transactions are still on disk.
*/
struct reiserfs_journal_desc desc;
struct reiserfs_journal_commit commit;
if (! journal_read (desc_block, sizeof (desc), (char *) &desc))
return 0;
j_len = __le32_to_cpu(desc.j_len);
while (i < j_len && i < JOURNAL_TRANS_HALF)
if (__le32_to_cpu(desc.j_realblock[i++]) == blockNr)
goto found;
if (j_len >= JOURNAL_TRANS_HALF)
{
int commit_block = (desc_block + 1 + j_len) & journal_mask;
if (! journal_read (commit_block,
sizeof (commit), (char *) &commit))
return 0;
while (i < j_len)
if (__le32_to_cpu(commit.j_realblock[i++ - JOURNAL_TRANS_HALF]) == blockNr)
goto found;
}
}
goto not_found;
found:
translatedNr = INFO->journal_block + ((desc_block + i) & journal_mask);
#ifdef REISERDEBUG
printf ("block_read: block %d is mapped to journal block %d.\n",
blockNr, translatedNr - INFO->journal_block);
#endif
/* We must continue the search, as this block may be overwritten
* in later transactions.
*/
not_found:
desc_block = (desc_block + 2 + j_len) & journal_mask;
}
return reiserfs_devread (translatedNr << INFO->blocksize_shift, start, len, buffer);
}
/* Init the journal data structure. We try to cache as much as
* possible in the JOURNAL_START-JOURNAL_END space, but if it is full
* we can still read the rest from the disk on demand.
*
* The first number of valid transactions and the descriptor block of the
* first valid transaction are held in INFO. The transactions are all
* adjacent, but we must take care of the journal wrap around.
*/
static int
journal_init (void)
{
unsigned int block_count = INFO->journal_block_count;
unsigned int desc_block;
unsigned int commit_block;
unsigned int next_trans_id;
struct reiserfs_journal_header header;
struct reiserfs_journal_desc desc;
struct reiserfs_journal_commit commit;
__u32 *journal_table = JOURNAL_START;
journal_read (block_count, sizeof (header), (char *) &header);
desc_block = __le32_to_cpu(header.j_first_unflushed_offset);
if (desc_block >= block_count)
return 0;
INFO->journal_first_desc = desc_block;
next_trans_id = __le32_to_cpu(header.j_last_flush_trans_id) + 1;
#ifdef REISERDEBUG
printf ("journal_init: last flushed %d\n",
__le32_to_cpu(header.j_last_flush_trans_id));
#endif
while (1)
{
journal_read (desc_block, sizeof (desc), (char *) &desc);
if (substring (JOURNAL_DESC_MAGIC, desc.j_magic) > 0
|| __le32_to_cpu(desc.j_trans_id) != next_trans_id
|| __le32_to_cpu(desc.j_mount_id) != __le32_to_cpu(header.j_mount_id))
/* no more valid transactions */
break;
commit_block = (desc_block + __le32_to_cpu(desc.j_len) + 1) & (block_count - 1);
journal_read (commit_block, sizeof (commit), (char *) &commit);
if (__le32_to_cpu(desc.j_trans_id) != commit.j_trans_id
|| __le32_to_cpu(desc.j_len) != __le32_to_cpu(commit.j_len))
/* no more valid transactions */
break;
#ifdef REISERDEBUG
printf ("Found valid transaction %d/%d at %d.\n",
__le32_to_cpu(desc.j_trans_id), __le32_to_cpu(desc.j_mount_id), desc_block);
#endif
next_trans_id++;
if (journal_table < JOURNAL_END)
{
if ((journal_table + 1 + __le32_to_cpu(desc.j_len)) >= JOURNAL_END)
{
/* The table is almost full; mark the end of the cached
* journal.*/
*journal_table = __cpu_to_le32(0xffffffff);
journal_table = JOURNAL_END;
}
else
{
unsigned int i;
/* Cache the length and the realblock numbers in the table.
* The block number of descriptor can easily be computed.
* and need not to be stored here.
*/
/* both are in the little endian format */
*journal_table++ = desc.j_len;
for (i = 0; i < __le32_to_cpu(desc.j_len) && i < JOURNAL_TRANS_HALF; i++)
{
/* both are in the little endian format */
*journal_table++ = desc.j_realblock[i];
#ifdef REISERDEBUG
printf ("block %d is in journal %d.\n",
__le32_to_cpu(desc.j_realblock[i]), desc_block);
#endif
}
for ( ; i < __le32_to_cpu(desc.j_len); i++)
{
/* both are in the little endian format */
*journal_table++ = commit.j_realblock[i-JOURNAL_TRANS_HALF];
#ifdef REISERDEBUG
printf ("block %d is in journal %d.\n",
__le32_to_cpu(commit.j_realblock[i-JOURNAL_TRANS_HALF]),
desc_block);
#endif
}
}
}
desc_block = (commit_block + 1) & (block_count - 1);
}
#ifdef REISERDEBUG
printf ("Transaction %d/%d at %d isn't valid.\n",
__le32_to_cpu(desc.j_trans_id), __le32_to_cpu(desc.j_mount_id), desc_block);
#endif
INFO->journal_transactions
= next_trans_id - __le32_to_cpu(header.j_last_flush_trans_id) - 1;
return errnum == 0;
}
/* check filesystem types and read superblock into memory buffer */
int
reiserfs_mount (unsigned part_length)
{
struct reiserfs_super_block super;
int superblock = REISERFS_DISK_OFFSET_IN_BYTES >> SECTOR_BITS;
if (part_length < superblock + (sizeof (super) >> SECTOR_BITS)
|| ! reiserfs_devread (superblock, 0, sizeof (struct reiserfs_super_block),
(char *) &super)
|| (substring (REISER3FS_SUPER_MAGIC_STRING, super.s_magic) > 0
&& substring (REISER2FS_SUPER_MAGIC_STRING, super.s_magic) > 0
&& substring (REISERFS_SUPER_MAGIC_STRING, super.s_magic) > 0)
|| (/* check that this is not a copy inside the journal log */
sb_journal_block(&super) * sb_blocksize(&super)
<= REISERFS_DISK_OFFSET_IN_BYTES))
{
/* Try old super block position */
superblock = REISERFS_OLD_DISK_OFFSET_IN_BYTES >> SECTOR_BITS;
if (part_length < superblock + (sizeof (super) >> SECTOR_BITS)
|| ! reiserfs_devread (superblock, 0, sizeof (struct reiserfs_super_block),
(char *) &super))
return 0;
if (substring (REISER2FS_SUPER_MAGIC_STRING, super.s_magic) > 0
&& substring (REISERFS_SUPER_MAGIC_STRING, super.s_magic) > 0)
{
/* pre journaling super block ? */
if (substring (REISERFS_SUPER_MAGIC_STRING,
(char*) ((int) &super + 20)) > 0)
return 0;
set_sb_blocksize(&super, REISERFS_OLD_BLOCKSIZE);
set_sb_journal_block(&super, 0);
set_sb_version(&super, 0);
}
}
/* check the version number. */
if (sb_version(&super) > REISERFS_MAX_SUPPORTED_VERSION)
return 0;
INFO->version = sb_version(&super);
INFO->blocksize = sb_blocksize(&super);
INFO->fullblocksize_shift = log2 (sb_blocksize(&super));
INFO->blocksize_shift = INFO->fullblocksize_shift - SECTOR_BITS;
INFO->cached_slots =
(FSYSREISER_CACHE_SIZE >> INFO->fullblocksize_shift) - 1;
#ifdef REISERDEBUG
printf ("reiserfs_mount: version=%d, blocksize=%d\n",
INFO->version, INFO->blocksize);
#endif /* REISERDEBUG */
/* Clear node cache. */
memset (INFO->blocks, 0, sizeof (INFO->blocks));
if (sb_blocksize(&super) < FSYSREISER_MIN_BLOCKSIZE
|| sb_blocksize(&super) > FSYSREISER_MAX_BLOCKSIZE
|| (SECTOR_SIZE << INFO->blocksize_shift) != sb_blocksize(&super))
return 0;
/* Initialize journal code. If something fails we end with zero
* journal_transactions, so we don't access the journal at all.
*/
INFO->journal_transactions = 0;
if (sb_journal_block(&super) != 0 && super.s_journal_dev == 0)
{
INFO->journal_block = sb_journal_block(&super);
INFO->journal_block_count = sb_journal_size(&super);
if (is_power_of_two (INFO->journal_block_count))
journal_init ();
/* Read in super block again, maybe it is in the journal */
block_read (superblock >> INFO->blocksize_shift,
0, sizeof (struct reiserfs_super_block), (char *) &super);
}
if (! block_read (sb_root_block(&super), 0, INFO->blocksize, (char*) ROOT))
return 0;
INFO->tree_depth = __le16_to_cpu(BLOCKHEAD (ROOT)->blk_level);
#ifdef REISERDEBUG
printf ("root read_in: block=%d, depth=%d\n",
sb_root_block(&super), INFO->tree_depth);
#endif /* REISERDEBUG */
if (INFO->tree_depth >= MAX_HEIGHT)
return 0;
if (INFO->tree_depth == DISK_LEAF_NODE_LEVEL)
{
/* There is only one node in the whole filesystem,
* which is simultanously leaf and root */
memcpy (LEAF, ROOT, INFO->blocksize);
}
return 1;
}
/***************** TREE ACCESSING METHODS *****************************/
/* I assume you are familiar with the ReiserFS tree, if not go to
* http://www.namesys.com/content_table.html
*
* My tree node cache is organized as following
* 0 ROOT node
* 1 LEAF node (if the ROOT is also a LEAF it is copied here
* 2-n other nodes on current path from bottom to top.
* if there is not enough space in the cache, the top most are
* omitted.
*
* I have only two methods to find a key in the tree:
* search_stat(dir_id, objectid) searches for the stat entry (always
* the first entry) of an object.
* next_key() gets the next key in tree order.
*
* This means, that I can only sequential reads of files are
* efficient, but this really doesn't hurt for grub.
*/
/* Read in the node at the current path and depth into the node cache.
* You must set INFO->blocks[depth] before.
*/
static char *
read_tree_node (unsigned int blockNr, int depth)
{
char* cache = CACHE(depth);
int num_cached = INFO->cached_slots;
if (depth < num_cached)
{
/* This is the cached part of the path. Check if same block is
* needed.
*/
if (blockNr == INFO->blocks[depth])
return cache;
}
else
cache = CACHE(num_cached);
#ifdef REISERDEBUG
printf (" next read_in: block=%d (depth=%d)\n",
blockNr, depth);
#endif /* REISERDEBUG */
if (! block_read (blockNr, 0, INFO->blocksize, cache))
return 0;
/* Make sure it has the right node level */
if (__le16_to_cpu(BLOCKHEAD (cache)->blk_level) != depth)
{
errnum = ERR_FSYS_CORRUPT;
return 0;
}
INFO->blocks[depth] = blockNr;
return cache;
}
/* Get the next key, i.e. the key following the last retrieved key in
* tree order. INFO->current_ih and
* INFO->current_info are adapted accordingly. */
static int
next_key (void)
{
int depth;
struct item_head *ih = INFO->current_ih + 1;
char *cache;
#ifdef REISERDEBUG
printf ("next_key:\n old ih: key %d:%d:%d:%d version:%d\n",
__le32_to_cpu(INFO->current_ih->ih_key.k_dir_id),
__le32_to_cpu(INFO->current_ih->ih_key.k_objectid),
__le32_to_cpu(INFO->current_ih->ih_key.u.v1.k_offset),
__le32_to_cpu(INFO->current_ih->ih_key.u.v1.k_uniqueness),
__le16_to_cpu(INFO->current_ih->ih_version));
#endif /* REISERDEBUG */
if (ih == &ITEMHEAD[__le16_to_cpu(BLOCKHEAD (LEAF)->blk_nr_item)])
{
depth = DISK_LEAF_NODE_LEVEL;
/* The last item, was the last in the leaf node.
* Read in the next block
*/
do
{
if (depth == INFO->tree_depth)
{
/* There are no more keys at all.
* Return a dummy item with MAX_KEY */
ih = (struct item_head *) &BLOCKHEAD (LEAF)->blk_right_delim_key;
goto found;
}
depth++;
#ifdef REISERDEBUG
printf (" depth=%d, i=%d\n", depth, INFO->next_key_nr[depth]);
#endif /* REISERDEBUG */
}
while (INFO->next_key_nr[depth] == 0);
if (depth == INFO->tree_depth)
cache = ROOT;
else if (depth <= INFO->cached_slots)
cache = CACHE (depth);
else
{
cache = read_tree_node (INFO->blocks[depth], depth);
if (! cache)
return 0;
}
do
{
int nr_item = __le16_to_cpu(BLOCKHEAD (cache)->blk_nr_item);
int key_nr = INFO->next_key_nr[depth]++;
#ifdef REISERDEBUG
printf (" depth=%d, i=%d/%d\n", depth, key_nr, nr_item);
#endif /* REISERDEBUG */
if (key_nr == nr_item)
/* This is the last item in this block, set the next_key_nr to 0 */
INFO->next_key_nr[depth] = 0;
cache = read_tree_node (dc_block_number(&(DC (cache)[key_nr])), --depth);
if (! cache)
return 0;
}
while (depth > DISK_LEAF_NODE_LEVEL);
ih = ITEMHEAD;
}
found:
INFO->current_ih = ih;
INFO->current_item = &LEAF[__le16_to_cpu(ih->ih_item_location)];
#ifdef REISERDEBUG
printf (" new ih: key %d:%d:%d:%d version:%d\n",
__le32_to_cpu(INFO->current_ih->ih_key.k_dir_id),
__le32_to_cpu(INFO->current_ih->ih_key.k_objectid),
__le32_to_cpu(INFO->current_ih->ih_key.u.v1.k_offset),
__le32_to_cpu(INFO->current_ih->ih_key.u.v1.k_uniqueness),
__le16_to_cpu(INFO->current_ih->ih_version));
#endif /* REISERDEBUG */
return 1;
}
/* preconditions: reiserfs_mount already executed, therefore
* INFO block is valid
* returns: 0 if error (errnum is set),
* nonzero iff we were able to find the key successfully.
* postconditions: on a nonzero return, the current_ih and
* current_item fields describe the key that equals the
* searched key. INFO->next_key contains the next key after
* the searched key.
* side effects: messes around with the cache.
*/
static int
search_stat (__u32 dir_id, __u32 objectid)
{
char *cache;
int depth;
int nr_item;
int i;
struct item_head *ih;
#ifdef REISERDEBUG
printf ("search_stat:\n key %d:%d:0:0\n", dir_id, objectid);
#endif /* REISERDEBUG */
depth = INFO->tree_depth;
cache = ROOT;
while (depth > DISK_LEAF_NODE_LEVEL)
{
struct key *key;
nr_item = __le16_to_cpu(BLOCKHEAD (cache)->blk_nr_item);
key = KEY (cache);
for (i = 0; i < nr_item; i++)
{
if (__le32_to_cpu(key->k_dir_id) > dir_id
|| (__le32_to_cpu(key->k_dir_id) == dir_id
&& (__le32_to_cpu(key->k_objectid) > objectid
|| (__le32_to_cpu(key->k_objectid) == objectid
&& (__le32_to_cpu(key->u.v1.k_offset)
| __le32_to_cpu(key->u.v1.k_uniqueness)) > 0))))
break;
key++;
}
#ifdef REISERDEBUG
printf (" depth=%d, i=%d/%d\n", depth, i, nr_item);
#endif /* REISERDEBUG */
INFO->next_key_nr[depth] = (i == nr_item) ? 0 : i+1;
cache = read_tree_node (dc_block_number(&(DC (cache)[i])), --depth);
if (! cache)
return 0;
}
/* cache == LEAF */
nr_item = __le16_to_cpu(BLOCKHEAD (LEAF)->blk_nr_item);
ih = ITEMHEAD;
for (i = 0; i < nr_item; i++)
{
if (__le32_to_cpu(ih->ih_key.k_dir_id) == dir_id
&& __le32_to_cpu(ih->ih_key.k_objectid) == objectid
&& __le32_to_cpu(ih->ih_key.u.v1.k_offset) == 0
&& __le32_to_cpu(ih->ih_key.u.v1.k_uniqueness) == 0)
{
#ifdef REISERDEBUG
printf (" depth=%d, i=%d/%d\n", depth, i, nr_item);
#endif /* REISERDEBUG */
INFO->current_ih = ih;
INFO->current_item = &LEAF[__le16_to_cpu(ih->ih_item_location)];
return 1;
}
ih++;
}
errnum = ERR_FSYS_CORRUPT;
return 0;
}
int
reiserfs_read (char *buf, unsigned len)
{
unsigned int blocksize;
unsigned int offset;
unsigned int to_read;
char *prev_buf = buf;
#ifdef REISERDEBUG
printf ("reiserfs_read: filepos=%d len=%d, offset=%Lx\n",
filepos, len, (__u64) IH_KEY_OFFSET (INFO->current_ih) - 1);
#endif /* REISERDEBUG */
if (__le32_to_cpu(INFO->current_ih->ih_key.k_objectid) != INFO->fileinfo.k_objectid
|| IH_KEY_OFFSET (INFO->current_ih) > filepos + 1)
{
search_stat (INFO->fileinfo.k_dir_id, INFO->fileinfo.k_objectid);
goto get_next_key;
}
while (! errnum)
{
if (__le32_to_cpu(INFO->current_ih->ih_key.k_objectid) != INFO->fileinfo.k_objectid) {
break;
}
offset = filepos - IH_KEY_OFFSET (INFO->current_ih) + 1;
blocksize = __le16_to_cpu(INFO->current_ih->ih_item_len);
#ifdef REISERDEBUG
printf (" loop: filepos=%d len=%d, offset=%d blocksize=%d\n",
filepos, len, offset, blocksize);
#endif /* REISERDEBUG */
if (IH_KEY_ISTYPE(INFO->current_ih, TYPE_DIRECT)
&& offset < blocksize)
{
#ifdef REISERDEBUG
printf ("direct_read: offset=%d, blocksize=%d\n",
offset, blocksize);
#endif /* REISERDEBUG */
to_read = blocksize - offset;
if (to_read > len)
to_read = len;
memcpy (buf, INFO->current_item + offset, to_read);
goto update_buf_len;
}
else if (IH_KEY_ISTYPE(INFO->current_ih, TYPE_INDIRECT))
{
blocksize = (blocksize >> 2) << INFO->fullblocksize_shift;
#ifdef REISERDEBUG
printf ("indirect_read: offset=%d, blocksize=%d\n",
offset, blocksize);
#endif /* REISERDEBUG */
while (offset < blocksize)
{
__u32 blocknr = __le32_to_cpu(((__u32 *) INFO->current_item)
[offset >> INFO->fullblocksize_shift]);
int blk_offset = offset & (INFO->blocksize-1);
to_read = INFO->blocksize - blk_offset;
if (to_read > len)
to_read = len;
/* Journal is only for meta data. Data blocks can be read
* directly without using block_read
*/
reiserfs_devread (blocknr << INFO->blocksize_shift,
blk_offset, to_read, buf);
update_buf_len:
len -= to_read;
buf += to_read;
offset += to_read;
filepos += to_read;
if (len == 0)
goto done;
}
}
get_next_key:
next_key ();
}
done:
return errnum ? 0 : buf - prev_buf;
}
/* preconditions: reiserfs_mount already executed, therefore
* INFO block is valid
* returns: 0 if error, nonzero iff we were able to find the file successfully
* postconditions: on a nonzero return, INFO->fileinfo contains the info
* of the file we were trying to look up, filepos is 0 and filemax is
* the size of the file.
*/
static int
reiserfs_dir (char *dirname)
{
struct reiserfs_de_head *de_head;
char *rest, ch;
__u32 dir_id, objectid, parent_dir_id = 0, parent_objectid = 0;
#ifndef STAGE1_5
int do_possibilities = 0;
#endif /* ! STAGE1_5 */
char linkbuf[PATH_MAX]; /* buffer for following symbolic links */
int link_count = 0;
int mode;
dir_id = REISERFS_ROOT_PARENT_OBJECTID;
objectid = REISERFS_ROOT_OBJECTID;
while (1)
{
#ifdef REISERDEBUG
printf ("dirname=%s\n", dirname);
#endif /* REISERDEBUG */
/* Search for the stat info first. */
if (! search_stat (dir_id, objectid))
return 0;
#ifdef REISERDEBUG
printf ("sd_mode=%x sd_size=%d\n",
stat_data_v1(INFO->current_ih) ? sd_v1_mode((struct stat_data_v1 *) INFO->current_item) :
sd_v2_mode((struct stat_data *) (INFO->current_item)),
stat_data_v1(INFO->current_ih) ? sd_v1_size((struct stat_data_v1 *) INFO->current_item) :
sd_v2_size((struct stat_data *) INFO->current_item)
);
#endif /* REISERDEBUG */
mode = stat_data_v1(INFO->current_ih) ?
sd_v1_mode((struct stat_data_v1 *) INFO->current_item) :
sd_v2_mode((struct stat_data *) INFO->current_item);
/* If we've got a symbolic link, then chase it. */
if (S_ISLNK (mode))
{
unsigned int len;
if (++link_count > MAX_LINK_COUNT)
{
errnum = ERR_SYMLINK_LOOP;
return 0;
}
/* Get the symlink size. */
filemax = stat_data_v1(INFO->current_ih) ?
sd_v1_size((struct stat_data_v1 *) INFO->current_item) :
sd_v2_size((struct stat_data *) INFO->current_item);
/* Find out how long our remaining name is. */
len = 0;
while (dirname[len] && !isspace (dirname[len]))
len++;
if (filemax + len > sizeof (linkbuf) - 1)
{
errnum = ERR_FILELENGTH;
return 0;
}
/* Copy the remaining name to the end of the symlink data.
Note that DIRNAME and LINKBUF may overlap! */
memmove (linkbuf + filemax, dirname, len+1);
INFO->fileinfo.k_dir_id = dir_id;
INFO->fileinfo.k_objectid = objectid;
filepos = 0;
if (! next_key ()
|| reiserfs_read (linkbuf, filemax) != filemax)
{
if (! errnum)
errnum = ERR_FSYS_CORRUPT;
return 0;
}
#ifdef REISERDEBUG
printf ("symlink=%s\n", linkbuf);
#endif /* REISERDEBUG */
dirname = linkbuf;
if (*dirname == '/')
{
/* It's an absolute link, so look it up in root. */
dir_id = REISERFS_ROOT_PARENT_OBJECTID;
objectid = REISERFS_ROOT_OBJECTID;
}
else
{
/* Relative, so look it up in our parent directory. */
dir_id = parent_dir_id;
objectid = parent_objectid;
}
/* Now lookup the new name. */
continue;
}
/* if we have a real file (and we're not just printing possibilities),
then this is where we want to exit */
if (! *dirname || isspace (*dirname))
{
if (! S_ISREG (mode))
{
errnum = ERR_BAD_FILETYPE;
return 0;
}
filepos = 0;
filemax = stat_data_v1(INFO->current_ih) ?
sd_v1_size((struct stat_data_v1 *) INFO->current_item) :
sd_v2_size((struct stat_data *) INFO->current_item);
INFO->fileinfo.k_dir_id = dir_id;
INFO->fileinfo.k_objectid = objectid;
return next_key ();
}
/* continue with the file/directory name interpretation */
while (*dirname == '/')
dirname++;
if (! S_ISDIR (mode))
{
errnum = ERR_BAD_FILETYPE;
return 0;
}
for (rest = dirname; (ch = *rest) && ! isspace (ch) && ch != '/'; rest++);
*rest = 0;
# ifndef STAGE1_5
if (print_possibilities && ch != '/')
do_possibilities = 1;
# endif /* ! STAGE1_5 */
while (1)
{
char *name_end;
int num_entries;
if (! next_key ())
return 0;
#ifdef REISERDEBUG
printf ("ih: key %d:%d:%d:%d version:%d\n",
__le32_to_cpu(INFO->current_ih->ih_key.k_dir_id),
__le32_to_cpu(INFO->current_ih->ih_key.k_objectid),
__le32_to_cpu(INFO->current_ih->ih_key.u.v1.k_offset),
__le32_to_cpu(INFO->current_ih->ih_key.u.v1.k_uniqueness),
__le16_to_cpu(INFO->current_ih->ih_version));
#endif /* REISERDEBUG */
if (__le32_to_cpu(INFO->current_ih->ih_key.k_objectid) != objectid)
break;
name_end = INFO->current_item + __le16_to_cpu(INFO->current_ih->ih_item_len);
de_head = (struct reiserfs_de_head *) INFO->current_item;
num_entries = __le16_to_cpu(INFO->current_ih->u.ih_entry_count);
while (num_entries > 0)
{
char *filename = INFO->current_item + deh_location(de_head);
char tmp = *name_end;
if ((deh_state(de_head) & DEH_Visible))
{
int cmp;
/* Directory names in ReiserFS are not null
* terminated. We write a temporary 0 behind it.
* NOTE: that this may overwrite the first block in
* the tree cache. That doesn't hurt as long as we
* don't call next_key () in between.
*/
*name_end = 0;
cmp = substring (dirname, filename);
*name_end = tmp;
# ifndef STAGE1_5
if (do_possibilities)
{
if (cmp <= 0)
{
char fn[PATH_MAX];
struct fsys_reiser_info info_save;
if (print_possibilities > 0)
print_possibilities = -print_possibilities;
*name_end = 0;
strcpy(fn, filename);
*name_end = tmp;
/* If NAME is "." or "..", do not count it. */
if (strcmp (fn, ".") != 0 && strcmp (fn, "..") != 0) {
memcpy(&info_save, INFO, sizeof(struct fsys_reiser_info));
search_stat (deh_dir_id(de_head), deh_objectid(de_head));
sd_print_item(INFO->current_ih, INFO->current_item);
printf(" %s\n", fn);
search_stat (dir_id, objectid);
memcpy(INFO, &info_save, sizeof(struct fsys_reiser_info));
}
}
}
else
# endif /* ! STAGE1_5 */
if (cmp == 0)
goto found;
}
/* The beginning of this name marks the end of the next name.
*/
name_end = filename;
de_head++;
num_entries--;
}
}
# ifndef STAGE1_5
if (print_possibilities < 0)
return 1;
# endif /* ! STAGE1_5 */
errnum = ERR_FILE_NOT_FOUND;
*rest = ch;
return 0;
found:
*rest = ch;
dirname = rest;
parent_dir_id = dir_id;
parent_objectid = objectid;
dir_id = deh_dir_id(de_head);
objectid = deh_objectid(de_head);
}
}
/*
* U-Boot interface functions
*/
/*
* List given directory
*
* RETURN: 0 - OK, else grub_error_t errnum
*/
int
reiserfs_ls (char *dirname)
{
char *dir_slash;
int res;
errnum = 0;
dir_slash = malloc(strlen(dirname) + 1);
if (dir_slash == NULL) {
return ERR_NUMBER_OVERFLOW;
}
strcpy(dir_slash, dirname);
/* add "/" to the directory name */
strcat(dir_slash, "/");
print_possibilities = 1;
res = reiserfs_dir (dir_slash);
free(dir_slash);
if (!res || errnum) {
return errnum;
}
return 0;
}
/*
* Open file for reading
*
* RETURN: >0 - OK, size of opened file
* <0 - ERROR -grub_error_t errnum
*/
int
reiserfs_open (char *filename)
{
/* open the file */
errnum = 0;
print_possibilities = 0;
if (!reiserfs_dir (filename) || errnum) {
return -errnum;
}
return filemax;
}
#endif /* CFG_CMD_REISER */

View File

@ -1,520 +0,0 @@
/*
* Copyright 2000-2002 by Hans Reiser, licensing governed by reiserfs/README
*
* GRUB -- GRand Unified Bootloader
* Copyright (C) 2000, 2001 Free Software Foundation, Inc.
*
* (C) Copyright 2003 - 2004
* Sysgo AG, <www.elinos.com>, Pavel Bartusek <pba@sysgo.com>
*
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
/* An implementation for the ReiserFS filesystem ported from GRUB.
* Some parts of this code (mainly the structures and defines) are
* from the original reiser fs code, as found in the linux kernel.
*/
#ifndef __BYTE_ORDER
#if defined(__LITTLE_ENDIAN) && !defined(__BIG_ENDIAN)
#define __BYTE_ORDER __LITTLE_ENDIAN
#elif defined(__BIG_ENDIAN) && !defined(__LITTLE_ENDIAN)
#define __BYTE_ORDER __BIG_ENDIAN
#else
#error "unable to define __BYTE_ORDER"
#endif
#endif /* not __BYTE_ORDER */
#define FSYS_BUFLEN 0x8000
#define FSYS_BUF fsys_buf
/* This is the new super block of a journaling reiserfs system */
struct reiserfs_super_block
{
__u32 s_block_count; /* blocks count */
__u32 s_free_blocks; /* free blocks count */
__u32 s_root_block; /* root block number */
__u32 s_journal_block; /* journal block number */
__u32 s_journal_dev; /* journal device number */
__u32 s_journal_size; /* size of the journal on FS creation. used to make sure they don't overflow it */
__u32 s_journal_trans_max; /* max number of blocks in a transaction. */
__u32 s_journal_magic; /* random value made on fs creation */
__u32 s_journal_max_batch; /* max number of blocks to batch into a trans */
__u32 s_journal_max_commit_age; /* in seconds, how old can an async commit be */
__u32 s_journal_max_trans_age; /* in seconds, how old can a transaction be */
__u16 s_blocksize; /* block size */
__u16 s_oid_maxsize; /* max size of object id array */
__u16 s_oid_cursize; /* current size of object id array */
__u16 s_state; /* valid or error */
char s_magic[16]; /* reiserfs magic string indicates that file system is reiserfs */
__u16 s_tree_height; /* height of disk tree */
__u16 s_bmap_nr; /* amount of bitmap blocks needed to address each block of file system */
__u16 s_version;
char s_unused[128]; /* zero filled by mkreiserfs */
};
#define sb_root_block(sbp) (__le32_to_cpu((sbp)->s_root_block))
#define sb_journal_block(sbp) (__le32_to_cpu((sbp)->s_journal_block))
#define set_sb_journal_block(sbp,v) ((sbp)->s_journal_block = __cpu_to_le32(v))
#define sb_journal_size(sbp) (__le32_to_cpu((sbp)->s_journal_size))
#define sb_blocksize(sbp) (__le16_to_cpu((sbp)->s_blocksize))
#define set_sb_blocksize(sbp,v) ((sbp)->s_blocksize = __cpu_to_le16(v))
#define sb_version(sbp) (__le16_to_cpu((sbp)->s_version))
#define set_sb_version(sbp,v) ((sbp)->s_version = __cpu_to_le16(v))
#define REISERFS_MAX_SUPPORTED_VERSION 2
#define REISERFS_SUPER_MAGIC_STRING "ReIsErFs"
#define REISER2FS_SUPER_MAGIC_STRING "ReIsEr2Fs"
#define REISER3FS_SUPER_MAGIC_STRING "ReIsEr3Fs"
#define MAX_HEIGHT 7
/* must be correct to keep the desc and commit structs at 4k */
#define JOURNAL_TRANS_HALF 1018
/* first block written in a commit. */
struct reiserfs_journal_desc {
__u32 j_trans_id; /* id of commit */
__u32 j_len; /* length of commit. len +1 is the commit block */
__u32 j_mount_id; /* mount id of this trans*/
__u32 j_realblock[JOURNAL_TRANS_HALF]; /* real locations for the first blocks */
char j_magic[12];
};
/* last block written in a commit */
struct reiserfs_journal_commit {
__u32 j_trans_id; /* must match j_trans_id from the desc block */
__u32 j_len; /* ditto */
__u32 j_realblock[JOURNAL_TRANS_HALF]; /* real locations for the last blocks */
char j_digest[16]; /* md5 sum of all the blocks involved, including desc and commit. not used, kill it */
};
/* this header block gets written whenever a transaction is considered
fully flushed, and is more recent than the last fully flushed
transaction.
fully flushed means all the log blocks and all the real blocks are
on disk, and this transaction does not need to be replayed.
*/
struct reiserfs_journal_header {
/* id of last fully flushed transaction */
__u32 j_last_flush_trans_id;
/* offset in the log of where to start replay after a crash */
__u32 j_first_unflushed_offset;
/* mount id to detect very old transactions */
__u32 j_mount_id;
};
/* magic string to find desc blocks in the journal */
#define JOURNAL_DESC_MAGIC "ReIsErLB"
/*
* directories use this key as well as old files
*/
struct offset_v1
{
/*
* for regular files this is the offset to the first byte of the
* body, contained in the object-item, as measured from the start of
* the entire body of the object.
*
* for directory entries, k_offset consists of hash derived from
* hashing the name and using few bits (23 or more) of the resulting
* hash, and generation number that allows distinguishing names with
* hash collisions. If number of collisions overflows generation
* number, we return EEXIST. High order bit is 0 always
*/
__u32 k_offset;
__u32 k_uniqueness;
};
struct offset_v2 {
/*
* for regular files this is the offset to the first byte of the
* body, contained in the object-item, as measured from the start of
* the entire body of the object.
*
* for directory entries, k_offset consists of hash derived from
* hashing the name and using few bits (23 or more) of the resulting
* hash, and generation number that allows distinguishing names with
* hash collisions. If number of collisions overflows generation
* number, we return EEXIST. High order bit is 0 always
*/
#if defined(__LITTLE_ENDIAN_BITFIELD)
/* little endian version */
__u64 k_offset:60;
__u64 k_type: 4;
#elif defined(__BIG_ENDIAN_BITFIELD)
/* big endian version */
__u64 k_type: 4;
__u64 k_offset:60;
#else
#error "__LITTLE_ENDIAN_BITFIELD or __BIG_ENDIAN_BITFIELD must be defined"
#endif
} __attribute__ ((__packed__));
#define TYPE_MAXTYPE 3
#define TYPE_ANY 15
#if (__BYTE_ORDER == __BIG_ENDIAN)
typedef union {
struct offset_v2 offset_v2;
__u64 linear;
} __attribute__ ((__packed__)) offset_v2_esafe_overlay;
static inline __u16 offset_v2_k_type( const struct offset_v2 *v2 )
{
offset_v2_esafe_overlay tmp = *(const offset_v2_esafe_overlay *)v2;
tmp.linear = __le64_to_cpu( tmp.linear );
return (tmp.offset_v2.k_type <= TYPE_MAXTYPE)?tmp.offset_v2.k_type:TYPE_ANY;
}
static inline loff_t offset_v2_k_offset( const struct offset_v2 *v2 )
{
offset_v2_esafe_overlay tmp = *(const offset_v2_esafe_overlay *)v2;
tmp.linear = __le64_to_cpu( tmp.linear );
return tmp.offset_v2.k_offset;
}
#elif (__BYTE_ORDER == __LITTLE_ENDIAN)
# define offset_v2_k_type(v2) ((v2)->k_type)
# define offset_v2_k_offset(v2) ((v2)->k_offset)
#else
#error "__BYTE_ORDER must be __LITTLE_ENDIAN or __BIG_ENDIAN"
#endif
struct key
{
/* packing locality: by default parent directory object id */
__u32 k_dir_id;
/* object identifier */
__u32 k_objectid;
/* the offset and node type (old and new form) */
union
{
struct offset_v1 v1;
struct offset_v2 v2;
}
u;
};
#define KEY_SIZE (sizeof (struct key))
/* Header of a disk block. More precisely, header of a formatted leaf
or internal node, and not the header of an unformatted node. */
struct block_head
{
__u16 blk_level; /* Level of a block in the tree. */
__u16 blk_nr_item; /* Number of keys/items in a block. */
__u16 blk_free_space; /* Block free space in bytes. */
struct key blk_right_delim_key; /* Right delimiting key for this block (supported for leaf level nodes
only) */
};
#define BLKH_SIZE (sizeof (struct block_head))
#define DISK_LEAF_NODE_LEVEL 1 /* Leaf node level. */
struct item_head
{
/* Everything in the tree is found by searching for it based on
* its key.*/
struct key ih_key;
union {
/* The free space in the last unformatted node of an
indirect item if this is an indirect item. This
equals 0xFFFF iff this is a direct item or stat data
item. Note that the key, not this field, is used to
determine the item type, and thus which field this
union contains. */
__u16 ih_free_space;
/* Iff this is a directory item, this field equals the
number of directory entries in the directory item. */
__u16 ih_entry_count;
} __attribute__ ((__packed__)) u;
__u16 ih_item_len; /* total size of the item body */
__u16 ih_item_location; /* an offset to the item body
* within the block */
__u16 ih_version; /* 0 for all old items, 2 for new
ones. Highest bit is set by fsck
temporary, cleaned after all
done */
} __attribute__ ((__packed__));
/* size of item header */
#define IH_SIZE (sizeof (struct item_head))
#define ITEM_VERSION_1 0
#define ITEM_VERSION_2 1
#define ih_version(ih) (__le16_to_cpu((ih)->ih_version))
#define IH_KEY_OFFSET(ih) (ih_version(ih) == ITEM_VERSION_1 \
? __le32_to_cpu((ih)->ih_key.u.v1.k_offset) \
: offset_v2_k_offset(&((ih)->ih_key.u.v2)))
#define IH_KEY_ISTYPE(ih, type) (ih_version(ih) == ITEM_VERSION_1 \
? __le32_to_cpu((ih)->ih_key.u.v1.k_uniqueness) == V1_##type \
: offset_v2_k_type(&((ih)->ih_key.u.v2)) == V2_##type)
/***************************************************************************/
/* DISK CHILD */
/***************************************************************************/
/* Disk child pointer: The pointer from an internal node of the tree
to a node that is on disk. */
struct disk_child {
__u32 dc_block_number; /* Disk child's block number. */
__u16 dc_size; /* Disk child's used space. */
__u16 dc_reserved;
};
#define DC_SIZE (sizeof(struct disk_child))
#define dc_block_number(dc_p) (__le32_to_cpu((dc_p)->dc_block_number))
/*
* old stat data is 32 bytes long. We are going to distinguish new one by
* different size
*/
struct stat_data_v1
{
__u16 sd_mode; /* file type, permissions */
__u16 sd_nlink; /* number of hard links */
__u16 sd_uid; /* owner */
__u16 sd_gid; /* group */
__u32 sd_size; /* file size */
__u32 sd_atime; /* time of last access */
__u32 sd_mtime; /* time file was last modified */
__u32 sd_ctime; /* time inode (stat data) was last changed (except changes to sd_atime and sd_mtime) */
union {
__u32 sd_rdev;
__u32 sd_blocks; /* number of blocks file uses */
} __attribute__ ((__packed__)) u;
__u32 sd_first_direct_byte; /* first byte of file which is stored
in a direct item: except that if it
equals 1 it is a symlink and if it
equals ~(__u32)0 there is no
direct item. The existence of this
field really grates on me. Let's
replace it with a macro based on
sd_size and our tail suppression
policy. Someday. -Hans */
} __attribute__ ((__packed__));
#define stat_data_v1(ih) (ih_version(ih) == ITEM_VERSION_1)
#define sd_v1_mode(sdp) ((sdp)->sd_mode)
#define sd_v1_nlink(sdp) (__le16_to_cpu((sdp)->sd_nlink))
#define sd_v1_uid(sdp) (__le16_to_cpu((sdp)->sd_uid))
#define sd_v1_gid(sdp) (__le16_to_cpu((sdp)->sd_gid))
#define sd_v1_size(sdp) (__le32_to_cpu((sdp)->sd_size))
#define sd_v1_mtime(sdp) (__le32_to_cpu((sdp)->sd_mtime))
/* Stat Data on disk (reiserfs version of UFS disk inode minus the
address blocks) */
struct stat_data {
__u16 sd_mode; /* file type, permissions */
__u16 sd_attrs; /* persistent inode flags */
__u32 sd_nlink; /* number of hard links */
__u64 sd_size; /* file size */
__u32 sd_uid; /* owner */
__u32 sd_gid; /* group */
__u32 sd_atime; /* time of last access */
__u32 sd_mtime; /* time file was last modified */
__u32 sd_ctime; /* time inode (stat data) was last changed (except changes to sd_atime and sd_mtime) */
__u32 sd_blocks;
union {
__u32 sd_rdev;
__u32 sd_generation;
/*__u32 sd_first_direct_byte; */
/* first byte of file which is stored in a
direct item: except that if it equals 1
it is a symlink and if it equals
~(__u32)0 there is no direct item. The
existence of this field really grates
on me. Let's replace it with a macro
based on sd_size and our tail
suppression policy? */
} __attribute__ ((__packed__)) u;
} __attribute__ ((__packed__));
#define stat_data_v2(ih) (ih_version(ih) == ITEM_VERSION_2)
#define sd_v2_mode(sdp) (__le16_to_cpu((sdp)->sd_mode))
#define sd_v2_nlink(sdp) (__le32_to_cpu((sdp)->sd_nlink))
#define sd_v2_size(sdp) (__le64_to_cpu((sdp)->sd_size))
#define sd_v2_uid(sdp) (__le32_to_cpu((sdp)->sd_uid))
#define sd_v2_gid(sdp) (__le32_to_cpu((sdp)->sd_gid))
#define sd_v2_mtime(sdp) (__le32_to_cpu((sdp)->sd_mtime))
#define sd_mode(sdp) (__le16_to_cpu((sdp)->sd_mode))
#define sd_size(sdp) (__le32_to_cpu((sdp)->sd_size))
#define sd_size_hi(sdp) (__le32_to_cpu((sdp)->sd_size_hi))
struct reiserfs_de_head
{
__u32 deh_offset; /* third component of the directory entry key */
__u32 deh_dir_id; /* objectid of the parent directory of the
object, that is referenced by directory entry */
__u32 deh_objectid;/* objectid of the object, that is referenced by
directory entry */
__u16 deh_location;/* offset of name in the whole item */
__u16 deh_state; /* whether 1) entry contains stat data (for
future), and 2) whether entry is hidden
(unlinked) */
};
#define DEH_SIZE (sizeof (struct reiserfs_de_head))
#define deh_offset(p_deh) (__le32_to_cpu((p_deh)->deh_offset))
#define deh_dir_id(p_deh) (__le32_to_cpu((p_deh)->deh_dir_id))
#define deh_objectid(p_deh) (__le32_to_cpu((p_deh)->deh_objectid))
#define deh_location(p_deh) (__le16_to_cpu((p_deh)->deh_location))
#define deh_state(p_deh) (__le16_to_cpu((p_deh)->deh_state))
#define DEH_Statdata (1 << 0) /* not used now */
#define DEH_Visible (1 << 2)
#define SD_OFFSET 0
#define SD_UNIQUENESS 0
#define DOT_OFFSET 1
#define DOT_DOT_OFFSET 2
#define DIRENTRY_UNIQUENESS 500
#define V1_TYPE_STAT_DATA 0x0
#define V1_TYPE_DIRECT 0xffffffff
#define V1_TYPE_INDIRECT 0xfffffffe
#define V1_TYPE_DIRECTORY_MAX 0xfffffffd
#define V2_TYPE_STAT_DATA 0
#define V2_TYPE_INDIRECT 1
#define V2_TYPE_DIRECT 2
#define V2_TYPE_DIRENTRY 3
#define REISERFS_ROOT_OBJECTID 2
#define REISERFS_ROOT_PARENT_OBJECTID 1
#define REISERFS_DISK_OFFSET_IN_BYTES (64 * 1024)
/* the spot for the super in versions 3.5 - 3.5.11 (inclusive) */
#define REISERFS_OLD_DISK_OFFSET_IN_BYTES (8 * 1024)
#define REISERFS_OLD_BLOCKSIZE 4096
#define S_ISREG(mode) (((mode) & 0170000) == 0100000)
#define S_ISDIR(mode) (((mode) & 0170000) == 0040000)
#define S_ISLNK(mode) (((mode) & 0170000) == 0120000)
#define PATH_MAX 1024 /* include/linux/limits.h */
#define MAX_LINK_COUNT 5 /* number of symbolic links to follow */
/* The size of the node cache */
#define FSYSREISER_CACHE_SIZE 24*1024
#define FSYSREISER_MIN_BLOCKSIZE SECTOR_SIZE
#define FSYSREISER_MAX_BLOCKSIZE FSYSREISER_CACHE_SIZE / 3
/* Info about currently opened file */
struct fsys_reiser_fileinfo
{
__u32 k_dir_id;
__u32 k_objectid;
};
/* In memory info about the currently mounted filesystem */
struct fsys_reiser_info
{
/* The last read item head */
struct item_head *current_ih;
/* The last read item */
char *current_item;
/* The information for the currently opened file */
struct fsys_reiser_fileinfo fileinfo;
/* The start of the journal */
__u32 journal_block;
/* The size of the journal */
__u32 journal_block_count;
/* The first valid descriptor block in journal
(relative to journal_block) */
__u32 journal_first_desc;
/* The ReiserFS version. */
__u16 version;
/* The current depth of the reiser tree. */
__u16 tree_depth;
/* SECTOR_SIZE << blocksize_shift == blocksize. */
__u8 blocksize_shift;
/* 1 << full_blocksize_shift == blocksize. */
__u8 fullblocksize_shift;
/* The reiserfs block size (must be a power of 2) */
__u16 blocksize;
/* The number of cached tree nodes */
__u16 cached_slots;
/* The number of valid transactions in journal */
__u16 journal_transactions;
unsigned int blocks[MAX_HEIGHT];
unsigned int next_key_nr[MAX_HEIGHT];
};
/* The cached s+tree blocks in FSYS_BUF, see below
* for a more detailed description.
*/
#define ROOT ((char *) ((int) FSYS_BUF))
#define CACHE(i) (ROOT + ((i) << INFO->fullblocksize_shift))
#define LEAF CACHE (DISK_LEAF_NODE_LEVEL)
#define BLOCKHEAD(cache) ((struct block_head *) cache)
#define ITEMHEAD ((struct item_head *) ((int) LEAF + BLKH_SIZE))
#define KEY(cache) ((struct key *) ((int) cache + BLKH_SIZE))
#define DC(cache) ((struct disk_child *) \
((int) cache + BLKH_SIZE + KEY_SIZE * nr_item))
/* The fsys_reiser_info block.
*/
#define INFO \
((struct fsys_reiser_info *) ((int) FSYS_BUF + FSYSREISER_CACHE_SIZE))
/*
* The journal cache. For each transaction it contains the number of
* blocks followed by the real block numbers of this transaction.
*
* If the block numbers of some transaction won't fit in this space,
* this list is stopped with a 0xffffffff marker and the remaining
* uncommitted transactions aren't cached.
*/
#define JOURNAL_START ((__u32 *) (INFO + 1))
#define JOURNAL_END ((__u32 *) (FSYS_BUF + FSYS_BUFLEN))
static __inline__ unsigned long
log2 (unsigned long word)
{
#ifdef __I386__
__asm__ ("bsfl %1,%0"
: "=r" (word)
: "r" (word));
return word;
#else
int i;
for(i=0; i<(8*sizeof(word)); i++)
if ((1<<i) & word)
return i;
return 0;
#endif
}
static __inline__ int
is_power_of_two (unsigned long word)
{
return (word & -word) == word;
}
extern const char *bb_mode_string(int mode);
extern int reiserfs_devread (int sector, int byte_offset, int byte_len, char *buf);