#include #include #include #include #include #include #include #include "cc4group.h" #include "platform/platform.h" bool catNormalFile(const char* const path, const off_t size) { int file = open(path, O_RDONLY); if(file == -1) { fprintf(stderr, "ERROR: Reading \"%s\": %s\n", path, strerror(errno)); return false; } void* extra; void* mappedFile = cc4group_mmap(NULL, size, PROT_READ, MAP_PRIVATE, file, 0, &extra); if(close(file) == -1) { fprintf(stderr, "ERROR: Closing \"%s\": %s\n", path, strerror(errno)); } if(mappedFile == MAP_FAILED) { fprintf(stderr, "ERROR: Mapping \"%s\" for reading: %s\n", path, strerror(errno)); return false; } if(write(STDOUT_FILENO, mappedFile, size) != size) { fprintf(stderr, "ERROR: Writing file contents of \"%s\" to stdout: %s\n", path, strerror(errno)); } if(cc4group_munmap(mappedFile, size, extra) == -1) { fprintf(stderr, "ERROR: Unmapping \"%s\": %s\n", path, strerror(errno)); } return true; } bool catFileWithPathsAndSize(const char* const completePath, const char* const groupPath, off_t fileSize) { if(strcmp(groupPath, completePath) == 0) { return catNormalFile(completePath, fileSize); } const char* pathInGroup = completePath + strlen(groupPath) + 1; CC4Group* group = cc4group.new(); if(!cc4group.openExisting(group, groupPath)) { fprintf(stderr, "ERROR: Can not open group file \"%s\": %s\n", groupPath, cc4group.getErrorMessage(group)); return false; } const void* data; size_t size; bool success = cc4group.getEntryData(group, pathInGroup, &data, &size); if(success) { if(write(STDOUT_FILENO, data, size) != (ssize_t)size) { fprintf(stderr, "ERROR: Writing file contents of \"%s\" to stdout: %s\n", completePath, strerror(errno)); } } else { fprintf(stderr, "ERROR: Reading \"%s\" from \"%s\": %s\n", pathInGroup, groupPath, strerror(ENOENT)); } cc4group.delete(group); return success; } bool catFile(const char* const completePath) { struct stat st; char* groupPath = strdup(completePath); char* slash; for(slash = groupPath + strlen(groupPath); slash != NULL; slash = strrchr(groupPath, '/')) { *slash = '\0'; if(stat(groupPath, &st) == 0 && !S_ISDIR(st.st_mode)) { break; } } bool success; if(slash == NULL) { fprintf(stderr, "ERROR: Reading \"%s\": %s\n", completePath, strerror(ENOENT)); success = false; } else { success = catFileWithPathsAndSize(completePath, groupPath, st.st_size); } free(groupPath); return success; } int main(int argc, char* argv[]) { if(argc < 2) { fprintf(stderr, "USAGE: %s ...\n", argv[0]); return EXIT_FAILURE; } bool success = true; for(int i = 1; i < argc; ++i) { success &= catFile(argv[i]); } return success ? EXIT_SUCCESS : EXIT_FAILURE; }