mirror of https://git.wuffs.org/MWCC
962 lines
21 KiB
C
962 lines
21 KiB
C
#include "oslib.h"
|
|
#include <dirent.h>
|
|
#include <errno.h>
|
|
#include <sys/stat.h>
|
|
#include <sys/times.h>
|
|
#include <time.h>
|
|
#include <utime.h>
|
|
#include <fcntl.h>
|
|
#include <unistd.h>
|
|
|
|
enum {
|
|
OSErrNeg2 = -2
|
|
};
|
|
|
|
static char *lastdlerr;
|
|
static char intbuf[256];
|
|
enum { MAX_PATH = 256 };
|
|
|
|
#define CONVERT_SPEC(spec, pathbuf) \
|
|
do { \
|
|
int _plen = strlen((spec)->path.s); \
|
|
int _nlen = strlen((spec)->name.s); \
|
|
if (_plen + _nlen >= sizeof(pathbuf)) return 63; \
|
|
memcpy((pathbuf), (spec)->path.s, _plen); \
|
|
memcpy((pathbuf) + _plen, (spec)->name.s, _nlen + 1); \
|
|
} while (0)
|
|
|
|
#define CONVERT_PATHSPEC(spec, pathbuf) \
|
|
do { \
|
|
int _plen = strlen((spec)->s); \
|
|
if (_plen >= sizeof(pathbuf)) return 63;\
|
|
memcpy((pathbuf), (spec)->s, _plen + 1);\
|
|
if (_plen > 1) { \
|
|
if ((pathbuf)[_plen - 1] == OS_PATHSEP) \
|
|
(pathbuf)[_plen - 1] = 0; \
|
|
} \
|
|
} while (0)
|
|
|
|
const char *OS_GetErrText(int err) {
|
|
if (err == -2) {
|
|
return !lastdlerr ? "Shared library function failed" : lastdlerr;
|
|
} else {
|
|
return strerror(err);
|
|
}
|
|
}
|
|
|
|
int OS_InitProgram(int *pArgc, char ***pArgv) {
|
|
return 0;
|
|
}
|
|
|
|
int OS_TermProgram() {
|
|
return 0;
|
|
}
|
|
|
|
uOSTypePair OS_TEXTTYPE = {0666};
|
|
|
|
int OS_Create(const OSSpec *spec, const uOSTypePair *type) {
|
|
int h;
|
|
int err;
|
|
|
|
CONVERT_SPEC(spec, intbuf);
|
|
h = open(intbuf, O_CREAT | O_TRUNC, type->perm);
|
|
if (h < 0)
|
|
return errno;
|
|
close(h);
|
|
|
|
err = OS_SetFileType(spec, type);
|
|
return ((err == 0) || (err == EPERM)) ? 0 : err;
|
|
}
|
|
|
|
int OS_Status(const OSSpec *spec) {
|
|
struct stat st;
|
|
CONVERT_SPEC(spec, intbuf);
|
|
if (stat(intbuf, &st))
|
|
return errno;
|
|
else
|
|
return 0;
|
|
}
|
|
|
|
int OS_GetFileType(const OSSpec *spec, uOSTypePair *type) {
|
|
struct stat st;
|
|
CONVERT_SPEC(spec, intbuf);
|
|
if (stat(intbuf, &st) < 0)
|
|
return errno;
|
|
type->perm = st.st_mode;
|
|
return 0;
|
|
}
|
|
|
|
int OS_SetFileType(const OSSpec *spec, const uOSTypePair *type) {
|
|
int oldmask;
|
|
int err;
|
|
|
|
CONVERT_SPEC(spec, intbuf);
|
|
oldmask = umask(0);
|
|
err = chmod(intbuf, type->perm & ~oldmask);
|
|
umask(oldmask);
|
|
|
|
if (err < 0)
|
|
return errno;
|
|
return 0;
|
|
}
|
|
|
|
int OS_GetFileTime(const OSSpec *spec, time_t *crtm, time_t *chtm) {
|
|
struct stat st;
|
|
CONVERT_SPEC(spec, intbuf);
|
|
if (stat(intbuf, &st) < 0)
|
|
return errno;
|
|
if (crtm)
|
|
*crtm = st.st_ctimespec.tv_sec;
|
|
if (chtm)
|
|
*chtm = st.st_mtimespec.tv_sec;
|
|
return 0;
|
|
}
|
|
|
|
int OS_SetFileTime(const OSSpec *spec, const time_t *crtm, const time_t *chtm) {
|
|
struct utimbuf buf;
|
|
struct stat st;
|
|
CONVERT_SPEC(spec, intbuf);
|
|
if (stat(intbuf, &st) < 0)
|
|
return errno;
|
|
buf.actime = chtm ? *chtm : st.st_atimespec.tv_sec;
|
|
buf.modtime = crtm ? *crtm : st.st_mtimespec.tv_sec;
|
|
if (utime(intbuf, &buf) < 0)
|
|
return errno;
|
|
return 0;
|
|
}
|
|
|
|
int OS_Open(const OSSpec *spec, OSOpenMode mode, int *ref) {
|
|
static int modetrans[4] = {
|
|
O_RDONLY,
|
|
O_WRONLY,
|
|
O_RDWR,
|
|
O_RDONLY | O_APPEND
|
|
};
|
|
CONVERT_SPEC(spec, intbuf);
|
|
*ref = open(intbuf, modetrans[mode]);
|
|
if (*ref < 0) {
|
|
*ref = -1;
|
|
return errno;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
int OS_Write(int ref, const void *buffer, UInt32 *length) {
|
|
struct stat st;
|
|
UInt32 pos;
|
|
|
|
if (fstat(ref, &st) < 0)
|
|
return errno;
|
|
|
|
pos = lseek(ref, 0, SEEK_CUR);
|
|
if (pos > st.st_size && !*length) {
|
|
lseek(ref, -1, SEEK_CUR);
|
|
if (write(ref, "", 1) != 1) {
|
|
*length = 0;
|
|
return errno;
|
|
}
|
|
}
|
|
|
|
*length = write(ref, buffer, *length);
|
|
if (((SInt32) *length) < 0)
|
|
return errno;
|
|
return 0;
|
|
}
|
|
|
|
int OS_Read(int ref, void *buffer, UInt32 *length) {
|
|
*length = read(ref, buffer, *length);
|
|
if (((SInt32) *length) < 0)
|
|
return errno;
|
|
return 0;
|
|
}
|
|
|
|
int OS_Seek(int ref, OSSeekMode how, SInt32 offset) {
|
|
static int howtrans[3] = {
|
|
SEEK_CUR,
|
|
SEEK_SET,
|
|
SEEK_END
|
|
};
|
|
|
|
return (lseek(ref, offset, howtrans[how]) < 0) ? errno : 0;
|
|
}
|
|
|
|
int OS_Tell(int ref, SInt32 *offset) {
|
|
*offset = lseek(ref, 0, SEEK_CUR);
|
|
if (*offset < 0)
|
|
return errno;
|
|
else
|
|
return 0;
|
|
}
|
|
|
|
int OS_Close(int ref) {
|
|
if (ref == -1)
|
|
return EBADF;
|
|
|
|
if (close(ref))
|
|
return errno;
|
|
else
|
|
return 0;
|
|
}
|
|
|
|
int OS_GetSize(int ref, UInt32 *length) {
|
|
struct stat st;
|
|
if (fstat(ref, &st) < 0) {
|
|
return errno;
|
|
} else {
|
|
*length = st.st_size;
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
int OS_SetSize(int ref, UInt32 size) {
|
|
if (ftruncate(ref, size))
|
|
return errno;
|
|
else
|
|
return 0;
|
|
}
|
|
|
|
int OS_Delete(const OSSpec *spec) {
|
|
CONVERT_SPEC(spec, intbuf);
|
|
if (unlink(intbuf))
|
|
return errno;
|
|
else
|
|
return 0;
|
|
}
|
|
|
|
int OS_Rename(const OSSpec *oldspec, const OSSpec *newspec) {
|
|
char newbuf[256];
|
|
CONVERT_SPEC(newspec, newbuf);
|
|
CONVERT_SPEC(oldspec, intbuf);
|
|
return rename(intbuf, newbuf) ? errno : 0;
|
|
}
|
|
|
|
int OS_Mkdir(const OSSpec *spec) {
|
|
CONVERT_SPEC(spec, intbuf);
|
|
if (mkdir(intbuf, 0777))
|
|
return errno;
|
|
else
|
|
return 0;
|
|
}
|
|
|
|
int OS_Rmdir(const OSPathSpec *spec) {
|
|
CONVERT_PATHSPEC(spec, intbuf);
|
|
if (rmdir(intbuf))
|
|
return errno;
|
|
else
|
|
return 0;
|
|
}
|
|
|
|
int OS_Chdir(const OSPathSpec *spec) {
|
|
CONVERT_PATHSPEC(spec, intbuf);
|
|
if (chdir(intbuf))
|
|
return errno;
|
|
else
|
|
return 0;
|
|
}
|
|
|
|
int OS_GetCWD(OSPathSpec *spec) {
|
|
char *ptr;
|
|
if (!getcwd(spec->s, sizeof(spec->s)))
|
|
return errno;
|
|
|
|
ptr = &spec->s[strlen(spec->s)];
|
|
if (ptr[-1] != OS_PATHSEP)
|
|
strcpy(ptr, "/");
|
|
return 0;
|
|
}
|
|
|
|
extern char **environ;
|
|
int OS_Execute(OSSpec *spec, char **argv, char **envp, const char *stdoutfile, const char *stderrfile, int *exitcode) {
|
|
int svstdout;
|
|
int svstderr;
|
|
pid_t kidpid;
|
|
int status;
|
|
int err; // not in stabs but i think this exists...?
|
|
|
|
if (stdoutfile) {
|
|
svstdout = dup(1);
|
|
close(1);
|
|
if (open(stdoutfile, O_CREAT|O_TRUNC|O_WRONLY, 0666) < 0) {
|
|
status = errno;
|
|
dup2(svstdout, 1);
|
|
close(svstdout);
|
|
return status;
|
|
}
|
|
}
|
|
|
|
if (stderrfile) {
|
|
svstderr = dup(2);
|
|
close(2);
|
|
if (open(stderrfile, O_CREAT|O_TRUNC|O_WRONLY, 0666) < 0) {
|
|
status = errno;
|
|
dup2(svstderr, 2);
|
|
close(svstderr);
|
|
return status;
|
|
}
|
|
}
|
|
|
|
kidpid = fork();
|
|
if (!kidpid) {
|
|
if (execve(argv[0], argv, (envp && envp[0]) ? envp : environ) < 0)
|
|
exit(-1);
|
|
return EINVAL;
|
|
} else {
|
|
if (stdoutfile) {
|
|
dup2(svstdout, 1);
|
|
close(svstdout);
|
|
}
|
|
if (stderrfile) {
|
|
dup2(svstderr, 2);
|
|
close(svstderr);
|
|
}
|
|
*exitcode = 0;
|
|
|
|
err = (waitpid(kidpid, &status, 0) <= 0) ? errno : 0;
|
|
|
|
if (!(status & 0x7F))
|
|
*exitcode = status >> 8;
|
|
|
|
if ((status & 0x7F) != 0x7F && (status & 0x7F) != 0)
|
|
*exitcode = -(status & 0x7F);
|
|
|
|
return err;
|
|
}
|
|
}
|
|
|
|
int OS_IsLegalPath(const char *path) {
|
|
const char *scan = path;
|
|
int pthlen;
|
|
int fnlen;
|
|
|
|
pthlen = 0;
|
|
fnlen = 0;
|
|
|
|
while (*scan) {
|
|
if (*scan == OS_PATHSEP)
|
|
fnlen = 0;
|
|
else
|
|
fnlen++;
|
|
++pthlen;
|
|
if (fnlen > 63 || pthlen > 255)
|
|
return ENAMETOOLONG;
|
|
++scan;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
int OS_IsFullPath(const char *path) {
|
|
return path[0] == OS_PATHSEP;
|
|
}
|
|
|
|
char *OS_GetDirPtr(char *path) {
|
|
return path;
|
|
}
|
|
|
|
static int OS_CompactPath(char *src, char *dst) {
|
|
char buf[256];
|
|
char *bptr;
|
|
char *to;
|
|
char *from;
|
|
char *start;
|
|
char *brk;
|
|
|
|
start = OS_GetDirPtr(src);
|
|
if (dst == NULL)
|
|
bptr = buf;
|
|
else
|
|
bptr = dst;
|
|
|
|
strncpy(bptr, src, start - src);
|
|
bptr = bptr + (start - src);
|
|
from = start;
|
|
to = bptr;
|
|
while (*from) {
|
|
brk = from + 1;
|
|
while (*brk && *brk != OS_PATHSEP)
|
|
++brk;
|
|
|
|
if ((brk - from) == 1) {
|
|
from = brk;
|
|
} else if ((brk - from) == 2 && from[1] == '.') {
|
|
from = brk;
|
|
} else if ((brk - from) == 3 && from[1] == '.' && from[2] == '.') {
|
|
if (to > bptr) {
|
|
do {
|
|
to--;
|
|
} while (to >= bptr && *to != OS_PATHSEP);
|
|
}
|
|
from = brk;
|
|
} else {
|
|
while (from < brk) {
|
|
*(to++) = *(from++);
|
|
}
|
|
}
|
|
}
|
|
|
|
if (to == bptr || from[-1] == OS_PATHSEP)
|
|
*(to++) = OS_PATHSEP;
|
|
*to = 0;
|
|
|
|
if (!dst)
|
|
strcpy(src, buf);
|
|
|
|
return 0;
|
|
}
|
|
|
|
int OS_EqualPath(const char *a, const char *b) {
|
|
return !strcmp(a, b);
|
|
}
|
|
|
|
int OS_CanonPath(const char *src, char *dst) {
|
|
int idx;
|
|
|
|
if (strlen(src) > 255)
|
|
return ENAMETOOLONG;
|
|
|
|
if (!dst)
|
|
dst = (char *) src;
|
|
|
|
for (idx = 0; src[idx]; idx++) {
|
|
if (src[idx] == '\\')
|
|
dst[idx] = OS_PATHSEP;
|
|
else
|
|
dst[idx] = src[idx];
|
|
}
|
|
|
|
dst[idx] = 0;
|
|
return 0;
|
|
}
|
|
|
|
int OS_MakeSpec(const char *path, OSSpec *spec, Boolean *isfile) {
|
|
char tmp[256];
|
|
struct stat st;
|
|
char *ptr;
|
|
int len;
|
|
int err;
|
|
char *end;
|
|
char orig[256];
|
|
|
|
spec->name.s[0] = 0;
|
|
spec->path.s[0] = 0;
|
|
err = OS_CanonPath((char *) path, tmp);
|
|
if (err)
|
|
return err;
|
|
|
|
if (!OS_IsFullPath(tmp)) {
|
|
strcpy(orig, tmp);
|
|
if (!getcwd(tmp, sizeof(tmp)))
|
|
return errno;
|
|
|
|
ptr = tmp + strlen(tmp) - 1;
|
|
if (ptr[0] != OS_PATHSEP) {
|
|
ptr[1] = OS_PATHSEP;
|
|
ptr[2] = 0;
|
|
ptr += 2;
|
|
}
|
|
|
|
if (((ptr - tmp) + strlen(orig)) >= 256)
|
|
return ENAMETOOLONG;
|
|
|
|
strcpy(ptr, orig);
|
|
} else {
|
|
if (strlen(tmp) >= 256)
|
|
return ENAMETOOLONG;
|
|
}
|
|
|
|
err = OS_CompactPath(tmp, 0);
|
|
if (err)
|
|
return err;
|
|
err = OS_IsLegalPath(tmp);
|
|
if (err)
|
|
return err;
|
|
|
|
if (!stat(tmp, &st)) {
|
|
ptr = tmp + strlen(tmp);
|
|
if (ptr[-1] == OS_PATHSEP)
|
|
ptr--;
|
|
if ((st.st_mode & S_IFMT) == S_IFDIR) {
|
|
if (isfile)
|
|
*isfile = 0;
|
|
ptr[0] = OS_PATHSEP;
|
|
ptr++;
|
|
} else {
|
|
if (isfile)
|
|
*isfile = 1;
|
|
}
|
|
*ptr = 0;
|
|
} else {
|
|
if (errno != ENOENT)
|
|
return errno;
|
|
if (isfile)
|
|
*isfile = 1;
|
|
}
|
|
|
|
ptr = strrchr(tmp, OS_PATHSEP) + 1;
|
|
len = ptr - tmp;
|
|
if (len >= 256) {
|
|
spec->path.s[0] = 0;
|
|
return ENAMETOOLONG;
|
|
}
|
|
|
|
memcpy(spec->path.s, tmp, len);
|
|
spec->path.s[len] = 0;
|
|
|
|
len = strlen(ptr);
|
|
if (len >= 64) {
|
|
spec->name.s[0] = 0;
|
|
return ENAMETOOLONG;
|
|
}
|
|
|
|
memcpy(spec->name.s, ptr, len);
|
|
spec->name.s[len] = 0;
|
|
|
|
return 0;
|
|
}
|
|
|
|
int OS_MakeFileSpec(const char *path, OSSpec *spec) {
|
|
Boolean isfile;
|
|
int err;
|
|
|
|
err = OS_MakeSpec(path, spec, &isfile);
|
|
if (err)
|
|
return err;
|
|
else
|
|
return (isfile != 0) ? 0 : EISDIR;
|
|
}
|
|
|
|
int OS_MakePathSpec(const char *vol, const char *dir, OSPathSpec *spec) {
|
|
Boolean isfile;
|
|
OSSpec tmp;
|
|
int err;
|
|
char path[256];
|
|
|
|
if (((vol ? strlen(vol) : 0) + (dir ? strlen(dir) : 0) + 2) > 256)
|
|
return ENAMETOOLONG;
|
|
|
|
sprintf(path,
|
|
"%s%s%s",
|
|
vol ? (strchr("/\\:", vol[0]) ? "" : "/") : "",
|
|
vol ? vol : "",
|
|
dir ? dir : ""
|
|
);
|
|
|
|
err = OS_MakeSpec(path, &tmp, &isfile);
|
|
strcpy(spec->s, tmp.path.s);
|
|
if (err)
|
|
return err;
|
|
|
|
if (isfile)
|
|
return !OS_Status(&tmp) ? ENOTDIR : ENOENT;
|
|
|
|
return 0;
|
|
}
|
|
|
|
int OS_MakeNameSpec(const char *name, OSNameSpec *spec) {
|
|
int len;
|
|
|
|
len = strlen(name);
|
|
spec->s[0] = 0;
|
|
if (len > 63)
|
|
return ENAMETOOLONG;
|
|
if (strchr(name, OS_PATHSEP))
|
|
return EISDIR;
|
|
if (strlen(name) > 63)
|
|
return ENAMETOOLONG;
|
|
memcpy(spec->s, name, len + 1);
|
|
return 0;
|
|
}
|
|
|
|
int OS_GetRootSpec(OSPathSpec *spec) {
|
|
strcpy(spec->s, "/");
|
|
return 0;
|
|
}
|
|
|
|
char *OS_SpecToString(const OSSpec *spec, char *path, int size) {
|
|
int plen;
|
|
int nlen;
|
|
|
|
if (!size)
|
|
size = 256;
|
|
|
|
if (!path) {
|
|
path = malloc(size);
|
|
if (!path)
|
|
return 0;
|
|
}
|
|
|
|
plen = strlen(spec->path.s);
|
|
nlen = strlen(spec->name.s);
|
|
if ((plen + nlen) >= size) {
|
|
if (plen >= size) {
|
|
nlen = 0;
|
|
plen = size - 1;
|
|
} else {
|
|
nlen = (size - plen) - 1;
|
|
}
|
|
}
|
|
|
|
memcpy(path, spec->path.s, plen);
|
|
memcpy(&path[plen], spec->name.s, nlen);
|
|
path[plen + nlen] = 0;
|
|
return path;
|
|
}
|
|
|
|
char *OS_PathSpecToString(const OSPathSpec *pspec, char *path, int size) {
|
|
int plen;
|
|
|
|
if (!size)
|
|
size = 256;
|
|
|
|
if (!path) {
|
|
path = malloc(size);
|
|
if (!path)
|
|
return 0;
|
|
}
|
|
|
|
plen = strlen(pspec->s);
|
|
if (plen >= size)
|
|
plen = size - 1;
|
|
|
|
memcpy(path, pspec->s, plen);
|
|
path[plen] = 0;
|
|
return path;
|
|
}
|
|
|
|
char *OS_NameSpecToString(const OSNameSpec *nspec, char *name, int size) {
|
|
int nlen;
|
|
|
|
if (!size)
|
|
size = 64;
|
|
|
|
if (!name) {
|
|
name = malloc(size);
|
|
if (!name)
|
|
return 0;
|
|
}
|
|
|
|
nlen = strlen(nspec->s);
|
|
if (nlen >= size)
|
|
nlen = size - 1;
|
|
|
|
memcpy(name, nspec->s, nlen);
|
|
name[nlen] = 0;
|
|
return name;
|
|
}
|
|
|
|
int OS_SizeOfPathSpec(const OSPathSpec *spec) {
|
|
return strlen(spec->s) + 1;
|
|
}
|
|
|
|
int OS_SizeOfNameSpec(const OSNameSpec *spec) {
|
|
return strlen(spec->s) + 1;
|
|
}
|
|
|
|
int OS_EqualSpec(const OSSpec *a, const OSSpec *b) {
|
|
return OS_EqualPathSpec(&a->path, &b->path) && OS_EqualNameSpec(&a->name, &b->name);
|
|
}
|
|
|
|
int OS_EqualPathSpec(const OSPathSpec *a, const OSPathSpec *b) {
|
|
return !strcmp(a->s, b->s);
|
|
}
|
|
|
|
int OS_EqualNameSpec(const OSNameSpec *a, const OSNameSpec *b) {
|
|
return !strcmp(a->s, b->s);
|
|
}
|
|
|
|
int OS_IsDir(const OSSpec *spec) {
|
|
struct stat st;
|
|
|
|
if (!OS_SpecToString(spec, intbuf, sizeof(intbuf)))
|
|
return 0;
|
|
if (stat(intbuf, &st) < 0)
|
|
return 0;
|
|
return ((st.st_mode & S_IFMT) == S_IFDIR);
|
|
}
|
|
|
|
int OS_IsFile(const OSSpec *spec) {
|
|
struct stat st;
|
|
|
|
if (!OS_SpecToString(spec, intbuf, sizeof(intbuf)))
|
|
return 0;
|
|
if (stat(intbuf, &st) < 0)
|
|
return 0;
|
|
return ((st.st_mode & S_IFMT) != S_IFDIR);
|
|
}
|
|
|
|
int OS_IsLink(const OSSpec *spec) {
|
|
struct stat st;
|
|
char *ptr;
|
|
|
|
if (!OS_SpecToString(spec, intbuf, sizeof(intbuf)))
|
|
return 0;
|
|
|
|
ptr = intbuf + strlen(intbuf) - 1;
|
|
if (*ptr == OS_PATHSEP)
|
|
*ptr = 0;
|
|
|
|
if (lstat(intbuf, &st) < 0)
|
|
return 0;
|
|
|
|
return ((st.st_mode & S_IFMT) == S_IFLNK);
|
|
}
|
|
|
|
int OS_ResolveLink(const OSSpec *link, OSSpec *target) {
|
|
char fn[64];
|
|
char path[256];
|
|
int len;
|
|
|
|
if (!OS_SpecToString(link, intbuf, sizeof(intbuf)))
|
|
return ENAMETOOLONG;
|
|
|
|
len = readlink(intbuf, fn, sizeof(fn));
|
|
if (len < 0)
|
|
return errno;
|
|
fn[len] = 0;
|
|
|
|
sprintf(path, "%s%s", (fn[0] != OS_PATHSEP) ? link->path.s : "", fn);
|
|
return OS_MakeSpec(path, target, 0);
|
|
}
|
|
|
|
int OS_OpenDir(const OSPathSpec *spec, OSOpenedDir *ref) {
|
|
DIR *dptr;
|
|
|
|
CONVERT_PATHSPEC(spec, intbuf);
|
|
dptr = opendir(intbuf);
|
|
if (!dptr) {
|
|
ref->dir = 0;
|
|
return errno;
|
|
}
|
|
|
|
ref->spec = *spec;
|
|
ref->dir = dptr;
|
|
return 0;
|
|
}
|
|
|
|
int OS_ReadDir(OSOpenedDir *ref, OSSpec *spec, char *filename, Boolean *isfile) {
|
|
struct dirent *de;
|
|
char fn[256];
|
|
int err;
|
|
int len;
|
|
|
|
do {
|
|
de = readdir(ref->dir);
|
|
if (!de)
|
|
return ENOENT;
|
|
} while (!strcmp(de->d_name, ".") || !strcmp(de->d_name, "..") || (strlen(ref->spec.s) + strlen(de->d_name) >= 256));
|
|
|
|
len = strlen(ref->spec.s);
|
|
strncpy(fn, ref->spec.s, 255);
|
|
if (len < 256) {
|
|
strncpy(&fn[len], de->d_name, 255 - len);
|
|
fn[255] = 0;
|
|
} else {
|
|
return ENAMETOOLONG;
|
|
}
|
|
|
|
strncpy(filename, de->d_name, 63);
|
|
filename[63] = 0;
|
|
|
|
return OS_MakeSpec(fn, spec, isfile);
|
|
}
|
|
|
|
int OS_CloseDir(OSOpenedDir *ref) {
|
|
if (ref->dir)
|
|
return closedir(ref->dir);
|
|
else
|
|
return 0;
|
|
}
|
|
|
|
UInt32 OS_GetMilliseconds() {
|
|
struct tms tms;
|
|
return times(&tms) * 1000 / CLOCKS_PER_SEC;
|
|
}
|
|
|
|
void OS_GetTime(time_t *p) {
|
|
time(p);
|
|
}
|
|
|
|
int OS_NewHandle(UInt32 size, OSHandle *hand) {
|
|
hand->addr = 0;
|
|
hand->used = size;
|
|
hand->size = (size + 256) & ~255;
|
|
hand->addr = malloc(hand->size);
|
|
return !hand->addr ? ENOMEM : 0;
|
|
}
|
|
|
|
int OS_ResizeHandle(OSHandle *hand, UInt32 size) {
|
|
UInt32 nsize;
|
|
void *naddr;
|
|
|
|
nsize = (size + 256) & ~255;
|
|
naddr = realloc(hand->addr, nsize);
|
|
if (!naddr)
|
|
return ENOMEM;
|
|
|
|
hand->addr = naddr;
|
|
hand->size = nsize;
|
|
hand->used = size;
|
|
return 0;
|
|
}
|
|
|
|
void *OS_LockHandle(OSHandle *hand) {
|
|
return hand->addr;
|
|
}
|
|
|
|
void OS_UnlockHandle(OSHandle *hand) {
|
|
}
|
|
|
|
int OS_FreeHandle(OSHandle *hand) {
|
|
if (!hand->addr)
|
|
return ENOMEM;
|
|
|
|
free(hand->addr);
|
|
hand->size = 0;
|
|
hand->used = 0;
|
|
hand->addr = 0;
|
|
return 0;
|
|
}
|
|
|
|
int OS_GetHandleSize(OSHandle *hand, UInt32 *size) {
|
|
if (hand->addr) {
|
|
*size = hand->used;
|
|
return 0;
|
|
} else {
|
|
*size = 0;
|
|
return ENOMEM;
|
|
}
|
|
}
|
|
|
|
void OS_InvalidateHandle(OSHandle *hand) {
|
|
hand->addr = 0;
|
|
hand->used = 0;
|
|
}
|
|
|
|
Boolean OS_ValidHandle(OSHandle *hand) {
|
|
return (hand && hand->addr);
|
|
}
|
|
|
|
OSErr OS_MacError(int err) {
|
|
switch (err) {
|
|
case 0: return noErr;
|
|
case ENOENT /*2*/: return fnfErr;
|
|
case EFAULT /*14*/:
|
|
case EINVAL /*22*/: return paramErr;
|
|
case ENOTDIR /*20*/: return dirNFErr;
|
|
case EISDIR /*21*/: return notAFileErr;
|
|
case ENAMETOOLONG /*63*/: return bdNamErr;
|
|
case EBUSY /*16*/: return memLockedErr;
|
|
case E2BIG /*7*/:
|
|
case ENOMEM /*12*/: return memFullErr;
|
|
case EACCES /*13*/: return permErr;
|
|
case EIO /*5*/: return ioErr;
|
|
case EEXIST /*17*/: return dupFNErr;
|
|
case EMFILE /*24*/: return tmfoErr;
|
|
case EFBIG /*27*/: return fsDataTooBigErr;
|
|
case EBADF /*9*/: return rfNumErr;
|
|
case EINTR /*4*/: return abortErr;
|
|
default: return (OSErr) (0xFFFF8000 | err);
|
|
}
|
|
}
|
|
|
|
void OS_TimeToMac(time_t sectm, UInt32 *secs) {
|
|
struct tm *tmrec;
|
|
int years;
|
|
int ydays;
|
|
|
|
tmrec = localtime(§m);
|
|
years = tmrec->tm_year - 4;
|
|
|
|
ydays =
|
|
(years * 365) +
|
|
((years + 3) / 4) -
|
|
((years + 4) / 100) +
|
|
((years - 296) / 400);
|
|
|
|
*secs =
|
|
((ydays + tmrec->tm_yday) * 86400)
|
|
+ (tmrec->tm_hour * 3600)
|
|
+ (tmrec->tm_min * 60)
|
|
+ (tmrec->tm_sec)
|
|
+ (tmrec->tm_isdst ? -3600 : 0);
|
|
}
|
|
|
|
void OS_MacToTime(UInt32 secs, time_t *sectm) {
|
|
static int monthdays[12] = {
|
|
31, 28, 31, 30,
|
|
31, 30, 31, 31,
|
|
30, 31, 30, 31
|
|
};
|
|
struct tm tmrec;
|
|
int month;
|
|
|
|
memset(&tmrec, 0, sizeof(tmrec));
|
|
tmrec.tm_sec = secs % 60; // line 1523
|
|
tmrec.tm_min = (secs / 60) % 60; // line 1524
|
|
tmrec.tm_hour = (secs / 3600) % 24; // line 1525
|
|
tmrec.tm_yday = (secs / 86400) % 365;
|
|
tmrec.tm_year = (secs / 31536000) + 4; // line 1533
|
|
tmrec.tm_yday -=
|
|
((((secs / 31536000) + 3) / 4)
|
|
-
|
|
(((secs / 31536000) + 4) / 100)
|
|
+
|
|
((SInt32)((secs / 31536000) - 296) / 400))
|
|
;
|
|
|
|
if ((tmrec.tm_year % 4) && ((tmrec.tm_year % 100) || !(tmrec.tm_year % 400))) {
|
|
monthdays[1] = 28;
|
|
} else {
|
|
monthdays[1] = 29;
|
|
}
|
|
|
|
if (tmrec.tm_yday >= (monthdays[1] + 62) && tmrec.tm_yday < (monthdays[1] + 245)) {
|
|
tmrec.tm_hour++;
|
|
if (tmrec.tm_hour >= 24) {
|
|
tmrec.tm_yday++;
|
|
tmrec.tm_hour -= 24;
|
|
}
|
|
}
|
|
|
|
for (month = 0; tmrec.tm_yday >= monthdays[month]; month++) {
|
|
tmrec.tm_yday -= monthdays[month];
|
|
}
|
|
tmrec.tm_mon = month;
|
|
tmrec.tm_mday = tmrec.tm_yday + 1;
|
|
|
|
*sectm = mktime(&tmrec);
|
|
}
|
|
|
|
SInt16 OS_RefToMac(int ref) {
|
|
return (ref < -1) ? (SInt16) 0 : (SInt16) (ref + 1);
|
|
}
|
|
|
|
int OS_MacToRef(SInt16 refnum) {
|
|
return (refnum >= 0) ? (refnum - 1) : -1;
|
|
}
|
|
|
|
int OS_OpenLibrary(const char *a, void **lib) {
|
|
*lib = 0;
|
|
lastdlerr = "No support for shared libraries";
|
|
return OSErrNeg2;
|
|
}
|
|
|
|
int OS_GetLibrarySymbol(void *a, void *b, void **sym) {
|
|
*sym = 0;
|
|
lastdlerr = "No support for shared libraries";
|
|
return OSErrNeg2;
|
|
}
|
|
|
|
int OS_CloseLibrary(void *a) {
|
|
lastdlerr = "No support for shared libraries";
|
|
return OSErrNeg2;
|
|
}
|
|
|
|
int OS_LoadMacResourceFork(const OSSpec *spec, void **file_data, SInt32 *file_len) {
|
|
return ENOENT;
|
|
}
|
|
|
|
Boolean OS_IsMultiByte(const char *str, int offset) {
|
|
return 0;
|
|
}
|