Subversion Repositories QNX 8.QNX8 IFS tool

Rev

Rev 20 | Rev 22 | Go to most recent revision | Show entire file | Ignore whitespace | Details | Blame | Last modification | View Log | RSS feed

Rev 20 Rev 21
Line 4... Line 4...
4
// TODO: startup file stripping
4
// TODO: startup file stripping
5
// TODO: kernel file stripping
-
 
6
// TODO: boot script compiler
5
// TODO: boot script compiler
7
 
6
 
8
// standard C includes
7
// standard C includes
9
#include <stdint.h>
8
#include <stdint.h>
10
#include <stdbool.h>
9
#include <stdbool.h>
Line 94... Line 93...
94
   bool should_allow_nonexistent_files; // [+|-optional] whether to continue processing on unexistent files
93
   bool should_allow_nonexistent_files; // [+|-optional] whether to continue processing on unexistent files
95
   bool is_bootstrap_file; // entry has the [virtual] attribute
94
   bool is_bootstrap_file; // entry has the [virtual] attribute
96
   bool is_compiled_bootscript; // entry has [+script] attribute
95
   bool is_compiled_bootscript; // entry has [+script] attribute
97
   int extra_ino_flags; // bitmap of extra inode flags (IFS_INO_xxx)
96
   int extra_ino_flags; // bitmap of extra inode flags (IFS_INO_xxx)
98
   char *search; // [search=path[:path]] binary search path (the default one will be constructed at startup)
97
   char *search; // [search=path[:path]] binary search path (the default one will be constructed at startup)
99
 
-
 
100
 
98
 
101
   buffer_t data; // the resolved file's own data bytes
99
   buffer_t data; // the resolved file's own data bytes
102
} parms_t;
100
} parms_t;
103
 
101
 
104
 
102
 
Line 136... Line 134...
136
// bootable IFS support
134
// bootable IFS support
137
static char *bootfile_pathname = NULL;           // HACK: pathname to bootcode binary blob file to put at the start of a bootable IFS
135
static char *bootfile_pathname = NULL;           // HACK: pathname to bootcode binary blob file to put at the start of a bootable IFS
138
static size_t bootfile_size = 0;                 // HACK: size of the bootcode binary blob file to put at the start of a bootable IFS
136
static size_t bootfile_size = 0;                 // HACK: size of the bootcode binary blob file to put at the start of a bootable IFS
139
static char *startupfile_pathname = NULL;        // HACK: pathname to precompiled startup file blob to put in the startup header of a bootable IFS
137
static char *startupfile_pathname = NULL;        // HACK: pathname to precompiled startup file blob to put in the startup header of a bootable IFS
140
static size_t startupfile_ep_from_imagebase = 0; // HACK: startup code entrypoint offset from image base for a bootable IFS 
138
static size_t startupfile_ep_from_imagebase = 0; // HACK: startup code entrypoint offset from image base for a bootable IFS 
141
static size_t kernelfile_offset = 0x32000;       // kernel file offset in the IFS (is it ever supposed to change)
139
static size_t kernelfile_offset = 0x32000;       // kernel file offset in the IFS (is it ever supposed to change?)
142
 
140
 
143
 
141
 
144
// exported function prototypes
142
// exported function prototypes
145
int32_t update_checksum (const void *data, const size_t data_len, const bool is_foreign_endianness); // compute an IFS image or startup checksum to store in the trailer
143
int32_t update_checksum (const void *data, const size_t data_len, const bool is_foreign_endianness); // compute an IFS image or startup checksum to store in the trailer
146
 
144
 
Line 754... Line 752...
754
      char **args;
752
      char **args;
755
      size_t count;
753
      size_t count;
756
   } stringarray_t;
754
   } stringarray_t;
757
 
755
 
758
   static thread_local char *candidate_pathname = NULL;
756
   static thread_local char *candidate_pathname = NULL;
-
 
757
   static thread_local parms_t default_parms = { 0 };
759
   static int inode_count = 0; // will be preincremented each time this function is called
758
   static int inode_count = 0; // will be preincremented each time this function is called
760
 
759
 
761
   stringarray_t global_argv = { NULL, 0 };
760
   stringarray_t global_argv = { NULL, 0 };
762
   stringarray_t global_envp = { NULL, 0 };
761
   stringarray_t global_envp = { NULL, 0 };
763
   stringarray_t line_argv = { NULL, 0 };
762
   stringarray_t line_argv = { NULL, 0 };
Line 799... Line 798...
799
      ASSERT_WITH_ERRNO (candidate_pathname);
798
      ASSERT_WITH_ERRNO (candidate_pathname);
800
   }
799
   }
801
 
800
 
802
   if (S_ISDIR (entry_parms->st_mode)) // are we storing a directory ?
801
   if (S_ISDIR (entry_parms->st_mode)) // are we storing a directory ?
803
   {
802
   {
-
 
803
      if (buildhost_pathname != NULL) // was a source file pathname supplied ?
-
 
804
      {
-
 
805
         memcpy (&default_parms, entry_parms, sizeof (parms_t)); // apply current entry parameters when including a directory recursively
-
 
806
         add_directory_contents_recursively (fsentries, fsentry_count, buildhost_pathname, strlen (buildhost_pathname), &default_parms); // if so, add this diretory contents recursively
-
 
807
      }
804
      LOG_INFO ("directory: ino 0x%x uid %d gid %d mode 0%o path \"%s\"", inode_count + 1, entry_parms->uid, entry_parms->gid, entry_parms->st_mode, stored_pathname);
808
      LOG_INFO ("directory: ino 0x%x uid %d gid %d mode 0%o path \"%s\"", inode_count + 1, entry_parms->uid, entry_parms->gid, entry_parms->st_mode, stored_pathname);
805
   }
809
   }
806
   else if (S_ISREG (entry_parms->st_mode)) // else are we storing a regular file ?
810
   else if (S_ISLNK (entry_parms->st_mode)) // else are we storing a symbolic link ?
807
   {
811
   {
-
 
812
      // do we already know the data for this data blob ?
-
 
813
      if (entry_parms->data.bytes != NULL)
-
 
814
      {
-
 
815
         entry_parms->mtime = entry_parms->mtime_for_inline_files; // if so, set it a mtime equal to the mtime to use for inline files
-
 
816
         LOG_INFO ("symlink: ino 0x%x uid %d gid %d mode 0%o path \"%s\" -> \"%s\"", inode_count + 1, entry_parms->uid, entry_parms->gid, entry_parms->st_mode, stored_pathname, entry_parms->data.bytes);
-
 
817
      }
-
 
818
      else if (buildhost_pathname != NULL) // else was a source file pathname supplied ?
-
 
819
      {
-
 
820
         entry_parms->data.bytes = malloc (MAXPATHLEN); // allocate enough space for symlink data
-
 
821
         ASSERT_WITH_ERRNO (entry_parms->data.bytes);
-
 
822
         retval = readlink (buildhost_pathname, entry_parms->data.bytes, MAXPATHLEN); // read symlink contents
-
 
823
         ASSERT_WITH_ERRNO (retval > 0);
-
 
824
         entry_parms->data.size = retval; // save symlink target length
-
 
825
      }
-
 
826
      else
-
 
827
         DIE_WITH_EXITCODE (1, "unexpected code path: can't store a symlink without neither explicit contents nor a host pathname. This is a bug in the program. Please contact the author.");
-
 
828
   }
-
 
829
   else if (S_ISFIFO (entry_parms->st_mode)) // else are we storing a FIFO ?
-
 
830
   {
-
 
831
      if ((entry_parms->data.bytes == NULL) || (strchr (entry_parms->data.bytes, ':') == NULL))
-
 
832
         DIE_WITH_EXITCODE (1, "device entry \"%s\" malformed (no 'dev:rdev' pair)", stored_pathname);
-
 
833
      LOG_INFO ("fifo: ino 0x%x uid %d gid %d mode 0%o path \"%s\" dev:rdev %s)", inode_count + 1, entry_parms->uid, entry_parms->gid, entry_parms->st_mode, stored_pathname, entry_parms->data.bytes);
-
 
834
   }
-
 
835
   else // necessarily a regular file (either S_IFREG is specified, or st_mode is zero)
-
 
836
   {
-
 
837
      entry_parms->st_mode |= S_IFREG; // make this explicit
-
 
838
 
808
      if (entry_parms->is_bootstrap_file) // is it the bootstrap file ?
839
      if (entry_parms->is_bootstrap_file) // is it the bootstrap file ?
809
      {
840
      {
810
         // parse each line of contents
841
         // parse each line of contents
811
         ASSERT (entry_parms->data.size > 0, "kernel specification without inline contents");
842
         ASSERT (entry_parms->data.size > 0, "kernel specification without inline contents");
812
 
843
 
Line 1145... Line 1176...
1145
            Buffer_StripELFFile (&entry_parms->data, (const char **) saved_ELF_sections, saved_ELF_section_count, false, stored_pathname); // strip the ELF file à la mkifs
1176
            Buffer_StripELFFile (&entry_parms->data, (const char **) saved_ELF_sections, saved_ELF_section_count, false, stored_pathname); // strip the ELF file à la mkifs
1146
            entry_parms->extra_ino_flags |= IFS_INO_PROCESSED_ELF; // mark this inode as a preprocessed ELF file
1177
            entry_parms->extra_ino_flags |= IFS_INO_PROCESSED_ELF; // mark this inode as a preprocessed ELF file
1147
         } // end if the file is not yet a processed ELF
1178
         } // end if the file is not yet a processed ELF
1148
      } // end if the file we're storing is an ELF file
1179
      } // end if the file we're storing is an ELF file
1149
      #undef ELFHDR // undefine the macro that used to always point to the ELF header at the beginning of the file
1180
      #undef ELFHDR // undefine the macro that used to always point to the ELF header at the beginning of the file
1150
   }
-
 
1151
   else if (S_ISLNK (entry_parms->st_mode)) // else are we storing a symbolic link ?
-
 
1152
   {
-
 
1153
      // do we already know the data for this data blob ?
-
 
1154
      if (entry_parms->data.bytes != NULL)
-
 
1155
      {
-
 
1156
         entry_parms->mtime = entry_parms->mtime_for_inline_files; // if so, set it a mtime equal to the mtime to use for inline files
-
 
1157
         LOG_INFO ("symlink: ino 0x%x uid %d gid %d mode 0%o path \"%s\" -> \"%s\"", inode_count + 1, entry_parms->uid, entry_parms->gid, entry_parms->st_mode, stored_pathname, entry_parms->data.bytes);
-
 
1158
      }
-
 
1159
      else if (buildhost_pathname != NULL) // else was a source file pathname supplied ?
-
 
1160
      {
-
 
1161
         entry_parms->data.bytes = malloc (MAXPATHLEN); // allocate enough space for symlink data
-
 
1162
         ASSERT_WITH_ERRNO (entry_parms->data.bytes);
-
 
1163
         retval = readlink (buildhost_pathname, entry_parms->data.bytes, MAXPATHLEN); // read symlink contents
-
 
1164
         ASSERT_WITH_ERRNO (retval > 0);
-
 
1165
         entry_parms->data.size = retval; // save symlink target length
-
 
1166
      }
-
 
1167
      else
-
 
1168
         DIE_WITH_EXITCODE (1, "unexpected code path: can't store a symlink without neither explicit contents nor a host pathname. This is a bug in the program. Please contact the author.");
-
 
1169
   }
-
 
1170
   else // we must be storing a FIFO
-
 
1171
   {
-
 
1172
      if ((entry_parms->data.bytes == NULL) || (strchr (entry_parms->data.bytes, ':') == NULL))
-
 
1173
         DIE_WITH_EXITCODE (1, "device entry \"%s\" malformed (no 'dev:rdev' pair)", stored_pathname);
-
 
1174
      LOG_INFO ("fifo: ino 0x%x uid %d gid %d mode 0%o path \"%s\" dev:rdev %s)", inode_count + 1, entry_parms->uid, entry_parms->gid, entry_parms->st_mode, stored_pathname, entry_parms->data.bytes);
-
 
1175
   }
1181
   }
1176
 
1182
 
1177
   // have a pointer to where the stored pathname actually starts, without the leading slash
1183
   // have a pointer to where the stored pathname actually starts, without the leading slash
1178
   stored_pathname_without_leading_slash = stored_pathname[0] == '/' ? &stored_pathname[1] : stored_pathname;
1184
   stored_pathname_without_leading_slash = stored_pathname[0] == '/' ? &stored_pathname[1] : stored_pathname;
1179
 
1185
 
Line 1688... Line 1694...
1688
   fsentry_t *fsentries = NULL; // output IFS's filesystem entries
1694
   fsentry_t *fsentries = NULL; // output IFS's filesystem entries
1689
   size_t fsentry_count = 0; // number of entries in the IFS filesystem
1695
   size_t fsentry_count = 0; // number of entries in the IFS filesystem
1690
   parms_t default_parms = { // default parameters for a filesystem entry
1696
   parms_t default_parms = { // default parameters for a filesystem entry
1691
      .dperms = 0755,
1697
      .dperms = 0755,
1692
      .perms = 0644,
1698
      .perms = 0644,
1693
      .uid = 0,
-
 
1694
      .gid = 0,
-
 
1695
      .st_mode = S_IFREG,
-
 
1696
      .mtime = UINT32_MAX,
1699
      .mtime = UINT32_MAX,
1697
      .mtime_for_inline_files = UINT32_MAX,
1700
      .mtime_for_inline_files = UINT32_MAX,
1698
      .prefix = "/proc/boot",
1701
      .prefix = "/proc/boot",
1699
      .should_follow_symlinks = true, // [+|-followlink]
1702
      .should_follow_symlinks = true, // [+|-followlink]
1700
      .should_autosymlink_dylib = true, // [+|-autolink]
1703
      .should_autosymlink_dylib = true, // [+|-autolink]
1701
      .is_compiled_bootscript = false, // [+|-script]
-
 
1702
      .extra_ino_flags = 0,
-
 
1703
      .search = NULL,
-
 
1704
      .data = { NULL, 0 }
-
 
1705
   };
1704
   };
1706
   parms_t entry_parms = { 0 }; // current parameters for a filesystem entry (will be initialized to default_parms each time a new entry is parsed in the build file)
1705
   parms_t entry_parms = { 0 }; // current parameters for a filesystem entry (will be initialized to default_parms each time a new entry is parsed in the build file)
1707
 
1706
 
1708
   char path_on_buildhost[MAXPATHLEN] = "";
1707
   char path_on_buildhost[MAXPATHLEN] = "";
1709
   char path_in_ifs[MAXPATHLEN] = "";
1708
   char path_in_ifs[MAXPATHLEN] = "";
Line 1830... Line 1829...
1830
      fprintf (out, "    ifstool --info [--everything] <ifs file>\n");
1829
      fprintf (out, "    ifstool --info [--everything] <ifs file>\n");
1831
      fprintf (out, "    ifstool --dump [--outdir <path>] <ifs file>\n");
1830
      fprintf (out, "    ifstool --dump [--outdir <path>] <ifs file>\n");
1832
      fprintf (out, "    ifstool --strip [--outfile <pathname>] <ELF file>\n");
1831
      fprintf (out, "    ifstool --strip [--outfile <pathname>] <ELF file>\n");
1833
      fprintf (out, "    ifstool [-?|--help]\n");
1832
      fprintf (out, "    ifstool [-?|--help]\n");
1834
      // mkifs [-?] [-l inputline] [-n[n]] [-o directory] [-p patchfile] [-r rootdir] [-s section] [-v] [buildfile] [directory] [outputfile]
1833
      // mkifs [-?] [-l inputline] [-n[n]] [-o directory] [-p patchfile] [-r rootdir] [-s section] [-v] [buildfile] [directory] [outputfile]
1835
      fprintf (out, "    ifstool [--bootfile <pathname>] [--startupfile <pathname>@<EP_from_imgbase>] [--kernelfile <pathname>@<fileoffs>] [-a suffix] [-l inputline] [-n[n]] [-r rootdir] [-s section] [-v[...]] <buildfile> [directory] [outfile]\n");
1834
      fprintf (out, "    ifstool [--bootfile <pathname>] [--startupfile <pathname>@<EP_from_imgbase>] [--kerneloffs <fileoffs>] [-a suffix] [-l inputline] [-n[n]] [-r rootdir] [-s section] [-v[...]] [buildfile] [directory] [outputfile]\n");
1836
      fprintf (out, "NOTE: the compiler mode requires predigested boot, startup and kernel files produced by mkifs.\n");
1835
      fprintf (out, "NOTE: the compiler mode requires predigested boot and startup files produced by mkifs.\n");
1837
      fprintf (out, "options:\n");
1836
      fprintf (out, "options:\n");
1838
      fprintf (out, "    -?       Display some help information.\n");
1837
      fprintf (out, "    -?       Display some help information.\n");
1839
      fprintf (out, "    -a .ext  Append a suffix to symbol files generated via [+keeplinked].\n");
1838
      fprintf (out, "    -a .ext  Append a suffix to symbol files generated via [+keeplinked].\n");
1840
      fprintf (out, "    -l line  Process line before interpreting the buildfile. Input lines given\n");
1839
      fprintf (out, "    -l line  Process line before interpreting the buildfile. Input lines given\n");
1841
      fprintf (out, "             to mkifs should be quoted to prevent interpretation by the shell\n");
1840
      fprintf (out, "             to mkifs should be quoted to prevent interpretation by the shell\n");