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