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