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