2 ** Splint - annotation-assisted static program checker
3 ** Copyright (C) 1994-2003 University of Virginia,
4 ** Massachusetts Institute of Technology
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.
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.
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.
20 ** For information on splint: info@splint.org
21 ** To report a bug: splint-bug@splint.org
22 ** For more information: http://www.splint.org
27 ** Provide a system-independent interface to system-dependent
32 * Modified by Herbert 04/19/97:
33 * - added conditional 'OS2'
34 * - added include of new header portab.h.
35 * - changed occurance of '/' as path delimiter to a macro.
36 * - added DOS / OS/2 specific stuff in osd_getPath.
38 * - added OS/2 specific includes before osd_getPid()
39 * - handle files like in WIN32 for OS/2 in osd_fileExists()
41 * - added OS/2 support to absolute file names
46 # include <sys/types.h>
47 # include <sys/stat.h>
49 /* Fix suggested by Lars Rasmussen */
56 # include <io.h> /* _open() */
57 # define open(pathname, flags, mode) _open(pathname, flags, mode)
58 # define getpid() _getpid()
59 # define getcwd(buf, size) _getcwd(buf, size)
60 extern /*@external@*/ int _flushall (void) /*@modifies fileSystem@*/ ;
66 extern /*@external@*/ int system (const char *) /*@modifies fileSystem@*/ ;
70 /* This should be defined by unistd.h */
72 extern /*@external@*/ int unlink (const char *) /*@modifies fileSystem@*/ ;
79 # include "splintMacros.nf"
85 /*@constant observer char *DEFAULT_TMPDIR; @*/
86 # define DEFAULT_TMPDIR "\\WINDOWS\\TEMP\\"
87 # elif defined(P_tmpdir)
88 /*@constant observer char *DEFAULT_TMPDIR; @*/
89 # define DEFAULT_TMPDIR P_tmpdir
91 /*@constant observer char *DEFAULT_TMPDIR; @*/
92 # define DEFAULT_TMPDIR "/tmp/"
95 # if defined (OS2) || defined (WIN32)
96 /*@constant char ALTCONNECTCHAR@*/
97 # define ALTCONNECTCHAR '/'
98 /*@constant char DRIVECONNECTCHAR@*/
99 # define DRIVECONNECTCHAR ':'
103 ** MAXPATHLEN defines the longest permissable path length.
105 ** POSIX defines PATHMAX in limits.h
108 # if defined (PATH_MAX)
109 /*@constant size_t MAXPATHLEN; @*/
110 # define MAXPATHLEN PATH_MAX
112 /*@constant size_t MAXPATHLEN; @*/
113 # define MAXPATHLEN 1024
118 #define S_ISREG(m) (((m) & S_IFMT) == S_IFREG)
124 #define S_ISDIR(m) (((m) & S_IFMT) == S_IFDIR)
130 # define S_IWUSR _S_IWRITE
136 # define S_IRUSR _S_IREAD
141 # if defined (S_IRUSR) && defined (S_IWUSR) && \
142 defined (S_IRGRP) && defined (S_IWGRP) && \
143 defined (S_IROTH) && defined (S_IWOTH)
144 # define S_IRWALL (S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH)
155 osd_fileExists (cstring filespec
)
157 # if defined (WIN32) || defined (OS2)
158 FILE *test
= fileTable_openReadFile (context_fileTable (), filespec
);
162 (void) fileTable_closeFile (context_fileTable (),test
);
171 /*@i3@*/ return (stat (cstring_toCharsSafe (filespec
), &buf
) == 0);
176 osd_fileIsReadable (cstring f
)
178 # if defined (WIN32) || defined (OS2)
179 FILE *fl
= fileTable_openReadFile (context_fileTable (), f
);
183 check (fileTable_closeFile (context_fileTable (), fl
));
192 /*@i3@*/ return (stat (cstring_toCharsSafe (f
), &buf
) == 0 && S_ISREG(buf
.st_mode
));
197 osd_fileIsExecutable (/*@unused@*/ char *filespec
)
199 /*@-compdestroy@*/ /* possible memory leaks here? */
201 if (stat (filespec
, &buf
) == 0)
203 /* mask by file type */
204 /*@-type@*/ /* confusion about __mode_t and mode_t types */
205 if (!S_ISDIR(buf
.st_mode
))
208 /* as long as it is an executable file */
210 int com_or_exe_pos
= strlen( filespec
) - 4;
211 return stricmp( &filespec
[com_or_exe_pos
], ".exe") == 0
212 || stricmp( &filespec
[com_or_exe_pos
], ".com") == 0
213 || stricmp( &filespec
[com_or_exe_pos
], ".bat") == 0
214 || stricmp( &filespec
[com_or_exe_pos
], ".cmd") == 0;
216 return (((buf
.st_mode
& S_IXUSR
)
217 # if defined (S_IXGRP) && defined (S_IXOTH)
218 | (buf
.st_mode
& S_IXGRP
)
219 | (buf
.st_mode
& S_IXOTH
)
229 cstring
osd_pathListConcat (const char* p0
, const char* p1
)
234 llassert (p0
!= NULL
&& p1
!= NULL
);
239 res
= dmalloc (l0
+ 1 + l1
+ 1);
241 res
[l0
] = PATH_SEPARATOR
;
242 strcpy (res
+ l0
+ 1, p1
);
244 return cstring_fromChars (res
);
249 ** FUNCTIONAL DESCRIPTION:
251 ** Find the next directory from a directory path.
253 ** FORMAL PARAMETERS:
255 ** char ** current_dir :
256 ** Points to the current position in the path string. The first time
257 ** you call this routine, this should point to the first character of
258 ** the path. On return, this will be updated to point to the
259 ** terminating \0 or : of the first directory found. You can then pass
260 ** it unchanged for subsequent calls; this routine will correctly skip
264 ** On exit, this will point to the first character of the directory
265 ** that was found. This will be a pointer directly into the client's
268 ** unsigned int * len :
269 ** On exit, this will contain the length of the directory that was
270 ** found, not counting any terminating \0 or :. If no directory was
271 ** found, this will be 0.
274 ** TRUE if we found another directory.
279 ** We return a pointer and length, rather than a string, because of a)
280 ** historical reasons; and b) this avoids having to allocate storage.
288 nextdir (d_char
*current_dir
, d_char
*dir
, size_t *len
)
292 if (**current_dir
== '\0')
299 *dir
= (**current_dir
== PATH_SEPARATOR
? *current_dir
+ 1 : *current_dir
);
301 /* Find next PATH_SEPARATOR or end of string */
302 for (tchar
= *dir
; *tchar
!= '\0' && *tchar
!= PATH_SEPARATOR
; tchar
++)
307 *current_dir
= tchar
;
308 *len
= size_fromInt (tchar
- *dir
);
314 ** FUNCTIONAL DESCRIPTION:
316 ** This function attempts to locate a file in a search list. On Ultrix,
317 ** it searches for the file on the path.
319 ** FORMAL PARAMETERS:
321 ** path: search path where to look for the file.
322 ** file: name of file to search for.
323 ** returnPath: if a file is found, this is where the concatenated
324 ** directory and file name are returned.
328 ** OSD_FILEFOUND: the file was found on the search list.
329 ** OSD_FILENOTFOUND the file was not found.
330 ** OSD_PATHTOOLONG the concatenated directory and file name are too
339 ** Requires that parameters, path and file, are valid C strings.
346 osd_getPathFilter (cstring path
, cstring file
, cstring
*returnPath
,
347 bool (*pathFilter
) (cstring filespec
))
349 filestatus rVal
= OSD_FILENOTFOUND
;
353 llassert (cstring_isDefined (file
));
354 llassert (returnPath
!= NULL
);
356 *returnPath
= cstring_undefined
;
358 if ( osd_pathIsAbsolute (file
)
363 if (pathFilter (file
))
365 rVal
= OSD_FILEFOUND
;
366 *returnPath
= cstring_fromCharsNew (file
);
374 char aPath
[MAXPATHLEN
];
377 while (nextdir (&fullPath
, &dirPtr
, &dirLen
)
378 && rVal
== OSD_FILENOTFOUND
)
380 if ((dirLen
+ 1 + strlen (file
) + 1) <= sizeof(aPath
))
382 strncpy (aPath
, dirPtr
, dirLen
);
383 aPath
[dirLen
] = CONNECTCHAR
;
384 strcpy (aPath
+ dirLen
+ 1, file
);
385 if (pathFilter (aPath
))
387 rVal
= OSD_FILEFOUND
;
388 *returnPath
= cstring_fromCharsNew (aPath
);
393 rVal
= OSD_PATHTOOLONG
;
399 /*@noaccess cstring@*/
403 osd_getPath (cstring path
, cstring file
, cstring
*returnPath
)
405 return osd_getPathFilter (path
, file
, returnPath
, osd_fileExists
);
409 osd_getExePath (cstring path
, cstring file
, cstring
*returnPath
)
411 return osd_getPathFilter (path
, file
, returnPath
, osd_fileIsExecutable
);
414 static bool s_tempError
= FALSE
;
416 static void osd_setTempError (void)
417 /*@modifies internalState@*/
422 int osd_system (cstring cmd
)
429 res
= system (cstring_toCharsSafe (cmd
));
433 int osd_unlink (cstring fname
)
437 res
= unlink (cstring_toCharsSafe (fname
));
443 llcontbug (message ("Cannot remove temporary file: %s (%s)",
445 cstring_fromChars (strerror (errno
))));
455 return (int) getpid ();
458 bool osd_isConnectChar (char c
)
460 if (c
== CONNECTCHAR
)
465 # if defined (OS2) || defined (WIN32)
466 if (c
== ALTCONNECTCHAR
)
476 ** Returns true if c2 starts with the same path as c1
478 ** This is called by context_isSystemDir to determine if a
479 ** directory is on the system path.
481 ** In unix, this is just a string comparison. For Win32 and OS2, we need a more
482 ** complex comparison.
485 static bool osd_equalCanonicalPrefix (cstring dirpath
, cstring prefixpath
)
487 llassert (cstring_isDefined (prefixpath
));
489 if (cstring_isEmpty (dirpath
))
491 return (cstring_isEmpty (prefixpath
));
494 # if defined (WIN32) || defined (OS2)
499 int len
= size_toInt (strlen (prefixpath
));
502 char *dirdrive
, *prefixdrive
;
505 ** If one has a drive specification, but the other doesn't, skip it.
508 dirdrive
= strchr (dirpath
, DRIVECONNECTCHAR
);
509 prefixdrive
= strchr (prefixpath
, DRIVECONNECTCHAR
);
510 if (dirdrive
== NULL
&& prefixdrive
!= NULL
)
512 prefixpath
= prefixdrive
+ 1;
514 else if (prefixdrive
== NULL
&& dirdrive
!= NULL
)
516 dirpath
= dirdrive
+ 1;
519 for (i
= 0, slen
= 0; i
< len
; i
++, slen
++)
521 /* Allow any number of connect characters in any combination:
522 * c:/usr//src\/foo == c:\\usr/src\/foo
523 * After this we'll be at the last of such a sequence */
525 if (osd_isConnectChar (dirpath
[slen
]) && osd_isConnectChar (prefixpath
[i
]))
527 /* Skip one or more connect chars */
529 for (; osd_isConnectChar (dirpath
[slen
+1]); ++slen
)
534 for (; osd_isConnectChar (prefixpath
[i
+1]); ++i
)
539 /* DOS-like systems use case-insensitive path specs! */
540 else if (toupper (dirpath
[slen
]) != toupper (prefixpath
[i
]))
548 /*@noaccess cstring@*/
552 return (cstring_equalPrefix (dirpath
, prefixpath
));
557 osd_pathPrefixInPathList (cstring path
, cstring pathList
)
559 cstring tmpPathList
, curPathList
;
563 llassert (cstring_isDefined (pathList
));
565 tmpPathList
= cstring_copy (pathList
);
566 curPathList
= tmpPathList
;
572 curPath
= curPathList
;
573 curPathList
= cstring_afterChar (curPath
, PATH_SEPARATOR
);
574 if (cstring_isDefined (curPathList
))
579 /*@noaccess cstring@*/
587 ** herbert: don't compare with an empty name!
588 ** should return false for empty directory path
590 if (cstring_isEmpty (curPath
))
595 if (osd_equalCanonicalPrefix (path
, curPath
))
603 cstring_free (tmpPathList
);
611 ** This code is adapted from:
613 ** 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
616 ** Protoize program - Original version by Ron Guilmette (rfg@segfault.us.com).
617 ** Copyright (C) 1989, 1992, 1993, 1994, 1995 Free Software Foundation, Inc.
619 ** This file is part of GNU CC.
621 ** GNU CC is free software; you can redistribute it and/or modify
622 ** it under the terms of the GNU General Public License as published by
623 ** the Free Software Foundation; either version 2, or (at your option)
624 ** any later version.
626 ** GNU CC is distributed in the hope that it will be useful,
627 ** but WITHOUT ANY WARRANTY; without even the implied warranty of
628 ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
629 ** GNU General Public License for more details.
631 ** You should have received a copy of the GNU General Public License
632 ** along with GNU CC; see the file COPYING. If not, write to
633 ** the Free Software Foundation, 59 Temple Place - Suite 330,
634 ** Boston, MA 02111-1307, USA.
638 ** Return the absolutized filename for the given relative
639 ** filename. Note that if that filename is already absolute, it may
640 ** still be returned in a modified form because this routine also
641 ** eliminates redundant slashes and single dots and eliminates double
642 ** dots to get a shortest possible filename from the given input
643 ** filename. The absolutization of relative filenames is made by
644 ** assuming that the given filename is to be taken as relative to
645 ** the first argument (cwd) or to the current directory if cwd is
649 /* A pointer to the current directory filename (used by abspath). */
650 static /*@only@*/ cstring osd_cwd
= cstring_undefined
;
652 static void osd_setWorkingDirectory (void)
654 # if !(defined (WIN32))
655 char *buf
= dmalloc (sizeof (*buf
) * MAXPATHLEN
);
656 char *cwd
= getcwd (buf
, MAXPATHLEN
);
658 llassert (cstring_isUndefined (osd_cwd
));
662 lldiagmsg (message ("Cannot get working directory: %s\n",
663 lldecodeerror (errno
)));
664 osd_cwd
= cstring_makeLiteral ("<missing directory>");
668 osd_pathMakeNative (cwd
);
669 osd_cwd
= cstring_fromCharsNew (cwd
);
674 ; /* Don't know how to do this for non-POSIX platforms */
678 void osd_initMod (void)
680 osd_setWorkingDirectory ();
683 void osd_destroyMod (void)
685 cstring_free (osd_cwd
);
686 osd_cwd
= cstring_undefined
;
689 cstring
osd_absolutePath (cstring filename
)
691 # if !(defined (WIN32))
693 char *endp
, *outp
, *inp
;
696 llassert (cstring_isDefined (osd_cwd
));
697 llassert (cstring_isDefined (filename
));
699 abs_buffer
= (char *) dmalloc (cstring_length (osd_cwd
) + cstring_length (filename
) + 2);
703 ** Copy the filename (possibly preceded by the current working
704 ** directory name) into the absolutization buffer.
710 if (!osd_pathIsAbsolute (filename
))
714 while ((*endp
++ = *src_p
++) != '\0')
719 *(endp
-1) = CONNECTCHAR
; /* overwrite null */
724 while ((*endp
++ = *src_p
++) != '\0')
730 /* Now make a copy of abs_buffer into abs_buffer, shortening the
731 filename (by taking out slashes and dots) as we go. */
733 outp
= inp
= abs_buffer
;
734 *outp
++ = *inp
++; /* copy first slash */
735 # if defined (apollo)
737 *outp
++ = *inp
++; /* copy second slash */
745 else if (osd_isConnectChar (inp
[0]) && osd_isConnectChar (outp
[-1]))
750 else if (inp
[0] == '.' && osd_isConnectChar (outp
[-1]))
756 else if (osd_isConnectChar (inp
[1]))
761 else if ((inp
[1] == '.')
762 && (inp
[2] == '\0' || osd_isConnectChar (inp
[2])))
764 inp
+= (osd_isConnectChar (inp
[2])) ? 3 : 2;
767 while (outp
>= abs_buffer
&& !osd_isConnectChar (*outp
))
772 if (outp
< abs_buffer
)
774 /* Catch cases like /.. where we try to backup to a
775 point above the absolute root of the logical file
778 llfatalbug (message ("Invalid file name: %s", filename
));
797 /* On exit, make sure that there is a trailing null, and make sure that
798 the last character of the returned string is *not* a slash. */
801 if (osd_isConnectChar (outp
[-1]))
804 /*@noaccess cstring@*/
805 return cstring_fromChars (abs_buffer
);
807 DPRINTF (("Here: %s", filename
));
808 return cstring_copy (filename
);
813 ** Given a filename (and possibly a directory name from which the filename
814 ** is relative) return a string which is the shortest possible
815 ** equivalent for the corresponding full (absolutized) filename. The
816 ** shortest possible equivalent may be constructed by converting the
817 ** absolutized filename to be a relative filename (i.e. relative to
818 ** the actual current working directory). However if a relative filename
819 ** is longer, then the full absolute filename is returned.
821 ** KNOWN BUG: subpart of the original filename is actually a symbolic link.
823 ** this is really horrible code...surely someone has written a less buggy version of this!
826 cstring
osd_outputPath (cstring filename
)
828 # if !(defined (WIN32))
831 cstring cwd_p
= osd_cwd
;
833 int unmatched_slash_count
= 0;
834 size_t filename_len
= cstring_length (filename
);
836 llassertretval (filename_len
> 0, filename
);
840 rel_buffer
= (char *) dmalloc (filename_len
);
841 rel_buf_p
= rel_buffer
;
846 /* Need to prevent recursive assertion failures */
847 return cstring_copy (filename
);
850 llassert (cwd_p
!= NULL
);
851 llassert (path_p
!= NULL
);
853 while ((*cwd_p
!= '\0') && (*cwd_p
== *path_p
))
859 if ((*cwd_p
== '\0') && (*path_p
== '\0' || osd_isConnectChar (*path_p
))) /* whole pwd matched */
861 if (*path_p
== '\0') /* input *is* the current path! */
863 cstring_free (rel_buffer
);
864 return cstring_makeLiteral (".");
868 cstring_free (rel_buffer
);
869 return cstring_fromCharsNew (path_p
+ 1);
875 /* evans 2002-02-05 This is horrible code, which I've removed. I couldn't
876 ** find any test cases that need it, so I hope I'm not breaking anything.
879 /* drl 2002-10/14 I had to put this code back.
880 ** The case that needs it is when splint is given an absolute path name of
881 ** a file outside of the current directory and the subdirectories below the
882 ** current directory. e.g. cd /home/; splint /tmp/prog.c
890 while (cwd_p
>= osd_cwd
&& !osd_isConnectChar (*cwd_p
)) /* backup to last slash */
897 unmatched_slash_count
++;
900 /* Find out how many directory levels in cwd were *not* matched. */
901 while (*cwd_p
!= '\0')
903 if (osd_isConnectChar (*cwd_p
++))
904 unmatched_slash_count
++;
907 /* Now we know how long the "short name" will be.
908 Reject it if longer than the input. */
909 if (unmatched_slash_count
* 3 + strlen (path_p
) >= filename_len
)
911 cstring_free (rel_buffer
);
912 /* fprintf (stderr, "Returning filename: %s [%p]\n", filename); */
913 return cstring_copy (filename
);
917 /* For each of them, put a `../' at the beginning of the short name. */
918 while (unmatched_slash_count
-- > 0)
920 /* Give up if the result gets to be longer
921 than the absolute path name. */
922 char * temp_rel_buf_p
;
924 /*drl This comment is necessary because for some reason Splint
925 does not realize that the pasts where rel_buf_p is released
928 temp_rel_buf_p
= rel_buf_p
;
931 if (rel_buffer
+ filename_len
<= temp_rel_buf_p
+ 3)
934 return cstring_copy (filename
);
939 *rel_buf_p
++ = CONNECTCHAR
;
942 /* Then tack on the unmatched part of the desired file's name. */
946 if (rel_buffer
+ filename_len
<= rel_buf_p
)
948 cstring_free (rel_buffer
);
949 return cstring_copy (filename
);
952 while ((*rel_buf_p
++ = *path_p
++) != '\0') ;
955 /*@=usereleased@*/ /* Splint limitation: shouldn't need these */
958 if (osd_isConnectChar (*(rel_buf_p
-1)))
961 /* fprintf (stderr, "Returning buffer: %s [%p]\n", rel_buffer, rel_buffer); */
964 /*@noaccess cstring@*/
966 return cstring_copy (filename
);
970 cstring
osd_getCurrentDirectory (void)
972 # if defined(WIN32) || defined(OS2)
973 return cstring_makeLiteralTemp ("");
975 return cstring_makeLiteralTemp ("./");
980 int osd_openForReading (const char *pathname
)
982 return open(pathname
, O_RDONLY
, S_IRWALL
);
985 /* Read LEN bytes at PTR from descriptor DESC, retrying if necessary.
986 Return a negative value if an error occurs, otherwise return the
987 actual number of bytes read, which must be LEN unless end-of-file
990 int osd_readSafe (int desc
, char *ptr
, int len
)
997 /*@-compdef@*/ /* ptr is an out parameter */
998 int nchars
= _read (desc
, ptr
, (unsigned) left
);
1001 int nchars
= (int) read (desc
, ptr
, size_fromInt (left
));
1006 # if defined (EINTR)
1024 int osd_close(int fid
)
1030 FILE *osd_createTmpFile (cstring fname
, bool read
)
1036 flags
= (read
? O_RDWR
: O_WRONLY
) | O_CREAT
| O_TRUNC
| O_EXCL
;
1037 fdesc
= open (cstring_toCharsSafe (fname
), flags
, S_IRUSR
| S_IWUSR
);
1040 osd_setTempError ();
1043 res
= fdopen (fdesc
, read
? "w+" : "w");
1046 DPRINTF (("Error opening: %s", fname
));
1047 osd_setTempError ();
1051 DPRINTF (("Opening file: %s / %p", fname
, res
));
1055 int osd_fcloseall(void)
1057 # if defined (WIN32)
1059 return _fcloseall ();
1067 ** Get the file-mode and data size of the file open on FD
1068 ** and store them in *MODE_POINTER and *SIZE_POINTER.
1072 osd_file_mode_and_size (int fd
, filemode
*mode_pointer
, size_t *size_pointer
)
1076 if (fstat (fd
, &sbuf
) < 0) {
1079 /*@-compdestroy@*/ /* possibly spurious warnings here (or memory leak) */
1084 if (mode_pointer
!= NULL
)
1086 if (S_ISREG (sbuf
.st_mode
))
1088 *mode_pointer
= OSD_MODEREGULAR
;
1090 else if (S_ISDIR (sbuf
.st_mode
))
1092 *mode_pointer
= OSD_MODEDIRECTORY
;
1096 *mode_pointer
= OSD_MODEOTHER
;
1100 if (size_pointer
!= NULL
)
1102 *size_pointer
= (size_t) sbuf
.st_size
;
1105 /*@-compdestroy@*/ /* possibly spurious warnings here (or memory leak) */
1110 bool osd_pathIsAbsolute (const char* pathname
)
1112 llassert (pathname
!= NULL
&& *pathname
!= '\0');
1114 return (osd_isConnectChar (*pathname
)
1115 # if defined (WIN32) || defined (OS2)
1116 || (isalpha(*pathname
) && *(pathname
+ 1) == DRIVECONNECTCHAR
)
1121 void osd_pathMakePosix (char *pathname
)
1123 #if defined (WIN32) || defined (OS2)
1124 cstring_replaceAll (fname
, CONNECTCHAR
, ALTCONNECTCHAR
);
1128 void osd_pathMakeNative (char *pathname
)
1130 #if defined (WIN32) || defined (OS2)
1131 cstring_replaceAll (fname
, ALTCONNECTCHAR
, CONNECTCHAR
);
1135 char* osd_pathBase (char *path
)
1139 base
= strrchr (path
, CONNECTCHAR
);
1140 # if defined (OS2) || defined (WIN32)
1142 char *altbase
= strrchr (path
, ALTCONNECTCHAR
);
1143 if (altbase
!= NULL
&& (base
== NULL
|| (altbase
> base
)))
1156 ++base
; /* skip found char */
1163 cstring
osd_getTempDir(void)
1165 # if defined (WIN32) || defined (OS2)
1167 env
= getenv ("TMP");
1170 env
= getenv ("TEMP");
1174 return cstring_makeLiteral (env
);
1178 return cstring_makeLiteral (DEFAULT_TMPDIR
);
1181 cstring
osd_removePreDirs (cstring s
)
1183 /*@access cstring@*/
1185 llassert (cstring_isDefined (s
));
1187 while (*s
== '.' && *(s
+ 1) == CONNECTCHAR
)
1193 /* remove remainders from double path delimiters... */
1194 while (*s
== CONNECTCHAR
)
1201 /*@noaccess cstring@*/
1204 bool osd_pathHasDir(const char* pathname
)
1206 return strchr (pathname
, CONNECTCHAR
) != NULL
1207 # if defined (OS2) || defined (WIN32)
1208 || strchr (pathname
, ALTCONNECTCHAR
) != NULL