Subversion Repositories QNX 8.QNX8 IFS tool

Rev

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
   const char *nextsep;
238
   char *nextsep;
-
 
239
   char *endbit;
226
   const char *token;
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
         token = (*search_paths_or_NULL_for_MKIFS_PATH_envvar != 0 ? search_paths_or_NULL_for_MKIFS_PATH_envvar : NULL);
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 // FIXME: segment corruption somewhere!
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 (stored_pathname[0] == '/' ? &stored_pathname[1] : stored_pathname);
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 (stored_pathname[0] == '/' ? &stored_pathname[1] : stored_pathname);
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 (stored_pathname[0] == '/' ? &stored_pathname[1] : stored_pathname) + 1);
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 (stored_pathname[0] == '/' ? &stored_pathname[1] : stored_pathname);
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 (stored_pathname[0] == '/' ? &stored_pathname[1] : stored_pathname);
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",              "%d");
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",      "%d");
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