[freenos] [freenos commit] r221 - LinnCreate: Implemented -s to strip(1) executable input files.

  • From: codesite-noreply@xxxxxxxxxx
  • To: freenos@xxxxxxxxxxxxx
  • Date: Fri, 10 Jul 2009 05:41:10 +0000

Author: nieklinnenbank
Date: Thu Jul  9 22:40:09 2009
New Revision: 221

Modified:
   trunk/site_scons/linn.py
   trunk/srv/filesystem/linn/LinnCreate.cpp
   trunk/srv/filesystem/linn/LinnCreate.h

Log:
LinnCreate: Implemented -s to strip(1) executable input files.
This reduces the size of the output image from ~2MB to ~400KB.


Modified: trunk/site_scons/linn.py
==============================================================================
--- trunk/site_scons/linn.py    (original)
+++ trunk/site_scons/linn.py    Thu Jul  9 22:40:09 2009
@@ -24,7 +24,7 @@
 def generateLinnFS(target=None, source=None, env=None):

     os.system("srv/filesystem/linn/host/create boot/boot.linn" \
- " -d . -n 16384 -e '*.cpp' -e '*.h' -e '*.c' -e '*.o' -e 'lib*' -e 'doc' " \ + " -d . -s -n 16384 -e '*.cpp' -e '*.h' -e '*.c' -e '*.o' -e 'lib*' -e 'doc' " \
              " -e 'SCons*' -e '*.a' -e '*.S' -e '*.ld' -e 'boot*'")
     os.system("gzip -f boot/boot.linn")


Modified: trunk/srv/filesystem/linn/LinnCreate.cpp
==============================================================================
--- trunk/srv/filesystem/linn/LinnCreate.cpp    (original)
+++ trunk/srv/filesystem/linn/LinnCreate.cpp    Thu Jul  9 22:40:09 2009
@@ -35,6 +35,8 @@
 #include <string.h>
 #include <errno.h>
 #include <libgen.h>
+#include <unistd.h>
+#include <fcntl.h>
 #include <sys/types.h>
 #include <sys/stat.h>

@@ -45,6 +47,7 @@
     super     = ZERO;
     input     = ZERO;
     verbose   = false;
+    strip     = false;
 }

 LinnInode * LinnCreate::createInode(le32 inodeNum, FileType type,
@@ -138,6 +141,54 @@
     return in;
 }

+bool LinnCreate::openFile(char *inputFile, struct stat *st, int *fd)
+{
+    int tmp, bytes, total = 0;
+    char buf[1024];
+
+    /* Open the local file. */
+    if ((*fd = open(inputFile, O_RDONLY)) < 0)
+    {
+       printf("%s: failed to fopen() `%s': %s\n",
+               prog, inputFile, strerror(errno));
+       exit(EXIT_FAILURE);
+    }
+    /* Attempt to strip(1) the file. */
+    if (strip && S_ISREG(st->st_mode) && st->st_mode & S_IXUSR)
+    {
+       strncpy(inputFile, "execXXXXXX", 11);
+
+       /* Open temporary file. */
+       if ((tmp = mkstemp(inputFile)) == -1)
+       {
+           printf("%s: failed to mkstemp() for `%s': %s\n",
+                   prog, inputFile, strerror(errno));
+           exit(EXIT_FAILURE);
+       }
+       /* Copy contents. */
+       while ((bytes = read(*fd, buf, sizeof(buf))) > 0)
+       {
+           write(tmp, buf, bytes);
+           total += bytes;
+       }
+       /* Switch file descriptor. */
+       close(*fd);
+       close(tmp);
+       
+       /* Now attempt to strip it. */
+       snprintf(buf, sizeof(buf), "strip '%s' &> /dev/null", inputFile);
+       system(buf);
+       
+       /* Reopen. */
+       *fd = open(inputFile, O_RDONLY);
+       
+       /* Update file information. */
+       st->st_size = total;
+       return true;
+    }
+    return false;
+}
+
 void LinnCreate::insertIndirect(le32 *ptr, le32 blockNumber,
                                le32 blockValue, Size depth)
 {
@@ -172,39 +223,30 @@
 void LinnCreate::insertFile(char *inputFile, LinnInode *inode,
                            struct stat *st)
 {
-    FILE *fp;
+    int fd, bytes;
     le32 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);
-    }
+    bool stripped;
+    char *tmpPath = strdup(inputFile);
+
+    /* Get file handle. */
+    stripped = openFile(tmpPath, st, &fd);
+
     /* Read blocks from the file. */
-    while (reading)
+    while (true)
     {
        /* Grab a block. */
        blockNr = BLOCK(super);

        /* Read a block. */
-       if (fread(BLOCKPTR(u8, blockNr), super->blockSize, 1, fp) != 1)
+       if ((bytes = read(fd, BLOCKPTR(u8, blockNr), super->blockSize)) < 0)
        {
-           /* 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);
-           }
+           printf("%s: failed to read() `%s': %s\n",
+                   prog, inputFile, strerror(errno));
+           exit(EXIT_FAILURE);
        }
+       /* End of file? */
+       if (!bytes) break;
+       
        /* Insert the block (direct). */
        if (LINN_INODE_NUM_BLOCKS(super, inode) <
            LINN_INODE_DIR_BLOCKS)
@@ -246,13 +288,11 @@
            break;
        }
        /* Increment size appropriately. */
-       if (reading)
-           inode->size += super->blockSize;
-       else
-           inode->size += st->st_size % super->blockSize;
+       inode->size += bytes;
     }
     /* Cleanup. */
-    fclose(fp);
+    close(fd);
+    if (stripped) unlink(tmpPath);
 }

 void LinnCreate::insertEntry(le32 dirInode, le32 entryInode,
@@ -502,6 +542,11 @@
     this->verbose = newVerbose;
 }

+void LinnCreate::setStrip(bool newStrip)
+{
+    this->strip = newStrip;
+}
+
 int main(int argc, char **argv)
 {
     LinnCreate fs;
@@ -519,6 +564,7 @@
               " -v           Output verbose messages.\r\n"
" -d DIRECTORY Insert files from the given directory into the image\r\n" " -e PATTERN Exclude matching files from the created filesystem\r\n"
+              " -s           Use strip(1) on executable input files.\r\n"
               " -b SIZE      Specifies the blocksize in bytes.\r\n"
               " -n COUNT     Specifies the maximum number of blocks.\r\n"
               " -i COUNT     Specifies the number of inodes to allocate.\r\n",
@@ -548,6 +594,11 @@
        {
            fs.setInput(argv[i + 3]);
            i++;
+       }
+       /* Strip executable files. */
+       else if (!strcmp(argv[i + 2], "-s"))
+       {
+           fs.setStrip(true);
        }
        /* Block size. */
        else if (!strcmp(argv[i + 2], "-b") && i < argc - 3)

Modified: trunk/srv/filesystem/linn/LinnCreate.h
==============================================================================
--- trunk/srv/filesystem/linn/LinnCreate.h      (original)
+++ trunk/srv/filesystem/linn/LinnCreate.h      Thu Jul  9 22:40:09 2009
@@ -123,6 +123,12 @@
         */
        void setVerbose(bool newVerbose);

+       /**
+        * Invoke strip(1) on executable input files.
+        * @param newStrip True to enable stripping, false to disable.
+        */
+       void setStrip(bool newStrip);
+
     private:

        /**
@@ -146,6 +152,15 @@
        le32 createInode(char *inputFile, struct stat *st);

        /**
+        * Opens the given input file. Optionally strips the input file.
+        * @param inputFile Path to the file to open.
+        * @param st File information.
+        * @param fd Pointer to file handle buffer.
+        * @return True if stripped, false if not.
+        */
+       bool openFile(char *inputFile, struct stat *st, int *fd);
+
+       /**
         * Inserts an LinnDirectoryEntry to the given directory inode.
         * @param dirInode Inode number of the directory.
         * @param entryInode Inode number of the entry to create.
@@ -201,6 +216,9 @@

        /** Output verbose messages. */
        bool verbose;
+       
+       /** Strip executable files. */
+       bool strip;

        /** List of file patterns to ignore. */
        List<String> excludes;

Other related posts:

  • » [freenos] [freenos commit] r221 - LinnCreate: Implemented -s to strip(1) executable input files. - codesite-noreply