📄 mk_romfs.c
字号:
DIR *dh;
struct dirent *e;
node **last_p = &mynode->child;
node *th;
int was_hardlinked;
if ( (dh = opendir( mynode->path )) == NULL ) {
perror(mynode->path);
return;
}
verb_printf(VERB_EXCESSIVE, "Construct directory '%s'(%d):\n",
mynode->path, mynode->nodenum );
// Add . & .. here because they MUST be present in the image
AddDirEntry( ".", mynode, mynode->nodenum );
AddDirEntry( "..", mynode, p_node );
while ( (e = readdir( dh )) ) {
// Ignore . & .. here because they MAY NOT be in the host filesystem
if ( strcmp(e->d_name,".") && strcmp(e->d_name,"..") ) {
th = GetNodeInfo( mynode->path, e->d_name, &was_hardlinked );
AddDirEntry( e->d_name, mynode, th->nodenum );
if ( !was_hardlinked ) {
verb_printf( VERB_EXCESSIVE, "\t\tNew node %d for entry '%s'\n", th->nodenum, e->d_name);
*last_p = th;
last_p = &th->sibling;
} else {
verb_printf( VERB_EXCESSIVE, "\t\tRe-used node %d for entry '%s'\n", th->nodenum, e->d_name);
}
}
}
closedir( dh );
verb_printf(VERB_EXCESSIVE,"Completed '%s'. Checking for child directories...\n", mynode->path);
for ( th = mynode->child ; th ; th = th->sibling ) {
if ( IS_DIRECTORY( th->st_mode ) ) {
mynode->nlink++;
ScanDirectory( th, mynode->nodenum );
}
}
}
static void AllocateSpaceToDirectories( node *first ) {
node *np;
for ( np = first ; np ; np = np->sibling ) {
if ( IS_DIRECTORY( np->st_mode ) ) {
// The first node is a directory. Add its data
np->offset = coffset;
np->entry_size = ALIGN_TO( np->size, DIRECTORY_ALIGN );
coffset += np->entry_size;
verb_printf( VERB_MAX, "\t\tnode %5d : 0x%06lX (+0x%05X)\n",
np->nodenum, np->offset, np->entry_size );
// Link this node into the write order chain.
// For node 0 (the root), this will overwrite the first pointer with itself
*last_p = np;
last_p = &np->next_in_rom;
}
}
// Now add any child directories
for ( np = first ; np ; np = np->sibling ) {
if ( IS_DIRECTORY( np->st_mode ) && np->child )
AllocateSpaceToDirectories( np->child );
}
}
static void AllocateSpaceToDataFiles( node *first ) {
node *np;
// There are two loops below. It CAN be done in just one, but this re-orders
// the file positions in relation to their inode numbers. To keep it simple
// to check, allocation takes place in the first loop, recursion in the second
// Search for child data files
for ( np = first->child ; np ; np = np->sibling ) {
if ( IS_DATAFILE( np->st_mode ) || IS_SYMLINK( np->st_mode ) ) {
np->offset = coffset;
np->entry_size = ALIGN_TO( np->size, DATA_ALIGN );
coffset += np->entry_size;
// Link in to the rom write order list
*last_p = np;
last_p = &np->next_in_rom;
verb_printf( VERB_MAX, "\t\tnode %5d : 0x%06lX (+0x%05X)\n",
np->nodenum, np->offset, np->entry_size );
}
}
// Recurse into sub-directories
for ( np = first->child ; np ; np = np->sibling ) {
if ( IS_DIRECTORY( np->st_mode ) ) {
AllocateSpaceToDataFiles( np );
}
}
}
static void AllocateSpaceToExecutables( node *first ) {
node *np;
// The first node is a directory. Don't bother with that...
// Search for child executables
for ( np = first->child ; np ; np = np->sibling ) {
if ( IS_EXECUTABLE( np->st_mode ) ) {
np->offset = coffset;
np->entry_size = ALIGN_TO( np->size, EXEC_ALIGN );
coffset += np->entry_size;
// Link in to the rom write order list
*last_p = np;
last_p = &np->next_in_rom;
verb_printf( VERB_MAX, "\t\tnode %5d : 0x%06lX (+0x%05X)\n",
np->nodenum, np->offset, np->entry_size );
}
}
// Recurse into sub-directories
for ( np = first->child ; np ; np = np->sibling ) {
if ( IS_DIRECTORY( np->st_mode ) ) {
AllocateSpaceToExecutables( np );
}
}
}
static void WriteNode( int fd, node *np ) {
romfs_node anode;
char padhere[9];
outputlong( (char*) &anode.mode, ConvertMode( np->st_mode ) );
outputlong( (char*) &anode.nlink, np->nlink );
outputshort((char*) &anode.uid, np->uid );
outputshort((char*) &anode.gid, np->gid );
outputlong( (char*) &anode.size, np->size );
outputlong( (char*) &anode.ctime, np->ctime );
outputlong( (char*) &anode.data_offset, np->offset );
sprintf( padhere, "<%6d>", np->nodenum );
memcpy( anode.pad, padhere, 8 );
if ( dowrite && write( fd, (void*)&anode, sizeof(anode) ) != sizeof(anode) )
fatal_error(EXIT_WRITE, "Error writing node %d (%s): %s\n", np->nodenum, np->path, strerror(errno) );
}
static int WriteNodeAndSiblings( int fd, int nodenum, node *first ) {
node *np;
for ( np = first ; np ; np = np->sibling ) {
if ( np->nodenum != nodenum++ ) {
fatal_error(EXIT_BUG, "BUG: Out of sequence node number; got %d, expected %d\n", np->nodenum, nodenum-1);
}
WriteNode( fd, np );
}
for ( np = first ; np ; np = np->sibling ) {
if ( IS_DIRECTORY( np->st_mode ) && np->child ) {
nodenum = WriteNodeAndSiblings( fd, nodenum, np->child );
}
}
return nodenum;
}
static void WriteNodeTable( int fd ) {
romfs_disk header;
int wnodes;
outputlong( (char*) &header.magic, ROMFS_MAGIC );
outputlong( (char*) &header.nodecount, nodes );
outputlong( (char*) &header.disksize, coffset );
outputlong( (char*) &header.dev_id, 0x01020304 );
strcpy( header.name, "ROMFS v1.0" );
if ( dowrite && write( fd, (void*)&header, sizeof(header) ) != sizeof(header) )
fatal_error(EXIT_WRITE, "Error writing ROMFS header: %s\n", strerror(errno) );
if ( (wnodes = WriteNodeAndSiblings( fd, 0, first )) != nodes ) {
fatal_error(EXIT_BUG, "BUG: Lost/gained some nodes; wrote %d, expected %d\n", wnodes, nodes );
}
}
#ifndef O_BINARY
#define O_BINARY 0
#endif
static void WriteData( int fd, node *np ) {
char newpath[1024];
int ffd;
unsigned long todo;
if ( IS_SYMLINK( np->st_mode ) ) {
if ( (ffd = readlink( np->path, newpath, sizeof(newpath) )) < 0 )
fatal_error(EXIT_FILESYS, "Error reading symlink \"%s\": %s\n", np->path, strerror(errno) );
if ( !dowrite ) return;
if ( lseek( fd, np->offset, SEEK_SET ) != np->offset )
fatal_error(EXIT_SEEK, "Error seeking to offset 0x%lX: %s\n", np->offset, strerror(errno) );
if ( write( fd, newpath, ffd ) != ffd )
fatal_error(EXIT_WRITE, "Write error: %s\n", strerror(errno) );
return;
}
if ( (ffd=open(np->path, O_RDONLY | O_BINARY )) < 0 )
fatal_error(EXIT_FILESYS, "Error opening \"%s\": %s\n", np->path, strerror(errno) );
if ( dowrite && lseek( fd, np->offset, SEEK_SET ) != np->offset )
fatal_error(EXIT_SEEK, "Error seeking to offset 0x%lX: %s\n", np->offset, strerror(errno) );
todo = np->size;
while ( todo >= 1024 ) {
if ( read( ffd, newpath, 1024 ) != 1024 )
fatal_error(EXIT_FILESYS, "Error reading file \"%s\" at offset 0x%lX: %s\n", np->path, np->size - todo, strerror(errno) );
if ( dowrite && write( fd, newpath, 1024 ) != 1024 )
fatal_error(EXIT_WRITE, "Write error: %s\n", strerror(errno) );
todo -= 1024;
}
if ( todo ) {
if ( read( ffd, newpath, todo ) != todo )
fatal_error(EXIT_FILESYS, "Error reading file \"%s\" at offset 0x%lX: %s\n", np->path, np->size - todo, strerror(errno) );
if ( dowrite && write( fd, newpath, todo ) != todo )
fatal_error(EXIT_WRITE, "Write error: %s\n", strerror(errno) );
}
close(ffd);
}
static void WriteDataBlocks( int fd, node *first ) {
for ( ; first ; first = first->next_in_rom ) {
if ( dowrite && lseek( fd, first->offset, SEEK_SET ) != first->offset )
fatal_error(EXIT_SEEK, "Error seeking to offset 0x%lX: %s\n", first->offset, strerror(errno) );
if ( IS_DIRECTORY( first->st_mode ) ) {
if ( dowrite && write( fd, first->entry, first->size ) != first->size )
fatal_error(EXIT_WRITE, "Write error: %s\n", strerror(errno) );
} else {
WriteData( fd, first );
}
}
}
static void usage(void) {
fprintf(stderr,"\n%s - Create an eCos ROMFS disk image from the files\n",prog);
fprintf(stderr,"%*s contained under a specified directory\n\n", strlen(prog), "");
fprintf(stderr,"Usage: %s [options] <fs_root> <fs_file>\n", prog);
fprintf(stderr," fs_root is the directory containing the files to package into the ROMFS image\n");
fprintf(stderr," fs_file is the name of the ROMFS image file to create\n");
fprintf(stderr," Options include:\n");
fprintf(stderr," -v / -q increase / decrease verbosity\n");
fprintf(stderr," -n do everything EXCEPT creating the output file\n");
fprintf(stderr," -b write a big-endian image (default is little endian)\n");
fprintf(stderr," -l collapse hard links to a single node\n");
fprintf(stderr,"\n");
exit(EXIT_ARGS);
}
int main(int ac, char *av[]) {
int dummy;
prog = av[0];
// Check structure sizes
if (sizeof(romfs_node) != 32) {
fatal_error(EXIT_COMPILE , "Size of romfs_node is %d, NOT 32\n", sizeof(romfs_node) );
} else if (sizeof(romfs_dirent) != 8) {
fatal_error(EXIT_COMPILE , "Size of romfs_dirent is %d, NOT 8\n", sizeof(romfs_dirent) );
} else if (sizeof(romfs_disk) != 32) {
fatal_error(EXIT_COMPILE , "Size of romfs_disk is %d, NOT 32\n", sizeof(romfs_disk) );
}
// Parse option arguments
while ( ac > 1 && av[1][0] == '-' ) {
char *o = &av[1][1];
for ( ; *o ; o++ ) {
switch ( *o ) {
case 'q' :
verbose--;
break;
case 'v' :
verbose++;
break;
case 'n' :
dowrite = 0;
break;
case 'b' :
bigendian = 1;
break;
case 'l' :
hardlinks = 1;
break;
default :
fprintf(stderr,"%s: Invalid flag -%c\n", prog, *o );
usage();
}
}
av++; ac--;
}
// Check remaining arguments
if ( ac != 3 ) usage();
verb_printf( VERB_MINIMUM, "%s: Verbosity %d %s%s endian\n",
prog, verbose,
dowrite ? "" : "no write, ",
bigendian ? "big" : "little" );
// Phase 1. Recursively scan the root directory for files and directories.
verb_printf(VERB_MINIMUM, "Phase 1 - Build file list\n");
first = GetNodeInfo( av[1], ".", &dummy ); // Initialize the root node entry.
ScanDirectory( first, 0 );
// Phase 2. Work out space allocations for filesystem
verb_printf(VERB_MINIMUM, "Phase 2 - Calculate space allocation\n");
coffset = sizeof(romfs_disk) + nodes * sizeof(romfs_node);
verb_printf(VERB_MAX,"\t\tnode table : 0x000000 (+0x%05lX) %d nodes\n", coffset, nodes );
// Phase 2a. Work out space allocations for the directories of the filesystem
verb_printf(VERB_SUB,"Phase 2a - * Directories\n");
coffset = ALIGN_TO( coffset, DIRECTORY_ALIGN );
AllocateSpaceToDirectories( first );
// Phase 2b. Work out space allocations for the data files of the filesystem
verb_printf(VERB_SUB,"Phase 2b - * Regular files\n");
coffset = ALIGN_TO( coffset, DATA_ALIGN );
AllocateSpaceToDataFiles( first );
// Phase 2c. Work out space allocations for the executable files of the filesystem
verb_printf(VERB_SUB,"Phase 2c - * Executable files\n");
coffset = ALIGN_TO( coffset, EXEC_ALIGN );
AllocateSpaceToExecutables( first );
// Round off the image size...
coffset = ALIGN_TO( coffset, EXEC_ALIGN );
// Phase 3. Write out the image file
verb_printf(VERB_MINIMUM, "Phase 3 - Construct ROMFS image file (%ld kb)\n", ALIGN_TO( coffset, 1024 )/1024);
if ( dowrite ) {
if ( (fd = open( av[2], O_WRONLY|O_CREAT|O_TRUNC|O_BINARY, 0666 )) < 0 ) {
fatal_error(EXIT_WRITE,"Failed to open output file '%s', errno=%d\n", av[2], errno );
}
} else {
verb_printf(VERB_NONE," (No image is being written)\n");
}
verb_printf(VERB_SUB,"Phase 3a - * Node table\n");
WriteNodeTable( fd );
verb_printf(VERB_SUB,"Phase 3b - * Data blocks\n");
WriteDataBlocks( fd, first );
if ( fd >= 0 ) close(fd);
verb_printf(VERB_MINIMUM, "%s completed\n", av[2] );
return 0;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -