summaryrefslogtreecommitdiffstats
path: root/crawl-ref/source/package.cc
diff options
context:
space:
mode:
authorAdam Borowski <kilobyte@angband.pl>2010-10-07 00:13:20 +0200
committerAdam Borowski <kilobyte@angband.pl>2010-10-07 00:35:26 +0200
commit2d20a979dd95b082f58486da06bdb8340ceeb675 (patch)
tree5af71b437319a42ae6cfd2fb2b8dc1110d327861 /crawl-ref/source/package.cc
parent4ef016b9b477eb660c79c739442367c64ecdb377 (diff)
downloadcrawl-ref-2d20a979dd95b082f58486da06bdb8340ceeb675.tar.gz
crawl-ref-2d20a979dd95b082f58486da06bdb8340ceeb675.zip
Don't leak file descriptors when trying to open a save file fails.
The save browser is likely to open many, especially if you have a lot of old saves after a compat break. Actually running out of descriptors would require a bizarre case, but a bug is a bug...
Diffstat (limited to 'crawl-ref/source/package.cc')
-rw-r--r--crawl-ref/source/package.cc86
1 files changed, 52 insertions, 34 deletions
diff --git a/crawl-ref/source/package.cc b/crawl-ref/source/package.cc
index 18f48b4dcb..be98d610ca 100644
--- a/crawl-ref/source/package.cc
+++ b/crawl-ref/source/package.cc
@@ -103,7 +103,10 @@ package::package(const char* file, bool writeable, bool empty)
sysfail("can't create save file (%s)", file);
if (!lock_file(fd, true))
+ {
+ close(fd);
sysfail("failed to lock newly created save (%s)", file);
+ }
dirty = true;
file_len = sizeof(file_header);
@@ -114,46 +117,61 @@ package::package(const char* file, bool writeable, bool empty)
if (fd == -1)
sysfail("can't open save file (%s)", file);
- if (!lock_file(fd, writeable))
- fail("Another game is already in progress using this save!");
-
- file_header head;
- ssize_t res = ::read(fd, &head, sizeof(file_header));
- if (res < 0)
- sysfail("error reading the save file (%s)", file);
- if (!res || !(head.magic || head.version || head.padding[0]
- || head.padding[1] || head.padding[2] || head.start))
+ try
{
- fail("The save file (%s) is empty!", file);
+ if (!lock_file(fd, writeable))
+ fail("Another game is already in progress using this save!");
+
+ load();
}
- if (res != sizeof(file_header))
- fail("save file (%s) corrupted -- header truncated", file);
-
- if (htole(head.magic) != PACKAGE_MAGIC)
- fail("save file (%s) corrupted -- not a DCSS save file", file);
- if (head.version != PACKAGE_VERSION)
- fail("save file (%s) uses an unknown format %u", file, head.version);
- off_t len = lseek(fd, 0, SEEK_END);
- if (len == -1)
- sysfail("save file (%s) is not seekable", file);
- file_len = len;
- read_directory(htole(head.start));
-
- if (writeable)
+ catch (std::exception &e)
{
- free_blocks[sizeof(file_header)] = file_len - sizeof(file_header);
+ close(fd);
+ throw;
+ }
+ }
+}
- for(directory_t::iterator ch = directory.begin();
- ch != directory.end(); ch++)
- {
- trace_chunk(ch->second);
- }
+void package::load()
+{
+ file_header head;
+ ssize_t res = ::read(fd, &head, sizeof(file_header));
+ if (res < 0)
+ sysfail("error reading the save file (%s)", filename.c_str());
+ if (!res || !(head.magic || head.version || head.padding[0]
+ || head.padding[1] || head.padding[2] || head.start))
+ {
+ fail("The save file (%s) is empty!", filename.c_str());
+ }
+ if (res != sizeof(file_header))
+ fail("save file (%s) corrupted -- header truncated", filename.c_str());
+
+ 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());
+ file_len = len;
+ read_directory(htole(head.start));
+
+ if (rw)
+ {
+ free_blocks[sizeof(file_header)] = file_len - sizeof(file_header);
+
+ for(directory_t::iterator ch = directory.begin();
+ ch != directory.end(); ch++)
+ {
+ trace_chunk(ch->second);
+ }
#ifdef COSTLY_ASSERTS
- // any inconsitency in the save is guaranteed to be already found
- // by this time -- this checks only for internal bugs
- fsck();
+ // any inconsitency in the save is guaranteed to be already found
+ // by this time -- this checks only for internal bugs
+ fsck();
#endif
- }
}
}