]> git.proxmox.com Git - ceph.git/blob - ceph/src/boost/tools/build/src/engine/pathsys.c
Add patch for failing prerm scripts
[ceph.git] / ceph / src / boost / tools / build / src / engine / pathsys.c
1 /*
2 * Copyright 1993-2002 Christopher Seiwald and Perforce Software, Inc.
3 *
4 * This file is part of Jam - see jam.c for Copyright information.
5 */
6
7 /* This file is ALSO:
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)
13 */
14
15 /*
16 * pathsys.c - platform independent path manipulation support
17 *
18 * External routines:
19 * path_build() - build a filename given dir/base/suffix/member
20 * path_parent() - make a PATHNAME point to its parent dir
21 * path_parse() - split a file name into dir/base/suffix/member
22 * path_tmpdir() - returns the system dependent temporary folder path
23 * path_tmpfile() - returns a new temporary path
24 * path_tmpnam() - returns a new temporary name
25 *
26 * File_parse() and path_build() just manipulate a string and a structure;
27 * they do not make system calls.
28 */
29
30 #include "jam.h"
31 #include "pathsys.h"
32
33 #include "filesys.h"
34
35 #include <stdlib.h>
36 #include <time.h>
37
38
39 /* Internal OS specific implementation details - have names ending with an
40 * underscore and are expected to be implemented in an OS specific pathXXX.c
41 * module.
42 */
43 unsigned long path_get_process_id_( void );
44 void path_get_temp_path_( string * buffer );
45 int path_translate_to_os_( char const * f, string * file );
46
47
48 /*
49 * path_parse() - split a file name into dir/base/suffix/member
50 */
51
52 void path_parse( char const * file, PATHNAME * f )
53 {
54 char const * p;
55 char const * q;
56 char const * end;
57
58 memset( (char *)f, 0, sizeof( *f ) );
59
60 /* Look for '<grist>'. */
61
62 if ( ( file[ 0 ] == '<' ) && ( p = strchr( file, '>' ) ) )
63 {
64 f->f_grist.ptr = file;
65 f->f_grist.len = p - file;
66 file = p + 1;
67 }
68
69 /* Look for 'dir/'. */
70
71 p = strrchr( file, '/' );
72
73 #if PATH_DELIM == '\\'
74 /* On NT, look for dir\ as well */
75 {
76 char * const p1 = strrchr( p ? p + 1 : file, '\\' );
77 if ( p1 ) p = p1;
78 }
79 #endif
80
81 if ( p )
82 {
83 f->f_dir.ptr = file;
84 f->f_dir.len = p - file;
85
86 /* Special case for / - dirname is /, not "" */
87 if ( !f->f_dir.len )
88 ++f->f_dir.len;
89
90 #if PATH_DELIM == '\\'
91 /* Special case for D:/ - dirname is D:/, not "D:" */
92 if ( f->f_dir.len == 2 && file[ 1 ] == ':' )
93 ++f->f_dir.len;
94 #endif
95
96 file = p + 1;
97 }
98
99 end = file + strlen( file );
100
101 /* Look for '(member)'. */
102 if ( ( p = strchr( file, '(' ) ) && ( end[ -1 ] == ')' ) )
103 {
104 f->f_member.ptr = p + 1;
105 f->f_member.len = end - p - 2;
106 end = p;
107 }
108
109 /* Look for '.suffix'. This would be memrchr(). */
110 p = 0;
111 for ( q = file; ( q = (char *)memchr( q, '.', end - q ) ); ++q )
112 p = q;
113 if ( p )
114 {
115 f->f_suffix.ptr = p;
116 f->f_suffix.len = end - p;
117 end = p;
118 }
119
120 /* Leaves base. */
121 f->f_base.ptr = file;
122 f->f_base.len = end - file;
123 }
124
125
126 /*
127 * is_path_delim() - true iff c is a path delimiter
128 */
129
130 static int is_path_delim( char const c )
131 {
132 return c == PATH_DELIM
133 #if PATH_DELIM == '\\'
134 || c == '/'
135 #endif
136 ;
137 }
138
139
140 /*
141 * as_path_delim() - convert c to a path delimiter if it is not one already
142 */
143
144 static char as_path_delim( char const c )
145 {
146 return is_path_delim( c ) ? c : PATH_DELIM;
147 }
148
149
150 /*
151 * path_build() - build a filename given dir/base/suffix/member
152 *
153 * To avoid changing slash direction on NT when reconstituting paths, instead of
154 * unconditionally appending PATH_DELIM we check the past-the-end character of
155 * the previous path element. If it is a path delimiter, we append that, and
156 * only append PATH_DELIM as a last resort. This heuristic is based on the fact
157 * that PATHNAME objects are usually the result of calling path_parse, which
158 * leaves the original slashes in the past-the-end position. Correctness depends
159 * on the assumption that all strings are zero terminated, so a past-the-end
160 * character will always be available.
161 *
162 * As an attendant patch, we had to ensure that backslashes are used explicitly
163 * in 'timestamp.c'.
164 */
165
166 void path_build( PATHNAME * f, string * file )
167 {
168 int check_f;
169 int check_f_pos;
170
171 file_build1( f, file );
172
173 /* Do not prepend root if it is '.' or the directory is rooted. */
174 check_f = (f->f_root.len
175 && !( f->f_root.len == 1 && f->f_root.ptr[ 0 ] == '.')
176 && !( f->f_dir.len && f->f_dir.ptr[ 0 ] == '/' ));
177 #if PATH_DELIM == '\\'
178 check_f = (check_f
179 && !( f->f_dir.len && f->f_dir.ptr[ 0 ] == '\\' )
180 && !( f->f_dir.len && f->f_dir.ptr[ 1 ] == ':' ));
181 #endif
182 if (check_f)
183 {
184 string_append_range( file, f->f_root.ptr, f->f_root.ptr + f->f_root.len
185 );
186 /* If 'root' already ends with a path delimeter, do not add another one.
187 */
188 if ( !is_path_delim( f->f_root.ptr[ f->f_root.len - 1 ] ) )
189 string_push_back( file, as_path_delim( f->f_root.ptr[ f->f_root.len
190 ] ) );
191 }
192
193 if ( f->f_dir.len )
194 string_append_range( file, f->f_dir.ptr, f->f_dir.ptr + f->f_dir.len );
195
196 /* Put path separator between dir and file. */
197 /* Special case for root dir: do not add another path separator. */
198 check_f_pos = (f->f_dir.len && ( f->f_base.len || f->f_suffix.len ));
199 #if PATH_DELIM == '\\'
200 check_f_pos = (check_f_pos && !( f->f_dir.len == 3 && f->f_dir.ptr[ 1 ] == ':' ));
201 #endif
202 check_f_pos = (check_f_pos && !( f->f_dir.len == 1 && is_path_delim( f->f_dir.ptr[ 0 ])));
203 if (check_f_pos)
204 string_push_back( file, as_path_delim( f->f_dir.ptr[ f->f_dir.len ] ) );
205
206 if ( f->f_base.len )
207 string_append_range( file, f->f_base.ptr, f->f_base.ptr + f->f_base.len
208 );
209
210 if ( f->f_suffix.len )
211 string_append_range( file, f->f_suffix.ptr, f->f_suffix.ptr +
212 f->f_suffix.len );
213
214 if ( f->f_member.len )
215 {
216 string_push_back( file, '(' );
217 string_append_range( file, f->f_member.ptr, f->f_member.ptr +
218 f->f_member.len );
219 string_push_back( file, ')' );
220 }
221 }
222
223
224 /*
225 * path_parent() - make a PATHNAME point to its parent dir
226 */
227
228 void path_parent( PATHNAME * f )
229 {
230 f->f_base.ptr = f->f_suffix.ptr = f->f_member.ptr = "";
231 f->f_base.len = f->f_suffix.len = f->f_member.len = 0;
232 }
233
234
235 /*
236 * path_tmpdir() - returns the system dependent temporary folder path
237 *
238 * Returned value is stored inside a static buffer and should not be modified.
239 * Returned value does *not* include a trailing path separator.
240 */
241
242 string const * path_tmpdir()
243 {
244 static string buffer[ 1 ];
245 static int have_result;
246 if ( !have_result )
247 {
248 string_new( buffer );
249 path_get_temp_path_( buffer );
250 have_result = 1;
251 }
252 return buffer;
253 }
254
255
256 /*
257 * path_tmpnam() - returns a new temporary name
258 */
259
260 OBJECT * path_tmpnam( void )
261 {
262 char name_buffer[ 64 ];
263 unsigned long const pid = path_get_process_id_();
264 static unsigned long t;
265 if ( !t ) t = time( 0 ) & 0xffff;
266 t += 1;
267 sprintf( name_buffer, "jam%lx%lx.000", pid, t );
268 return object_new( name_buffer );
269 }
270
271
272 /*
273 * path_tmpfile() - returns a new temporary path
274 */
275
276 OBJECT * path_tmpfile( void )
277 {
278 OBJECT * result;
279 OBJECT * tmpnam;
280
281 string file_path[ 1 ];
282 string_copy( file_path, path_tmpdir()->value );
283 string_push_back( file_path, PATH_DELIM );
284 tmpnam = path_tmpnam();
285 string_append( file_path, object_str( tmpnam ) );
286 object_free( tmpnam );
287 result = object_new( file_path->value );
288 string_free( file_path );
289
290 return result;
291 }
292
293
294 /*
295 * path_translate_to_os() - translate filename to OS-native path
296 *
297 */
298
299 int path_translate_to_os( char const * f, string * file )
300 {
301 return path_translate_to_os_( f, file );
302 }