summaryrefslogtreecommitdiffstats
path: root/examples/c4cat_dyn.c
diff options
context:
space:
mode:
authorMarkus Mittendrein <git@maxmitti.tk>2018-08-15 22:46:40 +0200
committerMarkus Mittendrein <git@maxmitti.tk>2018-08-15 23:15:15 +0200
commit0d1ae015fef8e15442dafa61b9c8d929ce467969 (patch)
treea8d56fd12f5c5366e1f6fa3ecc20c78c0202f747 /examples/c4cat_dyn.c
parente04f662a42c75cb202684e7254d3b7600e6e1756 (diff)
downloadcc4group-0d1ae015fef8e15442dafa61b9c8d929ce467969.tar.gz
cc4group-0d1ae015fef8e15442dafa61b9c8d929ce467969.zip
Refactor code into a library and implement basic file management methods
Diffstat (limited to 'examples/c4cat_dyn.c')
-rw-r--r--examples/c4cat_dyn.c145
1 files changed, 145 insertions, 0 deletions
diff --git a/examples/c4cat_dyn.c b/examples/c4cat_dyn.c
new file mode 100644
index 0000000..92da979
--- /dev/null
+++ b/examples/c4cat_dyn.c
@@ -0,0 +1,145 @@
+#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 <dlfcn.h>
+#include <assert.h>
+
+#define CC4GROUP_DYNAMIC_LOAD
+#include "cc4group.h"
+#undef CC4GROUP_DYNAMIC_LOAD
+
+CC4Group_API* cc4group_dyn;
+#define cc4group (*cc4group_dyn)
+
+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[])
+{
+ void* dl = dlopen("./libcc4group_dyn.so", RTLD_LAZY);
+ assert(dl);
+
+ dlerror();
+ cc4group_dyn = dlsym(dl, "cc4group");
+ assert(!dlerror());
+
+ 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]);
+ }
+
+ dlclose(dl);
+
+ return success ? EXIT_SUCCESS : EXIT_FAILURE;
+}