switched from wpitchoune@gmail.com to jeanfi@gmail.com (my usual email)
[psensor.git] / src / plib / plib_io.c
1 /*
2     Copyright (C) 2010-2011 jeanfi@gmail.com
3
4     This program is free software; you can redistribute it and/or modify
5     it under the terms of the GNU General Public License as published by
6     the Free Software Foundation; either version 2 of the License, or
7     (at your option) any later version.
8
9     This program is distributed in the hope that it will be useful,
10     but WITHOUT ANY WARRANTY; without even the implied warranty of
11     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12     GNU 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
20 #include <stdlib.h>
21 #include <stdio.h>
22 #include <sys/stat.h>
23 #include <string.h>
24 #include <dirent.h>
25
26 #include "plib_io.h"
27
28 int is_dir(const char *path)
29 {
30         struct stat st;
31
32         int ret = lstat(path, &st);
33
34         if (ret == 0 && S_ISDIR(st.st_mode))
35                 return 1;
36
37         return 0;
38 }
39
40 int is_file(const char *path)
41 {
42         struct stat st;
43
44         int ret = lstat(path, &st);
45
46         if (ret == 0 && S_ISREG(st.st_mode))
47                 return 1;
48
49         return 0;
50 }
51
52 char *dir_normalize(const char *dpath)
53 {
54         char *npath;
55         int n;
56
57         if (!dpath || !strlen(dpath))
58                 return NULL;
59
60         npath = strdup(dpath);
61
62         n = strlen(npath);
63
64         if (n > 1 && npath[n - 1] == '/')
65                 npath[n - 1] = '\0';
66
67         return npath;
68 }
69
70 char **dir_list(const char *dpath, int (*filter) (const char *path))
71 {
72         struct dirent *ent;
73         DIR *dir;
74         char **paths;
75         int n;
76
77         dir = opendir(dpath);
78
79         if (!dir)
80                 return NULL;
81
82         n = 1;
83         paths = malloc(sizeof(void *));
84         *paths = NULL;
85
86         while ((ent = readdir(dir)) != NULL) {
87                 char *fpath;
88                 char *name = ent->d_name;
89
90                 if (!strcmp(name, ".") || !strcmp(name, ".."))
91                         continue;
92
93                 fpath = malloc(strlen(dpath) + 1 + strlen(name) + 1);
94
95                 strcpy(fpath, dpath);
96                 strcat(fpath, "/");
97                 strcat(fpath, name);
98
99                 if (!filter || filter(fpath)) {
100                         char **npaths;
101
102                         n++;
103                         npaths = malloc(n * sizeof(void *));
104                         memcpy(npaths + 1, paths, (n - 1) * sizeof(void *));
105                         free(paths);
106                         paths = npaths;
107                         *npaths = fpath;
108
109                 } else {
110                         free(fpath);
111                 }
112         }
113
114         closedir(dir);
115
116         return paths;
117 }
118
119 void paths_free(char **paths)
120 {
121         char **paths_cur;
122
123         paths_cur = paths;
124         while (*paths_cur) {
125                 free(*paths_cur);
126
127                 paths_cur++;
128         }
129
130         free(paths);
131 }
132
133 char *file_get_content(const char *fpath)
134 {
135         long size;
136
137         char *page;
138
139         size = file_get_size(fpath);
140
141         if (size == -1) {
142                 page = NULL;
143
144         } else if (size == 0) {
145                 page = malloc(1);
146                 *page = '\0';
147
148         } else {
149                 FILE *fp = fopen(fpath, "rb");
150                 if (fp) {
151                         page = malloc(size + 1);
152                         if (!page || size != fread(page, 1, size, fp)) {
153                                 free(page);
154                                 return NULL;
155                         }
156
157                         *(page + size) = '\0';
158
159                         fclose(fp);
160                 } else {
161                         page = NULL;
162                 }
163         }
164
165         return page;
166 }
167
168 long file_get_size(const char *path)
169 {
170         FILE *fp;
171
172         if (!is_file(path))
173                 return -1;
174
175         fp = fopen(path, "rb");
176         if (fp) {
177                 long size;
178
179                 if (fseek(fp, 0, SEEK_END) == -1)
180                         return -1;
181
182                 size = ftell(fp);
183
184                 fclose(fp);
185
186                 return size;
187         }
188
189         return -1;
190 }
191
192 #define FCOPY_BUF_SZ 4096
193 static int FILE_copy(FILE *src, FILE *dst)
194 {
195         int ret = 0;
196         char *buf = malloc(FCOPY_BUF_SZ);
197         int n;
198
199         if (!buf)
200                 return FILE_COPY_ERROR_ALLOC_BUFFER;
201
202         while (!ret) {
203                 n = fread(buf, 1, FCOPY_BUF_SZ, src);
204                 if (n) {
205                         if (fwrite(buf, 1, n, dst) != n)
206                                 ret = FILE_COPY_ERROR_WRITE;
207                 } else {
208                         if (!feof(src))
209                                 ret = FILE_COPY_ERROR_READ;
210                         else
211                                 break;
212                 }
213         }
214
215         free(buf);
216
217         return ret;
218 }
219
220 int
221 file_copy(const char *src, const char *dst)
222 {
223         FILE *fsrc, *fdst;
224         int ret = 0;
225
226         fsrc = fopen(src, "r");
227
228         if (fsrc) {
229                 fdst = fopen(dst, "w+");
230
231                 if (fdst) {
232                         ret = FILE_copy(fsrc, fdst);
233                         fclose(fdst);
234                 } else {
235                         ret = FILE_COPY_ERROR_OPEN_DST;
236                 }
237
238                 fclose(fsrc);
239         } else {
240                 ret = FILE_COPY_ERROR_OPEN_SRC;
241         }
242
243         return ret;
244 }
245
246 char *path_append(const char *dir, const char *path)
247 {
248         char *ret, *ndir;
249
250         ndir = dir_normalize(dir);
251
252         if (!ndir && (!path || !strlen(path)))
253                 ret = NULL;
254
255         else if (!ndir) {
256                 ret = strdup(path);
257
258         } else if (!path || !strlen(path)) {
259                 return ndir;
260
261         } else {
262                 ret = malloc(strlen(ndir) + 1 + strlen(path) + 1);
263                 strcpy(ret, ndir);
264                 strcat(ret, "/");
265                 strcat(ret, path);
266         }
267
268         free(ndir);
269
270         return ret;
271 }
272
273 void
274 file_copy_print_error(int code, const char *src, const char *dst)
275 {
276         switch (code) {
277         case 0:
278                 break;
279         case FILE_COPY_ERROR_OPEN_SRC:
280                 printf("File copy error: failed to open %s.\n", src);
281                 break;
282         case FILE_COPY_ERROR_OPEN_DST:
283                 printf("File copy error: failed to open %s.\n", dst);
284                 break;
285         case FILE_COPY_ERROR_READ:
286                 printf("File copy error: failed to read %s.\n", src);
287                 break;
288         case FILE_COPY_ERROR_WRITE:
289                 printf("File copy error: failed to write %s.\n", src);
290                 break;
291         case FILE_COPY_ERROR_ALLOC_BUFFER:
292                 printf("File copy error: failed to allocate buffer.\n");
293                 break;
294         default:
295                 printf("File copy error: unknown error %d.\n", code);
296         }
297 }