reactos/sdk/lib/ucrt/filesystem/fullpath.cpp

153 lines
4.7 KiB
C++

/***
*fullpath.c -
*
* Copyright (c) Microsoft Corporation. All rights reserved.
*
*Purpose: contains the function _fullpath which makes an absolute path out
* of a relative path. i.e. ..\pop\..\main.c => c:\src\main.c if the
* current directory is c:\src\src
*
*******************************************************************************/
#include <stdio.h>
#include <direct.h>
#include <errno.h>
#include <stdlib.h>
#include <corecrt_internal_traits.h>
#include <windows.h>
/***
*_TCHAR *_fullpath( _TCHAR *buf, const _TCHAR *path, maxlen );
*
*Purpose:
*
* _fullpath - combines the current directory with path to form
* an absolute path. i.e. _fullpath takes care of .\ and ..\
* in the path.
*
* The result is placed in buf. If the length of the result
* is greater than maxlen nullptr is returned, otherwise
* the address of buf is returned.
*
* If buf is nullptr then a buffer is malloc'ed and maxlen is
* ignored. If there are no errors then the address of this
* buffer is returned.
*
* If path specifies a drive, the curent directory of this
* drive is combined with path. If the drive is not valid
* and _fullpath needs the current directory of this drive
* then nullptr is returned. If the current directory of this
* non existant drive is not needed then a proper value is
* returned.
* For example: path = "z:\\pop" does not need z:'s current
* directory but path = "z:pop" does.
*
*
*
*Entry:
* _TCHAR *buf - pointer to a buffer maintained by the user;
* _TCHAR *path - path to "add" to the current directory
* int maxlen - length of the buffer pointed to by buf
*
*Exit:
* Returns pointer to the buffer containing the absolute path
* (same as buf if non-nullptr; otherwise, malloc is
* used to allocate a buffer)
*
*Exceptions:
*
*******************************************************************************/
template <typename Character>
_Success_(return != 0)
static Character* __cdecl common_fullpath(
_Out_writes_z_(max_count) Character* const user_buffer,
Character const* const path,
size_t const max_count,
int const block_use,
char const* const file_name,
int const line_number
) throw()
{
// These are referenced only in the Debug CRT build
UNREFERENCED_PARAMETER(block_use);
UNREFERENCED_PARAMETER(file_name);
UNREFERENCED_PARAMETER(line_number);
typedef __crt_char_traits<Character> traits;
// If the path is empty, we have no work to do:
if (path == nullptr || path[0] == '\0')
{
#pragma warning(suppress:__WARNING_POSTCONDITION_NULLTERMINATION_VIOLATION) // 26036 Prefast does not understand perfect forwarding.
return traits::tgetcwd(user_buffer, static_cast<int>(__min(max_count, INT_MAX)));
}
if (user_buffer != nullptr) {
// Using user buffer. Fail if not enough space.
__crt_no_alloc_win32_buffer<Character> buffer(user_buffer, max_count);
if (!traits::get_full_path_name(path, buffer)) {
return user_buffer;
} else {
return nullptr;
}
} else {
// Always new memory suitable for debug mode and releasing to the user.
__crt_public_win32_buffer<Character> buffer(
__crt_win32_buffer_debug_info(block_use, file_name, line_number)
);
traits::get_full_path_name(path, buffer);
return buffer.detach();
}
}
extern "C" char* __cdecl _fullpath(
char* const user_buffer,
char const* const path,
size_t const max_count
)
{
return common_fullpath(user_buffer, path, max_count, _NORMAL_BLOCK, nullptr, 0);
}
extern "C" wchar_t* __cdecl _wfullpath(
wchar_t* const user_buffer,
wchar_t const* const path,
size_t const max_count
)
{
return common_fullpath(user_buffer, path, max_count, _NORMAL_BLOCK, nullptr, 0);
}
#ifdef _DEBUG
#undef _fullpath_dbg
#undef _wfullpath_dbg
extern "C" char* __cdecl _fullpath_dbg(
char* const user_buffer,
char const* const path,
size_t const max_count,
int const block_use,
char const* const file_name,
int const line_number
)
{
return common_fullpath(user_buffer, path, max_count, block_use, file_name, line_number);
}
extern "C" wchar_t* __cdecl _wfullpath_dbg(
wchar_t* const user_buffer,
wchar_t const* const path,
size_t const max_count,
int const block_use,
char const* const file_name,
int const line_number
)
{
return common_fullpath(user_buffer, path, max_count, block_use, file_name, line_number);
}
#endif // _DEBUG