@@ -1241,6 +1241,82 @@ struct tm *localtime_r(const time_t *timep, struct tm *result)
12411241}
12421242#endif
12431243
1244+ char * mingw_strbuf_realpath (struct strbuf * resolved , const char * path )
1245+ {
1246+ wchar_t wpath [MAX_PATH ];
1247+ HANDLE h ;
1248+ DWORD ret ;
1249+ int len ;
1250+ const char * last_component = NULL ;
1251+ char * append = NULL ;
1252+
1253+ if (xutftowcs_path (wpath , path ) < 0 )
1254+ return NULL ;
1255+
1256+ h = CreateFileW (wpath , 0 ,
1257+ FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE , NULL ,
1258+ OPEN_EXISTING , FILE_FLAG_BACKUP_SEMANTICS , NULL );
1259+
1260+ /*
1261+ * strbuf_realpath() allows the last path component to not exist. If
1262+ * that is the case, now it's time to try without last component.
1263+ */
1264+ if (h == INVALID_HANDLE_VALUE &&
1265+ GetLastError () == ERROR_FILE_NOT_FOUND ) {
1266+ /* cut last component off of `wpath` */
1267+ wchar_t * p = wpath + wcslen (wpath );
1268+
1269+ while (p != wpath )
1270+ if (* (-- p ) == L'/' || * p == L'\\' )
1271+ break ; /* found start of last component */
1272+
1273+ if (p != wpath && (last_component = find_last_dir_sep (path ))) {
1274+ append = xstrdup (last_component + 1 ); /* skip directory separator */
1275+ /*
1276+ * Do not strip the trailing slash at the drive root, otherwise
1277+ * the path would be e.g. `C:` (which resolves to the
1278+ * _current_ directory on that drive).
1279+ */
1280+ if (p [-1 ] == L':' )
1281+ p [1 ] = L'\0' ;
1282+ else
1283+ * p = L'\0' ;
1284+ h = CreateFileW (wpath , 0 , FILE_SHARE_READ |
1285+ FILE_SHARE_WRITE | FILE_SHARE_DELETE ,
1286+ NULL , OPEN_EXISTING ,
1287+ FILE_FLAG_BACKUP_SEMANTICS , NULL );
1288+ }
1289+ }
1290+
1291+ if (h == INVALID_HANDLE_VALUE ) {
1292+ realpath_failed :
1293+ FREE_AND_NULL (append );
1294+ return NULL ;
1295+ }
1296+
1297+ ret = GetFinalPathNameByHandleW (h , wpath , ARRAY_SIZE (wpath ), 0 );
1298+ CloseHandle (h );
1299+ if (!ret || ret >= ARRAY_SIZE (wpath ))
1300+ goto realpath_failed ;
1301+
1302+ len = wcslen (wpath ) * 3 ;
1303+ strbuf_grow (resolved , len );
1304+ len = xwcstoutf (resolved -> buf , normalize_ntpath (wpath ), len );
1305+ if (len < 0 )
1306+ goto realpath_failed ;
1307+ resolved -> len = len ;
1308+
1309+ if (append ) {
1310+ /* Use forward-slash, like `normalize_ntpath()` */
1311+ strbuf_complete (resolved , '/' );
1312+ strbuf_addstr (resolved , append );
1313+ FREE_AND_NULL (append );
1314+ }
1315+
1316+ return resolved -> buf ;
1317+
1318+ }
1319+
12441320char * mingw_getcwd (char * pointer , int len )
12451321{
12461322 wchar_t cwd [MAX_PATH ], wpointer [MAX_PATH ];
0 commit comments