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 *******************************************************************************/ 33 template <typename Character> 34 _Success_(return == 0) 35 static 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 56 template <typename Character> 57 _Success_(return == 0) 58 static 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 101 extern "C" int __cdecl _chdir(char const* const path) 102 { 103 return common_chdir(path); 104 } 105 106 extern "C" int __cdecl _wchdir(wchar_t const* const path) 107 { 108 return common_chdir(path); 109 } 110