summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAsh Wolf <ninji@wuffs.org>2022-10-13 12:39:17 +0100
committerAsh Wolf <ninji@wuffs.org>2022-10-13 12:39:17 +0100
commitc198d1135a80d607161c62ec43c1d1182f62bbf7 (patch)
treead979bf1166f6c6d07283e6be74e12bb66fb3bd9
parentbdf2608f1d72f3b0705e783c1870d5d31a53a2d7 (diff)
downloadMWCC-c198d1135a80d607161c62ec43c1d1182f62bbf7.tar.gz
MWCC-c198d1135a80d607161c62ec43c1d1182f62bbf7.zip
finish OSLib/MacSpecs.c and use OS_PATHSEP in more places
-rw-r--r--command_line/CmdLine/Src/OSLib/Generic.c20
-rw-r--r--command_line/CmdLine/Src/OSLib/MacSpecs.c367
-rw-r--r--command_line/CmdLine/Src/OSLib/Posix.c36
-rw-r--r--includes/oslib.h2
4 files changed, 396 insertions, 29 deletions
diff --git a/command_line/CmdLine/Src/OSLib/Generic.c b/command_line/CmdLine/Src/OSLib/Generic.c
index a4e9fed..f2c2ac9 100644
--- a/command_line/CmdLine/Src/OSLib/Generic.c
+++ b/command_line/CmdLine/Src/OSLib/Generic.c
@@ -48,7 +48,7 @@ int WildCardMatch(char *wild, char *name) {
}
}
- return !name[0] || (name[0] == '/' && !name[1]);
+ return !name[0] || (name[0] == OS_PATHSEP && !name[1]);
}
OSSpec *OS_MatchPath(const char *path) {
@@ -58,7 +58,7 @@ OSSpec *OS_MatchPath(const char *path) {
const char *nptr;
if (path) {
- nptr = strrchr(path, '/');
+ nptr = strrchr(path, OS_PATHSEP);
if (!nptr) {
nptr = path;
strcpyn(wilddir, ".", -1, 256);
@@ -89,7 +89,7 @@ OSSpec *OS_MatchPath(const char *path) {
char *OS_GetFileNamePtr(char *path) {
char *ptr;
- ptr = strrchr(path, '/');
+ ptr = strrchr(path, OS_PATHSEP);
return !ptr ? path : (ptr + 1);
}
@@ -102,12 +102,12 @@ char *OS_GetDirName(const OSPathSpec *spec, char *buf, int size) {
path = OS_PathSpecToString(spec, STSbuf, 256);
pptr = path + strlen(path) - 1;
- if (pptr > path && *pptr == '/') {
+ if (pptr > path && *pptr == OS_PATHSEP) {
*pptr = 0;
--pptr;
}
- while (pptr >= path && *pptr != '/')
+ while (pptr >= path && *pptr != OS_PATHSEP)
pptr--;
strncpy(buf, pptr, size - 1);
@@ -133,8 +133,8 @@ int OS_MakeSpec2(const char *path, const char *filename, OSSpec *spec) {
strncpy(bpath, path, pthlen);
eptr = bpath + pthlen;
- if (eptr[-1] != '/')
- *(eptr++) = '/';
+ if (eptr[-1] != OS_PATHSEP)
+ *(eptr++) = OS_PATHSEP;
strcpy(eptr, filename);
return OS_MakeSpec(bpath, spec, 0);
@@ -323,7 +323,7 @@ char *OS_SpecToStringRelative(const OSSpec *spec, const OSPathSpec *cwdspec, cha
while (cwd > cwdbuf) {
cwd--;
full--;
- if (*cwd == '/')
+ if (*cwd == OS_PATHSEP)
break;
}
@@ -334,7 +334,7 @@ char *OS_SpecToStringRelative(const OSSpec *spec, const OSPathSpec *cwdspec, cha
if (*(++cwd)) {
pptr = path;
while (*cwd) {
- if (*cwd == '/')
+ if (*cwd == OS_PATHSEP)
pptr += sprintf(pptr, "../");
++cwd;
}
@@ -390,7 +390,7 @@ int OS_FindProgram(const char *filename, OSSpec *spec) {
strncpy(temp, filename, 256);
temp[255] = 0;
- if (!strchr(temp, '/')) {
+ if (!strchr(temp, OS_PATHSEP)) {
plist = getenv("PATH");
err = OS_FindFileInPath(temp, plist, spec);
if (!err)
diff --git a/command_line/CmdLine/Src/OSLib/MacSpecs.c b/command_line/CmdLine/Src/OSLib/MacSpecs.c
index 8648324..defcab1 100644
--- a/command_line/CmdLine/Src/OSLib/MacSpecs.c
+++ b/command_line/CmdLine/Src/OSLib/MacSpecs.c
@@ -1,25 +1,392 @@
#include "oslib.h"
+#include <errno.h>
+
+extern char STSbuf[256];
+
+#define OPTION_ASSERT(cond) do { if (!(cond)) { printf("%s:%u: failed assertion\n", __FILE__, __LINE__); abort(); } } while(0)
+
+typedef struct DirNode {
+ char *name;
+ unsigned int dirID;
+ union {
+ struct DirNode *parent;
+ struct VolNode *volume;
+ } p;
+ struct DirNode *list;
+ struct DirNode *next;
+} DirNode;
+
+typedef struct VolNode {
+ UInt16 vRefNum;
+ DirNode root;
+ struct VolNode *next;
+} VolNode;
+
+static unsigned int lastDirID = 3;
+static unsigned int lastVolRef = 2;
+static char stname[256];
+static char stpath[256];
+static char stdir[256];
+static char stvol[8];
+static unsigned int dirMapRows;
+static DirNode **dirIDMap[256];
+static VolNode *vols;
+
+static int AddDirMapEntry(DirNode *node) {
+ unsigned int row;
+ unsigned int col;
+
+ row = node->dirID >> 8;
+ col = node->dirID & 0xFF;
+
+ while (row >= dirMapRows) {
+ if (row >= 256) {
+ fprintf(stderr, "Fatal error: too many directories referenced, out of memory\n");
+ return 0;
+ }
+
+ dirIDMap[row] = calloc(sizeof(DirNode *), 256);
+ if (!dirIDMap[row])
+ return 0;
+
+ dirMapRows++;
+ }
+
+ dirIDMap[row][col] = node;
+ return 1;
+}
+
+static VolNode *FindOrAddVolRef(VolNode **list, char *name) {
+ int sz;
+ VolNode *vn;
+
+ while (*list) {
+ if (OS_EqualPath(name, (*list)->root.name))
+ return *list;
+ list = &(*list)->next;
+ }
+
+ if (lastVolRef >= 256)
+ return 0;
+
+ vn = malloc(sizeof(VolNode));
+ if (!vn)
+ return 0;
+
+ vn->next = 0;
+ vn->vRefNum = lastVolRef++;
+
+ sz = strlen(name) + 1;
+ vn->root.name = malloc(sz);
+ if (!vn->root.name)
+ return 0;
+
+ strcpy(vn->root.name, name);
+ vn->root.dirID = 2;
+ vn->root.p.volume = vn;
+ vn->root.list = 0;
+ vn->root.next = 0;
+ *list = vn;
+ return vn;
+}
+
+static DirNode *FindDirMapEntry(unsigned int dirID) {
+ unsigned int row;
+ unsigned int col;
+
+ row = dirID >> 8;
+ col = dirID & 0xFF;
+#line 166
+ OPTION_ASSERT(dirID != 2);
+
+ if (row >= dirMapRows)
+ return 0;
+ else
+ return dirIDMap[row][col];
+}
+
+static DirNode *FindOrAddDirRef(DirNode *parent, char *name) {
+ int sz;
+ DirNode *dn;
+ DirNode **list;
+
+ list = &parent->list;
+ while (*list) {
+ if (OS_EqualPath(name, (*list)->name))
+ return *list;
+ list = &(*list)->next;
+ }
+
+ if (lastDirID >= 0x10000)
+ return 0;
+
+ sz = strlen(name) + 1;
+
+ dn = malloc(sizeof(DirNode));
+ if (!dn)
+ return 0;
+ dn->name = malloc(sz);
+ if (!dn->name)
+ return 0;
+ strcpy(dn->name, name);
+
+ dn->list = 0;
+ dn->next = 0;
+ dn->dirID = lastDirID++;
+
+ if (!AddDirMapEntry(dn))
+ return 0;
+
+ dn->p.parent = parent;
+ *list = dn;
+ return dn;
+}
+
+static int FindOrAdd(const OSPathSpec *path, unsigned int *vRefNum, unsigned int *dirID) {
+ VolNode *vol;
+ DirNode *level;
+ char pb[256];
+ char voln[8];
+ char pathbuf[256];
+ char *ptr;
+ char *st;
+ char ch;
+
+ if (!OS_PathSpecToString(path, pathbuf, 256))
+ return 0;
+ if (!pathbuf[0])
+ return 0;
+
+ ptr = OS_GetDirPtr(pathbuf);
+ strncpy(voln, pathbuf, ptr - pathbuf);
+ voln[ptr - pathbuf] = 0;
+ strcpy(pb, ptr);
+
+ vol = FindOrAddVolRef(&vols, voln);
+ if (!vol)
+ return 0;
+
+ *vRefNum = vol->vRefNum;
+ level = &vol->root;
+ ptr = &pb[1];
+#line 267
+ OPTION_ASSERT(*pb == OS_PATHSEP);
+
+ while (*ptr) {
+ st = ptr;
+ while ((ch = *ptr) && *ptr != OS_PATHSEP) {
+ ++ptr;
+ }
+
+ *ptr = 0;
+
+ level = FindOrAddDirRef(level, st);
+ if (!ch)
+ break;
+ ++ptr;
+ if (!level)
+ return 0;
+ }
+
+ *dirID = level->dirID;
+ return 1;
+}
+
+static void StepVolDir(unsigned int *vRefNum, unsigned int *dirID, DirNode **node) {
+ VolNode *step;
+
+ if (*vRefNum == 1) {
+ *node = 0;
+ return;
+ }
+
+ if (*dirID == 2) {
+ step = vols;
+ while (step && step->vRefNum != *vRefNum)
+ step = step->next;
+ if (step) {
+ *node = &step->root;
+ *vRefNum = 1;
+ *dirID = 1;
+ } else {
+ *node = 0;
+ }
+ } else {
+ *node = FindDirMapEntry(*dirID);
+ if (*node)
+ *dirID = (*node)->p.parent->dirID;
+ }
+}
+
+static int ResolvePath(const OSPathSpec *path, unsigned int *vRefNum, unsigned int *dirID) {
+ if (FindOrAdd(path, vRefNum, dirID)) {
+ *vRefNum = -*vRefNum;
+ return 1;
+ } else {
+ *vRefNum = 0;
+ *dirID = 0;
+ return 0;
+ }
+}
+
+static int ResolveVolDir(unsigned int vRefNum, unsigned int dirID, char *vol, char *dir) {
+ DirNode *nodes[256];
+ DirNode *cur;
+ int idx;
+ int len;
+ char *dptr;
+
+ vRefNum = -vRefNum;
+ idx = 0;
+ do {
+ StepVolDir(&vRefNum, &dirID, &cur);
+ if (cur)
+ nodes[idx++] = cur;
+ } while (cur);
+
+ if (idx) {
+ strcpy(vol, nodes[--idx]->name);
+ } else {
+ vol[0] = 0;
+ dir[0] = 0;
+ return 0;
+ }
+
+ dptr = dir;
+ *(dptr++) = OS_PATHSEP;
+ while (idx--) {
+ len = strlen(nodes[idx]->name);
+ if ((dptr - dir) + len + 1 > 256) {
+ *dptr = 0;
+ return 0;
+ } else {
+ memcpy(dptr, nodes[idx]->name, len);
+ dptr += len;
+ *(dptr++) = OS_PATHSEP;
+ }
+ }
+
+ *dptr = 0;
+ return 1;
+}
int OS_OSPathSpec_To_VolDir(const OSPathSpec *spec, SInt16 *vRefNum, SInt32 *dirID) {
+ unsigned int vol;
+ unsigned int dir;
+ if (ResolvePath(spec, &vol, &dir)) {
+ *vRefNum = vol;
+ *dirID = dir;
+ return 0;
+ } else {
+ *vRefNum = 0;
+ *dirID = 0;
+ return ENOENT;
+ }
}
int OS_OSSpec_To_FSSpec(const OSSpec *spec, FSSpec *fss) {
+ int err;
+ SInt16 vRefNum;
+ SInt32 dirID;
+ char *s;
+
+ err = OS_OSPathSpec_To_VolDir(&spec->path, &vRefNum, &dirID);
+ fss->vRefNum = vRefNum;
+ fss->parID = dirID;
+ if (err) return err;
+
+ s = OS_NameSpecToString(&spec->name, STSbuf, sizeof(STSbuf));
+ if (!s || strlen(s) >= 256)
+ return ENAMETOOLONG;
+ c2pstrcpy(fss->name, s);
+ return 0;
}
int OS_VolDir_To_OSNameSpec(SInt16 vRefNum, SInt32 dirID, OSNameSpec *spec, SInt32 *parID) {
+ unsigned int cv;
+ unsigned int cd;
+ DirNode *node;
+ cv = -vRefNum;
+ cd = dirID;
+ StepVolDir(&cv, &cd, &node);
+ if (!node)
+ return ENOENT;
+
+ *parID = cd;
+ return OS_MakeNameSpec(node->name, spec);
}
int OS_VolDir_To_OSPathSpec(SInt16 vRefNum, SInt32 dirID, OSPathSpec *spec) {
+ int err;
+ int vlen;
+ int dlen;
+
+ if (!vRefNum || !dirID) {
+ err = OS_GetCWD(spec);
+ if (err)
+ return err;
+ } else {
+ if (!ResolveVolDir(vRefNum, dirID, stvol, stdir))
+ return ENOENT;
+ vlen = strlen(stvol);
+ dlen = strlen(stdir);
+ if (vlen + dlen < 256) {
+ memcpy(spec->s, stvol, vlen);
+ memcpy(spec->s + vlen, stdir, dlen + 1);
+ }
+ }
+
+ return 0;
}
int OS_FSSpec_To_OSSpec(const FSSpec *fss, OSSpec *spec) {
+ int err;
+
+ err = OS_VolDir_To_OSPathSpec(fss->vRefNum, fss->parID, &spec->path);
+ if (err)
+ return err;
+ p2cstrcpy(stname, fss->name);
+ err = OS_MakeNameSpec(stname, &spec->name);
+ if (err)
+ return err;
+
+ return err;
}
int OS_GetRsrcOSSpec(const OSSpec *spec, OSSpec *rspec, Boolean create) {
+ char dbuffer[256];
+ int err;
+
+ OS_PathSpecToString(&spec->path, dbuffer, sizeof(dbuffer));
+ err = OS_MakeSpec2(dbuffer, "resource.frk", rspec);
+ if (err)
+ return err;
+
+ err = OS_Status(rspec);
+ if (err) {
+ if (create) {
+ err = OS_Mkdir(rspec);
+ if (err)
+ return err;
+ // Windows version has a call to SetFileAttributes here
+ } else {
+ return err;
+ }
+ err = OS_MakeSpec2(dbuffer, "resource.frk", rspec);
+ if (err)
+ return err;
+ } else if (OS_IsFile(rspec)) {
+ return ENOTDIR;
+ }
+
+ err = OS_MakeNameSpec(OS_NameSpecToString(&spec->name, STSbuf, sizeof(STSbuf)), &rspec->name);
+ if (err)
+ return err;
+ return 0;
}
diff --git a/command_line/CmdLine/Src/OSLib/Posix.c b/command_line/CmdLine/Src/OSLib/Posix.c
index e836653..dc22651 100644
--- a/command_line/CmdLine/Src/OSLib/Posix.c
+++ b/command_line/CmdLine/Src/OSLib/Posix.c
@@ -31,7 +31,7 @@ int _plen = strlen((spec)->s); \
if (_plen >= sizeof(pathbuf)) return 63;\
memcpy((pathbuf), (spec)->s, _plen + 1);\
if (_plen > 1) { \
-if ((pathbuf)[_plen - 1] == '/') \
+if ((pathbuf)[_plen - 1] == OS_PATHSEP) \
(pathbuf)[_plen - 1] = 0; \
} \
} while (0)
@@ -260,7 +260,7 @@ int OS_GetCWD(OSPathSpec *spec) {
return errno;
ptr = &spec->s[strlen(spec->s)];
- if (ptr[-1] != '/')
+ if (ptr[-1] != OS_PATHSEP)
strcpy(ptr, "/");
return 0;
}
@@ -332,15 +332,13 @@ int OS_IsLegalPath(const char *path) {
fnlen = 0;
while (*scan) {
- if (*scan == '/')
+ if (*scan == OS_PATHSEP)
fnlen = 0;
else
fnlen++;
++pthlen;
if (fnlen > 63 || pthlen > 255)
return ENAMETOOLONG;
- //if ((fnlen = (*scan == '/') ? 0 : (fnlen + 1)) > 63 || ++pthlen > 255)
- // return ENAMETOOLONG;
++scan;
}
@@ -348,7 +346,7 @@ int OS_IsLegalPath(const char *path) {
}
int OS_IsFullPath(const char *path) {
- return path[0] == '/';
+ return path[0] == OS_PATHSEP;
}
char *OS_GetDirPtr(char *path) {
@@ -375,7 +373,7 @@ static int OS_CompactPath(char *src, char *dst) {
to = bptr;
while (*from) {
brk = from + 1;
- while (*brk && *brk != '/')
+ while (*brk && *brk != OS_PATHSEP)
++brk;
if ((brk - from) == 1) {
@@ -386,7 +384,7 @@ static int OS_CompactPath(char *src, char *dst) {
if (to > bptr) {
do {
to--;
- } while (to >= bptr && *to != '/');
+ } while (to >= bptr && *to != OS_PATHSEP);
}
from = brk;
} else {
@@ -396,8 +394,8 @@ static int OS_CompactPath(char *src, char *dst) {
}
}
- if (to == bptr || from[-1] == '/')
- *(to++) = '/';
+ if (to == bptr || from[-1] == OS_PATHSEP)
+ *(to++) = OS_PATHSEP;
*to = 0;
if (!dst)
@@ -421,7 +419,7 @@ int OS_CanonPath(char *src, char *dst) {
for (idx = 0; src[idx]; idx++) {
if (src[idx] == '\\')
- dst[idx] = '/';
+ dst[idx] = OS_PATHSEP;
else
dst[idx] = src[idx];
}
@@ -451,8 +449,8 @@ int OS_MakeSpec(const char *path, OSSpec *spec, Boolean *isfile) {
return errno;
ptr = tmp + strlen(tmp) - 1;
- if (ptr[0] != '/') {
- ptr[1] = '/';
+ if (ptr[0] != OS_PATHSEP) {
+ ptr[1] = OS_PATHSEP;
ptr[2] = 0;
ptr += 2;
}
@@ -475,12 +473,12 @@ int OS_MakeSpec(const char *path, OSSpec *spec, Boolean *isfile) {
if (!stat(tmp, &st)) {
ptr = tmp + strlen(tmp);
- if (ptr[-1] == '/')
+ if (ptr[-1] == OS_PATHSEP)
ptr--;
if ((st.st_mode & S_IFMT) == S_IFDIR) {
if (isfile)
*isfile = 0;
- ptr[0] = '/';
+ ptr[0] = OS_PATHSEP;
ptr++;
} else {
if (isfile)
@@ -494,7 +492,7 @@ int OS_MakeSpec(const char *path, OSSpec *spec, Boolean *isfile) {
*isfile = 1;
}
- ptr = strrchr(tmp, '/') + 1;
+ ptr = strrchr(tmp, OS_PATHSEP) + 1;
len = ptr - tmp;
if (len >= 256) {
spec->path.s[0] = 0;
@@ -561,7 +559,7 @@ int OS_MakeNameSpec(const char *name, OSNameSpec *spec) {
spec->s[0] = 0;
if (len > 63)
return ENAMETOOLONG;
- if (strchr(name, '/'))
+ if (strchr(name, OS_PATHSEP))
return EISDIR;
if (strlen(name) > 63)
return ENAMETOOLONG;
@@ -694,7 +692,7 @@ int OS_IsLink(const OSSpec *spec) {
return 0;
ptr = intbuf + strlen(intbuf) - 1;
- if (*ptr == '/')
+ if (*ptr == OS_PATHSEP)
*ptr = 0;
if (lstat(intbuf, &st) < 0)
@@ -716,7 +714,7 @@ int OS_ResolveLink(const OSSpec *link, OSSpec *target) {
return errno;
fn[len] = 0;
- sprintf(path, "%s%s", (fn[0] != '/') ? link->path.s : "", fn);
+ sprintf(path, "%s%s", (fn[0] != OS_PATHSEP) ? link->path.s : "", fn);
return OS_MakeSpec(path, target, 0);
}
diff --git a/includes/oslib.h b/includes/oslib.h
index fadc81f..bb841ac 100644
--- a/includes/oslib.h
+++ b/includes/oslib.h
@@ -1,6 +1,8 @@
#pragma once
#include "common.h"
+#define OS_PATHSEP '/'
+
/**
* OS abstraction layer
*/