Reactos
1/***
2*chdir.c - change directory
3*
4* Copyright (c) Microsoft Corporation. All rights reserved.
5*
6*Purpose:
7* This file has the _chdir() function - change current directory.
8*
9*******************************************************************************/
10
11#include <direct.h>
12#include <corecrt_internal_traits.h>
13#include <corecrt_internal_win32_buffer.h>
14#include <malloc.h>
15#include <stdlib.h>
16
17/***
18*int _chdir(path) - change current directory
19*
20*Purpose:
21* Changes the current working directory to that given in path.
22*
23*Entry:
24* _TSCHAR *path - directory to change to
25*
26*Exit:
27* returns 0 if successful,
28* returns -1 and sets errno if unsuccessful
29*
30*Exceptions:
31*
32*******************************************************************************/
33template <typename Character>
34_Success_(return == 0)
35static int __cdecl set_cwd_environment_variable(_In_z_ Character const* const path) throw()
36{
37 typedef __crt_char_traits<Character> traits;
38
39 // If the path is a UNC name, no need to update:
40 if ((path[0] == '\\' || path[0] == '/') && path[0] == path[1])
41 return 0;
42
43#pragma warning(suppress:28931) // unused assignment of variable drive_letter
44 Character const drive_letter = static_cast<Character>(toupper(static_cast<char>(path[0])));
45 Character const name[] = { '=', drive_letter, ':', '\0' };
46
47 if (traits::set_environment_variable(name, path))
48 return 0;
49
50 __acrt_errno_map_os_error(GetLastError());
51 return -1;
52}
53
54
55
56template <typename Character>
57_Success_(return == 0)
58static int __cdecl common_chdir(_In_z_ Character const* const path) throw()
59{
60 typedef __crt_char_traits<Character> traits;
61
62 _VALIDATE_CLEAR_OSSERR_RETURN(path != nullptr, EINVAL, -1);
63
64 if (!traits::set_current_directory(path))
65 {
66 __acrt_errno_map_os_error(GetLastError());
67 return -1;
68 }
69
70 // If the new current directory path is not a UNC path, we must update the
71 // OS environment variable specifying the current full current directory,
72 // build the environment variable string, and call SetEnvironmentVariable().
73 // We need to do this because the SetCurrentDirectory() API does not update
74 // the environment variables, and other functions (fullpath, spawn, etc.)
75 // need them to be set.
76 //
77 // If associated with a 'drive', the current directory should have the
78 // form of the example below:
79 //
80 // D:\nt\private\mytests
81 //
82 // So that the environment variable should be of the form:
83 //
84 // =D:=D:\nt\private\mytests
85
86 Character buffer_initial_storage[MAX_PATH + 1];
87 __crt_internal_win32_buffer<Character> current_directory_buffer(buffer_initial_storage);
88
89 errno_t const err = traits::get_current_directory(current_directory_buffer);
90
91 if (err != 0) {
92 // Appropriate error already set
93 return -1;
94 }
95
96 return set_cwd_environment_variable(current_directory_buffer.data());
97}
98
99
100
101extern "C" int __cdecl _chdir(char const* const path)
102{
103 return common_chdir(path);
104}
105
106extern "C" int __cdecl _wchdir(wchar_t const* const path)
107{
108 return common_chdir(path);
109}