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 |
|
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 |
|
320 | // resolve possible environment variables in pathname |
268 |
|
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 |
|
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 // |
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 | // |
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 = |
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, |
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, |
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 |
|
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 = |
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 |