diff options
author | Ash Wolf <ninji@wuffs.org> | 2022-10-13 12:39:17 +0100 |
---|---|---|
committer | Ash Wolf <ninji@wuffs.org> | 2022-10-13 12:39:17 +0100 |
commit | c198d1135a80d607161c62ec43c1d1182f62bbf7 (patch) | |
tree | ad979bf1166f6c6d07283e6be74e12bb66fb3bd9 /command_line/CmdLine/Src | |
parent | bdf2608f1d72f3b0705e783c1870d5d31a53a2d7 (diff) | |
download | MWCC-c198d1135a80d607161c62ec43c1d1182f62bbf7.tar.gz MWCC-c198d1135a80d607161c62ec43c1d1182f62bbf7.zip |
finish OSLib/MacSpecs.c and use OS_PATHSEP in more places
Diffstat (limited to 'command_line/CmdLine/Src')
-rw-r--r-- | command_line/CmdLine/Src/OSLib/Generic.c | 20 | ||||
-rw-r--r-- | command_line/CmdLine/Src/OSLib/MacSpecs.c | 367 | ||||
-rw-r--r-- | command_line/CmdLine/Src/OSLib/Posix.c | 36 |
3 files changed, 394 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); } |