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