mk_romfs.c
来自「eCos操作系统源码」· C语言 代码 · 共 735 行 · 第 1/2 页
C
735 行
//==========================================================================//// 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 architecturestypedef struct romfs_dirent { LONG node; // 4 LONG next; // 8 char name[0]; // 8 + strlen(name) + 1} romfs_dirent; // Aligns to next 32 byte boundarytypedef 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 heretypedef 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 nodetypedef 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 returnstatic void fatal_error( int exitcode, const char *fmt, ... ) \ __attribute__ (( noreturn,format (printf, 2, 3) ));// Use gcc format argument checking on this functionstatic 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 + =
减小字号Ctrl + -
显示快捷键?