]>
git.proxmox.com Git - ceph.git/blob - ceph/src/boost/tools/build/src/engine/pathnt.cpp
2 * Copyright 1993-2002 Christopher Seiwald and Perforce Software, Inc.
4 * This file is part of Jam - see jam.c for Copyright information.
8 * Copyright 2001-2004 David Abrahams.
9 * Copyright 2005 Rene Rivera.
10 * Distributed under the Boost Software License, Version 1.0.
11 * (See accompanying file LICENSE_1_0.txt or copy at
12 * http://www.boost.org/LICENSE_1_0.txt)
16 * pathnt.c - NT specific path manipulation support
23 #define WIN32_LEAN_AND_MEAN
27 # include <cygwin/version.h>
28 # include <sys/cygwin.h>
29 # ifdef CYGWIN_VERSION_CYGWIN_CONV
39 /* The definition of this in winnt.h is not ANSI-C compatible. */
40 #undef INVALID_FILE_ATTRIBUTES
41 #define INVALID_FILE_ATTRIBUTES ((DWORD)-1)
44 typedef struct path_key_entry
51 static struct hash
* path_key_cache
;
55 * path_get_process_id_()
58 unsigned long path_get_process_id_( void )
60 return GetCurrentProcessId();
65 * path_get_temp_path_()
68 void path_get_temp_path_( string
* buffer
)
70 DWORD pathLength
= GetTempPathA( 0, NULL
);
71 string_reserve( buffer
, pathLength
);
72 pathLength
= GetTempPathA( pathLength
, buffer
->value
);
73 buffer
->value
[ pathLength
- 1 ] = '\0';
74 buffer
->size
= pathLength
- 1;
79 * canonicWindowsPath() - convert a given path into its canonic/long format
81 * Appends the canonic path to the end of the given 'string' object.
83 * FIXME: This function is still work-in-progress as it originally did not
84 * necessarily return the canonic path format (could return slightly different
85 * results for certain equivalent path strings) and could accept paths pointing
86 * to non-existing file system entities as well.
88 * Caches results internally, automatically caching any parent paths it has to
89 * convert to their canonic format in the process.
92 * - path given in normalized form, i.e. all of its folder separators have
93 * already been converted into '\\'
94 * - path_key_cache path/key mapping cache object already initialized
97 static int canonicWindowsPath( char const * const path
, int const path_length
,
100 char const * last_element
;
101 unsigned long saved_size
;
105 /* This is only called via path_key(), which initializes the cache. */
106 assert( path_key_cache
);
111 if ( path_length
== 1 && path
[ 0 ] == '\\' )
113 string_push_back( out
, '\\' );
117 if ( path
[ 1 ] == ':' &&
118 ( path_length
== 2 ||
119 ( path_length
== 3 && path
[ 2 ] == '\\' ) ) )
121 string_push_back( out
, toupper( path
[ 0 ] ) );
122 string_push_back( out
, ':' );
123 string_push_back( out
, '\\' );
127 /* Find last '\\'. */
128 for ( p
= path
+ path_length
- 1; p
>= path
&& *p
!= '\\'; --p
);
129 last_element
= p
+ 1;
131 /* Special case '\' && 'D:\' - include trailing '\'. */
133 p
== path
+ 2 && path
[ 1 ] == ':' )
140 char const * const dir
= path
;
141 int const dir_length
= p
- path
;
142 OBJECT
* const dir_obj
= object_new_range( dir
, dir_length
);
144 path_key_entry
* const result
= (path_key_entry
*)hash_insert(
145 path_key_cache
, dir_obj
, &found
);
148 result
->path
= dir_obj
;
149 if ( canonicWindowsPath( dir
, dir_length
, out
) )
153 result
->key
= object_new( out
->value
);
157 object_free( dir_obj
);
158 string_append( out
, object_str( result
->key
) );
160 if ( !result
->exists
)
164 if ( out
->size
&& out
->value
[ out
->size
- 1 ] != '\\' )
165 string_push_back( out
, '\\' );
167 saved_size
= out
->size
;
168 string_append_range( out
, last_element
, path
+ path_length
);
170 if ( !missing_parent
)
172 char const * const n
= last_element
;
173 int const n_length
= path
+ path_length
- n
;
174 if ( !( n_length
== 1 && n
[ 0 ] == '.' )
175 && !( n_length
== 2 && n
[ 0 ] == '.' && n
[ 1 ] == '.' ) )
178 HANDLE
const hf
= FindFirstFileA( out
->value
, &fd
);
179 if ( hf
!= INVALID_HANDLE_VALUE
)
181 string_truncate( out
, saved_size
);
182 string_append( out
, fd
.cFileName
);
197 * normalize_path() - 'normalizes' the given path for the path-key mapping
199 * The resulting string has nothing to do with 'normalized paths' as used in
200 * Boost Jam build scripts and the built-in NORMALIZE_PATH rule. It is intended
201 * to be used solely as an intermediate step when mapping an arbitrary path to
202 * its canonical representation.
204 * When choosing the intermediate string the important things are for it to be
205 * inexpensive to calculate and any two paths having different canonical
206 * representations also need to have different calculated intermediate string
207 * representations. Any implemented additional rules serve only to simplify
208 * constructing the canonical path representation from the calculated
209 * intermediate string.
211 * Implemented returned path rules:
212 * - use backslashes as path separators
213 * - lowercase only (since all Windows file systems are case insensitive)
214 * - trim trailing path separator except in case of a root path, i.e. 'X:\'
217 static void normalize_path( string
* path
)
220 for ( s
= path
->value
; s
< path
->value
+ path
->size
; ++s
)
221 *s
= *s
== '/' ? '\\' : tolower( *s
);
222 /* Strip trailing "/". */
223 if ( path
->size
&& path
->size
!= 3 && path
->value
[ path
->size
- 1 ] == '\\'
225 string_pop_back( path
);
229 static path_key_entry
* path_key( OBJECT
* const path
,
230 int const known_to_be_canonic
)
232 path_key_entry
* result
;
235 if ( !path_key_cache
)
236 path_key_cache
= hashinit( sizeof( path_key_entry
), "path to key" );
238 result
= (path_key_entry
*)hash_insert( path_key_cache
, path
, &found
);
243 path_key_entry
* nresult
;
247 string_copy( buf
, object_str( path
) );
248 normalize_path( buf
);
249 normalized
= object_new( buf
->value
);
250 normalized_size
= buf
->size
;
253 nresult
= (path_key_entry
*)hash_insert( path_key_cache
, normalized
,
255 if ( !found
|| nresult
== result
)
257 nresult
->path
= normalized
;
258 if ( known_to_be_canonic
)
260 nresult
->key
= object_copy( path
);
265 string canonic_path
[ 1 ];
266 string_new( canonic_path
);
267 if ( canonicWindowsPath( object_str( normalized
), normalized_size
,
272 nresult
->key
= object_new( canonic_path
->value
);
273 string_free( canonic_path
);
277 object_free( normalized
);
278 if ( nresult
!= result
)
280 result
->path
= object_copy( path
);
281 result
->key
= object_copy( nresult
->key
);
282 result
->exists
= nresult
->exists
;
291 * translate_path_cyg2win() - conversion of a cygwin to a Windows path.
297 static int translate_path_cyg2win( string
* path
)
301 #ifdef CYGWIN_VERSION_CYGWIN_CONV
302 /* Use new Cygwin API added with Cygwin 1.7. Old one had no error
303 * handling and has been deprecated.
305 char * dynamicBuffer
= 0;
306 char buffer
[ MAX_PATH
+ 1001 ];
307 char const * result
= buffer
;
308 cygwin_conv_path_t
const conv_type
= CCP_POSIX_TO_WIN_A
| CCP_RELATIVE
;
309 ssize_t
const apiResult
= cygwin_conv_path( conv_type
, path
->value
,
310 buffer
, sizeof( buffer
) / sizeof( *buffer
) );
311 assert( apiResult
== 0 || apiResult
== -1 );
312 assert( apiResult
|| strlen( result
) < sizeof( buffer
) / sizeof(
317 if ( errno
== ENOSPC
)
319 ssize_t
const size
= cygwin_conv_path( conv_type
, path
->value
,
321 assert( size
>= -1 );
324 dynamicBuffer
= (char *)BJAM_MALLOC_ATOMIC( size
);
327 ssize_t
const apiResult
= cygwin_conv_path( conv_type
,
328 path
->value
, dynamicBuffer
, size
);
329 assert( apiResult
== 0 || apiResult
== -1 );
332 result
= dynamicBuffer
;
333 assert( strlen( result
) < size
);
339 #else /* CYGWIN_VERSION_CYGWIN_CONV */
340 /* Use old Cygwin API deprecated with Cygwin 1.7. */
341 char result
[ MAX_PATH
+ 1 ];
342 cygwin_conv_to_win32_path( path
->value
, result
);
343 assert( strlen( result
) <= MAX_PATH
);
344 #endif /* CYGWIN_VERSION_CYGWIN_CONV */
348 string_truncate( path
, 0 );
349 string_append( path
, result
);
353 #ifdef CYGWIN_VERSION_CYGWIN_CONV
355 BJAM_FREE( dynamicBuffer
);
360 #endif /* OS_CYGWIN */
364 * path_translate_to_os_()
367 int path_translate_to_os_( char const * f
, string
* file
)
371 /* by default, pass on the original path */
372 string_copy( file
, f
);
375 translated
= translate_path_cyg2win( file
);
382 void path_register_key( OBJECT
* canonic_path
)
384 path_key( canonic_path
, 1 );
388 OBJECT
* path_as_key( OBJECT
* path
)
390 return object_copy( path_key( path
, 0 )->key
);
394 static void free_path_key_entry( void * xentry
, void * const data
)
396 path_key_entry
* const entry
= (path_key_entry
*)xentry
;
397 object_free( entry
->path
);
398 object_free( entry
->key
);
402 void path_done( void )
404 if ( path_key_cache
)
406 hashenumerate( path_key_cache
, &free_path_key_entry
, 0 );
407 hashdone( path_key_cache
);