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 + -
显示快捷键?