cramfs
Subsystems (3)
PATCH 6/6 cramfs
-------------- next part --------------
#
# Author: Robert Schwebel <[email protected]>
#
# Description: Patch by Kai-Uwe Bloem: add support for cramfs.
#
# State: 2003-12-09: submit
#
#
# Patch managed by http://www.mn-logistik.de/unsupported/pxa250/patcher
#
fs/cramfs/cramfs.c new file +362 -0
@@ -0,0 +1,362 @@ +/* +* cramfs.c +* +* Copyright (C) 1999 Linus Torvalds +* +* Copyright (C) 2000-2002 Transmeta Corporation +* +* Copyright (C) 2003 Kai-Uwe Bloem, +* Auerswald GmbH & Co KG, <[email protected]> +* - adapted from the www.tuxbox.org u-boot tree, added "ls" command +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License (Version 2) as +* published by the Free Software Foundation. +* +* Compressed ROM filesystem for Linux. +* +* TODO: +* add support for resolving symbolic links +*/ + +/* +* These are the VFS interfaces to the compressed ROM filesystem. +* The actual compression is based on zlib, see the other files. +*/ + +#include <common.h> +#include <malloc.h> + +#if (CONFIG_COMMANDS &CFG_CMD_JFFS2 ) + +#include <asm/byteorder.h> +#include <linux/stat.h> +#include <jffs2/load_kernel.h> +#include "cramfs_fs.h" + +/* These two macros may change in future, to provide better st_ino +semantics. */ +#define CRAMINO (x) (CRAMFS_GET_OFFSET(x) ? CRAMFS_GET_OFFSET(x)<<2 : 1) +#define OFFSET (x) ((x)->i_ino) + +struct cramfs_super super; + +static int cramfs_read_super (struct part_info *info) +{ +unsigned long root_offset; + +/* Read the first block and get the superblock from it */ +memcpy (&super, (void *) info->offset,sizeof (super)); + +/* Do sanity checks on the superblock */ +if (super.magic !=CRAMFS_32 (CRAMFS_MAGIC )) { +/* check at 512 byte offset */ +memcpy (&super, (void *) info->offset +512 ,sizeof (super)); +if (super.magic !=CRAMFS_32 (CRAMFS_MAGIC )) { +printf ("cramfs: wrong magic\n" ); +return -1 ; + } + } + +/* flags is reused several times, so swab it once */ + super.flags =CRAMFS_32 (super.flags); + super.size =CRAMFS_32 (super.size); + +/* get feature flags first */ +if (super.flags & ~CRAMFS_SUPPORTED_FLAGS ) { +printf ("cramfs: unsupported filesystem features\n" ); +return -1 ; + } + +/* Check that the root inode is in a sane state */ +if (!S_ISDIR (CRAMFS_16 (super.root.mode))) { +printf ("cramfs: root is not a directory\n" ); +return -1 ; + } + root_offset =CRAMFS_GET_OFFSET (&(super.root)) <<2 ; +if (root_offset ==0 ) +printf ("cramfs: empty filesystem" ); +else if (!(super.flags &CRAMFS_FLAG_SHIFTED_ROOT_OFFSET ) && + ((root_offset !=sizeof (struct cramfs_super )) && + (root_offset !=512 +sizeof (struct cramfs_super )))) + { +printf ("cramfs: bad root offset %lu\n" , root_offset); +return -1 ; + } + +return 0 ; +} + +static unsigned long cramfs_resolve (char *begin,unsigned long offset, +unsigned long size,int raw,char *filename) +{ +unsigned long inodeoffset =0 , nextoffset; + +while (inodeoffset < size) { +struct cramfs_inode *inode; +char *name; +int namelen; + + inode = (struct cramfs_inode *) (begin + offset + inodeoffset); + +/* +* Namelengths on disk are shifted by two +* and the name padded out to 4-byte boundaries +* with zeroes. +*/ + namelen =CRAMFS_GET_NAMELEN (inode) <<2 ; + name = (char *) inode +sizeof (struct cramfs_inode ); + + nextoffset = inodeoffset +sizeof (struct cramfs_inode ) + namelen; + +for (;;) { +if (!namelen) +return -1 ; +if (name[namelen-1 ]) +break ; + namelen--; + } + +if (!strncmp (filename, name, namelen)) + { +char *p =strtok (NULL ,"/" ); +if (raw && (p ==NULL || *p =='\0' )) +return offset + inodeoffset; + +if (S_ISDIR (CRAMFS_16 (inode->mode))) + { +return cramfs_resolve (begin, +CRAMFS_GET_OFFSET (inode) <<2 , +CRAMFS_24 (inode->size), raw, p); + } +else if (S_ISREG (CRAMFS_16 (inode->mode))) + { +return offset + inodeoffset; + } +else + { +printf ("%*.*s: unsupported file type (%x)\n" , + namelen, namelen, name, +CRAMFS_16 (inode->mode)); +return 0 ; + } + } + + inodeoffset = nextoffset; + } + +printf ("can't find corresponding entry\n" ); +return 0 ; +} + +static int cramfs_uncompress (char * begin,unsigned long offset, +unsigned long loadoffset) +{ +struct cramfs_inode *inode = (struct cramfs_inode *) (begin + offset); +unsigned long *block_ptrs = (unsigned long *) + (begin + (CRAMFS_GET_OFFSET (inode) <<2 )); +unsigned long curr_block = (CRAMFS_GET_OFFSET (inode) + + (((CRAMFS_24 (inode->size)) +4095 ) >>12 )) <<2 ; +int size, total_size =0 ; +int i; + +cramfs_uncompress_init (); + +for (i =0 ; i < ((CRAMFS_24 (inode->size) +4095 ) >>12 ); i++) + { + size =cramfs_uncompress_block ((void *) loadoffset, + (void *) (begin + curr_block), + (CRAMFS_32 (block_ptrs[i]) - curr_block)); +if (size <0 ) +return size; + loadoffset += size; + total_size += size; + curr_block =CRAMFS_32 (block_ptrs[i]); + } + +cramfs_uncompress_exit (); +return total_size; +} + +int cramfs_load (char *loadoffset,struct part_info *info,char *filename) +{ +unsigned long offset; + +if (cramfs_read_super (info)) +return -1 ; + + offset =cramfs_resolve (info->offset, +CRAMFS_GET_OFFSET (&(super.root)) <<2 , +CRAMFS_24 (super.root.size),0 ,strtok (filename,"/" )); + +if (offset <=0 ) +return offset; + +return cramfs_uncompress (info->offset, offset, + (unsigned long ) loadoffset); +} + +static char *mkmodestr (unsigned long mode,char *str) +{ +static const char *l ="xwr" ; +int mask =1 , i; +char c; + +switch (mode &S_IFMT ) { +case S_IFDIR : str[0 ] ='d' ;break ; +case S_IFBLK : str[0 ] ='b' ;break ; +case S_IFCHR : str[0 ] ='c' ;break ; +case S_IFIFO : str[0 ] ='f' ;break ; +case S_IFLNK : str[0 ] ='l' ;break ; +case S_IFSOCK : str[0 ] ='s' ;break ; +case S_IFREG : str[0 ] ='-' ;break ; +default : str[0 ] ='?' ; + } + +for (i =0 ; i <9 ; i++) { + c = l[i%3 ]; + str[9 -i] = (mode & mask)?c:'-' ; + mask = mask<<1 ; + } + +if (mode &S_ISUID ) str[3 ] = (mode &S_IXUSR )?'s' :'S' ; +if (mode &S_ISGID ) str[6 ] = (mode &S_IXGRP )?'s' :'S' ; +if (mode &S_ISVTX ) str[9 ] = (mode &S_IXOTH )?'t' :'T' ; + str[10 ] ='\0' ; +return str; +} + +static int cramfs_list_inode (struct part_info *info,unsigned long offset) +{ +struct cramfs_inode *inode = (struct cramfs_inode *) + (info->offset + offset); +char *name, str[20 ]; +int namelen, nextoff; + +/* +* Namelengths on disk are shifted by two +* and the name padded out to 4-byte boundaries +* with zeroes. +*/ + namelen =CRAMFS_GET_NAMELEN (inode) <<2 ; + name = (char *) inode +sizeof (struct cramfs_inode ); + nextoff = namelen; + +for (;;) { +if (!namelen) +return namelen; +if (name[namelen-1 ]) +break ; + namelen--; + } + +printf (" %s %8d %*.*s" ,mkmodestr (CRAMFS_16 (inode->mode),str), +CRAMFS_24 (inode->size), namelen, namelen, name); + +if ((CRAMFS_16 (inode->mode) &S_IFMT ) ==S_IFLNK ) { +/* symbolic link. +* Unpack the link target, trusting in the inode's size field. +*/ +unsigned long size =CRAMFS_24 (inode->size); +char *link =malloc (size); +if (link !=NULL &&cramfs_uncompress (info->offset, offset, + (unsigned long )link) == size) +printf (" -> %*.*s\n" , (int )size, (int )size, link); +else +printf (" [Error reading link]\n" ); +if (link)free (link); + }else +printf ("\n" ); + +return nextoff; +} + +int cramfs_ls (struct part_info *info,char *filename) +{ +struct cramfs_inode *inode; +unsigned long inodeoffset =0 , nextoffset; +unsigned long offset, size; + +if (cramfs_read_super (info)) +return -1 ; + +if (strlen (filename) ==0 || !strcmp (filename,"/" )) { +/* Root directory. Use root inode in super block */ + offset =CRAMFS_GET_OFFSET (&(super.root)) <<2 ; + size =CRAMFS_24 (super.root.size); + }else { +/* Resolve the path */ + offset =cramfs_resolve (info->offset, +CRAMFS_GET_OFFSET (&(super.root)) <<2 , +CRAMFS_24 (super.root.size),1 ,strtok (filename,"/" )); + +if (offset <=0 ) +return offset; + +/* Resolving was successful. Examine the inode */ + inode = (struct cramfs_inode *) (info->offset + offset); +if (!S_ISDIR (CRAMFS_16 (inode->mode))) { +/* It's not a directory - list it, and that's that */ +return (cramfs_list_inode (info, offset) >0 ); + } + +/* It's a directory. List files within */ + offset =CRAMFS_GET_OFFSET (inode) <<2 ; + size =CRAMFS_24 (inode->size); + } + +/* List the given directory */ +while (inodeoffset < size) { + inode = (struct cramfs_inode *) (info->offset + offset + inodeoffset); + + nextoffset =cramfs_list_inode (info, offset + inodeoffset); +if (nextoffset ==0 ) +break ; + inodeoffset +=sizeof (struct cramfs_inode ) + nextoffset; + } + +return 1 ; +} + +int cramfs_info (struct part_info *info) +{ +if (cramfs_read_super (info)) +return 0 ; + +printf ("size: 0x%x (%u)\n" , super.size, super.size); + +if (super.flags !=0 ) + { +printf ("flags:\n" ); +if (super.flags &CRAMFS_FLAG_FSID_VERSION_2 ) +printf ("\tFSID version 2\n" ); +if (super.flags &CRAMFS_FLAG_SORTED_DIRS ) +printf ("\tsorted dirs\n" ); +if (super.flags &CRAMFS_FLAG_HOLES ) +printf ("\tholes\n" ); +if (super.flags &CRAMFS_FLAG_SHIFTED_ROOT_OFFSET ) +printf ("\tshifted root offset\n" ); + } + +printf ("fsid:\n\tcrc: 0x%x\n\tedition: 0x%x\n" , + super.fsid.crc, super.fsid.edition); +printf ("name: %16s\n" , super.name); + +return 1 ; +} + +int cramfs_check (struct part_info *info) +{ +struct cramfs_super *sb = (struct cramfs_super *)info->offset; + +if (sb->magic !=CRAMFS_32 (CRAMFS_MAGIC )) { +/* check at 512 byte offset */ + sb = (struct cramfs_super *)(info->offset +512 ); +if (sb->magic !=CRAMFS_32 (CRAMFS_MAGIC )) { +return 0 ; + } + } +return 1 ; +} + +#endif /* CFG_FS_CRAMFS */
fs/cramfs/cramfs_fs.h new file +133 -0
133 lines not on this page · raw message
fs/cramfs/Makefile new file +47 -0
47 lines not on this page · raw message
fs/cramfs/uncompress.c new file +107 -0
107 lines not on this page · raw message
fs/Makefile renamed from fs/Makefile~cramfs +1 -1
@@ -22,7 +22,7 @@ # # -SUBDIRS := jffs2 fdos fat +SUBDIRS := jffs2 cramfs fdos fat .depend all: @for dir in $(SUBDIRS) ; do \
include/cramfs/cramfs_fs.h new file +98 -0
98 lines not on this page · raw message
include/cramfs/cramfs_fs_sb.h new file +19 -0
@@ -0,0 +1,19 @@ +#ifndef _CRAMFS_FS_SB +#define _CRAMFS_FS_SB + +/* +* cramfs super-block data in memory +*/ +struct cramfs_sb_info { +unsigned long magic; +unsigned long size; +unsigned long blocks; +unsigned long files; +unsigned long flags; +#ifdef CONFIG_CRAMFS_LINEAR +unsigned long linear_phys_addr; +char * linear_virt_addr; +#endif +}; + +#endif
common/cmd_jffs2.c renamed from common/cmd_jffs2.c~cramfs +47 -12
121 lines not on this page · raw message
fs/jffs2/jffs2_1pass.c renamed from fs/jffs2/jffs2_1pass.c~cramfs +2 -2
@@ -106,8 +106,8 @@* * You still should have paper bags at hand :-(. The code lacks more or less * any comment, and is still arcane and difficult to read in places. As this -* is incompatible with any new code from the jffs2 maintainers anyway, it -* should probably be dumped and replaced by something like jffs2reader! +* might be incompatible with any new code from the jffs2 maintainers anyway, +* it should probably be dumped and replaced by something like jffs2reader! */
PATCH 6/6 cramfs
Quoted 4 lines · In message <[email protected]> you wrote:
# Author: Robert Schwebel <[email protected]>
#
# Description: Patch by Kai-Uwe Bloem: add support for cramfs.
Added.
Please:
- remove trailing white space (fs/cramfs/Makefile)
- don't use C++ stype comments (fs/cramfs/uncompress.c)
Ummm... we now have some duplicated code (like mkmodestr() in fs/jffs2/jffs2_1pass.c and fs/cramfs/cramfs.c, etc.). Can you pleae reorganize / cleanup this?
Best regards,
Wolfgang Denk
Signature · 4 lines
Software Engineering: Embedded and Realtime Systems, Embedded Linux Phone: (+49)-8142-4596-87 Fax: (+49)-8142-4596-88 Email: wd at denx.de The human mind ordinarily operates at only ten percent of its capacity. The rest is overhead for the operating system.