aboutsummaryrefslogtreecommitdiff
path: root/src/platform/posix
diff options
context:
space:
mode:
Diffstat (limited to 'src/platform/posix')
-rw-r--r--src/platform/posix/posix_file.c207
1 files changed, 207 insertions, 0 deletions
diff --git a/src/platform/posix/posix_file.c b/src/platform/posix/posix_file.c
new file mode 100644
index 00000000..d7033095
--- /dev/null
+++ b/src/platform/posix/posix_file.c
@@ -0,0 +1,207 @@
+//
+// Copyright 2017 Garrett D'Amore <garrett@damore.org>
+// Copyright 2017 Capitar IT Group BV <info@capitar.com>
+//
+// This software is supplied under the terms of the MIT License, a
+// copy of which should be located in the distribution where this
+// file was obtained (LICENSE.txt). A copy of the license may also be
+// found online at https://opensource.org/licenses/MIT.
+//
+
+#include "core/nng_impl.h"
+
+#ifdef NNG_PLATFORM_POSIX
+
+#include <dirent.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <unistd.h>
+
+// File support.
+
+// nni_plat_file_put writes the named file, with the provided data,
+// and the given size. If the file already exists it is overwritten.
+// The permissions on the file should be limited to read and write
+// access by the entity running the application only.
+int
+nni_plat_file_put(const char *name, const void *data, size_t len)
+{
+ FILE *f;
+ int rv = 0;
+
+ if ((f = fopen(name, "wb")) == NULL) {
+ return (nni_plat_errno(errno));
+ }
+ if (fwrite(data, 1, len, f) != len) {
+ rv = nni_plat_errno(errno);
+ (void) unlink(name);
+ }
+ (void) fclose(f);
+ return (rv);
+}
+
+// nni_plat_file_get reads the entire named file, allocating storage
+// to receive the data and returning the data and the size in the
+// reference arguments.
+int
+nni_plat_file_get(const char *name, void **datap, size_t *lenp)
+{
+ FILE * f;
+ struct stat st;
+ int rv = 0;
+ int len;
+ void * data;
+
+ if ((f = fopen(name, "rb")) == NULL) {
+ return (nni_plat_errno(errno));
+ }
+
+ if (stat(name, &st) != 0) {
+ rv = nni_plat_errno(errno);
+ (void) fclose(f);
+ return (rv);
+ }
+
+ len = st.st_size;
+ if ((data = nni_alloc(len)) == NULL) {
+ rv = NNG_ENOMEM;
+ goto done;
+ }
+ if (fread(data, 1, len, f) != len) {
+ rv = nni_plat_errno(errno);
+ nni_free(data, len);
+ goto done;
+ }
+ *datap = data;
+ *lenp = len;
+done:
+ (void) fclose(f);
+ return (rv);
+}
+
+// nni_plat_file_delete deletes the named file.
+int
+nni_plat_file_delete(const char *name)
+{
+ if (unlink(name) < 0) {
+ return (nni_plat_errno(errno));
+ }
+ return (0);
+}
+
+// nni_plat_dir_open attempts to "open a directory" for listing. The
+// handle for further operations is returned in the first argument, and
+// the directory name is supplied in the second.
+int
+nni_plat_dir_open(void **dirp, const char *name)
+{
+ DIR *dir;
+
+ if ((dir = opendir(name)) == NULL) {
+ return (nni_plat_errno(errno));
+ }
+ *dirp = dir;
+ return (0);
+}
+
+int
+nni_plat_dir_create(const char *name)
+{
+ if (mkdir(name, S_IRWXU) != 0) {
+ if (errno == EEXIST) {
+ return (0);
+ }
+ return (nni_plat_errno(errno));
+ }
+ return (0);
+}
+
+int
+nni_plat_dir_remove(const char *name)
+{
+ if (rmdir(name) != 0) {
+ if (errno == ENOENT) {
+ return (0);
+ }
+ return (nni_plat_errno(errno));
+ }
+ return (0);
+}
+
+// nni_plat_dir_next gets the next directory entry. Each call returns
+// a new entry (arbitrary order). When no more entries exist, it returns
+// NNG_ENOENT.
+int
+nni_plat_dir_next(void *dir, const char **namep)
+{
+ for (;;) {
+ struct dirent *ent;
+
+ if ((ent = readdir((DIR *) dir)) == NULL) {
+ return (NNG_ENOENT);
+ }
+ // Skip "." and ".." -- we would like to skip all
+ // directories, but that would require checking full
+ // paths.
+ if ((strcmp(ent->d_name, ".") == 0) ||
+ (strcmp(ent->d_name, "..") == 0)) {
+ continue;
+ }
+ *namep = ent->d_name;
+ return (0);
+ }
+}
+
+// nni_plat_dir_close closes the directory handle, freeing all
+// resources associated with it.
+void
+nni_plat_dir_close(void *dir)
+{
+ (void) closedir((DIR *) dir);
+}
+
+char *
+nni_plat_temp_dir(void)
+{
+ char *temp;
+
+ // POSIX says $TMPDIR is required.
+ if ((temp = getenv("TMPDIR")) != NULL) {
+ return (nni_strdup(temp));
+ }
+ return (nni_strdup("/tmp"));
+}
+
+char *
+nni_plat_home_dir(void)
+{
+ char *home;
+
+ // POSIX says that $HOME is *REQUIRED*. We could look in getpwuid,
+ // but realistically this is simply not required.
+ if ((home = getenv("HOME")) != NULL) {
+ return (nni_strdup(home));
+ }
+ return (NULL);
+}
+
+char *
+nni_plat_join_dir(const char *prefix, const char *suffix)
+{
+ char * newdir;
+ size_t len;
+
+ len = strlen(prefix) + strlen(suffix) + 2;
+ newdir = nni_alloc(strlen(prefix) + strlen(suffix) + 2);
+ if (newdir != NULL) {
+ (void) snprintf(newdir, len, "%s/%s", prefix, suffix);
+ }
+ return (newdir);
+}
+
+#endif // NNG_PLATFORM_POSIX