diff options
Diffstat (limited to 'examples/c4cat.c')
| -rw-r--r-- | examples/c4cat.c | 128 |
1 files changed, 128 insertions, 0 deletions
diff --git a/examples/c4cat.c b/examples/c4cat.c new file mode 100644 index 0000000..04f51b6 --- /dev/null +++ b/examples/c4cat.c @@ -0,0 +1,128 @@ +#include <stdlib.h> +#include <stdio.h> +#include <errno.h> +#include <string.h> +#include <sys/stat.h> +#include <sys/mman.h> +#include <fcntl.h> +#include <unistd.h> + +#include "cc4group.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* mappedFile = mmap(NULL, size, PROT_READ, MAP_PRIVATE, file, 0); + + 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(munmap(mappedFile, size) == -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 <entry path>...\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; +} |
