fork of PCE focusing on macplus, supporting DaynaPort SCSI network emulation
1/*****************************************************************************
2 * pce *
3 *****************************************************************************/
4
5/*****************************************************************************
6 * File name: src/lib/path.c *
7 * Created: 2008-11-06 by Hampa Hug <hampa@hampa.ch> *
8 * Copyright: (C) 2008-2009 Hampa Hug <hampa@hampa.ch> *
9 *****************************************************************************/
10
11/*****************************************************************************
12 * This program is free software. You can redistribute it and / or modify it *
13 * under the terms of the GNU General Public License version 2 as published *
14 * by the Free Software Foundation. *
15 * *
16 * This program is distributed in the hope that it will be useful, but *
17 * WITHOUT ANY WARRANTY, without even the implied warranty of *
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General *
19 * Public License for more details. *
20 *****************************************************************************/
21
22
23#include <config.h>
24
25#include <stdlib.h>
26#include <stdio.h>
27#include <string.h>
28
29#include <libini/libini.h>
30
31#include <lib/path.h>
32
33
34static unsigned par_path_cnt = 0;
35static char **par_path_dir = NULL;
36
37
38static
39char *pce_path_strdup (const char *str)
40{
41 unsigned n;
42 char *ret;
43
44 n = strlen (str);
45
46 ret = malloc (n + 1);
47 if (ret == NULL) {
48 return (NULL);
49 }
50
51 memcpy (ret, str, n);
52 ret[n] = 0;
53
54 return (ret);
55}
56
57static
58char *pce_path_cat (const char *str1, const char *str2)
59{
60 unsigned n1, n2;
61 char *ret;
62
63 if (str1 == NULL) {
64 return (pce_path_strdup (str2));
65 }
66
67 n1 = strlen (str1);
68 n2 = strlen (str2);
69
70 ret = malloc (n1 + n2 + 2);
71 if (ret == NULL) {
72 return (NULL);
73 }
74
75 memcpy (ret, str1, n1);
76 ret[n1] = PCE_DIR_SEP;
77 memcpy (ret + n1 + 1, str2, n2);
78
79 ret[n1 + n2 + 1] = 0;
80
81 return (ret);
82}
83
84static
85int pce_path_is_absolute (const char *str)
86{
87 if (*str == PCE_DIR_SEP) {
88 return (1);
89 }
90
91 return (0);
92}
93
94void pce_path_clear (void)
95{
96 unsigned i;
97
98 for (i = 0; i < par_path_cnt; i++) {
99 free (par_path_dir[i]);
100 }
101
102 free (par_path_dir);
103
104 par_path_cnt = 0;
105 par_path_dir = NULL;
106}
107
108int pce_path_add (const char *dir, int atend)
109{
110 unsigned i, n;
111 char **tmp;
112 char *str;
113
114 n = strlen (dir);
115
116 while ((n > 0) && (dir[n - 1] == PCE_DIR_SEP)) {
117 n -= 1;
118 }
119
120 if ((n == 0) || ((n == 1) && (dir[0] == '.'))) {
121 str = NULL;
122 }
123 else {
124 str = malloc (n + 1);
125 if (str == NULL) {
126 return (1);
127 }
128
129 memcpy (str, dir, n);
130 str[n] = 0;
131 }
132
133 tmp = realloc (par_path_dir, (par_path_cnt + 1) * sizeof (char *));
134 if (tmp == NULL) {
135 free (str);
136 return (1);
137 }
138
139 if (atend) {
140 tmp[par_path_cnt] = str;
141 }
142 else {
143 for (i = par_path_cnt; i > 0; i--) {
144 tmp[i] = tmp[i - 1];
145 }
146
147 tmp[0] = str;
148 }
149
150 par_path_cnt += 1;
151 par_path_dir = tmp;
152
153 return (0);
154}
155
156int pce_path_set (const char *dir)
157{
158 int atend;
159
160 atend = 1;
161
162 if (*dir == '+') {
163 dir += 1;
164 }
165 else if (*dir == '-') {
166 dir += 1;
167 atend = 0;
168 }
169 else if (*dir == '=') {
170 dir += 1;
171 pce_path_clear();
172 }
173
174 return (pce_path_add (dir, atend));
175}
176
177char *pce_path_get (const char *fname)
178{
179 unsigned i;
180 char *str, *tmp;
181 FILE *fp;
182
183 if (fname == NULL) {
184 return (NULL);
185 }
186
187 str = pce_path_strdup (fname);
188 if (str == NULL) {
189 return (NULL);
190 }
191
192 if (pce_path_is_absolute (str)) {
193 return (str);
194 }
195
196 for (i = 0; i < par_path_cnt; i++) {
197 tmp = pce_path_cat (par_path_dir[i], str);
198 if (tmp == NULL) {
199 free (str);
200 return (NULL);
201 }
202
203 fp = fopen (tmp, "r");
204
205 if (fp != NULL) {
206 fclose (fp);
207 free (str);
208 return (tmp);
209 }
210
211 free (tmp);
212 }
213
214 return (str);
215}
216
217FILE *pce_fopen_inp (const char *fname, const char *mode, char **path)
218{
219 unsigned i;
220 char *str;
221 FILE *fp;
222
223 if (pce_path_is_absolute (fname)) {
224 if (path != NULL) {
225 *path = pce_path_strdup (fname);
226 }
227
228 return (fopen (fname, mode));
229 }
230
231 for (i = 0; i < par_path_cnt; i++) {
232 str = pce_path_cat (par_path_dir[i], fname);
233 if (str == NULL) {
234 return (NULL);
235 }
236
237 fp = fopen (str, mode);
238
239 if (fp != NULL) {
240 if (path != NULL) {
241 *path = str;
242 }
243 else {
244 free (str);
245 }
246
247 return (fp);
248 }
249
250 free (str);
251 }
252
253 if (path != NULL) {
254 *path = pce_path_strdup (fname);
255 }
256
257 return (fopen (fname, mode));
258}
259
260FILE *pce_fopen_out (const char *fname, const char *mode)
261{
262 return (fopen (fname, mode));
263}
264
265int pce_path_ini (ini_sct_t *sct)
266{
267 const char *str;
268 ini_val_t *val;
269
270 val = NULL;
271 while (1) {
272 val = ini_next_val (sct, val, "path");
273
274 if (val == NULL) {
275 break;
276 }
277
278 str = ini_val_get_str (val);
279 if (str == NULL) {
280 return (1);
281 }
282
283 if (pce_path_set (str)) {
284 return (1);
285 }
286 }
287
288 return (0);
289}