1 /* $Id: path.c,v 1.2 2002/02/20 09:17:57 hyperion Exp $
4 * COPYRIGHT: See COPYING in the top level directory
5 * PROJECT: ReactOS POSIX+ Subsystem
6 * FILE: subsys/psx/lib/psxdll/misc/path.c
7 * PURPOSE: POSIX subsystem path utilities
8 * PROGRAMMER: KJK::Hyperion <noog@libero.it>
13 #include <ddk/ntddk.h>
16 #include <psx/stdlib.h>
17 #include <psx/pdata.h>
21 __PdxPosixPathGetNextComponent_U
23 IN UNICODE_STRING PathName
,
24 IN OUT PUNICODE_STRING PathComponent
,
25 OUT PBOOLEAN TrailingDelimiter OPTIONAL
29 USHORT l
= PathName
.Length
/ sizeof(WCHAR
);
31 if(PathComponent
->Buffer
== 0)
34 i
= ((ULONG
)PathComponent
->Buffer
- (ULONG
)PathName
.Buffer
+ PathComponent
->Length
) / sizeof(WCHAR
);
36 /* skip leading empty components */
40 PathComponent
->Length
= PathComponent
->MaximumLength
= 0;
43 else if(IS_CHAR_DELIMITER_U(PathName
.Buffer
[i
]))
50 PathComponent
->Length
= PathComponent
->MaximumLength
= 0;
54 PathComponent
->Buffer
= &PathName
.Buffer
[i
];
58 /* advance until the end of the string, or the next delimiter */
64 if(TrailingDelimiter
!= 0)
65 *TrailingDelimiter
= FALSE
;
69 else if (IS_CHAR_DELIMITER_U(PathName
.Buffer
[j
]))
72 if(TrailingDelimiter
!= 0)
73 *TrailingDelimiter
= TRUE
;
81 PathComponent
->Length
= PathComponent
->MaximumLength
= (j
- i
) * sizeof(WCHAR
);
88 __PdxPosixPathResolve_U
90 IN UNICODE_STRING PathName
,
91 OUT PUNICODE_STRING ResolvedPathName
,
92 IN WCHAR PathDelimiter OPTIONAL
95 UNICODE_STRING wstrThisComponent
= {0, 0, NULL
};
100 if(PathDelimiter
== 0)
101 PathDelimiter
= L
'/';
103 /* start from the beginning of the return buffer */
104 pwcCurPos
= ResolvedPathName
->Buffer
;
106 /* path begins with a delimiter (absolute path) */
107 if(IS_CHAR_DELIMITER_U(PathName
.Buffer
[0]))
109 /* put a delimiter in front of the return buffer */
110 *pwcCurPos
= PathDelimiter
;
111 /* move to next character */
115 pwcStartPos
= pwcCurPos
;
117 /* repeat until the end of the path string */
118 while(__PdxPosixPathGetNextComponent_U(PathName
, &wstrThisComponent
, &bIsDirectory
))
121 if(IS_COMPONENT_DOT_U(wstrThisComponent
))
123 /* "..": go back to the last component */
124 else if(IS_COMPONENT_DOTDOT_U(wstrThisComponent
))
126 if(pwcCurPos
== pwcStartPos
)
129 /* skip the last (undefined) character */
131 /* down to the previous path delimiter */
132 do{ pwcCurPos
--; }while(!IS_CHAR_DELIMITER_U(*pwcCurPos
));
133 /* include the delimiter */
138 /* copy this component into the return string */
142 wstrThisComponent
.Buffer
,
143 wstrThisComponent
.Length
146 /* move the current position to the end of the string */
147 pwcCurPos
= (PWCHAR
)((PBYTE
)pwcCurPos
+ wstrThisComponent
.Length
);
149 /* component had a trailing delimiter */
152 /* append a delimiter */
153 *pwcCurPos
= PathDelimiter
;
154 /* on to next character */
160 /* set the return string's length as the byte offset between the initial buffer
161 position and the current position */
162 ResolvedPathName
->Length
= ((ULONG
)pwcCurPos
- (ULONG
)ResolvedPathName
->Buffer
);
169 __PdxPosixPathGetNextComponent_A
171 IN ANSI_STRING PathName
,
172 IN OUT PANSI_STRING PathComponent
,
173 OUT PBOOLEAN TrailingDelimiter OPTIONAL
178 if(PathComponent
->Buffer
== 0)
181 i
= ((ULONG
)PathComponent
->Buffer
- (ULONG
)PathName
.Buffer
+ PathComponent
->Length
);
183 /* skip leading empty components */
185 if(i
>= PathName
.Length
)
187 PathComponent
->Length
= PathComponent
->MaximumLength
= 0;
190 else if(IS_CHAR_DELIMITER_A(PathName
.Buffer
[i
]))
195 if(i
> PathName
.Length
)
197 PathComponent
->Length
= PathComponent
->MaximumLength
= 0;
201 PathComponent
->Buffer
= &PathName
.Buffer
[i
];
205 /* advance until the end of the string, or the next delimiter */
208 if(j
>= PathName
.Length
)
211 if(TrailingDelimiter
!= 0)
212 *TrailingDelimiter
= FALSE
;
216 else if (IS_CHAR_DELIMITER_A(PathName
.Buffer
[j
]))
219 if(TrailingDelimiter
!= 0)
220 *TrailingDelimiter
= TRUE
;
228 PathComponent
->Length
= PathComponent
->MaximumLength
= j
- i
;
235 __PdxPosixPathResolve_A
237 IN ANSI_STRING PathName
,
238 OUT PANSI_STRING ResolvedPathName
,
239 IN CHAR PathDelimiter OPTIONAL
242 ANSI_STRING strThisComponent
= {0, 0, NULL
};
245 BOOLEAN bIsDirectory
;
247 if(PathDelimiter
== 0)
250 /* start from the beginning of the return buffer */
251 pcCurPos
= ResolvedPathName
->Buffer
;
253 /* path begins with a delimiter (absolute path) */
254 if(IS_CHAR_DELIMITER_A(PathName
.Buffer
[0]))
256 /* put a delimiter in front of the return buffer */
257 *pcCurPos
= PathDelimiter
;
258 /* move to next character */
262 pcStartPos
= pcCurPos
;
264 /* repeat until the end of the path string */
265 while(__PdxPosixPathGetNextComponent_A(PathName
, &strThisComponent
, &bIsDirectory
))
268 if(IS_COMPONENT_DOT_A(strThisComponent
))
270 /* "..": go back to the last component */
271 else if(IS_COMPONENT_DOTDOT_A(strThisComponent
))
273 if(pcCurPos
== pcStartPos
)
276 /* skip the last (undefined) character */
278 /* down to the previous path delimiter */
279 do{ pcCurPos
--; }while(!IS_CHAR_DELIMITER_A(*pcCurPos
));
280 /* include the delimiter */
285 /* copy this component into the return string */
289 strThisComponent
.Buffer
,
290 strThisComponent
.Length
293 /* move the current position to the end of the string */
294 pcCurPos
= (PCHAR
)((PBYTE
)pcCurPos
+ strThisComponent
.Length
);
296 /* component had a trailing delimiter */
299 /* append a delimiter */
300 *pcCurPos
= PathDelimiter
;
301 /* on to next character */
307 /* set the return string's length as the byte offset between the initial buffer
308 position and the current position */
309 ResolvedPathName
->Length
= ((ULONG
)pcCurPos
- (ULONG
)ResolvedPathName
->Buffer
);
316 __PdxPosixPathNameToNtPathName
319 OUT PUNICODE_STRING NativePath
,
320 IN PUNICODE_STRING CurDir OPTIONAL
,
321 IN PUNICODE_STRING RootDir OPTIONAL
324 UNICODE_STRING wstrPosixPath
;
325 UNICODE_STRING wstrTempString
;
327 /* parameter validation */
332 NativePath
->Buffer
== 0 ||
333 NativePath
->MaximumLength
== 0 ||
334 (RootDir
!= 0 && RootDir
->Buffer
== 0)
341 RtlInitUnicodeString(&wstrPosixPath
, PosixPath
);
344 if(0 == wstrPosixPath
.Length
)
350 /* first, copy the root path into the return buffer */
351 /* if no root dir passed by the caller... */
353 /* return buffer too small */
354 if(NativePath
->MaximumLength
< sizeof(WCHAR
))
359 /* set the first character to a backslash, and set length accordingly */
362 NativePath
->Buffer
[0] = L
'\\';
363 NativePath
->Length
= sizeof(WCHAR
);
365 /* ... else copy the root dir into the return buffer */
367 /* return buffer too small */
368 if(NativePath
->MaximumLength
< RootDir
->Length
)
373 /* copy the root directory into the return buffer, and set length */
376 memcpy(NativePath
->Buffer
, RootDir
->Buffer
, RootDir
->Length
);
377 NativePath
->Length
= RootDir
->Length
;
380 /* path is "/" - our work is done */
381 if(sizeof(WCHAR
) == wstrPosixPath
.Length
&& IS_CHAR_DELIMITER_U(wstrPosixPath
.Buffer
[0]))
384 /* temp string pointing to the tail of the return buffer */
385 wstrTempString
.Length
= 0;
386 wstrTempString
.MaximumLength
= NativePath
->MaximumLength
- NativePath
->Length
;
387 wstrTempString
.Buffer
= (PWCHAR
)(((PBYTE
)(NativePath
->Buffer
)) + NativePath
->Length
);
389 /* path begins with '/': absolute path. Append the resolved path to the return buffer */
390 if(IS_CHAR_DELIMITER_U(wstrPosixPath
.Buffer
[0]))
392 /* copy the resolved path in the return buffer */
393 __PdxPosixPathResolve_U(wstrPosixPath
, &wstrTempString
, L
'\\');
399 UNICODE_STRING wstrAbsolutePath
;
402 CurDir
= __PdxGetCurDir();
404 /* initialize the buffer for the absolute path */
405 wstrAbsolutePath
.Length
= 0;
406 wstrAbsolutePath
.MaximumLength
= 0xFFFF;
407 wstrAbsolutePath
.Buffer
= __malloc(0xFFFF);
409 /* if the current directory is not null... */
410 if(!(CurDir
->Buffer
== 0 || CurDir
->Length
== 0))
412 /* copy it into the absolute path buffer */
413 memcpy(wstrAbsolutePath
.Buffer
, CurDir
->Buffer
, CurDir
->Length
);
414 wstrAbsolutePath
.Length
+= CurDir
->Length
;
417 /* not enough space to append an extra slash */
418 if((wstrAbsolutePath
.MaximumLength
- wstrAbsolutePath
.Length
) < (USHORT
)sizeof(WCHAR
))
420 __free(wstrAbsolutePath
.Buffer
);
421 NativePath
->Length
= 0;
426 /* append an extra slash */
427 wstrAbsolutePath
.Buffer
[wstrAbsolutePath
.Length
/ sizeof(WCHAR
)] = L
'/';
428 wstrAbsolutePath
.Length
+= sizeof(WCHAR
);
430 /* not enough space to copy the relative path */
431 if((wstrAbsolutePath
.MaximumLength
- wstrAbsolutePath
.Length
) < wstrPosixPath
.Length
)
433 __free(wstrAbsolutePath
.Buffer
);
434 NativePath
->Length
= 0;
439 /* append the relative path to the absolute path */
441 (PWCHAR
)(((PBYTE
)wstrAbsolutePath
.Buffer
) + wstrAbsolutePath
.Length
),
442 wstrPosixPath
.Buffer
,
445 wstrAbsolutePath
.Length
+= wstrPosixPath
.Length
;
447 /* resolve the path */
448 __PdxPosixPathResolve_U(wstrAbsolutePath
, &wstrTempString
, L
'\\');
450 __free(wstrAbsolutePath
.Buffer
);