@@ -1215,6 +1215,82 @@ struct tm *localtime_r(const time_t *timep, struct tm *result)
12151215}
12161216#endif
12171217
1218+ char * mingw_strbuf_realpath (struct strbuf * resolved , const char * path )
1219+ {
1220+ wchar_t wpath [MAX_PATH ];
1221+ HANDLE h ;
1222+ DWORD ret ;
1223+ int len ;
1224+ const char * last_component = NULL ;
1225+ char * append = NULL ;
1226+
1227+ if (xutftowcs_path (wpath , path ) < 0 )
1228+ return NULL ;
1229+
1230+ h = CreateFileW (wpath , 0 ,
1231+ FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE , NULL ,
1232+ OPEN_EXISTING , FILE_FLAG_BACKUP_SEMANTICS , NULL );
1233+
1234+ /*
1235+ * strbuf_realpath() allows the last path component to not exist. If
1236+ * that is the case, now it's time to try without last component.
1237+ */
1238+ if (h == INVALID_HANDLE_VALUE &&
1239+ GetLastError () == ERROR_FILE_NOT_FOUND ) {
1240+ /* cut last component off of `wpath` */
1241+ wchar_t * p = wpath + wcslen (wpath );
1242+
1243+ while (p != wpath )
1244+ if (* (-- p ) == L'/' || * p == L'\\' )
1245+ break ; /* found start of last component */
1246+
1247+ if (p != wpath && (last_component = find_last_dir_sep (path ))) {
1248+ append = xstrdup (last_component + 1 ); /* skip directory separator */
1249+ /*
1250+ * Do not strip the trailing slash at the drive root, otherwise
1251+ * the path would be e.g. `C:` (which resolves to the
1252+ * _current_ directory on that drive).
1253+ */
1254+ if (p [-1 ] == L':' )
1255+ p [1 ] = L'\0' ;
1256+ else
1257+ * p = L'\0' ;
1258+ h = CreateFileW (wpath , 0 , FILE_SHARE_READ |
1259+ FILE_SHARE_WRITE | FILE_SHARE_DELETE ,
1260+ NULL , OPEN_EXISTING ,
1261+ FILE_FLAG_BACKUP_SEMANTICS , NULL );
1262+ }
1263+ }
1264+
1265+ if (h == INVALID_HANDLE_VALUE ) {
1266+ realpath_failed :
1267+ FREE_AND_NULL (append );
1268+ return NULL ;
1269+ }
1270+
1271+ ret = GetFinalPathNameByHandleW (h , wpath , ARRAY_SIZE (wpath ), 0 );
1272+ CloseHandle (h );
1273+ if (!ret || ret >= ARRAY_SIZE (wpath ))
1274+ goto realpath_failed ;
1275+
1276+ len = wcslen (wpath ) * 3 ;
1277+ strbuf_grow (resolved , len );
1278+ len = xwcstoutf (resolved -> buf , normalize_ntpath (wpath ), len );
1279+ if (len < 0 )
1280+ goto realpath_failed ;
1281+ resolved -> len = len ;
1282+
1283+ if (append ) {
1284+ /* Use forward-slash, like `normalize_ntpath()` */
1285+ strbuf_complete (resolved , '/' );
1286+ strbuf_addstr (resolved , append );
1287+ FREE_AND_NULL (append );
1288+ }
1289+
1290+ return resolved -> buf ;
1291+
1292+ }
1293+
12181294char * mingw_getcwd (char * pointer , int len )
12191295{
12201296 wchar_t cwd [MAX_PATH ], wpointer [MAX_PATH ];
0 commit comments