Subversion Repositories QNX 8.QNX8 IFS tool

Rev

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

Rev 22 Rev 24
Line 162... Line 162...
162
int32_t update_checksum (const void *data, const size_t data_len, const bool is_foreign_endianness); // compute an IFS image or startup checksum to store in the trailer
162
int32_t update_checksum (const void *data, const size_t data_len, const bool is_foreign_endianness); // compute an IFS image or startup checksum to store in the trailer
163
 
163
 
164
 
164
 
165
// prototypes of local functions
165
// prototypes of local functions
166
static long long read_integer (const char *str); // reads an integer number for a string that may be specified in either hex, octal or decimal base, and may have an optional unit suffix (k, m, g, t)
166
static long long read_integer (const char *str); // reads an integer number for a string that may be specified in either hex, octal or decimal base, and may have an optional unit suffix (k, m, g, t)
-
 
167
static char *resolve_envvars (const char *str); // resolves environment variables in str and replaces them with their value, or an empty string if undefined. Returns a mallocated string (caller frees)
167
static char *resolve_pathname (const char *pathname, const char *search_paths_or_NULL_for_MKIFS_PATH_envvar); // locates pathname among the known search paths and returns a pointer to the resolved pathname (static string)
168
static char *resolve_pathname (const char *pathname, const char *search_paths_or_NULL_for_MKIFS_PATH_envvar); // locates pathname among the known search paths and returns a pointer to the resolved pathname (static string)
168
static elf_section_header_t *elf_get_section_header_by_name (const elf_header_t *elf, const char *section_name); // get a pointer to a named section header in an ELF file
169
static elf_section_header_t *elf_get_section_header_by_name (const elf_header_t *elf, const char *section_name); // get a pointer to a named section header in an ELF file
169
static size_t Buffer_WriteIFSDirectoryEntryAt (buffer_t *ifs_data, const size_t write_offset, const fsentry_t *fsentry); // writes the given filesystem entry (without its contents) to the IFS buffer
170
static size_t Buffer_WriteIFSDirectoryEntryAt (buffer_t *ifs_data, const size_t write_offset, const fsentry_t *fsentry); // writes the given filesystem entry (without its contents) to the IFS buffer
170
static size_t Buffer_AppendIFSFileData (buffer_t *ifs_data, const fsentry_t *fsentry); // writes the given filesystem entry's file data (i.e. its contents) to the IFS buffer
171
static size_t Buffer_AppendIFSFileData (buffer_t *ifs_data, const fsentry_t *fsentry); // writes the given filesystem entry's file data (i.e. its contents) to the IFS buffer
171
static int Buffer_StripELFFile (buffer_t *file, const char **saved_sections, const size_t saved_section_count, const bool should_align_segsize_with_ramsize, const char *indicative_pathname); // strips an ELF file buffer the way mkifs does it and returns whether it succeeded
172
static int Buffer_StripELFFile (buffer_t *file, const char **saved_sections, const size_t saved_section_count, const bool should_align_segsize_with_ramsize, const char *indicative_pathname); // strips an ELF file buffer the way mkifs does it and returns whether it succeeded
Line 219... Line 220...
219
      else if ((*endptr == 'm') || (*endptr == 'M')) ret *= (size_t) 1024 * 1024;
220
      else if ((*endptr == 'm') || (*endptr == 'M')) ret *= (size_t) 1024 * 1024;
220
      else if ((*endptr == 'g') || (*endptr == 'G')) ret *= (size_t) 1024 * 1024 * 1024;
221
      else if ((*endptr == 'g') || (*endptr == 'G')) ret *= (size_t) 1024 * 1024 * 1024;
221
      else if ((*endptr == 't') || (*endptr == 'T')) ret *= (size_t) 1024 * 1024 * 1024 * 1024; // future-proof enough, I suppose?
222
      else if ((*endptr == 't') || (*endptr == 'T')) ret *= (size_t) 1024 * 1024 * 1024 * 1024; // future-proof enough, I suppose?
222
   }
223
   }
223
   return (ret);
224
   return (ret);
-
 
225
}
-
 
226
 
-
 
227
 
-
 
228
static char *resolve_envvars (const char *str)
-
 
229
{
-
 
230
   // resolves environment variables in str and replaces them with their value, or an empty string if undefined
-
 
231
   // returns a mallocated string (caller frees), or dies with errno
-
 
232
 
-
 
233
   signed int erase_index;
-
 
234
   void *reallocated_ptr;
-
 
235
   size_t replacement_len;
-
 
236
   size_t middlebit_len;
-
 
237
   size_t old_str_len;
-
 
238
   size_t new_str_len;
-
 
239
   size_t endbit_len;
-
 
240
   char erased_char;
-
 
241
   char *resolved_str;
-
 
242
   char *replacement;
-
 
243
   char *varname;
-
 
244
   char *endbit;
-
 
245
   char *token;
-
 
246
 
-
 
247
   resolved_str = strdup (str); // have a working copy of the input string
-
 
248
   ASSERT_WITH_ERRNO (resolved_str);
-
 
249
   while ((((token = strstr (resolved_str, "${")) != NULL) && ((endbit = strchr (token, '}')) != NULL)) // look for variables in the "${VARNAME}" format *AND* in "$VARNAME" format
-
 
250
          || (((token = strstr (resolved_str, "$")) != NULL) && ((middlebit_len = strspn (token, "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789_")) != strlen (token))))
-
 
251
   {
-
 
252
      if (token[1] == '{') // "${VARNAME}" format
-
 
253
      {
-
 
254
         endbit++; // locate where the end bit begins
-
 
255
         varname = token + 2; // skip the leading two characters: "${"
-
 
256
         erase_index = -1; // we shall split the string at the character that's *just before* where the end bit starts
-
 
257
      }
-
 
258
      else // "$VARNAME" format
-
 
259
      {
-
 
260
         endbit = &token[middlebit_len]; // locate where the end bit begins
-
 
261
         varname = token + 1; // skip the leading '$'
-
 
262
         erase_index = 0; // we shall split the string at the character that's *right where* the end bit starts
-
 
263
      }
-
 
264
      old_str_len = strlen (resolved_str); // measure current string length
-
 
265
      endbit_len = strlen (endbit); // measure the length of the end bit (skip the closing curly brace)
-
 
266
      erased_char = endbit[erase_index]; // remember which is the character we're going to erase
-
 
267
      endbit[erase_index] = 0; // split the string at the end of the variable name
-
 
268
      if (strcmp (varname, "PFS") == 0)
-
 
269
         replacement = PATH_SEP; // special case: if it's the PFS variable, select ":" or ";" based on the host platform
-
 
270
      else
-
 
271
         replacement = getenv (varname); // peek at the environment for its value
-
 
272
      if (replacement == NULL)
-
 
273
         replacement = ""; // if this variable isn't defined, fallback to an empty string, just like what a UNIX shell does
-
 
274
      endbit[erase_index] = erased_char; // put the erased character back
-
 
275
      replacement_len = strlen (replacement); // measure replacement length
-
 
276
      new_str_len = (size_t) token - (size_t) resolved_str + replacement_len + endbit_len; // measure updated string len
-
 
277
      if (new_str_len > old_str_len)
-
 
278
      {
-
 
279
         reallocated_ptr = realloc (resolved_str, new_str_len + 1); // grow it if necessary
-
 
280
         ASSERT_WITH_ERRNO (reallocated_ptr);
-
 
281
         token = &((char *) reallocated_ptr)[token - resolved_str]; // fix the pointers that may have moved
-
 
282
         endbit = &((char *) reallocated_ptr)[endbit - resolved_str]; // fix the pointers that may have moved
-
 
283
         resolved_str = reallocated_ptr;
-
 
284
      }
-
 
285
      memmove (token + replacement_len, endbit, endbit_len + 1); // move the end bit to its final location (including its nul terminator)
-
 
286
      memcpy (token, replacement, replacement_len); // and patch the replacement in between
-
 
287
   }
-
 
288
 
-
 
289
   return (resolved_str); // finished, return the mallocated resolved string (caller frees)
224
}
290
}
225
 
291
 
226
 
292
 
227
static char *resolve_pathname (const char *pathname, const char *search_paths_or_NULL_for_MKIFS_PATH_envvar)
293
static char *resolve_pathname (const char *pathname, const char *search_paths_or_NULL_for_MKIFS_PATH_envvar)
228
{
294
{
Line 242... Line 308...
242
      { false, "/lib/dll"  }, // prefix with $PROCESSOR/
308
      { false, "/lib/dll"  }, // prefix with $PROCESSOR/
243
      { false, "/usr/lib"  }  // prefix with $PROCESSOR/
309
      { false, "/usr/lib"  }  // prefix with $PROCESSOR/
244
   };
310
   };
245
   static thread_local char *resolved_pathname = NULL;
311
   static thread_local char *resolved_pathname = NULL;
246
 
312
 
247
   void *reallocated_ptr;
313
   char *pathname_without_envvars;
248
   char *resolved_search_path;
314
   char *resolved_search_path;
249
   char *replacement;
-
 
250
   size_t old_searchpath_len;
-
 
251
   size_t new_searchpath_len;
-
 
252
   size_t replacement_len;
-
 
253
   size_t middlebit_len;
-
 
254
   size_t endbit_len;
-
 
255
   size_t defaultpath_index;
315
   size_t defaultpath_index;
256
   struct stat stat_buf;
316
   struct stat stat_buf;
257
   int erase_index;
-
 
258
   char erased_char;
-
 
259
   char *varname;
-
 
260
   char *nextsep;
317
   char *nextsep;
261
   char *endbit;
-
 
262
   char *token;
318
   char *token;
263
 
319
 
264
   // initial allocation (per thread)
-
 
265
   if (resolved_pathname == NULL)
-
 
266
   {
-
 
267
      resolved_pathname = malloc (MAXPATHLEN);
320
   // resolve possible environment variables in pathname
268
      ASSERT_WITH_ERRNO (resolved_pathname);
321
   pathname_without_envvars = resolve_envvars (pathname);
269
   }
-
 
270
 
322
 
271
   // is it an absolute pathname (POSIX and Windows variants) ?
323
   // is it an absolute pathname (POSIX and Windows variants) OR a relative pathname ?
272
   if (IS_DIRSEP (pathname[0])
324
   if (IS_DIRSEP (pathname[0])
273
#ifdef _WIN32
325
#ifdef _WIN32
274
       || (isalpha (pathname[0]) && (pathname[1] == ':') && IS_DIRSEP (pathname[2]))
326
       || (isalpha (pathname[0]) && (pathname[1] == ':') && IS_DIRSEP (pathname[2]))
-
 
327
       || (strchr (pathname, '\\') != NULL)
275
#endif // _WIN32
328
#endif // _WIN32
-
 
329
       || (strchr (pathname, '/') != NULL)
276
       )
330
       )
277
      strcpy_s (resolved_pathname, MAXPATHLEN, pathname); // in this case, it MUST exist at its designated location (either absolute or relative to the current working directory)
331
      return (pathname_without_envvars); // in this case, it MUST exist at its designated location (either absolute or relative to the current working directory)
278
   else // the path is relative, search it among the search paths we have
332
   else // what we've been given is just a basename, so search it among the search paths we have
279
   {
333
   {
280
      // QNX docs:
334
      // QNX docs:
281
      // When searching for host files to be included in the image, search
335
      // When searching for host files to be included in the image, search the default paths used for storing binaries within the specified directory before searching the default paths within $QNX_TARGET.
282
      // the default paths used for storing binaries within the specified
-
 
283
      // directory before searching the default paths within $QNX_TARGET.
-
 
284
      // You can define multiple -r options; each adds a set of paths to
336
      // You can define multiple -r options; each adds a set of paths to search for files.
285
      // search for files. The -r options are evaluated from left to right
-
 
286
      // meaning the paths prefixed with the first (leftmost) rootdir are
337
      // The -r options are evaluated from left to right meaning the paths prefixed with the first (leftmost) rootdir are searched first, then those prefixed with the second rootdir, and so on.
287
      // searched first, then those prefixed with the second rootdir, and
-
 
288
      // so on.
-
 
289
      // Normally, mkifs searches any paths defined in $MKIFS_PATH when
338
      // Normally, mkifs searches any paths defined in $MKIFS_PATH when it was called and then the default paths within $QNX_TARGET.
290
      // it was called and then the default paths within $QNX_TARGET. The
-
 
291
      // default paths are based on the CPU architecture specified by
339
      // The default paths are based on the CPU architecture specified by $PROCESSOR and $PROCESSOR_BASE.
292
      // $PROCESSOR and $PROCESSOR_BASE. If you specify -r options, mkifs
-
 
293
      // searches the default paths prefixed with each dir variable before
340
      // If you specify -r options, mkifs searches the default paths prefixed with each dir variable before searching those within $QNX_TARGET.
294
      // searching those within $QNX_TARGET. These paths are:
341
      // These paths are:
295
      //   dir/${PROCESSOR}/sbin
342
      //   dir/${PROCESSOR}/sbin
296
      //   dir/${PROCESSOR}/usr/sbin
343
      //   dir/${PROCESSOR}/usr/sbin
297
      //   dir/${PROCESSOR}/boot/sys
344
      //   dir/${PROCESSOR}/boot/sys
298
      //   dir/${PROCESSOR_BASE}/boot/sys
345
      //   dir/${PROCESSOR_BASE}/boot/sys
299
      //   dir/${PROCESSOR}/bin
346
      //   dir/${PROCESSOR}/bin
300
      //   dir/${PROCESSOR}/usr/bin
347
      //   dir/${PROCESSOR}/usr/bin
301
      //   dir/${PROCESSOR}/lib
348
      //   dir/${PROCESSOR}/lib
302
      //   dir/${PROCESSOR}/lib/dll
349
      //   dir/${PROCESSOR}/lib/dll
303
      //   dir/${PROCESSOR}/usr/lib
350
      //   dir/${PROCESSOR}/usr/lib
304
      // NOTE: The structure of the directory paths under dir must be
-
 
305
      // identical to that of the default paths under $QNX_TARGET, but the
351
      // NOTE: The structure of the directory paths under dir must be identical to that of the default paths under $QNX_TARGET, but the root dir itself may be any path you choose.
306
      // root dir itself may be any path you choose. For example, if you
-
 
307
      // wanted to include /scratch/aarch64le/sbin/devb-sata, you would
352
      // For example, if you wanted to include /scratch/aarch64le/sbin/devb-sata, you would specify a -r option like this:
308
      // specify a -r option like this:
-
 
309
      //   -r /scratch
353
      //   -r /scratch
310
      // Note that you don't include $PROCESSOR or $PROCESSOR_BASE in dir.
354
      // Note that you don't include $PROCESSOR or $PROCESSOR_BASE in dir.
311
 
355
 
312
      //  - search all paths in explicit path/[default paths] (if explicit path supplied)
356
      //  - search all paths in explicit path/[default paths] (if explicit path supplied)
313
      //  - search all paths in (-r flags if have some|MKIFS_PATH)/[default paths] (if no explicit path supplied)
357
      //  - search all paths in (-r flags if have some|MKIFS_PATH)/[default paths] (if no explicit path supplied)
314
      //  - search all paths in $QNX_TARGET/[default paths]
358
      //  - search all paths in $QNX_TARGET/[default paths]
-
 
359
 
-
 
360
      // initial allocation (per thread)
-
 
361
      if (resolved_pathname == NULL)
-
 
362
      {
-
 
363
         resolved_pathname = malloc (MAXPATHLEN);
-
 
364
         ASSERT_WITH_ERRNO (resolved_pathname);
-
 
365
      }
315
 
366
 
316
      // if no file-specific explicit search path was supplied, use the path list supplied by the -r command-line arguments, else fallback to MKIFS_PATH if we don't have any
367
      // if no file-specific explicit search path was supplied, use the path list supplied by the -r command-line arguments, else fallback to MKIFS_PATH if we don't have any
317
      if (search_paths_or_NULL_for_MKIFS_PATH_envvar == NULL)
368
      if (search_paths_or_NULL_for_MKIFS_PATH_envvar == NULL)
318
         search_paths_or_NULL_for_MKIFS_PATH_envvar = (SEARCH_PATH != NULL ? SEARCH_PATH : getenv ("MKIFS_PATH"));
369
         search_paths_or_NULL_for_MKIFS_PATH_envvar = (SEARCH_PATH != NULL ? SEARCH_PATH : getenv ("MKIFS_PATH"));
319
 
370
 
320
      // construct a potential final path using each element of the search path
371
      // construct a potential final path using each element of the search path
321
      if (search_paths_or_NULL_for_MKIFS_PATH_envvar != NULL)
372
      if (search_paths_or_NULL_for_MKIFS_PATH_envvar != NULL)
322
      {
373
      {
323
         // the first step is to resolve all environment variables in the search path
374
         // the first step is to resolve all environment variables in the search path
324
         resolved_search_path = strdup (search_paths_or_NULL_for_MKIFS_PATH_envvar);
375
         resolved_search_path = resolve_envvars (search_paths_or_NULL_for_MKIFS_PATH_envvar);
325
         ASSERT_WITH_ERRNO (resolved_search_path);
-
 
326
         while ((((token = strstr (resolved_search_path, "${")) != NULL) && ((endbit = strchr (token, '}')) != NULL)) // look for variables in the "${VARNAME}" format *AND* in "$VARNAME" format
-
 
327
                || (((token = strstr (resolved_search_path, "$")) != NULL) && ((middlebit_len = strspn (token, "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789_")) != strlen (token))))
-
 
328
         {
-
 
329
            if (token[1] == '{') // "${VARNAME}" format
-
 
330
            {
-
 
331
               endbit++; // locate where the end bit begins
-
 
332
               varname = token + 2; // skip the leading two characters: "${"
-
 
333
               erase_index = -1; // we shall split the string at the character that's *just before* where the end bit starts
-
 
334
            }
-
 
335
            else // "$VARNAME" format
-
 
336
            {
-
 
337
               endbit = &token[middlebit_len]; // locate where the end bit begins
-
 
338
               varname = token + 1; // skip the leading '$'
-
 
339
               erase_index = 0; // we shall split the string at the character that's *right where* the end bit starts
-
 
340
            }
-
 
341
            old_searchpath_len = strlen (resolved_search_path); // measure current string length
-
 
342
            endbit_len = strlen (endbit); // measure the length of the end bit (skip the closing curly brace)
-
 
343
            erased_char = endbit[erase_index]; // remember which is the character we're going to erase
-
 
344
            endbit[erase_index] = 0; // split the string at the end of the variable name
-
 
345
            replacement = getenv (varname); // peek at the environment for its value
-
 
346
            if (replacement == NULL)
-
 
347
               replacement = ""; // if this variable isn't defined, fallback to an empty string, just like what a UNIX shell does
-
 
348
            endbit[erase_index] = erased_char; // put the erased character back
-
 
349
            replacement_len = strlen (replacement); // measure replacement length
-
 
350
            new_searchpath_len = (size_t) token - (size_t) resolved_search_path + replacement_len + endbit_len; // measure updated search path len
-
 
351
            if (new_searchpath_len > old_searchpath_len)
-
 
352
            {
-
 
353
               reallocated_ptr = realloc (resolved_search_path, new_searchpath_len + 1); // grow it if necessary
-
 
354
               ASSERT_WITH_ERRNO (reallocated_ptr);
-
 
355
               token = &((char *) reallocated_ptr)[token - resolved_search_path]; // fix the pointers that may have moved
-
 
356
               endbit = &((char *) reallocated_ptr)[endbit - resolved_search_path]; // fix the pointers that may have moved
-
 
357
               resolved_search_path = reallocated_ptr;
-
 
358
            }
-
 
359
            memmove (token + replacement_len, endbit, endbit_len + 1); // move the end bit to its final location (including its nul terminator)
-
 
360
            memcpy (token, replacement, replacement_len); // and patch the replacement in between
-
 
361
         }
-
 
362
 
376
 
363
         // now split this search path string into multiple tokens and process them one after the other
377
         // now split this search path string into multiple tokens and process them one after the other
364
         token = (*resolved_search_path != 0 ? resolved_search_path : NULL);
378
         token = (*resolved_search_path != 0 ? resolved_search_path : NULL);
365
         nextsep = (token != NULL ? &token[strcspn (token, PATH_SEP)] : NULL);
379
         nextsep = (token != NULL ? &token[strcspn (token, PATH_SEP)] : NULL);
366
         while (token != NULL)
380
         while (token != NULL)
367
         {
381
         {
368
            // look under this search path at each of the known subpaths
382
            // look under this search path at each of the known subpaths
369
            for (defaultpath_index = 0; defaultpath_index < sizeof (default_paths) / sizeof (default_paths[0]); defaultpath_index++)
383
            for (defaultpath_index = 0; defaultpath_index < sizeof (default_paths) / sizeof (default_paths[0]); defaultpath_index++)
370
            {
384
            {
371
               sprintf_s (resolved_pathname, MAXPATHLEN, "%.*s/%s/%s/%s", (int) (nextsep - token), token, (default_paths[defaultpath_index].uses_processor_base ? image_processor_base : image_processor), default_paths[defaultpath_index].subpath, pathname);
385
               sprintf_s (resolved_pathname, MAXPATHLEN, "%.*s/%s/%s/%s", (int) (nextsep - token), token, (default_paths[defaultpath_index].uses_processor_base ? image_processor_base : image_processor), default_paths[defaultpath_index].subpath, pathname_without_envvars);
372
               if ((stat (resolved_pathname, &stat_buf) == 0) && S_ISREG (stat_buf.st_mode))
386
               if ((stat (resolved_pathname, &stat_buf) == 0) && S_ISREG (stat_buf.st_mode))
-
 
387
               {
-
 
388
                  free (pathname_without_envvars);
373
                  return (resolved_pathname); // if a file can indeed be found at this location, stop searching
389
                  return (resolved_pathname); // if a file can indeed be found at this location, stop searching
-
 
390
               }
374
            }
391
            }
375
 
392
 
376
            token = (*nextsep != 0 ? nextsep + 1 : NULL);
393
            token = (*nextsep != 0 ? nextsep + 1 : NULL);
377
            nextsep = (token != NULL ? &token[strcspn (token, PATH_SEP)] : NULL);
394
            nextsep = (token != NULL ? &token[strcspn (token, PATH_SEP)] : NULL);
378
         }
395
         }
379
      }
396
      }
380
 
397
 
381
      // file not found in search paths: look under QNX_TARGET at each of the known subpaths
398
      // file not found in search paths: look under QNX_TARGET at each of the known subpaths
382
      for (defaultpath_index = 0; defaultpath_index < sizeof (default_paths) / sizeof (default_paths[0]); defaultpath_index++)
399
      for (defaultpath_index = 0; defaultpath_index < sizeof (default_paths) / sizeof (default_paths[0]); defaultpath_index++)
383
      {
400
      {
384
         sprintf_s (resolved_pathname, MAXPATHLEN, "%s/%s/%s/%s", QNX_TARGET, (default_paths[defaultpath_index].uses_processor_base ? image_processor_base : image_processor), default_paths[defaultpath_index].subpath, pathname);
401
         sprintf_s (resolved_pathname, MAXPATHLEN, "%s/%s/%s/%s", QNX_TARGET, (default_paths[defaultpath_index].uses_processor_base ? image_processor_base : image_processor), default_paths[defaultpath_index].subpath, pathname_without_envvars);
385
         if ((stat (resolved_pathname, &stat_buf) == 0) && S_ISREG (stat_buf.st_mode))
402
         if ((stat (resolved_pathname, &stat_buf) == 0) && S_ISREG (stat_buf.st_mode))
-
 
403
         {
-
 
404
            free (pathname_without_envvars);
386
            return (resolved_pathname); // if a file can indeed be found at this location, stop searching
405
            return (resolved_pathname); // if a file can indeed be found at this location, stop searching
-
 
406
         }
387
      }
407
      }
388
   }
408
   }
389
 
409
 
-
 
410
   free (pathname_without_envvars);
390
   errno = ENOENT; // we exhausted all possibilities
411
   errno = ENOENT; // we exhausted all possibilities
391
   return (NULL); // file not found, return with ENOENT
412
   return (NULL); // file not found, return with ENOENT
392
}
413
}
393
 
414
 
394
 
415
 
Line 752... Line 773...
752
   static thread_local stringarray_t aps_partnames = { NULL, 0 };
773
   static thread_local stringarray_t aps_partnames = { NULL, 0 };
753
   static int inode_count = 0; // will be preincremented each time this function is called
774
   static int inode_count = 0; // will be preincremented each time this function is called
754
 
775
 
755
   typedef struct scriptcmd_s
776
   typedef struct scriptcmd_s
756
   {
777
   {
757
      const char *argv0;
778
      char *argv0;
758
      int cpu_number;
779
      int cpu_number;
759
      bool is_external;
780
      bool is_external;
760
      int priority;
781
      int priority;
761
      int sched_policy;
782
      int sched_policy;
762
      int aps_partindex;
783
      int aps_partindex;
Line 810... Line 831...
810
      ASSERT_WITH_ERRNO (candidate_pathname);
831
      ASSERT_WITH_ERRNO (candidate_pathname);
811
   }
832
   }
812
 
833
 
813
   if (S_ISDIR (entry_parms->st_mode)) // are we storing a directory ?
834
   if (S_ISDIR (entry_parms->st_mode)) // are we storing a directory ?
814
   {
835
   {
815
      if (buildhost_pathname != NULL) // was a source file pathname supplied ?
836
      if ((buildhost_pathname != NULL) && (buildhost_pathname[0] != 0)) // was a source file pathname supplied ?
816
      {
837
      {
817
         memcpy (&default_parms, entry_parms, sizeof (parms_t)); // apply current entry parameters when including a directory recursively
838
         memcpy (&default_parms, entry_parms, sizeof (parms_t)); // apply current entry parameters when including a directory recursively
818
         add_directory_contents_recursively (fsentries, fsentry_count, buildhost_pathname, strlen (buildhost_pathname), &default_parms); // if so, add this diretory contents recursively
839
         add_directory_contents_recursively (fsentries, fsentry_count, buildhost_pathname, strlen (buildhost_pathname), &default_parms); // if so, add this diretory contents recursively
819
      }
840
      }
820
      LOG_INFO ("directory: ino 0x%x uid %d gid %d mode 0%o path \"%s\"", inode_count + 1, entry_parms->uid, entry_parms->gid, entry_parms->st_mode, stored_pathname);
841
      LOG_INFO ("directory: ino 0x%x uid %d gid %d mode 0%o path \"%s\"", inode_count + 1, entry_parms->uid, entry_parms->gid, entry_parms->st_mode, stored_pathname);
Line 1348... Line 1369...
1348
                     LOG_INFO ("changing default " descr " from " fmt " to " fmt " by attribute at \"%s\" line %zd of inline document '%s'", default_scriptcmd_params.attr, current_scriptcmd_params.attr, buildfile_pathname, 1 + line_index, stored_pathname); \
1369
                     LOG_INFO ("changing default " descr " from " fmt " to " fmt " by attribute at \"%s\" line %zd of inline document '%s'", default_scriptcmd_params.attr, current_scriptcmd_params.attr, buildfile_pathname, 1 + line_index, stored_pathname); \
1349
                     default_scriptcmd_params.attr = current_scriptcmd_params.attr; \
1370
                     default_scriptcmd_params.attr = current_scriptcmd_params.attr; \
1350
                  } } while (0)
1371
                  } } while (0)
1351
               #define APPLY_DEFAULT_ATTR_STR(attr,descr,fmt) do { if (((default_scriptcmd_params.attr == NULL) && (current_scriptcmd_params.attr != NULL)) || ((default_scriptcmd_params.attr != NULL) && (current_scriptcmd_params.attr == NULL)) || ((default_scriptcmd_params.attr != NULL) && (current_scriptcmd_params.attr != NULL) && (strcmp (current_scriptcmd_params.attr, default_scriptcmd_params.attr) != 0))) { \
1372
               #define APPLY_DEFAULT_ATTR_STR(attr,descr,fmt) do { if (((default_scriptcmd_params.attr == NULL) && (current_scriptcmd_params.attr != NULL)) || ((default_scriptcmd_params.attr != NULL) && (current_scriptcmd_params.attr == NULL)) || ((default_scriptcmd_params.attr != NULL) && (current_scriptcmd_params.attr != NULL) && (strcmp (current_scriptcmd_params.attr, default_scriptcmd_params.attr) != 0))) { \
1352
                  LOG_INFO ("changing default " descr " from " fmt " to " fmt " by attribute at \"%s\" line %zd of inline document '%s'", (default_scriptcmd_params.attr != NULL ? default_scriptcmd_params.attr : "none"), current_scriptcmd_params.attr, buildfile_pathname, 1 + line_index, stored_pathname); \
1373
                  LOG_INFO ("changing default " descr " from " fmt " to " fmt " by attribute at \"%s\" line %zd of inline document '%s'", (default_scriptcmd_params.attr != NULL ? default_scriptcmd_params.attr : "none"), current_scriptcmd_params.attr, buildfile_pathname, 1 + line_index, stored_pathname); \
-
 
1374
                     if (default_scriptcmd_params.attr != NULL) free (default_scriptcmd_params.attr); \
-
 
1375
                     default_scriptcmd_params.attr = strdup (current_scriptcmd_params.attr); \
-
 
1376
                     ASSERT_WITH_ERRNO (default_scriptcmd_params.attr != NULL); \
1353
                     default_scriptcmd_params.attr = current_scriptcmd_params.attr; \
1377
                     default_scriptcmd_params.attr = current_scriptcmd_params.attr; \
1354
                  } } while (0)
1378
                  } } while (0)
1355
               APPLY_DEFAULT_ATTR_STR (argv0,                          "executable name",                 "\"%s\"");
1379
               APPLY_DEFAULT_ATTR_STR (argv0,                          "executable name",                 "\"%s\"");
1356
               APPLY_DEFAULT_ATTR_NUM (cpu_number,                     "CPU mask",                        "0%o");
1380
               APPLY_DEFAULT_ATTR_NUM (cpu_number,                     "CPU mask",                        "0%o");
1357
               APPLY_DEFAULT_ATTR_NUM (is_external,                    "external command flag",           "0%o");
1381
               APPLY_DEFAULT_ATTR_NUM (is_external,                    "external command flag",           "0%o");
Line 1771... Line 1795...
1771
               LOG_INFO ("changing default " descr " from " fmt " to " fmt " by attribute at \"%s\" line %d", default_parms->attr, entry_parms.attr, buildfile_pathname, lineno); \
1795
               LOG_INFO ("changing default " descr " from " fmt " to " fmt " by attribute at \"%s\" line %d", default_parms->attr, entry_parms.attr, buildfile_pathname, lineno); \
1772
               default_parms->attr = entry_parms.attr; \
1796
               default_parms->attr = entry_parms.attr; \
1773
            } } while (0)
1797
            } } while (0)
1774
         #define APPLY_DEFAULT_ATTR_STR(attr,descr,fmt) do { if (((default_parms->attr == NULL) && (entry_parms.attr != NULL)) || ((default_parms->attr != NULL) && (entry_parms.attr == NULL)) || ((default_parms->attr != NULL) && (entry_parms.attr != NULL) && (strcmp (entry_parms.attr, default_parms->attr) != 0))) { \
1798
         #define APPLY_DEFAULT_ATTR_STR(attr,descr,fmt) do { if (((default_parms->attr == NULL) && (entry_parms.attr != NULL)) || ((default_parms->attr != NULL) && (entry_parms.attr == NULL)) || ((default_parms->attr != NULL) && (entry_parms.attr != NULL) && (strcmp (entry_parms.attr, default_parms->attr) != 0))) { \
1775
            LOG_INFO ("changing default " descr " from " fmt " to " fmt " by attribute at \"%s\" line %d", (default_parms->attr != NULL ? default_parms->attr : "none"), entry_parms.attr, buildfile_pathname, lineno); \
1799
            LOG_INFO ("changing default " descr " from " fmt " to " fmt " by attribute at \"%s\" line %d", (default_parms->attr != NULL ? default_parms->attr : "none"), entry_parms.attr, buildfile_pathname, lineno); \
-
 
1800
               if (default_parms->attr != NULL) free (default_parms->attr); \
1776
               default_parms->attr = entry_parms.attr; \
1801
               default_parms->attr = strdup (entry_parms.attr); \
-
 
1802
               ASSERT_WITH_ERRNO (default_parms->attr != NULL); \
1777
            } } while (0)
1803
            } } while (0)
1778
         //APPLY_DEFAULT_ATTR_STR (new_cwd,                        "current working directory",       "\"%s\"");
1804
         //APPLY_DEFAULT_ATTR_STR (new_cwd,                        "current working directory",       "\"%s\"");
1779
         APPLY_DEFAULT_ATTR_STR (search,                         "search path list",                "\"%s\"");
1805
         APPLY_DEFAULT_ATTR_STR (search,                         "search path list",                "\"%s\"");
1780
         APPLY_DEFAULT_ATTR_STR (prefix,                         "prefix",                          "\"%s\"");
1806
         APPLY_DEFAULT_ATTR_STR (prefix,                         "prefix",                          "\"%s\"");
1781
         APPLY_DEFAULT_ATTR_NUM (dperms,                         "directory permissions",           "0%o");
1807
         APPLY_DEFAULT_ATTR_NUM (dperms,                         "directory permissions",           "0%o");
Line 1809... Line 1835...
1809
   if (*line_ptr == '/')
1835
   if (*line_ptr == '/')
1810
   {
1836
   {
1811
      LOG_WARNING ("paths in the IFS file should not begin with a leading '/' in \"%s\" line %d", buildfile_pathname, lineno);
1837
      LOG_WARNING ("paths in the IFS file should not begin with a leading '/' in \"%s\" line %d", buildfile_pathname, lineno);
1812
      line_ptr++; // consistency check: paths in the IFS should not begin with a '/'
1838
      line_ptr++; // consistency check: paths in the IFS should not begin with a '/'
1813
   }
1839
   }
1814
   while ((*line_ptr != 0) && ((!is_quoted_context && (*line_ptr != '=') && !isspace (*line_ptr)) || (is_quoted_context && (*line_ptr == '"'))))
1840
   while ((*line_ptr != 0) && ((!is_quoted_context && (*line_ptr != '=') && !isspace (*line_ptr)) || (is_quoted_context && (*line_ptr != '"'))))
1815
   {
1841
   {
1816
      if (*line_ptr == '\\')
1842
      if (*line_ptr == '\\')
1817
      {
1843
      {
1818
         line_ptr++;
1844
         line_ptr++;
1819
         *write_ptr++ = *line_ptr; // unescape characters that are escaped with '\'
1845
         *write_ptr++ = *line_ptr; // unescape characters that are escaped with '\'
Line 1883... Line 1909...
1883
         is_quoted_context = (*line_ptr == '"');
1909
         is_quoted_context = (*line_ptr == '"');
1884
         if (is_quoted_context)
1910
         if (is_quoted_context)
1885
            line_ptr++; // skip a possible initial quote
1911
            line_ptr++; // skip a possible initial quote
1886
         specifiedpathname_start = line_ptr; // remember where the specified pathname starts
1912
         specifiedpathname_start = line_ptr; // remember where the specified pathname starts
1887
         write_ptr = line_ptr; // now unescape all characters
1913
         write_ptr = line_ptr; // now unescape all characters
1888
         while ((*line_ptr != 0) && ((!is_quoted_context && !isspace (*line_ptr)) || (is_quoted_context && (*line_ptr == '"'))))
1914
         while ((*line_ptr != 0) && ((!is_quoted_context && !isspace (*line_ptr)) || (is_quoted_context && (*line_ptr != '"'))))
1889
         {
1915
         {
1890
            if (*line_ptr == '\\')
1916
            if (*line_ptr == '\\')
1891
            {
1917
            {
1892
               line_ptr++;
1918
               line_ptr++;
1893
               *write_ptr++ = *line_ptr; // unescape characters that are escaped with '\'
1919
               *write_ptr++ = *line_ptr; // unescape characters that are escaped with '\'
Line 1966... Line 1992...
1966
   parms_t default_parms = { // default parameters for a filesystem entry
1992
   parms_t default_parms = { // default parameters for a filesystem entry
1967
      .dperms = 0755,
1993
      .dperms = 0755,
1968
      .perms = 0644,
1994
      .perms = 0644,
1969
      .mtime = UINT32_MAX,
1995
      .mtime = UINT32_MAX,
1970
      .mtime_for_inline_files = UINT32_MAX,
1996
      .mtime_for_inline_files = UINT32_MAX,
1971
      .prefix = "/proc/boot",
1997
      .prefix = NULL, // will be initialized to a *mallocated* string: "/proc/boot"
1972
      .should_follow_symlinks = true, // [+|-followlink]
1998
      .should_follow_symlinks = true, // [+|-followlink]
1973
      .should_autosymlink_dylib = true, // [+|-autolink]
1999
      .should_autosymlink_dylib = true, // [+|-autolink]
1974
   };
2000
   };
1975
   parms_t entry_parms = { 0 }; // current parameters for a filesystem entry (will be initialized to default_parms each time a new entry is parsed in the build file)
2001
   parms_t entry_parms = { 0 }; // current parameters for a filesystem entry (will be initialized to default_parms each time a new entry is parsed in the build file)
1976
 
2002
 
Line 2012... Line 2038...
2012
   saved_ELF_sections[0] = "QNX_info"; // NOTE: MUST BE THE FIRST ONE as we artificially shrink down the array to 1 when using it for boot ELF files
2038
   saved_ELF_sections[0] = "QNX_info"; // NOTE: MUST BE THE FIRST ONE as we artificially shrink down the array to 1 when using it for boot ELF files
2013
   saved_ELF_sections[1] = ".gnu_debuglink";
2039
   saved_ELF_sections[1] = ".gnu_debuglink";
2014
   saved_ELF_sections[2] = "QNX_usage";
2040
   saved_ELF_sections[2] = "QNX_usage";
2015
   saved_ELF_sections[3] = ".note.gnu.build-id"; // undocumented by QNX, but nonetheless preserved
2041
   saved_ELF_sections[3] = ".note.gnu.build-id"; // undocumented by QNX, but nonetheless preserved
2016
   saved_ELF_section_count = 4;
2042
   saved_ELF_section_count = 4;
-
 
2043
   default_parms.prefix = strdup ("/proc/boot");
-
 
2044
   ASSERT_WITH_ERRNO (default_parms.prefix);
2017
 
2045
 
2018
   // parse arguments
2046
   // parse arguments
2019
   for (arg_index = 1; arg_index < argc; arg_index++)
2047
   for (arg_index = 1; arg_index < argc; arg_index++)
2020
   {
2048
   {
2021
      if ((strcmp (argv[arg_index], "--bootfile") == 0) && (arg_index + 1 < argc)) // --bootfile path/to/blob.bin
2049
      if ((strcmp (argv[arg_index], "--bootfile") == 0) && (arg_index + 1 < argc)) // --bootfile path/to/blob.bin