Reactos
at master 109 lines 3.1 kB view raw
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}