+
+ def GetUniqueName(self):
+ """Get a unique name for a node
+
+ Returns:
+ String containing a unique name for a node, consisting of the name
+ of all ancestors (starting from within the 'binman' node) separated
+ by a dot ('.'). This can be useful for generating unique filesnames
+ in the output directory.
+ """
+ name = self.name
+ node = self._node
+ while node.parent:
+ node = node.parent
+ if node.name == 'binman':
+ break
+ name = '%s.%s' % (node.name, name)
+ return name
+
+ def ExpandToLimit(self, limit):
+ """Expand an entry so that it ends at the given offset limit"""
+ if self.offset + self.size < limit:
+ self.size = limit - self.offset
+ # Request the contents again, since changing the size requires that
+ # the data grows. This should not fail, but check it to be sure.
+ if not self.ObtainContents():
+ self.Raise('Cannot obtain contents when expanding entry')
+
+ def HasSibling(self, name):
+ """Check if there is a sibling of a given name
+
+ Returns:
+ True if there is an entry with this name in the the same section,
+ else False
+ """
+ return name in self.section.GetEntries()
+
+ def GetSiblingImagePos(self, name):
+ """Return the image position of the given sibling
+
+ Returns:
+ Image position of sibling, or None if the sibling has no position,
+ or False if there is no such sibling
+ """
+ if not self.HasSibling(name):
+ return False
+ return self.section.GetEntries()[name].image_pos
+
+ @staticmethod
+ def AddEntryInfo(entries, indent, name, etype, size, image_pos,
+ uncomp_size, offset, entry):
+ """Add a new entry to the entries list
+
+ Args:
+ entries: List (of EntryInfo objects) to add to
+ indent: Current indent level to add to list
+ name: Entry name (string)
+ etype: Entry type (string)
+ size: Entry size in bytes (int)
+ image_pos: Position within image in bytes (int)
+ uncomp_size: Uncompressed size if the entry uses compression, else
+ None
+ offset: Entry offset within parent in bytes (int)
+ entry: Entry object
+ """
+ entries.append(EntryInfo(indent, name, etype, size, image_pos,
+ uncomp_size, offset, entry))
+
+ def ListEntries(self, entries, indent):
+ """Add files in this entry to the list of entries
+
+ This can be overridden by subclasses which need different behaviour.
+
+ Args:
+ entries: List (of EntryInfo objects) to add to
+ indent: Current indent level to add to list
+ """
+ self.AddEntryInfo(entries, indent, self.name, self.etype, self.size,
+ self.image_pos, self.uncomp_size, self.offset, self)
+
+ def ReadData(self, decomp=True):
+ """Read the data for an entry from the image
+
+ This is used when the image has been read in and we want to extract the
+ data for a particular entry from that image.
+
+ Args:
+ decomp: True to decompress any compressed data before returning it;
+ False to return the raw, uncompressed data
+
+ Returns:
+ Entry data (bytes)
+ """
+ # Use True here so that we get an uncompressed section to work from,
+ # although compressed sections are currently not supported
+ tout.Debug("ReadChildData section '%s', entry '%s'" %
+ (self.section.GetPath(), self.GetPath()))
+ data = self.section.ReadChildData(self, decomp)
+ return data
+
+ def ReadChildData(self, child, decomp=True):
+ """Read the data for a particular child entry
+
+ This reads data from the parent and extracts the piece that relates to
+ the given child.
+
+ Args:
+ child: Child entry to read data for (must be valid)
+ decomp: True to decompress any compressed data before returning it;
+ False to return the raw, uncompressed data
+
+ Returns:
+ Data for the child (bytes)
+ """
+ pass
+
+ def LoadData(self, decomp=True):
+ data = self.ReadData(decomp)
+ self.contents_size = len(data)
+ self.ProcessContentsUpdate(data)
+ self.Detail('Loaded data size %x' % len(data))
+
+ def GetImage(self):
+ """Get the image containing this entry
+
+ Returns:
+ Image object containing this entry
+ """
+ return self.section.GetImage()
+
+ def WriteData(self, data, decomp=True):
+ """Write the data to an entry in the image
+
+ This is used when the image has been read in and we want to replace the
+ data for a particular entry in that image.
+
+ The image must be re-packed and written out afterwards.
+
+ Args:
+ data: Data to replace it with
+ decomp: True to compress the data if needed, False if data is
+ already compressed so should be used as is
+
+ Returns:
+ True if the data did not result in a resize of this entry, False if
+ the entry must be resized
+ """
+ if self.size is not None:
+ self.contents_size = self.size
+ else:
+ self.contents_size = self.pre_reset_size
+ ok = self.ProcessContentsUpdate(data)
+ self.Detail('WriteData: size=%x, ok=%s' % (len(data), ok))
+ section_ok = self.section.WriteChildData(self)
+ return ok and section_ok
+
+ def WriteChildData(self, child):
+ """Handle writing the data in a child entry
+
+ This should be called on the child's parent section after the child's
+ data has been updated. It
+
+ This base-class implementation does nothing, since the base Entry object
+ does not have any children.
+
+ Args:
+ child: Child Entry that was written
+
+ Returns:
+ True if the section could be updated successfully, False if the
+ data is such that the section could not updat
+ """
+ return True
+
+ def GetSiblingOrder(self):
+ """Get the relative order of an entry amoung its siblings
+
+ Returns:
+ 'start' if this entry is first among siblings, 'end' if last,
+ otherwise None
+ """
+ entries = list(self.section.GetEntries().values())
+ if entries:
+ if self == entries[0]:
+ return 'start'
+ elif self == entries[-1]:
+ return 'end'
+ return 'middle'