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