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