]> andersk Git - splint.git/blame - src/osd.c
Removed /bin/csh from tainted/Makefile
[splint.git] / src / osd.c
CommitLineData
616915dd 1/*
11db3170 2** Splint - annotation-assisted static program checker
77d37419 3** Copyright (C) 1994-2002 University of Virginia,
616915dd 4** Massachusetts Institute of Technology
5**
6** This program is free software; you can redistribute it and/or modify it
7** under the terms of the GNU General Public License as published by the
8** Free Software Foundation; either version 2 of the License, or (at your
9** option) any later version.
10**
11** This program is distributed in the hope that it will be useful, but
12** WITHOUT ANY WARRANTY; without even the implied warranty of
13** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14** General Public License for more details.
15**
16** The GNU General Public License is available from http://www.gnu.org/ or
17** the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
18** MA 02111-1307, USA.
19**
1b8ae690 20** For information on splint: splint@cs.virginia.edu
21** To report a bug: splint-bug@cs.virginia.edu
11db3170 22** For more information: http://www.splint.org
616915dd 23*/
24/*
25** osd.c
26**
27** Provide a system-independent interface to system-dependent
28** file operations.
29*/
30
31/*
32 * Modified by Herbert 04/19/97:
33 * - added conditional 'OS2' to conditional 'MSDOS'
34 * - added include of new header portab.h.
35 * - changed '/' to macro.
36 * - added DOS / OS/2 specific stuff in osd_getPath.
37 * Herbert 06/12/2000:
38 * - added OS/2 specific includes before osd_getPid()
39 * - handle files like in WIN32 for OS/2 in osd_fileExists()
40 */
41
42/*@-allmacros*/
43/*@ignore@*/
44# include <sys/types.h>
45# include <sys/stat.h>
46/* Fix suggested by Lars Rasmussen */
47# include <errno.h>
4dd72714 48# ifdef WIN32
49# include <direct.h>
50# define getcwd _getcwd
51# endif
b7e84605 52
53/* POSIX platforms should defined getpid in unistd.h */
54# if defined (WIN32) || (defined(OS2) && defined(__IBMC__))
55# include <process.h>
56# else
57# include <unistd.h>
58# endif
59
616915dd 60/*@end@*/
61/*@=allmacros*/
1b8ae690 62# include "splintMacros.nf"
616915dd 63# include "basic.h"
64# include "osd.h"
65# include "portab.h"
66
67/* from stat.h */
68/*@ignore@*/
69extern int stat (const char *, /*@out@*/ struct stat *);
70/*@end@*/
71
72static bool osd_executableFileExists (char *);
73
74static bool nextdir (char **p_current_dir, /*@out@*/ char **p_dir,
75 /*@out@*/ size_t *p_len);
76
28bf4b0b 77extern cstring LSLRootName (cstring filespec)
616915dd 78{
28bf4b0b 79 /*@access cstring@*/
616915dd 80 char *result, *startName, *tail;
81 size_t nameLength;
82
28bf4b0b 83 llassert (cstring_isDefined (filespec));
616915dd 84 tail = strrchr (filespec, CONNECTCHAR);
85 startName = (tail == NULL ? filespec : &tail[1]);
86 tail = strrchr (startName, '.');
87 nameLength = (tail == NULL ? strlen (startName)
88 : size_fromInt (tail - startName));
89 result = dmalloc (nameLength + 1);
90 strncpy (result, startName, nameLength);
91 result[(int) nameLength] = '\0';
92 return result;
28bf4b0b 93 /*@noaccess cstring@*/
616915dd 94}
95
28bf4b0b 96extern /*@observer@*/ cstring
97osd_getEnvironment (cstring env, /*@returned@*/ cstring def)
616915dd 98{
28bf4b0b 99 /*@access cstring@*/
616915dd 100 char *ret = osd_getEnvironmentVariable (env);
101
102 if (ret == NULL)
103 {
104 return def;
105 }
106 else
107 {
108 return ret;
109 }
28bf4b0b 110 /*@noaccess cstring@*/
616915dd 111}
112
113
114/*
115**++
116** FUNCTIONAL DESCRIPTION:
117**
118** This function attempts to locate a file in a search list. On VMS, it
119** just concatinates the path and file names, and then lets RMS do the
120** searching. On Ultrix, it searches for the file on the path.
121**
122** FORMAL PARAMETERS:
123**
124** path: search path where to look for the file.
125** file: name of file to search for.
126** returnPath: if a file is found, this is where the concatenated
127** directory and file name are returned.
128**
129** RETURN VALUE:
130**
131** OSD_FILEFOUND: the file was found on the search list.
132** OSD_FILENOTFOUND the file was not found.
133** OSD_PATHTOOLONG the concatenated directory and file name are too
134** long.
135**
136** SIDE EFFECTS:
137**
138** None
139**
140** PRECONDITIONS:
141**
142** Requires that parameters, path and file, are valid C strings.
143**
144**
145**--
146*/
147
28bf4b0b 148extern /*@observer@*/ cstring osd_getHomeDir ()
616915dd 149{
150 /* Would something different be better for windows? */
28bf4b0b 151 return (osd_getEnvironmentVariable (cstring_makeLiteralTemp ("HOME")));
616915dd 152}
153
28bf4b0b 154filestatus osd_findOnLarchPath (cstring file, cstring *returnPath)
616915dd 155{
28bf4b0b 156 return (osd_getPath (context_getLarchPath (), file, returnPath));
616915dd 157}
158
159extern filestatus
28bf4b0b 160osd_getPath (cstring path, cstring file, cstring *returnPath)
616915dd 161{
162 char *fullPath;
163 char *dirPtr;
164 size_t dirLen;
165 char aPath[MAXPATHLEN];
166 filestatus rVal = OSD_FILENOTFOUND; /* assume file not found. */
28bf4b0b 167
168 /*@access cstring@*/
169
616915dd 170 fullPath = path;
28bf4b0b 171 llassert (cstring_isDefined (file));
172
3e3ec469 173 /* 2002-01-01: make sure returnPath gets defined even when there are errors.
174 ** (fixed splint checking detected this)
175 */
176
177 *returnPath = cstring_undefined;
178
28bf4b0b 179 if (fullPath == NULL
180 ||
616915dd 181# if defined(OS2) || defined(MSDOS) || defined(WIN32)
28bf4b0b 182 /* under OS/2 and MSDOS the includePath may be empty, if so, search
183 * the current directory. */
184 *fullPath == '\0' ||
185 (*file == CONNECTCHAR || (file[0] != '\0' && file[1] == ':'))
616915dd 186# else
28bf4b0b 187 (*file == CONNECTCHAR)
616915dd 188# endif
28bf4b0b 189 )
616915dd 190 {
28bf4b0b 191 /* No path specified. Look for it in the current directory. */
192
616915dd 193 strcpy (&aPath[0], file);
28bf4b0b 194
616915dd 195 if (osd_fileExists (&aPath[0]))
196 {
197 rVal = OSD_FILEFOUND;
198 *returnPath = dmalloc (strlen (&aPath[0]) + 1);
199 strcpy (*returnPath, &aPath[0]);
200 }
201 }
202 else
203 {
28bf4b0b 204 /* Path specified. Loop through directories in path looking for the */
205 /* first occurrence of the file. */
206
616915dd 207 while (nextdir (&fullPath, &dirPtr, &dirLen) &&
208 rVal == OSD_FILENOTFOUND)
209 {
210 if ((dirLen + strlen (file) + 2) <= MAXPATHLEN)
211 {
28bf4b0b 212 /* Cat directory and filename, and see if file exists. */
616915dd 213 strncpy (&aPath[0], dirPtr, dirLen);
214 strcpy (&aPath[0] + dirLen, ""); /* Null terminate aPath. */
215 strcat (&aPath[0], CONNECTSTR);
216 strcat (&aPath[0], file);
28bf4b0b 217
616915dd 218 if (osd_fileExists (&aPath[0]))
219 {
220 rVal = OSD_FILEFOUND;
221 *returnPath = (char *) dmalloc (strlen (&aPath[0]) + 1);
222 strcpy (*returnPath, &aPath[0]);
223 }
224 }
225 else
226 {
227 rVal = OSD_PATHTOOLONG;
228 }
229 }
230 }
3e3ec469 231
616915dd 232 return rVal;
28bf4b0b 233 /*@noaccess cstring@*/
616915dd 234}
235
236extern filestatus
28bf4b0b 237osd_getExePath (cstring path, cstring file, cstring *returnPath)
616915dd 238{
239 char *fullPath;
240 char *dirPtr;
241 size_t dirLen;
242 char aPath[MAXPATHLEN];
243 filestatus rVal = OSD_FILENOTFOUND; /* assume file not found. */
28bf4b0b 244 /*@access cstring@*/
3e3ec469 245
246 *returnPath = cstring_undefined;
616915dd 247 fullPath = osd_getEnvironmentVariable (path);
28bf4b0b 248
616915dd 249 if (fullPath == NULL)
250 {
28bf4b0b 251 /* No path specified. Look for it in the current directory. */
252 llassert (cstring_isDefined (file));
616915dd 253 strcpy (&aPath[0], file);
28bf4b0b 254
616915dd 255 if (osd_fileExists (&aPath[0]))
256 {
257 rVal = OSD_FILEFOUND;
258 *returnPath = dmalloc (strlen (&aPath[0]) + 1);
259 strcpy (*returnPath, &aPath[0]);
260 }
261 }
262 else
263 {
264 /*
265 ** Path specified. Loop through directories in path looking
266 ** for the first occurrence of the file.
267 */
268
269 while (nextdir (&fullPath, &dirPtr, &dirLen) &&
270 rVal == OSD_FILENOTFOUND)
271 {
28bf4b0b 272 llassert (cstring_isDefined (file));
273
274 if ((dirLen + cstring_length (file) + 2) <= MAXPATHLEN)
616915dd 275 {
276 /* Cat directory and filename, and see if file exists. */
277 strncpy (&aPath[0], dirPtr, dirLen);
278 strcpy (&aPath[0] + dirLen, ""); /* Null terminate aPath. */
279 strcat (&aPath[0], CONNECTSTR);
280 strcat (&aPath[0], file);
281
282 if (osd_executableFileExists (&aPath[0]))
283 {
284 rVal = OSD_FILEFOUND;
285 *returnPath = dmalloc (strlen (&aPath[0]) + 1);
286 strcpy (*returnPath, &aPath[0]);
287 }
288 }
289 else
290 {
291 rVal = OSD_PATHTOOLONG;
292 }
293 }
294 }
295
296 return rVal;
28bf4b0b 297 /*@noaccess cstring@*/
616915dd 298}
299
300bool
28bf4b0b 301osd_fileExists (cstring filespec)
616915dd 302{
303# ifdef UNIX
304 struct stat buf;
28bf4b0b 305 return (stat (cstring_toCharsSafe (filespec), &buf) == 0);
616915dd 306# else
307# if defined (WIN32) || defined (OS2)
dfd82dce 308 FILE *test = fileTable_openFile (context_fileTable (), filespec, "r");
28bf4b0b 309
616915dd 310 if (test != NULL)
28bf4b0b 311 {
dfd82dce 312 (void) fileTable_closeFile (context_fileTable (),test);
28bf4b0b 313 return TRUE;
314 }
616915dd 315 else
28bf4b0b 316 {
317 return FALSE;
318 }
616915dd 319# else
320 return FALSE;
321# endif
322# endif
323}
324
4dd72714 325# if defined(__IBMC__) && defined(OS2)
326# define S_IFMT (unsigned short)0xFFFF
327# endif
328
329/*
330** Works form Win32 at least...
331*/
332
333# ifndef S_IXUSR
334/*@-macrounrecog@*/
335# define S_IXUSR _S_IEXEC
336/*@=macrounrecog@*/
337# endif
338
616915dd 339bool
340osd_executableFileExists (/*@unused@*/ char *filespec)
341{
342# ifdef UNIX
4dd72714 343 struct stat buf;
616915dd 344 if (stat (filespec, &buf) == 0)
345 {
346 /* mask by file type */
347 /*@-unrecog@*/ /* S_IFMT is not defined */
348 if ((buf.st_mode & S_IFMT) != S_IFDIR /*@=unrecog@*/) /* not a directory */
349 {
350 /* as long as it is an executable file */
351# if defined(__IBMC__) && defined(OS2)
4dd72714 352 int com_or_exe_pos = strlen( filespec) - 4;
353 return stricmp( &filespec[com_or_exe_pos], ".exe") == 0
354 || stricmp( &filespec[com_or_exe_pos], ".com") == 0
355 || stricmp( &filespec[com_or_exe_pos], ".bat") == 0
356 || stricmp( &filespec[com_or_exe_pos], ".cmd") == 0;
616915dd 357# else
358 return (((buf.st_mode & S_IXUSR)
4dd72714 359# if defined (S_IXGRP) && defined (S_IXOTH)
616915dd 360 | (buf.st_mode & S_IXGRP) |
361 (buf.st_mode & S_IXOTH)
362# endif
363 ) != 0);
364# endif
365 }
366 }
616915dd 367# endif
368 return (FALSE);
369
370}
371
372/*
373**++
374** FUNCTIONAL DESCRIPTION:
375**
376** Find the next directory from a directory path.
377**
378** FORMAL PARAMETERS:
379**
380** char ** current_dir :
381** Points to the current position in the path string. The first time
382** you call this routine, this should point to the first character of
383** the path. On return, this will be updated to point to the
384** terminating \0 or : of the first directory found. You can then pass
385** it unchanged for subsequent calls; this routine will correctly skip
386** over the :.
387**
388** char ** dir :
389** On exit, this will point to the first character of the directory
390** that was found. This will be a pointer directly into the client's
391** path string.
392**
393** unsigned int * len :
394** On exit, this will contain the length of the directory that was
395** found, not counting any terminating \0 or :. If no directory was
396** found, this will be 0.
397**
398** RETURN VALUE:
399** TRUE if we found another directory.
400** FALSE otherwise.
401**
402** DESIGN:
403**
404** We return a pointer and length, rather than a string, because of a)
405** historical reasons; and b) this avoids having to allocate storage.
406**
407**
408**
409**--
410*/
411
412static bool
413nextdir (d_char *current_dir, d_char *dir, size_t *len)
414{
415 char *tchar;
416
417 if (**current_dir == '\0')
418 {
419 *len = 0;
3e3ec469 420 *dir = NULL;
616915dd 421 return FALSE;
422 }
423
7272a1c1 424 *dir = (**current_dir == PATH_SEPARATOR ? *current_dir + 1 : *current_dir);
616915dd 425
426 /* Find next ':' or end of string */
7272a1c1 427 for (tchar = *dir; *tchar != '\0' && *tchar != PATH_SEPARATOR; tchar++)
616915dd 428 {
429 ;
430 }
431
432 *current_dir = tchar;
433 *len = size_fromInt (tchar - *dir);
434 return TRUE;
435}
436
28bf4b0b 437/*@observer@*/ /*@null@*/ cstring osd_getEnvironmentVariable (cstring var)
616915dd 438{
1d239d69 439 /* evans - 2001-08-26 fixed OS instead of OS2 bug, reported by Alexander Mai */
440# if defined(UNIX) || defined(OS2) || defined(MSDOS) || defined(WIN32)
28bf4b0b 441 char *val = getenv (cstring_toCharsSafe (var));
442
443 if (val == NULL)
444 {
445 return cstring_undefined;
446 }
447 else
448 {
449 return cstring_makeLiteralTemp (val);
450 }
616915dd 451# else
28bf4b0b 452 return cstring_undefined;
616915dd 453# endif
454}
455
456# ifndef NOLCL
457
458# ifdef WIN32
459extern /*@external@*/ int _flushall (void) /*@modifies fileSystem@*/ ;
460# endif
461
462# ifndef system
463extern /*@external@*/ int system (const char *) /*@modifies fileSystem@*/ ;
464# endif
28bf4b0b 465int osd_system (cstring cmd)
616915dd 466{
467 int res;
468 /* system ("printenv"); */
469# ifdef WIN32
470 (void) _flushall ();
471# endif
472
28bf4b0b 473 res = system (cstring_toCharsSafe (cmd));
616915dd 474 return res;
475}
476# endif
477
478# ifndef unlink
b7e84605 479/* This should be defined by unistd.h */
616915dd 480/*@-redecl@*/
481extern /*@external@*/ int unlink (const char *) /*@modifies fileSystem@*/ ;
482/*@=redecl@*/
483# endif
484
4dd72714 485static s_tempError = FALSE;
486
487void osd_setTempError (void)
488{
489 s_tempError = TRUE;
490}
491
28bf4b0b 492int osd_unlink (cstring fname)
616915dd 493{
494 int res;
495
28bf4b0b 496 res = unlink (cstring_toCharsSafe (fname));
616915dd 497
498 if (res != 0)
499 {
4dd72714 500 if (!s_tempError)
501 {
502 llcontbug (message ("Cannot remove temporary file: %s (%s)",
503 fname,
504 cstring_fromChars (strerror (errno))));
505 }
616915dd 506 }
507
508 return res;
509}
510
616915dd 511# if defined (WIN32) || defined (OS2) && defined (__IBMC__)
512int
513# else
514int /* pid_t */
515# endif
516osd_getPid ()
517{
518# if defined (WIN32) || defined (OS2) && defined (__IBMC__)
519 int pid = _getpid ();
520# else
28bf4b0b 521 pid_t pid = getpid ();
616915dd 522# endif
523
524 return (int) pid;
525}
526
28bf4b0b 527cstring osd_fixDefine (cstring x)
616915dd 528{
28bf4b0b 529 /*@access cstring@*/
530 llassert (cstring_isDefined (x));
616915dd 531# ifdef UNIX
532 if (strchr (x, '\'') != NULL) {
533 /*
534 ** If there is a single quote, check for <ident>='<string>' and
535 ** produce <ident>=<string>
536 */
537
538 char *eqs = strchr (x, '=');
539
540 if (eqs != NULL) {
541 if (eqs[1] == '\'') {
542 char *endqu = strrchr (x, '\'');
543
544 if (endqu != NULL) {
545 if (*(endqu - 1) != '\\') {
546 if (*(endqu + 1) == '\0') {
547 cstring res;
548 cstring def;
549
550 *endqu = '\0';
551 def = cstring_fromChars (eqs + 2);
552 eqs[1] = '\0';
553 res = cstring_concat (cstring_fromChars (x), def);
554 return res;
555 }
556 }
557 }
558 }
559 }
560 }
561
562# endif
563
28bf4b0b 564 return cstring_copy (x);
565 /*@noaccess cstring@*/
616915dd 566}
567
28bf4b0b 568bool osd_fileIsReadable (cstring f)
616915dd 569{
dfd82dce 570 FILE *fl = fileTable_openFile (context_fileTable (), f, "r");
616915dd 571
dfd82dce 572 if (fl != NULL)
616915dd 573 {
dfd82dce 574 check (fileTable_closeFile (context_fileTable (), fl));
616915dd 575 return (TRUE);
576 }
577 else
578 {
579 return (FALSE);
580 }
581}
582
583bool osd_isConnectChar (char c)
584{
585 if (c == CONNECTCHAR)
586 {
587 return TRUE;
588 }
589
590# ifdef HASALTCONNECTCHAR
591 if (c == ALTCONNECTCHAR)
592 {
593 return TRUE;
594 }
595# endif
596
597 return FALSE;
598}
599
68de3f33 600/*
601** Returns true if c2 starts with the same path as c1
602**
603** This is called by context_isSystemDir to determine if a
604** directory is on the system path.
605**
606** In unix, this is just a string comparison. For Win32 and OS2, we need a more
607** complex comparison.
608*/
609
610bool osd_equalCanonicalPrefix (cstring dirpath, cstring prefixpath)
611{
612 llassert (cstring_isDefined (prefixpath));
613
614 if (cstring_isEmpty (dirpath))
615 {
616 return (cstring_isEmpty (prefixpath));
617 }
618
619# if defined (WIN32) || defined (OS2)
620
621 /*@access cstring@*/ /* Moved this from cstring - should abstract it... */
622
623 /*
624 ** If one has a drive specification, but the other doesn't, skip it.
625 */
626
627 if (strchr (dirpath, ':') == NULL
628 && strchr (prefixpath, ':') != NULL)
629 {
630 prefixpath = strchr (prefixpath, ':') + 1;
631 }
632 else
633 {
634 if (strchr (prefixpath, ':') == NULL
635 && strchr (dirpath, ':') != NULL)
636 {
637 dirpath = strchr (dirpath, ':') + 1;
638 }
639 }
640
641 {
642 int len = size_toInt (strlen (prefixpath));
643 int i = 0;
644 int slen = 0;
645
646 for (i = 0, slen = 0; i < len; i++, slen++)
647 {
648 /* Allow any number of connect characters in any combination:
649 * c:/usr//src\/foo == c:\\usr/src\/foo
650 * After this we'll be at the last of such a sequence */
651
652 if (osd_isConnectChar (dirpath[slen]) && osd_isConnectChar (prefixpath[i]))
653 {
654 /* Skip one or more connect chars */
655
656 for (; osd_isConnectChar (dirpath[slen+1]); ++slen)
657 {
658 ;
659 }
660
661 for (; osd_isConnectChar (prefixpath[i+1]); ++i)
662 {
663 ;
664 }
665 }
666 /* Windows, MSDOS and OS/2 use case-insensitive path specs! */
667 else if (toupper (dirpath[slen]) != toupper (prefixpath[i]))
668 {
669 return FALSE;
670 }
671
672 }
673 }
674
675 /*@noaccess cstring@*/
676
677 return TRUE;
678# else
679 return (cstring_equalPrefix (dirpath, prefixpath));
680# endif
681}
682
107b60d6 683# if 0
684/*
685** This code provided by Herbert Martin Dietze, to canonicalize path names.
686*/
687
688char *osd_getcwd (/*@returned@*/ char *str, size_t size)
689{
690 return getcwd (str, size);
691}
692
693/*@null@*/ /*@observer@*/ char *
694osd_dirNext (char *str)
695{
696 char *p1 = strchr (str, '/');
697 char *p2 = strchr (str, '\\');
698
699 if (p1 == NULL)
700 {
701 if (p2 != NULL)
702 {
703 return p2 + 1;
704 }
705 else
706 {
707 return NULL;
708 }
709 }
710 else if (p2 == NULL)
711 {
712 return p1 + 1;
713 }
714 else /* both not null */
715 {
716 return (p1 < p2 ? p1 : p2) + 1;
717 }
718}
719
720static void
721osd_dirShift (char *str, size_t num) /*@modifies str@*/
722{
723 int i;
724
725 assert (num <= strlen (str));
726
727 for (i = 0; str[i] != '\0'; i++)
728 {
729 str[i] = str[i + num];
730 }
731}
732
733bool
734osd_dirDotdot (char *str)
735{
736 return str[0] == '.' && str[1] == '.' && osd_isConnectChar (str[2]);
737}
738
739void
740osd_dirNormalize (char *str)
741{
742 char *pos1, *pos2;
743
744 for (; osd_isConnectChar (str[0]); str++)
745 {
746 }
747
748 for (; str != NULL && osd_dirDotdot (str); str = osd_dirNext (str))
749 {
750 }
751
752 for (pos1 = pos2 = str;
753 pos1 != NULL;
754 pos2 = pos1, pos1 = osd_dirNext (pos1))
755 {
756 /* remove redundant `./' entry */
757 while (pos1[0] == '.' && osd_isConnectChar (pos1[1]))
758 {
759 osd_dirShift (pos1, 2);
760 }
761
762 /* remove redundant `foo/../' entry */
763 if (osd_dirDotdot (pos1) && pos2 < pos1)
764 {
765 osd_dirShift (pos2, pos1 - pos2 + 1);
766 osd_dirNormalize (str);
767 }
768 }
769}
770
771/*@null@*/ char *
772osd_dirAbsolute (char *str)
773{
774 char *ret = NULL;
775 size_t size = PATH_MAX * sizeof (*ret);
776
4dd72714 777 DPRINTF (("Absolute for: %s", str));
778
779# ifdef WIN32
780 if (strlen (str) > 1 && str[1] == ':')
781 {
782 /*
783 ** Its a drive letter
784 */
785
786 ret = dmalloc ((strlen (str) + 1) * sizeof (*ret));
787 strcpy (ret, str);
788 }
789 else
790# endif
107b60d6 791 if (osd_isConnectChar (str[0]))
792 {
793 ret = dmalloc ((strlen (str) + 1) * sizeof (*ret));
794 strcpy (ret, str);
795 }
796 else
797 {
798 ret = dmalloc (size);
799
800 ret = osd_getcwd (ret, size);
801 ret = realloc (ret, (strlen (str) + strlen (ret) + 2) * sizeof (*ret));
802
803 if (ret == NULL)
804 {
805 return NULL;
806 }
807
808 strcat (ret, CONNECTSTR);
809 strcat (ret, str);
810 }
811
812 osd_dirNormalize (ret);
813 return ret;
814}
815
816# endif
53a89507 817
818/*
819** absolute paths
820**
821** This code is adapted from:
822**
823** http://src.openresources.com/debian/src/devel/HTML/S/altgcc_2.7.2.2.orig%20altgcc-2.7.2.2.orig%20protoize.c.html#1297
824**
825**
826** Protoize program - Original version by Ron Guilmette (rfg@segfault.us.com).
827** Copyright (C) 1989, 1992, 1993, 1994, 1995 Free Software Foundation, Inc.
828**
829** This file is part of GNU CC.
830**
831** GNU CC is free software; you can redistribute it and/or modify
832** it under the terms of the GNU General Public License as published by
833** the Free Software Foundation; either version 2, or (at your option)
834** any later version.
835**
836** GNU CC is distributed in the hope that it will be useful,
837** but WITHOUT ANY WARRANTY; without even the implied warranty of
838** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
839** GNU General Public License for more details.
840**
841** You should have received a copy of the GNU General Public License
842** along with GNU CC; see the file COPYING. If not, write to
843** the Free Software Foundation, 59 Temple Place - Suite 330,
844** Boston, MA 02111-1307, USA.
845*/
846
847/*
848** Return the absolutized filename for the given relative
849** filename. Note that if that filename is already absolute, it may
850** still be returned in a modified form because this routine also
851** eliminates redundant slashes and single dots and eliminates double
852** dots to get a shortest possible filename from the given input
853** filename. The absolutization of relative filenames is made by
854** assuming that the given filename is to be taken as relative to
855** the first argument (cwd) or to the current directory if cwd is
856** NULL.
857*/
858
859/* A pointer to the current directory filename (used by abspath). */
860static /*@only@*/ cstring osd_cwd = cstring_undefined;
861
862static void osd_setWorkingDirectory (void)
863{
864# ifdef UNIX
865 char *buf = dmalloc (sizeof (*buf) * MAXPATHLEN);
866 char *cwd = getcwd (buf, MAXPATHLEN);
867
868 llassert (cstring_isUndefined (osd_cwd));
869
870 if (cwd == NULL)
871 {
872 lldiagmsg (message ("Cannot get working directory: %s\n",
873 lldecodeerror (errno)));
874 }
875 else
876 {
877 osd_cwd = cstring_fromCharsNew (cwd);
878 }
879
880 sfree (buf);
881# else
882 ; /* Don't know how to do this for non-POSIX platforms */
883# endif
884}
885
886void osd_initMod (void)
887{
888 osd_setWorkingDirectory ();
889}
890
891cstring osd_absolutePath (cstring cwd, cstring filename)
892{
893# ifdef UNIX
894 /* Setup the current working directory as needed. */
895 cstring cwd2 = cstring_isDefined (cwd) ? cwd : osd_cwd;
896 char *abs_buffer;
897 char *endp, *outp, *inp;
898
899 /*@access cstring@*/
900 llassert (cstring_isDefined (cwd2));
901 llassert (cstring_isDefined (filename));
902
903 abs_buffer = (char *) dmalloc (size_fromInt (cstring_length (cwd2) + cstring_length (filename) + 2));
904 endp = abs_buffer;
905
906 /*
907 ** Copy the filename (possibly preceded by the current working
908 ** directory name) into the absolutization buffer.
909 */
910
911 {
912 const char *src_p;
913
914 if (filename[0] != '/')
915 {
916 src_p = cwd2;
917
918 while ((*endp++ = *src_p++) != '\0')
919 {
920 continue;
921 }
922
923 *(endp-1) = '/'; /* overwrite null */
924 }
925
926 src_p = filename;
927
928 while ((*endp++ = *src_p++) != '\0')
929 {
930 continue;
931 }
932 }
933
934 /* Now make a copy of abs_buffer into abs_buffer, shortening the
935 filename (by taking out slashes and dots) as we go. */
936
937 outp = inp = abs_buffer;
938 *outp++ = *inp++; /* copy first slash */
939#ifdef apollo
940 if (inp[0] == '/')
941 *outp++ = *inp++; /* copy second slash */
942#endif
943 for (;;)
944 {
945 if (inp[0] == '\0')
946 {
947 break;
948 }
949 else if (inp[0] == '/' && outp[-1] == '/')
950 {
951 inp++;
952 continue;
953 }
954 else if (inp[0] == '.' && outp[-1] == '/')
955 {
956 if (inp[1] == '\0')
957 {
958 break;
959 }
960 else if (inp[1] == '/')
961 {
962 inp += 2;
963 continue;
964 }
965 else if ((inp[1] == '.')
966 && (inp[2] == '\0' || inp[2] == '/'))
967 {
968 inp += (inp[2] == '/') ? 3 : 2;
969 outp -= 2;
970
971 while (outp >= abs_buffer && *outp != '/')
972 {
973 outp--;
974 }
975
976 if (outp < abs_buffer)
977 {
978 /* Catch cases like /.. where we try to backup to a
979 point above the absolute root of the logical file
980 system. */
981
982 llfatalbug (message ("Invalid file name: %s", filename));
983 }
984
985 *++outp = '\0';
986 continue;
987 }
988 else
989 {
990 ;
991 }
992 }
993 else
994 {
995 ;
996 }
997
998 *outp++ = *inp++;
999 }
1000
1001 /* On exit, make sure that there is a trailing null, and make sure that
1002 the last character of the returned string is *not* a slash. */
1003
1004 *outp = '\0';
1005 if (outp[-1] == '/')
1006 *--outp = '\0';
1007
1008 /*@noaccess cstring@*/
1009 return cstring_fromChars (abs_buffer);
1010# else
4dd72714 1011 DPRINTF (("Here: %s", filename));
53a89507 1012 return cstring_copy (filename);
1013# endif
1014}
1015
1016/*
1017** Given a filename (and possibly a directory name from which the filename
1018** is relative) return a string which is the shortest possible
1019** equivalent for the corresponding full (absolutized) filename. The
1020** shortest possible equivalent may be constructed by converting the
1021** absolutized filename to be a relative filename (i.e. relative to
1022** the actual current working directory). However if a relative filename
1023** is longer, then the full absolute filename is returned.
1024**
1025** KNOWN BUG: subpart of the original filename is actually a symbolic link.
1026*/
1027
1028cstring osd_outputPath (cstring filename)
1029{
1030# ifdef UNIX
1031 char *rel_buffer;
1032 char *rel_buf_p;
1033 cstring cwd_p = osd_cwd;
1034 char *path_p;
1035 int unmatched_slash_count = 0;
1036 size_t filename_len = size_fromInt (cstring_length (filename));
1037
1038 /*@access cstring@*/
1039 path_p = filename;
1040 rel_buf_p = rel_buffer = (char *) dmalloc (filename_len);
1041
1042 llassert (cwd_p != NULL);
1043 llassert (path_p != NULL);
1044
1045 while ((*cwd_p != '\0') && (*cwd_p == *path_p))
1046 {
1047 cwd_p++;
1048 path_p++;
1049 }
1050
1051 if ((*cwd_p == '\0') && (*path_p == '\0' || *path_p == '/')) /* whole pwd matched */
1052 {
1053 if (*path_p == '\0') /* input *is* the current path! */
1054 return cstring_makeLiteral (".");
1055 else
1056 {
1b8ae690 1057 /*@i324 ! splint didn't report an errors for: return ++path_p; */
53a89507 1058 return cstring_fromCharsNew (++path_p);
1059 }
1060 }
1061 else
1062 {
1063 if (*path_p != '\0')
1064 {
1065 --cwd_p;
1066 --path_p;
1067 while (*cwd_p != '/') /* backup to last slash */
1068 {
1069 --cwd_p;
1070 --path_p;
1071 }
1072 cwd_p++;
1073 path_p++;
1074 unmatched_slash_count++;
1075 }
1076
1077 /* Find out how many directory levels in cwd were *not* matched. */
1078 while (*cwd_p != '\0')
1079 {
1080 if (*cwd_p++ == '/')
1081 unmatched_slash_count++;
1082 }
1083
1084 /* Now we know how long the "short name" will be.
1085 Reject it if longer than the input. */
1086 if (unmatched_slash_count * 3 + strlen (path_p) >= filename_len)
1087 {
1088 return cstring_copy (filename);
1089 }
1090
1091 /*
1092 ** evans 2001-10-15
1093 ** I'm trusting the code on this one...don't see how this is guaranteed though.
1094 */
1095
1096 assertSet (rel_buffer);
1097
1098 /* For each of them, put a `../' at the beginning of the short name. */
1099 while (unmatched_slash_count-- > 0)
1100 {
1101 /* Give up if the result gets to be longer
1102 than the absolute path name. */
1103 if (rel_buffer + filename_len <= rel_buf_p + 3)
1104 {
1105 sfree (rel_buffer);
1106 return cstring_copy (filename);
1107 }
1108
1109 *rel_buf_p++ = '.';
1110 *rel_buf_p++ = '.';
1111 *rel_buf_p++ = '/';
1112 }
1113
1114 /* Then tack on the unmatched part of the desired file's name. */
1115 do
1116 {
1117 if (rel_buffer + filename_len <= rel_buf_p)
1118 {
1119 cstring_free (rel_buffer);
1120 return cstring_copy (filename);
1121 }
146e25eb 1122 } /*@-usereleased@*/
53a89507 1123 while ((*rel_buf_p++ = *path_p++) != '\0') ;
146e25eb 1124 /*@=usereleased@*/ /*@i523! shouldn't need these */
1125
53a89507 1126 --rel_buf_p;
1127 if (*(rel_buf_p-1) == '/')
1128 *--rel_buf_p = '\0';
1129
1130 return rel_buffer;
1131 }
1132 /*@noaccess cstring@*/
1133# else
1134 return cstring_copy (filename);
1135# endif
1136}
1137
f2b6724f 1138cstring osd_getCurrentDirectory ()
1139{
1140# if defined(MSDOS) || defined(OS2)
1141 return cstring_makeLiteralTemp ("");
1142# else
1143 return cstring_makeLiteralTemp ("./");
1144# endif
1145}
1146
53a89507 1147
1148
This page took 1.579377 seconds and 5 git commands to generate.