Subversion Repositories QNX 8.QNX8 IFS tool

Rev

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

Rev 7 Rev 8
Line 30... Line 30...
30
#define strdup(s) _strdup ((s))
30
#define strdup(s) _strdup ((s))
31
#define strcasecmp(s1,s2) _stricmp ((s1), (s2))
31
#define strcasecmp(s1,s2) _stricmp ((s1), (s2))
32
#define fseek(fp,off,m) _fseeki64 ((fp), (off), (m))
32
#define fseek(fp,off,m) _fseeki64 ((fp), (off), (m))
33
#define access(p,m) _access ((p), (m))
33
#define access(p,m) _access ((p), (m))
34
#define MAXPATHLEN 1024
34
#define MAXPATHLEN 1024
-
 
35
#ifndef thread_local
-
 
36
#define thread_local __declspec(thread) // the thread_local keyword wasn't defined before C++11 and C23
-
 
37
#endif // !thread_local
35
#else // !_MSC_VER
38
#else // !_MSC_VER
36
#include <sys/param.h>
39
#include <sys/param.h>
37
#include <unistd.h>
40
#include <unistd.h>
-
 
41
#ifndef thread_local
-
 
42
#define thread_local __thread // the thread_local keyword wasn't defined before C++11 and C23
-
 
43
#endif // !thread_local
38
#endif // _MSC_VER
44
#endif // _MSC_VER
39
 
45
 
40
 
46
 
41
// handy macros that generate a version number in the format "YYYYMMDD" corresponding to the build date. Usage: printf ("version " VERSION_FMT_YYYYMMDD "\n", VERSION_ARG_YYYYMMDD);
47
// handy macros that generate a version number in the format "YYYYMMDD" corresponding to the build date. Usage: printf ("version " VERSION_FMT_YYYYMMDD "\n", VERSION_ARG_YYYYMMDD);
42
#ifndef VERSION_ARG_YYYYMMDD
48
#ifndef VERSION_ARG_YYYYMMDD
Line 85... Line 91...
85
                                                     (*((uint32_t *) &__DATE__[3]) == *((uint32_t *) " 30 ") ? "30" : \
91
                                                     (*((uint32_t *) &__DATE__[3]) == *((uint32_t *) " 30 ") ? "30" : \
86
                                                      (*((uint32_t *) &__DATE__[3]) == *((uint32_t *) " 31 ") ? "31" : "XX"))))))))))))))))))))))))))))))) // compiler will optimize this into a const string, e.g. "14"
92
                                                      (*((uint32_t *) &__DATE__[3]) == *((uint32_t *) " 31 ") ? "31" : "XX"))))))))))))))))))))))))))))))) // compiler will optimize this into a const string, e.g. "14"
87
#define VERSION_FMT_YYYYMMDD "%04s%02s%02s"
93
#define VERSION_FMT_YYYYMMDD "%04s%02s%02s"
88
#define VERSION_ARG_YYYYMMDD BUILDDATE_YEAR, BUILDDATE_MONTH, BUILDDATE_DAY
94
#define VERSION_ARG_YYYYMMDD BUILDDATE_YEAR, BUILDDATE_MONTH, BUILDDATE_DAY
89
#endif // !VERSION_ARG_YYYYMMDD
95
#endif // !VERSION_ARG_YYYYMMDD
-
 
96
 
-
 
97
 
-
 
98
// we don't mind about this macro's efficiency...
-
 
99
#define __FILENAME__ (strrchr (__FILE__, '\\') ? strrchr (__FILE__, '\\') + 1 : (strrchr (__FILE__, '/') ? strrchr (__FILE__, '/') + 1 : __FILE__))
-
 
100
 
-
 
101
 
-
 
102
// exit less brutally than with abort() if something doesn't go the way we'd like to
-
 
103
#define WELLMANNERED_ASSERT(is_is_true,...) do { if (!(is_is_true)) { fprintf (stderr, "ifstool: fatal error: assertion within %s() in %s line %d failed: ", __FUNCTION__, __FILENAME__, __LINE__); fprintf (stderr, __VA_ARGS__); fputc ('\n', stderr); exit (1); } } while (0)
-
 
104
 
-
 
105
 
-
 
106
// checked read/write/seek operations
-
 
107
#define fseek_or_die(fp,pos,mode) do { if (fseek ((fp), (pos), (mode)) != 0) { fprintf (stderr, "ifstool: fatal error: fseek() failure within %s() in %s line %d: errno %d (%s)\n", __FUNCTION__, __FILENAME__, __LINE__, errno, strerror (errno)); exit (1); } } while (0)
-
 
108
#define fread_or_die(buf,sz,len,fp) do { if (fread ((buf), (sz), (len), (fp)) != (len)) { fprintf (stderr, "ifstool: fatal error: fread() failure within %s() in %s line %d: errno %d (%s)\n", __FUNCTION__, __FILENAME__, __LINE__, errno, strerror (errno)); exit (1); } } while (0)
-
 
109
#define fwrite_or_die(buf,sz,len,fp) do { if ((fwrite ((buf), (sz), (len), (fp)) != (len)) || (fflush ((fp)) != 0)) { fprintf (stderr, "ifstool: fatal error: fwrite() failure within %s() in %s line %d: errno %d (%s)\n", __FUNCTION__, __FILENAME__, __LINE__, errno, strerror (errno)); exit (1); } } while (0)
90
 
110
 
91
 
111
 
92
#define ROUND_TO_UPPER_MULTIPLE(val,multiple) ((((val) + (size_t) (multiple) - 1) / (multiple)) * (multiple)) // note that val is being evaluated once, so it can be the result of a function call
112
#define ROUND_TO_UPPER_MULTIPLE(val,multiple) ((((val) + (size_t) (multiple) - 1) / (multiple)) * (multiple)) // note that val is being evaluated once, so it can be the result of a function call
93
#ifdef _WIN32
113
#ifdef _WIN32
94
#define IS_DIRSEP(c) (((c) == '/') || ((c) == '\\'))
114
#define IS_DIRSEP(c) (((c) == '/') || ((c) == '\\'))
Line 804... Line 824...
804
static uint8_t *SHA512 (void *data, size_t data_len, uint8_t *digest_or_NULL)
824
static uint8_t *SHA512 (void *data, size_t data_len, uint8_t *digest_or_NULL)
805
{
825
{
806
   // computes the SHA-512 hash of a block of data in one pass and write it to digest, or to a static buffer if NULL
826
   // computes the SHA-512 hash of a block of data in one pass and write it to digest, or to a static buffer if NULL
807
   // returns the STRING REPRESENTATION of digest in a statically-allocated string
827
   // returns the STRING REPRESENTATION of digest in a statically-allocated string
808
 
828
 
809
   static uint8_t static_digest[SHA512_DIGEST_LENGTH] = "";
829
   static thread_local uint8_t static_digest[SHA512_DIGEST_LENGTH] = "";
810
   static char digest_as_string[2 * SHA512_DIGEST_LENGTH + 1] = "";
830
   static thread_local char digest_as_string[2 * SHA512_DIGEST_LENGTH + 1] = "";
811
 
831
 
812
   SHA512_CTX ctx;
832
   SHA512_CTX ctx;
813
   size_t byte_index;
833
   size_t byte_index;
814
 
834
 
815
   SHA512_Init (&ctx);
835
   SHA512_Init (&ctx);
Line 838... Line 858...
838
   for (i = 0; i < data_len; i++)
858
   for (i = 0; i < data_len; i++)
839
   {
859
   {
840
      accumulator[i % 4] = *current_char_ptr;
860
      accumulator[i % 4] = *current_char_ptr;
841
      if (i % 4 == 3)
861
      if (i % 4 == 3)
842
         if (is_foreign_endianness)
862
         if (is_foreign_endianness)
843
            image_cksum += (accumulator[3] <<  0) + (accumulator[2] <<  8) + (accumulator[1] << 16) + (accumulator[0] << 24);
863
            image_cksum += (accumulator[3] << 0) + (accumulator[2] << 8) + (accumulator[1] << 16) + (accumulator[0] << 24);
844
         else
864
         else
845
            image_cksum += (accumulator[0] <<  0) + (accumulator[1] <<  8) + (accumulator[2] << 16) + (accumulator[3] << 24);
865
            image_cksum += (accumulator[0] << 0) + (accumulator[1] << 8) + (accumulator[2] << 16) + (accumulator[3] << 24);
846
      current_char_ptr++;
866
      current_char_ptr++;
847
   }
867
   }
848
 
868
 
849
   return (is_foreign_endianness ? __builtin_bswap32 (-image_cksum) : -image_cksum);
869
   return (is_foreign_endianness ? __builtin_bswap32 (-image_cksum) : -image_cksum);
850
}
870
}
Line 904... Line 924...
904
 
924
 
905
static char *binary (const uint8_t x, char char_for_zero, char char_for_one)
925
static char *binary (const uint8_t x, char char_for_zero, char char_for_one)
906
{
926
{
907
   // returns the binary representation of x as a string
927
   // returns the binary representation of x as a string
908
 
928
 
909
   static char outstr[9] = "00000000";
929
   static thread_local char outstr[9] = "00000000";
910
   for (int i = 0; i < 8; i++)
930
   for (int i = 0; i < 8; i++)
911
      outstr[i] = (x & (0x80 >> i) ? char_for_one : char_for_zero);
931
      outstr[i] = (x & (0x80 >> i) ? char_for_one : char_for_zero);
912
   return (outstr);
932
   return (outstr);
913
}
933
}
914
 
934
 
915
 
935
 
916
static char *describe_uint8 (const uint8_t x, const char *bitwise_stringdescs[8])
936
static char *describe_uint8 (const uint8_t x, const char *bitwise_stringdescs[8])
917
{
937
{
918
   // returns the ORed description of byte 'x' according to the description strings for each bit
938
   // returns the ORed description of byte 'x' according to the description strings for each bit
919
 
939
 
920
   static char *default_bitstrings[8] = { "bit0", "bit1", "bit2", "bit3", "bit4", "bit5", "bit6", "bit7" };
940
   static thread_local char *default_bitstrings[8] = { "bit0", "bit1", "bit2", "bit3", "bit4", "bit5", "bit6", "bit7" };
921
   static char outstr[8 * 64] = "";
941
   static thread_local char outstr[8 * 64] = "";
922
 
942
 
923
   outstr[0] = 0;
943
   outstr[0] = 0;
924
   for (int i = 0; i < 8; i++)
944
   for (int i = 0; i < 8; i++)
925
      if (x & (1 << i))
945
      if (x & (1 << i))
926
      {
946
      {
Line 934... Line 954...
934
 
954
 
935
static char *read_filecontents (const char *pathname, const char *search_path, uint8_t **databuf, size_t *datalen)
955
static char *read_filecontents (const char *pathname, const char *search_path, uint8_t **databuf, size_t *datalen)
936
{
956
{
937
   // locates pathname among MKIFS_PATH, and places its contents in a buffer (caller frees). Returns resolved pathname (static buffer) or NULL.
957
   // locates pathname among MKIFS_PATH, and places its contents in a buffer (caller frees). Returns resolved pathname (static buffer) or NULL.
938
 
958
 
939
   /*thread_local*/ static char final_pathname[MAXPATHLEN];
959
   static thread_local char final_pathname[MAXPATHLEN];
940
 
960
 
941
   const char *nextsep;
961
   const char *nextsep;
942
   const char *token;
962
   const char *token;
943
   FILE *fp;
963
   FILE *fp;
944
 
964
 
Line 946... Line 966...
946
   if (IS_DIRSEP (pathname[0]) || (isalpha (pathname[0]) && (pathname[1] == ':') && IS_DIRSEP (pathname[2])))
966
   if (IS_DIRSEP (pathname[0]) || (isalpha (pathname[0]) && (pathname[1] == ':') && IS_DIRSEP (pathname[2])))
947
      strcpy (final_pathname, pathname); // in this case, it MUST exist at its designated location (either absolute or relative to the current working directory)
967
      strcpy (final_pathname, pathname); // in this case, it MUST exist at its designated location (either absolute or relative to the current working directory)
948
   else // the path is relative, search it among the search paths we have
968
   else // the path is relative, search it among the search paths we have
949
   {
969
   {
950
      // construct a potential final path using each element of the search path
970
      // construct a potential final path using each element of the search path
951
      token = search_path;
971
      token = (*search_path != 0 ? search_path : NULL);
952
      nextsep = &token[strcspn (token, PATH_SEP_STR)];
972
      nextsep = (token != NULL ? &token[strcspn (token, PATH_SEP_STR)] : NULL);
953
      while (token != NULL)
973
      while (token != NULL)
954
      {
974
      {
955
         sprintf (final_pathname, "%.*s/%s", (int) (nextsep - token), token, pathname);
975
         sprintf (final_pathname, "%.*s/%s", (int) (nextsep - token), token, pathname);
956
         if (access (final_pathname, 0) == 0)
976
         if (access (final_pathname, 0) == 0)
957
            break; // if a file can indeed be found at this location, stop searching
977
            break; // if a file can indeed be found at this location, stop searching
Line 1019... Line 1039...
1019
   fseek (blob_fp, 0, SEEK_SET);
1039
   fseek (blob_fp, 0, SEEK_SET);
1020
   fread (blob_buffer, 1, blob_size, blob_fp);
1040
   fread (blob_buffer, 1, blob_size, blob_fp);
1021
   fclose (blob_fp);
1041
   fclose (blob_fp);
1022
 
1042
 
1023
   ret = (int) fwrite (blob_buffer, 1, blob_size, fp);
1043
   ret = (int) fwrite (blob_buffer, 1, blob_size, fp);
-
 
1044
   fflush (fp); // force flush to disk, because the C stream API is *buffered*
1024
   free (blob_buffer);
1045
   free (blob_buffer);
1025
   return (ret);
1046
   return (ret);
1026
}
1047
}
1027
 
1048
 
1028
 
1049
 
Line 1036... Line 1057...
1036
   size_t datalen;
1057
   size_t datalen;
1037
   size_t count;
1058
   size_t count;
1038
 
1059
 
1039
   count = 0;
1060
   count = 0;
1040
   if (fp != NULL)
1061
   if (fp != NULL)
1041
      fwrite (&fsentry->header, sizeof (fsentry->header), 1, fp); // write the entry header (PACKED STRUCT)
1062
      fwrite_or_die (&fsentry->header, 1, sizeof (fsentry->header), fp); // write the entry header (PACKED STRUCT)
1042
   count += sizeof (fsentry->header);
1063
   count += sizeof (fsentry->header);
1043
   if (S_ISREG (fsentry->header.mode))
1064
   if (S_ISREG (fsentry->header.mode))
1044
   {
1065
   {
1045
      if (fp != NULL)
1066
      if (fp != NULL)
1046
      {
1067
      {
1047
         fwrite (&fsentry->u.file.offset, sizeof (uint32_t), 1, fp); // write offset
1068
         fwrite_or_die (&fsentry->u.file.offset, 1, sizeof (uint32_t), fp); // write offset
1048
         fwrite (&fsentry->u.file.size,   sizeof (uint32_t), 1, fp); // write size
1069
         fwrite_or_die (&fsentry->u.file.size,   1, sizeof (uint32_t), fp); // write size
1049
      }
1070
      }
1050
      count += 2 * sizeof (uint32_t);
1071
      count += 2 * sizeof (uint32_t);
1051
      datalen = strlen (fsentry->u.file.path) + 1;
1072
      datalen = strlen (fsentry->u.file.path) + 1;
1052
      if (fp != NULL)
1073
      if (fp != NULL)
1053
         fwrite (fsentry->u.file.path, (size_t) datalen, 1, fp); // write null-terminated path (no leading slash)
1074
         fwrite_or_die (fsentry->u.file.path, 1, (size_t) datalen, fp); // write null-terminated path (no leading slash)
1054
      count += datalen;
1075
      count += datalen;
1055
   }
1076
   }
1056
   else if (S_ISDIR (fsentry->header.mode))
1077
   else if (S_ISDIR (fsentry->header.mode))
1057
   {
1078
   {
1058
      datalen = strlen (fsentry->u.dir.path) + 1;
1079
      datalen = strlen (fsentry->u.dir.path) + 1;
1059
      if (fp != NULL)
1080
      if (fp != NULL)
1060
         fwrite (fsentry->u.dir.path, (size_t) datalen, 1, fp); // write null-terminated path (no leading slash)
1081
         fwrite_or_die (fsentry->u.dir.path, 1, (size_t) datalen, fp); // write null-terminated path (no leading slash)
1061
      count += datalen;
1082
      count += datalen;
1062
   }
1083
   }
1063
   else if (S_ISLNK (fsentry->header.mode))
1084
   else if (S_ISLNK (fsentry->header.mode))
1064
   {
1085
   {
1065
      if (fp != NULL)
1086
      if (fp != NULL)
1066
      {
1087
      {
1067
         fwrite (&fsentry->u.symlink.sym_offset, sizeof (uint16_t), 1, fp); // write offset
1088
         fwrite_or_die (&fsentry->u.symlink.sym_offset, 1, sizeof (uint16_t), fp); // write offset
1068
         fwrite (&fsentry->u.symlink.sym_size,   sizeof (uint16_t), 1, fp); // write size
1089
         fwrite_or_die (&fsentry->u.symlink.sym_size,   1, sizeof (uint16_t), fp); // write size
1069
      }
1090
      }
1070
      count += 2 * sizeof (uint16_t);
1091
      count += 2 * sizeof (uint16_t);
1071
      datalen = strlen (fsentry->u.symlink.path) + 1;
1092
      datalen = strlen (fsentry->u.symlink.path) + 1;
1072
      if (fp != NULL)
1093
      if (fp != NULL)
1073
         fwrite (fsentry->u.symlink.path, (size_t) datalen, 1, fp); // write null-terminated path (no leading slash)
1094
         fwrite_or_die (fsentry->u.symlink.path, 1, (size_t) datalen, fp); // write null-terminated path (no leading slash)
1074
      count += datalen;
1095
      count += datalen;
1075
      datalen = strlen (fsentry->u.symlink.contents) + 1;
1096
      datalen = strlen (fsentry->u.symlink.contents) + 1;
1076
      if (fp != NULL)
1097
      if (fp != NULL)
1077
         fwrite (fsentry->u.symlink.contents, (size_t) datalen, 1, fp); // write null-terminated symlink contents
1098
         fwrite_or_die (fsentry->u.symlink.contents, 1, (size_t) datalen, fp); // write null-terminated symlink contents
1078
      count += datalen;
1099
      count += datalen;
1079
   }
1100
   }
1080
   else
1101
   else
1081
   {
1102
   {
1082
      if (fp != NULL)
1103
      if (fp != NULL)
1083
      {
1104
      {
1084
         fwrite (&fsentry->u.device.dev,  sizeof (uint32_t), 1, fp); // write dev number
1105
         fwrite_or_die (&fsentry->u.device.dev,  1, sizeof (uint32_t), fp); // write dev number
1085
         fwrite (&fsentry->u.device.rdev, sizeof (uint32_t), 1, fp); // write rdev number
1106
         fwrite_or_die (&fsentry->u.device.rdev, 1, sizeof (uint32_t), fp); // write rdev number
1086
      }
1107
      }
1087
      count += 2 * sizeof (uint32_t);
1108
      count += 2 * sizeof (uint32_t);
1088
      datalen = strlen (fsentry->u.device.path) + 1;
1109
      datalen = strlen (fsentry->u.device.path) + 1;
1089
      if (fp != NULL)
1110
      if (fp != NULL)
1090
         fwrite (fsentry->u.device.path, (size_t) datalen, 1, fp); // write null-terminated path (no leading slash)
1111
         fwrite_or_die (fsentry->u.device.path, 1, (size_t) datalen, fp); // write null-terminated path (no leading slash)
1091
      count += datalen;
1112
      count += datalen;
1092
   }
1113
   }
1093
 
1114
 
1094
   if (count < fsentry->header.size)
1115
   if (count < fsentry->header.size)
1095
   {
1116
   {
1096
      if (fp != NULL)
1117
      if (fp != NULL)
1097
         fwrite (zeropad_buffer, fsentry->header.size - count, 1, fp); // pad as necessary
1118
         fwrite_or_die (zeropad_buffer, 1, fsentry->header.size - count, fp); // pad as necessary
1098
      count += fsentry->header.size - count;
1119
      count += fsentry->header.size - count;
1099
   }
1120
   }
1100
   else if (count > fsentry->header.size)
1121
   else if (count > fsentry->header.size)
1101
   {
1122
   {
1102
      fprintf (stderr, "ERROR: attempt to write invalid dirent (claimed size %zd, written size %zd). Aborting.\n", (size_t) fsentry->header.size, count);
1123
      fprintf (stderr, "ERROR: attempt to write invalid dirent (claimed size %zd, written size %zd). Aborting.\n", (size_t) fsentry->header.size, count);
Line 1107... Line 1128...
1107
}
1128
}
1108
 
1129
 
1109
 
1130
 
1110
static size_t add_fsentry (fsentry_t **fsentries, size_t *fsentry_count, parms_t *entry_parms, const char *stored_pathname, const char *buildhost_pathname)
1131
static size_t add_fsentry (fsentry_t **fsentries, size_t *fsentry_count, parms_t *entry_parms, const char *stored_pathname, const char *buildhost_pathname)
1111
{
1132
{
1112
   static char candidate_pathname[1024];
1133
   static thread_local char candidate_pathname[1024];
1113
   static int inode_count = 0; // will be preincremented each time this function is called
1134
   static int inode_count = 0; // will be preincremented each time this function is called
1114
 
1135
 
1115
   const char *original_stored_pathname = NULL;
1136
   const char *original_stored_pathname = NULL;
1116
   const elf_dynamic_section_entry_t *dynamic_entry; // dynamic section entry
1137
   const elf_dynamic_section_entry_t *dynamic_entry; // dynamic section entry
1117
   const elf_section_header_t *shdr_shstr; // section headers strings (containing ELF sections names)
1138
   const elf_section_header_t *shdr_shstr; // section headers strings (containing ELF sections names)
Line 1145... Line 1166...
1145
         // HACK: for now just consider the kernel as a binary blob
1166
         // HACK: for now just consider the kernel as a binary blob
1146
         // FIXME: reimplement properly
1167
         // FIXME: reimplement properly
1147
         sprintf (candidate_pathname, "%s/procnto-smp-instr", entry_parms->prefix); // fix the entry name
1168
         sprintf (candidate_pathname, "%s/procnto-smp-instr", entry_parms->prefix); // fix the entry name
1148
         stored_pathname = candidate_pathname;
1169
         stored_pathname = candidate_pathname;
1149
         extra_ino_flags = IFS_INO_PROCESSED_ELF | IFS_INO_BOOTSTRAP_EXE; // procnto needs to have these flags stamped on the inode
1170
         extra_ino_flags = IFS_INO_PROCESSED_ELF | IFS_INO_BOOTSTRAP_EXE; // procnto needs to have these flags stamped on the inode
-
 
1171
         entry_parms->st_mode = S_IFREG | 0700; // procnto requires 0700 permissions
1150
         image_kernel_ino = extra_ino_flags | (inode_count + 1);
1172
         image_kernel_ino = extra_ino_flags | (inode_count + 1);
1151
      }
1173
      }
1152
      else if (entry_parms->is_compiled_bootscript) // else is it a startup script ?
1174
      else if (entry_parms->is_compiled_bootscript) // else is it a startup script ?
1153
         image_bootscript_ino = inode_count + 1; // save boot script inode number for image header
1175
         image_bootscript_ino = inode_count + 1; // save boot script inode number for image header
1154
 
1176
 
Line 1156... Line 1178...
1156
      if (entry_parms->data != NULL)
1178
      if (entry_parms->data != NULL)
1157
      {
1179
      {
1158
         entry_parms->mtime = entry_parms->mtime_for_inline_files;
1180
         entry_parms->mtime = entry_parms->mtime_for_inline_files;
1159
         fprintf (stderr, "file: ino 0x%x uid %d gid %d mode 0%o path \"%s\" blob (len %zd)\n", extra_ino_flags | (inode_count + 1), entry_parms->uid, entry_parms->gid, entry_parms->st_mode, stored_pathname, entry_parms->datalen);
1181
         fprintf (stderr, "file: ino 0x%x uid %d gid %d mode 0%o path \"%s\" blob (len %zd)\n", extra_ino_flags | (inode_count + 1), entry_parms->uid, entry_parms->gid, entry_parms->st_mode, stored_pathname, entry_parms->datalen);
1160
      }
1182
      }
1161
/*
-
 
1162
         else if (entry_parms->should_compile_contents_as_startup_script) // should we compile this contents as a startup script ?
-
 
1163
         {
-
 
1164
            // HACK: for now just use a precompiled script
-
 
1165
            // FIXME: replace this with a true compilation with the rules defined above
-
 
1166
            data_buffer = malloc (INITIAL_STARTUP_SCRIPT_LEN);
-
 
1167
            if (data_buffer == NULL)
-
 
1168
            {
-
 
1169
               fprintf (stderr, "fatal error: out of memory\n");
-
 
1170
               exit (1);
-
 
1171
            }
-
 
1172
            memcpy (data_buffer, INITIAL_STARTUP_SCRIPT, INITIAL_STARTUP_SCRIPT_LEN);
-
 
1173
            data_len = INITIAL_STARTUP_SCRIPT_LEN;
-
 
1174
            image_bootscript_ino = inode_count + 1; // save boot script inode number for image header
-
 
1175
         }*/
-
 
1176
 
-
 
1177
      else if (buildhost_pathname != NULL) // else entry_datalen == 0, was some sort of pathname supplied ?
1183
      else if (buildhost_pathname != NULL) // else was a source file pathname supplied ?
1178
      {
1184
      {
1179
         resolved_pathname = read_filecontents (buildhost_pathname, (entry_parms->search[0] != 0 ? entry_parms->search : MKIFS_PATH), &entry_parms->data, &entry_parms->datalen);
1185
         resolved_pathname = read_filecontents (buildhost_pathname, (entry_parms->search[0] != 0 ? entry_parms->search : MKIFS_PATH), &entry_parms->data, &entry_parms->datalen); // locate the file
1180
         if (resolved_pathname == NULL)
1186
         if (resolved_pathname == NULL)
1181
         {
1187
         {
1182
            fprintf (stderr, "fatal error: filesystem entry \"%s\" specified in \"%s\" line %d not found on build host: %s\n", buildhost_pathname, buildfile_pathname, lineno, strerror (errno));
1188
            fprintf (stderr, "fatal error: filesystem entry \"%s\" specified in \"%s\" line %d not found on build host: %s\n", buildhost_pathname, buildfile_pathname, lineno, strerror (errno));
1183
            fprintf (stderr, "             v\n");
-
 
1184
            fprintf (stderr, "%s", current_line);
-
 
1185
            fprintf (stderr, "             ^\n");
-
 
1186
            exit (1);
1189
            exit (1);
1187
         }
1190
         }
1188
         stat (resolved_pathname, &stat_buf); // can't fail
1191
         stat (resolved_pathname, &stat_buf); // can't fail
1189
         if (entry_parms->mtime == UINT32_MAX)
1192
         if (entry_parms->mtime == UINT32_MAX)
1190
            entry_parms->mtime = (uint32_t) stat_buf.st_mtime;
1193
            entry_parms->mtime = (uint32_t) stat_buf.st_mtime;
1191
         fprintf (stderr, "file: ino 0x%x uid %d gid %d mode 0%o path \"%s\" buildhost_file \"%s\" (len %zd)\n", inode_count + 1, entry_parms->uid, entry_parms->gid, entry_parms->st_mode, stored_pathname, buildhost_pathname, entry_parms->datalen);
1194
         fprintf (stderr, "file: ino 0x%x uid %d gid %d mode 0%o path \"%s\" buildhost_file \"%s\" (len %zd)\n", inode_count + 1, entry_parms->uid, entry_parms->gid, entry_parms->st_mode, stored_pathname, buildhost_pathname, entry_parms->datalen);
1192
      } // end if "was pathname supplied"
1195
      }
1193
 
1196
 
1194
      // is the file we're storing a dylib and should we check for its canonical name ? FIXME: support for big endian is wrong. We should swap only if endianness is foreign, and also swap all ELF struct members below.
1197
      // is the file we're storing a dylib and should we check for its canonical name ? FIXME: support for big endian is wrong. We should swap only if endianness is foreign, and also swap all ELF struct members below.
1195
      if ((entry_parms->datalen > 52) // file is big enough to contain an ELF header
1198
      if ((entry_parms->datalen > 52) // file is big enough to contain an ELF header
1196
          && ((elf = (elf_header_t *) entry_parms->data) != NULL) // cast (necessary true)
1199
          && ((elf = (elf_header_t *) entry_parms->data) != NULL) // cast (necessary true)
1197
          && (memcmp (ELF_HDR_MEMBER (elf, magic), ELF_MAGIC_STR, 4) == 0) // file starts with the ELF magic
1200
          && (memcmp (ELF_HDR_MEMBER (elf, magic), ELF_MAGIC_STR, 4) == 0) // file starts with the ELF magic
Line 1285... Line 1288...
1285
   {
1288
   {
1286
      fsentry->u.file.offset = WILL_BE_FILLED_LATER; // will be filled later in main() when the file's data blob will be written to the output file
1289
      fsentry->u.file.offset = WILL_BE_FILLED_LATER; // will be filled later in main() when the file's data blob will be written to the output file
1287
      fsentry->u.file.size = (uint32_t) entry_parms->datalen;
1290
      fsentry->u.file.size = (uint32_t) entry_parms->datalen;
1288
      fsentry->u.file.path = strdup (stored_pathname[0] == '/' ? &stored_pathname[1] : stored_pathname);
1291
      fsentry->u.file.path = strdup (stored_pathname[0] == '/' ? &stored_pathname[1] : stored_pathname);
1289
      fsentry->u.file.UNSAVED_databuf = malloc (entry_parms->datalen);
1292
      fsentry->u.file.UNSAVED_databuf = malloc (entry_parms->datalen);
1290
      if (fsentry->u.file.UNSAVED_databuf == NULL)
1293
      WELLMANNERED_ASSERT (fsentry->u.file.UNSAVED_databuf, "out of memory");
1291
      {
-
 
1292
         fprintf (stderr, "fatal error: out of memory\n");
-
 
1293
         exit (1);
-
 
1294
      }
-
 
1295
      memcpy (fsentry->u.file.UNSAVED_databuf, entry_parms->data, entry_parms->datalen);
1294
      memcpy (fsentry->u.file.UNSAVED_databuf, entry_parms->data, entry_parms->datalen);
1296
      fsentry->header.size = (uint16_t) ROUND_TO_UPPER_MULTIPLE (sizeof (fsentry->header) + sizeof (uint32_t) + sizeof (uint32_t) + strlen (fsentry->u.file.path) + 1, image_align); // now we can set the size
1295
      fsentry->header.size = (uint16_t) ROUND_TO_UPPER_MULTIPLE (sizeof (fsentry->header) + sizeof (uint32_t) + sizeof (uint32_t) + strlen (fsentry->u.file.path) + 1, image_align); // now we can set the size
1297
      fsentry->UNSAVED_was_data_written = false; // there *IS* data to save
1296
      fsentry->UNSAVED_was_data_written = false; // there *IS* data to save
1298
   }
1297
   }
1299
   else if (S_ISLNK (entry_parms->st_mode))
1298
   else if (S_ISLNK (entry_parms->st_mode))
1300
   {
1299
   {
1301
      fsentry->u.symlink.sym_offset = (uint16_t) (strlen (stored_pathname[0] == '/' ? &stored_pathname[1] : stored_pathname) + 1);
1300
      fsentry->u.symlink.sym_offset = (uint16_t) (strlen (stored_pathname[0] == '/' ? &stored_pathname[1] : stored_pathname) + 1);
1302
      fsentry->u.symlink.sym_size = (uint16_t) entry_parms->datalen;
1301
      fsentry->u.symlink.sym_size = (uint16_t) entry_parms->datalen;
1303
      fsentry->u.symlink.path = strdup (stored_pathname[0] == '/' ? &stored_pathname[1] : stored_pathname);
1302
      fsentry->u.symlink.path = strdup (stored_pathname[0] == '/' ? &stored_pathname[1] : stored_pathname);
1304
      fsentry->u.symlink.contents = strdup (entry_parms->data);
1303
      fsentry->u.symlink.contents = strdup (entry_parms->data);
1305
      if (fsentry->u.symlink.contents == NULL)
1304
      WELLMANNERED_ASSERT (fsentry->u.symlink.contents, "out of memory");
1306
      {
-
 
1307
         fprintf (stderr, "fatal error: out of memory\n");
-
 
1308
         exit (1);
-
 
1309
      }
-
 
1310
      fsentry->header.size = (uint16_t) ROUND_TO_UPPER_MULTIPLE (sizeof (fsentry->header) + sizeof (uint16_t) + sizeof (uint16_t) + (size_t) fsentry->u.symlink.sym_offset + fsentry->u.symlink.sym_size + 1, image_align); // now we can set the size
1305
      fsentry->header.size = (uint16_t) ROUND_TO_UPPER_MULTIPLE (sizeof (fsentry->header) + sizeof (uint16_t) + sizeof (uint16_t) + (size_t) fsentry->u.symlink.sym_offset + fsentry->u.symlink.sym_size + 1, image_align); // now we can set the size
1311
      fsentry->UNSAVED_was_data_written = true; // no data to save
1306
      fsentry->UNSAVED_was_data_written = true; // no data to save
1312
   }
1307
   }
1313
   else // necessarily a device node
1308
   else // necessarily a device node
1314
   {
1309
   {
Line 1375... Line 1370...
1375
      data_len = strlen (processor_base);
1370
      data_len = strlen (processor_base);
1376
      if ((data_len > 2) && ((processor_base[data_len - 2] == 'b') || (processor_base[data_len - 2] == 'l')) && (processor_base[data_len - 1] == 'e'))
1371
      if ((data_len > 2) && ((processor_base[data_len - 2] == 'b') || (processor_base[data_len - 2] == 'l')) && (processor_base[data_len - 1] == 'e'))
1377
         processor_base[data_len - 2] = 0; // if it ends with "le" or "be", strip that too
1372
         processor_base[data_len - 2] = 0; // if it ends with "le" or "be", strip that too
1378
 
1373
 
1379
      MKIFS_PATH = malloc (10 * MAXPATHLEN); // construct a default MKIFS_PATH now
1374
      MKIFS_PATH = malloc (10 * MAXPATHLEN); // construct a default MKIFS_PATH now
1380
      if (MKIFS_PATH == NULL)
-
 
1381
      {
-
 
1382
         fprintf (stderr, "fatal error: out of memory\n");
1375
      WELLMANNERED_ASSERT (MKIFS_PATH, "out of memory");
1383
         exit (1);
-
 
1384
      }
-
 
1385
      sprintf (MKIFS_PATH, "." PATH_SEP_STR "%s/%s/sbin" PATH_SEP_STR "%s/%s/usr/sbin" PATH_SEP_STR "%s/%s/boot/sys" PATH_SEP_STR "%s/%s/boot/sys" PATH_SEP_STR "%s/%s/bin" PATH_SEP_STR "%s/%s/usr/bin" PATH_SEP_STR "%s/%s/lib" PATH_SEP_STR "%s/%s/lib/dll" PATH_SEP_STR "%s/%s/usr/lib", // use a platform-specific character as path separator
1376
      sprintf (MKIFS_PATH, "." PATH_SEP_STR "%s/%s/sbin" PATH_SEP_STR "%s/%s/usr/sbin" PATH_SEP_STR "%s/%s/boot/sys" PATH_SEP_STR "%s/%s/boot/sys" PATH_SEP_STR "%s/%s/bin" PATH_SEP_STR "%s/%s/usr/bin" PATH_SEP_STR "%s/%s/lib" PATH_SEP_STR "%s/%s/lib/dll" PATH_SEP_STR "%s/%s/usr/lib", // use a platform-specific character as path separator
1386
               QNX_TARGET, processor,
1377
               QNX_TARGET, processor,
1387
               QNX_TARGET, processor,
1378
               QNX_TARGET, processor,
1388
               QNX_TARGET, processor,
1379
               QNX_TARGET, processor,
1389
               QNX_TARGET, processor_base,
1380
               QNX_TARGET, processor_base,
Line 1442... Line 1433...
1442
   void *reallocated_ptr;
1433
   void *reallocated_ptr;
1443
   struct tm utc_time;
1434
   struct tm utc_time;
1444
   struct stat stat_buf;
1435
   struct stat stat_buf;
1445
   size_t startuptrailer_offset;
1436
   size_t startuptrailer_offset;
1446
   size_t startupheader_offset;
1437
   size_t startupheader_offset;
1447
   size_t imgtrailer_offset;
1438
   size_t imagetrailer_offset;
1448
   size_t imgheader_offset;
1439
   size_t imageheader_offset;
1449
   size_t imgdir_offset;
1440
   size_t imgdir_offset;
1450
   size_t imgdir_size;
1441
   size_t imgdir_size;
1451
   size_t final_size;
1442
   size_t final_size;
1452
   size_t blob_size;
1443
   size_t blob_size;
1453
   size_t available_space;
1444
   size_t available_space;
1454
   size_t allocated_size;
1445
   size_t allocated_size;
1455
   size_t fsentry_index;
1446
   size_t fsentry_index;
1456
   size_t largest_index;
1447
   size_t largest_index;
1457
   size_t largest_size;
1448
   size_t largest_size;
1458
   size_t curr_offset;
1449
   size_t curr_offset;
-
 
1450
   uint8_t *blob_data;
-
 
1451
   int32_t checksum;
1459
   char *specifiedpathname_start;
1452
   char *specifiedpathname_start;
1460
   char *directiveblock_start;
1453
   char *directiveblock_start;
1461
   char *blob_data;
-
 
1462
   char *write_ptr;
1454
   char *write_ptr;
1463
   char *line_ptr;
1455
   char *line_ptr;
1464
   char *token;
1456
   char *token;
1465
   char *value;
1457
   char *value;
1466
   char *sep;
1458
   char *sep;
1467
   //char *ctx;
1459
   //char *ctx;
1468
   int arg_index;
1460
   int arg_index;
1469
   bool is_quoted_context = false;
1461
   bool is_quoted_context = false;
1470
   bool is_escaped_char = false;
1462
   bool is_escaped_char = false;
-
 
1463
   bool has_data_already = false;
1471
   bool want_info = false;
1464
   bool want_info = false;
1472
   bool want_help = false;
1465
   bool want_help = false;
1473
   bool is_foreign_endianness;
1466
   bool is_foreign_endianness;
1474
   int string_len;
1467
   int string_len;
1475
   int read_char;
1468
   int read_char;
Line 1573... Line 1566...
1573
   while (fgets (line_buffer, sizeof (line_buffer), buildfile_fp) != NULL)
1566
   while (fgets (line_buffer, sizeof (line_buffer), buildfile_fp) != NULL)
1574
   {
1567
   {
1575
      if (current_line != NULL)
1568
      if (current_line != NULL)
1576
         free (current_line);
1569
         free (current_line);
1577
      current_line = strdup (line_buffer);
1570
      current_line = strdup (line_buffer);
1578
      if (current_line == NULL)
-
 
1579
      {
-
 
1580
         fprintf (stderr, "fatal error: out of memory\n");
1571
      WELLMANNERED_ASSERT (current_line, "out of memory");
1581
         exit (1);
-
 
1582
      }
-
 
1583
      lineno++; // keep track of current line number
1572
      lineno++; // keep track of current line number
1584
      //fprintf (stderr, "read buildfile line %d: {%s}\n", lineno, line_buffer);
1573
      //fprintf (stderr, "read buildfile line %d: {%s}\n", lineno, line_buffer);
1585
 
1574
 
1586
      line_ptr = line_buffer;
1575
      line_ptr = line_buffer;
1587
      while ((*line_ptr != 0) && isspace (*line_ptr))
1576
      while ((*line_ptr != 0) && isspace (*line_ptr))
Line 1596... Line 1585...
1596
 
1585
 
1597
      // reset entry values
1586
      // reset entry values
1598
      memcpy (&entry_parms, &default_parms, sizeof (default_parms));
1587
      memcpy (&entry_parms, &default_parms, sizeof (default_parms));
1599
      path_in_ifs[0] = 0;
1588
      path_in_ifs[0] = 0;
1600
      path_on_buildhost[0] = 0;
1589
      path_on_buildhost[0] = 0;
-
 
1590
      has_data_already = false;
1601
 
1591
 
1602
      //fprintf (stderr, "parsing buildfile line %d: [%s]\n", lineno, line_ptr);
1592
      //fprintf (stderr, "parsing buildfile line %d: [%s]\n", lineno, line_ptr);
1603
 
1593
 
1604
      // does this line start with an attribute block ?
1594
      // does this line start with an attribute block ?
1605
      if (*line_ptr == '[')
1595
      if (*line_ptr == '[')
Line 1663... Line 1653...
1663
                  fprintf (stderr, "error: unable to stat the boot file \"%s\" specified in \"%s\" line %d: %s\n", bootfile_pathname, buildfile_pathname, lineno, strerror (errno));
1653
                  fprintf (stderr, "error: unable to stat the boot file \"%s\" specified in \"%s\" line %d: %s\n", bootfile_pathname, buildfile_pathname, lineno, strerror (errno));
1664
                  exit (1);
1654
                  exit (1);
1665
               }
1655
               }
1666
               bootfile_size = stat_buf.st_size; // save preboot file size
1656
               bootfile_size = stat_buf.st_size; // save preboot file size
1667
               fprintf (stderr, "info: processor \"%s\" bootfile \"%s\"\n", image_processor, bootfile_pathname);
1657
               fprintf (stderr, "info: processor \"%s\" bootfile \"%s\"\n", image_processor, bootfile_pathname);
1668
               if (stat (kernelfile_pathname, &stat_buf) != 0)
1658
               if (read_filecontents (kernelfile_pathname, ".", &entry_parms.data, &entry_parms.datalen) == NULL)
1669
               {
1659
               {
1670
                  fprintf (stderr, "fatal error: unable to read precompiled kernel file \"%s\" specified in --kernelfile argument\n", kernelfile_pathname);
1660
                  fprintf (stderr, "fatal error: unable to read precompiled kernel file \"%s\" specified in --kernelfile argument\n", kernelfile_pathname);
1671
                  exit (1);
1661
                  exit (1);
1672
               }
1662
               }
1673
               entry_parms.data = malloc (stat_buf.st_size);
1663
               has_data_already = true; // remember we already have data
1674
               if (entry_parms.data == NULL)
-
 
1675
               {
-
 
1676
                  fprintf (stderr, "fatal error: out of memory\n");
-
 
1677
                  exit (1);
-
 
1678
               }
-
 
1679
               fp = fopen (kernelfile_pathname, "rb");
-
 
1680
               fread (entry_parms.data, 1, stat_buf.st_size, fp);
-
 
1681
               fclose (fp);
-
 
1682
               entry_parms.datalen = stat_buf.st_size;
-
 
1683
            }
1664
            }
1684
            else if (strncmp (token, "mtime=", 6) == 0) { REACH_TOKEN_VALUE (); if (strcmp (value, "*") == 0) entry_parms.mtime = UINT32_MAX; else {
1665
            else if (strncmp (token, "mtime=", 6) == 0) { REACH_TOKEN_VALUE (); if (strcmp (value, "*") == 0) entry_parms.mtime = UINT32_MAX; else {
1685
                  // value *must* be "YYYY-MM-DD-HH:MM:SS" by specification
1666
                  // value *must* be "YYYY-MM-DD-HH:MM:SS" by specification
1686
                  memset (&utc_time, 0, sizeof (utc_time));
1667
                  memset (&utc_time, 0, sizeof (utc_time));
1687
                  if (sscanf (value, "%u-%u-%u-%u:%u:%u", &utc_time.tm_year, &utc_time.tm_mon, &utc_time.tm_mday, &utc_time.tm_hour, &utc_time.tm_min, &utc_time.tm_sec) != 6)
1668
                  if (sscanf (value, "%u-%u-%u-%u:%u:%u", &utc_time.tm_year, &utc_time.tm_mon, &utc_time.tm_mday, &utc_time.tm_hour, &utc_time.tm_min, &utc_time.tm_sec) != 6)
Line 1694... Line 1675...
1694
               }
1675
               }
1695
            }
1676
            }
1696
            else if (strcmp (token, "+script")     == 0) {
1677
            else if (strcmp (token, "+script")     == 0) {
1697
               entry_parms.is_compiled_bootscript = true;
1678
               entry_parms.is_compiled_bootscript = true;
1698
               entry_parms.data = malloc (sizeof (INITIAL_STARTUP_SCRIPT) - 1);
1679
               entry_parms.data = malloc (sizeof (INITIAL_STARTUP_SCRIPT) - 1);
1699
               if (entry_parms.data == NULL)
-
 
1700
               {
-
 
1701
                  fprintf (stderr, "fatal error: out of memory\n");
1680
               WELLMANNERED_ASSERT (entry_parms.data, "out of memory");
1702
                  exit (1);
-
 
1703
               }
-
 
1704
               memcpy (entry_parms.data, INITIAL_STARTUP_SCRIPT, sizeof (INITIAL_STARTUP_SCRIPT) - 1); // FIXME: HACK until the script compiler is implemented
1681
               memcpy (entry_parms.data, INITIAL_STARTUP_SCRIPT, sizeof (INITIAL_STARTUP_SCRIPT) - 1); // FIXME: HACK until the script compiler is implemented
1705
               entry_parms.datalen = sizeof (INITIAL_STARTUP_SCRIPT) - 1;
1682
               entry_parms.datalen = sizeof (INITIAL_STARTUP_SCRIPT) - 1;
-
 
1683
               has_data_already = true; // remember we already have data
1706
            }
1684
            }
1707
            else if (strcmp (token, "-script")     == 0) entry_parms.is_compiled_bootscript = false;
1685
            else if (strcmp (token, "-script")     == 0) entry_parms.is_compiled_bootscript = false;
1708
            else if (strcmp (token, "+followlink") == 0) entry_parms.should_follow_symlinks = true;
1686
            else if (strcmp (token, "+followlink") == 0) entry_parms.should_follow_symlinks = true;
1709
            else if (strcmp (token, "-followlink") == 0) entry_parms.should_follow_symlinks = false;
1687
            else if (strcmp (token, "-followlink") == 0) entry_parms.should_follow_symlinks = false;
1710
            else if (strcmp (token, "+autolink")   == 0) entry_parms.should_autosymlink_dylib = true;
1688
            else if (strcmp (token, "+autolink")   == 0) entry_parms.should_autosymlink_dylib = true;
Line 1807... Line 1785...
1807
               if (read_char == EOF)
1785
               if (read_char == EOF)
1808
               {
1786
               {
1809
                  fprintf (stderr, "fatal error: syntax error in \"%s\" line %d: unterminated contents block (end of file reached)\n", buildfile_pathname, lineno);
1787
                  fprintf (stderr, "fatal error: syntax error in \"%s\" line %d: unterminated contents block (end of file reached)\n", buildfile_pathname, lineno);
1810
                  exit (1); // invalid contents block
1788
                  exit (1); // invalid contents block
1811
               }
1789
               }
1812
               else if (read_char == '\\')
1790
               else if ((read_char == '\\') && !is_escaped_char)
1813
                  is_escaped_char = true; // remember the next char is escaped
1791
                  is_escaped_char = true; // remember the next char is escaped
1814
               else if ((read_char == '}') && !is_escaped_char)
1792
               else if ((read_char == '}') && !is_escaped_char)
1815
                  break; // found an unescaped closing bracked, stop parsing
1793
                  break; // found an unescaped closing bracked, stop parsing
1816
               else
1794
               else
1817
               {
1795
               {
1818
                  is_escaped_char = false; // any other char, meaning the next one will not be escaped
1796
                  is_escaped_char = false; // any other char, meaning the next one will not be escaped
1819
                  if (entry_parms.data == NULL) // only store the contents if we do NOT know the data yet
1797
                  if (!has_data_already) // only store the contents if we do NOT know the data yet
1820
                  {
1798
                  {
1821
                     if (entry_parms.datalen == allocated_size) // reallocate in 4 kb blocks
1799
                     if (entry_parms.datalen == allocated_size) // reallocate in 4 kb blocks
1822
                     {
1800
                     {
1823
                        reallocated_ptr = realloc (entry_parms.data, allocated_size + 4096);
1801
                        reallocated_ptr = realloc (entry_parms.data, allocated_size + 4096);
1824
                        if (reallocated_ptr == NULL)
-
 
1825
                        {
-
 
1826
                           fprintf (stderr, "fatal error: out of memory\n");
1802
                        WELLMANNERED_ASSERT (reallocated_ptr, "out of memory");
1827
                           exit (1);
-
 
1828
                        }
-
 
1829
                        entry_parms.data = reallocated_ptr;
1803
                        entry_parms.data = reallocated_ptr;
1830
                        allocated_size += 4096;
1804
                        allocated_size += 4096;
1831
                     }
1805
                     }
1832
                     entry_parms.data[entry_parms.datalen++] = read_char;
1806
                     entry_parms.data[entry_parms.datalen++] = read_char;
1833
                  }
1807
                  }
1834
                  if (read_char == '\n')
1808
                  if (read_char == '\n')
1835
                     lineno++;
1809
                     lineno++; // update line counter as we parse the inline content
1836
               }
1810
               }
1837
            }
1811
            } // end for
-
 
1812
            has_data_already = true; // remember we have data now
1838
         }
1813
         }
1839
         else // not a content definition between { brackets }, must be either a pathname on the build host, or the target of a symlink
1814
         else // not a content definition between { brackets }, must be either a pathname on the build host, or the target of a symlink
1840
         {
1815
         {
1841
            is_quoted_context = (*line_ptr == '"');
1816
            is_quoted_context = (*line_ptr == '"');
1842
            if (is_quoted_context)
1817
            if (is_quoted_context)
Line 1858... Line 1833...
1858
            if (is_quoted_context && (*line_ptr == '"'))
1833
            if (is_quoted_context && (*line_ptr == '"'))
1859
               line_ptr++; // skip a possible final quote
1834
               line_ptr++; // skip a possible final quote
1860
 
1835
 
1861
            if (S_ISLNK (entry_parms.st_mode)) // are we storing a symlink ?
1836
            if (S_ISLNK (entry_parms.st_mode)) // are we storing a symlink ?
1862
            {
1837
            {
1863
               entry_parms.datalen = strlen (specifiedpathname_start); // if so, store the symlink target as the dirent's blob data
1838
               entry_parms.data = strdup (specifiedpathname_start); // if so, store the symlink target as the dirent's blob data
1864
               entry_parms.data = strdup (specifiedpathname_start);
1839
               WELLMANNERED_ASSERT (entry_parms.data, "out of memory");
1865
               if (entry_parms.data == NULL)
1840
               entry_parms.datalen = strlen (specifiedpathname_start);
1866
               {
-
 
1867
                  fprintf (stderr, "fatal error: out of memory\n");
1841
               has_data_already = true; // remember we have data now
1868
                  exit (1);
-
 
1869
               }
-
 
1870
            }
1842
            }
1871
            else // it's a build host filesystem path
1843
            else // it's a build host filesystem path
1872
               strcpy (path_on_buildhost, line_ptr); // the path on the build host is given after the equal sign
1844
               strcpy (path_on_buildhost, line_ptr); // the path on the build host is given after the equal sign
1873
         }
1845
         }
1874
      }
1846
      }
Line 1937... Line 1909...
1937
      startup_header.ram_size      = WILL_BE_FILLED_LATER;                                  // [ S] Amount of RAM used by the startup program and executables contained in the file system, here 0x00cd6128 i.e. 13 459 752 dec. which is 13 Mb. i.e. IFS file size minus 0x9eee (40686)
1909
      startup_header.ram_size      = WILL_BE_FILLED_LATER;                                  // [ S] Amount of RAM used by the startup program and executables contained in the file system, here 0x00cd6128 i.e. 13 459 752 dec. which is 13 Mb. i.e. IFS file size minus 0x9eee (40686)
1938
      startup_header.startup_size  = WILL_BE_FILLED_LATER;                                  // [I ] Size of startup (never compressed), here 0x02f148 or 192 840 bytes
1910
      startup_header.startup_size  = WILL_BE_FILLED_LATER;                                  // [I ] Size of startup (never compressed), here 0x02f148 or 192 840 bytes
1939
      startup_header.stored_size   = WILL_BE_FILLED_LATER;                                  // [I ] Size of entire image, here 0x00cd6128 (same as ram_size)
1911
      startup_header.stored_size   = WILL_BE_FILLED_LATER;                                  // [I ] Size of entire image, here 0x00cd6128 (same as ram_size)
1940
      startup_header.imagefs_size  = WILL_BE_FILLED_LATER;                                  // [ S] Size of uncompressed imagefs, here 0x00ca6fe0 or 13 266 912 bytes
1912
      startup_header.imagefs_size  = WILL_BE_FILLED_LATER;                                  // [ S] Size of uncompressed imagefs, here 0x00ca6fe0 or 13 266 912 bytes
1941
      startup_header.preboot_size  = (uint16_t) bootfile_size;                              // [I ] Size of loaded before header, here 0xf30 or 3888 bytes (size of "bios.boot" file))
1913
      startup_header.preboot_size  = (uint16_t) bootfile_size;                              // [I ] Size of loaded before header, here 0xf30 or 3888 bytes (size of "bios.boot" file))
1942
      fwrite (&startup_header, sizeof (startup_header), 1, fp); // write startup header
1914
      fwrite_or_die (&startup_header, 1, sizeof (startup_header), fp); // write startup header
1943
      PAD_OUTFILE_TO (ROUND_TO_UPPER_MULTIPLE (ftell (fp), image_align)); // pad as necessary
1915
      PAD_OUTFILE_TO (ROUND_TO_UPPER_MULTIPLE (ftell (fp), image_align)); // pad as necessary
1944
 
1916
 
1945
      // ######################################################################################################################################################################################################################################
1917
      // ######################################################################################################################################################################################################################################
1946
      // # FIXME: figure out how to re-create it: linker call involved
1918
      // # FIXME: figure out how to re-create it: linker call involved
1947
      // # $ x86_64-pc-nto-qnx8.0.0-ld --sysroot=${QNX_TARGET}/x86_64/ -T${QNX_TARGET}/x86_64/lib/nto.link --section-start .text=0x1401030 --no-relax ${QNX_TARGET}/x86_64/boot/sys/startup-x86 -o startup.bin.UNSTRIPPED
1919
      // # $ x86_64-pc-nto-qnx8.0.0-ld --sysroot=${QNX_TARGET}/x86_64/ -T${QNX_TARGET}/x86_64/lib/nto.link --section-start .text=0x1401030 --no-relax ${QNX_TARGET}/x86_64/boot/sys/startup-x86 -o startup.bin.UNSTRIPPED
1948
      // ######################################################################################################################################################################################################################################
1920
      // ######################################################################################################################################################################################################################################
1949
      fwrite_filecontents (startupfile_pathname, fp); // write startup code from blob file
1921
      fwrite_filecontents (startupfile_pathname, fp); // write startup code from blob file
1950
      PAD_OUTFILE_TO (ROUND_TO_UPPER_MULTIPLE (ftell (fp), image_align)); // pad as necessary
1922
      PAD_OUTFILE_TO (ROUND_TO_UPPER_MULTIPLE (ftell (fp), image_align)); // pad as necessary
1951
 
1923
 
1952
      startuptrailer_offset = ftell (fp); // save startup trailer offset
1924
      startuptrailer_offset = ftell (fp); // save startup trailer offset
1953
      fwrite (&startup_trailer, sizeof (startup_trailer), 1, fp); // write startup trailer
1925
      fwrite_or_die (&startup_trailer, 1, sizeof (startup_trailer), fp); // write startup trailer
1954
      PAD_OUTFILE_TO (ROUND_TO_UPPER_MULTIPLE (ftell (fp), image_align)); // pad as necessary
1926
      PAD_OUTFILE_TO (ROUND_TO_UPPER_MULTIPLE (ftell (fp), image_align)); // pad as necessary
1955
   }
1927
   }
1956
 
1928
 
1957
   imgheader_offset = ftell (fp); // save image header offset
1929
   imageheader_offset = ftell (fp); // save image header offset
1958
   memset (&image_header, 0, sizeof (image_header)); // prepare image header
1930
   memset (&image_header, 0, sizeof (image_header)); // prepare image header
1959
   memcpy (&image_header.signature, "imagefs", 7); // image filesystem signature, i.e. "imagefs"
1931
   memcpy (&image_header.signature, "imagefs", 7); // image filesystem signature, i.e. "imagefs"
1960
   image_header.flags         = IMAGE_FLAGS_TRAILER_V2 | IMAGE_FLAGS_SORTED | IMAGE_FLAGS_INO_BITS; // endian neutral flags, 0x1c (IMAGE_FLAGS_TRAILER_V2 | IMAGE_FLAGS_SORTED | IMAGE_FLAGS_INO_BITS)
1932
   image_header.flags         = IMAGE_FLAGS_TRAILER_V2 | IMAGE_FLAGS_SORTED | IMAGE_FLAGS_INO_BITS; // endian neutral flags, 0x1c (IMAGE_FLAGS_TRAILER_V2 | IMAGE_FLAGS_SORTED | IMAGE_FLAGS_INO_BITS)
1961
   image_header.image_size    = WILL_BE_FILLED_LATER; // size from header to end of trailer (here 0xca6fe0 or 13 266 912)
1933
   image_header.image_size    = WILL_BE_FILLED_LATER; // size from header to end of trailer (here 0xca6fe0 or 13 266 912)
1962
   image_header.hdr_dir_size  = WILL_BE_FILLED_LATER; // size from header to last dirent (here 0x12b8 or 4792)
1934
   image_header.hdr_dir_size  = WILL_BE_FILLED_LATER; // size from header to last dirent (here 0x12b8 or 4792)
1963
   image_header.dir_offset    = sizeof (image_header); // offset from header to first dirent (here 0x5c or 92)
1935
   image_header.dir_offset    = sizeof (image_header); // offset from header to first dirent (here 0x5c or 92)
1964
   image_header.boot_ino[0]   = image_kernel_ino; // inode of files for bootstrap p[ro?]g[ra?]ms (here 0xa0000002, 0, 0, 0)
1936
   image_header.boot_ino[0]   = image_kernel_ino; // inode of files for bootstrap p[ro?]g[ra?]ms (here 0xa0000002, 0, 0, 0)
1965
   image_header.script_ino    = image_bootscript_ino; // inode of file for script (here 3)
1937
   image_header.script_ino    = image_bootscript_ino; // inode of file for script (here 3)
1966
   image_header.mountpoint[0] = '/'; // default mountpoint for image ("/" + "\0\0\0")
1938
   image_header.mountpoint[0] = '/'; // default mountpoint for image ("/" + "\0\0\0")
1967
   fwrite (&image_header, sizeof (image_header), 1, fp); // write image header
1939
   fwrite_or_die (&image_header, 1, sizeof (image_header), fp); // write image header
1968
   PAD_OUTFILE_TO (ROUND_TO_UPPER_MULTIPLE (ftell (fp), image_align)); // pad as necessary
1940
   PAD_OUTFILE_TO (ROUND_TO_UPPER_MULTIPLE (ftell (fp), image_align)); // pad as necessary
1969
 
1941
 
1970
   // write image directory (with the wrong file offsets)
1942
   // write image directory (with the wrong file offsets)
1971
   if (image_header.flags & IMAGE_FLAGS_SORTED)
-
 
1972
      qsort (&fsentries[1], fsentry_count - 1, sizeof (fsentry_t), fsentry_compare_pathnames_cb); // sort the filesystem entries by pathname
-
 
1973
   imgdir_offset = ftell (fp);
1943
   imgdir_offset = ftell (fp);
1974
   imgdir_size = 0; // measure image dir size on the fly
1944
   imgdir_size = 0; // measure image dir size on the fly
1975
   for (fsentry_index = 0; fsentry_index < fsentry_count; fsentry_index++)
1945
   for (fsentry_index = 0; fsentry_index < fsentry_count; fsentry_index++)
1976
      imgdir_size += fwrite_fsentry (&fsentries[fsentry_index], fp); // NOTE: padding is handled in this function
1946
      imgdir_size += fwrite_fsentry (&fsentries[fsentry_index], fp); // NOTE: padding is handled in this function
-
 
1947
 
1977
   imgdir_size += fwrite ("\0\0\0\0", 1, 4, fp); // there seems to be 4 bytes of padding after the image directory
1948
   fwrite_or_die ("\0\0\0\0", 1, 4, fp); // there seems to be 4 bytes of padding after the image directory
-
 
1949
   imgdir_size += 4;
1978
 
1950
 
1979
   // is it a bootable image with a kernel file ?
1951
   // is it a bootable image with a kernel file ?
1980
   if ((startupfile_pathname != NULL) && (kernelfile_pathname != NULL))
1952
   if ((startupfile_pathname != NULL) && (kernelfile_pathname != NULL))
1981
   {
1953
   {
1982
      // start by writing the startup script data blob, if we have one
1954
      // start by writing the startup script data blob, if we have one
1983
      for (fsentry_index = 1; fsentry_index < fsentry_count; fsentry_index++)
1955
      for (fsentry_index = 1; fsentry_index < fsentry_count; fsentry_index++)
1984
         if (fsentries[fsentry_index].header.ino == image_bootscript_ino)
1956
         if (fsentries[fsentry_index].header.ino == image_bootscript_ino)
1985
            break; // locate it
1957
            break; // locate the startup script directory entry
1986
      if (fsentry_index < fsentry_count) // found it ?
1958
      if (fsentry_index < fsentry_count) // found it ?
1987
      {
1959
      {
1988
         curr_offset = ftell (fp);
1960
         curr_offset = ftell (fp);
1989
         if (curr_offset + fsentries[fsentry_index].u.file.size >= kernelfile_offset)
1961
         if (curr_offset + fsentries[fsentry_index].u.file.size >= kernelfile_offset)
1990
         {
1962
         {
1991
            fprintf (stderr, "error: the compiled startup script is too big (%zd bytes, max is %zd) to fit at current offset %zd\n", (size_t) fsentries[fsentry_index].u.file.size, kernelfile_offset - curr_offset, curr_offset);
1963
            fprintf (stderr, "error: the compiled startup script is too big (%zd bytes, max is %zd) to fit at current offset %zd\n", (size_t) fsentries[fsentry_index].u.file.size, kernelfile_offset - curr_offset, curr_offset);
1992
            exit (1);
1964
            exit (1);
1993
         }
1965
         }
1994
         fsentries[fsentry_index].u.file.offset = (uint32_t) (curr_offset - imgheader_offset); // save file data blob offset in file structure
1966
         fsentries[fsentry_index].u.file.offset = (uint32_t) (curr_offset - imageheader_offset); // save file data blob offset in file structure
1995
         fwrite (fsentries[fsentry_index].u.file.UNSAVED_databuf, 1, fsentries[fsentry_index].u.file.size, fp); // write file data blob
1967
         fwrite_or_die (fsentries[fsentry_index].u.file.UNSAVED_databuf, 1, fsentries[fsentry_index].u.file.size, fp); // write file data blob
1996
//            PAD_OUTFILE_TO (ROUND_TO_UPPER_MULTIPLE (ftell (fp), image_align)); // pad as necessary
-
 
1997
         fsentries[fsentry_index].UNSAVED_was_data_written = true; // and remember this file's data was written
1968
         fsentries[fsentry_index].UNSAVED_was_data_written = true; // and remember this file's data was written
1998
      }
1969
      }
1999
 
1970
 
2000
      // now write the filesystem entries that may fit before the kernel
1971
      // now write the filesystem entries that may fit before the kernel
2001
      for (;;)
1972
      for (;;)
Line 2003... Line 1974...
2003
         curr_offset = ftell (fp); // see where we are
1974
         curr_offset = ftell (fp); // see where we are
2004
         available_space = kernelfile_offset - curr_offset; // measure the available space
1975
         available_space = kernelfile_offset - curr_offset; // measure the available space
2005
 
1976
 
2006
         // look for the biggest one that can fit
1977
         // look for the biggest one that can fit
2007
         largest_index = 0;
1978
         largest_index = 0;
2008
         largest_size = SIZE_MAX;
1979
         largest_size = 0;
2009
         for (fsentry_index = 1; fsentry_index < fsentry_count; fsentry_index++)
1980
         for (fsentry_index = 1; fsentry_index < fsentry_count; fsentry_index++)
2010
         {
1981
         {
2011
            if (!S_ISREG (fsentries[fsentry_index].header.mode) || fsentries[fsentry_index].UNSAVED_was_data_written || (fsentries[fsentry_index].u.file.size > available_space))
1982
            if (!S_ISREG (fsentries[fsentry_index].header.mode) || fsentries[fsentry_index].UNSAVED_was_data_written || (fsentries[fsentry_index].u.file.size > available_space))
2012
               continue; // skip all entries that don't have a separate data block, those who were written already and those that wouldn't fit
1983
               continue; // skip all entries that don't have a separate data block, those who were written already and those that wouldn't fit
2013
            if (fsentries[fsentry_index].u.file.size > largest_size)
1984
            if (fsentries[fsentry_index].u.file.size > largest_size)
2014
            {
1985
            {
2015
               largest_size = fsentries[fsentry_index].u.file.size;
1986
               largest_size = fsentries[fsentry_index].u.file.size;
2016
               largest_index = fsentry_index;
1987
               largest_index = fsentry_index;
2017
            }
1988
            }
2018
         }
1989
         }
2019
         if (largest_size == SIZE_MAX)
1990
         if (largest_size == 0)
2020
            break; // found none ? if so, stop searching
1991
            break; // found none ? if so, stop searching
2021
 
1992
 
2022
         fsentries[largest_index].u.file.offset = (uint32_t) (curr_offset - imgheader_offset); // save file data blob offset in file structure
1993
         fsentries[largest_index].u.file.offset = (uint32_t) (curr_offset - imageheader_offset); // save file data blob offset in file structure
2023
         fwrite (fsentries[largest_index].u.file.UNSAVED_databuf, 1, fsentries[largest_index].u.file.size, fp); // write file data blob
1994
         fwrite_or_die (fsentries[largest_index].u.file.UNSAVED_databuf, 1, fsentries[largest_index].u.file.size, fp); // write file data blob
2024
//         PAD_OUTFILE_TO (ROUND_TO_UPPER_MULTIPLE (ftell (fp), image_align)); // pad as necessary
-
 
2025
         fsentries[largest_index].UNSAVED_was_data_written = true; // and remember this file's data was written
1995
         fsentries[largest_index].UNSAVED_was_data_written = true; // and remember this file's data was written
2026
      }
1996
      }
2027
      PAD_OUTFILE_TO (kernelfile_offset); // reach the kernel offset
1997
      PAD_OUTFILE_TO (kernelfile_offset); // reach the kernel offset
2028
 
1998
 
-
 
1999
      // now write the QNX kernel
-
 
2000
      for (fsentry_index = 1; fsentry_index < fsentry_count; fsentry_index++)
-
 
2001
         if (fsentries[fsentry_index].header.ino == image_kernel_ino)
-
 
2002
            break; // locate the kernel directory entry (can't fail)
-
 
2003
      curr_offset = ftell (fp); // see where we are
-
 
2004
      fsentries[fsentry_index].u.file.offset = (uint32_t) (curr_offset - imageheader_offset); // save file data blob offset in file structure
2029
      // ######################################################################################################################################################################################################################################
2005
      // ######################################################################################################################################################################################################################################
2030
      // # FIXME: figure out how to re-create it: linker call involved
2006
      // # FIXME: figure out how to re-create it: linker call involved
2031
      // # $ x86_64-pc-nto-qnx8.0.0-ld --sysroot=${QNX_TARGET}/x86_64/ -T${QNX_TARGET}/x86_64/lib/nto.link --section-start .text=0xffff800000001000 --no-relax ${QNX_TARGET}/x86_64/boot/sys/procnto-smp-instr -o procnto-smp-instr.sym.UNSTRIPPED
2007
      // # $ x86_64-pc-nto-qnx8.0.0-ld --sysroot=${QNX_TARGET}/x86_64/ -T${QNX_TARGET}/x86_64/lib/nto.link --section-start .text=0xffff800000001000 --no-relax ${QNX_TARGET}/x86_64/boot/sys/procnto-smp-instr -o procnto-smp-instr.sym.UNSTRIPPED
2032
      // ######################################################################################################################################################################################################################################
2008
      // ######################################################################################################################################################################################################################################
2033
      fwrite_filecontents (kernelfile_pathname, fp); // write kernel from blob file
2009
      fwrite_filecontents (kernelfile_pathname, fp); // write kernel from blob file
2034
      PAD_OUTFILE_TO (ROUND_TO_UPPER_MULTIPLE (ftell (fp), image_align)); // pad as necessary
2010
      PAD_OUTFILE_TO (ROUND_TO_UPPER_MULTIPLE (ftell (fp), image_align)); // pad as necessary
-
 
2011
      fsentries[fsentry_index].UNSAVED_was_data_written = true; // and remember this file's data was written
2035
   }
2012
   }
2036
 
2013
 
2037
   // then write all the other files
2014
   // then write all the other files by increasing inode number: ELF files first
2038
   for (fsentry_index = 1; fsentry_index < fsentry_count; fsentry_index++)
2015
   for (fsentry_index = 1; fsentry_index < fsentry_count; fsentry_index++)
2039
   {
2016
   {
2040
      if (!S_ISREG (fsentries[fsentry_index].header.mode) || fsentries[fsentry_index].UNSAVED_was_data_written)
2017
      if (!S_ISREG (fsentries[fsentry_index].header.mode) || fsentries[fsentry_index].UNSAVED_was_data_written // filter out anything that's not a file, and anything that's been already written
-
 
2018
          || (fsentries[fsentry_index].u.file.size < 4) || (memcmp (fsentries[fsentry_index].u.file.UNSAVED_databuf, ELF_MAGIC_STR, 4) != 0)) // filter out anything that's not an ELF file
2041
         continue; // skip all entries that don't have a separate data block and those who were written already
2019
         continue; // skip all entries that don't have a separate data block and those who were written already
2042
      curr_offset = ftell (fp);
2020
      curr_offset = ftell (fp);
2043
      fsentries[fsentry_index].u.file.offset = (uint32_t) (curr_offset - imgheader_offset); // save file data blob offset in file structure
2021
      fsentries[fsentry_index].u.file.offset = (uint32_t) (curr_offset - imageheader_offset); // save file data blob offset in file structure
2044
      fwrite (fsentries[fsentry_index].u.file.UNSAVED_databuf, 1, fsentries[fsentry_index].u.file.size, fp); // write file data blob
2022
      fwrite_or_die (fsentries[fsentry_index].u.file.UNSAVED_databuf, 1, fsentries[fsentry_index].u.file.size, fp); // write file data blob
2045
//      PAD_OUTFILE_TO (ROUND_TO_UPPER_MULTIPLE (ftell (fp), image_align)); // pad as necessary
-
 
2046
      fsentries[fsentry_index].UNSAVED_was_data_written = true; // and remember this file's data was written
2023
      fsentries[fsentry_index].UNSAVED_was_data_written = true; // and remember this file's data was written
2047
   }
2024
   }
-
 
2025
   for (fsentry_index = 1; fsentry_index < fsentry_count; fsentry_index++) // other files (non-ELF, e.g. scripts and data files) last
-
 
2026
   {
-
 
2027
      if (!S_ISREG (fsentries[fsentry_index].header.mode) || fsentries[fsentry_index].UNSAVED_was_data_written) // filter out anything that's not a file, and anything that's been already written
-
 
2028
         continue; // skip all entries that don't have a separate data block and those who were written already
-
 
2029
      curr_offset = ftell (fp);
-
 
2030
      fsentries[fsentry_index].u.file.offset = (uint32_t) (curr_offset - imageheader_offset); // save file data blob offset in file structure
-
 
2031
      fwrite_or_die (fsentries[fsentry_index].u.file.UNSAVED_databuf, 1, fsentries[fsentry_index].u.file.size, fp); // write file data blob
-
 
2032
      fsentries[fsentry_index].UNSAVED_was_data_written = true; // and remember this file's data was written
-
 
2033
   }
-
 
2034
   PAD_OUTFILE_TO (ROUND_TO_UPPER_MULTIPLE (ftell (fp), image_align)); // pad as necessary
2048
 
2035
 
2049
   // finally, write trailer (including empty checksum)
2036
   // finally, write trailer (including empty checksum)
2050
   imgtrailer_offset = ftell (fp); // save image trailer offset
2037
   imagetrailer_offset = ftell (fp); // save image trailer offset
2051
   fwrite (&image_trailer, sizeof (image_trailer), 1, fp); // write image trailer
2038
   fwrite_or_die (&image_trailer, 1, sizeof (image_trailer), fp); // write image trailer
2052
   PAD_OUTFILE_TO (ROUND_TO_UPPER_MULTIPLE (ftell (fp), image_align)); // pad as necessary
2039
   PAD_OUTFILE_TO (ROUND_TO_UPPER_MULTIPLE (ftell (fp), image_align)); // pad as necessary
2053
 
2040
 
2054
   // if we need to pad it to a specific length, do so
2041
   // if we need to pad it to a specific length, do so
2055
   PAD_OUTFILE_TO (image_totalsize);
2042
   PAD_OUTFILE_TO (image_totalsize);
2056
   final_size = ftell (fp);
2043
   final_size = ftell (fp);
Line 2064... Line 2051...
2064
 
2051
 
2065
   // do we have a startup file ? if so, this is a bootable image
2052
   // do we have a startup file ? if so, this is a bootable image
2066
   if (startupfile_pathname != NULL)
2053
   if (startupfile_pathname != NULL)
2067
   {
2054
   {
2068
      // rewrite startup header with final values
2055
      // rewrite startup header with final values
2069
      fseek (fp, startupheader_offset, SEEK_SET);
2056
      fseek_or_die (fp, startupheader_offset, SEEK_SET);
2070
      startup_header.startup_size = (uint32_t) (imgheader_offset - startupheader_offset); // size of startup header up to image header
2057
      startup_header.startup_size = (uint32_t) (imageheader_offset - startupheader_offset); // size of startup header up to image header
2071
      startup_header.imagefs_size = (uint32_t) (final_size - imgheader_offset); // size of uncompressed imagefs
2058
      startup_header.imagefs_size = (uint32_t) (final_size - imageheader_offset); // size of uncompressed imagefs
2072
      startup_header.ram_size = (uint32_t) final_size; // FIXME: this is necessarily a bit less, but should we really bother calculating the right size ?
2059
      startup_header.ram_size = (uint32_t) final_size; // FIXME: this is necessarily less, but should we really bother calculating the right size ?
2073
      startup_header.stored_size = startup_header.ram_size;
2060
      startup_header.stored_size = (uint32_t) final_size;
2074
      fwrite (&startup_header, sizeof (startup_header), 1, fp); // write startup header
2061
      fwrite_or_die (&startup_header, 1, sizeof (startup_header), fp); // write startup header
-
 
2062
   }
2075
 
2063
 
-
 
2064
   // rewrite image header with final values
-
 
2065
   fseek_or_die (fp, imageheader_offset, SEEK_SET);
-
 
2066
   image_header.image_size = (uint32_t) (final_size - imageheader_offset); // size of uncompressed imagefs
-
 
2067
   image_header.hdr_dir_size = sizeof (image_header) + (uint32_t) imgdir_size; // size from start of image header to last dirent
-
 
2068
   fwrite_or_die (&image_header, 1, sizeof (image_header), fp); // write image header
-
 
2069
 
-
 
2070
   // rewrite image directory with final offset values
-
 
2071
   fseek_or_die (fp, imgdir_offset, SEEK_SET);
-
 
2072
   if (image_header.flags & IMAGE_FLAGS_SORTED)
-
 
2073
      qsort (&fsentries[1], fsentry_count - 1, sizeof (fsentry_t), fsentry_compare_pathnames_cb); // sort the filesystem entries by pathname
-
 
2074
   for (fsentry_index = 0; fsentry_index < fsentry_count; fsentry_index++)
-
 
2075
      fwrite_fsentry (&fsentries[fsentry_index], fp);
-
 
2076
 
-
 
2077
   fclose (fp); // ensure everything is flushed
-
 
2078
 
-
 
2079
   // ALL CHECKSUMS AT THE VERY END
-
 
2080
 
-
 
2081
   blob_data = NULL;
-
 
2082
   read_filecontents (ifs_pathname, ".", &blob_data, &blob_size);
-
 
2083
   WELLMANNERED_ASSERT (blob_data, "failed to open IFS file for checksumming: %s", strerror (errno));
-
 
2084
 
-
 
2085
   // do we have a startup file ? if so, this is a bootable image
-
 
2086
   if (startupfile_pathname != NULL)
-
 
2087
   {
2076
      // compute SHA-512 checksum and V1 checksum of startup block
2088
      // compute SHA-512 checksum and V1 checksum of startup block
2077
      blob_size = startuptrailer_offset - startupheader_offset;
-
 
2078
      blob_data = malloc (blob_size + sizeof (startup_trailer));
-
 
2079
      if (blob_data == NULL)
-
 
2080
      {
-
 
2081
         fprintf (stderr, "fatal error: out of memory\n");
-
 
2082
         exit (1);
-
 
2083
      }
-
 
2084
      fseek (fp, startupheader_offset, SEEK_SET);
-
 
2085
      fread (blob_data, 1, blob_size, fp);
-
 
2086
      SHA512 (blob_data, blob_size, startup_trailer.sha512); // compute SHA512 checksum
-
 
2087
      if (   ( (startup_header.flags1 & STARTUP_HDR_FLAGS1_BIGENDIAN) && (__BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__))
2089
      if (   ( (startup_header.flags1 & STARTUP_HDR_FLAGS1_BIGENDIAN) && (__BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__))
2088
          || (!(startup_header.flags1 & STARTUP_HDR_FLAGS1_BIGENDIAN) && (__BYTE_ORDER__ == __ORDER_BIG_ENDIAN__)))
2090
          || (!(startup_header.flags1 & STARTUP_HDR_FLAGS1_BIGENDIAN) && (__BYTE_ORDER__ == __ORDER_BIG_ENDIAN__)))
2089
         is_foreign_endianness = true; // if the header is big endian and we're on a little endian machine, or the other way around, it's a foreign endianness
2091
         is_foreign_endianness = true; // if the header is big endian and we're on a little endian machine, or the other way around, it's a foreign endianness
2090
      else
2092
      else
2091
         is_foreign_endianness = false; // else this header is for the same endianness as us
2093
         is_foreign_endianness = false; // else this header is for the same endianness as us
2092
      fseek (fp, startupheader_offset, SEEK_SET);
-
 
2093
      fread (blob_data, 1, blob_size + SHA512_DIGEST_LENGTH, fp);
-
 
2094
      startup_trailer.cksum = update_checksum (blob_data, blob_size + SHA512_DIGEST_LENGTH, is_foreign_endianness); // compute old checksum
-
 
2095
      free (blob_data);
-
 
2096
 
2094
 
2097
      // rewrite startup trailer with final values
2095
      SHA512 (&blob_data[startupheader_offset], startuptrailer_offset - startupheader_offset, &blob_data[startuptrailer_offset]); // compute SHA512 checksum and write it in place in blob data
2098
      fseek (fp, startuptrailer_offset, SEEK_SET);
2096
      checksum = update_checksum (&blob_data[startupheader_offset], startuptrailer_offset + SHA512_DIGEST_LENGTH - startupheader_offset, is_foreign_endianness); // compute old checksum
2099
      fwrite (&startup_trailer, sizeof (startup_trailer), 1, fp); // write startup trailer
2097
      memcpy (&blob_data[startuptrailer_offset + SHA512_DIGEST_LENGTH], &checksum, 4); // and write it in place
2100
   }
2098
   }
2101
 
-
 
2102
   // rewrite image header with final values
-
 
2103
   fseek (fp, imgheader_offset, SEEK_SET);
-
 
2104
   image_header.image_size = (uint32_t) (final_size - imgheader_offset); // size of uncompressed imagefs
-
 
2105
   image_header.hdr_dir_size = sizeof (image_header) + (uint32_t) imgdir_size; // size from start of image header to last dirent
-
 
2106
   fwrite (&image_header, sizeof (image_header), 1, fp); // write image header
-
 
2107
 
-
 
2108
   // rewrite image directory with final offset values
-
 
2109
   fseek (fp, imgdir_offset, SEEK_SET);
-
 
2110
   for (fsentry_index = 0; fsentry_index < fsentry_count; fsentry_index++)
-
 
2111
      fwrite_fsentry (&fsentries[fsentry_index], fp);
-
 
2112
 
2099
 
2113
   // compute SHA-512 checksum and V1 checksum of image block
2100
   // compute SHA-512 checksum and V1 checksum of image block
2114
   blob_size = imgtrailer_offset - imgheader_offset;
-
 
2115
   blob_data = malloc (blob_size + sizeof (image_trailer));
-
 
2116
   if (blob_data == NULL)
-
 
2117
   {
-
 
2118
      fprintf (stderr, "fatal error: out of memory\n");
-
 
2119
      exit (1);
-
 
2120
   }
-
 
2121
   fseek (fp, imgheader_offset, SEEK_SET);
-
 
2122
   fread (blob_data, 1, blob_size, fp);
-
 
2123
   SHA512 (blob_data, blob_size, image_trailer.sha512); // compute SHA512 checksum
-
 
2124
   if (   ( (image_header.flags & IMAGE_FLAGS_BIGENDIAN) && (__BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__))
2101
   if (   ( (image_header.flags & IMAGE_FLAGS_BIGENDIAN) && (__BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__))
2125
       || (!(image_header.flags & IMAGE_FLAGS_BIGENDIAN) && (__BYTE_ORDER__ == __ORDER_BIG_ENDIAN__)))
2102
       || (!(image_header.flags & IMAGE_FLAGS_BIGENDIAN) && (__BYTE_ORDER__ == __ORDER_BIG_ENDIAN__)))
2126
      is_foreign_endianness = true; // if the header is big endian and we're on a little endian machine, or the other way around, it's a foreign endianness
2103
      is_foreign_endianness = true; // if the header is big endian and we're on a little endian machine, or the other way around, it's a foreign endianness
2127
   else
2104
   else
2128
      is_foreign_endianness = false; // else this header is for the same endianness as us
2105
      is_foreign_endianness = false; // else this header is for the same endianness as us
2129
   fseek (fp, imgheader_offset, SEEK_SET);
-
 
2130
   fread (blob_data, 1, blob_size + SHA512_DIGEST_LENGTH, fp);
-
 
2131
   image_trailer.cksum = update_checksum (blob_data, blob_size, is_foreign_endianness); // compute old checksum
-
 
2132
   free (blob_data);
-
 
2133
 
2106
 
2134
   // rewrite image trailer with final checksum values
2107
   SHA512 (&blob_data[imageheader_offset], imagetrailer_offset - imageheader_offset, &blob_data[imagetrailer_offset]); // compute SHA512 checksum and write it in place in blob data
2135
   fseek (fp, imgtrailer_offset, SEEK_SET);
2108
   checksum = update_checksum (&blob_data[imageheader_offset], imagetrailer_offset + SHA512_DIGEST_LENGTH - imageheader_offset, is_foreign_endianness); // compute old checksum
2136
   fwrite (&image_trailer, sizeof (image_trailer), 1, fp); // write image trailer
2109
   memcpy (&blob_data[imagetrailer_offset + SHA512_DIGEST_LENGTH], &checksum, 4); // and write it in place
2137
 
2110
 
2138
   // finished, close IFS file and exit with a success code
2111
   // now rewrite IFS with the correct checksums
-
 
2112
   fp = fopen (ifs_pathname, "wb");
-
 
2113
   WELLMANNERED_ASSERT (fp, "failed to reopen IFS file for checksumming: %s", strerror (errno));
-
 
2114
   fwrite_or_die (blob_data, 1, blob_size, fp);
2139
   fclose (fp);
2115
   fclose (fp);
-
 
2116
   free (blob_data);
-
 
2117
 
-
 
2118
   // finished, exit with a success code
2140
   fprintf (stdout, "Success\n");
2119
   fprintf (stdout, "Success\n");
2141
   exit (0);
2120
   exit (0);
2142
}
2121
}
2143
 
2122
 
2144
 
2123
 
Line 2174... Line 2153...
2174
      "", // bit 6
2153
      "", // bit 6
2175
      "", // bit 7
2154
      "", // bit 7
2176
   };
2155
   };
2177
 
2156
 
2178
   startup_header_t *startup_header = NULL;
2157
   startup_header_t *startup_header = NULL;
-
 
2158
   size_t startupheader_offset = 0;
2179
   startup_trailer_v1_t *startup_trailer_v1 = NULL;
2159
   startup_trailer_v1_t *startup_trailer_v1 = NULL;
2180
   startup_trailer_v2_t *startup_trailer_v2 = NULL;
2160
   startup_trailer_v2_t *startup_trailer_v2 = NULL;
-
 
2161
   size_t startuptrailer_offset = 0;
2181
   image_header_t *image_header = NULL;
2162
   image_header_t *image_header = NULL;
2182
   size_t imageheader_offset = 0;
2163
   size_t imageheader_offset = 0;
2183
   image_trailer_v1_t *image_trailer_v1 = NULL;
2164
   image_trailer_v1_t *image_trailer_v1 = NULL;
2184
   image_trailer_v2_t *image_trailer_v2 = NULL;
2165
   image_trailer_v2_t *image_trailer_v2 = NULL;
2185
   size_t imagetrailer_offset = 0;
2166
   size_t imagetrailer_offset = 0;
Line 2200... Line 2181...
2200
   uint32_t recorded_checksum;
2181
   uint32_t recorded_checksum;
2201
   uint32_t computed_checksum;
2182
   uint32_t computed_checksum;
2202
   uint8_t *filedata;
2183
   uint8_t *filedata;
2203
   size_t filesize;
2184
   size_t filesize;
2204
   time_t mtime;
2185
   time_t mtime;
2205
   FILE *fp;
-
 
2206
 
2186
 
2207
   // open and read IFS file
2187
   // open and read IFS file
2208
   fp = fopen (ifs_pathname, "rb");
2188
   if (read_filecontents (ifs_pathname, ".", &filedata, &filesize) == NULL)
2209
   if (fp == NULL)
-
 
2210
   {
2189
   {
2211
      fprintf (stderr, "error: can't open \"%s\" for reading: %s\n", ifs_pathname, strerror (errno));
2190
      fprintf (stderr, "error: can't open \"%s\" for reading: %s\n", ifs_pathname, strerror (errno));
2212
      return (1);
2191
      return (1);
2213
   }
2192
   }
2214
   fseek (fp, 0, SEEK_END);
-
 
2215
   filesize = ftell (fp);
-
 
2216
   filedata = malloc (filesize);
-
 
2217
   if (filedata == NULL)
-
 
2218
   {
-
 
2219
      fprintf (stderr, "fatal error: out of memory\n");
-
 
2220
      exit (1);
-
 
2221
   }
-
 
2222
   fseek (fp, 0, SEEK_SET);
-
 
2223
   fread (filedata, 1, filesize, fp);
-
 
2224
   fclose (fp);
-
 
2225
 
2193
 
2226
   printf ("QNX In-kernel Filesystem analysis produced by ifstool version " VERSION_FMT_YYYYMMDD "\n", VERSION_ARG_YYYYMMDD);
2194
   printf ("QNX In-kernel Filesystem analysis produced by ifstool version " VERSION_FMT_YYYYMMDD "\n", VERSION_ARG_YYYYMMDD);
2227
   printf ("IFS file \"%s\" - size 0x%zx (%zd) bytes\n", ifs_pathname, filesize, filesize);
2195
   printf ("IFS file \"%s\" - size 0x%zx (%zd) bytes\n", ifs_pathname, filesize, filesize);
2228
 
2196
 
2229
   // parse file from start to end
2197
   // parse file from start to end
Line 2231... Line 2199...
2231
   for (;;)
2199
   for (;;)
2232
   {
2200
   {
2233
      // does a startup header start here ?
2201
      // does a startup header start here ?
2234
      if ((current_offset + sizeof (startup_header_t) < filesize) && (memcmp (&filedata[current_offset], "\xeb\x7e\xff\x00", 4) == 0))
2202
      if ((current_offset + sizeof (startup_header_t) < filesize) && (memcmp (&filedata[current_offset], "\xeb\x7e\xff\x00", 4) == 0))
2235
      {
2203
      {
-
 
2204
         startupheader_offset = current_offset;
2236
         startup_header = (startup_header_t *) &filedata[current_offset];
2205
         startup_header = (startup_header_t *) &filedata[startupheader_offset];
2237
 
2206
 
2238
         // layout:
2207
         // layout:
2239
         // [STARTUP HEADER]
2208
         // [STARTUP HEADER]
2240
         // (startup file blob)
2209
         // (startup file blob)
2241
         // [STARTUP TRAILER v1 or v2]
2210
         // [STARTUP TRAILER v1 or v2]
Line 2278... Line 2247...
2278
            is_foreign_endianness = false; // else this header is for the same endianness as us
2247
            is_foreign_endianness = false; // else this header is for the same endianness as us
2279
 
2248
 
2280
         // locate the right startup trailer at the right offset
2249
         // locate the right startup trailer at the right offset
2281
         if (startup_header->flags1 & STARTUP_HDR_FLAGS1_TRAILER_V2)
2250
         if (startup_header->flags1 & STARTUP_HDR_FLAGS1_TRAILER_V2)
2282
         {
2251
         {
2283
            startup_trailer_v2 = (startup_trailer_v2_t *) &filedata[current_offset + startup_header->startup_size - sizeof (startup_trailer_v2_t)];
2252
            startuptrailer_offset = current_offset + startup_header->startup_size - sizeof (startup_trailer_v2_t);
-
 
2253
            startup_trailer_v2 = (startup_trailer_v2_t *) &filedata[startuptrailer_offset];
2284
            startupfile_blobsize = startup_header->startup_size - sizeof (startup_header_t) - sizeof (startup_trailer_v2_t);
2254
            startupfile_blobsize = startup_header->startup_size - sizeof (startup_header_t) - sizeof (startup_trailer_v2_t);
2285
         }
2255
         }
2286
         else // old V1 trailer
2256
         else // old V1 trailer
2287
         {
2257
         {
2288
            startup_trailer_v1 = (startup_trailer_v1_t *) &filedata[current_offset + startup_header->startup_size - sizeof (startup_trailer_v1_t)];
2258
            startuptrailer_offset = current_offset + startup_header->startup_size - sizeof (startup_trailer_v1_t);
-
 
2259
            startup_trailer_v1 = (startup_trailer_v1_t *) &filedata[startuptrailer_offset];
2289
            startupfile_blobsize = startup_header->startup_size - sizeof (startup_header_t) - sizeof (startup_trailer_v1_t);
2260
            startupfile_blobsize = startup_header->startup_size - sizeof (startup_header_t) - sizeof (startup_trailer_v1_t);
2290
         }
2261
         }
2291
 
2262
 
2292
         current_offset += sizeof (startup_header_t); // jump over the startup header and reach the startup blob
2263
         current_offset += sizeof (startup_header_t); // jump over the startup header and reach the startup blob
2293
         printf ("\n");
2264
         printf ("\n");
Line 2300... Line 2271...
2300
         printf ("Startup trailer at offset 0x%zx (%zd) - version %d:\n", current_offset, current_offset, (startup_header->flags1 & STARTUP_HDR_FLAGS1_TRAILER_V2 ? 2 : 1));
2271
         printf ("Startup trailer at offset 0x%zx (%zd) - version %d:\n", current_offset, current_offset, (startup_header->flags1 & STARTUP_HDR_FLAGS1_TRAILER_V2 ? 2 : 1));
2301
         if (startup_header->flags1 & STARTUP_HDR_FLAGS1_TRAILER_V2)
2272
         if (startup_header->flags1 & STARTUP_HDR_FLAGS1_TRAILER_V2)
2302
         {
2273
         {
2303
            for (byte_index = 0; byte_index < SHA512_DIGEST_LENGTH; byte_index++)
2274
            for (byte_index = 0; byte_index < SHA512_DIGEST_LENGTH; byte_index++)
2304
               sprintf (&recorded_sha512[2 * byte_index], "%02x", startup_trailer_v2->sha512[byte_index]);
2275
               sprintf (&recorded_sha512[2 * byte_index], "%02x", startup_trailer_v2->sha512[byte_index]);
2305
            strcpy (computed_sha512, SHA512 (startup_header, (size_t) ((uint8_t *) startup_trailer_v2 - (uint8_t *) startup_header), NULL));
2276
            strcpy (computed_sha512, SHA512 (startup_header, startuptrailer_offset - startupheader_offset, NULL));
2306
            recorded_checksum = startup_trailer_v2->cksum;
2277
            recorded_checksum = startup_trailer_v2->cksum;
2307
            computed_checksum = update_checksum (startup_header, sizeof (startup_header_t) + startupfile_blobsize + SHA512_DIGEST_LENGTH, is_foreign_endianness);
2278
            computed_checksum = update_checksum (startup_header, startuptrailer_offset + SHA512_DIGEST_LENGTH - startupheader_offset, is_foreign_endianness);
2308
            printf ("    sha512 = %s - %s\n", recorded_sha512, (strcasecmp (computed_sha512, recorded_sha512) == 0 ? "GOOD" : "BAD"));
2279
            printf ("    sha512([0x%zx-0x%zx[) = %s - %s\n", startupheader_offset, startuptrailer_offset, recorded_sha512, (strcasecmp (computed_sha512, recorded_sha512) == 0 ? "GOOD" : "BAD"));
2309
            printf ("    cksum = 0x%08x (%d) - %s\n", recorded_checksum, recorded_checksum, (computed_checksum == recorded_checksum ? "GOOD" : "BAD"));
2280
            printf ("    cksum([0x%zx-0x%zx[) = 0x%08x (%d) - %s\n", startupheader_offset, startuptrailer_offset + SHA512_DIGEST_LENGTH, recorded_checksum, recorded_checksum, (computed_checksum == recorded_checksum ? "GOOD" : "BAD"));
2310
            if (strcasecmp (computed_sha512, recorded_sha512) != 0)
2281
            if (strcasecmp (computed_sha512, recorded_sha512) != 0)
2311
               printf ("Computed SHA-512: %s\n", computed_sha512);
2282
               printf ("Computed SHA-512: %s\n", computed_sha512);
2312
            if (computed_checksum != recorded_checksum)
2283
            if (computed_checksum != recorded_checksum)
2313
               printf ("Computed cksum: 0x%08x (%d)\n", computed_checksum, computed_checksum);
2284
               printf ("Computed cksum: 0x%08x (%d)\n", computed_checksum, computed_checksum);
2314
         }
2285
         }
2315
         else // old v1 trailer
2286
         else // old v1 trailer
2316
         {
2287
         {
2317
            recorded_checksum = startup_trailer_v1->cksum;
2288
            recorded_checksum = startup_trailer_v1->cksum;
2318
            computed_checksum = update_checksum (startup_header, sizeof (startup_header) + startupfile_blobsize, is_foreign_endianness);
2289
            computed_checksum = update_checksum (startup_header, sizeof (startup_header) + startupfile_blobsize, is_foreign_endianness);
2319
            printf ("    cksum = 0x%08x (%d) - %s\n", recorded_checksum, recorded_checksum, (computed_checksum == recorded_checksum ? "GOOD" : "BAD"));
2290
            printf ("    cksum([0x%zx-0x%zx[) = 0x%08x (%d) - %s\n", startupheader_offset, startuptrailer_offset, recorded_checksum, recorded_checksum, (computed_checksum == recorded_checksum ? "GOOD" : "BAD"));
2320
            if (computed_checksum != recorded_checksum)
2291
            if (computed_checksum != recorded_checksum)
2321
               printf ("Computed cksum: 0x%08x (%d)\n", computed_checksum, computed_checksum);
2292
               printf ("Computed cksum: 0x%08x (%d)\n", computed_checksum, computed_checksum);
2322
         }
2293
         }
2323
 
2294
 
2324
         current_offset += (startup_header->flags1 & STARTUP_HDR_FLAGS1_TRAILER_V2 ? sizeof (startup_trailer_v2_t) : sizeof (startup_trailer_v1_t)); // now reach the next segment
2295
         current_offset += (startup_header->flags1 & STARTUP_HDR_FLAGS1_TRAILER_V2 ? sizeof (startup_trailer_v2_t) : sizeof (startup_trailer_v1_t)); // now reach the next segment
Line 2396... Line 2367...
2396
            if (imageheader_offset + image_header->hdr_dir_size - current_offset < sizeof (current_fsentry->header))
2367
            if (imageheader_offset + image_header->hdr_dir_size - current_offset < sizeof (current_fsentry->header))
2397
               break; // end padding reached
2368
               break; // end padding reached
2398
 
2369
 
2399
            // stack up the filesystem entry pointers in an array while we read them
2370
            // stack up the filesystem entry pointers in an array while we read them
2400
            reallocated_ptr = realloc (fsentries, (fsentry_count + 1) * sizeof (fsentry_t *));
2371
            reallocated_ptr = realloc (fsentries, (fsentry_count + 1) * sizeof (fsentry_t *));
2401
            if (reallocated_ptr == NULL)
-
 
2402
            {
-
 
2403
               fprintf (stderr, "fatal error: out of memory\n");
2372
            WELLMANNERED_ASSERT (reallocated_ptr, "out of memory");
2404
               exit (1);
-
 
2405
            }
-
 
2406
            fsentries = reallocated_ptr;
2373
            fsentries = reallocated_ptr;
2407
            fsentries[fsentry_count] = current_fsentry;
2374
            fsentries[fsentry_count] = current_fsentry;
2408
            fsentry_count++;
2375
            fsentry_count++;
2409
 
2376
 
2410
            printf ("\n");
2377
            printf ("\n");
Line 2483... Line 2450...
2483
               printf ("   corresponding inode 0x%08x (%d) -%s%s%s%s\n", current_fsentry->header.ino, current_fsentry->header.ino, (current_fsentry->header.ino & 0xE0000000 ? "" : " nothing special"), (current_fsentry->header.ino & IFS_INO_PROCESSED_ELF ? " PROCESSED_ELF" : ""), (current_fsentry->header.ino & IFS_INO_RUNONCE_ELF ? " RUNONCE_ELF" : ""), (current_fsentry->header.ino & IFS_INO_BOOTSTRAP_EXE ? " BOOTSTRAP_EXE" : ""));
2450
               printf ("   corresponding inode 0x%08x (%d) -%s%s%s%s\n", current_fsentry->header.ino, current_fsentry->header.ino, (current_fsentry->header.ino & 0xE0000000 ? "" : " nothing special"), (current_fsentry->header.ino & IFS_INO_PROCESSED_ELF ? " PROCESSED_ELF" : ""), (current_fsentry->header.ino & IFS_INO_RUNONCE_ELF ? " RUNONCE_ELF" : ""), (current_fsentry->header.ino & IFS_INO_BOOTSTRAP_EXE ? " BOOTSTRAP_EXE" : ""));
2484
               printf ("   corresponding path: \"%s\"\n", (char *) &current_fsentry->u.file.path); // convert from pointer to char array
2451
               printf ("   corresponding path: \"%s\"\n", (char *) &current_fsentry->u.file.path); // convert from pointer to char array
2485
               printf ("   size 0x%zx (%zd) bytes\n", (size_t) current_fsentry->u.file.size, (size_t) current_fsentry->u.file.size);
2452
               printf ("   size 0x%zx (%zd) bytes\n", (size_t) current_fsentry->u.file.size, (size_t) current_fsentry->u.file.size);
2486
               if (current_offset + 4 < filesize)
2453
               if (current_offset + 4 < filesize)
2487
               {
2454
               {
2488
                  if ((current_fsentry->u.file.size < 1024) && (current_offset + current_fsentry->u.file.size < filesize))
2455
                  if ((current_fsentry->u.file.size < 16 * 1024) && (current_offset + current_fsentry->u.file.size < filesize))
2489
                     hex_printf (&filedata[current_offset], current_fsentry->u.file.size, "   data:\n");
2456
                     hex_printf (&filedata[current_offset], current_fsentry->u.file.size, "   data:\n");
2490
                  else
2457
                  else
2491
                     printf ("   first 4 bytes: %02x%02x%02x%02x \"%c%c%c%c\" (%s)\n", (uint8_t) filedata[current_offset + 0], (uint8_t) filedata[current_offset + 1], (uint8_t) filedata[current_offset + 2], (uint8_t) filedata[current_offset + 3], (isprint (filedata[current_offset + 0]) ? filedata[current_offset + 0] : '.'), (isprint (filedata[current_offset + 1]) ? filedata[current_offset + 1] : '.'), (isprint (filedata[current_offset + 2]) ? filedata[current_offset + 2] : '.'), (isprint (filedata[current_offset + 3]) ? filedata[current_offset + 3] : '.'), (memcmp (&filedata[current_offset], ELF_MAGIC_STR, 4) == 0 ? "ELF binary" : (memcmp (&filedata[current_offset], "#!", 2) == 0 ? "shell script" : "data file")));
2458
                     printf ("   first 4 bytes: %02x%02x%02x%02x \"%c%c%c%c\" (%s)\n", (uint8_t) filedata[current_offset + 0], (uint8_t) filedata[current_offset + 1], (uint8_t) filedata[current_offset + 2], (uint8_t) filedata[current_offset + 3], (isprint (filedata[current_offset + 0]) ? filedata[current_offset + 0] : '.'), (isprint (filedata[current_offset + 1]) ? filedata[current_offset + 1] : '.'), (isprint (filedata[current_offset + 2]) ? filedata[current_offset + 2] : '.'), (isprint (filedata[current_offset + 3]) ? filedata[current_offset + 3] : '.'), (memcmp (&filedata[current_offset], ELF_MAGIC_STR, 4) == 0 ? "ELF binary" : (memcmp (&filedata[current_offset], "#!", 2) == 0 ? "shell script" : "data file")));
2492
               }
2459
               }
2493
               if (current_offset + current_fsentry->u.file.size < filesize)
2460
               if (current_offset + current_fsentry->u.file.size < filesize)
Line 2511... Line 2478...
2511
         printf ("Image trailer at offset 0x%zx (%zd) - version %d:\n", current_offset, current_offset, (image_header->flags & IMAGE_FLAGS_TRAILER_V2 ? 2 : 1));
2478
         printf ("Image trailer at offset 0x%zx (%zd) - version %d:\n", current_offset, current_offset, (image_header->flags & IMAGE_FLAGS_TRAILER_V2 ? 2 : 1));
2512
         if (image_header->flags & IMAGE_FLAGS_TRAILER_V2)
2479
         if (image_header->flags & IMAGE_FLAGS_TRAILER_V2)
2513
         {
2480
         {
2514
            for (byte_index = 0; byte_index < SHA512_DIGEST_LENGTH; byte_index++)
2481
            for (byte_index = 0; byte_index < SHA512_DIGEST_LENGTH; byte_index++)
2515
               sprintf (&recorded_sha512[2 * byte_index], "%02x", image_trailer_v2->sha512[byte_index]);
2482
               sprintf (&recorded_sha512[2 * byte_index], "%02x", image_trailer_v2->sha512[byte_index]);
2516
            strcpy (computed_sha512, SHA512 (image_header, (size_t) ((uint8_t *) image_trailer_v2 - (uint8_t *) image_header), NULL));
2483
            strcpy (computed_sha512, SHA512 (image_header, imagetrailer_offset - imageheader_offset, NULL));
2517
            recorded_checksum = image_trailer_v2->cksum;
2484
            recorded_checksum = image_trailer_v2->cksum;
2518
            computed_checksum = update_checksum (image_header, image_header->image_size - sizeof (image_trailer_v2_t) + SHA512_DIGEST_LENGTH, is_foreign_endianness);
2485
            computed_checksum = update_checksum (image_header, imagetrailer_offset + SHA512_DIGEST_LENGTH - imageheader_offset, is_foreign_endianness);
2519
            printf ("    sha512 = %s - %s\n", recorded_sha512, (strcasecmp (computed_sha512, recorded_sha512) == 0 ? "GOOD" : "BAD"));
2486
            printf ("    sha512([0x%zx-0x%zx[) = %s - %s\n", imageheader_offset, imagetrailer_offset, recorded_sha512, (strcasecmp (computed_sha512, recorded_sha512) == 0 ? "GOOD" : "BAD"));
2520
            printf ("    cksum = 0x%08x (%d) - %s\n", recorded_checksum, recorded_checksum, (computed_checksum == recorded_checksum ? "GOOD" : "BAD"));
2487
            printf ("    cksum([0x%zx-0x%zx[) = 0x%08x (%d) - %s\n", imageheader_offset, imagetrailer_offset + SHA512_DIGEST_LENGTH, recorded_checksum, recorded_checksum, (computed_checksum == recorded_checksum ? "GOOD" : "BAD"));
2521
            if (strcasecmp (computed_sha512, recorded_sha512) != 0)
2488
            if (strcasecmp (computed_sha512, recorded_sha512) != 0)
2522
               printf ("Computed SHA-512: %s\n", computed_sha512);
2489
               printf ("Computed SHA-512: %s\n", computed_sha512);
2523
            if (computed_checksum != recorded_checksum)
2490
            if (computed_checksum != recorded_checksum)
2524
               printf ("Computed cksum: 0x%08x (%d)\n", computed_checksum, computed_checksum);
2491
               printf ("Computed cksum: 0x%08x (%d)\n", computed_checksum, computed_checksum);
2525
         }
2492
         }
2526
         else // old v1 trailer
2493
         else // old v1 trailer
2527
         {
2494
         {
2528
            recorded_checksum = image_trailer_v1->cksum;
2495
            recorded_checksum = image_trailer_v1->cksum;
2529
            computed_checksum = update_checksum (image_header, image_header->image_size - sizeof (image_trailer_v1_t), is_foreign_endianness);
2496
            computed_checksum = update_checksum (image_header, image_header->image_size - sizeof (image_trailer_v1_t), is_foreign_endianness);
2530
            printf ("    cksum = 0x%08x (%d) - %s\n", recorded_checksum, recorded_checksum, (computed_checksum == recorded_checksum ? "GOOD" : "BAD"));
2497
            printf ("    cksum([0x%zx-0x%zx[) = 0x%08x (%d) - %s\n", imageheader_offset, imagetrailer_offset, recorded_checksum, recorded_checksum, (computed_checksum == recorded_checksum ? "GOOD" : "BAD"));
2531
            if (computed_checksum != recorded_checksum)
2498
            if (computed_checksum != recorded_checksum)
2532
               printf ("Computed cksum: 0x%08x (%d)\n", computed_checksum, computed_checksum);
2499
               printf ("Computed cksum: 0x%08x (%d)\n", computed_checksum, computed_checksum);
2533
         }
2500
         }
2534
 
2501
 
2535
         current_offset += (image_header->flags & IMAGE_FLAGS_TRAILER_V2 ? sizeof (image_trailer_v2_t) : sizeof (image_trailer_v1_t)); // now reach the next segment (typically end of file)
2502
         current_offset += (image_header->flags & IMAGE_FLAGS_TRAILER_V2 ? sizeof (image_trailer_v2_t) : sizeof (image_trailer_v1_t)); // now reach the next segment (typically end of file)