aboutsummaryrefslogtreecommitdiff
path: root/win32/mingw.c
diff options
context:
space:
mode:
Diffstat (limited to 'win32/mingw.c')
-rw-r--r--win32/mingw.c133
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
1291static 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
1330static 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
1366int 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
1288static char *normalize_ntpathA(char *buf) 1420static 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
1403ssize_t readlink(const char *pathname, char *buf, size_t bufsiz) 1534ssize_t readlink(const char *pathname, char *buf, size_t bufsiz)
1404{ 1535{
1405 HANDLE h; 1536 HANDLE h;