334 lines
7.3 KiB
C
334 lines
7.3 KiB
C
#include <stdlib.h>
|
|
#include <stdio.h>
|
|
#include <stdint.h>
|
|
#include <string.h>
|
|
#include <unistd.h>
|
|
#include <hfs/hfsplus.h>
|
|
#include <dirent.h>
|
|
|
|
#include <hfs/hfslib.h>
|
|
#include "abstractfile.h"
|
|
#include <inttypes.h>
|
|
|
|
char endianness;
|
|
|
|
|
|
void cmd_ls(Volume* volume, int argc, const char *argv[]) {
|
|
if(argc > 1)
|
|
hfs_ls(volume, argv[1]);
|
|
else
|
|
hfs_ls(volume, "/");
|
|
}
|
|
|
|
void cmd_cat(Volume* volume, int argc, const char *argv[]) {
|
|
HFSPlusCatalogRecord* record;
|
|
AbstractFile* stdoutFile;
|
|
|
|
record = getRecordFromPath(argv[1], volume, NULL, NULL);
|
|
|
|
stdoutFile = createAbstractFileFromFile(stdout);
|
|
|
|
if(record != NULL) {
|
|
if(record->recordType == kHFSPlusFileRecord)
|
|
writeToFile((HFSPlusCatalogFile*)record, stdoutFile, volume);
|
|
else
|
|
printf("Not a file\n");
|
|
} else {
|
|
printf("No such file or directory\n");
|
|
}
|
|
|
|
free(record);
|
|
free(stdoutFile);
|
|
}
|
|
|
|
void cmd_extract(Volume* volume, int argc, const char *argv[]) {
|
|
HFSPlusCatalogRecord* record;
|
|
AbstractFile *outFile;
|
|
|
|
if(argc < 3) {
|
|
printf("Not enough arguments");
|
|
return;
|
|
}
|
|
|
|
outFile = createAbstractFileFromFile(fopen(argv[2], "wb"));
|
|
|
|
if(outFile == NULL) {
|
|
printf("cannot create file");
|
|
}
|
|
|
|
record = getRecordFromPath(argv[1], volume, NULL, NULL);
|
|
|
|
if(record != NULL) {
|
|
if(record->recordType == kHFSPlusFileRecord)
|
|
writeToFile((HFSPlusCatalogFile*)record, outFile, volume);
|
|
else
|
|
printf("Not a file\n");
|
|
} else {
|
|
printf("No such file or directory\n");
|
|
}
|
|
|
|
outFile->close(outFile);
|
|
free(record);
|
|
}
|
|
|
|
void cmd_mv(Volume* volume, int argc, const char *argv[]) {
|
|
if(argc > 2) {
|
|
move(argv[1], argv[2], volume);
|
|
} else {
|
|
printf("Not enough arguments");
|
|
}
|
|
}
|
|
|
|
void cmd_symlink(Volume* volume, int argc, const char *argv[]) {
|
|
if(argc > 2) {
|
|
makeSymlink(argv[1], argv[2], volume);
|
|
} else {
|
|
printf("Not enough arguments");
|
|
}
|
|
}
|
|
|
|
void cmd_mkdir(Volume* volume, int argc, const char *argv[]) {
|
|
if(argc > 1) {
|
|
newFolder(argv[1], volume);
|
|
} else {
|
|
printf("Not enough arguments");
|
|
}
|
|
}
|
|
|
|
void cmd_add(Volume* volume, int argc, const char *argv[]) {
|
|
AbstractFile *inFile;
|
|
|
|
if(argc < 3) {
|
|
printf("Not enough arguments");
|
|
return;
|
|
}
|
|
|
|
inFile = createAbstractFileFromFile(fopen(argv[1], "rb"));
|
|
|
|
if(inFile == NULL) {
|
|
printf("file to add not found");
|
|
}
|
|
|
|
add_hfs(volume, inFile, argv[2]);
|
|
}
|
|
|
|
void cmd_rm(Volume* volume, int argc, const char *argv[]) {
|
|
if(argc > 1) {
|
|
removeFile(argv[1], volume);
|
|
} else {
|
|
printf("Not enough arguments");
|
|
}
|
|
}
|
|
|
|
void cmd_chmod(Volume* volume, int argc, const char *argv[]) {
|
|
int mode;
|
|
|
|
if(argc > 2) {
|
|
sscanf(argv[1], "%o", &mode);
|
|
chmodFile(argv[2], mode, volume);
|
|
} else {
|
|
printf("Not enough arguments");
|
|
}
|
|
}
|
|
|
|
void cmd_extractall(Volume* volume, int argc, const char *argv[]) {
|
|
HFSPlusCatalogRecord* record;
|
|
char cwd[1024];
|
|
char* name;
|
|
|
|
ASSERT(getcwd(cwd, 1024) != NULL, "cannot get current working directory");
|
|
|
|
if(argc > 1)
|
|
record = getRecordFromPath(argv[1], volume, &name, NULL);
|
|
else
|
|
record = getRecordFromPath("/", volume, &name, NULL);
|
|
|
|
if(argc > 2) {
|
|
ASSERT(chdir(argv[2]) == 0, "chdir");
|
|
}
|
|
|
|
if(record != NULL) {
|
|
if(record->recordType == kHFSPlusFolderRecord)
|
|
extractAllInFolder(((HFSPlusCatalogFolder*)record)->folderID, volume);
|
|
else
|
|
printf("Not a folder\n");
|
|
} else {
|
|
printf("No such file or directory\n");
|
|
}
|
|
free(record);
|
|
|
|
ASSERT(chdir(cwd) == 0, "chdir");
|
|
}
|
|
|
|
|
|
void cmd_rmall(Volume* volume, int argc, const char *argv[]) {
|
|
HFSPlusCatalogRecord* record;
|
|
char* name;
|
|
char initPath[1024];
|
|
int lastCharOfPath;
|
|
|
|
if(argc > 1) {
|
|
record = getRecordFromPath(argv[1], volume, &name, NULL);
|
|
strcpy(initPath, argv[1]);
|
|
lastCharOfPath = strlen(argv[1]) - 1;
|
|
if(argv[1][lastCharOfPath] != '/') {
|
|
initPath[lastCharOfPath + 1] = '/';
|
|
initPath[lastCharOfPath + 2] = '\0';
|
|
}
|
|
} else {
|
|
record = getRecordFromPath("/", volume, &name, NULL);
|
|
initPath[0] = '/';
|
|
initPath[1] = '\0';
|
|
}
|
|
|
|
if(record != NULL) {
|
|
if(record->recordType == kHFSPlusFolderRecord) {
|
|
removeAllInFolder(((HFSPlusCatalogFolder*)record)->folderID, volume, initPath);
|
|
} else {
|
|
printf("Not a folder\n");
|
|
}
|
|
} else {
|
|
printf("No such file or directory\n");
|
|
}
|
|
free(record);
|
|
}
|
|
|
|
void cmd_addall(Volume* volume, int argc, const char *argv[]) {
|
|
if(argc < 2) {
|
|
printf("Not enough arguments");
|
|
return;
|
|
}
|
|
|
|
if(argc > 2) {
|
|
addall_hfs(volume, argv[1], argv[2]);
|
|
} else {
|
|
addall_hfs(volume, argv[1], "/");
|
|
}
|
|
}
|
|
|
|
void cmd_grow(Volume* volume, int argc, const char *argv[]) {
|
|
uint64_t newSize;
|
|
|
|
if(argc < 2) {
|
|
printf("Not enough arguments\n");
|
|
return;
|
|
}
|
|
|
|
newSize = 0;
|
|
sscanf(argv[1], "%" PRId64, &newSize);
|
|
|
|
grow_hfs(volume, newSize);
|
|
|
|
printf("grew volume: %" PRId64 "\n", newSize);
|
|
}
|
|
|
|
void cmd_getattr(Volume* volume, int argc, const char *argv[]) {
|
|
HFSPlusCatalogRecord* record;
|
|
|
|
if(argc < 3) {
|
|
printf("Not enough arguments");
|
|
return;
|
|
}
|
|
|
|
record = getRecordFromPath(argv[1], volume, NULL, NULL);
|
|
|
|
if(record != NULL) {
|
|
HFSCatalogNodeID id;
|
|
uint8_t* data;
|
|
size_t size;
|
|
if(record->recordType == kHFSPlusFileRecord)
|
|
id = ((HFSPlusCatalogFile*)record)->fileID;
|
|
else
|
|
id = ((HFSPlusCatalogFolder*)record)->folderID;
|
|
|
|
size = getAttribute(volume, id, argv[2], &data);
|
|
|
|
if(size > 0) {
|
|
fwrite(data, size, 1, stdout);
|
|
free(data);
|
|
} else {
|
|
printf("No such attribute\n");
|
|
}
|
|
} else {
|
|
printf("No such file or directory\n");
|
|
}
|
|
|
|
free(record);
|
|
}
|
|
|
|
void TestByteOrder()
|
|
{
|
|
short int word = 0x0001;
|
|
char *byte = (char *) &word;
|
|
endianness = byte[0] ? IS_LITTLE_ENDIAN : IS_BIG_ENDIAN;
|
|
}
|
|
|
|
|
|
int main(int argc, const char *argv[]) {
|
|
io_func* io;
|
|
Volume* volume;
|
|
|
|
TestByteOrder();
|
|
|
|
if(argc < 3) {
|
|
printf("usage: %s <image-file> <ls|cat|mv|mkdir|add|rm|chmod|extract|extractall|rmall|addall|debug> <arguments>\n", argv[0]);
|
|
return 0;
|
|
}
|
|
|
|
io = openFlatFile(argv[1]);
|
|
if(io == NULL) {
|
|
fprintf(stderr, "error: Cannot open image-file.\n");
|
|
return 1;
|
|
}
|
|
|
|
volume = openVolume(io);
|
|
if(volume == NULL) {
|
|
fprintf(stderr, "error: Cannot open volume.\n");
|
|
CLOSE(io);
|
|
return 1;
|
|
}
|
|
|
|
if(argc > 1) {
|
|
if(strcmp(argv[2], "ls") == 0) {
|
|
cmd_ls(volume, argc - 2, argv + 2);
|
|
} else if(strcmp(argv[2], "cat") == 0) {
|
|
cmd_cat(volume, argc - 2, argv + 2);
|
|
} else if(strcmp(argv[2], "mv") == 0) {
|
|
cmd_mv(volume, argc - 2, argv + 2);
|
|
} else if(strcmp(argv[2], "symlink") == 0) {
|
|
cmd_symlink(volume, argc - 2, argv + 2);
|
|
} else if(strcmp(argv[2], "mkdir") == 0) {
|
|
cmd_mkdir(volume, argc - 2, argv + 2);
|
|
} else if(strcmp(argv[2], "add") == 0) {
|
|
cmd_add(volume, argc - 2, argv + 2);
|
|
} else if(strcmp(argv[2], "rm") == 0) {
|
|
cmd_rm(volume, argc - 2, argv + 2);
|
|
} else if(strcmp(argv[2], "chmod") == 0) {
|
|
cmd_chmod(volume, argc - 2, argv + 2);
|
|
} else if(strcmp(argv[2], "extract") == 0) {
|
|
cmd_extract(volume, argc - 2, argv + 2);
|
|
} else if(strcmp(argv[2], "extractall") == 0) {
|
|
cmd_extractall(volume, argc - 2, argv + 2);
|
|
} else if(strcmp(argv[2], "rmall") == 0) {
|
|
cmd_rmall(volume, argc - 2, argv + 2);
|
|
} else if(strcmp(argv[2], "addall") == 0) {
|
|
cmd_addall(volume, argc - 2, argv + 2);
|
|
} else if(strcmp(argv[2], "grow") == 0) {
|
|
cmd_grow(volume, argc - 2, argv + 2);
|
|
} else if(strcmp(argv[2], "getattr") == 0) {
|
|
cmd_getattr(volume, argc - 2, argv + 2);
|
|
} else if(strcmp(argv[2], "debug") == 0) {
|
|
if(argc > 3 && strcmp(argv[3], "verbose") == 0) {
|
|
debugBTree(volume->catalogTree, TRUE);
|
|
} else {
|
|
debugBTree(volume->catalogTree, FALSE);
|
|
}
|
|
}
|
|
}
|
|
|
|
closeVolume(volume);
|
|
CLOSE(io);
|
|
|
|
return 0;
|
|
}
|