Rev 17 | Rev 19 | Go to most recent revision | Show entire file | Ignore whitespace | Details | Blame | Last modification | View Log | RSS feed
| Rev 17 | Rev 18 | ||
|---|---|---|---|
| Line 86... | Line 86... | ||
| 86 | uint32_t mtime_for_inline_files; // same as above but only for files that don't exist on the build host (i.e. files with an explicit content blob)  | 
            86 | uint32_t mtime_for_inline_files; // same as above but only for files that don't exist on the build host (i.e. files with an explicit content blob)  | 
          
| 87 | char *prefix; // [prefix=path] install path (e.g. "proc/boot")  | 
            87 | char *prefix; // [prefix=path] install path (e.g. "proc/boot")  | 
          
| 88 | bool should_follow_symlinks; // follow symlinks  | 
            88 | bool should_follow_symlinks; // follow symlinks  | 
          
| 89 | bool should_autosymlink_dylib; // dynamic libraries should be written under their official SONAME and a named symlink be created pointing at them  | 
            89 | bool should_autosymlink_dylib; // dynamic libraries should be written under their official SONAME and a named symlink be created pointing at them  | 
          
| 90 | bool should_keep_ld_output; // whether to keep .sym files produced by ld calls, togglable by the [+keeplinked] attribute  | 
            90 | bool should_keep_ld_output; // whether to keep .sym files produced by ld calls, togglable by the [+keeplinked] attribute  | 
          
| - | 91 | bool should_ignore_duplicates; // [+|-dupignore] whether to ignore duplicates  | 
          |
| - | 92 | bool should_allow_nonexistent_files; // [+|-optional] whether to continue processing on unexistent files  | 
          |
| 91 | bool is_compiled_bootscript; // entry has [+script] attribute  | 
            93 | bool is_compiled_bootscript; // entry has [+script] attribute  | 
          
| 92 | int extra_ino_flags; // bitmap of extra inode flags (IFS_INO_xxx)  | 
            94 | int extra_ino_flags; // bitmap of extra inode flags (IFS_INO_xxx)  | 
          
| 93 | char *search; // [search=path[:path]] binary search path (the default one will be constructed at startup)  | 
            95 | char *search; // [search=path[:path]] binary search path (the default one will be constructed at startup)  | 
          
| 94 | 96 | ||
| 95 | buffer_t data; // the resolved file's own data bytes  | 
            97 | buffer_t data; // the resolved file's own data bytes  | 
          
| Line 218... | Line 220... | ||
| 218 | { false, "/lib/dll" }, // prefix with $PROCESSOR/  | 
            220 | { false, "/lib/dll" }, // prefix with $PROCESSOR/  | 
          
| 219 | { false, "/usr/lib" } // prefix with $PROCESSOR/  | 
            221 | { false, "/usr/lib" } // prefix with $PROCESSOR/  | 
          
| 220 | };  | 
            222 | };  | 
          
| 221 | static thread_local char *resolved_pathname = NULL;  | 
            223 | static thread_local char *resolved_pathname = NULL;  | 
          
| 222 | 224 | ||
| - | 225 | void *reallocated_ptr;  | 
          |
| - | 226 | char *resolved_search_path;  | 
          |
| - | 227 | char *replacement;  | 
          |
| - | 228 | size_t old_searchpath_len;  | 
          |
| - | 229 | size_t new_searchpath_len;  | 
          |
| - | 230 | size_t replacement_len;  | 
          |
| - | 231 | size_t middlebit_len;  | 
          |
| - | 232 | size_t endbit_len;  | 
          |
| 223 | size_t defaultpath_index;  | 
            233 | size_t defaultpath_index;  | 
          
| 224 | struct stat stat_buf;  | 
            234 | struct stat stat_buf;  | 
          
| - | 235 | int erase_index;  | 
          |
| - | 236 | char erased_char;  | 
          |
| - | 237 | char *varname;  | 
          |
| 225 | 
  | 
            238 | char *nextsep;  | 
          
| - | 239 | char *endbit;  | 
          |
| 226 | 
  | 
            240 | char *token;  | 
          
| 227 | 241 | ||
| 228 |    // initial allocation (per thread) | 
            242 |    // initial allocation (per thread) | 
          
| 229 | if (resolved_pathname == NULL)  | 
            243 | if (resolved_pathname == NULL)  | 
          
| 230 |    { | 
            244 |    { | 
          
| 231 | resolved_pathname = malloc (MAXPATHLEN);  | 
            245 | resolved_pathname = malloc (MAXPATHLEN);  | 
          
| Line 282... | Line 296... | ||
| 282 | search_paths_or_NULL_for_MKIFS_PATH_envvar = (SEARCH_PATH != NULL ? SEARCH_PATH : getenv ("MKIFS_PATH"));  | 
            296 | search_paths_or_NULL_for_MKIFS_PATH_envvar = (SEARCH_PATH != NULL ? SEARCH_PATH : getenv ("MKIFS_PATH"));  | 
          
| 283 | 297 | ||
| 284 |       // construct a potential final path using each element of the search path | 
            298 |       // construct a potential final path using each element of the search path | 
          
| 285 | if (search_paths_or_NULL_for_MKIFS_PATH_envvar != NULL)  | 
            299 | if (search_paths_or_NULL_for_MKIFS_PATH_envvar != NULL)  | 
          
| 286 |       { | 
            300 |       { | 
          
| - | 301 |          // the first step is to resolve all environment variables in the search path | 
          |
| 287 | 
  | 
            302 | resolved_search_path = strdup (search_paths_or_NULL_for_MKIFS_PATH_envvar);  | 
          
| - | 303 | ASSERT_WITH_ERRNO (resolved_search_path);  | 
          |
| - | 304 | while ((((token = strstr (resolved_search_path, "${")) != NULL) && ((endbit = strchr (token, '}')) != NULL)) // look for variables in the "${VARNAME}" format *AND* in "$VARNAME" format  | 
          |
| - | 305 | || (((token = strstr (resolved_search_path, "$")) != NULL) && ((middlebit_len = strspn (token, "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789_")) != strlen (token))))  | 
          |
| - | 306 |          { | 
          |
| - | 307 | if (token[1] == '{') // "${VARNAME}" format  | 
          |
| - | 308 |             { | 
          |
| - | 309 | endbit++; // locate where the end bit begins  | 
          |
| - | 310 | varname = token + 2; // skip the leading two characters: "${"  | 
          |
| - | 311 | erase_index = -1; // we shall split the string at the character that's *just before* where the end bit starts  | 
          |
| - | 312 |             } | 
          |
| - | 313 | else // "$VARNAME" format  | 
          |
| - | 314 |             { | 
          |
| - | 315 | endbit = &token[middlebit_len]; // locate where the end bit begins  | 
          |
| - | 316 | varname = token + 1; // skip the leading '$'  | 
          |
| - | 317 | erase_index = 0; // we shall split the string at the character that's *right where* the end bit starts  | 
          |
| - | 318 |             } | 
          |
| - | 319 | old_searchpath_len = strlen (resolved_search_path); // measure current string length  | 
          |
| - | 320 | endbit_len = strlen (endbit); // measure the length of the end bit (skip the closing curly brace)  | 
          |
| - | 321 | erased_char = endbit[erase_index]; // remember which is the character we're going to erase  | 
          |
| - | 322 | endbit[erase_index] = 0; // split the string at the end of the variable name  | 
          |
| - | 323 | replacement = getenv (varname); // peek at the environment for its value  | 
          |
| - | 324 | if (replacement == NULL)  | 
          |
| - | 325 | replacement = ""; // if this variable isn't defined, fallback to an empty string, just like what a UNIX shell does  | 
          |
| - | 326 | endbit[erase_index] = erased_char; // put the erased character back  | 
          |
| - | 327 | replacement_len = strlen (replacement); // measure replacement length  | 
          |
| - | 328 | new_searchpath_len = (size_t) token - (size_t) resolved_search_path + replacement_len + endbit_len; // measure updated search path len  | 
          |
| - | 329 | if (new_searchpath_len > old_searchpath_len)  | 
          |
| - | 330 |             { | 
          |
| - | 331 | reallocated_ptr = realloc (resolved_search_path, new_searchpath_len + 1); // grow it if necessary  | 
          |
| - | 332 | ASSERT_WITH_ERRNO (reallocated_ptr);  | 
          |
| - | 333 | token = &((char *) reallocated_ptr)[token - resolved_search_path]; // fix the pointers that may have moved  | 
          |
| - | 334 | endbit = &((char *) reallocated_ptr)[endbit - resolved_search_path]; // fix the pointers that may have moved  | 
          |
| - | 335 | resolved_search_path = reallocated_ptr;  | 
          |
| - | 336 |             } | 
          |
| - | 337 | memmove (token + replacement_len, endbit, endbit_len + 1); // move the end bit to its final location (including its nul terminator)  | 
          |
| - | 338 | memcpy (token, replacement, replacement_len); // and patch the replacement in between  | 
          |
| - | 339 |          } | 
          |
| - | 340 | ||
| - | 341 |          // now split this search path string into multiple tokens and process them one after the other | 
          |
| - | 342 | token = (*resolved_search_path != 0 ? resolved_search_path : NULL);  | 
          |
| 288 | nextsep = (token != NULL ? &token[strcspn (token, PATH_SEP)] : NULL);  | 
            343 | nextsep = (token != NULL ? &token[strcspn (token, PATH_SEP)] : NULL);  | 
          
| 289 | while (token != NULL)  | 
            344 | while (token != NULL)  | 
          
| 290 |          { | 
            345 |          { | 
          
| - | 346 |             // look under this search path at each of the known subpaths | 
          |
| 291 | for (defaultpath_index = 0; defaultpath_index < sizeof (default_paths) / sizeof (default_paths[0]); defaultpath_index++)  | 
            347 | for (defaultpath_index = 0; defaultpath_index < sizeof (default_paths) / sizeof (default_paths[0]); defaultpath_index++)  | 
          
| 292 |             { | 
            348 |             { | 
          
| 293 | 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);  | 
            349 | 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);  | 
          
| 294 | if ((stat (resolved_pathname, &stat_buf) == 0) && S_ISREG (stat_buf.st_mode))  | 
            350 | if ((stat (resolved_pathname, &stat_buf) == 0) && S_ISREG (stat_buf.st_mode))  | 
          
| 295 | return (resolved_pathname); // if a file can indeed be found at this location, stop searching  | 
            351 | return (resolved_pathname); // if a file can indeed be found at this location, stop searching  | 
          
| Line 298... | Line 354... | ||
| 298 | token = (*nextsep != 0 ? nextsep + 1 : NULL);  | 
            354 | token = (*nextsep != 0 ? nextsep + 1 : NULL);  | 
          
| 299 | nextsep = (token != NULL ? &token[strcspn (token, PATH_SEP)] : NULL);  | 
            355 | nextsep = (token != NULL ? &token[strcspn (token, PATH_SEP)] : NULL);  | 
          
| 300 |          } | 
            356 |          } | 
          
| 301 |       } | 
            357 |       } | 
          
| 302 | 358 | ||
| 303 |       // file not found in search paths: look under QNX_TARGET | 
            359 |       // file not found in search paths: look under QNX_TARGET at each of the known subpaths | 
          
| 304 | for (defaultpath_index = 0; defaultpath_index < sizeof (default_paths) / sizeof (default_paths[0]); defaultpath_index++)  | 
            360 | for (defaultpath_index = 0; defaultpath_index < sizeof (default_paths) / sizeof (default_paths[0]); defaultpath_index++)  | 
          
| 305 |       { | 
            361 |       { | 
          
| 306 | 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);  | 
            362 | 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);  | 
          
| 307 | if ((stat (resolved_pathname, &stat_buf) == 0) && S_ISREG (stat_buf.st_mode))  | 
            363 | if ((stat (resolved_pathname, &stat_buf) == 0) && S_ISREG (stat_buf.st_mode))  | 
          
| 308 | return (resolved_pathname); // if a file can indeed be found at this location, stop searching  | 
            364 | return (resolved_pathname); // if a file can indeed be found at this location, stop searching  | 
          
| Line 637... | Line 693... | ||
| 637 | static size_t add_fsentry (fsentry_t **fsentries, size_t *fsentry_count, parms_t *entry_parms, const char *stored_pathname, const char *buildhost_pathname)  | 
            693 | static size_t add_fsentry (fsentry_t **fsentries, size_t *fsentry_count, parms_t *entry_parms, const char *stored_pathname, const char *buildhost_pathname)  | 
          
| 638 | { | 
            694 | { | 
          
| 639 | static thread_local char *candidate_pathname = NULL;  | 
            695 | static thread_local char *candidate_pathname = NULL;  | 
          
| 640 | static int inode_count = 0; // will be preincremented each time this function is called  | 
            696 | static int inode_count = 0; // will be preincremented each time this function is called  | 
          
| 641 | 697 | ||
| - | 698 | const char *stored_pathname_without_leading_slash;  | 
          |
| 642 | const char *original_stored_pathname = NULL;  | 
            699 | const char *original_stored_pathname = NULL;  | 
          
| 643 | buffer_t *shstrtab = NULL;  | 
            700 | buffer_t *shstrtab = NULL;  | 
          
| 644 | const char *canonical_dylib_name;  | 
            701 | const char *canonical_dylib_name;  | 
          
| 645 | const char *dynamic_strings; // strings table of the ".dynamic" section  | 
            702 | const char *dynamic_strings; // strings table of the ".dynamic" section  | 
          
| 646 | const char *last_dirsep;  | 
            703 | const char *last_dirsep;  | 
          
| 647 | char *global_envstring = NULL;  | 
            704 | char *global_envstring = NULL;  | 
          
| 648 | size_t global_envstring_len = 0;  | 
            705 | size_t global_envstring_len = 0;  | 
          
| - | 706 | size_t fsentry_index;  | 
          |
| 649 | char *startup_name = NULL;  | 
            707 | char *startup_name = NULL;  | 
          
| 650 | char *procnto_name = NULL;  | 
            708 | char *procnto_name = NULL;  | 
          
| 651 | char *resolved_pathname;  | 
            709 | char *resolved_pathname;  | 
          
| 652 | void *reallocated_ptr;  | 
            710 | void *reallocated_ptr;  | 
          
| 653 | void *old_data;  | 
            711 | void *old_data;  | 
          
| Line 669... | Line 727... | ||
| 669 |    { | 
            727 |    { | 
          
| 670 | if (strcmp (stored_pathname, "/proc/boot/boot") == 0) // is it the kernel ?  | 
            728 | if (strcmp (stored_pathname, "/proc/boot/boot") == 0) // is it the kernel ?  | 
          
| 671 |       { | 
            729 |       { | 
          
| 672 |          // HACK: for now just consider the kernel as a binary blob | 
            730 |          // HACK: for now just consider the kernel as a binary blob | 
          
| 673 |          // FIXME: reimplement properly | 
            731 |          // FIXME: reimplement properly | 
          
| 674 | #ifdef PROCNTO_WIP | 
            732 | #ifdef PROCNTO_WIP | 
          
| 675 | char *linebit_start;  | 
            733 | char *linebit_start;  | 
          
| 676 | char *content_line;  | 
            734 | char *content_line;  | 
          
| 677 | char *write_ptr;  | 
            735 | char *write_ptr;  | 
          
| 678 | char *token;  | 
            736 | char *token;  | 
          
| 679 | char *value;  | 
            737 | char *value;  | 
          
| Line 941... | Line 999... | ||
| 941 |       } | 
            999 |       } | 
          
| 942 | else if (buildhost_pathname != NULL) // else was a source file pathname supplied ?  | 
            1000 | else if (buildhost_pathname != NULL) // else was a source file pathname supplied ?  | 
          
| 943 |       { | 
            1001 |       { | 
          
| 944 | resolved_pathname = resolve_pathname (buildhost_pathname, entry_parms->search); // locate the file  | 
            1002 | resolved_pathname = resolve_pathname (buildhost_pathname, entry_parms->search); // locate the file  | 
          
| 945 | if (resolved_pathname == NULL)  | 
            1003 | if (resolved_pathname == NULL)  | 
          
| - | 1004 |          { | 
          |
| - | 1005 | if (entry_parms->should_allow_nonexistent_files)  | 
          |
| - | 1006 |             { | 
          |
| - | 1007 | LOG_WARNING ("filesystem entry \"%s\" specified in \"%s\" line %d not found on build host: ignoring", buildhost_pathname, buildfile_pathname, lineno);  | 
          |
| - | 1008 | return (*fsentry_count); // if we're allowed to continue when a file to add doesn't exist, do so, else die with an error message  | 
          |
| - | 1009 |             } | 
          |
| 946 | DIE_WITH_EXITCODE (1, "filesystem entry \"%s\" specified in \"%s\" line %d not found on build host: %s", buildhost_pathname, buildfile_pathname, lineno, strerror (errno));  | 
            1010 | DIE_WITH_EXITCODE (1, "filesystem entry \"%s\" specified in \"%s\" line %d not found on build host: %s", buildhost_pathname, buildfile_pathname, lineno, strerror (errno));  | 
          
| - | 1011 |          } | 
          |
| 947 | if (!Buffer_ReadFromFile (&entry_parms->data, resolved_pathname))  | 
            1012 | if (!Buffer_ReadFromFile (&entry_parms->data, resolved_pathname))  | 
          
| 948 | DIE_WITH_EXITCODE (1, "filesystem entry \"%s\" specified in \"%s\" line %d can't be read: %s", buildhost_pathname, buildfile_pathname, lineno, strerror (errno));  | 
            1013 | DIE_WITH_EXITCODE (1, "filesystem entry \"%s\" specified in \"%s\" line %d can't be read: %s", buildhost_pathname, buildfile_pathname, lineno, strerror (errno));  | 
          
| 949 | stat (resolved_pathname, &stat_buf); // can't fail, since we could read it  | 
            1014 | stat (resolved_pathname, &stat_buf); // can't fail, since we could read it  | 
          
| 950 | if (entry_parms->mtime == UINT32_MAX)  | 
            1015 | if (entry_parms->mtime == UINT32_MAX)  | 
          
| 951 | entry_parms->mtime = (uint32_t) stat_buf.st_mtime;  | 
            1016 | entry_parms->mtime = (uint32_t) stat_buf.st_mtime;  | 
          
| Line 1009... | Line 1074... | ||
| 1009 | if (strchr (entry_parms->data.bytes, ':') == NULL)  | 
            1074 | if (strchr (entry_parms->data.bytes, ':') == NULL)  | 
          
| 1010 | DIE_WITH_EXITCODE (1, "device entry \"%s\" malformed (no 'dev:rdev' pair)", stored_pathname);  | 
            1075 | DIE_WITH_EXITCODE (1, "device entry \"%s\" malformed (no 'dev:rdev' pair)", stored_pathname);  | 
          
| 1011 | LOG_INFO ("fifo: ino 0x%x uid %d gid %d mode 0%o path \"%s\" dev:rdev %s)", inode_count + 1, entry_parms->uid, entry_parms->gid, entry_parms->st_mode, stored_pathname, entry_parms->data.bytes);  | 
            1076 | LOG_INFO ("fifo: ino 0x%x uid %d gid %d mode 0%o path \"%s\" dev:rdev %s)", inode_count + 1, entry_parms->uid, entry_parms->gid, entry_parms->st_mode, stored_pathname, entry_parms->data.bytes);  | 
          
| 1012 |    } | 
            1077 |    } | 
          
| 1013 | 1078 | ||
| - | 1079 |    // have a pointer to where the stored pathname actually starts, without the leading slash | 
          |
| - | 1080 | stored_pathname_without_leading_slash = stored_pathname[0] == '/' ? &stored_pathname[1] : stored_pathname;  | 
          |
| - | 1081 | ||
| - | 1082 |    // see if this item already has an entry in the current list of filesystem entries | 
          |
| - | 1083 | for (fsentry_index = 0; fsentry_index < *fsentry_count; fsentry_index++)  | 
          |
| - | 1084 |    { | 
          |
| - | 1085 | fsentry = &(*fsentries)[fsentry_index]; // quick access to fs entry slot  | 
          |
| - | 1086 | if ( (S_ISDIR (fsentry->header.mode) && (strcmp (fsentry->u.dir.path, stored_pathname_without_leading_slash) == 0))  | 
          |
| - | 1087 | || (S_ISREG (fsentry->header.mode) && (strcmp (fsentry->u.file.path, stored_pathname_without_leading_slash) == 0))  | 
          |
| - | 1088 | || (S_ISLNK (fsentry->header.mode) && (strcmp (fsentry->u.symlink.path, stored_pathname_without_leading_slash) == 0))  | 
          |
| - | 1089 | || (S_ISFIFO (fsentry->header.mode) && (strcmp (fsentry->u.symlink.path, stored_pathname_without_leading_slash) == 0)))  | 
          |
| - | 1090 | break; // stop searching as soon as we find a duplicate  | 
          |
| - | 1091 |    } | 
          |
| - | 1092 | ||
| - | 1093 |    // is there already an entry for this item ? | 
          |
| - | 1094 | if (fsentry_index < *fsentry_count)  | 
          |
| - | 1095 |    { | 
          |
| - | 1096 |       // if we should NOT ignore duplicates, bomb out, else just reuse that entry | 
          |
| - | 1097 | if (!entry_parms->should_ignore_duplicates)  | 
          |
| - | 1098 | DIE_WITH_EXITCODE (1, "duplicate detected: entry \"%s\" specified in \"%s\" line %d already exists in IFS file", stored_pathname, buildfile_pathname, lineno);  | 
          |
| - | 1099 |    } | 
          |
| 1014 |    // grow filesystem entries array to hold one more slot | 
            1100 | else // this is a new entry: grow filesystem entries array to hold one more slot  | 
          
| - | 1101 |    { | 
          |
| 1015 | reallocated_ptr = realloc (*fsentries, (*fsentry_count + 1) * sizeof (fsentry_t)); // attempt to reallocate  | 
            1102 | reallocated_ptr = realloc (*fsentries, (*fsentry_count + 1) * sizeof (fsentry_t)); // attempt to reallocate  | 
          
| 1016 | ASSERT_WITH_ERRNO (reallocated_ptr);  | 
            1103 | ASSERT_WITH_ERRNO (reallocated_ptr); // verify  | 
          
| 1017 | *fsentries = reallocated_ptr; // save reallocated pointer  | 
            1104 | *fsentries = reallocated_ptr; // save reallocated pointer  | 
          
| 1018 | fsentry = &(*fsentries)[*fsentry_count]; // quick access to fs entry slot  | 
            1105 | fsentry = &(*fsentries)[*fsentry_count]; // quick access to fs entry slot  | 
          
| - | 1106 | (*fsentry_count)++; // remember there's one entry more in the array  | 
          |
| - | 1107 |    } | 
          |
| - | 1108 | ||
| - | 1109 |    // save (or update) this entry's parameters | 
          |
| 1019 | fsentry->header.extattr_offset = 0;  | 
            1110 | fsentry->header.extattr_offset = 0;  | 
          
| 1020 | fsentry->header.ino = entry_parms->extra_ino_flags | (++inode_count);  | 
            1111 | fsentry->header.ino = entry_parms->extra_ino_flags | (++inode_count);  | 
          
| 1021 | fsentry->header.mode = entry_parms->st_mode;  | 
            1112 | fsentry->header.mode = entry_parms->st_mode;  | 
          
| 1022 | fsentry->header.gid = entry_parms->gid;  | 
            1113 | fsentry->header.gid = entry_parms->gid;  | 
          
| 1023 | fsentry->header.uid = entry_parms->uid;  | 
            1114 | fsentry->header.uid = entry_parms->uid;  | 
          
| 1024 | fsentry->header.mtime = (entry_parms->mtime == UINT32_MAX ? (uint32_t) time (NULL) : entry_parms->mtime);  | 
            1115 | fsentry->header.mtime = (entry_parms->mtime == UINT32_MAX ? (uint32_t) time (NULL) : entry_parms->mtime);  | 
          
| 1025 | if (S_ISDIR (entry_parms->st_mode))  | 
            1116 | if (S_ISDIR (entry_parms->st_mode))  | 
          
| 1026 |    { | 
            1117 |    { | 
          
| 1027 | fsentry->u.dir.path = strdup (  | 
            1118 | fsentry->u.dir.path = strdup (stored_pathname_without_leading_slash);  | 
          
| 1028 | 1119 | ||
| 1029 | fsentry->header.size = (uint16_t) ROUND_TO_UPPER_MULTIPLE (sizeof (fsentry->header) + strlen (fsentry->u.dir.path) + 1, image_align); // now we can set the size  | 
            1120 | fsentry->header.size = (uint16_t) ROUND_TO_UPPER_MULTIPLE (sizeof (fsentry->header) + strlen (fsentry->u.dir.path) + 1, image_align); // now we can set the size  | 
          
| 1030 | fsentry->UNSAVED_was_data_written = true; // no data to save  | 
            1121 | fsentry->UNSAVED_was_data_written = true; // no data to save  | 
          
| 1031 |    } | 
            1122 |    } | 
          
| 1032 | else if (S_ISREG (entry_parms->st_mode))  | 
            1123 | else if (S_ISREG (entry_parms->st_mode))  | 
          
| 1033 |    { | 
            1124 |    { | 
          
| 1034 | 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  | 
            1125 | 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  | 
          
| 1035 | fsentry->u.file.size = (uint32_t) entry_parms->data.size;  | 
            1126 | fsentry->u.file.size = (uint32_t) entry_parms->data.size;  | 
          
| 1036 | fsentry->u.file.path = strdup (  | 
            1127 | fsentry->u.file.path = strdup (stored_pathname_without_leading_slash);  | 
          
| 1037 | fsentry->u.file.UNSAVED_databuf = malloc (entry_parms->data.size);  | 
            1128 | fsentry->u.file.UNSAVED_databuf = malloc (entry_parms->data.size);  | 
          
| 1038 | ASSERT_WITH_ERRNO (fsentry->u.file.UNSAVED_databuf);  | 
            1129 | ASSERT_WITH_ERRNO (fsentry->u.file.UNSAVED_databuf);  | 
          
| 1039 | memcpy (fsentry->u.file.UNSAVED_databuf, entry_parms->data.bytes, entry_parms->data.size);  | 
            1130 | memcpy (fsentry->u.file.UNSAVED_databuf, entry_parms->data.bytes, entry_parms->data.size);  | 
          
| 1040 | 1131 | ||
| 1041 | 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  | 
            1132 | 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  | 
          
| 1042 | fsentry->UNSAVED_was_data_written = false; // there *IS* data to save  | 
            1133 | fsentry->UNSAVED_was_data_written = false; // there *IS* data to save  | 
          
| 1043 |    } | 
            1134 |    } | 
          
| 1044 | else if (S_ISLNK (entry_parms->st_mode))  | 
            1135 | else if (S_ISLNK (entry_parms->st_mode))  | 
          
| 1045 |    { | 
            1136 |    { | 
          
| 1046 | fsentry->u.symlink.sym_offset = (uint16_t) (strlen (  | 
            1137 | fsentry->u.symlink.sym_offset = (uint16_t) (strlen (stored_pathname_without_leading_slash) + 1);  | 
          
| 1047 | fsentry->u.symlink.sym_size = (uint16_t) entry_parms->data.size;  | 
            1138 | fsentry->u.symlink.sym_size = (uint16_t) entry_parms->data.size;  | 
          
| 1048 | fsentry->u.symlink.path = strdup (  | 
            1139 | fsentry->u.symlink.path = strdup (stored_pathname_without_leading_slash);  | 
          
| 1049 | fsentry->u.symlink.contents = strdup (entry_parms->data.bytes);  | 
            1140 | fsentry->u.symlink.contents = strdup (entry_parms->data.bytes);  | 
          
| 1050 | ASSERT_WITH_ERRNO (fsentry->u.symlink.contents);  | 
            1141 | ASSERT_WITH_ERRNO (fsentry->u.symlink.contents);  | 
          
| 1051 | 1142 | ||
| 1052 | 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  | 
            1143 | 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  | 
          
| 1053 | fsentry->UNSAVED_was_data_written = true; // no data to save  | 
            1144 | fsentry->UNSAVED_was_data_written = true; // no data to save  | 
          
| 1054 |    } | 
            1145 |    } | 
          
| 1055 | else // necessarily a device node  | 
            1146 | else // necessarily a device node  | 
          
| 1056 |    { | 
            1147 |    { | 
          
| 1057 | fsentry->u.device.dev = strtol (entry_parms->data.bytes, NULL, 0); // use strtol() to parse decimal (...), hexadecimal (0x...) and octal (0...) numbers  | 
            1148 | fsentry->u.device.dev = strtol (entry_parms->data.bytes, NULL, 0); // use strtol() to parse decimal (...), hexadecimal (0x...) and octal (0...) numbers  | 
          
| 1058 | fsentry->u.device.rdev = strtol (strchr (entry_parms->data.bytes, ':') + 1, NULL, 0); // use strtol() to parse decimal (...), hexadecimal (0x...) and octal (0...) numbers  | 
            1149 | fsentry->u.device.rdev = strtol (strchr (entry_parms->data.bytes, ':') + 1, NULL, 0); // use strtol() to parse decimal (...), hexadecimal (0x...) and octal (0...) numbers  | 
          
| 1059 | fsentry->u.device.path = strdup (  | 
            1150 | fsentry->u.device.path = strdup (stored_pathname_without_leading_slash);  | 
          
| 1060 | 1151 | ||
| 1061 | fsentry->header.size = (uint16_t) ROUND_TO_UPPER_MULTIPLE (sizeof (fsentry->header) + sizeof (uint32_t) + sizeof (uint32_t) + strlen (fsentry->u.device.path), image_align); // now we can set the size  | 
            1152 | fsentry->header.size = (uint16_t) ROUND_TO_UPPER_MULTIPLE (sizeof (fsentry->header) + sizeof (uint32_t) + sizeof (uint32_t) + strlen (fsentry->u.device.path), image_align); // now we can set the size  | 
          
| 1062 | fsentry->UNSAVED_was_data_written = true; // no data to save  | 
            1153 | fsentry->UNSAVED_was_data_written = true; // no data to save  | 
          
| 1063 |    } | 
            1154 |    } | 
          
| 1064 | (*fsentry_count)++;  | 
            - | |
| 1065 | 1155 | ||
| 1066 |    // should we also add a symlink to this entry ? (in case we stored a dylib file under its canonical name) | 
            1156 |    // should we also add a symlink to this entry ? (in case we stored a dylib file under its canonical name) | 
          
| 1067 | if (original_stored_pathname != NULL)  | 
            1157 | if (original_stored_pathname != NULL)  | 
          
| 1068 |    { | 
            1158 |    { | 
          
| 1069 | entry_parms->is_compiled_bootscript = false;  | 
            1159 | entry_parms->is_compiled_bootscript = false;  | 
          
| Line 1233... | Line 1323... | ||
| 1233 | else if (strcmp (token, "-followlink") == 0) entry_parms.should_follow_symlinks = false;  | 
            1323 | else if (strcmp (token, "-followlink") == 0) entry_parms.should_follow_symlinks = false;  | 
          
| 1234 | else if (strcmp (token, "+autolink") == 0) entry_parms.should_autosymlink_dylib = true;  | 
            1324 | else if (strcmp (token, "+autolink") == 0) entry_parms.should_autosymlink_dylib = true;  | 
          
| 1235 | else if (strcmp (token, "-autolink") == 0) entry_parms.should_autosymlink_dylib = false;  | 
            1325 | else if (strcmp (token, "-autolink") == 0) entry_parms.should_autosymlink_dylib = false;  | 
          
| 1236 | else if (strcmp (token, "+keeplinked") == 0) entry_parms.should_keep_ld_output = true;  | 
            1326 | else if (strcmp (token, "+keeplinked") == 0) entry_parms.should_keep_ld_output = true;  | 
          
| 1237 | else if (strcmp (token, "-keeplinked") == 0) entry_parms.should_keep_ld_output = false;  | 
            1327 | else if (strcmp (token, "-keeplinked") == 0) entry_parms.should_keep_ld_output = false;  | 
          
| - | 1328 | else if (strcmp (token, "+dupignore") == 0) entry_parms.should_ignore_duplicates = true;  | 
          |
| - | 1329 | else if (strcmp (token, "-dupignore") == 0) entry_parms.should_ignore_duplicates = false;  | 
          |
| - | 1330 | else if (strcmp (token, "+optional") == 0) entry_parms.should_allow_nonexistent_files = true;  | 
          |
| - | 1331 | else if (strcmp (token, "-optional") == 0) entry_parms.should_allow_nonexistent_files = false;  | 
          |
| 1238 | else LOG_WARNING ("unimplemented attribute in \"%s\" line %d: '%s'", buildfile_pathname, lineno, token);  | 
            1332 | else LOG_WARNING ("unimplemented attribute in \"%s\" line %d: '%s'", buildfile_pathname, lineno, token);  | 
          
| 1239 |          #undef REACH_TOKEN_VALUE | 
            1333 |          #undef REACH_TOKEN_VALUE | 
          
| 1240 | 1334 | ||
| 1241 | token = strtok_r (NULL, RECORD_SEP, &ctx); // proceed to next attribute token  | 
            1335 | token = strtok_r (NULL, RECORD_SEP, &ctx); // proceed to next attribute token  | 
          
| 1242 |       } | 
            1336 |       } | 
          
| Line 1254... | Line 1348... | ||
| 1254 |             } } while (0) | 
            1348 |             } } while (0) | 
          
| 1255 |          #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))) { \ | 
            1349 |          #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))) { \ | 
          
| 1256 |             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); \ | 
            1350 |             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); \ | 
          
| 1257 |                default_parms->attr = entry_parms.attr; \ | 
            1351 |                default_parms->attr = entry_parms.attr; \ | 
          
| 1258 |             } } while (0) | 
            1352 |             } } while (0) | 
          
| 1259 |          //APPLY_DEFAULT_ATTR_STR (new_cwd,                  "current working directory",       "\"%s\""); | 
            1353 |          //APPLY_DEFAULT_ATTR_STR (new_cwd,                        "current working directory",       "\"%s\""); | 
          
| 1260 | APPLY_DEFAULT_ATTR_STR (search, "search path list", "\"%s\"");  | 
            1354 | APPLY_DEFAULT_ATTR_STR (search, "search path list", "\"%s\"");  | 
          
| 1261 | APPLY_DEFAULT_ATTR_STR (prefix, "prefix", "\"%s\"");  | 
            1355 | APPLY_DEFAULT_ATTR_STR (prefix, "prefix", "\"%s\"");  | 
          
| 1262 | APPLY_DEFAULT_ATTR_NUM (dperms, "directory permissions", "0%o");  | 
            1356 | APPLY_DEFAULT_ATTR_NUM (dperms, "directory permissions", "0%o");  | 
          
| 1263 | APPLY_DEFAULT_ATTR_NUM (perms, "file permissions", "0%o");  | 
            1357 | APPLY_DEFAULT_ATTR_NUM (perms, "file permissions", "0%o");  | 
          
| 1264 | APPLY_DEFAULT_ATTR_NUM (uid, "owner ID", "%d");  | 
            1358 | APPLY_DEFAULT_ATTR_NUM (uid, "owner ID", "%d");  | 
          
| 1265 | APPLY_DEFAULT_ATTR_NUM (gid, "group ID", "%d");  | 
            1359 | APPLY_DEFAULT_ATTR_NUM (gid, "group ID", "%d");  | 
          
| 1266 | APPLY_DEFAULT_ATTR_NUM (st_mode, "inode type", "0%o");  | 
            1360 | APPLY_DEFAULT_ATTR_NUM (st_mode, "inode type", "0%o");  | 
          
| 1267 | APPLY_DEFAULT_ATTR_NUM (is_compiled_bootscript, "compiled script state", "%d");  | 
            1361 | APPLY_DEFAULT_ATTR_NUM (is_compiled_bootscript, "compiled script state", "%d");  | 
          
| 1268 | APPLY_DEFAULT_ATTR_NUM (should_follow_symlinks, "symlink resolution",  | 
            1362 | APPLY_DEFAULT_ATTR_NUM (should_follow_symlinks, "symlink resolution flag", "%d");  | 
          
| 1269 | APPLY_DEFAULT_ATTR_NUM (should_autosymlink_dylib, "dylib canonical name symlinking", "%d");  | 
            1363 | APPLY_DEFAULT_ATTR_NUM (should_autosymlink_dylib, "dylib canonical name symlinking", "%d");  | 
          
| 1270 | APPLY_DEFAULT_ATTR_NUM (should_keep_ld_output, "linker output preservation",  | 
            1364 | APPLY_DEFAULT_ATTR_NUM (should_keep_ld_output, "linker output preservation flag", "%d");  | 
          
| - | 1365 | APPLY_DEFAULT_ATTR_NUM (should_ignore_duplicates, "ignore duplicates flag", "%d");  | 
          |
| - | 1366 | APPLY_DEFAULT_ATTR_NUM (should_allow_nonexistent_files, "ignore nonexistent files flag", "%d");  | 
          |
| 1271 |          #undef APPLY_DEFAULT_ATTR_STR | 
            1367 |          #undef APPLY_DEFAULT_ATTR_STR | 
          
| 1272 |          #undef APPLY_DEFAULT_ATTR_NUM | 
            1368 |          #undef APPLY_DEFAULT_ATTR_NUM | 
          
| 1273 | return; // end of line reached, proceed to the next line  | 
            1369 | return; // end of line reached, proceed to the next line  | 
          
| 1274 |       } | 
            1370 |       } | 
          
| 1275 |       // end of attributes parsing | 
            1371 |       // end of attributes parsing |