source: git/src/filename.c @ 0087185

RELEASE/1.0RELEASE/1.1RELEASE/1.2debug-cidebug-ci-sanitisersfaster-cavernloglog-selectstereostereo-2025walls-datawalls-data-hanging-as-warningwarn-only-for-hanging-survey
Last change on this file since 0087185 was 759fb47, checked in by Olly Betts <olly@…>, 24 years ago

Change '...' to `...' in messages; .svx file reading errors now fatal;
unattached survey error now fatal; syntax errors in survex wrapper now
fatal.

git-svn-id: file:///home/survex-svn/survex/trunk@616 4b37db11-9a0c-4f06-9ece-9ab7cdaee568

  • Property mode set to 100644
File size: 7.8 KB
Line 
1/* OS dependent filename manipulation routines
2 * Copyright (c) Olly Betts 1998-2001
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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
17 */
18
19#ifdef HAVE_CONFIG_H
20# include <config.h>
21#endif
22
23#include "filename.h"
24
25#include <ctype.h>
26#include <string.h>
27
28/* FIXME: finish sorting out safe_fopen vs fopenWithPthAndExt... */
29
30/* Wrapper for fopen which throws a fatal error if it fails.
31 * Some versions of fopen() are quite happy to open a directory.
32 * We aren't, so catch this case. */
33extern FILE *
34safe_fopen(const char *fnm, const char *mode)
35{
36   FILE *f;
37   if (fDirectory(fnm))
38      fatalerror(/*Filename `%s' refers to directory*/44, fnm);
39
40   f = fopen(fnm, mode);
41   if (!f) fatalerror(mode[0] == 'w' ?
42                      /*Failed to open output file `%s'*/47 :
43                      /*Couldn't open data file `%s'*/24, fnm);
44   return f;
45}
46
47extern FILE *
48safe_fopen_with_ext(const char *fnm, const char *ext, const char *mode)
49{
50   FILE *f;
51   char *p;
52   p = add_ext(fnm, ext);
53   f = safe_fopen(p, mode);
54   osfree(p);
55   return f;
56}
57
58static FILE *
59fopen_not_dir(const char *fnm, const char *mode)
60{
61   if (fDirectory(fnm)) return NULL;
62   return fopen(fnm, mode);
63}
64
65extern char * FAR
66path_from_fnm(const char *fnm)
67{
68   char *pth;
69   const char *lf;
70   int lenpth = 0;
71
72   lf = strrchr(fnm, FNM_SEP_LEV);
73#ifdef FNM_SEP_LEV2
74   {
75      const char *lf2 = strrchr(lf ? lf + 1 : fnm, FNM_SEP_LEV2);
76      if (lf2) lf = lf2;
77   }
78#endif
79#ifdef FNM_SEP_DRV
80   if (!lf) lf = strrchr(fnm, FNM_SEP_DRV);
81#endif
82   if (lf) lenpth = lf - fnm + 1;
83
84   pth = osmalloc(lenpth + 1);
85   memcpy(pth, fnm, lenpth);
86   pth[lenpth] = '\0';
87
88   return pth;
89}
90
91extern char *
92base_from_fnm(const char *fnm)
93{
94   char *p;
95
96   p = strrchr(fnm, FNM_SEP_EXT);
97   /* Trim off any leaf extension, but dirs can have extensions too */
98   if (p && !strchr(p, FNM_SEP_LEV)
99#ifdef FNM_SEP_LEV2
100       && !strchr(p, FNM_SEP_LEV2)
101#endif
102       ) {
103      size_t len = (const char *)p - fnm;
104
105      p = osmalloc(len + 1);
106      memcpy(p, fnm, len);
107      p[len] = '\0';
108      return p;
109   }
110
111   return osstrdup(fnm);
112}
113
114extern char *
115baseleaf_from_fnm(const char *fnm)
116{
117   const char *p;
118   char *q;
119   size_t len;
120
121   p = fnm;
122   q = strrchr(p, FNM_SEP_LEV);
123   if (q) p = q + 1;
124#ifdef FNM_SEP_LEV2
125   q = strrchr(p, FNM_SEP_LEV2);
126   if (q) p = q + 1;
127#endif
128
129   q = strrchr(p, FNM_SEP_EXT);
130   if (q) len = (const char *)q - p; else len = strlen(p);
131
132   q = osmalloc(len + 1);
133   memcpy(q, p, len);
134   q[len] = '\0';
135   return q;
136}
137
138extern char * FAR
139leaf_from_fnm(const char *fnm)
140{
141   const char *lf;
142   lf = strrchr(fnm, FNM_SEP_LEV);
143   if (lf) fnm = lf + 1;
144#ifdef FNM_SEP_LEV2
145   lf = strrchr(fnm, FNM_SEP_LEV2);
146   if (lf) fnm = lf + 1;
147#endif
148#ifdef FNM_SEP_DRV
149   lf = strrchr(fnm, FNM_SEP_DRV);
150   if (lf) fnm = lf + 1;
151#endif
152   return osstrdup(fnm);
153}
154
155/* Make fnm from pth and lf, inserting an FNM_SEP_LEV if appropriate */
156extern char * FAR
157use_path(const char *pth, const char *lf)
158{
159   char *fnm;
160   int len, len_total;
161   bool fAddSep = fFalse;
162
163   len = strlen(pth);
164   len_total = len + strlen(lf) + 1;
165
166   /* if there's a path and it doesn't end in a separator, insert one */
167   if (len && pth[len - 1] != FNM_SEP_LEV) {
168#ifdef FNM_SEP_LEV2
169      if (pth[len - 1] != FNM_SEP_LEV2) {
170#endif
171#ifdef FNM_SEP_DRV
172         if (pth[len - 1] != FNM_SEP_DRV) {
173#endif
174            fAddSep = fTrue;
175            len_total++;
176#ifdef FNM_SEP_DRV
177         }
178#endif
179#ifdef FNM_SEP_LEV2
180      }
181#endif
182   }
183
184   fnm = osmalloc(len_total);
185   strcpy(fnm, pth);
186   if (fAddSep) fnm[len++] = FNM_SEP_LEV;
187   strcpy(fnm + len, lf);
188   return fnm;
189}
190
191/* Add ext to fnm, inserting an FNM_SEP_EXT if appropriate */
192extern char * FAR
193add_ext(const char *fnm, const char *ext)
194{
195   char * fnmNew;
196   int len, len_total;
197#ifdef FNM_SEP_EXT
198   bool fAddSep = fFalse;
199#endif
200
201   len = strlen(fnm);
202   len_total = len + strlen(ext) + 1;
203#ifdef FNM_SEP_EXT
204   if (ext[0] != FNM_SEP_EXT) {
205      fAddSep = fTrue;
206      len_total++;
207   }
208#endif
209
210   fnmNew = osmalloc(len_total);
211   strcpy(fnmNew, fnm);
212#ifdef FNM_SEP_EXT
213   if (fAddSep) fnmNew[len++] = FNM_SEP_EXT;
214#endif
215   strcpy(fnmNew + len, ext);
216   return fnmNew;
217}
218
219/* fopen file, found using pth and fnm
220 * pfnmUsed used to return filename used to open file (ignored if NULL)
221 * or NULL if file didn't open
222 */
223extern FILE FAR *
224fopenWithPthAndExt(const char * pth, const char * fnm, const char * szExt,
225                   const char * szMode, char **pfnmUsed)
226{
227   char *fnmFull = NULL;
228   FILE *fh = NULL;
229   bool fAbs;
230
231   /* if no pth treat fnm as absolute */
232   fAbs = (pth == NULL || *pth == '\0' || fAbsoluteFnm(fnm));
233
234   /* if appropriate, try it without pth */
235   if (fAbs) {
236      fh = fopen_not_dir(fnm, szMode);
237      if (fh) {
238         if (pfnmUsed) fnmFull = osstrdup(fnm);
239      } else {
240         if (szExt && *szExt) {
241            /* we've been given an extension so try using it */
242            fnmFull = add_ext(fnm, szExt);
243            fh = fopen_not_dir(fnmFull, szMode);
244         }
245      }
246   } else {
247      /* try using path given - first of all without the extension */
248      fnmFull = use_path(pth, fnm);
249      fh = fopen_not_dir(fnmFull, szMode);
250      if (!fh) {
251         if (szExt && *szExt) {
252            /* we've been given an extension so try using it */
253            char *fnmTmp;
254            fnmTmp = fnmFull;
255            fnmFull = add_ext(fnmFull, szExt);
256            osfree(fnmTmp);
257            fh = fopen_not_dir(fnmFull, szMode);
258         }
259      }
260   }
261
262   /* either it opened or didn't. If not, fh == NULL from fopen_not_dir() */
263
264   /* free name if it didn't open or name isn't wanted */
265   if (fh == NULL || pfnmUsed == NULL) osfree(fnmFull);
266   if (pfnmUsed) *pfnmUsed = (fh ? fnmFull : NULL);
267   return fh;
268}
269
270/* Like fopenWithPthAndExt except that "foreign" paths are translated to
271 * native ones (e.g. on Unix dir\file.ext -> dir/file.ext) */
272FILE *
273fopen_portable(const char *pth, const char *fnm, const char *ext,
274               const char *mode, char **pfnmUsed)
275{
276   FILE *fh = fopenWithPthAndExt(pth, fnm, ext, mode, pfnmUsed);
277   if (fh == NULL) {
278#if (OS==RISCOS) || (OS==UNIX)
279      int f_changed = 0;
280      char *fnm_trans, *p;
281#if OS==RISCOS
282      char *q;
283#endif
284      fnm_trans = osstrdup(fnm);
285#if OS==RISCOS
286      q = fnm_trans;
287#endif
288      for (p = fnm_trans; *p; p++) {
289         switch (*p) {
290#if (OS==RISCOS)
291         /* swap either slash to a dot, and a dot to a forward slash */
292         /* but .. goes to ^ */
293         case '.':
294            if (p[1] == '.') {
295               *q++ = '^';
296               p++; /* skip second dot */
297            } else {
298               *q++ = '/';
299            }
300            f_changed = 1;
301            break;
302         case '/': case '\\':
303            *q++ = '.';
304            f_changed = 1;
305            break;
306         default:
307            *q++ = *p; break;
308#else
309         case '\\': /* swap a backslash to a forward slash */
310            *p = '/';
311            f_changed = 1;
312            break;
313#endif
314         }
315      }
316#if OS==RISCOS
317      *q = '\0';
318#endif
319      if (f_changed)
320         fh = fopenWithPthAndExt(pth, fnm_trans, ext, mode, pfnmUsed);
321
322#if (OS==UNIX)
323      /* as a last ditch measure, try lowercasing the filename */
324      if (fh == NULL) {
325         f_changed = 0;
326         for (p = fnm_trans; *p ; p++)
327            if (isupper(*p)) {
328               *p = tolower(*p);
329               f_changed = 1;
330            }
331         if (f_changed)
332            fh = fopenWithPthAndExt(pth, fnm_trans, ext, mode, pfnmUsed);
333      }
334#endif
335      osfree(fnm_trans);
336#endif
337   }
338   return fh;
339}
Note: See TracBrowser for help on using the repository browser.