summaryrefslogtreecommitdiffstats
path: root/crawl-ref/source/package.cc
diff options
context:
space:
mode:
authorAdam Borowski <kilobyte@angband.pl>2011-01-08 00:14:45 +0100
committerAdam Borowski <kilobyte@angband.pl>2011-01-08 02:11:30 +0100
commit9ae74c385bde4e859c2b1afe0edd7d057c8fb46d (patch)
tree44e9249f7f7e3a6b23efb1bb4135c796cb0a453c /crawl-ref/source/package.cc
parent96eeefb472bc79dd4ee10e99ef77003a4a3347ee (diff)
downloadcrawl-ref-9ae74c385bde4e859c2b1afe0edd7d057c8fb46d.tar.gz
crawl-ref-9ae74c385bde4e859c2b1afe0edd7d057c8fb46d.zip
Change the max name length of save file chunks from 4 to 255.
The on-disk format has been changed; the saves will be upgraded just fine but old Crawls will be unable to read them.
Diffstat (limited to 'crawl-ref/source/package.cc')
-rw-r--r--crawl-ref/source/package.cc88
1 files changed, 52 insertions, 36 deletions
diff --git a/crawl-ref/source/package.cc b/crawl-ref/source/package.cc
index 721a1abe4a..fd01046fcf 100644
--- a/crawl-ref/source/package.cc
+++ b/crawl-ref/source/package.cc
@@ -31,6 +31,7 @@ Caveats/issues:
#include <unistd.h>
#include <string.h>
#include <stdlib.h>
+#include <sstream>
#include "AppHdr.h"
#include "package.h"
@@ -62,7 +63,7 @@ static len_t htole(len_t x)
#define dprintf(...) do {} while(0)
#endif
-#define PACKAGE_VERSION 0
+#define PACKAGE_VERSION 1
#define PACKAGE_MAGIC 0x53534344 /* "DCSS" */
struct file_header
@@ -79,12 +80,6 @@ struct block_header
len_t next;
};
-struct dir_entry
-{
- char name[sizeof(len_t)];
- len_t start;
-};
-
typedef std::map<std::string, len_t> directory_t;
typedef std::pair<len_t, len_t> bm_p;
typedef std::map<len_t, bm_p> bm_t;
@@ -151,9 +146,6 @@ void package::load()
if (htole(head.magic) != PACKAGE_MAGIC)
fail("save file (%s) corrupted -- not a DCSS save file",
filename.c_str());
- if (head.version > PACKAGE_VERSION)
- fail("save file (%s) uses an unknown format %u", filename.c_str(),
- head.version);
off_t len = lseek(fd, 0, SEEK_END);
if (len == -1)
sysfail("save file (%s) is not seekable", filename.c_str());
@@ -343,25 +335,22 @@ len_t package::write_directory()
{
delete_chunk("");
- std::vector<dir_entry> dir;
- dir.reserve(directory.size());
+ std::stringstream dir;
for (directory_t::iterator i = directory.begin();
i != directory.end(); i++)
{
- dir_entry ch;
- // probably the only case ever when strncpy() does exactly the
- // right thing
- strncpy(ch.name, i->first.c_str(), sizeof(ch.name));
- ch.start = htole(i->second);
- dir.push_back(ch);
+ uint8_t name_len = i->first.length();
+ dir.write((const char*)&name_len, sizeof(name_len));
+ dir.write(&i->first[0], i->first.length());
+ len_t start = htole(i->second);
+ dir.write((const char*)&start, sizeof(len_t));
}
- ASSERT(dir.size());
- dprintf("writing directory of size %u*%u\n", (unsigned int)dir.size(),
- (unsigned int)sizeof(dir_entry));
+ ASSERT(dir.str().size());
+ dprintf("writing directory (%u bytes)\n", (unsigned int)dir.str().size());
{
chunk_writer dch(this, "");
- dch.write(&dir.front(), dir.size() * sizeof(dir_entry));
+ dch.write(&dir.str()[0], dir.str().size());
}
return directory[""];
@@ -457,6 +446,12 @@ void package::fsck()
file_len = save_file_len;
}
+struct dir_entry0
+{
+ char name[sizeof(len_t)];
+ len_t start;
+};
+
void package::read_directory(len_t start, uint8_t version)
{
ASSERT(directory.empty());
@@ -465,15 +460,40 @@ void package::read_directory(len_t start, uint8_t version)
dprintf("package: reading directory\n");
chunk_reader rd(this, start);
- dir_entry ch;
- while(len_t res = rd.read(&ch, sizeof(dir_entry)))
+ switch(version)
{
- if (res != sizeof(dir_entry))
- fail("save file corrupted -- truncated directory");
- std::string chname(ch.name, 4);
- chname.resize(strlen(chname.c_str()));
- directory[chname] = htole(ch.start);
- dprintf("* %s\n", chname.c_str());
+ case 0:
+ dir_entry0 ch0;
+ while(len_t res = rd.read(&ch0, sizeof(dir_entry0)))
+ {
+ if (res != sizeof(dir_entry0))
+ fail("save file corrupted -- truncated directory");
+ std::string chname(ch0.name, 4);
+ chname.resize(strlen(chname.c_str()));
+ directory[chname] = htole(ch0.start);
+ dprintf("* %s\n", chname.c_str());
+ }
+ break;
+ case 1:
+ uint8_t name_len;
+ len_t bstart;
+ while(len_t res = rd.read(&name_len, sizeof(name_len)))
+ {
+ if (res != sizeof(name_len))
+ fail("save file corrupted -- truncated directory");
+ std::string chname;
+ chname.resize(name_len);
+ if (rd.read(&chname[0], name_len) != name_len)
+ fail("save file corrupted -- truncated directory");
+ if (rd.read(&bstart, sizeof(bstart)) != sizeof(bstart))
+ fail("save file corrupted -- truncated directory");
+ directory[chname] = htole(bstart);
+ dprintf("* %s\n", chname.c_str());
+ }
+ break;
+ default:
+ fail("save file (%s) uses an unknown format %u", filename.c_str(),
+ version);
}
}
@@ -554,12 +574,8 @@ chunk_writer::chunk_writer(package *parent, const std::string _name)
ASSERT(parent);
ASSERT(!parent->aborted);
- /*
- The save format is currently limited to 4 character names for simplicity
- (we use 3 max). If you want to extend this, please implement marshalling
- of arbitrary strings in {read,write}_directory().
- */
- ASSERT(_name.size() <= 4);
+ // If you need more, please change {read,write}_directory().
+ ASSERT(_name.length() < 256);
dprintf("chunk_writer(%s): starting\n", _name.c_str());
pkg = parent;