ciderpress/diskimg/DIUtil.cpp
Andy McFadden e620d054bb It's not Win9x
Changed the two IsWin9x() functions to always return false.

Eventually we'll want to roll this up, removing the Win9x branch
of the code that called these.
2015-01-08 18:04:09 -08:00

351 lines
8.6 KiB
C++

/*
* CiderPress
* Copyright (C) 2007 by faddenSoft, LLC. All Rights Reserved.
* See the file LICENSE for distribution terms.
*/
/*
* DiskImgLib global utility functions.
*/
#include "StdAfx.h"
#include "DiskImgPriv.h"
#define kFilenameExtDelim '.' /* separates extension from filename */
/*
* Get values from a memory buffer.
*/
uint16_t DiskImgLib::GetShortLE(const uint8_t* ptr)
{
return *ptr | (uint16_t) *(ptr+1) << 8;
}
uint32_t DiskImgLib::GetLongLE(const uint8_t* ptr)
{
return *ptr |
(uint32_t) *(ptr+1) << 8 |
(uint32_t) *(ptr+2) << 16 |
(uint32_t) *(ptr+3) << 24;
}
uint16_t DiskImgLib::GetShortBE(const uint8_t* ptr)
{
return *(ptr+1) | (uint16_t) *ptr << 8;
}
uint32_t DiskImgLib::GetLongBE(const uint8_t* ptr)
{
return *(ptr+3) |
(uint32_t) *(ptr+2) << 8 |
(uint32_t) *(ptr+1) << 16 |
(uint32_t) *ptr << 24;
}
uint32_t DiskImgLib::Get24BE(const uint8_t* ptr)
{
return *(ptr+2) |
(uint32_t) *(ptr+1) << 8 |
(uint32_t) *ptr << 16;
}
void DiskImgLib::PutShortLE(uint8_t* ptr, uint16_t val)
{
*ptr++ = (uint8_t) val;
*ptr = val >> 8;
}
void DiskImgLib::PutLongLE(uint8_t* ptr, uint32_t val)
{
*ptr++ = (uint8_t) val;
*ptr++ = (uint8_t) (val >> 8);
*ptr++ = (uint8_t) (val >> 16);
*ptr = (uint8_t) (val >> 24);
}
void DiskImgLib::PutShortBE(uint8_t* ptr, uint16_t val)
{
*ptr++ = val >> 8;
*ptr = (uint8_t) val;
}
void DiskImgLib::PutLongBE(uint8_t* ptr, uint32_t val)
{
*ptr++ = (uint8_t) (val >> 24);
*ptr++ = (uint8_t) (val >> 16);
*ptr++ = (uint8_t) (val >> 8);
*ptr = (uint8_t) val;
}
/*
* Read a two-byte little-endian value.
*/
DIError DiskImgLib::ReadShortLE(GenericFD* pGFD, uint16_t* pBuf)
{
DIError dierr;
uint8_t val[2];
dierr = pGFD->Read(&val[0], 1);
if (dierr == kDIErrNone)
dierr = pGFD->Read(&val[1], 1);
*pBuf = val[0] | (short) val[1] << 8;
return dierr;
}
/*
* Read a four-byte little-endian value.
*/
DIError DiskImgLib::ReadLongLE(GenericFD* pGFD, uint32_t* pBuf)
{
DIError dierr;
uint8_t val[4];
dierr = pGFD->Read(&val[0], 1);
if (dierr == kDIErrNone)
dierr = pGFD->Read(&val[1], 1);
if (dierr == kDIErrNone)
dierr = pGFD->Read(&val[2], 1);
if (dierr == kDIErrNone)
dierr = pGFD->Read(&val[3], 1);
*pBuf = val[0] | (uint32_t)val[1] << 8 |
(uint32_t)val[2] << 16 | (uint32_t)val[3] << 24;
return dierr;
}
/*
* Write a two-byte little-endian value.
*/
DIError DiskImgLib::WriteShortLE(FILE* fp, uint16_t val)
{
putc(val, fp);
putc(val >> 8, fp);
return kDIErrNone;
}
/*
* Write a four-byte little-endian value.
*/
DIError DiskImgLib::WriteLongLE(FILE* fp, uint32_t val)
{
putc(val, fp);
putc(val >> 8, fp);
putc(val >> 16, fp);
putc(val >> 24, fp);
return kDIErrNone;
}
/*
* Write a two-byte little-endian value.
*/
DIError DiskImgLib::WriteShortLE(GenericFD* pGFD, uint16_t val)
{
uint8_t buf;
buf = (uint8_t) val;
pGFD->Write(&buf, 1);
buf = val >> 8;
return pGFD->Write(&buf, 1);
}
/*
* Write a four-byte little-endian value.
*/
DIError DiskImgLib::WriteLongLE(GenericFD* pGFD, uint32_t val)
{
uint8_t buf;
buf = (uint8_t) val;
pGFD->Write(&buf, 1);
buf = (uint8_t) (val >> 8);
pGFD->Write(&buf, 1);
buf = (uint8_t) (val >> 16);
pGFD->Write(&buf, 1);
buf = (uint8_t) (val >> 24);
return pGFD->Write(&buf, 1);
}
/*
* Write a two-byte big-endian value.
*/
DIError DiskImgLib::WriteShortBE(GenericFD* pGFD, uint16_t val)
{
uint8_t buf;
buf = val >> 8;
pGFD->Write(&buf, 1);
buf = (uint8_t) val;
return pGFD->Write(&buf, 1);
}
/*
* Write a four-byte big-endian value.
*/
DIError DiskImgLib::WriteLongBE(GenericFD* pGFD, uint32_t val)
{
uint8_t buf;
buf = (uint8_t) (val >> 24);
pGFD->Write(&buf, 1);
buf = (uint8_t) (val >> 16);
pGFD->Write(&buf, 1);
buf = (uint8_t) (val >> 8);
pGFD->Write(&buf, 1);
buf = (uint8_t) val;
return pGFD->Write(&buf, 1);
}
/*
* Find the filename component of a local pathname. Uses the fssep passed
* in. If the fssep is '\0' (as is the case for DOS 3.3), then the entire
* pathname is returned.
*
* Always returns a pointer to a string; never returns NULL.
*/
const char* DiskImgLib::FilenameOnly(const char* pathname, char fssep)
{
const char* retstr;
const char* pSlash;
char* tmpStr = NULL;
assert(pathname != NULL);
if (fssep == '\0') {
retstr = pathname;
goto bail;
}
pSlash = strrchr(pathname, fssep);
if (pSlash == NULL) {
retstr = pathname; /* whole thing is the filename */
goto bail;
}
pSlash++;
if (*pSlash == '\0') {
if (strlen(pathname) < 2) {
retstr = pathname; /* the pathname is just "/"? Whatever */
goto bail;
}
/* some bonehead put an fssep on the very end; back up before it */
/* (not efficient, but this should be rare, and I'm feeling lazy) */
tmpStr = strdup(pathname);
tmpStr[strlen(pathname)-1] = '\0';
pSlash = strrchr(tmpStr, fssep);
if (pSlash == NULL) {
retstr = pathname; /* just a filename with a '/' after it */
goto bail;
}
pSlash++;
if (*pSlash == '\0') {
retstr = pathname; /* I give up! */
goto bail;
}
retstr = pathname + (pSlash - tmpStr);
} else {
retstr = pSlash;
}
bail:
free(tmpStr);
return retstr;
}
/*
* Return the filename extension found in a full pathname.
*
* An extension is the stuff following the last '.' in the filename. If
* there is nothing following the last '.', then there is no extension.
*
* Returns a pointer to the '.' preceding the extension, or NULL if no
* extension was found.
*
* We guarantee that there is at least one character after the '.'.
*/
const char* DiskImgLib::FindExtension(const char* pathname, char fssep)
{
const char* pFilename;
const char* pExt;
/*
* We have to isolate the filename so that we don't get excited
* about "/foo.bar/file".
*/
pFilename = FilenameOnly(pathname, fssep);
assert(pFilename != NULL);
pExt = strrchr(pFilename, kFilenameExtDelim);
/* also check for "/blah/foo.", which doesn't count */
if (pExt != NULL && *(pExt+1) != '\0')
return pExt;
return NULL;
}
/*
* Like strcpy(), but allocate with new[] instead.
*
* If "str" is NULL, or "new" fails, this returns NULL.
*
* TODO: should be "StrdupNew()"
*/
char* DiskImgLib::StrcpyNew(const char* str)
{
char* newStr;
if (str == NULL)
return NULL;
newStr = new char[strlen(str)+1];
if (newStr != NULL)
strcpy(newStr, str);
return newStr;
}
#ifdef _WIN32
/*
* Convert the value from GetLastError() to its DIError counterpart.
*/
DIError DiskImgLib::LastErrorToDIError(void)
{
DWORD lastErr = ::GetLastError();
switch (lastErr) {
case ERROR_FILE_NOT_FOUND: return kDIErrFileNotFound; // 2
case ERROR_ACCESS_DENIED: return kDIErrAccessDenied; // 5
case ERROR_WRITE_PROTECT: return kDIErrWriteProtected; // 19
case ERROR_SECTOR_NOT_FOUND: return kDIErrGeneric; // 27
case ERROR_SHARING_VIOLATION: return kDIErrSharingViolation; // 32
case ERROR_HANDLE_EOF: return kDIErrEOF; // 38
case ERROR_INVALID_PARAMETER: return kDIErrInvalidArg; // 87
case ERROR_SEM_TIMEOUT: return kDIErrGenericIO; // 121
// ERROR_SEM_TIMEOUT seen read bad blocks from floptical under Win2K
case ERROR_INVALID_HANDLE: // 6
LOGI("HEY: got ERROR_INVALID_HANDLE!");
return kDIErrInternal;
case ERROR_NEGATIVE_SEEK: // 131
LOGI("HEY: got ERROR_NEGATIVE_SEEK!");
return kDIErrInternal;
default:
LOGI("LastErrorToDIError: not converting 0x%08lx (%ld)",
lastErr, lastErr);
return kDIErrGeneric;
}
}
/*
* Returns "true" if we're running on Win9x (Win95, Win98, WinME), "false"
* if not (could be WinNT/2K/XP or even Win31 with Win32s).
*/
bool DiskImgLib::IsWin9x(void)
{
return false;
}
#endif