@@ -1140,6 +1140,82 @@ struct tm *localtime_r(const time_t *timep, struct tm *result)
1140
1140
}
1141
1141
#endif
1142
1142
1143
+ char * mingw_strbuf_realpath (struct strbuf * resolved , const char * path )
1144
+ {
1145
+ wchar_t wpath [MAX_PATH ];
1146
+ HANDLE h ;
1147
+ DWORD ret ;
1148
+ int len ;
1149
+ const char * last_component = NULL ;
1150
+ char * append = NULL ;
1151
+
1152
+ if (xutftowcs_path (wpath , path ) < 0 )
1153
+ return NULL ;
1154
+
1155
+ h = CreateFileW (wpath , 0 ,
1156
+ FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE , NULL ,
1157
+ OPEN_EXISTING , FILE_FLAG_BACKUP_SEMANTICS , NULL );
1158
+
1159
+ /*
1160
+ * strbuf_realpath() allows the last path component to not exist. If
1161
+ * that is the case, now it's time to try without last component.
1162
+ */
1163
+ if (h == INVALID_HANDLE_VALUE &&
1164
+ GetLastError () == ERROR_FILE_NOT_FOUND ) {
1165
+ /* cut last component off of `wpath` */
1166
+ wchar_t * p = wpath + wcslen (wpath );
1167
+
1168
+ while (p != wpath )
1169
+ if (* (-- p ) == L'/' || * p == L'\\' )
1170
+ break ; /* found start of last component */
1171
+
1172
+ if (p != wpath && (last_component = find_last_dir_sep (path ))) {
1173
+ append = xstrdup (last_component + 1 ); /* skip directory separator */
1174
+ /*
1175
+ * Do not strip the trailing slash at the drive root, otherwise
1176
+ * the path would be e.g. `C:` (which resolves to the
1177
+ * _current_ directory on that drive).
1178
+ */
1179
+ if (p [-1 ] == L':' )
1180
+ p [1 ] = L'\0' ;
1181
+ else
1182
+ * p = L'\0' ;
1183
+ h = CreateFileW (wpath , 0 , FILE_SHARE_READ |
1184
+ FILE_SHARE_WRITE | FILE_SHARE_DELETE ,
1185
+ NULL , OPEN_EXISTING ,
1186
+ FILE_FLAG_BACKUP_SEMANTICS , NULL );
1187
+ }
1188
+ }
1189
+
1190
+ if (h == INVALID_HANDLE_VALUE ) {
1191
+ realpath_failed :
1192
+ FREE_AND_NULL (append );
1193
+ return NULL ;
1194
+ }
1195
+
1196
+ ret = GetFinalPathNameByHandleW (h , wpath , ARRAY_SIZE (wpath ), 0 );
1197
+ CloseHandle (h );
1198
+ if (!ret || ret >= ARRAY_SIZE (wpath ))
1199
+ goto realpath_failed ;
1200
+
1201
+ len = wcslen (wpath ) * 3 ;
1202
+ strbuf_grow (resolved , len );
1203
+ len = xwcstoutf (resolved -> buf , normalize_ntpath (wpath ), len );
1204
+ if (len < 0 )
1205
+ goto realpath_failed ;
1206
+ resolved -> len = len ;
1207
+
1208
+ if (append ) {
1209
+ /* Use forward-slash, like `normalize_ntpath()` */
1210
+ strbuf_complete (resolved , '/' );
1211
+ strbuf_addstr (resolved , append );
1212
+ FREE_AND_NULL (append );
1213
+ }
1214
+
1215
+ return resolved -> buf ;
1216
+
1217
+ }
1218
+
1143
1219
char * mingw_getcwd (char * pointer , int len )
1144
1220
{
1145
1221
wchar_t cwd [MAX_PATH ], wpointer [MAX_PATH ];
0 commit comments