aboutsummaryrefslogtreecommitdiff
path: root/bfd/pdb.c
diff options
context:
space:
mode:
Diffstat (limited to 'bfd/pdb.c')
-rw-r--r--bfd/pdb.c57
1 files changed, 48 insertions, 9 deletions
diff --git a/bfd/pdb.c b/bfd/pdb.c
index b0455b0..340cda6 100644
--- a/bfd/pdb.c
+++ b/bfd/pdb.c
@@ -412,7 +412,8 @@ pdb_allocate_block (uint32_t *num_blocks, uint32_t block_size)
static bool
pdb_write_directory (bfd *abfd, uint32_t block_size, uint32_t num_files,
- uint32_t block_map_addr, uint32_t * num_blocks)
+ uint32_t block_map_addr, uint32_t * num_blocks,
+ uint32_t *stream0_start)
{
char tmp[sizeof (uint32_t)];
uint32_t block, left, block_map_off;
@@ -561,6 +562,9 @@ pdb_write_directory (bfd *abfd, uint32_t block_size, uint32_t num_files,
return false;
}
+ if (arelt == abfd->archive_head && i == 0)
+ *stream0_start = file_block;
+
left -= sizeof (uint32_t);
/* Read file contents into buffer. */
@@ -617,7 +621,8 @@ pdb_write_directory (bfd *abfd, uint32_t block_size, uint32_t num_files,
}
static bool
-pdb_write_bitmap (bfd *abfd, uint32_t block_size, uint32_t num_blocks)
+pdb_write_bitmap (bfd *abfd, uint32_t block_size, uint32_t num_blocks,
+ uint32_t stream0_start)
{
char *buf;
uint32_t num_intervals = (num_blocks + block_size - 1) / block_size;
@@ -626,8 +631,6 @@ pdb_write_bitmap (bfd *abfd, uint32_t block_size, uint32_t num_blocks)
if (!buf)
return false;
- num_blocks--; /* Superblock not included. */
-
for (uint32_t i = 0; i < num_intervals; i++)
{
if (bfd_seek (abfd, ((i * block_size) + 1) * block_size, SEEK_SET))
@@ -636,8 +639,8 @@ pdb_write_bitmap (bfd *abfd, uint32_t block_size, uint32_t num_blocks)
return false;
}
- /* All of our blocks are contiguous, making our free block map simple.
- 0 = used, 1 = free. */
+ /* All of our blocks are contiguous, making our free block map
+ relatively simple. 0 = used, 1 = free. */
if (num_blocks >= 8)
memset (buf, 0,
@@ -650,7 +653,7 @@ pdb_write_bitmap (bfd *abfd, uint32_t block_size, uint32_t num_blocks)
if (num_blocks % 8)
{
- buf[off] = (1 << (8 - (num_blocks % 8))) - 1;
+ buf[off] = 256 - (1 << (num_blocks % 8));
off++;
}
@@ -658,6 +661,40 @@ pdb_write_bitmap (bfd *abfd, uint32_t block_size, uint32_t num_blocks)
memset (buf + off, 0xff, block_size - off);
}
+ /* Mark the blocks allocated to stream 0 as free. This is because stream
+ 0 is intended to be used for the previous MSF directory, to allow
+ atomic updates. This doesn't apply to us, as we rewrite the whole
+ file whenever any change is made. */
+
+ if (i == 0 && abfd->archive_head)
+ {
+ bfd *arelt = abfd->archive_head;
+ uint32_t stream0_blocks =
+ (bfd_get_size (arelt) + block_size - 1) / block_size;
+
+ if (stream0_start % 8)
+ {
+ unsigned int high_bit;
+
+ high_bit = (stream0_start % 8) + stream0_blocks;
+ if (high_bit > 8)
+ high_bit = 8;
+
+ buf[stream0_start / 8] |=
+ (1 << high_bit) - (1 << (stream0_start % 8));
+
+ stream0_blocks -= high_bit - (stream0_start % 8);
+ stream0_start += high_bit - (stream0_start % 8);
+ }
+
+ memset (buf + (stream0_start / 8), 0xff, stream0_blocks / 8);
+ stream0_start += stream0_blocks / 8;
+ stream0_blocks %= 8;
+
+ if (stream0_blocks > 0)
+ buf[stream0_start / 8] |= (1 << stream0_blocks) - 1;
+ }
+
if (num_blocks < block_size * 8)
num_blocks = 0;
else
@@ -681,6 +718,7 @@ pdb_write_contents (bfd *abfd)
uint32_t num_blocks;
uint32_t num_files = 0;
uint32_t num_directory_bytes = sizeof (uint32_t);
+ uint32_t stream0_start = 0;
bfd *arelt;
if (bfd_write (pdb_magic, sizeof (pdb_magic), abfd) != sizeof (pdb_magic))
@@ -735,10 +773,11 @@ pdb_write_contents (bfd *abfd)
return false;
if (!pdb_write_directory
- (abfd, block_size, num_files, block_map_addr, &num_blocks))
+ (abfd, block_size, num_files, block_map_addr, &num_blocks,
+ &stream0_start))
return false;
- if (!pdb_write_bitmap (abfd, block_size, num_blocks))
+ if (!pdb_write_bitmap (abfd, block_size, num_blocks, stream0_start))
return false;
/* Write num_blocks now we know it. */