perf
[ppastats.git] / src / io.c
1 /*
2  * Copyright (C) 2011-2014 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
20 #include <stdio.h>
21 #include <stdlib.h>
22 #include <string.h>
23 #include <sys/stat.h>
24
25 #include "io.h"
26
27 /* Directory separator is \ when cross-compiling for MS Windows
28    systems */
29 #if defined(__MINGW32__)
30 #define DIRSEP ('\\')
31 #else
32 #define DIRSEP '/'
33 #endif
34
35 #define FCOPY_BUF_SZ 4096
36
37 static int file_copy(FILE *src, FILE *dst)
38 {
39         int ret = 0;
40         char *buf = malloc(FCOPY_BUF_SZ);
41         int n;
42
43         if (!buf)
44                 return FILE_COPY_ERROR_ALLOC_BUFFER;
45
46         while (!ret) {
47                 n = fread(buf, 1, FCOPY_BUF_SZ, src);
48                 if (n) {
49                         if (fwrite(buf, 1, n, dst) != n)
50                                 ret = FILE_COPY_ERROR_WRITE;
51                 } else {
52                         if (!feof(src))
53                                 ret = FILE_COPY_ERROR_READ;
54                         else
55                                 break;
56                 }
57         }
58
59         free(buf);
60
61         return ret;
62 }
63
64 int fcopy(const char *src, const char *dst)
65 {
66         FILE *fsrc, *fdst;
67         int ret = 0;
68
69         fsrc = fopen(src, "r");
70
71         if (fsrc) {
72                 fdst = fopen(dst, "w+");
73
74                 if (fdst) {
75                         ret = file_copy(fsrc, fdst);
76                         fclose(fdst);
77                 } else {
78                         ret = FILE_COPY_ERROR_OPEN_DST;
79                 }
80
81                 fclose(fsrc);
82         } else {
83                 ret = FILE_COPY_ERROR_OPEN_SRC;
84         }
85
86         return ret;
87 }
88
89 char *path_append(const char *odir, const char *name)
90 {
91         char *dir;
92
93         dir = malloc(strlen(odir)+1+strlen(name)+1);
94
95         sprintf(dir, "%s/%s", odir, name);
96
97         return dir;
98 }
99
100 void mkdirs(const char *dirs, mode_t mode)
101 {
102         char *c = (char *)dirs;
103         char *dir = malloc(strlen(dirs) + 1);
104
105         int i = 0;
106         while (*c) {
107                 if ((*c == DIRSEP || *c == '\0') && c != dirs) {
108                         strncpy(dir, dirs, i);
109                         dir[i] = '\0';
110                         mkdir(dir, mode);
111                 }
112
113                 c++;
114                 i++;
115         }
116
117         mkdir(dirs, mode);
118
119         free(dir);
120 }
121
122 static int is_file(const char *path)
123 {
124         struct stat st;
125
126         int ret = lstat(path, &st);
127
128         if (ret == 0 && S_ISREG(st.st_mode))
129                 return 1;
130
131         return 0;
132 }
133
134 static long file_get_size(const char *path)
135 {
136         FILE *fp;
137
138         if (!is_file(path))
139                 return -1;
140
141         fp = fopen(path, "rb");
142         if (fp) {
143                 long size;
144
145                 if (fseek(fp, 0, SEEK_END) == -1)
146                         return -1;
147
148                 size = ftell(fp);
149
150                 fclose(fp);
151
152                 return size;
153         }
154
155         return -1;
156 }
157
158 char *file_get_content(const char *fpath)
159 {
160         long size;
161
162         char *page;
163
164         size = file_get_size(fpath);
165         if (size == -1) {
166                 page = NULL;
167
168         } else if (size == 0) {
169                 page = malloc(1);
170                 *page = '\0';
171
172         } else {
173                 FILE *fp = fopen(fpath, "rb");
174                 if (fp) {
175                         page = malloc(size + 1);
176                         if (!page || size != fread(page, 1, size, fp)) {
177                                 free(page);
178                                 return NULL;
179                         }
180
181                         *(page + size) = '\0';
182
183                         fclose(fp);
184                 } else {
185                         page = NULL;
186                 }
187         }
188
189         return page;
190 }
191