mk_romfs.c

来自「eCos操作系统源码」· C语言 代码 · 共 735 行 · 第 1/2 页

C
735
字号
    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#endifstatic 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 + =
减小字号Ctrl + -
显示快捷键?