mirror of https://git.wuffs.org/MWCC
447 lines
9.7 KiB
C
447 lines
9.7 KiB
C
#include "oslib.h"
|
|
#include <errno.h>
|
|
|
|
static char wildname[63];
|
|
static char wilddir[255];
|
|
static OSOpenedDir wilddirref;
|
|
static OSSpec wildmatch;
|
|
char STSbuf[256];
|
|
|
|
inline char dummyfunc(int ch) {
|
|
return ch;
|
|
}
|
|
|
|
int WildCardMatch(char *wild, char *name) {
|
|
char next;
|
|
char *prev;
|
|
|
|
if (!name[0])
|
|
return 0;
|
|
|
|
while (*wild) {
|
|
if (*wild == '*') {
|
|
wild++;
|
|
next = *wild;
|
|
prev = 0;
|
|
|
|
while (*name) {
|
|
if (dummyfunc(*name) == dummyfunc(next))
|
|
prev = name;
|
|
++name;
|
|
}
|
|
|
|
if (prev)
|
|
name = prev;
|
|
|
|
if (dummyfunc(*name) != dummyfunc(next))
|
|
return 0;
|
|
} else if (*wild == '?' && *name) {
|
|
wild++;
|
|
name++;
|
|
if (!*wild && *name)
|
|
return 0;
|
|
} else if (dummyfunc(*wild) == dummyfunc(*name)) {
|
|
wild++;
|
|
name++;
|
|
} else {
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
return !name[0] || (name[0] == OS_PATHSEP && !name[1]);
|
|
}
|
|
|
|
OSSpec *OS_MatchPath(const char *path) {
|
|
char filename[64];
|
|
Boolean isfile;
|
|
OSSpec spec;
|
|
const char *nptr;
|
|
|
|
if (path) {
|
|
nptr = strrchr(path, OS_PATHSEP);
|
|
if (!nptr) {
|
|
nptr = path;
|
|
strcpyn(wilddir, ".", -1, 256);
|
|
} else {
|
|
nptr = nptr + 1;
|
|
strcpyn(wilddir, path, nptr - path, 256);
|
|
}
|
|
|
|
if (OS_MakePathSpec(0, wilddir, &spec.path))
|
|
return 0;
|
|
|
|
strcpyn(wildname, nptr, -1, 64);
|
|
if (OS_MakeNameSpec(wildname, &spec.name))
|
|
return 0;
|
|
|
|
if (OS_OpenDir(&spec.path, &wilddirref))
|
|
return 0;
|
|
}
|
|
|
|
while (!OS_ReadDir(&wilddirref, &wildmatch, filename, &isfile)) {
|
|
if (isfile && WildCardMatch(wildname, filename))
|
|
return &wildmatch;
|
|
}
|
|
|
|
OS_CloseDir(&wilddirref);
|
|
return 0;
|
|
}
|
|
|
|
char *OS_GetFileNamePtr(char *path) {
|
|
char *ptr;
|
|
ptr = strrchr(path, OS_PATHSEP);
|
|
return !ptr ? path : (ptr + 1);
|
|
}
|
|
|
|
char *OS_GetDirName(const OSPathSpec *spec, char *buf, int size) {
|
|
char *path;
|
|
char *pptr;
|
|
|
|
if (!spec || !buf || size <= 0)
|
|
return 0;
|
|
|
|
path = OS_PathSpecToString(spec, STSbuf, 256);
|
|
pptr = path + strlen(path) - 1;
|
|
if (pptr > path && *pptr == OS_PATHSEP) {
|
|
*pptr = 0;
|
|
--pptr;
|
|
}
|
|
|
|
while (pptr >= path && *pptr != OS_PATHSEP)
|
|
pptr--;
|
|
|
|
strncpy(buf, pptr, size - 1);
|
|
buf[size - 1] = 0;
|
|
return buf;
|
|
}
|
|
|
|
int OS_MakeSpec2(const char *path, const char *filename, OSSpec *spec) {
|
|
char bpath[256];
|
|
char *eptr;
|
|
int pthlen;
|
|
int fnlen;
|
|
|
|
if (!path)
|
|
path = "";
|
|
if (!filename)
|
|
filename = "";
|
|
|
|
fnlen = strlen(filename);
|
|
pthlen = strlen(path);
|
|
if (fnlen + pthlen + 1 > 255)
|
|
return ENAMETOOLONG;
|
|
|
|
strncpy(bpath, path, pthlen);
|
|
eptr = bpath + pthlen;
|
|
if (eptr[-1] != OS_PATHSEP)
|
|
*(eptr++) = OS_PATHSEP;
|
|
strcpy(eptr, filename);
|
|
|
|
return OS_MakeSpec(bpath, spec, 0);
|
|
}
|
|
|
|
int OS_MakeSpecWithPath(OSPathSpec *path, const char *filename, Boolean noRelative, OSSpec *spec) {
|
|
Boolean relpath;
|
|
char buf[256];
|
|
char *mptr;
|
|
char *eptr;
|
|
|
|
relpath = filename && strpbrk(filename, "/\\:");
|
|
|
|
if (!filename) {
|
|
if (path)
|
|
spec->path = *path;
|
|
else
|
|
OS_GetCWD(&spec->path);
|
|
return OS_MakeNameSpec("", &spec->name);
|
|
} else {
|
|
if ((!noRelative || !relpath) && !OS_IsFullPath(filename)) {
|
|
if (path)
|
|
OS_PathSpecToString(path, buf, 256);
|
|
else
|
|
buf[0] = 0;
|
|
|
|
mptr = &buf[255] - strlen(filename);
|
|
eptr = &buf[strlen(buf)];
|
|
strcpy((eptr > mptr) ? mptr : eptr, filename);
|
|
return OS_MakeSpec(buf, spec, 0);
|
|
} else {
|
|
return OS_MakeSpec(filename, spec, 0);
|
|
}
|
|
}
|
|
}
|
|
|
|
int OS_NameSpecChangeExtension(OSNameSpec *spec, const char *ext, Boolean append) {
|
|
char tmp[64];
|
|
char *per;
|
|
|
|
OS_NameSpecToString(spec, tmp, 256);
|
|
if (!append) {
|
|
per = strrchr(tmp, '.');
|
|
if (!per)
|
|
per = tmp + strlen(tmp);
|
|
} else {
|
|
per = tmp + strlen(tmp);
|
|
if (ext[0] != '.') {
|
|
per[0] = '.';
|
|
per[1] = 0;
|
|
per += 1;
|
|
}
|
|
}
|
|
|
|
if (strlen(tmp) + strlen(ext) > 64)
|
|
per = tmp + 63 - strlen(ext);
|
|
|
|
strcpy(per, ext);
|
|
return OS_MakeNameSpec(tmp, spec);
|
|
}
|
|
|
|
int OS_NameSpecSetExtension(OSNameSpec *spec, const char *ext) {
|
|
char tmp[64];
|
|
char *per;
|
|
|
|
OS_NameSpecToString(spec, tmp, 256);
|
|
if (ext[0] != '.') {
|
|
per = strrchr(tmp, '.');
|
|
if (!per)
|
|
per = tmp + strlen(tmp);
|
|
|
|
if (ext[0]) {
|
|
if (strlen(tmp) + 1 >= 64) {
|
|
per[-1] = '.';
|
|
} else {
|
|
per[0] = '.';
|
|
per++;
|
|
}
|
|
}
|
|
} else {
|
|
per = tmp + strlen(tmp);
|
|
}
|
|
|
|
if (strlen(tmp) + strlen(ext) > 64)
|
|
per = tmp + 63 - strlen(ext);
|
|
|
|
strcpy(per, ext);
|
|
return OS_MakeNameSpec(tmp, spec);
|
|
}
|
|
|
|
char *OS_CompactPaths(char *buf, const char *p, const char *n, int size) {
|
|
int plen;
|
|
int nlen;
|
|
char *ptr;
|
|
int bidx;
|
|
int wat;
|
|
|
|
plen = p ? strlen(p) : 0;
|
|
nlen = n ? strlen(n) : 0;
|
|
|
|
if (plen + nlen + 1 <= size) {
|
|
sprintf(buf, "%s%s", p ? p : "", n ? n : "");
|
|
return buf;
|
|
}
|
|
|
|
ptr = buf;
|
|
bidx = 0;
|
|
wat = plen + nlen - size;
|
|
|
|
while (plen > 0 && nlen > 0) {
|
|
if (plen > 0) {
|
|
*(ptr++) = *(p++);
|
|
plen--;
|
|
} else if (nlen > 0) {
|
|
*(ptr++) = *(n++);
|
|
nlen--;
|
|
}
|
|
|
|
if (++bidx == (size / 2) - 2) {
|
|
ptr[0] = '.';
|
|
ptr[1] = '.';
|
|
ptr[2] = '.';
|
|
ptr += 3;
|
|
bidx += 3;
|
|
if (plen > 0) {
|
|
plen -= wat / 2;
|
|
if (plen < 0) {
|
|
n -= plen;
|
|
nlen += plen;
|
|
plen = 0;
|
|
}
|
|
} else {
|
|
n += wat / 2;
|
|
nlen -= wat / 2;
|
|
}
|
|
}
|
|
}
|
|
|
|
*ptr = 0;
|
|
return buf;
|
|
}
|
|
|
|
char *OS_SpecToStringRelative(const OSSpec *spec, const OSPathSpec *cwdspec, char *path, int size) {
|
|
char fullbuf[256];
|
|
char *full;
|
|
char cwdbuf[256];
|
|
char *cwd;
|
|
OSPathSpec mycwdspec;
|
|
char *pptr;
|
|
|
|
full = fullbuf;
|
|
cwd = cwdbuf;
|
|
OS_SpecToString(spec, full, 256);
|
|
|
|
if (!size)
|
|
size = 256;
|
|
|
|
if (!path) {
|
|
path = malloc(size);
|
|
if (!path)
|
|
return 0;
|
|
}
|
|
|
|
if (!cwdspec) {
|
|
OS_GetCWD(&mycwdspec);
|
|
cwdspec = &mycwdspec;
|
|
}
|
|
|
|
if (!OS_PathSpecToString(cwdspec, cwdbuf, 256)) {
|
|
memcpy(path, fullbuf, size - 1);
|
|
path[size - 1] = 0;
|
|
return path;
|
|
}
|
|
|
|
while (*cwd && *full == *cwd) {
|
|
full++;
|
|
cwd++;
|
|
}
|
|
|
|
if ((cwd - cwdbuf) < (strlen(fullbuf) / 2) && (strlen(cwd) > (strlen(fullbuf) / 2))) {
|
|
memcpy(path, fullbuf, size - 1);
|
|
path[size - 1] = 0;
|
|
return path;
|
|
}
|
|
|
|
while (cwd > cwdbuf) {
|
|
cwd--;
|
|
full--;
|
|
if (*cwd == OS_PATHSEP)
|
|
break;
|
|
}
|
|
|
|
if (cwd == cwdbuf) {
|
|
strncpy(path, full, size - 1);
|
|
path[size - 1] = 0;
|
|
} else {
|
|
if (*(++cwd)) {
|
|
pptr = path;
|
|
while (*cwd) {
|
|
if (*cwd == OS_PATHSEP)
|
|
pptr += sprintf(pptr, "../");
|
|
++cwd;
|
|
}
|
|
strcpy(pptr, full + 1);
|
|
} else {
|
|
strncpy(path, full + 1, size - 1);
|
|
path[size - 1] = 0;
|
|
}
|
|
}
|
|
|
|
return path;
|
|
}
|
|
|
|
int OS_FindFileInPath(const char *filename, const char *plist, OSSpec *spec) {
|
|
const char *next;
|
|
char path[256];
|
|
int err;
|
|
|
|
while (plist && *plist) {
|
|
next = strchr(plist, ':');
|
|
if (!next)
|
|
next = strpbrk(plist, ":;");
|
|
|
|
if (!next)
|
|
next = plist + strlen(plist);
|
|
|
|
strcpyn(path, plist, next - plist, 255);
|
|
if (!OS_MakeSpec2(path, filename, spec)) {
|
|
if (!OS_Status(spec))
|
|
return 0;
|
|
}
|
|
|
|
if (*next)
|
|
plist = next + 1;
|
|
else
|
|
plist = 0;
|
|
}
|
|
|
|
err = OS_MakeFileSpec(filename, spec);
|
|
if (!err) {
|
|
err = OS_Status(spec);
|
|
if (!err)
|
|
err = 0;
|
|
}
|
|
return err;
|
|
}
|
|
|
|
int OS_FindProgram(const char *filename, OSSpec *spec) {
|
|
char *plist;
|
|
int err;
|
|
char temp[256];
|
|
|
|
strncpy(temp, filename, 256);
|
|
temp[255] = 0;
|
|
|
|
if (!strchr(temp, OS_PATHSEP)) {
|
|
plist = getenv("PATH");
|
|
err = OS_FindFileInPath(temp, plist, spec);
|
|
if (!err)
|
|
return 0;
|
|
}
|
|
|
|
err = OS_MakeFileSpec(temp, spec);
|
|
if (!err)
|
|
err = OS_Status(spec);
|
|
return err;
|
|
}
|
|
|
|
int OS_CopyHandle(OSHandle *hand, OSHandle *copy) {
|
|
int err;
|
|
UInt32 sz;
|
|
void *f;
|
|
void *t;
|
|
|
|
err = OS_GetHandleSize(hand, &sz);
|
|
if (!err) {
|
|
err = OS_NewHandle(sz, copy);
|
|
if (!err) {
|
|
f = OS_LockHandle(hand);
|
|
t = OS_LockHandle(copy);
|
|
memcpy(t, f, sz);
|
|
OS_UnlockHandle(hand);
|
|
OS_UnlockHandle(copy);
|
|
return 0;
|
|
}
|
|
}
|
|
OS_FreeHandle(copy);
|
|
return err;
|
|
}
|
|
|
|
int OS_AppendHandle(OSHandle *hand, const void *data, UInt32 len) {
|
|
int err;
|
|
UInt32 sz;
|
|
void *buffer;
|
|
|
|
err = OS_GetHandleSize(hand, &sz);
|
|
if (!err) {
|
|
err = OS_ResizeHandle(hand, sz + len);
|
|
if (!err) {
|
|
buffer = OS_LockHandle(hand);
|
|
if (buffer) {
|
|
memcpy((unsigned char *) buffer + sz, data, len);
|
|
OS_UnlockHandle(hand);
|
|
return 0;
|
|
}
|
|
}
|
|
}
|
|
return err;
|
|
}
|