Skip to content

Commit 6790e50

Browse files
committed
Fixed some file read/write issues in FSNode.
1 parent d082e6a commit 6790e50

1 file changed

Lines changed: 50 additions & 42 deletions

File tree

src/emucore/FSNode.cxx

Lines changed: 50 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -339,71 +339,78 @@ size_t FSNode::getSize() const
339339
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
340340
size_t FSNode::read(ByteBuffer& buffer, size_t size) const
341341
{
342-
size_t sizeRead = 0;
343-
344342
// File must actually exist
345343
if (!(exists() && isReadable()))
346344
throw std::runtime_error("File not found/readable");
347345

348346
// First let the private subclass attempt to open the file
349347
if (_realNode)
350-
if (sizeRead = _realNode->read(buffer, size); sizeRead > 0)
348+
{
349+
const size_t sizeRead = _realNode->read(buffer, size);
350+
if(sizeRead > 0)
351351
return sizeRead;
352+
}
352353

353354
// Otherwise, the default behaviour is to read from a normal C++ ifstream
354355
std::ifstream in(getPath(), std::ios::binary);
355-
if (in)
356-
{
357-
in.seekg(0, std::ios::end);
358-
sizeRead = static_cast<size_t>(in.tellg());
359-
in.seekg(0, std::ios::beg);
356+
if (!in)
357+
throw std::runtime_error("File open/read error");
360358

361-
if (sizeRead == 0)
362-
throw std::runtime_error("Zero-byte file");
363-
else if (size > 0) // If a requested size to read is provided, honour it
364-
sizeRead = std::min(sizeRead, size);
359+
in.seekg(0, std::ios::end);
360+
const std::streampos fileSize = in.tellg();
361+
if (fileSize <= 0)
362+
throw std::runtime_error("Zero-byte file");
363+
in.seekg(0, std::ios::beg);
365364

366-
buffer = std::make_unique<uInt8[]>(sizeRead);
367-
in.read(reinterpret_cast<char*>(buffer.get()), sizeRead);
368-
}
369-
else
370-
throw std::runtime_error("File open/read error");
365+
// If a requested size to read is provided (size > 0), honour it
366+
const size_t sizeRead = (size > 0)
367+
? std::min(static_cast<size_t>(fileSize), size)
368+
: static_cast<size_t>(fileSize);
369+
370+
buffer = std::make_unique<uInt8[]>(sizeRead);
371+
in.read(reinterpret_cast<char*>(buffer.get()),
372+
static_cast<std::streamsize>(sizeRead));
371373

372-
return sizeRead;
374+
if(!in)
375+
throw std::runtime_error("File read error");
376+
377+
return static_cast<size_t>(in.gcount());
373378
}
374379

375380
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
376381
size_t FSNode::read(std::stringstream& buffer) const
377382
{
378-
size_t sizeRead = 0;
379-
380383
// File must actually exist
381384
if (!(exists() && isReadable()))
382385
throw std::runtime_error("File not found/readable");
383386

384387
// First let the private subclass attempt to open the file
385388
if (_realNode)
386-
if (sizeRead = _realNode->read(buffer); sizeRead > 0)
389+
{
390+
const size_t sizeRead = _realNode->read(buffer);
391+
if(sizeRead > 0)
387392
return sizeRead;
393+
}
388394

389395
// Otherwise, the default behaviour is to read from a normal C++ ifstream
390396
// and convert to a stringstream
391397
std::ifstream in(getPath());
392-
if (in)
393-
{
394-
in.seekg(0, std::ios::end);
395-
sizeRead = static_cast<size_t>(in.tellg());
396-
in.seekg(0, std::ios::beg);
398+
if(!in)
399+
throw std::runtime_error("File open/read error");
397400

398-
if (sizeRead == 0)
399-
throw std::runtime_error("Zero-byte file");
401+
// Get file size
402+
in.seekg(0, std::ios::end);
403+
const std::streampos fileSize = in.tellg();
404+
if(fileSize <= 0)
405+
throw std::runtime_error("Zero-byte file");
406+
in.seekg(0, std::ios::beg);
400407

401-
buffer << in.rdbuf();
402-
}
403-
else
404-
throw std::runtime_error("File open/read error");
408+
// Read into buffer and verify
409+
buffer << in.rdbuf();
410+
if(!in)
411+
throw std::runtime_error("File read error");
405412

406-
return sizeRead;
413+
return static_cast<size_t>(fileSize);
407414
}
408415

409416
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
@@ -420,13 +427,15 @@ size_t FSNode::write(const ByteBuffer& buffer, size_t size) const
420427
std::ofstream out(getPath(), std::ios::binary);
421428
if (out)
422429
{
423-
out.write(reinterpret_cast<const char*>(buffer.get()), size);
424-
425-
out.seekp(0, std::ios::end);
426-
sizeWritten = static_cast<size_t>(out.tellp());
430+
out.write(reinterpret_cast<const char*>(buffer.get()),
431+
static_cast<std::streamsize>(size));
432+
if(out)
433+
sizeWritten = size;
434+
else
435+
throw std::runtime_error("File write error");
427436
}
428437
else
429-
throw std::runtime_error("File open/write error");
438+
throw std::runtime_error("File open error");
430439

431440
return sizeWritten;
432441
}
@@ -445,10 +454,9 @@ size_t FSNode::write(const std::ostringstream& buffer) const
445454
std::ofstream out(getPath());
446455
if (out)
447456
{
448-
out << buffer.rdbuf();
449-
450-
out.seekp(0, std::ios::end);
451-
sizeWritten = static_cast<size_t>(out.tellp());
457+
const auto view = buffer.view();
458+
out.write(view.data(), static_cast<std::streamsize>(view.size()));
459+
sizeWritten = view.size();
452460
}
453461
else
454462
throw std::runtime_error("File open/write error");

0 commit comments

Comments
 (0)