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