1360 %{ |
1358 %{ |
1361 HFILE f = NULL; |
1359 HFILE f = NULL; |
1362 int pass = 0; |
1360 int pass = 0; |
1363 |
1361 |
1364 if (!__isNonNilObject(encodedPathName) |
1362 if (!__isNonNilObject(encodedPathName) |
1365 || !(__isStringLike(openmode) || __isArrayLike(openmode))) |
1363 || !(__isStringLike(openmode) || __isArrayLike(openmode))) |
1366 goto badArgument; |
1364 goto badArgument; |
1367 |
1365 |
1368 retry: |
1366 retry: |
1369 #ifdef __VMS__ |
1367 #ifdef __VMS__ |
1370 if (__isStringLike(encodedPathName)) { |
1368 if (__isStringLike(encodedPathName)) { |
1371 do { |
1369 do { |
1372 /* |
1370 /* |
1373 * allow passing additional RMS arguments. |
1371 * allow passing additional RMS arguments. |
1374 * stupid: DEC does not seem to offer an interface for passing a char **. |
1372 * stupid: DEC does not seem to offer an interface for passing a char **. |
1375 */ |
1373 */ |
1376 __threadErrno = 0; |
1374 __threadErrno = 0; |
1377 |
1375 |
1378 { |
1376 { |
1379 if (__isArray(attributeSpec)) { |
1377 if (__isArray(attributeSpec)) { |
1380 OBJ *ap = __ArrayInstPtr(attributeSpec)->a_element; |
1378 OBJ *ap = __ArrayInstPtr(attributeSpec)->a_element; |
1381 int numAttrib = 0; |
1379 int numAttrib = 0; |
1382 int i; |
1380 int i; |
1383 |
1381 |
1384 numAttrib = __arraySize(attributeSpec); |
1382 numAttrib = __arraySize(attributeSpec); |
1385 for (i=0; i<numAttrib;i++) { |
1383 for (i=0; i<numAttrib;i++) { |
1386 if (! __isStringLike(ap[i])) { |
1384 if (! __isStringLike(ap[i])) { |
1387 __threadErrno = EINVAL; /* invalid argument */ |
1385 __threadErrno = EINVAL; /* invalid argument */ |
1388 goto getOutOfHere; |
1386 goto getOutOfHere; |
1389 } |
1387 } |
1390 } |
1388 } |
1391 switch (numAttrib) { |
1389 switch (numAttrib) { |
1392 case 0: |
1390 case 0: |
1393 __BEGIN_INTERRUPTABLE__ |
1391 __BEGIN_INTERRUPTABLE__ |
1394 f = fopen((char *)__stringVal(pathName), (char *)__stringVal(openmode)); |
1392 f = fopen((char *)__stringVal(pathName), (char *)__stringVal(openmode)); |
1395 __END_INTERRUPTABLE__ |
1393 __END_INTERRUPTABLE__ |
1396 break; |
1394 break; |
1397 case 1: |
1395 case 1: |
1398 __BEGIN_INTERRUPTABLE__ |
1396 __BEGIN_INTERRUPTABLE__ |
1399 f = fopen((char *)__stringVal(pathName), (char *)__stringVal(openmode), |
1397 f = fopen((char *)__stringVal(pathName), (char *)__stringVal(openmode), |
1400 __stringVal(ap[0])); |
1398 __stringVal(ap[0])); |
1401 __END_INTERRUPTABLE__ |
1399 __END_INTERRUPTABLE__ |
1402 break; |
1400 break; |
1403 case 2: |
1401 case 2: |
1404 __BEGIN_INTERRUPTABLE__ |
1402 __BEGIN_INTERRUPTABLE__ |
1405 f = fopen((char *)__stringVal(pathName), (char *)__stringVal(openmode), |
1403 f = fopen((char *)__stringVal(pathName), (char *)__stringVal(openmode), |
1406 __stringVal(ap[0]), __stringVal(ap[1])); |
1404 __stringVal(ap[0]), __stringVal(ap[1])); |
1407 __END_INTERRUPTABLE__ |
1405 __END_INTERRUPTABLE__ |
1408 break; |
1406 break; |
1409 case 3: |
1407 case 3: |
1410 __BEGIN_INTERRUPTABLE__ |
1408 __BEGIN_INTERRUPTABLE__ |
1411 f = fopen((char *)__stringVal(pathName), (char *)__stringVal(openmode), |
1409 f = fopen((char *)__stringVal(pathName), (char *)__stringVal(openmode), |
1412 __stringVal(ap[0]), __stringVal(ap[1]), __stringVal(ap[2])); |
1410 __stringVal(ap[0]), __stringVal(ap[1]), __stringVal(ap[2])); |
1413 __END_INTERRUPTABLE__ |
1411 __END_INTERRUPTABLE__ |
1414 break; |
1412 break; |
1415 case 4: |
1413 case 4: |
1416 __BEGIN_INTERRUPTABLE__ |
1414 __BEGIN_INTERRUPTABLE__ |
1417 f = fopen((char *)__stringVal(pathName), (char *)__stringVal(openmode), |
1415 f = fopen((char *)__stringVal(pathName), (char *)__stringVal(openmode), |
1418 __stringVal(ap[0]), __stringVal(ap[1]), __stringVal(ap[2]), |
1416 __stringVal(ap[0]), __stringVal(ap[1]), __stringVal(ap[2]), |
1419 __stringVal(ap[3])); |
1417 __stringVal(ap[3])); |
1420 __END_INTERRUPTABLE__ |
1418 __END_INTERRUPTABLE__ |
1421 break; |
1419 break; |
1422 case 5: |
1420 case 5: |
1423 __BEGIN_INTERRUPTABLE__ |
1421 __BEGIN_INTERRUPTABLE__ |
1424 f = fopen((char *)__stringVal(pathName), (char *)__stringVal(openmode), |
1422 f = fopen((char *)__stringVal(pathName), (char *)__stringVal(openmode), |
1425 __stringVal(ap[0]), __stringVal(ap[1]), __stringVal(ap[2]), |
1423 __stringVal(ap[0]), __stringVal(ap[1]), __stringVal(ap[2]), |
1426 __stringVal(ap[3]), __stringVal(ap[4])); |
1424 __stringVal(ap[3]), __stringVal(ap[4])); |
1427 __END_INTERRUPTABLE__ |
1425 __END_INTERRUPTABLE__ |
1428 break; |
1426 break; |
1429 case 6: |
1427 case 6: |
1430 __BEGIN_INTERRUPTABLE__ |
1428 __BEGIN_INTERRUPTABLE__ |
1431 f = fopen((char *)__stringVal(pathName), (char *)__stringVal(openmode), |
1429 f = fopen((char *)__stringVal(pathName), (char *)__stringVal(openmode), |
1432 __stringVal(ap[0]), __stringVal(ap[1]), __stringVal(ap[2]), |
1430 __stringVal(ap[0]), __stringVal(ap[1]), __stringVal(ap[2]), |
1433 __stringVal(ap[3]), __stringVal(ap[4]), __stringVal(ap[5])); |
1431 __stringVal(ap[3]), __stringVal(ap[4]), __stringVal(ap[5])); |
1434 __END_INTERRUPTABLE__ |
1432 __END_INTERRUPTABLE__ |
1435 break; |
1433 break; |
1436 case 7: |
1434 case 7: |
1437 __BEGIN_INTERRUPTABLE__ |
1435 __BEGIN_INTERRUPTABLE__ |
1438 f = fopen((char *)__stringVal(pathName), (char *)__stringVal(openmode), |
1436 f = fopen((char *)__stringVal(pathName), (char *)__stringVal(openmode), |
1439 __stringVal(ap[0]), __stringVal(ap[1]), __stringVal(ap[2]), |
1437 __stringVal(ap[0]), __stringVal(ap[1]), __stringVal(ap[2]), |
1440 __stringVal(ap[3]), __stringVal(ap[4]), __stringVal(ap[5]), |
1438 __stringVal(ap[3]), __stringVal(ap[4]), __stringVal(ap[5]), |
1441 __stringVal(ap[6])); |
1439 __stringVal(ap[6])); |
1442 __END_INTERRUPTABLE__ |
1440 __END_INTERRUPTABLE__ |
1443 break; |
1441 break; |
1444 case 8: |
1442 case 8: |
1445 __BEGIN_INTERRUPTABLE__ |
1443 __BEGIN_INTERRUPTABLE__ |
1446 f = fopen((char *)__stringVal(pathName), (char *)__stringVal(openmode), |
1444 f = fopen((char *)__stringVal(pathName), (char *)__stringVal(openmode), |
1447 __stringVal(ap[0]), __stringVal(ap[1]), __stringVal(ap[2]), |
1445 __stringVal(ap[0]), __stringVal(ap[1]), __stringVal(ap[2]), |
1448 __stringVal(ap[3]), __stringVal(ap[4]), __stringVal(ap[5]), |
1446 __stringVal(ap[3]), __stringVal(ap[4]), __stringVal(ap[5]), |
1449 __stringVal(ap[6]), __stringVal(ap[7])); |
1447 __stringVal(ap[6]), __stringVal(ap[7])); |
1450 __END_INTERRUPTABLE__ |
1448 __END_INTERRUPTABLE__ |
1451 break; |
1449 break; |
1452 case 9: |
1450 case 9: |
1453 __BEGIN_INTERRUPTABLE__ |
1451 __BEGIN_INTERRUPTABLE__ |
1454 f = fopen((char *)__stringVal(pathName), (char *)__stringVal(openmode), |
1452 f = fopen((char *)__stringVal(pathName), (char *)__stringVal(openmode), |
1455 __stringVal(ap[0]), __stringVal(ap[1]), __stringVal(ap[2]), |
1453 __stringVal(ap[0]), __stringVal(ap[1]), __stringVal(ap[2]), |
1456 __stringVal(ap[3]), __stringVal(ap[4]), __stringVal(ap[5]), |
1454 __stringVal(ap[3]), __stringVal(ap[4]), __stringVal(ap[5]), |
1457 __stringVal(ap[6]), __stringVal(ap[7]), __stringVal(ap[8])); |
1455 __stringVal(ap[6]), __stringVal(ap[7]), __stringVal(ap[8])); |
1458 __END_INTERRUPTABLE__ |
1456 __END_INTERRUPTABLE__ |
1459 break; |
1457 break; |
1460 case 10: |
1458 case 10: |
1461 __BEGIN_INTERRUPTABLE__ |
1459 __BEGIN_INTERRUPTABLE__ |
1462 f = fopen((char *)__stringVal(pathName), (char *)__stringVal(openmode), |
1460 f = fopen((char *)__stringVal(pathName), (char *)__stringVal(openmode), |
1463 __stringVal(ap[0]), __stringVal(ap[1]), __stringVal(ap[2]), |
1461 __stringVal(ap[0]), __stringVal(ap[1]), __stringVal(ap[2]), |
1464 __stringVal(ap[3]), __stringVal(ap[4]), __stringVal(ap[5]), |
1462 __stringVal(ap[3]), __stringVal(ap[4]), __stringVal(ap[5]), |
1465 __stringVal(ap[6]), __stringVal(ap[7]), __stringVal(ap[8]), |
1463 __stringVal(ap[6]), __stringVal(ap[7]), __stringVal(ap[8]), |
1466 __stringVal(ap[9])); |
1464 __stringVal(ap[9])); |
1467 __END_INTERRUPTABLE__ |
1465 __END_INTERRUPTABLE__ |
1468 break; |
1466 break; |
1469 default: |
1467 default: |
1470 __threadErrno = E2BIG; /* too many args */ |
1468 __threadErrno = E2BIG; /* too many args */ |
1471 goto getOutOfHere; |
1469 goto getOutOfHere; |
1472 } |
1470 } |
1473 } else if (attributeSpec != nil) { |
1471 } else if (attributeSpec != nil) { |
1474 __threadErrno = EINVAL; /* invalid argument */ |
1472 __threadErrno = EINVAL; /* invalid argument */ |
1475 goto getOutOfHere; |
1473 goto getOutOfHere; |
1476 } else { |
1474 } else { |
1477 /* |
1475 /* |
1478 * create file as sequential streamLF by default. |
1476 * create file as sequential streamLF by default. |
1479 */ |
1477 */ |
1480 __BEGIN_INTERRUPTABLE__ |
1478 __BEGIN_INTERRUPTABLE__ |
1481 f = fopen((char *)__stringVal(pathName), (char *)__stringVal(openmode), "rfm=stmlf"); |
1479 f = fopen((char *)__stringVal(pathName), (char *)__stringVal(openmode), "rfm=stmlf"); |
1482 __END_INTERRUPTABLE__ |
1480 __END_INTERRUPTABLE__ |
1483 } |
1481 } |
1484 } |
1482 } |
1485 } while ((f == NULL) && (__threadErrno == EINTR)); |
1483 } while ((f == NULL) && (__threadErrno == EINTR)); |
1486 } |
1484 } |
1487 #else /* not VMS */ |
1485 #else /* not VMS */ |
1488 |
1486 |
1489 # ifdef WIN32 |
1487 # ifdef WIN32 |
1490 { |
1488 { |
1491 DWORD share = 0, access = 0, create = 0, attr = 0; |
1489 DWORD share = 0, access = 0, create = 0, attr = 0; |
1492 char * __openmode; |
1490 char * __openmode; |
1493 HANDLE handle; |
1491 HANDLE handle; |
1494 SECURITY_ATTRIBUTES sa; |
1492 SECURITY_ATTRIBUTES sa; |
1495 |
1493 |
1496 if (__isStringLike(openmode)) { |
1494 if (__isStringLike(openmode)) { |
1497 share = FILE_SHARE_READ|FILE_SHARE_WRITE; |
1495 share = FILE_SHARE_READ|FILE_SHARE_WRITE; |
1498 __openmode = __stringVal(openmode); |
1496 __openmode = __stringVal(openmode); |
1499 if (strcmp(__openmode, "rb") == 0) { |
1497 if (strcmp(__openmode, "rb") == 0) { |
1500 access = GENERIC_READ; |
1498 access = GENERIC_READ; |
1501 create = OPEN_EXISTING; |
1499 create = OPEN_EXISTING; |
1502 } else if (strcmp(__openmode, "rb+") == 0) { |
1500 } else if (strcmp(__openmode, "rb+") == 0) { |
1503 access = GENERIC_READ | GENERIC_WRITE; |
1501 access = GENERIC_READ | GENERIC_WRITE; |
1504 create = OPEN_EXISTING; |
1502 create = OPEN_EXISTING; |
1505 } else if (strcmp(__openmode, "wb") == 0) { |
1503 } else if (strcmp(__openmode, "wb") == 0) { |
1506 access = GENERIC_WRITE; |
1504 access = GENERIC_WRITE; |
1507 create = CREATE_ALWAYS; |
1505 create = CREATE_ALWAYS; |
1508 } else if (strcmp(__openmode, "wb+") == 0) { |
1506 } else if (strcmp(__openmode, "wb+") == 0) { |
1509 access = GENERIC_READ | GENERIC_WRITE; |
1507 access = GENERIC_READ | GENERIC_WRITE; |
1510 create = CREATE_ALWAYS; |
1508 create = CREATE_ALWAYS; |
1511 } else if (strcmp(__openmode, "ab") == 0) { |
1509 } else if (strcmp(__openmode, "ab") == 0) { |
1512 access = FILE_APPEND_DATA|FILE_WRITE_ATTRIBUTES|FILE_WRITE_EA| |
1510 access = FILE_APPEND_DATA|FILE_WRITE_ATTRIBUTES|FILE_WRITE_EA| |
1513 STANDARD_RIGHTS_WRITE|SYNCHRONIZE; |
1511 STANDARD_RIGHTS_WRITE|SYNCHRONIZE; |
1514 create = OPEN_ALWAYS; |
1512 create = OPEN_ALWAYS; |
1515 } else if (strcmp(__openmode, "ab+") == 0) { |
1513 } else if (strcmp(__openmode, "ab+") == 0) { |
1516 access = GENERIC_READ |FILE_APPEND_DATA|FILE_WRITE_ATTRIBUTES|FILE_WRITE_EA| |
1514 access = GENERIC_READ |FILE_APPEND_DATA|FILE_WRITE_ATTRIBUTES|FILE_WRITE_EA| |
1517 STANDARD_RIGHTS_WRITE|SYNCHRONIZE; |
1515 STANDARD_RIGHTS_WRITE|SYNCHRONIZE; |
1518 create = OPEN_ALWAYS; |
1516 create = OPEN_ALWAYS; |
1519 } else { |
1517 } else { |
1520 console_fprintf(stderr, "Win32OS [warning]: unsupported open mode\n"); |
1518 console_fprintf(stderr, "Win32OS [warning]: unsupported open mode\n"); |
1521 } |
1519 } |
1522 } else if (__isArrayLike(openmode)) { |
1520 } else if (__isArrayLike(openmode)) { |
1523 OBJ *ap = __arrayVal(openmode); |
1521 OBJ *ap = __arrayVal(openmode); |
1524 int numAttrib = __arraySize(openmode); |
1522 int numAttrib = __arraySize(openmode); |
1525 int i; |
1523 int i; |
1526 |
1524 |
1527 __openmode = "rb+"; |
1525 __openmode = "rb+"; |
1528 |
1526 |
1529 for (i=0; i<numAttrib; i++) { |
1527 for (i=0; i<numAttrib; i++) { |
1530 OBJ attrSym = ap[i]; |
1528 OBJ attrSym = ap[i]; |
1531 |
1529 |
1532 if (attrSym == @symbol(FILE_SHARE_READ)) { |
1530 if (attrSym == @symbol(FILE_SHARE_READ)) { |
1533 share |= FILE_SHARE_READ; |
1531 share |= FILE_SHARE_READ; |
1534 } else if (attrSym == @symbol(FILE_SHARE_WRITE)) { |
1532 } else if (attrSym == @symbol(FILE_SHARE_WRITE)) { |
1535 share |= FILE_SHARE_WRITE; |
1533 share |= FILE_SHARE_WRITE; |
1536 |
1534 |
1537 } else if (attrSym == @symbol(GENERIC_READ)) { |
1535 } else if (attrSym == @symbol(GENERIC_READ)) { |
1538 access |= GENERIC_READ; |
1536 access |= GENERIC_READ; |
1539 } else if (attrSym == @symbol(GENERIC_WRITE)) { |
1537 } else if (attrSym == @symbol(GENERIC_WRITE)) { |
1540 access |= GENERIC_WRITE; |
1538 access |= GENERIC_WRITE; |
1541 } else if (attrSym == @symbol(GENERIC_READ_WRITE)) { |
1539 } else if (attrSym == @symbol(GENERIC_READ_WRITE)) { |
1542 access |= GENERIC_READ|GENERIC_WRITE; |
1540 access |= GENERIC_READ|GENERIC_WRITE; |
1543 |
1541 |
1544 } else if (attrSym == @symbol(CREATE_NEW)) { |
1542 } else if (attrSym == @symbol(CREATE_NEW)) { |
1545 create |= CREATE_NEW; |
1543 create |= CREATE_NEW; |
1546 } else if (attrSym == @symbol(CREATE_ALWAYS)) { |
1544 } else if (attrSym == @symbol(CREATE_ALWAYS)) { |
1547 create |= CREATE_ALWAYS; |
1545 create |= CREATE_ALWAYS; |
1548 } else if (attrSym == @symbol(OPEN_EXISTING)) { |
1546 } else if (attrSym == @symbol(OPEN_EXISTING)) { |
1549 create |= OPEN_EXISTING; |
1547 create |= OPEN_EXISTING; |
1550 } else if (attrSym == @symbol(OPEN_ALWAYS)) { |
1548 } else if (attrSym == @symbol(OPEN_ALWAYS)) { |
1551 create |= OPEN_ALWAYS; |
1549 create |= OPEN_ALWAYS; |
1552 } else if (attrSym == @symbol(TRUNCATE_EXISTING)) { |
1550 } else if (attrSym == @symbol(TRUNCATE_EXISTING)) { |
1553 create |= TRUNCATE_EXISTING; |
1551 create |= TRUNCATE_EXISTING; |
1554 |
1552 |
1555 } else if (attrSym == @symbol(FILE_ATTRIBUTE_HIDDEN)) { |
1553 } else if (attrSym == @symbol(FILE_ATTRIBUTE_HIDDEN)) { |
1556 attr |= FILE_ATTRIBUTE_HIDDEN; |
1554 attr |= FILE_ATTRIBUTE_HIDDEN; |
1557 } else if (attrSym == @symbol(FILE_ATTRIBUTE_READONLY)) { |
1555 } else if (attrSym == @symbol(FILE_ATTRIBUTE_READONLY)) { |
1558 attr |= FILE_ATTRIBUTE_READONLY; |
1556 attr |= FILE_ATTRIBUTE_READONLY; |
1559 } else if (attrSym == @symbol(FILE_FLAG_WRITE_THROUGH)) { |
1557 } else if (attrSym == @symbol(FILE_FLAG_WRITE_THROUGH)) { |
1560 attr |= FILE_FLAG_WRITE_THROUGH; |
1558 attr |= FILE_FLAG_WRITE_THROUGH; |
1561 } else if (attrSym == @symbol(FILE_FLAG_SEQUENTIAL_SCAN)) { |
1559 } else if (attrSym == @symbol(FILE_FLAG_SEQUENTIAL_SCAN)) { |
1562 attr |= FILE_FLAG_SEQUENTIAL_SCAN; |
1560 attr |= FILE_FLAG_SEQUENTIAL_SCAN; |
1563 } else if (attrSym == @symbol(FILE_FLAG_DELETE_ON_CLOSE)) { |
1561 } else if (attrSym == @symbol(FILE_FLAG_DELETE_ON_CLOSE)) { |
1564 attr |= FILE_FLAG_DELETE_ON_CLOSE; |
1562 attr |= FILE_FLAG_DELETE_ON_CLOSE; |
1565 } else if (!__isSymbol(attrSym) && __isStringLike(attrSym)) { |
1563 } else if (!__isSymbol(attrSym) && __isStringLike(attrSym)) { |
1566 __openmode = __stringVal(attrSym); |
1564 __openmode = __stringVal(attrSym); |
1567 } else { |
1565 } else { |
1568 console_fprintf(stderr, "Win32OS [warning]: unsupported open mode\n"); |
1566 console_fprintf(stderr, "Win32OS [warning]: unsupported open mode\n"); |
1569 } |
1567 } |
1570 } |
1568 } |
1571 } |
1569 } |
1572 if (create == 0) { |
1570 if (create == 0) { |
1573 // argumentError = @symbol(missingCreateMode); |
1571 // argumentError = @symbol(missingCreateMode); |
1574 goto badArgument; |
1572 goto badArgument; |
1575 } |
1573 } |
1576 if (attr == 0) { |
1574 if (attr == 0) { |
1577 attr = FILE_ATTRIBUTE_NORMAL; |
1575 attr = FILE_ATTRIBUTE_NORMAL; |
1578 } |
1576 } |
1579 |
1577 |
1580 /* |
1578 /* |
1581 * create security attributes - make handle inheritable by subprocesses |
1579 * create security attributes - make handle inheritable by subprocesses |
1582 */ |
1580 */ |
1583 memset(&sa, 0, sizeof (sa)); |
1581 memset(&sa, 0, sizeof (sa)); |
1584 sa.nLength = sizeof( sa ); |
1582 sa.nLength = sizeof( sa ); |
1585 // sa.bInheritHandle = TRUE; |
1583 // sa.bInheritHandle = TRUE; |
1586 sa.bInheritHandle = FALSE; |
1584 sa.bInheritHandle = FALSE; |
1587 |
1585 |
1588 if (__isStringLike(pathName)) { |
1586 if (__isStringLike(pathName)) { |
1589 char _aPathName[MAXPATHLEN]; |
1587 char _aPathName[MAXPATHLEN]; |
1590 |
1588 |
1591 strncpy(_aPathName, __stringVal(pathName), MAXPATHLEN-1); _aPathName[MAXPATHLEN-1] = '\0'; |
1589 strncpy(_aPathName, __stringVal(pathName), MAXPATHLEN-1); _aPathName[MAXPATHLEN-1] = '\0'; |
1592 do { |
1590 do { |
1593 __threadErrno = 0; |
1591 __threadErrno = 0; |
1594 handle = STX_API_NOINT_CALL7( "CreateFileA", CreateFileA, _aPathName, access, share, &sa, create, attr, 0 /* hTempl */); |
1592 handle = STX_API_NOINT_CALL7( "CreateFileA", CreateFileA, _aPathName, access, share, &sa, create, attr, 0 /* hTempl */); |
1595 if (__threadErrno == EINTR) { |
1593 if (__threadErrno == EINTR) { |
1596 handle = INVALID_HANDLE_VALUE; |
1594 handle = INVALID_HANDLE_VALUE; |
1597 } |
1595 } |
1598 } while ((handle == INVALID_HANDLE_VALUE) && (__threadErrno == EINTR)); |
1596 } while ((handle == INVALID_HANDLE_VALUE) && (__threadErrno == EINTR)); |
1599 } else if (__isUnicode16String(pathName)) { |
1597 } else if (__isUnicode16String(pathName)) { |
1600 wchar_t _aPathName[MAXPATHLEN+1]; |
1598 wchar_t _aPathName[MAXPATHLEN+1]; |
1601 int i, l; |
1599 int i, l; |
1602 |
1600 |
1603 l = __unicode16StringSize(pathName); |
1601 l = __unicode16StringSize(pathName); |
1604 if (l > MAXPATHLEN) l = MAXPATHLEN; |
1602 if (l > MAXPATHLEN) l = MAXPATHLEN; |
1605 for (i=0; i<l; i++) { |
1603 for (i=0; i<l; i++) { |
1606 _aPathName[i] = __unicode16StringVal(pathName)[i]; |
1604 _aPathName[i] = __unicode16StringVal(pathName)[i]; |
1607 } |
1605 } |
1608 _aPathName[i] = 0; |
1606 _aPathName[i] = 0; |
1609 |
1607 |
1610 do { |
1608 do { |
1611 __threadErrno = 0; |
1609 __threadErrno = 0; |
1612 handle = STX_API_NOINT_CALL7( "CreateFileW", CreateFileW, _aPathName, access, share, &sa, create, attr, 0 /* hTempl */); |
1610 handle = STX_API_NOINT_CALL7( "CreateFileW", CreateFileW, _aPathName, access, share, &sa, create, attr, 0 /* hTempl */); |
1613 if (__threadErrno == EINTR) { |
1611 if (__threadErrno == EINTR) { |
1614 handle = INVALID_HANDLE_VALUE; |
1612 handle = INVALID_HANDLE_VALUE; |
1615 } |
1613 } |
1616 } while ((handle == INVALID_HANDLE_VALUE) && (__threadErrno == EINTR)); |
1614 } while ((handle == INVALID_HANDLE_VALUE) && (__threadErrno == EINTR)); |
1617 } |
1615 } |
1618 if (handle != INVALID_HANDLE_VALUE) { |
1616 if (handle != INVALID_HANDLE_VALUE) { |
1619 int fd; |
1617 int fd; |
1620 extern void __stxWrapApiEnterCritical(), __stxWrapApiLeaveCritical(); |
1618 extern void __stxWrapApiEnterCritical(), __stxWrapApiLeaveCritical(); |
1621 |
1619 |
1622 __stxWrapApiEnterCritical(); |
1620 __stxWrapApiEnterCritical(); |
1623 fd = _open_osfhandle((long)handle, O_BINARY); |
1621 fd = _open_osfhandle((long)handle, O_BINARY); |
1624 if (fd < 0) { |
1622 if (fd < 0) { |
1625 if (__threadErrno == 0) { |
1623 if (__threadErrno == 0) { |
1626 // no more file descriptors |
1624 // no more file descriptors |
1627 __threadErrno = EMFILE; |
1625 __threadErrno = EMFILE; |
1628 } |
1626 } |
1629 CloseHandle(handle); |
1627 CloseHandle(handle); |
1630 } else { |
1628 } else { |
1631 f = fdopen(fd, __openmode); |
1629 f = fdopen(fd, __openmode); |
1632 } |
1630 } |
1633 __stxWrapApiLeaveCritical(); |
1631 __stxWrapApiLeaveCritical(); |
1634 } else { |
1632 } else { |
1635 __threadErrno = __WIN32_ERR(GetLastError()); |
1633 __threadErrno = __WIN32_ERR(GetLastError()); |
1636 } |
1634 } |
1637 } |
1635 } |
1638 # else /* not WIN32 */ |
1636 # else /* not WIN32 */ |
1639 |
1637 |
1640 if (__isStringLike(encodedPathName)) { |
1638 if (__isStringLike(encodedPathName)) { |
1641 int accessMode = 0666; // default access mode of fopen(), relies on umask() |
1639 int accessMode = 0666; // default access mode of fopen(), relies on umask() |
1642 int flags = 0; |
1640 int flags = 0; |
1643 int fd; |
1641 int fd; |
1644 char * __openmode; |
1642 char * __openmode; |
1645 |
1643 |
1646 if (__isStringLike(openmode)) { |
1644 if (__isStringLike(openmode)) { |
1647 __openmode = __stringVal(openmode); |
1645 __openmode = __stringVal(openmode); |
1648 if (strcmp(__openmode, "r") == 0) { |
1646 if (strcmp(__openmode, "r") == 0) { |
1649 flags = O_RDONLY; |
1647 flags = O_RDONLY; |
1650 } else if (strcmp(__openmode, "r+") == 0) { |
1648 } else if (strcmp(__openmode, "r+") == 0) { |
1651 flags = O_RDWR; |
1649 flags = O_RDWR; |
1652 } else if (strcmp(__openmode, "w") == 0) { |
1650 } else if (strcmp(__openmode, "w") == 0) { |
1653 flags = O_WRONLY | O_CREAT | O_TRUNC; |
1651 flags = O_WRONLY | O_CREAT | O_TRUNC; |
1654 } else if (strcmp(__openmode, "w+") == 0) { |
1652 } else if (strcmp(__openmode, "w+") == 0) { |
1655 flags = O_RDWR | O_CREAT | O_TRUNC; |
1653 flags = O_RDWR | O_CREAT | O_TRUNC; |
1656 } else if (strcmp(__openmode, "a") == 0) { |
1654 } else if (strcmp(__openmode, "a") == 0) { |
1657 flags = O_WRONLY | O_CREAT | O_APPEND; |
1655 flags = O_WRONLY | O_CREAT | O_APPEND; |
1658 } else if (strcmp(__openmode, "a+") == 0) { |
1656 } else if (strcmp(__openmode, "a+") == 0) { |
1659 flags = O_RDWR | O_CREAT| O_APPEND; |
1657 flags = O_RDWR | O_CREAT| O_APPEND; |
1660 } else { |
1658 } else { |
1661 console_fprintf(stderr, "UNIXOS [warning]: unsupported open mode\n"); |
1659 console_fprintf(stderr, "UNIXOS [warning]: unsupported open mode\n"); |
1662 } |
1660 } |
1663 } else if (__isArrayLike(openmode)) { |
1661 } else if (__isArrayLike(openmode)) { |
1664 OBJ *ap = __arrayVal(openmode); |
1662 OBJ *ap = __arrayVal(openmode); |
1665 int numAttrib = __arraySize(openmode); |
1663 int numAttrib = __arraySize(openmode); |
1666 int i; |
1664 int i; |
1667 |
1665 |
1668 __openmode = "r+"; |
1666 __openmode = "r+"; |
1669 |
1667 |
1670 for (i=0; i<numAttrib; i++) { |
1668 for (i=0; i<numAttrib; i++) { |
1671 OBJ attrSym = ap[i]; |
1669 OBJ attrSym = ap[i]; |
1672 |
1670 |
1673 if (attrSym == @symbol(FILE_SHARE_READ)) { |
1671 if (attrSym == @symbol(FILE_SHARE_READ)) { |
1674 // ignore |
1672 // ignore |
1675 } else if (attrSym == @symbol(FILE_SHARE_WRITE)) { |
1673 } else if (attrSym == @symbol(FILE_SHARE_WRITE)) { |
1676 // ignore |
1674 // ignore |
1677 } else if (attrSym == @symbol(GENERIC_READ)) { |
1675 } else if (attrSym == @symbol(GENERIC_READ)) { |
1678 flags |= O_RDONLY; |
1676 flags |= O_RDONLY; |
1679 } else if (attrSym == @symbol(GENERIC_WRITE)) { |
1677 } else if (attrSym == @symbol(GENERIC_WRITE)) { |
1680 flags |= O_WRONLY; |
1678 flags |= O_WRONLY; |
1681 } else if (attrSym == @symbol(GENERIC_READ_WRITE)) { |
1679 } else if (attrSym == @symbol(GENERIC_READ_WRITE)) { |
1682 flags |= O_RDWR; |
1680 flags |= O_RDWR; |
1683 |
1681 |
1684 } else if (attrSym == @symbol(CREATE_NEW)) { |
1682 } else if (attrSym == @symbol(CREATE_NEW)) { |
1685 flags |= O_CREAT|O_EXCL; |
1683 flags |= O_CREAT|O_EXCL; |
1686 accessMode = 0600; // simulate mkstemp() |
1684 accessMode = 0600; // simulate mkstemp() |
1687 } else if (attrSym == @symbol(CREATE_ALWAYS)) { |
1685 } else if (attrSym == @symbol(CREATE_ALWAYS)) { |
1688 flags |= O_CREAT|O_TRUNC; |
1686 flags |= O_CREAT|O_TRUNC; |
1689 } else if (attrSym == @symbol(OPEN_EXISTING)) { |
1687 } else if (attrSym == @symbol(OPEN_EXISTING)) { |
1690 // nothing to be set |
1688 // nothing to be set |
1691 } else if (attrSym == @symbol(OPEN_ALWAYS)) { |
1689 } else if (attrSym == @symbol(OPEN_ALWAYS)) { |
1692 flags |= O_CREAT; |
1690 flags |= O_CREAT; |
1693 } else if (attrSym == @symbol(TRUNCATE_EXISTING)) { |
1691 } else if (attrSym == @symbol(TRUNCATE_EXISTING)) { |
1694 flags |= O_TRUNC; |
1692 flags |= O_TRUNC; |
1695 |
1693 |
1696 } else if (attrSym == @symbol(FILE_ATTRIBUTE_HIDDEN)) { |
1694 } else if (attrSym == @symbol(FILE_ATTRIBUTE_HIDDEN)) { |
1697 // ignore |
1695 // ignore |
1698 } else if (attrSym == @symbol(FILE_ATTRIBUTE_READONLY)) { |
1696 } else if (attrSym == @symbol(FILE_ATTRIBUTE_READONLY)) { |
1699 accessMode &= 0444; |
1697 accessMode &= 0444; |
1700 } else if (attrSym == @symbol(FILE_FLAG_WRITE_THROUGH)) { |
1698 } else if (attrSym == @symbol(FILE_FLAG_WRITE_THROUGH)) { |
1701 #ifdef O_DIRECT |
1699 #ifdef O_DIRECT |
1702 flags |= O_DIRECT; |
1700 flags |= O_DIRECT; |
1703 #endif |
1701 #endif |
1704 } else if (attrSym == @symbol(FILE_FLAG_SEQUENTIAL_SCAN)) { |
1702 } else if (attrSym == @symbol(FILE_FLAG_SEQUENTIAL_SCAN)) { |
1705 // ignore |
1703 // ignore |
1706 } else if (attrSym == @symbol(FILE_FLAG_DELETE_ON_CLOSE)) { |
1704 } else if (attrSym == @symbol(FILE_FLAG_DELETE_ON_CLOSE)) { |
1707 // ignore; |
1705 // ignore; |
1708 } else if (!__isSymbol(attrSym) && __isStringLike(attrSym)) { |
1706 } else if (!__isSymbol(attrSym) && __isStringLike(attrSym)) { |
1709 __openmode = __stringVal(attrSym); |
1707 __openmode = __stringVal(attrSym); |
1710 } else { |
1708 } else { |
1711 console_fprintf(stderr, "UNIXOS [warning]: unsupported open mode\n"); |
1709 console_fprintf(stderr, "UNIXOS [warning]: unsupported open mode\n"); |
1712 } |
1710 } |
1713 } |
1711 } |
1714 } |
1712 } |
1715 do { |
1713 do { |
1716 __BEGIN_INTERRUPTABLE__ |
1714 __BEGIN_INTERRUPTABLE__ |
1717 fd = open((char *) __stringVal(encodedPathName), flags, accessMode); |
1715 fd = open((char *) __stringVal(encodedPathName), flags, accessMode); |
1718 __END_INTERRUPTABLE__ |
1716 __END_INTERRUPTABLE__ |
1719 } while ((fd < 0) && (__threadErrno == EINTR)); |
1717 } while ((fd < 0) && (__threadErrno == EINTR)); |
1720 |
1718 |
1721 if (fd >= 0) { |
1719 if (fd >= 0) { |
1722 __threadErrno = 0; |
1720 __threadErrno = 0; |
1723 f = fdopen(fd, __openmode); |
1721 f = fdopen(fd, __openmode); |
1724 if (f == NULL) { |
1722 if (f == NULL) { |
1725 close(fd); // fdopen failed, close before retry. |
1723 close(fd); // fdopen failed, close before retry. |
1726 } |
1724 } |
1727 } |
1725 } |
1728 } |
1726 } |
1729 |
1727 |
1730 # endif /* not WIN32 */ |
1728 # endif /* not WIN32 */ |
1731 #endif /* not VMS */ |
1729 #endif /* not VMS */ |
1732 |
1730 |
1733 |
1731 |
1734 if (f == NULL) { |
1732 if (f == NULL) { |
1735 /* |
1733 /* |
1736 * If no filedescriptors available, try to finalize |
1734 * If no filedescriptors available, try to finalize |
1737 * possibly collected fd's and try again. |
1735 * possibly collected fd's and try again. |
1738 */ |
1736 */ |
1739 if ((__threadErrno == ENFILE || __threadErrno == EMFILE) && pass == 0) { |
1737 if ((__threadErrno == ENFILE || __threadErrno == EMFILE) && pass == 0) { |
1740 pass = 1; |
1738 pass = 1; |
1741 __SSEND0(@global(ObjectMemory), @symbol(scavenge), 0); |
1739 __SSEND0(@global(ObjectMemory), @symbol(scavenge), 0); |
1742 __SSEND0(@global(ObjectMemory), @symbol(finalize), 0); |
1740 __SSEND0(@global(ObjectMemory), @symbol(finalize), 0); |
1743 goto retry; |
1741 goto retry; |
1744 } |
1742 } |
1745 badArgument: |
1743 badArgument: |
1746 getOutOfHere: |
1744 getOutOfHere: |
1747 error = __mkSmallInteger(__threadErrno); |
1745 error = __mkSmallInteger(__threadErrno); |
1748 __INST(position) = nil; |
1746 __INST(position) = nil; |
1749 } else { |
1747 } else { |
1750 #ifdef __VMS__ |
1748 #ifdef __VMS__ |
1751 /* |
1749 /* |
1752 * check to see if this is positionable ... |
1750 * check to see if this is positionable ... |
1753 */ |
1751 */ |
1754 __INST(canPosition) = false; |
1752 __INST(canPosition) = false; |
1755 # ifndef _POSIX_C_SOURCE |
1753 # ifndef _POSIX_C_SOURCE |
1756 { |
1754 { |
1757 struct stat statBuffer; |
1755 struct stat statBuffer; |
1758 |
1756 |
1759 if (fstat(fileno(f), &statBuffer) >= 0) { |
1757 if (fstat(fileno(f), &statBuffer) >= 0) { |
1760 switch (statBuffer.st_fab_rfm) { |
1758 switch (statBuffer.st_fab_rfm) { |
1761 case FAB$C_UDF: /* undefined (also stream binary) */ |
1759 case FAB$C_UDF: /* undefined (also stream binary) */ |
1762 case FAB$C_VAR: /* variable length records */ |
1760 case FAB$C_VAR: /* variable length records */ |
1763 case FAB$C_VFC: /* variable fixed control */ |
1761 case FAB$C_VFC: /* variable fixed control */ |
1764 case FAB$C_STM: /* RMS-11 stream (valid only for sequen) */ |
1762 case FAB$C_STM: /* RMS-11 stream (valid only for sequen) */ |
1765 default: |
1763 default: |
1766 __INST(canPosition) = false; |
1764 __INST(canPosition) = false; |
1767 break; |
1765 break; |
1768 |
1766 |
1769 case FAB$C_FIX: /* fixed length records */ |
1767 case FAB$C_FIX: /* fixed length records */ |
1770 case FAB$C_STMLF: /* LF stream (valid only for sequential) */ |
1768 case FAB$C_STMLF: /* LF stream (valid only for sequential) */ |
1771 case FAB$C_STMCR: /* CR stream (valid only for sequential) */ |
1769 case FAB$C_STMCR: /* CR stream (valid only for sequential) */ |
1772 __INST(canPosition) = true; |
1770 __INST(canPosition) = true; |
1773 break; |
1771 break; |
1774 } |
1772 } |
1775 } |
1773 } |
1776 } |
1774 } |
1777 # endif |
1775 # endif |
1778 #else /* not VMS */ |
1776 #else /* not VMS */ |
1779 __INST(canPosition) = true; |
1777 __INST(canPosition) = true; |
1780 #endif /* not VMS */ |
1778 #endif /* not VMS */ |
1781 |
1779 |
1782 if (@global(FileOpenTrace) == true) { |
1780 if (@global(FileOpenTrace) == true) { |
1783 console_fprintf(stderr, "fopen %s [FileStream] -> %"_lx_"\n", __stringVal(pathName), (INT)f); |
1781 console_fprintf(stderr, "fopen %s [FileStream] -> %"_lx_"\n", __stringVal(pathName), (INT)f); |
1784 } |
1782 } |
1785 if (f != NULL) { |
1783 if (f != NULL) { |
1786 OBJ fp; |
1784 OBJ fp; |
1787 |
1785 |
1788 wasBlocked = __BLOCKINTERRUPTS(); |
1786 wasBlocked = __BLOCKINTERRUPTS(); |
1789 #if 0 |
1787 #if 0 |
1790 // The original code was: |
1788 // The original code was: |
1791 __INST(handle) = fp = __MKEXTERNALADDRESS(f); __STORE(self, fp); |
1789 __INST(handle) = fp = __MKEXTERNALADDRESS(f); __STORE(self, fp); |
1792 // but for that, gcc generates wrong code, which loads self (volatile) into |
1790 // but for that, gcc generates wrong code, which loads self (volatile) into |
1793 // a register (bp), then calls __MKEXTERNALADDRESS, then stores indirect bp. |
1791 // a register (bp), then calls __MKEXTERNALADDRESS, then stores indirect bp. |
1794 // That is wrong if a scavenge occurs in __MKEXTERNALADDRESS, as bp is now still pointing to the old |
1792 // That is wrong if a scavenge occurs in __MKEXTERNALADDRESS, as bp is now still pointing to the old |
1795 // object. |
1793 // object. |
1796 #else |
1794 #else |
1797 fp = __MKEXTERNALADDRESS(f); |
1795 fp = __MKEXTERNALADDRESS(f); |
1798 __INST(handle) = fp; |
1796 __INST(handle) = fp; |
1799 __STORE(self, fp); |
1797 __STORE(self, fp); |
1800 #endif |
1798 #endif |
1801 } |
1799 } |
1802 } |
1800 } |
1803 %}. |
1801 %}. |
1804 error notNil ifTrue:[ |
1802 error notNil ifTrue:[ |
1805 lastErrorNumber := error. |
1803 lastErrorNumber := error. |
1806 ^ self openError:error. |
1804 ^ self openError:error. |
1807 ]. |
1805 ]. |
1808 handle isNil ifTrue:[ |
1806 handle isNil ifTrue:[ |
1809 ^ self openError:0. |
1807 ^ self openError:0. |
1810 ]. |
1808 ]. |
1811 |
1809 |
1812 position := 0. |
1810 position := 0. |
1813 handleType := #filePointer. |
1811 handleType := #filePointer. |
1814 Lobby register:self. |
1812 self registerForFinalization. |
1815 wasBlocked == false ifTrue:[OperatingSystem unblockInterrupts]. |
1813 wasBlocked == false ifTrue:[OperatingSystem unblockInterrupts]. |
1816 ^ handle |
1814 ^ handle |
1817 ! |
1815 ! |
1818 |
1816 |
1819 openForAppending |
1817 openForAppending |