source: git/src/filename.c @ f74d0cb

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 f74d0cb was d227ee5, checked in by Olly Betts <olly@…>, 25 years ago

Tidied up use of messages.

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

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