mirror of
https://github.com/fadden/ciderpress.git
synced 2024-10-06 01:56:20 +00:00
Improve filename handling when adding files
Most of this change is a conversion of the old FileDetails struct into a new LocalFileDetails class. The new class keeps the members private, and keeps the Unicode and MOR representations of the string separate. The NuFX and DiskImg libraries don't support UTF-16 filenames, so we stil can't add files with non-CP-1252 filenames, but we're a step closer. Also, update NufxLib with a couple of fixes from the main project. Also, fix handling of "%00" when adding files. Also, mark most of the A2FileDOS fields private. Not sure why they weren't.
This commit is contained in:
parent
d94b707489
commit
b79498da50
@ -375,7 +375,7 @@ bail:
|
||||
|
||||
/*static*/ CString AcuArchive::AppInit(void)
|
||||
{
|
||||
return "";
|
||||
return L"";
|
||||
}
|
||||
|
||||
GenericArchive::OpenResult AcuArchive::Open(const WCHAR* filename,
|
||||
@ -526,11 +526,11 @@ int AcuArchive::ReadMasterHeader(int* pNumEntries)
|
||||
header.unknown1 != 1 ||
|
||||
strcmp((char*) header.fZink, "fZink") != 0)
|
||||
{
|
||||
LOGI("Not an ACU archive");
|
||||
LOGW("Not an ACU archive");
|
||||
return -1;
|
||||
}
|
||||
|
||||
LOGI("Looks like an ACU archive with %d entries", header.fileCount);
|
||||
LOGD("Looks like an ACU archive with %d entries", header.fileCount);
|
||||
|
||||
*pNumEntries = header.fileCount;
|
||||
return 0;
|
||||
|
@ -162,7 +162,7 @@ private:
|
||||
}
|
||||
virtual void XferPrepare(const XferFileOptions* pXferOpts) override
|
||||
{ ASSERT(false); }
|
||||
virtual CString XferFile(FileDetails* pDetails, uint8_t** pDataBuf,
|
||||
virtual CString XferFile(LocalFileDetails* pDetails, uint8_t** pDataBuf,
|
||||
long dataLen, uint8_t** pRsrcBuf, long rsrcLen) override
|
||||
{ ASSERT(false); return "!"; }
|
||||
virtual void XferAbort(CWnd* pMsgWnd) override
|
||||
@ -172,7 +172,7 @@ private:
|
||||
|
||||
virtual ArchiveKind GetArchiveKind(void) override { return kArchiveACU; }
|
||||
virtual NuError DoAddFile(const AddFilesDialog* pAddOpts,
|
||||
FileDetails* pDetails) override
|
||||
LocalFileDetails* pDetails) override
|
||||
{ ASSERT(false); return kNuErrGeneric; }
|
||||
|
||||
enum {
|
||||
|
@ -2138,21 +2138,21 @@ void MainWindow::OnUpdateActionsConvFromWav(CCmdUI* pCmdUI)
|
||||
pCmdUI->Enable(fpContentList != NULL && !fpOpenArchive->IsReadOnly());
|
||||
}
|
||||
|
||||
/*static*/ bool MainWindow::SaveToArchive(GenericArchive::FileDetails* pDetails,
|
||||
const unsigned char* dataBufIn, long dataLen,
|
||||
const unsigned char* rsrcBufIn, long rsrcLen,
|
||||
CString& errMsg, CWnd* pDialog)
|
||||
/*static*/ bool MainWindow::SaveToArchive(GenericArchive::LocalFileDetails* pDetails,
|
||||
const uint8_t* dataBufIn, long dataLen,
|
||||
const uint8_t* rsrcBufIn, long rsrcLen,
|
||||
CString* pErrMsg, CWnd* pDialog)
|
||||
{
|
||||
MainWindow* pMain = GET_MAIN_WINDOW();
|
||||
GenericArchive* pArchive = pMain->GetOpenArchive();
|
||||
DiskImgLib::A2File* pTargetSubdir = NULL;
|
||||
XferFileOptions xferOpts;
|
||||
CString storagePrefix;
|
||||
unsigned char* dataBuf = NULL;
|
||||
unsigned char* rsrcBuf = NULL;
|
||||
uint8_t* dataBuf = NULL;
|
||||
uint8_t* rsrcBuf = NULL;
|
||||
|
||||
ASSERT(pArchive != NULL);
|
||||
ASSERT(errMsg.IsEmpty());
|
||||
ASSERT(pErrMsg->IsEmpty());
|
||||
|
||||
/*
|
||||
* Make a copy of the data for XferFile.
|
||||
@ -2163,7 +2163,7 @@ void MainWindow::OnUpdateActionsConvFromWav(CCmdUI* pCmdUI)
|
||||
else
|
||||
dataBuf = new unsigned char[dataLen];
|
||||
if (dataBuf == NULL) {
|
||||
errMsg.Format(L"Unable to allocate %ld bytes", dataLen);
|
||||
pErrMsg->Format(L"Unable to allocate %ld bytes", dataLen);
|
||||
goto bail;
|
||||
}
|
||||
memcpy(dataBuf, dataBufIn, dataLen);
|
||||
@ -2187,7 +2187,7 @@ void MainWindow::OnUpdateActionsConvFromWav(CCmdUI* pCmdUI)
|
||||
// Always use ':' separator for SHK; this is a matter of
|
||||
// convenience, so they can specify a full path.
|
||||
//details.storageName.Replace(':', '_');
|
||||
pDetails->fileSysInfo = ':';
|
||||
pDetails->SetFssep(':');
|
||||
}
|
||||
if (pTargetSubdir != NULL) {
|
||||
storagePrefix = pTargetSubdir->GetPathName();
|
||||
@ -2195,13 +2195,13 @@ void MainWindow::OnUpdateActionsConvFromWav(CCmdUI* pCmdUI)
|
||||
}
|
||||
if (!storagePrefix.IsEmpty()) {
|
||||
CString tmpStr, tmpFileName;
|
||||
tmpFileName = pDetails->storageName;
|
||||
tmpFileName = pDetails->GetStrippedLocalPathName();
|
||||
tmpFileName.Replace(':', '_'); // strip any ':'s in the name
|
||||
pDetails->fileSysInfo = ':';
|
||||
pDetails->SetFssep(':');
|
||||
tmpStr = storagePrefix;
|
||||
tmpStr += ':';
|
||||
tmpStr += tmpFileName;
|
||||
pDetails->storageName = tmpStr;
|
||||
pDetails->SetStrippedLocalPathName(tmpStr);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -2211,18 +2211,18 @@ void MainWindow::OnUpdateActionsConvFromWav(CCmdUI* pCmdUI)
|
||||
*/
|
||||
pArchive->XferPrepare(&xferOpts);
|
||||
|
||||
errMsg = pArchive->XferFile(pDetails, &dataBuf, dataLen,
|
||||
*pErrMsg = pArchive->XferFile(pDetails, &dataBuf, dataLen,
|
||||
&rsrcBuf, rsrcLen);
|
||||
delete[] dataBuf;
|
||||
delete[] rsrcBuf;
|
||||
|
||||
if (errMsg.IsEmpty())
|
||||
if (pErrMsg->IsEmpty())
|
||||
pArchive->XferFinish(pDialog);
|
||||
else
|
||||
pArchive->XferAbort(pDialog);
|
||||
|
||||
bail:
|
||||
return (errMsg.IsEmpty() != 0);
|
||||
return (pErrMsg->IsEmpty() != 0);
|
||||
}
|
||||
|
||||
|
||||
|
@ -149,7 +149,7 @@ private:
|
||||
}
|
||||
virtual void XferPrepare(const XferFileOptions* pXferOpts) override
|
||||
{ ASSERT(false); }
|
||||
virtual CString XferFile(FileDetails* pDetails, uint8_t** pDataBuf,
|
||||
virtual CString XferFile(LocalFileDetails* pDetails, uint8_t** pDataBuf,
|
||||
long dataLen, uint8_t** pRsrcBuf, long rsrcLen) override
|
||||
{ ASSERT(false); return "!"; }
|
||||
virtual void XferAbort(CWnd* pMsgWnd) override
|
||||
@ -159,7 +159,7 @@ private:
|
||||
|
||||
virtual ArchiveKind GetArchiveKind(void) override { return kArchiveBNY; }
|
||||
virtual NuError DoAddFile(const AddFilesDialog* pAddOpts,
|
||||
FileDetails* pDetails) override
|
||||
LocalFileDetails* pDetails) override
|
||||
{ ASSERT(false); return kNuErrGeneric; }
|
||||
|
||||
enum {
|
||||
|
@ -616,25 +616,27 @@ void ImportBASDialog::OnOK(void)
|
||||
/*
|
||||
* Write the file to the currently-open archive.
|
||||
*/
|
||||
GenericArchive::FileDetails details;
|
||||
GenericArchive::LocalFileDetails details;
|
||||
|
||||
details.entryKind = GenericArchive::FileDetails::kFileKindDataFork;
|
||||
details.origName = L"Imported BASIC";
|
||||
details.storageName = fileName;
|
||||
details.access = 0xe3; // unlocked, backup bit set
|
||||
details.fileType = kFileTypeBAS;
|
||||
details.extraType = 0x0801;
|
||||
details.storageType = DiskFS::kStorageSeedling;
|
||||
details.SetEntryKind(GenericArchive::LocalFileDetails::kFileKindDataFork);
|
||||
details.SetLocalPathName(L"Imported BASIC");
|
||||
details.SetStrippedLocalPathName(fileName);
|
||||
details.SetAccess(0xe3); // unlocked, backup bit set
|
||||
details.SetFileType(kFileTypeBAS);
|
||||
details.SetExtraType(0x0801);
|
||||
details.SetStorageType(DiskFS::kStorageSeedling);
|
||||
time_t now = time(NULL);
|
||||
GenericArchive::UNIXTimeToDateTime(&now, &details.createWhen);
|
||||
GenericArchive::UNIXTimeToDateTime(&now, &details.archiveWhen);
|
||||
GenericArchive::UNIXTimeToDateTime(&now, &details.modWhen);
|
||||
NuDateTime ndt;
|
||||
GenericArchive::UNIXTimeToDateTime(&now, &ndt);
|
||||
details.SetCreateWhen(ndt);
|
||||
details.SetArchiveWhen(ndt);
|
||||
details.SetModWhen(ndt);
|
||||
|
||||
CString errMsg;
|
||||
|
||||
fDirty = true;
|
||||
if (!MainWindow::SaveToArchive(&details, (const unsigned char*) fOutput,
|
||||
fOutputLen, NULL, -1, /*ref*/errMsg, this))
|
||||
fOutputLen, NULL, -1, &errMsg, this))
|
||||
{
|
||||
goto bail;
|
||||
}
|
||||
|
@ -418,29 +418,33 @@ void CassetteDialog::OnImport(void)
|
||||
/*
|
||||
* Write the file to the currently-open archive.
|
||||
*/
|
||||
GenericArchive::FileDetails details;
|
||||
GenericArchive::LocalFileDetails details;
|
||||
|
||||
details.entryKind = GenericArchive::FileDetails::kFileKindDataFork;
|
||||
details.origName = "Cassette WAV";
|
||||
details.storageName = impDialog.fFileName;
|
||||
details.access = 0xe3; // unlocked, backup bit set
|
||||
details.fileType = impDialog.GetFileType();
|
||||
if (details.fileType == kFileTypeBIN)
|
||||
details.extraType = impDialog.fStartAddr;
|
||||
else if (details.fileType == kFileTypeBAS)
|
||||
details.extraType = 0x0801;
|
||||
else
|
||||
details.extraType = 0x0000;
|
||||
details.storageType = DiskFS::kStorageSeedling;
|
||||
details.SetEntryKind(GenericArchive::LocalFileDetails::kFileKindDataFork);
|
||||
details.SetLocalPathName(L"Cassette WAV");
|
||||
details.SetStrippedLocalPathName(impDialog.fFileName);
|
||||
details.SetAccess(0xe3); // unlocked, backup bit set
|
||||
details.SetFileType(impDialog.GetFileType());
|
||||
if (details.GetFileType() == kFileTypeBIN) {
|
||||
details.SetExtraType(impDialog.fStartAddr);
|
||||
} else if (details.GetFileType() == kFileTypeBAS) {
|
||||
details.SetExtraType(0x0801);
|
||||
} else {
|
||||
details.SetExtraType(0x0000);
|
||||
}
|
||||
details.SetStorageType(DiskFS::kStorageSeedling);
|
||||
time_t now = time(NULL);
|
||||
GenericArchive::UNIXTimeToDateTime(&now, &details.createWhen);
|
||||
GenericArchive::UNIXTimeToDateTime(&now, &details.archiveWhen);
|
||||
NuDateTime ndt;
|
||||
GenericArchive::UNIXTimeToDateTime(&now, &ndt);
|
||||
details.SetCreateWhen(ndt);
|
||||
details.SetArchiveWhen(ndt);
|
||||
details.SetModWhen(ndt);
|
||||
|
||||
CString errMsg;
|
||||
|
||||
fDirty = true;
|
||||
if (!MainWindow::SaveToArchive(&details, fDataArray[idx].GetDataBuf(),
|
||||
fDataArray[idx].GetDataLen(), NULL, -1, /*ref*/errMsg, this))
|
||||
fDataArray[idx].GetDataLen(), NULL, -1, &errMsg, this))
|
||||
{
|
||||
goto bail;
|
||||
}
|
||||
|
@ -80,11 +80,11 @@ typedef struct FileCollectionEntry {
|
||||
uint32_t cmmtLen; // len of comments
|
||||
uint32_t fileType;
|
||||
uint32_t auxType;
|
||||
int64_t createWhen; // time_t
|
||||
int64_t modWhen; // time_t
|
||||
int64_t createWhen; // holds time_t
|
||||
int64_t modWhen; // holds time_t
|
||||
uint8_t access; // ProDOS access flags
|
||||
uint8_t entryKind; // GenericArchive::FileDetails::FileKind
|
||||
uint8_t sourceFS; // DiskImgLib::DiskImg::FSFormat
|
||||
uint8_t sourceFS; // holds DiskImgLib::DiskImg::FSFormat
|
||||
uint8_t fssep; // filesystem separator char, e.g. ':'
|
||||
|
||||
/* data comes next: null-terminated WCHAR filename, then data fork, then
|
||||
@ -440,17 +440,17 @@ CString MainWindow::CopyToCollection(GenericEntry* pEntry, void** pBuf,
|
||||
return errStr;
|
||||
}
|
||||
|
||||
GenericArchive::FileDetails::FileKind entryKind;
|
||||
GenericArchive::LocalFileDetails::FileKind entryKind;
|
||||
if (pEntry->GetRecordKind() == GenericEntry::kRecordKindDirectory)
|
||||
entryKind = GenericArchive::FileDetails::kFileKindDirectory;
|
||||
entryKind = GenericArchive::LocalFileDetails::kFileKindDirectory;
|
||||
else if (pEntry->GetHasDataFork() && pEntry->GetHasRsrcFork())
|
||||
entryKind = GenericArchive::FileDetails::kFileKindBothForks;
|
||||
entryKind = GenericArchive::LocalFileDetails::kFileKindBothForks;
|
||||
else if (pEntry->GetHasDataFork())
|
||||
entryKind = GenericArchive::FileDetails::kFileKindDataFork;
|
||||
entryKind = GenericArchive::LocalFileDetails::kFileKindDataFork;
|
||||
else if (pEntry->GetHasRsrcFork())
|
||||
entryKind = GenericArchive::FileDetails::kFileKindRsrcFork;
|
||||
entryKind = GenericArchive::LocalFileDetails::kFileKindRsrcFork;
|
||||
else if (pEntry->GetHasDiskImage())
|
||||
entryKind = GenericArchive::FileDetails::kFileKindDiskImage;
|
||||
entryKind = GenericArchive::LocalFileDetails::kFileKindDiskImage;
|
||||
else {
|
||||
ASSERT(false);
|
||||
return errStr;
|
||||
@ -912,30 +912,32 @@ bail:
|
||||
CString MainWindow::ProcessClipboardEntry(const FileCollectionEntry* pCollEnt,
|
||||
const WCHAR* pathName, const uint8_t* buf, long remLen)
|
||||
{
|
||||
GenericArchive::FileDetails::FileKind entryKind;
|
||||
GenericArchive::FileDetails details;
|
||||
GenericArchive::LocalFileDetails::FileKind entryKind;
|
||||
GenericArchive::LocalFileDetails details;
|
||||
uint8_t* dataBuf = NULL;
|
||||
uint8_t* rsrcBuf = NULL;
|
||||
long dataLen, rsrcLen, cmmtLen;
|
||||
CString errMsg;
|
||||
|
||||
entryKind = (GenericArchive::FileDetails::FileKind) pCollEnt->entryKind;
|
||||
LOGI(" Processing '%ls' (%d)", pathName, entryKind);
|
||||
entryKind = (GenericArchive::LocalFileDetails::FileKind) pCollEnt->entryKind;
|
||||
LOGD(" Processing '%ls' (%d)", pathName, entryKind);
|
||||
|
||||
details.entryKind = entryKind;
|
||||
details.origName = L"Clipboard";
|
||||
details.storageName = pathName; // TODO MacRoman convert
|
||||
details.fileSysFmt = (DiskImg::FSFormat) pCollEnt->sourceFS;
|
||||
details.fileSysInfo = pCollEnt->fssep;
|
||||
details.access = pCollEnt->access;
|
||||
details.fileType = pCollEnt->fileType;
|
||||
details.extraType = pCollEnt->auxType;
|
||||
GenericArchive::UNIXTimeToDateTime(&pCollEnt->createWhen,
|
||||
&details.createWhen);
|
||||
GenericArchive::UNIXTimeToDateTime(&pCollEnt->modWhen,
|
||||
&details.modWhen);
|
||||
details.SetEntryKind(entryKind);
|
||||
details.SetLocalPathName(L"Clipboard");
|
||||
details.SetStrippedLocalPathName(pathName);
|
||||
details.SetFileSysFmt((DiskImg::FSFormat) pCollEnt->sourceFS);
|
||||
details.SetFssep(pCollEnt->fssep);
|
||||
details.SetAccess(pCollEnt->access);
|
||||
details.SetFileType(pCollEnt->fileType);
|
||||
details.SetExtraType(pCollEnt->auxType);
|
||||
NuDateTime ndt;
|
||||
GenericArchive::UNIXTimeToDateTime(&pCollEnt->createWhen, &ndt);
|
||||
details.SetCreateWhen(ndt);
|
||||
GenericArchive::UNIXTimeToDateTime(&pCollEnt->modWhen, &ndt);
|
||||
details.SetModWhen(ndt);
|
||||
time_t now = time(NULL);
|
||||
GenericArchive::UNIXTimeToDateTime(&now, &details.archiveWhen);
|
||||
GenericArchive::UNIXTimeToDateTime(&now, &ndt);
|
||||
details.SetArchiveWhen(ndt);
|
||||
|
||||
/*
|
||||
* Because of the way XferFile works, we need to make a copy of
|
||||
@ -958,23 +960,23 @@ CString MainWindow::ProcessClipboardEntry(const FileCollectionEntry* pCollEnt,
|
||||
*/
|
||||
bool hasData = false;
|
||||
bool hasRsrc = false;
|
||||
if (details.entryKind == GenericArchive::FileDetails::kFileKindDataFork) {
|
||||
if (entryKind == GenericArchive::LocalFileDetails::kFileKindDataFork) {
|
||||
hasData = true;
|
||||
details.storageType = kNuStorageSeedling;
|
||||
} else if (details.entryKind == GenericArchive::FileDetails::kFileKindRsrcFork) {
|
||||
details.SetStorageType(kNuStorageSeedling);
|
||||
} else if (entryKind == GenericArchive::LocalFileDetails::kFileKindRsrcFork) {
|
||||
hasRsrc = true;
|
||||
details.storageType = kNuStorageExtended;
|
||||
} else if (details.entryKind == GenericArchive::FileDetails::kFileKindBothForks) {
|
||||
details.SetStorageType(kNuStorageExtended);
|
||||
} else if (entryKind == GenericArchive::LocalFileDetails::kFileKindBothForks) {
|
||||
hasData = hasRsrc = true;
|
||||
details.storageType = kNuStorageExtended;
|
||||
} else if (details.entryKind == GenericArchive::FileDetails::kFileKindDiskImage) {
|
||||
details.SetStorageType(kNuStorageExtended);
|
||||
} else if (entryKind == GenericArchive::LocalFileDetails::kFileKindDiskImage) {
|
||||
hasData = true;
|
||||
details.storageType = kNuStorageSeedling;
|
||||
} else if (details.entryKind == GenericArchive::FileDetails::kFileKindDirectory) {
|
||||
details.storageType = kNuStorageDirectory;
|
||||
details.SetStorageType(kNuStorageSeedling);
|
||||
} else if (entryKind == GenericArchive::LocalFileDetails::kFileKindDirectory) {
|
||||
details.SetStorageType(kNuStorageDirectory);
|
||||
} else {
|
||||
ASSERT(false);
|
||||
return "Internal error.";
|
||||
return L"Internal error.";
|
||||
}
|
||||
|
||||
if (hasData) {
|
||||
@ -985,7 +987,7 @@ CString MainWindow::ProcessClipboardEntry(const FileCollectionEntry* pCollEnt,
|
||||
dataLen = pCollEnt->dataLen;
|
||||
dataBuf = new uint8_t[dataLen];
|
||||
if (dataBuf == NULL)
|
||||
return "memory allocation failed.";
|
||||
return L"memory allocation failed.";
|
||||
memcpy(dataBuf, buf, dataLen);
|
||||
buf += dataLen;
|
||||
remLen -= dataLen;
|
||||
@ -1003,7 +1005,7 @@ CString MainWindow::ProcessClipboardEntry(const FileCollectionEntry* pCollEnt,
|
||||
rsrcLen = pCollEnt->rsrcLen;
|
||||
rsrcBuf = new uint8_t[rsrcLen];
|
||||
if (rsrcBuf == NULL)
|
||||
return "Memory allocation failed.";
|
||||
return L"Memory allocation failed.";
|
||||
memcpy(rsrcBuf, buf, rsrcLen);
|
||||
buf += rsrcLen;
|
||||
remLen -= rsrcLen;
|
||||
|
@ -466,21 +466,26 @@ GenericArchive::OpenResult DiskArchive::Open(const WCHAR* filename,
|
||||
{
|
||||
CWaitCursor waitc;
|
||||
|
||||
// TODO(Unicode): modify DiskImg lib to accept wide paths
|
||||
CStringA fileNameA(filename);
|
||||
if (!PathName::TestNarrowConversion(filename, fileNameA, &errMsg)) {
|
||||
result = kResultFailure;
|
||||
goto bail;
|
||||
}
|
||||
dierr = fDiskImg.OpenImage(fileNameA, PathProposal::kLocalFssep,
|
||||
readOnly);
|
||||
if (dierr == kDIErrAccessDenied && !readOnly && !isVolume) {
|
||||
// retry file open with read-only set
|
||||
// don't do that for volumes -- assume they know what they want
|
||||
LOGI(" Retrying open with read-only set");
|
||||
LOGD(" Retrying open with read-only set");
|
||||
fIsReadOnly = readOnly = true;
|
||||
dierr = fDiskImg.OpenImage(fileNameA, PathProposal::kLocalFssep,
|
||||
readOnly);
|
||||
}
|
||||
if (dierr != kDIErrNone) {
|
||||
if (dierr == kDIErrFileArchive)
|
||||
if (dierr == kDIErrFileArchive) {
|
||||
result = kResultFileArchive;
|
||||
else {
|
||||
} else {
|
||||
result = kResultFailure;
|
||||
errMsg.Format(L"Unable to open '%ls': %hs.", filename,
|
||||
DiskImgLib::DIStrError(dierr));
|
||||
@ -507,7 +512,7 @@ GenericArchive::OpenResult DiskArchive::Open(const WCHAR* filename,
|
||||
imf.SetAllowGenericFormats(false);
|
||||
|
||||
if (imf.DoModal() != IDOK) {
|
||||
LOGI("User bailed on IMF dialog");
|
||||
LOGD("User bailed on IMF dialog");
|
||||
result = kResultCancel;
|
||||
goto bail;
|
||||
}
|
||||
@ -1246,7 +1251,7 @@ bail:
|
||||
}
|
||||
|
||||
NuError DiskArchive::DoAddFile(const AddFilesDialog* pAddOpts,
|
||||
FileDetails* pDetails)
|
||||
LocalFileDetails* pDetails)
|
||||
{
|
||||
/*
|
||||
* Add a file to a disk image Unfortunately we can't just add the files
|
||||
@ -1286,8 +1291,9 @@ NuError DiskArchive::DoAddFile(const AddFilesDialog* pAddOpts,
|
||||
int neededLen = 64; // reasonable guess
|
||||
char* fsNormalBuf = NULL; // name as it will appear on disk image
|
||||
|
||||
LOGI(" +++ ADD file: orig='%ls' stor='%ls'",
|
||||
(LPCWSTR) pDetails->origName, (LPCWSTR) pDetails->storageName);
|
||||
LOGI(" +++ ADD file: orig='%ls' strip='%ls'",
|
||||
(LPCWSTR) pDetails->GetLocalPathName(),
|
||||
(LPCWSTR) pDetails->GetStrippedLocalPathName());
|
||||
|
||||
retry:
|
||||
/*
|
||||
@ -1295,14 +1301,13 @@ retry:
|
||||
*/
|
||||
delete[] fsNormalBuf;
|
||||
fsNormalBuf = new char[neededLen];
|
||||
CStringA storageNameA(pDetails->storageName);
|
||||
dierr = pDiskFS->NormalizePath(storageNameA,
|
||||
dierr = pDiskFS->NormalizePath(pDetails->GetStoragePathNameMOR(),
|
||||
PathProposal::kDefaultStoredFssep, fsNormalBuf, &neededLen);
|
||||
if (dierr == kDIErrDataOverrun) {
|
||||
/* not long enough, try again *once* */
|
||||
delete[] fsNormalBuf;
|
||||
fsNormalBuf = new char[neededLen];
|
||||
dierr = pDiskFS->NormalizePath(storageNameA,
|
||||
dierr = pDiskFS->NormalizePath(pDetails->GetStoragePathNameMOR(),
|
||||
PathProposal::kDefaultStoredFssep, fsNormalBuf, &neededLen);
|
||||
}
|
||||
if (dierr != kDIErrNone) {
|
||||
@ -1337,16 +1342,16 @@ retry:
|
||||
goto retry;
|
||||
} else if (result == kNuOverwrite) {
|
||||
/* delete the existing file immediately */
|
||||
LOGI(" Deleting existing file '%hs'", fsNormalBuf);
|
||||
LOGD(" Deleting existing file '%hs'", fsNormalBuf);
|
||||
dierr = pDiskFS->DeleteFile(pExisting);
|
||||
if (dierr != kDIErrNone) {
|
||||
// Would be nice to show a dialog and explain *why*, but
|
||||
// I'm not sure we have a window here.
|
||||
LOGI(" Deletion failed (err=%d)", dierr);
|
||||
LOGE(" Deletion failed (err=%d)", dierr);
|
||||
goto bail;
|
||||
}
|
||||
} else {
|
||||
LOGI("GLITCH: bad return %d from HandleReplaceExisting",result);
|
||||
LOGE("GLITCH: bad return %d from HandleReplaceExisting",result);
|
||||
assert(false);
|
||||
nuerr = kNuErrInternal;
|
||||
goto bail;
|
||||
@ -1364,7 +1369,7 @@ retry:
|
||||
goto bail;
|
||||
}
|
||||
|
||||
LOGI("FSNormalized is '%hs'", pAddData->GetFSNormalPath());
|
||||
LOGD("FSNormalized is '%hs'", pAddData->GetFSNormalPath());
|
||||
|
||||
AddToAddDataList(pAddData);
|
||||
|
||||
@ -1374,7 +1379,7 @@ bail:
|
||||
}
|
||||
|
||||
NuResult DiskArchive::HandleReplaceExisting(const A2File* pExisting,
|
||||
FileDetails* pDetails)
|
||||
LocalFileDetails* pDetails)
|
||||
{
|
||||
NuResult result;
|
||||
|
||||
@ -1390,8 +1395,8 @@ NuResult DiskArchive::HandleReplaceExisting(const A2File* pExisting,
|
||||
confOvwr.fExistingFile = pExisting->GetPathName();
|
||||
confOvwr.fExistingFileModWhen = pExisting->GetModWhen();
|
||||
|
||||
PathName srcPath(pDetails->origName);
|
||||
confOvwr.fNewFileSource = pDetails->origName; // or storageName?
|
||||
PathName srcPath(pDetails->GetLocalPathName());
|
||||
confOvwr.fNewFileSource = pDetails->GetLocalPathName();
|
||||
confOvwr.fNewFileModWhen = srcPath.GetModWhen();
|
||||
|
||||
if (confOvwr.DoModal() == IDCANCEL) {
|
||||
@ -1399,6 +1404,9 @@ NuResult DiskArchive::HandleReplaceExisting(const A2File* pExisting,
|
||||
return kNuAbort;
|
||||
}
|
||||
|
||||
// TODO: if they rename one fork, we need to track that fact and
|
||||
// carry it over to the other fork -- otherwise they can rename
|
||||
// the data and resource forks into separate files.
|
||||
if (confOvwr.fResultRename) {
|
||||
/*
|
||||
* Replace the name in FileDetails. They were asked to modify
|
||||
@ -1413,8 +1421,9 @@ NuResult DiskArchive::HandleReplaceExisting(const A2File* pExisting,
|
||||
* full path and reject "OK" if it's not valid. Instead, we just
|
||||
* allow the FS normalizer to force the filename to be valid.
|
||||
*/
|
||||
pDetails->storageName = confOvwr.fExistingFile;
|
||||
LOGI("Trying rename to '%ls'", (LPCWSTR) pDetails->storageName);
|
||||
pDetails->SetStrippedLocalPathName(confOvwr.fExistingFile);
|
||||
LOGI("Trying rename to '%ls'",
|
||||
(LPCWSTR) pDetails->GetStrippedLocalPathName());
|
||||
return kNuRename;
|
||||
}
|
||||
|
||||
@ -1470,26 +1479,26 @@ CString DiskArchive::ProcessFileAddData(DiskFS* pDiskFS, int addOptsConvEOL)
|
||||
|
||||
pData = fpAddDataHead;
|
||||
while (pData != NULL) {
|
||||
const FileDetails* pDataDetails = NULL;
|
||||
const FileDetails* pRsrcDetails = NULL;
|
||||
const FileDetails* pDetails = pData->GetDetails();
|
||||
const LocalFileDetails* pDataDetails = NULL;
|
||||
const LocalFileDetails* pRsrcDetails = NULL;
|
||||
const LocalFileDetails* pDetails = pData->GetDetails();
|
||||
const char* typeStr = "????"; // for debug msg only
|
||||
|
||||
switch (pDetails->entryKind) {
|
||||
case FileDetails::kFileKindDataFork:
|
||||
switch (pDetails->GetEntryKind()) {
|
||||
case LocalFileDetails::kFileKindDataFork:
|
||||
pDataDetails = pDetails;
|
||||
typeStr = "data";
|
||||
break;
|
||||
case FileDetails::kFileKindRsrcFork:
|
||||
case LocalFileDetails::kFileKindRsrcFork:
|
||||
pRsrcDetails = pDetails;
|
||||
typeStr = "rsrc";
|
||||
break;
|
||||
case FileDetails::kFileKindDiskImage:
|
||||
case LocalFileDetails::kFileKindDiskImage:
|
||||
pDataDetails = pDetails;
|
||||
typeStr = "disk";
|
||||
break;
|
||||
case FileDetails::kFileKindBothForks:
|
||||
case FileDetails::kFileKindDirectory:
|
||||
case LocalFileDetails::kFileKindBothForks:
|
||||
case LocalFileDetails::kFileKindDirectory:
|
||||
default:
|
||||
assert(false);
|
||||
return L"internal error";
|
||||
@ -1499,20 +1508,20 @@ CString DiskArchive::ProcessFileAddData(DiskFS* pDiskFS, int addOptsConvEOL)
|
||||
pDetails = pData->GetOtherFork()->GetDetails();
|
||||
typeStr = "both";
|
||||
|
||||
switch (pDetails->entryKind) {
|
||||
case FileDetails::kFileKindDataFork:
|
||||
switch (pDetails->GetEntryKind()) {
|
||||
case LocalFileDetails::kFileKindDataFork:
|
||||
assert(pDataDetails == NULL);
|
||||
pDataDetails = pDetails;
|
||||
break;
|
||||
case FileDetails::kFileKindRsrcFork:
|
||||
case LocalFileDetails::kFileKindRsrcFork:
|
||||
assert(pRsrcDetails == NULL);
|
||||
pRsrcDetails = pDetails;
|
||||
break;
|
||||
case FileDetails::kFileKindDiskImage:
|
||||
case LocalFileDetails::kFileKindDiskImage:
|
||||
assert(false);
|
||||
return L"(internal) add other disk error";
|
||||
case FileDetails::kFileKindBothForks:
|
||||
case FileDetails::kFileKindDirectory:
|
||||
case LocalFileDetails::kFileKindBothForks:
|
||||
case LocalFileDetails::kFileKindDirectory:
|
||||
default:
|
||||
assert(false);
|
||||
return L"internal error";
|
||||
@ -1520,7 +1529,7 @@ CString DiskArchive::ProcessFileAddData(DiskFS* pDiskFS, int addOptsConvEOL)
|
||||
}
|
||||
|
||||
LOGI("Adding file '%ls' (%hs)",
|
||||
(LPCWSTR) pDetails->storageName, typeStr);
|
||||
(LPCWSTR) pDetails->GetStrippedLocalPathName(), typeStr);
|
||||
ASSERT(pDataDetails != NULL || pRsrcDetails != NULL);
|
||||
|
||||
/*
|
||||
@ -1530,14 +1539,20 @@ CString DiskArchive::ProcessFileAddData(DiskFS* pDiskFS, int addOptsConvEOL)
|
||||
* but it could be awkward for HFS (not to mention HFS Plus!).
|
||||
*/
|
||||
DiskFS::CreateParms parms;
|
||||
ConvertFDToCP(pData->GetDetails(), &parms);
|
||||
/* use the FS-normalized path here */
|
||||
/* (do we have to? do we want to?) */
|
||||
parms.pathName = pData->GetFSNormalPath();
|
||||
if (pRsrcDetails != NULL)
|
||||
parms.storageType = kNuStorageExtended;
|
||||
else
|
||||
parms.storageType = kNuStorageSeedling;
|
||||
/* use the FS-normalized path here */
|
||||
/* (do we have to? do we want to?) */
|
||||
parms.pathName = pData->GetFSNormalPath();
|
||||
/* copy the rest out of the LocalFileDetails */
|
||||
parms.fssep = pDetails->GetFssep();
|
||||
parms.fileType = pDetails->GetFileType();
|
||||
parms.auxType = pDetails->GetExtraType();
|
||||
parms.access = pDetails->GetAccess();
|
||||
parms.createWhen = NufxArchive::DateTimeToSeconds(&pDetails->GetCreateWhen());
|
||||
parms.modWhen = NufxArchive::DateTimeToSeconds(&pDetails->GetModWhen());
|
||||
|
||||
dataLen = rsrcLen = -1;
|
||||
if (pDataDetails != NULL) {
|
||||
@ -1545,8 +1560,8 @@ CString DiskArchive::ProcessFileAddData(DiskFS* pDiskFS, int addOptsConvEOL)
|
||||
/* (HA conversion only happens if text conversion happens) */
|
||||
GenericEntry::ConvertHighASCII convHA;
|
||||
if (addOptsConvEOL == AddFilesDialog::kConvEOLType) {
|
||||
if (pDataDetails->fileType == kFileTypeTXT ||
|
||||
pDataDetails->fileType == kFileTypeSRC)
|
||||
if (pDataDetails->GetFileType() == kFileTypeTXT ||
|
||||
pDataDetails->GetFileType() == kFileTypeSRC)
|
||||
{
|
||||
LOGI("Enabling text conversion by type");
|
||||
convEOL = GenericEntry::kConvertEOLOn;
|
||||
@ -1559,14 +1574,14 @@ CString DiskArchive::ProcessFileAddData(DiskFS* pDiskFS, int addOptsConvEOL)
|
||||
else
|
||||
convHA = GenericEntry::kConvertHAOff;
|
||||
|
||||
errMsg = LoadFile(pDataDetails->origName, &dataBuf, &dataLen,
|
||||
errMsg = LoadFile(pDataDetails->GetLocalPathName(), &dataBuf, &dataLen,
|
||||
convEOL, convHA);
|
||||
if (!errMsg.IsEmpty())
|
||||
goto bail;
|
||||
}
|
||||
if (pRsrcDetails != NULL) {
|
||||
/* no text conversion on resource forks */
|
||||
errMsg = LoadFile(pRsrcDetails->origName, &rsrcBuf, &rsrcLen,
|
||||
errMsg = LoadFile(pRsrcDetails->GetLocalPathName(), &rsrcBuf, &rsrcLen,
|
||||
GenericEntry::kConvertEOLOff, GenericEntry::kConvertHAOff);
|
||||
if (!errMsg.IsEmpty())
|
||||
goto bail;
|
||||
@ -1575,7 +1590,7 @@ CString DiskArchive::ProcessFileAddData(DiskFS* pDiskFS, int addOptsConvEOL)
|
||||
/* really ought to do this separately for each thread */
|
||||
SET_PROGRESS_BEGIN();
|
||||
CString pathNameW(parms.pathName);
|
||||
SET_PROGRESS_UPDATE2(0, pDetails->origName, pathNameW);
|
||||
SET_PROGRESS_UPDATE2(0, pDetails->GetLocalPathName(), pathNameW);
|
||||
|
||||
DIError dierr;
|
||||
dierr = AddForksToDisk(pDiskFS, &parms, dataBuf, dataLen,
|
||||
@ -1954,25 +1969,6 @@ bail:
|
||||
return dierr;
|
||||
}
|
||||
|
||||
// TODO: make this a member of FileDetails, and return a struct owned by
|
||||
// FileDetails. This is necessary because we put const strings into
|
||||
// pCreateParms that are owned by FileDetails, and need to coordinate the
|
||||
// object lifetime.
|
||||
void DiskArchive::ConvertFDToCP(const FileDetails* pDetails,
|
||||
DiskFS::CreateParms* pCreateParms)
|
||||
{
|
||||
// ugly hack to get storage for narrow string
|
||||
pDetails->fStorageNameA = pDetails->storageName;
|
||||
pCreateParms->pathName = pDetails->fStorageNameA;
|
||||
pCreateParms->fssep = (char) pDetails->fileSysInfo;
|
||||
pCreateParms->storageType = pDetails->storageType;
|
||||
pCreateParms->fileType = pDetails->fileType;
|
||||
pCreateParms->auxType = pDetails->extraType;
|
||||
pCreateParms->access = pDetails->access;
|
||||
pCreateParms->createWhen = NufxArchive::DateTimeToSeconds(&pDetails->createWhen);
|
||||
pCreateParms->modWhen = NufxArchive::DateTimeToSeconds(&pDetails->modWhen);
|
||||
}
|
||||
|
||||
void DiskArchive::AddToAddDataList(FileAddData* pData)
|
||||
{
|
||||
ASSERT(pData != NULL);
|
||||
@ -1983,31 +1979,31 @@ void DiskArchive::AddToAddDataList(FileAddData* pData)
|
||||
* O(n^2) behavior, but I'm expecting N to be relatively small (under
|
||||
* 1000 in almost all cases).
|
||||
*/
|
||||
//if (strcasecmp(pData->GetDetails()->storageName, "system\\finder") == 0)
|
||||
// LOGI("whee");
|
||||
FileAddData* pSearch = fpAddDataHead;
|
||||
FileDetails::FileKind dataKind, listKind;
|
||||
LocalFileDetails::FileKind dataKind, listKind;
|
||||
|
||||
dataKind = pData->GetDetails()->entryKind;
|
||||
dataKind = pData->GetDetails()->GetEntryKind();
|
||||
while (pSearch != NULL) {
|
||||
if (pSearch->GetOtherFork() == NULL &&
|
||||
wcscmp(pSearch->GetDetails()->storageName,
|
||||
pData->GetDetails()->storageName) == 0)
|
||||
wcscmp(pSearch->GetDetails()->GetStrippedLocalPathName(),
|
||||
pData->GetDetails()->GetStrippedLocalPathName()) == 0)
|
||||
{
|
||||
//NuThreadID dataID = pData->GetDetails()->threadID;
|
||||
//NuThreadID listID = pSearch->GetDetails()->threadID;
|
||||
|
||||
listKind = pSearch->GetDetails()->entryKind;
|
||||
listKind = pSearch->GetDetails()->GetEntryKind();
|
||||
|
||||
/* got a name match */
|
||||
if (dataKind != listKind &&
|
||||
(dataKind == FileDetails::kFileKindDataFork || dataKind == FileDetails::kFileKindRsrcFork) &&
|
||||
(listKind == FileDetails::kFileKindDataFork || listKind == FileDetails::kFileKindRsrcFork))
|
||||
(dataKind == LocalFileDetails::kFileKindDataFork ||
|
||||
dataKind == LocalFileDetails::kFileKindRsrcFork) &&
|
||||
(listKind == LocalFileDetails::kFileKindDataFork ||
|
||||
listKind == LocalFileDetails::kFileKindRsrcFork))
|
||||
{
|
||||
/* looks good, hook it in here instead of the list */
|
||||
LOGD("--- connecting forks of '%ls' and '%ls'",
|
||||
(LPCWSTR) pData->GetDetails()->origName,
|
||||
(LPCWSTR) pSearch->GetDetails()->origName);
|
||||
(LPCWSTR) pData->GetDetails()->GetLocalPathName(),
|
||||
(LPCWSTR) pSearch->GetDetails()->GetLocalPathName());
|
||||
pSearch->SetOtherFork(pData);
|
||||
return;
|
||||
}
|
||||
@ -2299,7 +2295,7 @@ bool DiskArchive::RenameSelection(CWnd* pMsgWnd, SelectionSet* pSelSet)
|
||||
ShowFailureMsg(pMsgWnd, errMsg, IDS_FAILED);
|
||||
goto bail;
|
||||
}
|
||||
LOGI("Rename of '%ls' to '%ls' succeeded",
|
||||
LOGD("Rename of '%ls' to '%ls' succeeded",
|
||||
pEntry->GetDisplayName(), (LPCWSTR) renameDlg.fNewName);
|
||||
} else if (result == IDCANCEL) {
|
||||
LOGI("Canceling out of remaining renames");
|
||||
@ -2528,7 +2524,7 @@ bool DiskArchive::SetProps(CWnd* pMsgWnd, GenericEntry* pGenericEntry,
|
||||
DiskImg::FSFormat fsFormat;
|
||||
fsFormat = pFile->GetDiskFS()->GetDiskImg()->GetFSFormat();
|
||||
if (fsFormat == DiskImg::kFormatDOS32 || fsFormat == DiskImg::kFormatDOS33) {
|
||||
LOGI(" (reloading additional fields after DOS SFI)");
|
||||
LOGD(" (reloading additional fields after DOS SFI)");
|
||||
pEntry->SetDataForkLen(pFile->GetDataLength());
|
||||
pEntry->SetCompressedLen(pFile->GetDataSparseLength());
|
||||
pEntry->SetSuspicious(pFile->GetQuality() == A2File::kQualitySuspicious);
|
||||
@ -2559,9 +2555,9 @@ GenericArchive::XferStatus DiskArchive::XferSelection(CWnd* pMsgWnd,
|
||||
* forked or not.
|
||||
*/
|
||||
LOGI("DiskArchive XferSelection!");
|
||||
unsigned char* dataBuf = NULL;
|
||||
unsigned char* rsrcBuf = NULL;
|
||||
FileDetails fileDetails;
|
||||
uint8_t* dataBuf = NULL;
|
||||
uint8_t* rsrcBuf = NULL;
|
||||
LocalFileDetails fileDetails;
|
||||
CString errMsg, extractErrMsg, cmpStr;
|
||||
CString fixedPathName;
|
||||
XferStatus retval = kXferFailed;
|
||||
@ -2590,7 +2586,7 @@ GenericArchive::XferStatus DiskArchive::XferSelection(CWnd* pMsgWnd,
|
||||
*/
|
||||
fixedPathName = pEntry->GetPathName();
|
||||
if (fixedPathName.IsEmpty())
|
||||
fixedPathName = _T("(no filename)");
|
||||
fixedPathName = L"(no filename)";
|
||||
if (pEntry->GetFSFormat() != DiskImg::kFormatProDOS)
|
||||
fixedPathName.Replace(PathProposal::kDefaultStoredFssep, '.');
|
||||
if (pEntry->GetSubVolName() != NULL) {
|
||||
@ -2603,7 +2599,7 @@ GenericArchive::XferStatus DiskArchive::XferSelection(CWnd* pMsgWnd,
|
||||
|
||||
if (pEntry->GetRecordKind() == GenericEntry::kRecordKindVolumeDir) {
|
||||
/* this is the volume dir */
|
||||
LOGI(" XFER not transferring volume dir '%ls'",
|
||||
LOGD(" XFER not transferring volume dir '%ls'",
|
||||
(LPCWSTR) fixedPathName);
|
||||
continue;
|
||||
} else if (pEntry->GetRecordKind() == GenericEntry::kRecordKindDirectory) {
|
||||
@ -2613,22 +2609,22 @@ GenericArchive::XferStatus DiskArchive::XferSelection(CWnd* pMsgWnd,
|
||||
cmpStr += (char)PathProposal::kDefaultStoredFssep;
|
||||
|
||||
if (pSelSet->CountMatchingPrefix(cmpStr) == 0) {
|
||||
LOGI("FOUND empty dir '%ls'", (LPCWSTR) fixedPathName);
|
||||
LOGD("FOUND empty dir '%ls'", (LPCWSTR) fixedPathName);
|
||||
cmpStr += kEmptyFolderMarker;
|
||||
dataBuf = new unsigned char[1];
|
||||
dataLen = 0;
|
||||
fileDetails.entryKind = FileDetails::kFileKindDataFork;
|
||||
fileDetails.storageName = cmpStr;
|
||||
fileDetails.fileType = 0; // NON
|
||||
fileDetails.access =
|
||||
pEntry->GetAccess() | GenericEntry::kAccessInvisible;
|
||||
fileDetails.SetEntryKind(LocalFileDetails::kFileKindDataFork);
|
||||
fileDetails.SetStrippedLocalPathName(cmpStr);
|
||||
fileDetails.SetFileType(0); // NON
|
||||
fileDetails.SetAccess(
|
||||
pEntry->GetAccess() | GenericEntry::kAccessInvisible);
|
||||
goto have_stuff2;
|
||||
} else {
|
||||
LOGI("NOT empty dir '%ls'", (LPCWSTR) fixedPathName);
|
||||
LOGD("NOT empty dir '%ls'", (LPCWSTR) fixedPathName);
|
||||
}
|
||||
}
|
||||
|
||||
LOGI(" XFER not transferring directory '%ls'",
|
||||
LOGD(" XFER not transferring directory '%ls'",
|
||||
(LPCWSTR) fixedPathName);
|
||||
continue;
|
||||
}
|
||||
@ -2695,38 +2691,42 @@ GenericArchive::XferStatus DiskArchive::XferSelection(CWnd* pMsgWnd,
|
||||
ASSERT(rsrcBuf == NULL);
|
||||
}
|
||||
|
||||
if (pEntry->GetHasDataFork() && pEntry->GetHasRsrcFork())
|
||||
fileDetails.entryKind = FileDetails::kFileKindBothForks;
|
||||
else if (pEntry->GetHasDataFork())
|
||||
fileDetails.entryKind = FileDetails::kFileKindDataFork;
|
||||
else if (pEntry->GetHasRsrcFork())
|
||||
fileDetails.entryKind = FileDetails::kFileKindRsrcFork;
|
||||
else {
|
||||
if (pEntry->GetHasDataFork() && pEntry->GetHasRsrcFork()) {
|
||||
fileDetails.SetEntryKind(LocalFileDetails::kFileKindBothForks);
|
||||
} else if (pEntry->GetHasDataFork()) {
|
||||
fileDetails.SetEntryKind(LocalFileDetails::kFileKindDataFork);
|
||||
} else if (pEntry->GetHasRsrcFork()) {
|
||||
fileDetails.SetEntryKind(LocalFileDetails::kFileKindRsrcFork);
|
||||
} else {
|
||||
ASSERT(false);
|
||||
fileDetails.entryKind = FileDetails::kFileKindUnknown;
|
||||
fileDetails.SetEntryKind(LocalFileDetails::kFileKindUnknown);
|
||||
}
|
||||
|
||||
/*
|
||||
* Set up the FileDetails.
|
||||
* Set up the rest of the LocalFileDetails fields.
|
||||
*/
|
||||
fileDetails.storageName = fixedPathName;
|
||||
fileDetails.fileType = pEntry->GetFileType();
|
||||
fileDetails.access = pEntry->GetAccess();
|
||||
fileDetails.SetStrippedLocalPathName(fixedPathName);
|
||||
fileDetails.SetFileType(pEntry->GetFileType());
|
||||
fileDetails.SetAccess(pEntry->GetAccess());
|
||||
have_stuff2:
|
||||
fileDetails.fileSysFmt = pEntry->GetSourceFS();
|
||||
fileDetails.fileSysInfo = PathProposal::kDefaultStoredFssep;
|
||||
fileDetails.extraType = pEntry->GetAuxType();
|
||||
fileDetails.storageType = kNuStorageUnknown; /* let NufxLib deal */
|
||||
fileDetails.SetFileSysFmt(pEntry->GetSourceFS());
|
||||
fileDetails.SetFssep(PathProposal::kDefaultStoredFssep);
|
||||
fileDetails.SetExtraType(pEntry->GetAuxType());
|
||||
fileDetails.SetStorageType(kNuStorageUnknown); // let NufxLib deal
|
||||
|
||||
NuDateTime ndt;
|
||||
time_t when;
|
||||
when = time(NULL);
|
||||
UNIXTimeToDateTime(&when, &fileDetails.archiveWhen);
|
||||
UNIXTimeToDateTime(&when, &ndt);
|
||||
fileDetails.SetArchiveWhen(ndt);
|
||||
when = pEntry->GetModWhen();
|
||||
UNIXTimeToDateTime(&when, &fileDetails.modWhen);
|
||||
UNIXTimeToDateTime(&when, &ndt);
|
||||
fileDetails.SetModWhen(ndt);
|
||||
when = pEntry->GetCreateWhen();
|
||||
UNIXTimeToDateTime(&when, &fileDetails.createWhen);
|
||||
UNIXTimeToDateTime(&when, &ndt);
|
||||
fileDetails.SetCreateWhen(ndt);
|
||||
|
||||
pActionProgress->SetArcName(fileDetails.storageName);
|
||||
pActionProgress->SetArcName(fileDetails.GetStrippedLocalPathName());
|
||||
if (pActionProgress->SetProgress(0) == IDCANCEL) {
|
||||
retval = kXferCancelled;
|
||||
goto bail;
|
||||
@ -2780,23 +2780,20 @@ void DiskArchive::XferPrepare(const XferFileOptions* pXferOpts)
|
||||
fpXferTargetFS = pXferOpts->fpTargetFS;
|
||||
}
|
||||
|
||||
CString DiskArchive::XferFile(FileDetails* pDetails, uint8_t** pDataBuf,
|
||||
CString DiskArchive::XferFile(LocalFileDetails* pDetails, uint8_t** pDataBuf,
|
||||
long dataLen, uint8_t** pRsrcBuf, long rsrcLen)
|
||||
{
|
||||
//const int kFileTypeTXT = 0x04;
|
||||
DiskFS::CreateParms createParms;
|
||||
DiskFS* pDiskFS;
|
||||
CString errMsg;
|
||||
DIError dierr = kDIErrNone;
|
||||
|
||||
LOGI(" XFER: transfer '%ls' (dataLen=%ld rsrcLen=%ld)",
|
||||
(LPCWSTR) pDetails->storageName, dataLen, rsrcLen);
|
||||
(LPCWSTR) pDetails->GetStrippedLocalPathName(), dataLen, rsrcLen);
|
||||
|
||||
ASSERT(pDataBuf != NULL);
|
||||
ASSERT(pRsrcBuf != NULL);
|
||||
|
||||
/* fill out CreateParms from FileDetails */
|
||||
ConvertFDToCP(pDetails, &createParms);
|
||||
const DiskFS::CreateParms& createParms = pDetails->GetCreateParms();
|
||||
|
||||
if (fpXferTargetFS == NULL)
|
||||
pDiskFS = fpPrimaryDiskFS;
|
||||
@ -2813,22 +2810,24 @@ CString DiskArchive::XferFile(FileDetails* pDetails, uint8_t** pDataBuf,
|
||||
* not worth adding a new interface just for that.
|
||||
*/
|
||||
bool srcIsDOS, dstIsDOS;
|
||||
srcIsDOS = DiskImg::UsesDOSFileStructure(pDetails->fileSysFmt);
|
||||
srcIsDOS = DiskImg::UsesDOSFileStructure(pDetails->GetFileSysFmt());
|
||||
dstIsDOS = DiskImg::UsesDOSFileStructure(pDiskFS->GetDiskImg()->GetFSFormat());
|
||||
if (dataLen > 0 &&
|
||||
(pDetails->fileType == kFileTypeTXT || pDetails->fileType == kFileTypeSRC))
|
||||
(pDetails->GetFileType() == kFileTypeTXT ||
|
||||
pDetails->GetFileType() == kFileTypeSRC))
|
||||
{
|
||||
unsigned char* ucp = *pDataBuf;
|
||||
long len = dataLen;
|
||||
|
||||
if (srcIsDOS && !dstIsDOS) {
|
||||
LOGD(" Stripping high ASCII from '%ls'",
|
||||
(LPCWSTR) pDetails->storageName);
|
||||
(LPCWSTR) pDetails->GetStrippedLocalPathName());
|
||||
|
||||
while (len--)
|
||||
*ucp++ &= 0x7f;
|
||||
} else if (!srcIsDOS && dstIsDOS) {
|
||||
LOGD(" Adding high ASCII to '%ls'", (LPCWSTR) pDetails->storageName);
|
||||
LOGD(" Adding high ASCII to '%ls'",
|
||||
(LPCWSTR) pDetails->GetStrippedLocalPathName());
|
||||
|
||||
while (len--) {
|
||||
if (*ucp != '\0')
|
||||
@ -2837,9 +2836,10 @@ CString DiskArchive::XferFile(FileDetails* pDetails, uint8_t** pDataBuf,
|
||||
}
|
||||
} else if (srcIsDOS && dstIsDOS) {
|
||||
LOGD(" --- not altering DOS-to-DOS text '%ls'",
|
||||
(LPCWSTR) pDetails->storageName);
|
||||
(LPCWSTR) pDetails->GetStrippedLocalPathName());
|
||||
} else {
|
||||
LOGD(" --- non-DOS transfer '%ls'", (LPCWSTR) pDetails->storageName);
|
||||
LOGD(" --- non-DOS transfer '%ls'",
|
||||
(LPCWSTR) pDetails->GetStrippedLocalPathName());
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -231,7 +231,7 @@ private:
|
||||
virtual CString Close(void);
|
||||
|
||||
virtual void XferPrepare(const XferFileOptions* pXferOpts) override;
|
||||
virtual CString XferFile(FileDetails* pDetails, uint8_t** pDataBuf,
|
||||
virtual CString XferFile(LocalFileDetails* pDetails, uint8_t** pDataBuf,
|
||||
long dataLen, uint8_t** pRsrcBuf, long rsrcLen) override;
|
||||
virtual void XferAbort(CWnd* pMsgWnd) override;
|
||||
virtual void XferFinish(CWnd* pMsgWnd) override;
|
||||
@ -253,10 +253,10 @@ private:
|
||||
*/
|
||||
class FileAddData {
|
||||
public:
|
||||
FileAddData(const FileDetails* pDetails, char* fsNormalPath) {
|
||||
FileAddData(const LocalFileDetails* pDetails, char* fsNormalPathMOR) {
|
||||
fDetails = *pDetails;
|
||||
|
||||
fFSNormalPath = fsNormalPath;
|
||||
fFSNormalPathMOR = fsNormalPathMOR;
|
||||
fpOtherFork = NULL;
|
||||
fpNext = NULL;
|
||||
}
|
||||
@ -267,25 +267,21 @@ private:
|
||||
FileAddData* GetOtherFork(void) const { return fpOtherFork; }
|
||||
void SetOtherFork(FileAddData* pData) { fpOtherFork = pData; }
|
||||
|
||||
const FileDetails* GetDetails(void) const { return &fDetails; }
|
||||
const LocalFileDetails* GetDetails(void) const { return &fDetails; }
|
||||
|
||||
/*
|
||||
* Get the "FS-normal" path, i.e. exactly what we want to appear
|
||||
* on the disk image. This has the result of any conversions, so
|
||||
* we need to store it as a narrow string.
|
||||
* we need to store it as a narrow Mac OS Roman string.
|
||||
*/
|
||||
const char* GetFSNormalPath(void) const { return fFSNormalPath; }
|
||||
const char* GetFSNormalPath(void) const { return fFSNormalPathMOR; }
|
||||
|
||||
private:
|
||||
// Three filenames stored inside FileDetails:
|
||||
// fDetails.origName -- the name of the Windows file
|
||||
// fDetails.storageName -- origName with type-preservation goodies
|
||||
// stripped out
|
||||
// fFSNormalPath -- the FS-normalized version of "storageName", i.e.
|
||||
// the name as it will appear on the Apple II disk image
|
||||
LocalFileDetails fDetails;
|
||||
|
||||
FileDetails fDetails;
|
||||
CStringA fFSNormalPath;
|
||||
// The DiskFS-normalized version of the storage name. This is the
|
||||
// name as it will appear on the Apple II disk image.
|
||||
CStringA fFSNormalPathMOR;
|
||||
|
||||
FileAddData* fpOtherFork;
|
||||
FileAddData* fpNext;
|
||||
@ -293,7 +289,7 @@ private:
|
||||
|
||||
virtual ArchiveKind GetArchiveKind(void) override { return kArchiveDiskImage; }
|
||||
virtual NuError DoAddFile(const AddFilesDialog* pAddOpts,
|
||||
FileDetails* pDetails) override;
|
||||
LocalFileDetails* pDetails) override;
|
||||
|
||||
/*
|
||||
* Reload the contents of the archive, showing an error message if the
|
||||
@ -344,7 +340,7 @@ private:
|
||||
* Replaces pDetails->storageName if the user elects to rename
|
||||
*/
|
||||
NuResult HandleReplaceExisting(const A2File* pExisting,
|
||||
FileDetails* pDetails);
|
||||
LocalFileDetails* pDetails);
|
||||
|
||||
/*
|
||||
* Process the list of pending file adds.
|
||||
@ -394,15 +390,6 @@ private:
|
||||
*/
|
||||
void FreeAddDataList(void);
|
||||
|
||||
/*
|
||||
* Fill out a CreateParms structure from a FileDetails structure.
|
||||
*
|
||||
* The NuStorageType values correspond exactly to ProDOS storage types, so
|
||||
* there's no need to convert them.
|
||||
*/
|
||||
void ConvertFDToCP(const FileDetails* pDetails,
|
||||
DiskFS::CreateParms* pCreateParms);
|
||||
|
||||
/*
|
||||
* Set up a RenameEntryDialog for the entry in "*pEntry".
|
||||
*
|
||||
|
@ -1287,9 +1287,11 @@ void PathProposal::DenormalizePath(WCHAR* pathBuf)
|
||||
ch = HexDigit(*srcp) << 4;
|
||||
srcp++;
|
||||
if (isxdigit((int)*srcp)) {
|
||||
/* valid, output char */
|
||||
/* valid, output char (unless it's a %00 place-holder) */
|
||||
ch += HexDigit(*srcp);
|
||||
*dstp++ = ch;
|
||||
if (ch != '\0') {
|
||||
*dstp++ = ch;
|
||||
}
|
||||
srcp++;
|
||||
} else {
|
||||
/* bogus '%' with trailing hex digit found! */
|
||||
|
@ -10,6 +10,7 @@
|
||||
*/
|
||||
#include "stdafx.h"
|
||||
#include "GenericArchive.h"
|
||||
#include "NufxArchive.h"
|
||||
#include "FileNameConv.h"
|
||||
#include "ContentList.h"
|
||||
#include "Main.h"
|
||||
@ -46,36 +47,34 @@
|
||||
*/
|
||||
|
||||
GenericEntry::GenericEntry(void)
|
||||
: fPathName(NULL),
|
||||
fFileName(NULL),
|
||||
fFileNameExtension(NULL),
|
||||
fFssep('\0'),
|
||||
fSubVolName(NULL),
|
||||
fDisplayName(NULL),
|
||||
fFileType(0),
|
||||
fAuxType(0),
|
||||
fAccess(0),
|
||||
fCreateWhen(kDateNone),
|
||||
fModWhen(kDateNone),
|
||||
fRecordKind(kRecordKindUnknown),
|
||||
fFormatStr(L"Unknown"),
|
||||
fDataForkLen(0),
|
||||
fRsrcForkLen(0),
|
||||
fCompressedLen(0),
|
||||
fSourceFS(DiskImg::kFormatUnknown),
|
||||
fHasDataFork(false),
|
||||
fHasRsrcFork(false),
|
||||
fHasDiskImage(false),
|
||||
fHasComment(false),
|
||||
fHasNonEmptyComment(false),
|
||||
fDamaged(false),
|
||||
fSuspicious(false),
|
||||
fIndex(-1),
|
||||
fpPrev(NULL),
|
||||
fpNext(NULL)
|
||||
{
|
||||
fPathName = NULL;
|
||||
fFileName = NULL;
|
||||
fFssep = '\0';
|
||||
fSubVolName = NULL;
|
||||
fDisplayName = NULL;
|
||||
fFileType = 0;
|
||||
fAuxType = 0;
|
||||
fAccess = 0;
|
||||
fModWhen = kDateNone;
|
||||
fCreateWhen = kDateNone;
|
||||
fRecordKind = kRecordKindUnknown;
|
||||
fFormatStr = L"Unknown";
|
||||
fCompressedLen = 0;
|
||||
//fUncompressedLen = 0;
|
||||
fDataForkLen = fRsrcForkLen = 0;
|
||||
|
||||
fSourceFS = DiskImg::kFormatUnknown;
|
||||
|
||||
fHasDataFork = false;
|
||||
fHasRsrcFork = false;
|
||||
fHasDiskImage = false;
|
||||
fHasComment = false;
|
||||
fHasNonEmptyComment = false;
|
||||
|
||||
fIndex = -1;
|
||||
fpPrev = NULL;
|
||||
fpNext = NULL;
|
||||
|
||||
fDamaged = fSuspicious = false;
|
||||
}
|
||||
|
||||
GenericEntry::~GenericEntry(void)
|
||||
@ -177,7 +176,7 @@ const WCHAR* GenericEntry::GetFileTypeString(void) const
|
||||
}
|
||||
|
||||
/*static*/ bool GenericEntry::CheckHighASCII(const uint8_t* buffer,
|
||||
unsigned long count)
|
||||
size_t count)
|
||||
{
|
||||
/*
|
||||
* (Pulled from NufxLib Funnel.c.)
|
||||
@ -254,7 +253,7 @@ static const char kCharLF = '\n';
|
||||
static const char kCharCR = '\r';
|
||||
|
||||
/*static*/ GenericEntry::ConvertEOL GenericEntry::DetermineConversion(
|
||||
const uint8_t* buffer, long count,
|
||||
const uint8_t* buffer, size_t count,
|
||||
EOLType* pSourceType, ConvertHighASCII* pConvHA)
|
||||
{
|
||||
/*
|
||||
@ -277,7 +276,7 @@ static const char kCharCR = '\r';
|
||||
* it will be stripped *before* the EOL determination is made.
|
||||
*/
|
||||
ConvertHighASCII wantConvHA = *pConvHA;
|
||||
long bufCount, numBinary, numLF, numCR;
|
||||
size_t bufCount, numBinary, numLF, numCR;
|
||||
bool isHighASCII;
|
||||
uint8_t val;
|
||||
|
||||
@ -367,7 +366,7 @@ static inline void PutEOL(FILE* fp)
|
||||
{
|
||||
int err = 0;
|
||||
|
||||
LOGI("+++ WriteConvert conv=%d convHA=%d", *pConv, *pConvHA);
|
||||
LOGD("+++ WriteConvert conv=%d convHA=%d", *pConv, *pConvHA);
|
||||
|
||||
if (len == 0) {
|
||||
LOGI("WriteConvert asked to write 0 bytes; returning");
|
||||
@ -396,7 +395,7 @@ static inline void PutEOL(FILE* fp)
|
||||
*pConvHA = kConvertHAOff;
|
||||
}
|
||||
}
|
||||
LOGI("+++ After auto, conv=%d convHA=%d", *pConv, *pConvHA);
|
||||
LOGD("+++ After auto, conv=%d convHA=%d", *pConv, *pConvHA);
|
||||
ASSERT(*pConv == kConvertEOLOn || *pConv == kConvertEOLOff);
|
||||
ASSERT(*pConvHA == kConvertHAOn || *pConvHA == kConvertHAOff);
|
||||
|
||||
@ -404,7 +403,7 @@ static inline void PutEOL(FILE* fp)
|
||||
if (*pConv == kConvertEOLOff) {
|
||||
if (fwrite(buf, len, 1, fp) != 1) {
|
||||
err = errno;
|
||||
LOGI("WriteConvert failed, err=%d", errno);
|
||||
LOGE("WriteConvert failed, err=%d", errno);
|
||||
}
|
||||
} else {
|
||||
ASSERT(*pConv == kConvertEOLOn);
|
||||
@ -546,7 +545,7 @@ GenericArchive::CreateIndex(void)
|
||||
mangle.Delete(idx+1, len-(idx+1)); /* delete out to the end */
|
||||
mangle += kTmpTemplate;
|
||||
}
|
||||
LOGI("GenDerived: passed '%ls' returned '%ls'", filename, (LPCWSTR) mangle);
|
||||
LOGD("GenDerived: passed '%ls' returned '%ls'", filename, (LPCWSTR) mangle);
|
||||
|
||||
return mangle;
|
||||
}
|
||||
@ -594,13 +593,9 @@ GenericArchive::CreateIndex(void)
|
||||
*/
|
||||
|
||||
/*
|
||||
* This comes straight out of NuLib2, and uses NufxLib data structures. While
|
||||
* it may seem strange to use these structures for non-NuFX archives, they are
|
||||
* convenient and hold at least as much information as any other format needs.
|
||||
* Much of this was adapted from NuLib2.
|
||||
*/
|
||||
|
||||
typedef bool Boolean;
|
||||
|
||||
/*static*/ void GenericArchive::UNIXTimeToDateTime(const time_t* pWhen,
|
||||
NuDateTime* pDateTime)
|
||||
{
|
||||
@ -625,99 +620,6 @@ typedef bool Boolean;
|
||||
pDateTime->weekDay = ptm->tm_wday +1;
|
||||
}
|
||||
|
||||
NuError GenericArchive::GetFileDetails(const AddFilesDialog* pAddOpts,
|
||||
const WCHAR* pathname, struct _stat* psb, FileDetails* pDetails)
|
||||
{
|
||||
//char* livePathStr;
|
||||
time_t now;
|
||||
|
||||
ASSERT(pAddOpts != NULL);
|
||||