mirror of
https://github.com/depp/syncfiles.git
synced 2025-01-17 19:30:23 +00:00
Parse project chunks
This still doesn't show the project on-screen when opening, but it does parse the chunks inside the project file.
This commit is contained in:
parent
4cf55bffbc
commit
4a99288be2
@ -17,6 +17,8 @@ typedef enum ErrorCode {
|
|||||||
kErrCouldNotReadProject,
|
kErrCouldNotReadProject,
|
||||||
// The project file is damaged.
|
// The project file is damaged.
|
||||||
kErrProjectDamaged,
|
kErrProjectDamaged,
|
||||||
|
// The project data is too large.
|
||||||
|
kErrProjectLarge,
|
||||||
// The project file is from an unknown version of SyncFiles.
|
// The project file is from an unknown version of SyncFiles.
|
||||||
kErrProjectUnknownVersion,
|
kErrProjectUnknownVersion,
|
||||||
// Could not query volume parameters.
|
// Could not query volume parameters.
|
||||||
|
114
macos/project.c
114
macos/project.c
@ -48,6 +48,7 @@ boundary. This is just to make it easier to read hexdumps.
|
|||||||
#define kVersion 0x10000
|
#define kVersion 0x10000
|
||||||
|
|
||||||
#define kMaxChunkCount 32
|
#define kMaxChunkCount 32
|
||||||
|
#define kMaxChunkSize (4 * 1024)
|
||||||
|
|
||||||
// clang-format off
|
// clang-format off
|
||||||
|
|
||||||
@ -79,6 +80,9 @@ struct ProjectChunk {
|
|||||||
UInt32 crc32;
|
UInt32 crc32;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static const UInt32 kProjectAliasChunks[2] = {'LOCA', 'REMA'};
|
||||||
|
static const UInt32 kProjectPathChunks[2] = {'LOCP', 'REMP'};
|
||||||
|
|
||||||
// Dimensions of controls.
|
// Dimensions of controls.
|
||||||
enum {
|
enum {
|
||||||
kVBorder = 10,
|
kVBorder = 10,
|
||||||
@ -211,6 +215,73 @@ static void ProjectReadError(ProjectHandle project, ErrorCode err, OSErr osErr)
|
|||||||
ShowError(kErrCouldNotReadProject, err, osErr, name);
|
ShowError(kErrCouldNotReadProject, err, osErr, name);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
typedef enum ProjectChunkStatus {
|
||||||
|
kChunkNotFound,
|
||||||
|
kChunkFound,
|
||||||
|
kChunkError,
|
||||||
|
} ProjectChunkStatus;
|
||||||
|
|
||||||
|
static ProjectChunkStatus ProjectReadChunk(ProjectHandle project, int nchunks,
|
||||||
|
struct ProjectChunk **chunks,
|
||||||
|
UInt32 chunkID, Handle *dataPtr,
|
||||||
|
long *sizePtr)
|
||||||
|
{
|
||||||
|
struct ProjectChunk *chunk, *end;
|
||||||
|
UInt32 offset, size, crc32, gotCRC32;
|
||||||
|
long count;
|
||||||
|
Handle h;
|
||||||
|
OSErr osErr;
|
||||||
|
short fileRef;
|
||||||
|
|
||||||
|
chunk = *chunks;
|
||||||
|
end = chunk + nchunks;
|
||||||
|
for (; chunk < end; chunk++) {
|
||||||
|
if (chunk->id == chunkID) {
|
||||||
|
goto found;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return kChunkNotFound;
|
||||||
|
|
||||||
|
found:
|
||||||
|
offset = chunk->offset;
|
||||||
|
size = chunk->size;
|
||||||
|
crc32 = chunk->crc32;
|
||||||
|
if (size > kMaxChunkSize) {
|
||||||
|
ProjectReadError(project, kErrProjectLarge, 0);
|
||||||
|
return kChunkError;
|
||||||
|
}
|
||||||
|
h = NewHandle(size);
|
||||||
|
if (h == NULL) {
|
||||||
|
ProjectReadError(project, kErrOutOfMemory, MemError());
|
||||||
|
return kChunkError;
|
||||||
|
}
|
||||||
|
if (size > 0) {
|
||||||
|
fileRef = (*project)->fileRef;
|
||||||
|
osErr = SetFPos(fileRef, fsFromStart, offset);
|
||||||
|
if (osErr != 0) {
|
||||||
|
DisposeHandle(h);
|
||||||
|
ProjectReadError(project, kErrNone, osErr);
|
||||||
|
return kChunkError;
|
||||||
|
}
|
||||||
|
count = size;
|
||||||
|
osErr = FSRead(fileRef, &count, *h);
|
||||||
|
if (osErr != 0) {
|
||||||
|
DisposeHandle(h);
|
||||||
|
ProjectReadError(project, kErrNone, osErr);
|
||||||
|
return kChunkError;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
gotCRC32 = CRC32Update(0, *h, size);
|
||||||
|
if (crc32 != gotCRC32) {
|
||||||
|
DisposeHandle(h);
|
||||||
|
ProjectReadError(project, kErrProjectDamaged, 0);
|
||||||
|
return kChunkError;
|
||||||
|
}
|
||||||
|
*dataPtr = h;
|
||||||
|
*sizePtr = size;
|
||||||
|
return kChunkFound;
|
||||||
|
}
|
||||||
|
|
||||||
// ProjectRead reads the project from disk. Returns true on success.
|
// ProjectRead reads the project from disk. Returns true on success.
|
||||||
static Boolean ProjectRead(ProjectHandle project)
|
static Boolean ProjectRead(ProjectHandle project)
|
||||||
{
|
{
|
||||||
@ -220,8 +291,10 @@ static Boolean ProjectRead(ProjectHandle project)
|
|||||||
long count, size;
|
long count, size;
|
||||||
ErrorCode err;
|
ErrorCode err;
|
||||||
OSErr osErr;
|
OSErr osErr;
|
||||||
int nchunks;
|
int nchunks, i;
|
||||||
UInt32 headerCRC, gotCRC;
|
UInt32 headerCRC, gotCRC;
|
||||||
|
Handle chunkData;
|
||||||
|
ProjectChunkStatus chunkStatus;
|
||||||
|
|
||||||
chunks = NULL;
|
chunks = NULL;
|
||||||
err = kErrNone;
|
err = kErrNone;
|
||||||
@ -238,11 +311,14 @@ static Boolean ProjectRead(ProjectHandle project)
|
|||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
if (count < sizeof(header) ||
|
if (count < sizeof(header) ||
|
||||||
memcmp(header.magic, kMagic, sizeof(kMagic)) != 0 ||
|
memcmp(header.magic, kMagic, sizeof(kMagic)) != 0) {
|
||||||
header.chunkCount > kMaxChunkCount) {
|
|
||||||
err = kErrProjectDamaged;
|
err = kErrProjectDamaged;
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
|
if (header.chunkCount > kMaxChunkCount) {
|
||||||
|
err = kErrProjectLarge;
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
headerCRC = header.crc32;
|
headerCRC = header.crc32;
|
||||||
header.crc32 = 0;
|
header.crc32 = 0;
|
||||||
gotCRC = CRC32Update(0, &header, sizeof(header));
|
gotCRC = CRC32Update(0, &header, sizeof(header));
|
||||||
@ -271,7 +347,28 @@ static Boolean ProjectRead(ProjectHandle project)
|
|||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: read project data
|
for (i = 0; i < 2; i++) {
|
||||||
|
chunkStatus =
|
||||||
|
ProjectReadChunk(project, nchunks, chunks, kProjectAliasChunks[i],
|
||||||
|
&chunkData, &size);
|
||||||
|
if (chunkStatus == kChunkError) {
|
||||||
|
goto errorSilent;
|
||||||
|
}
|
||||||
|
if (chunkStatus == kChunkFound) {
|
||||||
|
(*project)->dirs[i].alias = (AliasHandle)chunkData;
|
||||||
|
// FIXME: Resolve the alias.
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
chunkStatus = ProjectReadChunk(
|
||||||
|
project, nchunks, chunks, kProjectPathChunks[i], &chunkData, &size);
|
||||||
|
if (chunkStatus == kChunkError) {
|
||||||
|
goto errorSilent;
|
||||||
|
}
|
||||||
|
if (chunkStatus == kChunkFound) {
|
||||||
|
(*project)->dirs[i].pathLength = size;
|
||||||
|
(*project)->dirs[i].path = chunkData;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (chunks != NULL) {
|
if (chunks != NULL) {
|
||||||
DisposeHandle((Handle)chunks);
|
DisposeHandle((Handle)chunks);
|
||||||
@ -284,6 +381,12 @@ error:
|
|||||||
}
|
}
|
||||||
ProjectReadError(project, err, osErr);
|
ProjectReadError(project, err, osErr);
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
errorSilent:
|
||||||
|
if (chunks != NULL) {
|
||||||
|
DisposeHandle((Handle)chunks);
|
||||||
|
}
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ProjectOpen(FSSpec *spec, ScriptCode script)
|
void ProjectOpen(FSSpec *spec, ScriptCode script)
|
||||||
@ -366,9 +469,6 @@ static OSErr ProjectWriteHeader(short refNum, int nchunks,
|
|||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
static const UInt32 kProjectAliasChunks[2] = {'LOCA', 'REMA'};
|
|
||||||
static const UInt32 kProjectPathChunks[2] = {'LOCP', 'REMP'};
|
|
||||||
|
|
||||||
static OSErr ProjectFlush(short refNum)
|
static OSErr ProjectFlush(short refNum)
|
||||||
{
|
{
|
||||||
ParamBlockRec pb;
|
ParamBlockRec pb;
|
||||||
|
@ -149,6 +149,7 @@ resource 'STR#' (rSTRS_Errors) {{
|
|||||||
"Could not save project “^1”.",
|
"Could not save project “^1”.",
|
||||||
"Could not read project “^1”.",
|
"Could not read project “^1”.",
|
||||||
"The project file is damaged.",
|
"The project file is damaged.",
|
||||||
|
"The project data is too large.",
|
||||||
"The project file is from an unknown version of SyncFiles.",
|
"The project file is from an unknown version of SyncFiles.",
|
||||||
"Could not query volume parameters.",
|
"Could not query volume parameters.",
|
||||||
"Could not create alias.",
|
"Could not create alias.",
|
||||||
|
Loading…
x
Reference in New Issue
Block a user