2012-04-24 01:22:36 +00:00
|
|
|
/*
|
2019-08-18 11:21:00 +00:00
|
|
|
Copyright 2015 Wolfgang Thaller.
|
2012-04-24 01:22:36 +00:00
|
|
|
|
2019-08-18 11:21:00 +00:00
|
|
|
This file is part of Retro68.
|
2012-04-24 01:22:36 +00:00
|
|
|
|
2019-08-18 11:21:00 +00:00
|
|
|
Retro68 is free software: you can redistribute it and/or modify
|
|
|
|
it under the terms of the GNU General Public License as published by
|
|
|
|
the Free Software Foundation, either version 3 of the License, or
|
|
|
|
(at your option) any later version.
|
2012-04-24 01:22:36 +00:00
|
|
|
|
2019-08-18 11:21:00 +00:00
|
|
|
Retro68 is distributed in the hope that it will be useful,
|
|
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
GNU General Public License for more details.
|
2012-04-24 01:22:36 +00:00
|
|
|
|
2019-08-18 11:21:00 +00:00
|
|
|
Under Section 7 of GPL version 3, you are granted additional
|
|
|
|
permissions described in the GCC Runtime Library Exception, version
|
|
|
|
3.1, as published by the Free Software Foundation.
|
2015-07-15 21:23:19 +00:00
|
|
|
|
2019-08-18 11:21:00 +00:00
|
|
|
You should have received a copy of the GNU General Public License and
|
|
|
|
a copy of the GCC Runtime Library Exception along with this program;
|
|
|
|
see the files COPYING and COPYING.RUNTIME respectively. If not, see
|
|
|
|
<http://www.gnu.org/licenses/>.
|
2012-04-24 01:22:36 +00:00
|
|
|
*/
|
|
|
|
|
2012-03-29 08:29:41 +00:00
|
|
|
#include <sys/types.h>
|
|
|
|
#include <sys/stat.h>
|
|
|
|
#include <unistd.h>
|
2015-09-15 22:39:03 +00:00
|
|
|
#include <sys/time.h>
|
2017-10-08 17:28:10 +00:00
|
|
|
#include <reent.h>
|
|
|
|
#include <errno.h>
|
|
|
|
#include <fcntl.h>
|
2017-10-09 13:43:52 +00:00
|
|
|
#include <string.h>
|
|
|
|
#include <stdlib.h>
|
2015-09-15 22:39:03 +00:00
|
|
|
|
2012-03-29 08:29:41 +00:00
|
|
|
#include <MacMemory.h>
|
|
|
|
#include <Processes.h>
|
2017-10-08 17:28:10 +00:00
|
|
|
#include <Files.h>
|
|
|
|
#include <TextUtils.h>
|
2019-08-18 10:31:32 +00:00
|
|
|
#include <Errors.h>
|
2012-03-29 08:29:41 +00:00
|
|
|
|
2017-10-08 17:28:10 +00:00
|
|
|
void *_sbrk_r(struct _reent *reent, ptrdiff_t increment)
|
2012-03-29 08:29:41 +00:00
|
|
|
{
|
2019-08-18 11:21:00 +00:00
|
|
|
Debugger();
|
|
|
|
return NewPtrClear(increment);
|
2012-03-29 08:29:41 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void _exit(int status)
|
|
|
|
{
|
2019-08-18 11:21:00 +00:00
|
|
|
//if(status != 0)
|
|
|
|
// Debugger();
|
|
|
|
ExitToShell();
|
|
|
|
for(;;)
|
|
|
|
;
|
2012-03-29 08:29:41 +00:00
|
|
|
}
|
|
|
|
|
2014-09-30 09:00:33 +00:00
|
|
|
ssize_t _consolewrite(int fd, const void *buf, size_t count);
|
|
|
|
ssize_t _consoleread(int fd, void *buf, size_t count);
|
2014-09-17 01:35:18 +00:00
|
|
|
|
2017-10-08 17:28:10 +00:00
|
|
|
const int kMacRefNumOffset = 10;
|
|
|
|
|
|
|
|
ssize_t _write_r(struct _reent *reent, int fd, const void *buf, size_t count)
|
2012-03-29 08:29:41 +00:00
|
|
|
{
|
2019-08-18 11:21:00 +00:00
|
|
|
long cnt = count;
|
|
|
|
if(fd >= kMacRefNumOffset)
|
|
|
|
{
|
|
|
|
FSWrite(fd - kMacRefNumOffset, &cnt, buf);
|
|
|
|
return cnt;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
return _consolewrite(fd,buf,count);
|
2012-03-29 08:29:41 +00:00
|
|
|
}
|
|
|
|
|
2017-10-08 17:28:10 +00:00
|
|
|
ssize_t _read_r(struct _reent *reent, int fd, void *buf, size_t count)
|
2012-03-29 08:29:41 +00:00
|
|
|
{
|
2019-08-18 11:21:00 +00:00
|
|
|
long cnt = count;
|
|
|
|
if(fd >= kMacRefNumOffset)
|
|
|
|
{
|
|
|
|
FSRead(fd - kMacRefNumOffset, &cnt, buf);
|
|
|
|
return cnt;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
return _consoleread(fd,buf,count);
|
2012-03-29 08:29:41 +00:00
|
|
|
}
|
|
|
|
|
2017-10-08 17:28:10 +00:00
|
|
|
int _open_r(struct _reent *reent, const char* name, int flags, int mode)
|
2012-03-29 08:29:41 +00:00
|
|
|
{
|
2019-08-18 11:21:00 +00:00
|
|
|
Str255 pname;
|
2018-05-16 00:07:24 +00:00
|
|
|
#if TARGET_API_MAC_CARBON
|
2019-08-18 11:21:00 +00:00
|
|
|
// Carbon has the new, sane version.
|
|
|
|
c2pstrcpy(pname,name);
|
2018-05-16 00:07:24 +00:00
|
|
|
#else
|
2022-10-06 00:53:00 +00:00
|
|
|
// It is also available in various glue code libraries and
|
2019-08-18 11:21:00 +00:00
|
|
|
// in some versions of InterfaceLib, but it's confusing.
|
|
|
|
// Using the inplace variant, c2pstr, isn't much better than
|
|
|
|
// doing things by hand:
|
|
|
|
strncpy(&pname[1],name,255);
|
|
|
|
pname[0] = strlen(name);
|
2018-05-16 00:07:24 +00:00
|
|
|
#endif
|
2019-08-18 11:21:00 +00:00
|
|
|
short ref;
|
|
|
|
|
|
|
|
SInt8 permission;
|
|
|
|
switch(flags & O_ACCMODE)
|
|
|
|
{
|
|
|
|
case O_RDONLY:
|
|
|
|
permission = fsRdPerm;
|
|
|
|
break;
|
|
|
|
case O_WRONLY:
|
|
|
|
permission = fsWrPerm;
|
|
|
|
break;
|
|
|
|
case O_RDWR:
|
|
|
|
permission = fsRdWrPerm;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
if(flags & O_CREAT)
|
|
|
|
{
|
|
|
|
HCreate(0,0,pname,'????','TEXT');
|
|
|
|
}
|
|
|
|
|
|
|
|
OSErr err = HOpenDF(0,0,pname,fsRdWrPerm,&ref);
|
2018-03-28 17:17:22 +00:00
|
|
|
if(err == paramErr)
|
|
|
|
err = HOpen(0,0,pname,fsRdWrPerm,&ref);
|
2017-10-08 17:28:10 +00:00
|
|
|
|
2019-08-18 11:21:00 +00:00
|
|
|
if(err)
|
|
|
|
return -1; // TODO: errno
|
2017-10-08 17:28:10 +00:00
|
|
|
|
2019-08-18 11:21:00 +00:00
|
|
|
if(flags & O_TRUNC)
|
|
|
|
{
|
|
|
|
SetEOF(ref, 0);
|
|
|
|
}
|
2017-10-08 17:28:10 +00:00
|
|
|
|
2019-08-18 11:21:00 +00:00
|
|
|
return ref + kMacRefNumOffset;
|
2017-10-08 17:28:10 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
int _close_r(struct _reent *reent, int fd)
|
|
|
|
{
|
2019-08-18 11:21:00 +00:00
|
|
|
if(fd >= kMacRefNumOffset)
|
|
|
|
FSClose(fd - kMacRefNumOffset);
|
|
|
|
return 0;
|
2012-03-29 08:29:41 +00:00
|
|
|
}
|
|
|
|
|
2017-10-08 17:28:10 +00:00
|
|
|
int _fstat_r(struct _reent *reent, int fd, struct stat *buf)
|
2012-03-29 08:29:41 +00:00
|
|
|
{
|
2019-08-18 11:21:00 +00:00
|
|
|
return -1;
|
2012-03-29 08:29:41 +00:00
|
|
|
}
|
|
|
|
|
2017-10-08 17:28:10 +00:00
|
|
|
extern int _stat_r(struct _reent * reent, const char *fn, struct stat *buf)
|
2012-03-29 08:29:41 +00:00
|
|
|
{
|
2019-08-18 11:21:00 +00:00
|
|
|
return -1;
|
2012-03-29 08:29:41 +00:00
|
|
|
}
|
|
|
|
|
2017-10-08 17:28:10 +00:00
|
|
|
off_t _lseek_r(struct _reent *reent, int fd, off_t offset, int whence)
|
2012-03-29 08:29:41 +00:00
|
|
|
{
|
2019-08-18 11:21:00 +00:00
|
|
|
if(fd >= kMacRefNumOffset)
|
|
|
|
{
|
|
|
|
short posMode;
|
|
|
|
switch(whence)
|
|
|
|
{
|
|
|
|
case SEEK_SET:
|
|
|
|
posMode = fsFromStart;
|
|
|
|
break;
|
|
|
|
case SEEK_CUR:
|
|
|
|
posMode = fsFromMark;
|
|
|
|
break;
|
|
|
|
case SEEK_END:
|
|
|
|
posMode = fsFromLEOF;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
short ref = fd - kMacRefNumOffset;
|
|
|
|
SetFPos(ref, posMode, offset);
|
|
|
|
long finalPos;
|
|
|
|
GetFPos(ref, &finalPos);
|
|
|
|
return finalPos;
|
|
|
|
}
|
|
|
|
return (off_t) -1;
|
2012-03-29 08:29:41 +00:00
|
|
|
}
|
|
|
|
|
2017-10-08 17:28:10 +00:00
|
|
|
int _kill_r(struct _reent *reent, pid_t pid, int sig)
|
2012-03-29 08:29:41 +00:00
|
|
|
{
|
2019-08-18 11:21:00 +00:00
|
|
|
if(pid == 42)
|
|
|
|
_exit(42);
|
|
|
|
else
|
|
|
|
return -1;
|
2012-03-29 08:29:41 +00:00
|
|
|
}
|
|
|
|
|
2017-10-08 17:28:10 +00:00
|
|
|
pid_t _getpid_r(struct _reent *reent)
|
2012-03-29 08:29:41 +00:00
|
|
|
{
|
2019-08-18 11:21:00 +00:00
|
|
|
return 42;
|
2012-03-29 08:29:41 +00:00
|
|
|
}
|
2015-09-15 22:39:03 +00:00
|
|
|
|
2017-10-08 17:28:10 +00:00
|
|
|
int _fork_r(struct _reent *reent)
|
|
|
|
{
|
2019-08-18 11:21:00 +00:00
|
|
|
return -1;
|
2017-10-08 17:28:10 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
int _execve_r(struct _reent *reent, const char *fn, char *const * argv, char *const *envp)
|
|
|
|
{
|
2019-08-18 11:21:00 +00:00
|
|
|
return -1;
|
2017-10-08 17:28:10 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
int _fcntl_r(struct _reent *reent, int fd, int cmd, int arg)
|
|
|
|
{
|
2019-08-18 11:21:00 +00:00
|
|
|
return -1;
|
2017-10-08 17:28:10 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
int _isatty_r(struct _reent *reent, int fd)
|
|
|
|
{
|
2019-08-18 11:21:00 +00:00
|
|
|
return fd < kMacRefNumOffset;
|
2017-10-08 17:28:10 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
int _link_r(struct _reent *reent, const char *from, const char *to)
|
|
|
|
{
|
2019-08-18 11:21:00 +00:00
|
|
|
reent->_errno = EPERM;
|
|
|
|
return -1;
|
2017-10-08 17:28:10 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
int _mkdir_r(struct _reent *reent, const char *fn, int mode)
|
|
|
|
{
|
2019-08-18 11:21:00 +00:00
|
|
|
return -1;
|
2017-10-08 17:28:10 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
int _rename_r(struct _reent *reent, const char *from, const char *to)
|
|
|
|
{
|
2019-08-18 11:21:00 +00:00
|
|
|
return -1;
|
2017-10-08 17:28:10 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
int _unlink_r(struct _reent *reent, const char *fn)
|
|
|
|
{
|
2019-08-18 11:21:00 +00:00
|
|
|
return -1;
|
2017-10-08 17:28:10 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
_CLOCK_T_ _times_r(struct _reent *reent, struct tms *buf)
|
|
|
|
{
|
2019-08-18 11:21:00 +00:00
|
|
|
reent->_errno = EACCES;
|
|
|
|
return -1;
|
2017-10-08 17:28:10 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
int _wait_r(struct _reent *reent, int *wstatus)
|
|
|
|
{
|
2019-08-18 11:21:00 +00:00
|
|
|
reent->_errno = ECHILD;
|
|
|
|
return -1; /* Always fails */
|
2017-10-08 17:28:10 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
int _gettimeofday_r(struct _reent *reent, struct timeval *tp, void *__tz)
|
2015-09-15 22:39:03 +00:00
|
|
|
{
|
2019-08-18 11:21:00 +00:00
|
|
|
/* Classic MacOS's GetDateTime function returns an integer.
|
2022-10-06 00:53:00 +00:00
|
|
|
* TickCount() has a slightly higher resolution, but is independent of the real-time clock.
|
2019-08-18 11:21:00 +00:00
|
|
|
*/
|
|
|
|
unsigned long secs;
|
|
|
|
GetDateTime(&secs);
|
|
|
|
unsigned long ticks = TickCount();
|
|
|
|
|
|
|
|
static unsigned long savedTicks = 0, savedSecs = 0;
|
|
|
|
|
|
|
|
if(!savedSecs)
|
|
|
|
{
|
|
|
|
savedTicks = ticks;
|
|
|
|
savedSecs = secs;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
unsigned long elapsedTicks = ticks - savedTicks;
|
|
|
|
unsigned long elapsedSecs = secs - savedSecs;
|
|
|
|
unsigned long expectedTicks = elapsedSecs * 60 + elapsedSecs * 3 / 20;
|
|
|
|
|
|
|
|
if(expectedTicks > elapsedTicks)
|
|
|
|
savedTicks = ticks;
|
|
|
|
else
|
|
|
|
savedTicks += expectedTicks;
|
|
|
|
savedSecs = secs;
|
|
|
|
}
|
|
|
|
|
|
|
|
if(tp)
|
|
|
|
{
|
2021-09-19 15:56:20 +00:00
|
|
|
const int epochDifferenceInYears = 1970 - 1904;
|
|
|
|
const int epochDifferenceInDays =
|
|
|
|
365 * epochDifferenceInYears
|
|
|
|
+ (epochDifferenceInYears + 3)/ 4; // round up for leap years
|
|
|
|
|
|
|
|
tp->tv_sec = secs - 86400 * epochDifferenceInDays;
|
2019-08-18 11:21:00 +00:00
|
|
|
tp->tv_usec = (ticks - savedTicks) * 20000000 / 2003;
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
2015-09-15 22:39:03 +00:00
|
|
|
}
|