#include #include #include #include #include "info.h" using namespace std; struct Node { char Name[256]; unsigned Flags; unsigned Size; unsigned Offset; Node* Parent; vector Children; }; Node Root; Node* Current; vector list; unsigned Flags; FILE* Out; char* removeQuotes (char* s) { if (*s == '"') s = s + 1; char* tmp = strrchr(s, '"'); if (tmp) *tmp = '\0'; return s; } int32 indexOf (char* s) { for (int i = 0; i < (int)Current->Children.size(); i++) if (strcmp(s, Current->Children[i]->Name) == 0) return i; return -1; } void CommandCreate (char** argv, int argc) { if (argc < 2) throw ExcSyntaxError; argv[1] = removeQuotes(argv[1]); // Set up root Root.Parent = &Root; Root.Flags = 0xB68; Current = &Root; Flags = 0xB68; // Open 'root' file Out = fopen(argv[1], "wb"); if (!Out) throw ExcCannotOpenOutput; } void CommandSetFlags (char** argv, int argc) { if (argc < 2) throw ExcSyntaxError; argv[1] = removeQuotes(argv[1]); unsigned long tmp = strtoul(argv[1], NULL, 0x10); Flags = (uint32) tmp & 0x497; } void CommandAddFile (char** argv, int argc) { if (argc < 2) throw ExcSyntaxError; argv[1] = removeQuotes(argv[1]); Node* node = new Node(); memset(node, 0, sizeof(Node)); strcpy(node->Name, argv[1]); node->Flags = Flags | 0x1; // File node->Parent = Current; list.push_back(node); Current->Children.push_back(node); } void CommandAddDirectory (char** argv, int argc) { if (argc < 2) throw ExcSyntaxError; argv[1] = removeQuotes(argv[1]); Node* node = new Node(); memset(node, 0, sizeof(Node)); strcpy(node->Name, argv[1]); node->Flags = Flags | 0x2; // Directory node->Parent = Current; list.push_back(node); Current->Children.push_back(node); } void CommandChangeDirectory (char** argv, int argc) { if (argc < 2) throw ExcSyntaxError; argv[1] = removeQuotes(argv[1]); if (argv[1][0] == '\0') return; // See if we need to go to root if (argv[1][0] == '\\') { Current = &Root; argv[1] = argv[1] + 1; } // Process every folder in path while (argv[1]) { char* next = strchr(argv[1], '\\'); // mark next entry to parse if (next) { *next = 0; next = next+1; } // previous dir? if (strcmp(argv[1], "..") == 0) Current = Current->Parent; else { // Find next node int index = indexOf(argv[1]); if (index == -1 && strcmp(argv[1], ".") != 0) throw ExcInvalidPath; // Invalid path // Set as current Current = Current->Children[index]; } argv[1] = next; } } unsigned CurrentOffset; void ProcessNodes(Node* node) { for (int i = 0; i < node->Children.size(); i++) { // Calculate size & offset node->Children[i]->Offset = CurrentOffset; // File if (node->Children[i]->Flags & 0x1) node->Children[i]->Size = InfoGetFileSize(node->Children[i]->Name); // Directory else node->Children[i]->Size = sizeof(unsigned) + (sizeof(DirectoryEntry) * node->Children[i]->Children.size()); CurrentOffset += node->Children[i]->Size; // If it is a directory, go in if (node->Children[i]->Flags & 0x2) ProcessNodes(node->Children[i]); } } bool NodeSort (Node* a, Node* b) { return (a->Offset < b->Offset); } void WriteFile (char* path) { FILE* in = fopen(path, "rb"); if (!in) throw ExcCannotOpenInput; void* buffer = malloc(0x1000); uint32 r = 0; // Copy in 4kb blocks while (r = fread(buffer, sizeof(uint8), 0x1000, in)) fwrite(buffer, sizeof(uint8), r, Out ); free(buffer); } void WriteDirectory (Node* node) { unsigned sz = node->Children.size(); // Write directory header (items count) fwrite (&sz, 1, sizeof (unsigned), Out); for (int i = 0; i < sz; i++) { // Get the info DirectoryEntry dir; memset (&dir, 0, sizeof(DirectoryEntry)); char* temp = InfoGetFileName(node->Children[i]->Name); strcpy(dir.Name, temp); dir.Flags = node->Children[i]->Flags; dir.OwnerId = dir.GroupId = 0; dir.Size = node->Children[i]->Size; dir.TimeCreated = InfoGetFileCreated(node->Children[i]->Name); dir.TimeModified = InfoGetFileModified(node->Children[i]->Name); dir.TimeAccessed = InfoGetTime(); dir.Offset = node->Children[i]->Offset; // Write it fwrite (&dir, 1, sizeof(DirectoryEntry), Out); } } void CommandClose () { unsigned MAGIC = 0xCC23AA90; char* OemStr = "luxram"; CurrentOffset = sizeof(MAGIC) + strlen(OemStr); // Process root Root.Offset = CurrentOffset; Root.Size = sizeof (unsigned) + (Root.Children.size() * sizeof(DirectoryEntry)); CurrentOffset += Root.Size; // Process recursively all the nodes ProcessNodes(&Root); // Now we need to sort the nodes by offset sort(list.begin(), list.end(), NodeSort); // And now we need to write everything to output file fwrite(&MAGIC, sizeof(uint8), 4, Out); // Magic number fwrite(OemStr, sizeof(uint8), strlen(OemStr), Out); // Oem string WriteDirectory(&Root); // Write the root for (int i = 0; i < list.size(); i++) { // If file, write content if (list[i]->Flags & 1) WriteFile(list[i]->Name); // If directory, write list else WriteDirectory(list[i]); } // Done; cleanup while (list.size()) { delete list.back(); list.pop_back(); } fclose(Out); }