Author: nieklinnenbank Date: Tue Jul 7 06:51:52 2009 New Revision: 205 Modified: trunk/srv/filesystem/linn/LinnCreate.cpp trunk/srv/filesystem/linn/LinnCreate.h trunk/srv/filesystem/linn/LinnDump.cpp trunk/srv/filesystem/linn/LinnGroup.h trunk/srv/filesystem/linn/LinnInode.h Log: LinnCreate now writes direct LinnInode blocks to the output image. It reads input files from the directory specified with the -d argument, and creates a LinnInode for each file. The contents of the file are inserted but are currently limited to only direct block pointers. Additionally, the LINN_INODE_ROOT inode is unconditionally created. Modified: trunk/srv/filesystem/linn/LinnCreate.cpp ============================================================================== --- trunk/srv/filesystem/linn/LinnCreate.cpp (original) +++ trunk/srv/filesystem/linn/LinnCreate.cpp Tue Jul 7 06:51:52 2009 @@ -21,6 +21,8 @@ #include <String.h> #include <Types.h> #include <Macros.h> +#include <FileType.h> +#include <FileMode.h> #include "LinnCreate.h" #include "LinnSuperBlock.h" #include "LinnGroup.h" @@ -40,9 +42,210 @@ prog = ZERO; image = ZERO; super = ZERO; + input = ZERO; verbose = false; }+LinnInode * LinnCreate::createInode(le64 inodeNum, FileType type, FileModes mode,
+ UserID uid, GroupID gid) +{ + LinnGroup *group; + LinnInode *inode; + + /* Point to the correct group. */ + group = BLOCKPTR(LinnGroup, super->groupsTable); + group += inodeNum / super->inodesPerGroup; + + /* Use it to find the inode. */ + inode = BLOCKPTR(LinnInode, group->inodeTable); + inode += inodeNum % super->inodesPerGroup; + + /* Initialize the inode. */ + inode->type = type; + inode->mode = mode; + inode->uid = uid; + inode->gid = gid; + inode->accessTime = ZERO; + inode->createTime = time(NULL); + inode->modifyTime = inode->createTime; + inode->changeTime = inode->createTime; + inode->links = 1; + + /* Update superblock. */ + super->freeInodesCount--; + group->freeInodesCount--; + + /* Done. */ + return inode; +} + +le64 LinnCreate::createInode(char *inputFile, struct stat *st) +{ + LinnGroup *group; + LinnInode *inode; + BitMap *map; + u64 gn, in; + + /* Loop all available LinnGroups. */ + for (gn = 0; gn < LINN_GROUP_COUNT(super); gn++) + { + /* Point to the correct LinnGroup. */ + group = BLOCKPTR(LinnGroup, super->groupsTable) + gn; + + /* Does it have any free inodes? */ + if (!group->freeInodesCount) + { + group = ZERO; + continue; + } + else + break; + } + /* Did we find an appropriate group? */ + if (!group) + { + printf("%s: no free inode available for `%s'\n", + prog, inputFile); + exit(EXIT_FAILURE); + } + /* Find an empty inode number. */ + map = new BitMap(super->inodesPerGroup, + BLOCKPTR(u8, group->inodeMap)); + in = map->markNext(); + + /* Instantiate the inode. */ + inode = createInode(in, FILETYPE_FROM_ST(st), + FILEMODE_FROM_ST(st), st->st_uid, st->st_gid); + + /* Insert file contents. */ + if (S_ISREG(st->st_mode)) + { + insertFile(inputFile, inode, st); + } + /* Debug out. */ + if (verbose) + { + printf("%s inode=%llu size=%llu\n", inputFile, in, inode->size); + } + return in; +} + +void LinnCreate::insertFile(char *inputFile, LinnInode *inode, + struct stat *st) +{ + FILE *fp; + le64 blockNr; + bool reading = true; + + /* Open the local file. */ + if ((fp = fopen(inputFile, "r")) == NULL) + { + printf("%s: failed to fopen() `%s': %s\n", + prog, inputFile, strerror(errno)); + exit(EXIT_FAILURE); + } + /* Read blocks from the file. */ + while (reading) + { + /* Grab a block. */ + blockNr = BLOCK(super); + + /* Read a block. */ + if (fread(BLOCKPTR(u8, blockNr), super->blockSize, 1, fp) != 1) + { + /* End-of-file? */ + if (feof(fp)) + { + reading = false; + } + /* Read error occurred. */ + else + { + printf("%s: failed to fread() `%s': %s\n", + prog, inputFile, strerror(errno)); + exit(EXIT_FAILURE); + } + } + /* Insert the block (direct). */ + if (LINN_INODE_NUM_BLOCKS(super, inode) < + LINN_INODE_DIR_BLOCKS) + { + inode->block[LINN_INODE_NUM_BLOCKS(super,inode)] = blockNr; + } + /* Insert the block (indirect). */ + else + { + printf("%s: Indirect blocks not (yet) supported: `%s'.\n", + prog, inputFile); + break; + } + /* Increment size appropriately. */ + if (reading) + inode->size += super->blockSize; + else + inode->size += st->st_size % super->blockSize; + } + /* Cleanup. */ + fclose(fp); +} ++void LinnCreate::insertDirectory(char *inputDir, le64 inodeNum, le64 parentNum)
+{ + struct dirent *ent; + struct stat st; + DIR *dir; + char path[255]; + le64 child; + bool skip = false; + + /* Open the input directory. */ + if ((dir = opendir(inputDir)) == NULL) + { + printf("%s: failed to opendir() `%s': %s\n", + prog, inputDir, strerror(errno)); + exit(EXIT_FAILURE); + } + /* Read all it's entries. */ + while ((ent = readdir(dir))) + { + /* Skip hidden. */ + skip = ent->d_name[0] == '.'; + + /* Skip excluded. */ + for (ListIterator<String> e(&excludes); e.hasNext(); e++) + { + if (e.current()->match(ent->d_name, **e.current())) + { + skip = true; + break; + } + } + if (skip) continue; + + /* Construct local path. */ + snprintf(path, sizeof(path), "%s/%s", + inputDir, ent->d_name); + + /* Stat the file. */ + if (stat(path, &st) != 0) + { + printf("%s: failed to stat() `%s': %s\n", + prog, path, strerror(errno)); + exit(EXIT_FAILURE); + } + /* Create an inode for the child. */ + child = createInode(path, &st); + + /* Traverse down. */ + if (S_ISDIR(st.st_mode)) + { + insertDirectory(path, child, inodeNum); + } + } + /* All done. */ + closedir(dir); +} + int LinnCreate::create(Size blockSize, Size blockNum, Size inodeNum) { assert(image != ZERO); @@ -62,10 +265,10 @@ super->minorRevision = LINN_SUPER_MINOR; super->state = LINN_SUPER_VALID; super->blockSize = blockSize; - super->blocksPerGroup = LINNCREATE_BLOCKS_PER_GROUP; + super->blocksPerGroup = LINN_CREATE_BLOCKS_PER_GROUP; super->inodesCount = inodeNum; super->blocksCount = blockNum; - super->inodesPerGroup = super->inodesCount / LINNGROUP_COUNT(super); + super->inodesPerGroup = super->inodesCount / LINN_GROUP_COUNT(super); super->freeInodesCount = super->inodesCount; super->freeBlocksCount = blockNum - 2; super->creationTime = time(NULL); @@ -75,7 +278,7 @@ super->groupsTable = 2; /* Allocate LinnGroups. */ - for (Size i = 0; i < LINNGROUP_COUNT(super); i++) + for (Size i = 0; i < LINN_GROUP_COUNT(super); i++) { /* Point to the correct LinnGroup. */ LinnGroup *group = BLOCKPTR(LinnGroup, 2) + i; @@ -83,15 +286,27 @@ /* Fill the group. */ group->freeBlocksCount = super->blocksPerGroup; group->freeInodesCount = super->inodesPerGroup; - group->blockMap = BLOCKS(super, LINNGROUP_NUM_BLOCKMAP(super)); - group->inodeMap = BLOCKS(super, LINNGROUP_NUM_INODEMAP(super)); - group->inodeTable = BLOCKS(super, LINNGROUP_NUM_INODETAB(super)); + group->blockMap = BLOCKS(super, LINN_GROUP_NUM_BLOCKMAP(super)); + group->inodeMap = BLOCKS(super, LINN_GROUP_NUM_INODEMAP(super)); + group->inodeTable = BLOCKS(super, LINN_GROUP_NUM_INODETAB(super)); /* Increment counter. */ - super->freeBlocksCount -= LINNGROUP_NUM_BLOCKMAP(super) + - LINNGROUP_NUM_INODEMAP(super) + - LINNGROUP_NUM_INODETAB(super); + super->freeBlocksCount -= LINN_GROUP_NUM_BLOCKMAP(super) + + LINN_GROUP_NUM_INODEMAP(super) + + LINN_GROUP_NUM_INODETAB(super); + } + /* Create the root inode. */ + createInode(LINN_INODE_ROOT, DirectoryFile, + OwnerRWX | GroupRX | OtherRX); + + /* Insert into directory contents, if set. */ + if (input) + { + insertDirectory(input, LINN_INODE_ROOT, + LINN_INODE_ROOT); } + /* Mark block #0 -> super->blocksCount used. */ + /* Write the final image. */ return writeImage(); } @@ -149,9 +364,9 @@ int main(int argc, char **argv) { LinnCreate fs; - Size blockSize = LINNCREATE_BLOCK_SIZE; - Size blockNum = LINNCREATE_BLOCK_NUM; - Size inodeNum = LINNCREATE_INODE_NUM; + Size blockSize = LINN_CREATE_BLOCK_SIZE; + Size blockNum = LINN_CREATE_BLOCK_NUM; + Size inodeNum = LINN_CREATE_INODE_NUM; /* Verify command-line arguments. */ if (argc < 2) Modified: trunk/srv/filesystem/linn/LinnCreate.h ============================================================================== --- trunk/srv/filesystem/linn/LinnCreate.h (original) +++ trunk/srv/filesystem/linn/LinnCreate.h Tue Jul 7 06:51:52 2009 @@ -15,28 +15,29 @@ * along with this program. If not, see <http://www.gnu.org/licenses/>. */ -#ifndef __FILESYSTEM_LINNCREATE_H -#define __FILESYSTEM_LINNCREATE_H +#ifndef __FILESYSTEM_LINN_CREATE_H +#define __FILESYSTEM_LINN_CREATE_H #include <BitMap.h> #include <List.h> #include <String.h> #include "LinnSuperBlock.h" +#include "LinnInode.h" /** Default block size. */ -#define LINNCREATE_BLOCK_SIZE 2048 +#define LINN_CREATE_BLOCK_SIZE 2048 /** Default number of blocks to allocate. */ -#define LINNCREATE_BLOCK_NUM 8192 +#define LINN_CREATE_BLOCK_NUM 8192 /** Default number of data blocks per group descriptor. */ -#define LINNCREATE_BLOCKS_PER_GROUP 8192 +#define LINN_CREATE_BLOCKS_PER_GROUP 8192 /** Default number of inodes to allocate. */ -#define LINNCREATE_INODE_NUM 1024 +#define LINN_CREATE_INODE_NUM 1024 /** Default number of inodes per group descriptor. */ -#define LINNCREATE_INODES_PER_GROUP 1024 +#define LINN_CREATE_INODES_PER_GROUP 1024 /** * @brief Returns a pointer to the correct in-memory block. @@ -64,12 +65,12 @@ }) /** - * Retrieve on free block. + * Retrieve one free block. * @param sb LinnSuperBlock pointer. * @return Block number of a free block. */ #define BLOCK(sb) \ - BLOCKS(sb, 1) + BLOCKS(sb, ((u64)1)) /** * Class for creating new Linnenbank FileSystems. @@ -125,6 +126,38 @@ private: /** + * Creates an empty LinnInode. + * @param inodeNum Inode number. + * @param type Type of file. + * @param mode Access permissions. + * @param uid User identity. + * @param gid Group identity. + * @return LinnInode pointer. + */ + LinnInode * createInode(le64 inodeNum, FileType type, FileModes mode, + UserID uid = ZERO, GroupID gid = ZERO); + + /** + * Copies a local file contents into an LinnInode. + * @param inputFile Path to the local file to insert. + * @param st POSIX stat pointer for the local file. + * @return Inode number of the inserted file. + */ + le64 createInode(char *inputFile, struct stat *st); + + /** + * Inserts the given directory and it's childs to the filesystem image. + * @param inputFile Path to a local directory. + * @param inodeNum Inode number for the input directory. + * @param parentNum Inode number of our parent. + * @note This function is recursive. + */ + void insertDirectory(char *inputFile, le64 inodeNum, le64 parentNum); + + void insertFile(char *inputFile, LinnInode *inode, + struct stat *st); + + /** * Writes the final image to disk. * @return EXIT_SUCCESS if successfull and EXIT_FAILURE otherwise. */ @@ -155,4 +188,4 @@ u8 *blocks; }; -#endif /* __FILESYSTEM_LINNCREATE_H */ +#endif /* __FILESYSTEM_LINN_CREATE_H */ Modified: trunk/srv/filesystem/linn/LinnDump.cpp ============================================================================== --- trunk/srv/filesystem/linn/LinnDump.cpp (original) +++ trunk/srv/filesystem/linn/LinnDump.cpp Tue Jul 7 06:51:52 2009 @@ -174,7 +174,7 @@ return EXIT_FAILURE; } /* Dump group information. */ - for (Size i = 0; i < LINNGROUP_COUNT(&super); i++) + for (Size i = 0; i < LINN_GROUP_COUNT(&super); i++) { /* Read the LinnGroup. */ if (fread(&group, sizeof(group), 1, fp) != 1) @@ -198,11 +198,11 @@ group.freeBlocksCount, group.freeInodesCount, group.blockMap, - LINNGROUP_NUM_BLOCKMAP(&super), + LINN_GROUP_NUM_BLOCKMAP(&super), group.inodeMap, - LINNGROUP_NUM_INODEMAP(&super), + LINN_GROUP_NUM_INODEMAP(&super), group.inodeTable, - LINNGROUP_NUM_INODETAB(&super)); + LINN_GROUP_NUM_INODETAB(&super)); } /* Cleanup and terminate. */ fclose(fp); Modified: trunk/srv/filesystem/linn/LinnGroup.h ============================================================================== --- trunk/srv/filesystem/linn/LinnGroup.h (original) +++ trunk/srv/filesystem/linn/LinnGroup.h Tue Jul 7 06:51:52 2009 @@ -15,8 +15,8 @@ * along with this program. If not, see <http://www.gnu.org/licenses/>. */ -#ifndef __FILESYSTEM_LINNGROUP_H -#define __FILESYSTEM_LINNGROUP_H +#ifndef __FILESYSTEM_LINN_GROUP_H +#define __FILESYSTEM_LINN_GROUP_H #include <Types.h> @@ -31,13 +31,13 @@ */ /** Block index of the block bitmap. */ -#define LINNGROUP_BLOCK_BITMAP 0 +#define LINN_GROUP_BLOCK_BITMAP 0 /** Block index of the inode bitmap. */ -#define LINNGROUP_INODE_BITMAP 1 +#define LINN_GROUP_INODE_BITMAP 1 /** Block index of the inode table. */ -#define LINNGROUP_INODE_TABLE 2 +#define LINN_GROUP_INODE_TABLE 2 /** * @} @@ -54,7 +54,7 @@ * @param sb LinnSuperBlock pointer. * @return Number of LinnGroups in the filesystem. */ -#define LINNGROUP_COUNT(sb) \ +#define LINN_GROUP_COUNT(sb) \ ((sb)->blocksCount / (sb)->blocksPerGroup ? \ (sb)->blocksCount / (sb)->blocksPerGroup : 1) @@ -63,7 +63,7 @@ * @param sb LinnSuperBlock pointer. * @return Number of blocks needed for the blocks bitmap. */ -#define LINNGROUP_NUM_BLOCKMAP(sb) \ +#define LINN_GROUP_NUM_BLOCKMAP(sb) \ (u64)((sb)->blocksPerGroup / ((sb)->blockSize / sizeof(u64))) /** @@ -71,7 +71,7 @@ * @param sb LinnSuperBlock pointer. * @return Number of blocks needed for the inodes bitmap. */ -#define LINNGROUP_NUM_INODEMAP(sb) \ +#define LINN_GROUP_NUM_INODEMAP(sb) \ (u64)((sb)->inodesPerGroup / ((sb)->blockSize / sizeof(u64))) /** @@ -79,7 +79,7 @@ * @param sb LinnSuperBlock pointer. * @return Number of blocks needed for the inodes table. */ -#define LINNGROUP_NUM_INODETAB(sb) \ +#define LINN_GROUP_NUM_INODETAB(sb) \ (u64)((sb)->inodesPerGroup / ((sb)->blockSize / sizeof(LinnInode))) /** @@ -87,7 +87,7 @@ * @param sb LinnSuperBlock pointer. * @return Number of LinnGroups per block. */ -#define LINNGROUP_PER_BLOCK(sb) \ +#define LINN_GROUP_PER_BLOCK(sb) \ ((sb)->blockSize / sizeof(LinnGroup)) /** @@ -95,9 +95,9 @@ * @param sb LinnSuperBlock pointer. * @return Number of blocks required for LinnGroups. */ -#define LINNGROUP_BLOCKS(sb) \ - (LINNGROUP_COUNT(sb) / LINNGROUP_PER_BLOCK(sb) ? \ - LINNGROUP_COUNT(sb) / LINNGROUP_PER_BLOCK(sb) : 1) +#define LINN_GROUP_BLOCKS(sb) \ + (LINN_GROUP_COUNT(sb) / LINN_GROUP_PER_BLOCK(sb) ? \ + LINN_GROUP_COUNT(sb) / LINN_GROUP_PER_BLOCK(sb) : 1) /** * @} @@ -129,4 +129,4 @@ * @} */ -#endif /* __FILESYSTEM_LINNGROUP_H */ +#endif /* __FILESYSTEM_LINN_GROUP_H */ Modified: trunk/srv/filesystem/linn/LinnInode.h ============================================================================== --- trunk/srv/filesystem/linn/LinnInode.h (original) +++ trunk/srv/filesystem/linn/LinnInode.h Tue Jul 7 06:51:52 2009 @@ -15,33 +15,77 @@ * along with this program. If not, see <http://www.gnu.org/licenses/>. */ -#ifndef __FILESYSTEM_LINNINODE_H -#define __FILESYSTEM_LINNINODE_H +#ifndef __FILESYSTEM_LINN_INODE_H +#define __FILESYSTEM_LINN_INODE_H /** * @defgroup linn Linnenbank Filesystem (LinnFS) * @{ */ +/** + * @brief Special Inode Numbers + * @{ + */ + +/** Root inode. */ +#define LINN_INODE_ROOT 0 + +/** Boot loader inode. */ +#define LINN_INODE_LOADER 1 + +/** Bad blocks inode. */ +#define LINN_INODE_BAD 2 + +/** Journal inode. */ +#define LINN_INODE_JOURNAL 3 + +/** First non-reserved inode. */ +#define LINN_INODE_FIRST 4 + +/** + * @} + */ + /** - * @name Inode (in)direct block counts. + * @brief Inode (in)direct block counts. * @{ */ -/** Number of direct blocks. */ -#define LINN_NDIR_BLOCKS 12 +/** Direct blocks. */ +#define LINN_INODE_DIR_BLOCKS 5 /** Indirect blocks. */ -#define LINN_IND_BLOCK (LINN_NDIR_BLOCKS) +#define LINN_INODE_IND_BLOCKS (LINN_INODE_DIR_BLOCKS + 1) /** Double indirect blocks. */ -#define LINN_DIND_BLOCK (LINN_IND_BLOCK + 1) +#define LINN_INODE_DIND_BLOCKS (LINN_INODE_IND_BLOCKS + 1) /** Triple indirect blocks. */ -#define LINN_TIND_BLOCK (LINN_DIND_BLOCK + 1) +#define LINN_INODE_TIND_BLOCKS (LINN_INODE_DIND_BLOCKS + 1) + +/** Total number of block pointers in an LinnInode. */ +#define LINN_INODE_BLOCKS (LINN_INODE_TIND_BLOCKS + 1) -/** Total number of blocks in an Ext2Inode. */ -#define LINN_INODE_BLOCKS (LINN_TIND_BLOCK + 1) +/** + * @} + */ + +/** + * @brief Inode macros. + * @{ + */ + +/** + * Calculate the number of blocks used in an LinnInode. + * @param super LinnSuperBlock pointer. + * @param inode LinnInode pointer. + * @return Number of blocks used. + */ +#define LINN_INODE_NUM_BLOCKS(super,inode) \ + ((inode)->size % (super)->blockSize ? \ + (inode)->size / (super)->blockSize + 1 : \ + (inode)->size / (super)->blockSize) /** * @} @@ -52,16 +96,17 @@ */ typedef struct LinnInode { - le16 mode; /**< POSIX file mode. */ - le16 uid; /**< User Identity. */ - le16 gid; /**< Group Identity. */ - le64 size; /**< Size in bytes. */ - le64 atime; /**< Access time. */ - le64 ctime; /**< Creation time. */ - le64 mtime; /**< Modification time. */ - le16 links; /**< Links count. */ + le16 type:3; /**< Type of file, as an FileType. */ + le16 mode:13; /**< Access permissions, as an FileMode. */ + le16 uid; /**< User Identity. */ + le16 gid; /**< Group Identity. */ + le64 size; /**< Size in bytes. */ + le64 accessTime; /**< Access time. */ + le64 createTime; /**< Creation time. */ + le64 modifyTime; /**< Modification time. */ + le64 changeTime; /**< Status change timestamp. */ + le16 links; /**< Links count. */ le64 block[LINN_INODE_BLOCKS]; /**< Pointers to blocks. */ - le16 padding; /**< Padding for 64 bytes. */ } LinnInode; @@ -69,4 +114,4 @@ * @} */ -#endif /* __FILESYSTEM_LINNINODE_H */ +#endif /* __FILESYSTEM_LINN_INODE_H */