@@ -1118,6 +1118,82 @@ struct tm *localtime_r(const time_t *timep, struct tm *result)
11181118}
11191119#endif
11201120
1121+ char * mingw_strbuf_realpath (struct strbuf * resolved , const char * path )
1122+ {
1123+ wchar_t wpath [MAX_PATH ];
1124+ HANDLE h ;
1125+ DWORD ret ;
1126+ int len ;
1127+ const char * last_component = NULL ;
1128+ char * append = NULL ;
1129+
1130+ if (xutftowcs_path (wpath , path ) < 0 )
1131+ return NULL ;
1132+
1133+ h = CreateFileW (wpath , 0 ,
1134+ FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE , NULL ,
1135+ OPEN_EXISTING , FILE_FLAG_BACKUP_SEMANTICS , NULL );
1136+
1137+ /*
1138+ * strbuf_realpath() allows the last path component to not exist. If
1139+ * that is the case, now it's time to try without last component.
1140+ */
1141+ if (h == INVALID_HANDLE_VALUE &&
1142+ GetLastError () == ERROR_FILE_NOT_FOUND ) {
1143+ /* cut last component off of `wpath` */
1144+ wchar_t * p = wpath + wcslen (wpath );
1145+
1146+ while (p != wpath )
1147+ if (* (-- p ) == L'/' || * p == L'\\' )
1148+ break ; /* found start of last component */
1149+
1150+ if (p != wpath && (last_component = find_last_dir_sep (path ))) {
1151+ append = xstrdup (last_component + 1 ); /* skip directory separator */
1152+ /*
1153+ * Do not strip the trailing slash at the drive root, otherwise
1154+ * the path would be e.g. `C:` (which resolves to the
1155+ * _current_ directory on that drive).
1156+ */
1157+ if (p [-1 ] == L':' )
1158+ p [1 ] = L'\0' ;
1159+ else
1160+ * p = L'\0' ;
1161+ h = CreateFileW (wpath , 0 , FILE_SHARE_READ |
1162+ FILE_SHARE_WRITE | FILE_SHARE_DELETE ,
1163+ NULL , OPEN_EXISTING ,
1164+ FILE_FLAG_BACKUP_SEMANTICS , NULL );
1165+ }
1166+ }
1167+
1168+ if (h == INVALID_HANDLE_VALUE ) {
1169+ realpath_failed :
1170+ FREE_AND_NULL (append );
1171+ return NULL ;
1172+ }
1173+
1174+ ret = GetFinalPathNameByHandleW (h , wpath , ARRAY_SIZE (wpath ), 0 );
1175+ CloseHandle (h );
1176+ if (!ret || ret >= ARRAY_SIZE (wpath ))
1177+ goto realpath_failed ;
1178+
1179+ len = wcslen (wpath ) * 3 ;
1180+ strbuf_grow (resolved , len );
1181+ len = xwcstoutf (resolved -> buf , normalize_ntpath (wpath ), len );
1182+ if (len < 0 )
1183+ goto realpath_failed ;
1184+ resolved -> len = len ;
1185+
1186+ if (append ) {
1187+ /* Use forward-slash, like `normalize_ntpath()` */
1188+ strbuf_complete (resolved , '/' );
1189+ strbuf_addstr (resolved , append );
1190+ FREE_AND_NULL (append );
1191+ }
1192+
1193+ return resolved -> buf ;
1194+
1195+ }
1196+
11211197char * mingw_getcwd (char * pointer , int len )
11221198{
11231199 wchar_t cwd [MAX_PATH ], wpointer [MAX_PATH ];
0 commit comments