📄 mk_romfs.c
字号:
//==========================================================================
//
// mk_romfs.c
//
// Create ROM file system image
//
//==========================================================================
//####ECOSGPLCOPYRIGHTBEGIN####
// -------------------------------------------
// This file is part of eCos, the Embedded Configurable Operating System.
// Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc.
//
// eCos 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 or (at your option) any later version.
//
// eCos 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 eCos; if not, write to the Free Software Foundation, Inc.,
// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
//
// As a special exception, if other files instantiate templates or use macros
// or inline functions from this file, or you compile this file and link it
// with other works to produce a work based on this file, this file does not
// by itself cause the resulting work to be covered by the GNU General Public
// License. However the source code for this file must still be made available
// in accordance with section (3) of the GNU General Public License.
//
// This exception does not invalidate any other reasons why a work based on
// this file might be covered by the GNU General Public License.
//
// Alternative licenses for eCos may be arranged by contacting Red Hat, Inc.
// at http://sources.redhat.com/ecos/ecos-license/
// -------------------------------------------
//####ECOSGPLCOPYRIGHTEND####
//==========================================================================
//#####DESCRIPTIONBEGIN####
//
// Author(s): richard.panton@3glab.com
// Contributors: richard.panton@3glab.com
// Date: 2000-07-25
// Purpose: ROM file system
// Description: This program creates a ROM file system image, suitable
// for use with the sample ROM file system implemented by
// this package.
// * CAUTION! * This is host code and can only be built
// in a host, e.g. Linux, environment.
//
//####DESCRIPTIONEND####
//==========================================================================
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <stdarg.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <dirent.h>
#include <fcntl.h>
#include <unistd.h>
#include <errno.h>
//==========================================================================
//
// CONFIGURABLE ITEMS HERE
//
//==========================================================================
// define LONG to be a four byte unsigned integer on the host
#define LONG unsigned long
// define SHORT to be a two byte unsigned integer on the host
#define SHORT unsigned short
// All data files should be aligned to this sized boundary (minimum probably 32)
#define DATA_ALIGN 32
// The data stored in a directory should be aligned to this size boundary
#define DIRECTORY_ALIGN 32
// All executable files should be aligned to this sized boundary (minimum probably 32)
#define EXEC_ALIGN 32
// Undefine this if the host filesystem does not support lstat()
#define HAS_LSTAT
//==========================================================================
// Return (n) aligned to the next (b) byte boundary
#define ALIGN_TO( n, b ) (( (n) + (b)-1 ) & ~((b)-1))
// Set the stat call to use
#ifdef HAS_LSTAT
#define get_status( p, b ) lstat( (p), (b) )
#else
#define get_status( p, b ) stat( (p), (b) )
#endif
// This is how we identify a directory from its mode
#define IS_DIRECTORY( m ) (S_ISDIR(m))
// This is how we identify a data file from its mode
#define IS_DATAFILE( m ) (S_ISREG(m) && ((m)&S_IXUSR) == 0 )
// This is how we identify an executable from its mode
#define IS_EXECUTABLE( m ) (S_ISREG(m) && ((m)&S_IXUSR) != 0 )
// This is how we identify a symbolic link from its mode
#define IS_SYMLINK( m ) (S_ISLNK(m))
#define ROMFS_MAGIC 0x526f6d2e
//=========================================================================
// EXIT CODES
#define EXIT_SUCCESS 0
#define EXIT_ARGS 1
#define EXIT_MALLOC 2
#define EXIT_FILESYS 3
#define EXIT_WRITE 4
#define EXIT_SEEK 5
#define EXIT_COMPILE 6
#define EXIT_BUG 7
// These are the structures we will build into the ROMFS image.
// The sizes of these structures should be fixed for all architectures
typedef struct romfs_dirent {
LONG node; // 4
LONG next; // 8
char name[0]; // 8 + strlen(name) + 1
} romfs_dirent; // Aligns to next 32 byte boundary
typedef struct romfs_node {
LONG mode; // 4
LONG nlink; // 8
SHORT uid; // 10
SHORT gid; // 12
LONG size; // 16
LONG ctime; // 20
LONG data_offset; // 24
char pad[8]; // 32
} romfs_node; // Next node begins here
typedef struct romfs_disk {
LONG magic; // 4
LONG nodecount; // 8
LONG disksize; // 12
LONG dev_id; // 16
char name[16]; // 32
} romfs_disk; // Nodes start here
// This is the holding structure for a node
typedef struct node {
const char *path; // Filename (inc. path) of a link to this node
size_t size; // Size of file/directory/link
mode_t st_mode; // Type and permissions
uid_t uid; // Owner id
gid_t gid; // Group id
time_t ctime; // File creation time
int nodenum; // Nodenumber of this node in the ROMFS image
dev_t device; // Device (for hardlink check)
ino_t inode; // Inode (for hardlink check)
int nlink; // [DIRECTORIES] Number of sub-directories [FILES] hard links
romfs_dirent *entry; // [DIRECTORIES] Points to an array of directory entries
int entry_size; // Size to be allocated to file (includes alignment bytes)
unsigned long offset; // Offset within ROMFS image of data
struct node *sibling; // Points to the next entry in this directory
struct node *child; // [DIRECTORIES] Points to any subdirectories
struct node *next_in_rom; // Next in ROMFS write order
struct node *next_multilink;// Next node that is multilinked
} node;
static int nodes = 0;
static char *prog;
static int verbose = 1;
static int dowrite = 1;
static int bigendian = 0;
static int hardlinks = 0;
static unsigned long coffset = 0;
static node * first = NULL;
static node ** last_p = &first;
static node * first_multilink = NULL;
static node ** last_multilink_p = &first_multilink;
static int fd = -1;
#define VERB_NONE 0
#define VERB_MINIMUM 1
#define VERB_SUB 2
#define VERB_MAX 3
#define VERB_EXCESSIVE 4
// Use gcc format argument checking on this function, which cannot return
static void fatal_error( int exitcode, const char *fmt, ... ) \ __attribute__ (( noreturn,format (printf, 2, 3) ));
// Use gcc format argument checking on this function
static void verb_printf( int level, const char *fmt, ... ) \ __attribute__ ((format (printf, 2, 3) ));
static void fatal_error( int exitcode, const char *fmt, ... ) {
va_list v;
va_start( v, fmt );
vfprintf( stderr, fmt, v );
exit(exitcode);
}
static void verb_printf( int level, const char *fmt, ... ){
if ( level <= verbose ) {
va_list v;
va_start( v,fmt );
vprintf(fmt, v);
}
}
static void *mymalloc( size_t size ) {
void *p = malloc(size);
if ( !p ) {
fatal_error( EXIT_MALLOC, "Out of memory allocating %d bytes\n", size );
}
return p;
}
static void myrealloc( void **o, size_t newsize ) {
if ( *o == NULL )
*o = mymalloc( newsize );
else if ( !(*o = realloc( *o, newsize )) ) {
fatal_error( EXIT_MALLOC, "Out of memory re-allocating %d bytes\n", newsize );
}
}
static void outputlong( unsigned char *b, unsigned long w ) {
if ( bigendian ) {
b[0] = (w>>24) & 0xff;
b[1] = (w>>16) & 0xff;
b[2] = (w>> 8) & 0xff;
b[3] = (w ) & 0xff;
} else {
b[3] = (w>>24) & 0xff;
b[2] = (w>>16) & 0xff;
b[1] = (w>> 8) & 0xff;
b[0] = (w ) & 0xff;
}
}
static void outputshort( unsigned char *b, unsigned short w ) {
if ( bigendian ) {
b[0] = (w>> 8) & 0xff;
b[1] = (w ) & 0xff;
} else {
b[1] = (w>> 8) & 0xff;
b[0] = (w ) & 0xff;
}
}
static unsigned long ConvertMode( unsigned long posix_mode ) {
unsigned long result = 0;
if ( S_ISDIR( posix_mode ) ) result |= 1<<0;
if ( S_ISCHR( posix_mode ) ) result |= 1<<1;
if ( S_ISBLK( posix_mode ) ) result |= 1<<2;
if ( S_ISREG( posix_mode ) ) result |= 1<<3;
if ( S_ISFIFO(posix_mode ) ) result |= 1<<4;
// We cannot create MQ, SEM, or SHM entries here
if ( posix_mode & S_IRUSR ) result |= 1<<16;
if ( posix_mode & S_IWUSR ) result |= 1<<17;
if ( posix_mode & S_IXUSR ) result |= 1<<18;
if ( posix_mode & S_IRGRP ) result |= 1<<19;
if ( posix_mode & S_IWGRP ) result |= 1<<20;
if ( posix_mode & S_IXGRP ) result |= 1<<21;
if ( posix_mode & S_IROTH ) result |= 1<<22;
if ( posix_mode & S_IWOTH ) result |= 1<<23;
if ( posix_mode & S_IXOTH ) result |= 1<<24;
if ( posix_mode & S_ISUID ) result |= 1<<25;
if ( posix_mode & S_ISGID ) result |= 1<<26;
return result;
}
static const char *AddDirEntry( const char *name, node *parent_node, int node_num ) {
int this_size = ((strlen(name) + 4 + 4 + 1) + 31) & ~31;
int start = parent_node->size;
romfs_dirent *g;
myrealloc( (void**)&parent_node->entry, (parent_node->size += this_size) );
g = (romfs_dirent *)((unsigned char *)parent_node->entry + start);
memset( (void*)g, '\0', this_size );
outputlong( (char*)&g->node, node_num);
outputlong( (char*)&g->next, parent_node->size);
strcpy(g->name,name);
verb_printf( VERB_MAX, "\t%s --> node %d\n", name, node_num );
return (const char *)g->name;
}
extern int errno;
static node * FindLink( dev_t d, ino_t i ) {
// See if the node has been previously included by checking the device/inode
// combinations of all known multi-linked nodes
node *np = first_multilink;
for ( ; np ; np = np->next_multilink ) {
if ( np->device == d && np->inode == i )
return np;
}
return NULL;
}
static node * GetNodeInfo( const char *path, const char *name, int *hlink ) {
char newpath[1024];
node *node, *lnode;
struct stat stbuff;
sprintf(newpath,"%s/%s",path,name);
if ( (get_status(newpath,&stbuff)) < 0 ) {
fatal_error(EXIT_FILESYS, "stat(%s) failed: %s\n", newpath, strerror(errno));
}
if ( !(stbuff.st_mode & S_IRUSR) ) {
fatal_error(EXIT_FILESYS, "\"%s\" is not readable\n", newpath );
}
if ( hardlinks && S_ISREG( stbuff.st_mode ) && stbuff.st_nlink > 1 ) {
// See if this node has already been loaded
lnode = FindLink( stbuff.st_dev, stbuff.st_ino );
if ( lnode ) {
lnode->nlink++;
*hlink = 1;
return lnode; // Return the found link instead
}
// Create a new node
node = mymalloc( sizeof(struct node) );
// Incorporate the new link into the 'multi-linked' node list
*last_multilink_p = node;
last_multilink_p = &node->next_multilink;
} else {
// Create a new node
node = mymalloc( sizeof(struct node) );
}
node->path = strdup( newpath );
// We re-calculate the size for directories
node->size = IS_DIRECTORY( stbuff.st_mode ) ? 0 : stbuff.st_size;
node->st_mode = stbuff.st_mode;
node->uid = stbuff.st_uid;
node->gid = stbuff.st_gid;
node->ctime = stbuff.st_ctime;
node->nodenum = nodes++;
node->device = stbuff.st_dev;
node->inode = stbuff.st_ino;
// We always re-calculate the number of links
node->nlink = IS_DIRECTORY( stbuff.st_mode ) ? 2 : 1;
node->entry = NULL;
node->entry_size = 0;
node->offset = 0;
node->sibling = NULL;
node->child = NULL;
node->next_in_rom = NULL;
node->next_multilink = NULL;
*hlink = 0;
return node;
}
static void ScanDirectory(node *mynode, int p_node) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -