1 /* Support Cygwin paths under MinGW.
2 Copyright (C) 2006 Free Software Foundation, Inc.
3 Written by CodeSourcery.
5 This file is part of the libiberty library.
6 Libiberty is free software; you can redistribute it and/or modify it
7 under the terms of the GNU Library General Public License as published
8 by the Free Software Foundation; either version 2 of the License, or
9 (at your option) any later version.
11 Libiberty is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 Library General Public License for more details.
16 You should have received a copy of the GNU Library General Public
17 License along with libiberty; see the file COPYING.LIB. If not, write
18 to the Free Software Foundation, Inc., 51 Franklin Street - Fifth
19 Floor, Boston, MA 02110-1301, USA. */
25 #include <sys/types.h>
30 #include "libiberty.h"
32 /* If non-zero, we have attempted to use cygpath. CYGPATH_PEX may
33 still be NULL, if cygpath is unavailable. */
34 static int cygpath_initialized
;
36 /* If non-NULL, an instance of cygpath connected via a pipe. */
37 static struct pex_obj
*cygpath_pex
;
39 /* The input to cygpath. */
40 static FILE *cygpath_in
;
42 /* The output from cygpath. */
43 static FILE *cygpath_out
;
45 /* CYG_PATH is a pointer to a Cygwin path. This function converts the
46 Cygwin path to a Windows path, storing the result in
47 WIN32_PATH. Returns true if the conversion was successful; false
50 cygpath (const char *cyg_path
, char win32_path
[MAX_PATH
+ 1])
54 if (!cygpath_initialized
)
56 const char *argv
[] = { "cygpath", "-w", "-f", "-", NULL
};
57 const char *cygpath_path
;
60 /* If we are unable to invoke cygpath, we do not want to try
61 again. So, we set the initialized flag at this point; if
62 errors occur during the invocation, it will remain set. */
63 cygpath_initialized
= 1;
64 /* Check to see if the user wants cygpath support. */
65 cygpath_path
= getenv ("CYGPATH");
67 /* The user doesn't need to support Cygwin paths. */
69 /* If the environment variable is set to a non-empty string, use
70 that string as the path to cygpath. */
71 if (cygpath_path
[0] != '\0')
72 argv
[0] = cygpath_path
;
73 /* Create the pex object. */
74 cygpath_pex
= pex_init (PEX_SEARCH
| PEX_USE_PIPES
,
78 /* Get the FILE we will use to write to the child. */
79 cygpath_in
= pex_write_input (cygpath_pex
, /*binary=*/0);
82 /* Start the child process. */
83 if (pex_run (cygpath_pex
, PEX_SEARCH
| PEX_USE_PIPES
,
84 argv
[0], (char**) argv
,
88 /* Get the FILE we will use to read from the child. */
89 cygpath_out
= pex_read_output (cygpath_pex
, /*binary=*/1);
93 else if (!cygpath_pex
)
94 /* We previously tried to use cygpath, but something went wrong. */
97 /* Write CYG_PATH to the child, on a line by itself. */
98 if (fprintf (cygpath_in
, "%s\n", cyg_path
) < 0)
100 /* Flush the output. (We cannot set the stream into line-buffered
101 mode with setvbuf because Windows treats _IOLBF as a synonym for
104 /* Read the output. */
109 if (!fgets (win32_path
, MAX_PATH
, cygpath_out
))
111 pathlen
= strlen (win32_path
);
112 if (pathlen
== 0 && ok
)
113 /* This isn't a well-formed response from cygpath. */
115 if (win32_path
[pathlen
- 1] == '\n')
117 win32_path
[pathlen
- 1] = '\0';
120 /* We didn't reach the end of the line. There's no point in
121 trying to use this output, since we know the length of
122 paths are limited to MAX_PATH characters, but we read the
123 entire line so that we are still in sync with
132 /* Free resources. */
135 fclose (cygpath_out
);
145 pex_free (cygpath_pex
);
152 /* Returns the handle for the MVCRT DLL, or NULL if it is not
157 static HANDLE dll
= INVALID_HANDLE_VALUE
;
159 /* After we call LoadLibrary, DLL will be either a valid handle or
160 NULL, so this check ensures that we only try to load the library
162 if (dll
== INVALID_HANDLE_VALUE
)
163 dll
= LoadLibrary ("msvcrt.dll");
168 /* Call the underlying MSVCRT fopen with PATH and MODE, and return
171 msvcrt_fopen (const char *path
, const char *mode
)
173 typedef FILE *(fopen_type
)(const char *path
,
176 static fopen_type
*f
= NULL
;
178 /* Get the address of "fopen". */
181 HANDLE dll
= msvcrt_dll ();
187 f
= (fopen_type
*) GetProcAddress (dll
, "fopen");
196 return (*f
)(path
, mode
);
200 fopen (const char *path
, const char *mode
)
203 char win32_path
[MAX_PATH
+ 1];
205 /* Assume PATH is a Windows path. */
206 f
= msvcrt_fopen (path
, mode
);
207 if (f
|| errno
!= ENOENT
)
209 /* Perhaps it is a Cygwin path? */
210 if (cygpath (path
, win32_path
))
211 f
= msvcrt_fopen (win32_path
, mode
);
216 open (const char *path
, int oflag
, ...)
219 char win32_path
[MAX_PATH
+ 1];
222 if ((oflag
& _O_CREAT
))
225 va_start (ap
, oflag
);
226 pmode
= va_arg (ap
, int);
230 /* Assume PATH is a Windows path. */
231 fd
= _open (path
, oflag
, pmode
);
232 if (fd
!= -1 || errno
!= ENOENT
)
234 /* Perhaps it is a Cygwin path? */
235 if (cygpath (path
, win32_path
))
236 fd
= _open (win32_path
, oflag
, pmode
);
241 stat (const char *path
, struct stat
*buffer
)
244 char win32_path
[MAX_PATH
+ 1];
246 /* Assume PATH is a Windows path. */
247 r
= _stat (path
, (struct _stat
*) buffer
);
248 if (r
!= -1 || errno
!= ENOENT
)
250 /* Perhaps it is a Cygwin path? */
251 if (cygpath (path
, win32_path
))
252 r
= _stat (win32_path
, (struct _stat
*) buffer
);
257 access (const char *path
, int mode
)
260 char win32_path
[MAX_PATH
+ 1];
262 /* Assume PATH is a Windows path. */
263 r
= _access (path
, mode
);
264 if (r
!= -1 || errno
!= ENOENT
)
266 /* Perhaps it is a Cygwin path? */
267 if (cygpath (path
, win32_path
))
268 r
= _access (win32_path
, mode
);