[freenos] [freenos commit] r205 - LinnCreate now writes direct LinnInode blocks to the output image.

  • From: codesite-noreply@xxxxxxxxxx
  • To: freenos@xxxxxxxxxxxxx
  • Date: Tue, 07 Jul 2009 13:52:54 +0000

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 */

Other related posts:

  • » [freenos] [freenos commit] r205 - LinnCreate now writes direct LinnInode blocks to the output image. - codesite-noreply