diff options
Diffstat (limited to 'win32/mingw.c')
-rw-r--r-- | win32/mingw.c | 133 |
1 files changed, 132 insertions, 1 deletions
diff --git a/win32/mingw.c b/win32/mingw.c index c35b1d6af..79aaa86f1 100644 --- a/win32/mingw.c +++ b/win32/mingw.c | |||
@@ -1285,6 +1285,138 @@ int symlink(const char *target, const char *linkpath) | |||
1285 | return 0; | 1285 | return 0; |
1286 | } | 1286 | } |
1287 | 1287 | ||
1288 | /* Create a directory junction */ | ||
1289 | #define MRPB rptr->MountPointReparseBuffer | ||
1290 | #if 0 | ||
1291 | static void print_junction(REPARSE_DATA_BUFFER *rptr) | ||
1292 | { | ||
1293 | int i; | ||
1294 | #define MRPB_HEADER_SIZE \ | ||
1295 | (FIELD_OFFSET(REPARSE_DATA_BUFFER, MountPointReparseBuffer.PathBuffer) - \ | ||
1296 | FIELD_OFFSET(REPARSE_DATA_BUFFER, MountPointReparseBuffer)) | ||
1297 | |||
1298 | fprintf(stderr, "---\n"); | ||
1299 | fprintf(stderr, "Tag: %lx\n", rptr->ReparseTag); | ||
1300 | fprintf(stderr, "ReparseDataLength: %d (%d + %d + %d + %d + %d = %d)\n", | ||
1301 | rptr->ReparseDataLength, MRPB_HEADER_SIZE, | ||
1302 | MRPB.SubstituteNameLength, sizeof(WCHAR), | ||
1303 | MRPB.PrintNameLength, sizeof(WCHAR), | ||
1304 | MRPB_HEADER_SIZE + MRPB.SubstituteNameLength + sizeof(WCHAR) + | ||
1305 | MRPB.PrintNameLength + sizeof(WCHAR)); | ||
1306 | fprintf(stderr, "Reserved: %d\n", rptr->Reserved); | ||
1307 | fprintf(stderr, "---\n"); | ||
1308 | fprintf(stderr, "SubstituteNameOffset: %d\n", MRPB.SubstituteNameOffset); | ||
1309 | fprintf(stderr, "SubstituteNameLength: %d\n", MRPB.SubstituteNameLength); | ||
1310 | fprintf(stderr, "PrintNameOffset: %d\n", MRPB.PrintNameOffset); | ||
1311 | fprintf(stderr, "PrintNameLength: %d\n", MRPB.PrintNameLength); | ||
1312 | fprintf(stderr, "SubstituteName: "); | ||
1313 | for (i = 0; i < MRPB.SubstituteNameLength/sizeof(WCHAR); i++) | ||
1314 | fprintf(stderr, "%c", | ||
1315 | MRPB.PathBuffer[MRPB.SubstituteNameOffset/sizeof(WCHAR) + i]); | ||
1316 | fprintf(stderr, " (%x)", | ||
1317 | MRPB.PathBuffer[MRPB.SubstituteNameOffset/sizeof(WCHAR) + i]); | ||
1318 | fprintf(stderr, "\n"); | ||
1319 | fprintf(stderr, "PrintName: "); | ||
1320 | for (i = 0; i < MRPB.PrintNameLength/sizeof(WCHAR); i++) | ||
1321 | fprintf(stderr, "%c", | ||
1322 | MRPB.PathBuffer[MRPB.PrintNameOffset/sizeof(WCHAR) + i]); | ||
1323 | fprintf(stderr, " (%x)", | ||
1324 | MRPB.PathBuffer[MRPB.PrintNameOffset/sizeof(WCHAR) + i]); | ||
1325 | fprintf(stderr, "\n"); | ||
1326 | fprintf(stderr, "---\n"); | ||
1327 | } | ||
1328 | #endif | ||
1329 | |||
1330 | static REPARSE_DATA_BUFFER *make_junction_data_buffer(char *rpath) | ||
1331 | { | ||
1332 | WCHAR pbuf[PATH_MAX]; | ||
1333 | int plen, slen, rbufsize; | ||
1334 | REPARSE_DATA_BUFFER *rptr; | ||
1335 | |||
1336 | /* We need two strings for the reparse data. The PrintName is the | ||
1337 | * target path in Win32 format, the SubstituteName is the same in | ||
1338 | * NT format. */ | ||
1339 | slash_to_bs(rpath); | ||
1340 | plen = MultiByteToWideChar(CP_ACP, 0, rpath, -1, pbuf, PATH_MAX); | ||
1341 | if (plen == 0) { | ||
1342 | errno = err_win_to_posix(); | ||
1343 | return NULL; | ||
1344 | } | ||
1345 | slen = plen + 4; | ||
1346 | |||
1347 | rbufsize = (slen + plen + 2) * sizeof(WCHAR) + | ||
1348 | FIELD_OFFSET(REPARSE_DATA_BUFFER, MountPointReparseBuffer.PathBuffer); | ||
1349 | rptr = xzalloc(rbufsize); | ||
1350 | |||
1351 | rptr->ReparseTag = IO_REPARSE_TAG_MOUNT_POINT; | ||
1352 | rptr->ReparseDataLength = rbufsize - | ||
1353 | FIELD_OFFSET(REPARSE_DATA_BUFFER, MountPointReparseBuffer); | ||
1354 | /* rptr->Reserved = 0; */ | ||
1355 | /* MRPB.SubstituteNameOffset = 0; */ | ||
1356 | MRPB.SubstituteNameLength = slen * sizeof(WCHAR); | ||
1357 | MRPB.PrintNameOffset = MRPB.SubstituteNameLength + sizeof(WCHAR); | ||
1358 | MRPB.PrintNameLength = plen * sizeof(WCHAR); | ||
1359 | |||
1360 | wcscpy(MRPB.PathBuffer, L"\\??\\"); | ||
1361 | wcscpy(MRPB.PathBuffer + 4, pbuf); | ||
1362 | wcscpy(MRPB.PathBuffer + slen + 1, pbuf); | ||
1363 | return rptr; | ||
1364 | } | ||
1365 | |||
1366 | int create_junction(const char *oldpath, const char *newpath) | ||
1367 | { | ||
1368 | char rpath[PATH_MAX]; | ||
1369 | struct stat statbuf; | ||
1370 | REPARSE_DATA_BUFFER *rptr = NULL; | ||
1371 | HANDLE h; | ||
1372 | int error = 0; | ||
1373 | DWORD bytes; | ||
1374 | |||
1375 | if (realpath(oldpath, rpath) == NULL || stat(rpath, &statbuf) < 0) | ||
1376 | return -1; | ||
1377 | |||
1378 | if (!has_dos_drive_prefix(rpath)) { | ||
1379 | errno = EINVAL; | ||
1380 | return -1; | ||
1381 | } | ||
1382 | |||
1383 | if (!S_ISDIR(statbuf.st_mode)) { | ||
1384 | errno = ENOTDIR; | ||
1385 | return -1; | ||
1386 | } | ||
1387 | |||
1388 | if (!(rptr = make_junction_data_buffer(rpath))) { | ||
1389 | return -1; | ||
1390 | } | ||
1391 | |||
1392 | if (mkdir(newpath, 0777) < 0) { | ||
1393 | free(rptr); | ||
1394 | return -1; | ||
1395 | } | ||
1396 | |||
1397 | h = CreateFileA(newpath, GENERIC_READ | GENERIC_WRITE, 0, NULL, | ||
1398 | OPEN_EXISTING, | ||
1399 | FILE_FLAG_OPEN_REPARSE_POINT | FILE_FLAG_BACKUP_SEMANTICS, NULL); | ||
1400 | if (h != INVALID_HANDLE_VALUE) { | ||
1401 | if (DeviceIoControl(h, FSCTL_SET_REPARSE_POINT, rptr, | ||
1402 | rptr->ReparseDataLength + REPARSE_DATA_BUFFER_HEADER_SIZE, | ||
1403 | NULL, 0, &bytes, NULL) != 0) { | ||
1404 | CloseHandle(h); | ||
1405 | free(rptr); | ||
1406 | return 0; | ||
1407 | } | ||
1408 | error = err_win_to_posix(); | ||
1409 | CloseHandle(h); | ||
1410 | } else { | ||
1411 | error = err_win_to_posix(); | ||
1412 | } | ||
1413 | |||
1414 | rmdir(newpath); | ||
1415 | free(rptr); | ||
1416 | errno = error; | ||
1417 | return -1; | ||
1418 | } | ||
1419 | |||
1288 | static char *normalize_ntpathA(char *buf) | 1420 | static char *normalize_ntpathA(char *buf) |
1289 | { | 1421 | { |
1290 | /* fix absolute path prefixes */ | 1422 | /* fix absolute path prefixes */ |
@@ -1399,7 +1531,6 @@ static wchar_t *normalize_ntpath(wchar_t *wbuf) | |||
1399 | } | 1531 | } |
1400 | 1532 | ||
1401 | #define SRPB rptr->SymbolicLinkReparseBuffer | 1533 | #define SRPB rptr->SymbolicLinkReparseBuffer |
1402 | #define MRPB rptr->MountPointReparseBuffer | ||
1403 | ssize_t readlink(const char *pathname, char *buf, size_t bufsiz) | 1534 | ssize_t readlink(const char *pathname, char *buf, size_t bufsiz) |
1404 | { | 1535 | { |
1405 | HANDLE h; | 1536 | HANDLE h; |