Fixed restoration of the panel divider position.
[psensor.git] / src / lib / pio.c
index 54d9efb..1942348 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2010-2011 jeanfi@gmail.com
+ * Copyright (C) 2010-2017 jeanfi@gmail.com
  *
  * This program is free software; you can redistribute it and/or
  * modify it under the terms of the GNU General Public License as
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
  * 02110-1301 USA
  */
-#include <stdlib.h>
+#define _LARGEFILE_SOURCE 1
+#include "config.h"
+
+#include <dirent.h>
 #include <stdio.h>
-#include <sys/stat.h>
+#include <stdlib.h>
 #include <string.h>
-#include <dirent.h>
+#include <sys/stat.h>
+
+#include <plog.h>
+#include <pio.h>
+
+/* Directory separator is \ when cross-compiling for MS Windows
+ * systems
+ */
+#if defined(__MINGW32__)
+#define DIRSEP ('\\')
+#else
+#define DIRSEP '/'
+#endif
+
+#define FCOPY_BUF_SZ 4096
+
+int is_dir(const char *path)
+{
+       struct stat st;
+
+       int ret = lstat(path, &st);
+
+       if (ret == 0 && S_ISDIR(st.st_mode))
+               return 1;
+
+       return 0;
+}
+
+int is_file(const char *path)
+{
+       struct stat st;
+
+       int ret = lstat(path, &st);
+
+       if (ret == 0 && S_ISREG(st.st_mode))
+               return 1;
+
+       return 0;
+}
+
+static char *dir_normalize(const char *dpath)
+{
+       char *npath;
+       int n;
+
+       if (!dpath || !strlen(dpath))
+               return NULL;
+
+       npath = strdup(dpath);
 
-#include "pio.h"
+       n = strlen(npath);
 
-char **dir_list(const char *dpath, int (*filter) (const char *path))
+       if (n > 1 && npath[n - 1] == '/')
+               npath[n - 1] = '\0';
+
+       return npath;
+}
+
+static char **paths_add(char **paths, int n, char *path)
+{
+       char **result;
+
+       result = malloc((n+1) * sizeof(void *));
+
+       memcpy(result + 1, paths, n * sizeof(void *));
+
+       *result = path;
+
+       return result;
+}
+
+char **dir_list(const char *dpath, int (*filter) (const char *))
 {
        struct dirent *ent;
        DIR *dir;
-       char **paths;
+       char **paths, *path, *name, **tmp;
        int n;
 
        dir = opendir(dpath);
@@ -41,30 +111,21 @@ char **dir_list(const char *dpath, int (*filter) (const char *path))
        *paths = NULL;
 
        while ((ent = readdir(dir)) != NULL) {
-               char *fpath;
-               char *name = ent->d_name;
+               name = ent->d_name;
 
                if (!strcmp(name, ".") || !strcmp(name, ".."))
                        continue;
 
-               fpath = malloc(strlen(dpath) + 1 + strlen(name) + 1);
-
-               strcpy(fpath, dpath);
-               strcat(fpath, "/");
-               strcat(fpath, name);
-
-               if (!filter || filter(fpath)) {
-                       char **npaths;
+               path = path_append(dpath, name);
 
-                       n++;
-                       npaths = malloc(n * sizeof(void *));
-                       memcpy(npaths + 1, paths, (n - 1) * sizeof(void *));
+               if (!filter || filter(path)) {
+                       tmp = paths_add(paths, n, path);
                        free(paths);
-                       paths = npaths;
-                       *npaths = fpath;
+                       paths = tmp;
 
+                       n++;
                } else {
-                       free(fpath);
+                       free(path);
                }
        }
 
@@ -87,3 +148,206 @@ void paths_free(char **paths)
        free(paths);
 }
 
+char *file_get_content(const char *fpath)
+{
+       long size, n;
+       char *page;
+
+       log_fct_enter();
+
+       size = file_get_size(fpath);
+
+       if (size == -1) {
+               page = NULL;
+
+       } else if (size == 0) {
+               page = malloc(1);
+               *page = '\0';
+
+       } else {
+               FILE *fp = fopen(fpath, "rb");
+
+               if (fp) {
+                       page = malloc(size + 1);
+
+                       if (page) {
+                               clearerr(fp);
+                               n = fread(page, 1, size, fp);
+                               if (n != size && ferror(fp)) {
+                                       free(page);
+                                       page = NULL;
+                               } else {
+                                       *(page + n) = '\0';
+                               }
+                       }
+
+                       fclose(fp);
+               } else {
+                       log_debug("failed to open %s", fpath);
+                       page = NULL;
+               }
+       }
+
+       log_fct_exit();
+
+       return page;
+}
+
+long file_get_size(const char *path)
+{
+       FILE *fp;
+       long size;
+
+       if (!is_file(path))
+               return -1;
+
+       fp = fopen(path, "rb");
+       if (fp) {
+               if (fseek(fp, 0, SEEK_END) == -1)
+                       size = -1;
+               else
+                       size = ftell(fp);
+
+               fclose(fp);
+       } else {
+               size = -1;
+       }
+
+       return size;
+}
+
+#define FCOPY_BUF_SZ 4096
+static int FILE_copy(FILE *src, FILE *dst)
+{
+       int ret = 0;
+       char *buf = malloc(FCOPY_BUF_SZ);
+       int n;
+
+       if (!buf)
+               return FILE_COPY_ERROR_ALLOC_BUFFER;
+
+       while (!ret) {
+               n = fread(buf, 1, FCOPY_BUF_SZ, src);
+               if (n) {
+                       if (fwrite(buf, 1, n, dst) != n)
+                               ret = FILE_COPY_ERROR_WRITE;
+               } else {
+                       if (!feof(src))
+                               ret = FILE_COPY_ERROR_READ;
+                       else
+                               break;
+               }
+       }
+
+       free(buf);
+
+       return ret;
+}
+
+int
+file_copy(const char *src, const char *dst)
+{
+       FILE *fsrc, *fdst;
+       int ret = 0;
+
+       log_fct("copy %s to %s", src, dst);
+
+       fsrc = fopen(src, "r");
+
+       if (fsrc) {
+               fdst = fopen(dst, "w+");
+
+               if (fdst) {
+                       ret = FILE_copy(fsrc, fdst);
+                       fclose(fdst);
+               } else {
+                       ret = FILE_COPY_ERROR_OPEN_DST;
+               }
+
+               fclose(fsrc);
+       } else {
+               ret = FILE_COPY_ERROR_OPEN_SRC;
+       }
+
+       return ret;
+}
+
+char *path_append(const char *dir, const char *path)
+{
+       char *ret, *ndir;
+
+       ndir = dir_normalize(dir);
+
+       if (!ndir && (!path || !strlen(path)))
+               ret = NULL;
+
+       else if (!ndir) {
+               ret = strdup(path);
+
+       } else if (!path || !strlen(path)) {
+               return ndir;
+
+       } else {
+               ret = malloc(strlen(ndir) + 1 + strlen(path) + 1);
+               strcpy(ret, ndir);
+               strcat(ret, "/");
+               strcat(ret, path);
+       }
+
+       free(ndir);
+
+       return ret;
+}
+
+void mkdirs(const char *dirs, mode_t mode)
+{
+       char *c, *dir;
+       int i;
+
+       log_fct("mkdirs %s", dirs);
+
+       c = (char *)dirs;
+       dir = malloc(strlen(dirs) + 1);
+
+       i = 0;
+       while (*c) {
+               if ((*c == DIRSEP || *c == '\0') && c != dirs) {
+                       strncpy(dir, dirs, i);
+                       dir[i] = '\0';
+                       mkdir(dir, mode);
+               }
+
+               c++;
+               i++;
+       }
+
+       mkdir(dirs, mode);
+
+       free(dir);
+}
+
+void
+file_copy_print_error(int code, const char *src, const char *dst)
+{
+       switch (code) {
+       case 0:
+               break;
+       case FILE_COPY_ERROR_OPEN_SRC:
+               printf("File copy error: failed to open %s.\n", src);
+               break;
+       case FILE_COPY_ERROR_OPEN_DST:
+               printf("File copy error: failed to open %s.\n", dst);
+               break;
+       case FILE_COPY_ERROR_READ:
+               printf("File copy error: failed to read %s.\n", src);
+               break;
+       case FILE_COPY_ERROR_WRITE:
+               printf("File copy error: failed to write %s.\n", src);
+               break;
+       case FILE_COPY_ERROR_ALLOC_BUFFER:
+               printf("File copy error: failed to allocate buffer.\n");
+               break;
+       default:
+               printf("File copy error: unknown error %d.\n", code);
+       }
+}