Imported Upstream version 1.2.0
[psensor-pkg-debian.git] / src / lib / pio.c
1 /*
2  * Copyright (C) 2010-2016 jeanfi@gmail.com
3  *
4  * This program is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU General Public License as
6  * published by the Free Software Foundation; either version 2 of the
7  * License, or (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful, but
10  * WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  * General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software
16  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
17  * 02110-1301 USA
18  */
19 #define _LARGEFILE_SOURCE 1
20 #include "config.h"
21
22 #include <dirent.h>
23 #include <stdio.h>
24 #include <stdlib.h>
25 #include <string.h>
26 #include <sys/stat.h>
27 #include <sys/types.h>
28
29 #include <plog.h>
30 #include <pio.h>
31
32 /* Directory separator is \ when cross-compiling for MS Windows
33  * systems
34  */
35 #if defined(__MINGW32__)
36 #define DIRSEP ('\\')
37 #else
38 #define DIRSEP '/'
39 #endif
40
41 #define FCOPY_BUF_SZ 4096
42
43 int is_dir(const char *path)
44 {
45         struct stat st;
46
47         int ret = lstat(path, &st);
48
49         if (ret == 0 && S_ISDIR(st.st_mode))
50                 return 1;
51
52         return 0;
53 }
54
55 int is_file(const char *path)
56 {
57         struct stat st;
58
59         int ret = lstat(path, &st);
60
61         if (ret == 0 && S_ISREG(st.st_mode))
62                 return 1;
63
64         return 0;
65 }
66
67 static char *dir_normalize(const char *dpath)
68 {
69         char *npath;
70         int n;
71
72         if (!dpath || !strlen(dpath))
73                 return NULL;
74
75         npath = strdup(dpath);
76
77         n = strlen(npath);
78
79         if (n > 1 && npath[n - 1] == '/')
80                 npath[n - 1] = '\0';
81
82         return npath;
83 }
84
85 static char **paths_add(char **paths, int n, char *path)
86 {
87         char **result;
88
89         result = malloc((n+1) * sizeof(void *));
90
91         memcpy(result + 1, paths, n * sizeof(void *));
92
93         *result = path;
94
95         return result;
96 }
97
98 char **dir_list(const char *dpath, int (*filter) (const char *))
99 {
100         struct dirent *ent;
101         DIR *dir;
102         char **paths, *path, *name, **tmp;
103         int n;
104
105         dir = opendir(dpath);
106
107         if (!dir)
108                 return NULL;
109
110         n = 1;
111         paths = malloc(sizeof(void *));
112         *paths = NULL;
113
114         while ((ent = readdir(dir)) != NULL) {
115                 name = ent->d_name;
116
117                 if (!strcmp(name, ".") || !strcmp(name, ".."))
118                         continue;
119
120                 path = path_append(dpath, name);
121
122                 if (!filter || filter(path)) {
123                         tmp = paths_add(paths, n, path);
124                         free(paths);
125                         paths = tmp;
126
127                         n++;
128                 } else {
129                         free(path);
130                 }
131         }
132
133         closedir(dir);
134
135         return paths;
136 }
137
138 void paths_free(char **paths)
139 {
140         char **paths_cur;
141
142         paths_cur = paths;
143         while (*paths_cur) {
144                 free(*paths_cur);
145
146                 paths_cur++;
147         }
148
149         free(paths);
150 }
151
152 char *file_get_content(const char *fpath)
153 {
154         long size;
155
156         char *page;
157
158         size = file_get_size(fpath);
159         if (size == -1) {
160                 page = NULL;
161
162         } else if (size == 0) {
163                 page = malloc(1);
164                 *page = '\0';
165
166         } else {
167                 FILE *fp = fopen(fpath, "rb");
168
169                 if (fp) {
170                         page = malloc(size + 1);
171                         if (!page || size != fread(page, 1, size, fp)) {
172                                 free(page);
173                                 page = NULL;
174                         } else {
175                                 *(page + size) = '\0';
176                         }
177
178                         fclose(fp);
179                 } else {
180                         page = NULL;
181                 }
182         }
183
184         return page;
185 }
186
187 long file_get_size(const char *path)
188 {
189         FILE *fp;
190         long size;
191
192         if (!is_file(path))
193                 return -1;
194
195         fp = fopen(path, "rb");
196         if (fp) {
197                 if (fseek(fp, 0, SEEK_END) == -1)
198                         size = -1;
199                 else
200                         size = ftell(fp);
201
202                 fclose(fp);
203         } else {
204                 size = -1;
205         }
206
207         return size;
208 }
209
210 #define FCOPY_BUF_SZ 4096
211 static int FILE_copy(FILE *src, FILE *dst)
212 {
213         int ret = 0;
214         char *buf = malloc(FCOPY_BUF_SZ);
215         int n;
216
217         if (!buf)
218                 return FILE_COPY_ERROR_ALLOC_BUFFER;
219
220         while (!ret) {
221                 n = fread(buf, 1, FCOPY_BUF_SZ, src);
222                 if (n) {
223                         if (fwrite(buf, 1, n, dst) != n)
224                                 ret = FILE_COPY_ERROR_WRITE;
225                 } else {
226                         if (!feof(src))
227                                 ret = FILE_COPY_ERROR_READ;
228                         else
229                                 break;
230                 }
231         }
232
233         free(buf);
234
235         return ret;
236 }
237
238 int
239 file_copy(const char *src, const char *dst)
240 {
241         FILE *fsrc, *fdst;
242         int ret = 0;
243
244         log_fct("copy %s to %s", src, dst);
245
246         fsrc = fopen(src, "r");
247
248         if (fsrc) {
249                 fdst = fopen(dst, "w+");
250
251                 if (fdst) {
252                         ret = FILE_copy(fsrc, fdst);
253                         fclose(fdst);
254                 } else {
255                         ret = FILE_COPY_ERROR_OPEN_DST;
256                 }
257
258                 fclose(fsrc);
259         } else {
260                 ret = FILE_COPY_ERROR_OPEN_SRC;
261         }
262
263         return ret;
264 }
265
266 char *path_append(const char *dir, const char *path)
267 {
268         char *ret, *ndir;
269
270         ndir = dir_normalize(dir);
271
272         if (!ndir && (!path || !strlen(path)))
273                 ret = NULL;
274
275         else if (!ndir) {
276                 ret = strdup(path);
277
278         } else if (!path || !strlen(path)) {
279                 return ndir;
280
281         } else {
282                 ret = malloc(strlen(ndir) + 1 + strlen(path) + 1);
283                 strcpy(ret, ndir);
284                 strcat(ret, "/");
285                 strcat(ret, path);
286         }
287
288         free(ndir);
289
290         return ret;
291 }
292
293 void mkdirs(const char *dirs, mode_t mode)
294 {
295         char *c, *dir;
296         int i;
297
298         log_fct("mkdirs %s", dirs);
299
300         c = (char *)dirs;
301         dir = malloc(strlen(dirs) + 1);
302
303         i = 0;
304         while (*c) {
305                 if ((*c == DIRSEP || *c == '\0') && c != dirs) {
306                         strncpy(dir, dirs, i);
307                         dir[i] = '\0';
308                         mkdir(dir, mode);
309                 }
310
311                 c++;
312                 i++;
313         }
314
315         mkdir(dirs, mode);
316
317         free(dir);
318 }
319
320 void
321 file_copy_print_error(int code, const char *src, const char *dst)
322 {
323         switch (code) {
324         case 0:
325                 break;
326         case FILE_COPY_ERROR_OPEN_SRC:
327                 printf("File copy error: failed to open %s.\n", src);
328                 break;
329         case FILE_COPY_ERROR_OPEN_DST:
330                 printf("File copy error: failed to open %s.\n", dst);
331                 break;
332         case FILE_COPY_ERROR_READ:
333                 printf("File copy error: failed to read %s.\n", src);
334                 break;
335         case FILE_COPY_ERROR_WRITE:
336                 printf("File copy error: failed to write %s.\n", src);
337                 break;
338         case FILE_COPY_ERROR_ALLOC_BUFFER:
339                 printf("File copy error: failed to allocate buffer.\n");
340                 break;
341         default:
342                 printf("File copy error: unknown error %d.\n", code);
343         }
344 }