⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 mk_romfs.c

📁 eCos/RedBoot for勤研ARM AnywhereII(4510) 含全部源代码
💻 C
📖 第 1 页 / 共 2 页
字号:

    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 + -