/* * 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. */ unsigned short DiskImgLib::GetShortLE(const unsigned char* ptr) { return *ptr | (unsigned short) *(ptr+1) << 8; } unsigned long DiskImgLib::GetLongLE(const unsigned char* ptr) { return *ptr | (unsigned long) *(ptr+1) << 8 | (unsigned long) *(ptr+2) << 16 | (unsigned long) *(ptr+3) << 24; } unsigned short DiskImgLib::GetShortBE(const unsigned char* ptr) { return *(ptr+1) | (unsigned short) *ptr << 8; } unsigned long DiskImgLib::GetLongBE(const unsigned char* ptr) { return *(ptr+3) | (unsigned long) *(ptr+2) << 8 | (unsigned long) *(ptr+1) << 16 | (unsigned long) *ptr << 24; } unsigned long DiskImgLib::Get24BE(const unsigned char* ptr) { return *(ptr+2) | (unsigned long) *(ptr+1) << 8 | (unsigned long) *ptr << 16; } void DiskImgLib::PutShortLE(unsigned char* ptr, unsigned short val) { *ptr++ = (unsigned char) val; *ptr = val >> 8; } void DiskImgLib::PutLongLE(unsigned char* ptr, unsigned long val) { *ptr++ = (unsigned char) val; *ptr++ = (unsigned char) (val >> 8); *ptr++ = (unsigned char) (val >> 16); *ptr = (unsigned char) (val >> 24); } void DiskImgLib::PutShortBE(unsigned char* ptr, unsigned short val) { *ptr++ = val >> 8; *ptr = (unsigned char) val; } void DiskImgLib::PutLongBE(unsigned char* ptr, unsigned long val) { *ptr++ = (unsigned char) (val >> 24); *ptr++ = (unsigned char) (val >> 16); *ptr++ = (unsigned char) (val >> 8); *ptr = (unsigned char) val; } /* * Read a two-byte little-endian value. */ DIError DiskImgLib::ReadShortLE(GenericFD* pGFD, short* pBuf) { DIError dierr; unsigned char 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, long* pBuf) { DIError dierr; unsigned char 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] | (long)val[1] << 8 | (long)val[2] << 16 | (long)val[3] << 24; return dierr; } /* * Write a two-byte little-endian value. */ DIError DiskImgLib::WriteShortLE(FILE* fp, unsigned short val) { putc(val, fp); putc(val >> 8, fp); return kDIErrNone; } /* * Write a four-byte little-endian value. */ DIError DiskImgLib::WriteLongLE(FILE* fp, unsigned long 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, unsigned short val) { unsigned char buf; buf = (unsigned char) 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, unsigned long val) { unsigned char buf; buf = (unsigned char) val; pGFD->Write(&buf, 1); buf = (unsigned char) (val >> 8); pGFD->Write(&buf, 1); buf = (unsigned char) (val >> 16); pGFD->Write(&buf, 1); buf = (unsigned char) (val >> 24); return pGFD->Write(&buf, 1); } /* * Write a two-byte big-endian value. */ DIError DiskImgLib::WriteShortBE(GenericFD* pGFD, unsigned short val) { unsigned char buf; buf = val >> 8; pGFD->Write(&buf, 1); buf = (unsigned char) val; return pGFD->Write(&buf, 1); } /* * Write a four-byte big-endian value. */ DIError DiskImgLib::WriteLongBE(GenericFD* pGFD, unsigned long val) { unsigned char buf; buf = (unsigned char) (val >> 24); pGFD->Write(&buf, 1); buf = (unsigned char) (val >> 16); pGFD->Write(&buf, 1); buf = (unsigned char) (val >> 8); pGFD->Write(&buf, 1); buf = (unsigned char) 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 nil. */ const char* DiskImgLib::FilenameOnly(const char* pathname, char fssep) { const char* retstr; const char* pSlash; char* tmpStr = nil; assert(pathname != nil); if (fssep == '\0') { retstr = pathname; goto bail; } pSlash = strrchr(pathname, fssep); if (pSlash == nil) { 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 == nil) { 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 nil 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 != nil); pExt = strrchr(pFilename, kFilenameExtDelim); /* also check for "/blah/foo.", which doesn't count */ if (pExt != nil && *(pExt+1) != '\0') return pExt; return nil; } /* * Like strcpy(), but allocate with new[] instead. * * If "str" is nil, or "new" fails, this returns nil. * * TODO: should be "StrdupNew()" */ char* DiskImgLib::StrcpyNew(const char* str) { char* newStr; if (str == nil) return nil; newStr = new char[strlen(str)+1]; if (newStr != nil) 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 WMSG0("HEY: got ERROR_INVALID_HANDLE!\n"); return kDIErrInternal; case ERROR_NEGATIVE_SEEK: // 131 WMSG0("HEY: got ERROR_NEGATIVE_SEEK!\n"); return kDIErrInternal; default: WMSG2("LastErrorToDIError: not converting 0x%08lx (%ld)\n", 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) { OSVERSIONINFO osvers; BOOL result; osvers.dwOSVersionInfoSize = sizeof(osvers); result = ::GetVersionEx(&osvers); assert(result != FALSE); if (osvers.dwPlatformId == VER_PLATFORM_WIN32_WINDOWS) return true; else return false; } #endif